|
|
1.1 root 1: /*
2: * Copyright (c) 1982, 1986, 1988 Regents of the University of California.
3: * All rights reserved.
4: *
5: * Redistribution and use in source and binary forms, with or without
6: * modification, are permitted provided that the following conditions
7: * are met:
8: * 1. Redistributions of source code must retain the above copyright
9: * notice, this list of conditions and the following disclaimer.
10: * 2. Redistributions in binary form must reproduce the above copyright
11: * notice, this list of conditions and the following disclaimer in the
12: * documentation and/or other materials provided with the distribution.
13: * 3. All advertising materials mentioning features or use of this software
14: * must display the following acknowledgement:
15: * This product includes software developed by the University of
16: * California, Berkeley and its contributors.
17: * 4. Neither the name of the University nor the names of its contributors
18: * may be used to endorse or promote products derived from this software
19: * without specific prior written permission.
20: *
21: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31: * SUCH DAMAGE.
32: *
1.1.1.2 ! root 33: * from: @(#)tcp_usrreq.c 7.15 (Berkeley) 6/28/90
! 34: * $Id: tcp_usrreq.c,v 1.2 1993/05/18 18:20:21 cgd Exp $
1.1 root 35: */
36:
37: #include "param.h"
38: #include "systm.h"
39: #include "malloc.h"
1.1.1.2 ! root 40: #include "select.h"
1.1 root 41: #include "mbuf.h"
42: #include "socket.h"
43: #include "socketvar.h"
44: #include "protosw.h"
45: #include "errno.h"
46: #include "stat.h"
47:
48: #include "../net/if.h"
49: #include "../net/route.h"
50:
51: #include "in.h"
52: #include "in_systm.h"
53: #include "ip.h"
54: #include "in_pcb.h"
55: #include "ip_var.h"
56: #include "tcp.h"
57: #include "tcp_fsm.h"
58: #include "tcp_seq.h"
59: #include "tcp_timer.h"
60: #include "tcp_var.h"
61: #include "tcpip.h"
62: #include "tcp_debug.h"
63:
64: /*
65: * TCP protocol interface to socket abstraction.
66: */
67: extern char *tcpstates[];
68: struct tcpcb *tcp_newtcpcb();
69:
70: /*
71: * Process a TCP user request for TCP tb. If this is a send request
72: * then m is the mbuf chain of send data. If this is a timer expiration
73: * (called from the software clock routine), then timertype tells which timer.
74: */
75: /*ARGSUSED*/
76: tcp_usrreq(so, req, m, nam, control)
77: struct socket *so;
78: int req;
79: struct mbuf *m, *nam, *control;
80: {
81: register struct inpcb *inp;
82: register struct tcpcb *tp;
83: int s;
84: int error = 0;
85: int ostate;
86:
87: if (req == PRU_CONTROL)
88: return (in_control(so, (int)m, (caddr_t)nam,
89: (struct ifnet *)control));
90: if (control && control->m_len) {
91: m_freem(control);
92: if (m)
93: m_freem(m);
94: return (EINVAL);
95: }
96:
97: s = splnet();
98: inp = sotoinpcb(so);
99: /*
100: * When a TCP is attached to a socket, then there will be
101: * a (struct inpcb) pointed at by the socket, and this
102: * structure will point at a subsidary (struct tcpcb).
103: */
104: if (inp == 0 && req != PRU_ATTACH) {
105: splx(s);
106: return (EINVAL); /* XXX */
107: }
108: if (inp) {
109: tp = intotcpcb(inp);
110: /* WHAT IF TP IS 0? */
111: #ifdef KPROF
112: tcp_acounts[tp->t_state][req]++;
113: #endif
114: ostate = tp->t_state;
115: } else
116: ostate = 0;
117: switch (req) {
118:
119: /*
120: * TCP attaches to socket via PRU_ATTACH, reserving space,
121: * and an internet control block.
122: */
123: case PRU_ATTACH:
124: if (inp) {
125: error = EISCONN;
126: break;
127: }
128: error = tcp_attach(so);
129: if (error)
130: break;
131: if ((so->so_options & SO_LINGER) && so->so_linger == 0)
132: so->so_linger = TCP_LINGERTIME;
133: tp = sototcpcb(so);
134: break;
135:
136: /*
137: * PRU_DETACH detaches the TCP protocol from the socket.
138: * If the protocol state is non-embryonic, then can't
139: * do this directly: have to initiate a PRU_DISCONNECT,
140: * which may finish later; embryonic TCB's can just
141: * be discarded here.
142: */
143: case PRU_DETACH:
144: if (tp->t_state > TCPS_LISTEN)
145: tp = tcp_disconnect(tp);
146: else
147: tp = tcp_close(tp);
148: break;
149:
150: /*
151: * Give the socket an address.
152: */
153: case PRU_BIND:
154: error = in_pcbbind(inp, nam);
155: if (error)
156: break;
157: break;
158:
159: /*
160: * Prepare to accept connections.
161: */
162: case PRU_LISTEN:
163: if (inp->inp_lport == 0)
164: error = in_pcbbind(inp, (struct mbuf *)0);
165: if (error == 0)
166: tp->t_state = TCPS_LISTEN;
167: break;
168:
169: /*
170: * Initiate connection to peer.
171: * Create a template for use in transmissions on this connection.
172: * Enter SYN_SENT state, and mark socket as connecting.
173: * Start keep-alive timer, and seed output sequence space.
174: * Send initial segment on connection.
175: */
176: case PRU_CONNECT:
177: if (inp->inp_lport == 0) {
178: error = in_pcbbind(inp, (struct mbuf *)0);
179: if (error)
180: break;
181: }
182: error = in_pcbconnect(inp, nam);
183: if (error)
184: break;
185: tp->t_template = tcp_template(tp);
186: if (tp->t_template == 0) {
187: in_pcbdisconnect(inp);
188: error = ENOBUFS;
189: break;
190: }
191: soisconnecting(so);
192: tcpstat.tcps_connattempt++;
193: tp->t_state = TCPS_SYN_SENT;
194: tp->t_timer[TCPT_KEEP] = TCPTV_KEEP_INIT;
195: tp->iss = tcp_iss; tcp_iss += TCP_ISSINCR/2;
196: tcp_sendseqinit(tp);
197: error = tcp_output(tp);
198: break;
199:
200: /*
201: * Create a TCP connection between two sockets.
202: */
203: case PRU_CONNECT2:
204: error = EOPNOTSUPP;
205: break;
206:
207: /*
208: * Initiate disconnect from peer.
209: * If connection never passed embryonic stage, just drop;
210: * else if don't need to let data drain, then can just drop anyways,
211: * else have to begin TCP shutdown process: mark socket disconnecting,
212: * drain unread data, state switch to reflect user close, and
213: * send segment (e.g. FIN) to peer. Socket will be really disconnected
214: * when peer sends FIN and acks ours.
215: *
216: * SHOULD IMPLEMENT LATER PRU_CONNECT VIA REALLOC TCPCB.
217: */
218: case PRU_DISCONNECT:
219: tp = tcp_disconnect(tp);
220: break;
221:
222: /*
223: * Accept a connection. Essentially all the work is
224: * done at higher levels; just return the address
225: * of the peer, storing through addr.
226: */
227: case PRU_ACCEPT: {
228: struct sockaddr_in *sin = mtod(nam, struct sockaddr_in *);
229:
230: nam->m_len = sizeof (struct sockaddr_in);
231: sin->sin_family = AF_INET;
232: sin->sin_len = sizeof(*sin);
233: sin->sin_port = inp->inp_fport;
234: sin->sin_addr = inp->inp_faddr;
235: break;
236: }
237:
238: /*
239: * Mark the connection as being incapable of further output.
240: */
241: case PRU_SHUTDOWN:
242: socantsendmore(so);
243: tp = tcp_usrclosed(tp);
244: if (tp)
245: error = tcp_output(tp);
246: break;
247:
248: /*
249: * After a receive, possibly send window update to peer.
250: */
251: case PRU_RCVD:
252: (void) tcp_output(tp);
253: break;
254:
255: /*
256: * Do a send by putting data in output queue and updating urgent
257: * marker if URG set. Possibly send more data.
258: */
259: case PRU_SEND:
260: sbappend(&so->so_snd, m);
261: error = tcp_output(tp);
262: break;
263:
264: /*
265: * Abort the TCP.
266: */
267: case PRU_ABORT:
268: tp = tcp_drop(tp, ECONNABORTED);
269: break;
270:
271: case PRU_SENSE:
272: ((struct stat *) m)->st_blksize = so->so_snd.sb_hiwat;
273: (void) splx(s);
274: return (0);
275:
276: case PRU_RCVOOB:
277: if ((so->so_oobmark == 0 &&
278: (so->so_state & SS_RCVATMARK) == 0) ||
279: so->so_options & SO_OOBINLINE ||
280: tp->t_oobflags & TCPOOB_HADDATA) {
281: error = EINVAL;
282: break;
283: }
284: if ((tp->t_oobflags & TCPOOB_HAVEDATA) == 0) {
285: error = EWOULDBLOCK;
286: break;
287: }
288: m->m_len = 1;
289: *mtod(m, caddr_t) = tp->t_iobc;
290: if (((int)nam & MSG_PEEK) == 0)
291: tp->t_oobflags ^= (TCPOOB_HAVEDATA | TCPOOB_HADDATA);
292: break;
293:
294: case PRU_SENDOOB:
295: if (sbspace(&so->so_snd) < -512) {
296: m_freem(m);
297: error = ENOBUFS;
298: break;
299: }
300: /*
301: * According to RFC961 (Assigned Protocols),
302: * the urgent pointer points to the last octet
303: * of urgent data. We continue, however,
304: * to consider it to indicate the first octet
305: * of data past the urgent section.
306: * Otherwise, snd_up should be one lower.
307: */
308: sbappend(&so->so_snd, m);
309: tp->snd_up = tp->snd_una + so->so_snd.sb_cc;
310: tp->t_force = 1;
311: error = tcp_output(tp);
312: tp->t_force = 0;
313: break;
314:
315: case PRU_SOCKADDR:
316: in_setsockaddr(inp, nam);
317: break;
318:
319: case PRU_PEERADDR:
320: in_setpeeraddr(inp, nam);
321: break;
322:
323: /*
324: * TCP slow timer went off; going through this
325: * routine for tracing's sake.
326: */
327: case PRU_SLOWTIMO:
328: tp = tcp_timers(tp, (int)nam);
329: req |= (int)nam << 8; /* for debug's sake */
330: break;
331:
332: default:
333: panic("tcp_usrreq");
334: }
335: if (tp && (so->so_options & SO_DEBUG))
336: tcp_trace(TA_USER, ostate, tp, (struct tcpiphdr *)0, req);
337: splx(s);
338: return (error);
339: }
340:
341: tcp_ctloutput(op, so, level, optname, mp)
342: int op;
343: struct socket *so;
344: int level, optname;
345: struct mbuf **mp;
346: {
347: int error = 0;
348: struct inpcb *inp = sotoinpcb(so);
349: register struct tcpcb *tp = intotcpcb(inp);
350: register struct mbuf *m;
351:
352: if (level != IPPROTO_TCP)
353: return (ip_ctloutput(op, so, level, optname, mp));
354:
355: switch (op) {
356:
357: case PRCO_SETOPT:
358: m = *mp;
359: switch (optname) {
360:
361: case TCP_NODELAY:
362: if (m == NULL || m->m_len < sizeof (int))
363: error = EINVAL;
364: else if (*mtod(m, int *))
365: tp->t_flags |= TF_NODELAY;
366: else
367: tp->t_flags &= ~TF_NODELAY;
368: break;
369:
370: case TCP_MAXSEG: /* not yet */
371: default:
372: error = EINVAL;
373: break;
374: }
375: if (m)
376: (void) m_free(m);
377: break;
378:
379: case PRCO_GETOPT:
380: *mp = m = m_get(M_WAIT, MT_SOOPTS);
381: m->m_len = sizeof(int);
382:
383: switch (optname) {
384: case TCP_NODELAY:
385: *mtod(m, int *) = tp->t_flags & TF_NODELAY;
386: break;
387: case TCP_MAXSEG:
388: *mtod(m, int *) = tp->t_maxseg;
389: break;
390: default:
391: error = EINVAL;
392: break;
393: }
394: break;
395: }
396: return (error);
397: }
398:
399: u_long tcp_sendspace = 1024*4;
400: u_long tcp_recvspace = 1024*4;
401:
402: /*
403: * Attach TCP protocol to socket, allocating
404: * internet protocol control block, tcp control block,
405: * bufer space, and entering LISTEN state if to accept connections.
406: */
407: tcp_attach(so)
408: struct socket *so;
409: {
410: register struct tcpcb *tp;
411: struct inpcb *inp;
412: int error;
413:
414: if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0) {
415: error = soreserve(so, tcp_sendspace, tcp_recvspace);
416: if (error)
417: return (error);
418: }
419: error = in_pcballoc(so, &tcb);
420: if (error)
421: return (error);
422: inp = sotoinpcb(so);
423: tp = tcp_newtcpcb(inp);
424: if (tp == 0) {
425: int nofd = so->so_state & SS_NOFDREF; /* XXX */
426:
427: so->so_state &= ~SS_NOFDREF; /* don't free the socket yet */
428: in_pcbdetach(inp);
429: so->so_state |= nofd;
430: return (ENOBUFS);
431: }
432: tp->t_state = TCPS_CLOSED;
433: return (0);
434: }
435:
436: /*
437: * Initiate (or continue) disconnect.
438: * If embryonic state, just send reset (once).
439: * If in ``let data drain'' option and linger null, just drop.
440: * Otherwise (hard), mark socket disconnecting and drop
441: * current input data; switch states based on user close, and
442: * send segment to peer (with FIN).
443: */
444: struct tcpcb *
445: tcp_disconnect(tp)
446: register struct tcpcb *tp;
447: {
448: struct socket *so = tp->t_inpcb->inp_socket;
449:
450: if (tp->t_state < TCPS_ESTABLISHED)
451: tp = tcp_close(tp);
452: else if ((so->so_options & SO_LINGER) && so->so_linger == 0)
453: tp = tcp_drop(tp, 0);
454: else {
455: soisdisconnecting(so);
456: sbflush(&so->so_rcv);
457: tp = tcp_usrclosed(tp);
458: if (tp)
459: (void) tcp_output(tp);
460: }
461: return (tp);
462: }
463:
464: /*
465: * User issued close, and wish to trail through shutdown states:
466: * if never received SYN, just forget it. If got a SYN from peer,
467: * but haven't sent FIN, then go to FIN_WAIT_1 state to send peer a FIN.
468: * If already got a FIN from peer, then almost done; go to LAST_ACK
469: * state. In all other cases, have already sent FIN to peer (e.g.
470: * after PRU_SHUTDOWN), and just have to play tedious game waiting
471: * for peer to send FIN or not respond to keep-alives, etc.
472: * We can let the user exit from the close as soon as the FIN is acked.
473: */
474: struct tcpcb *
475: tcp_usrclosed(tp)
476: register struct tcpcb *tp;
477: {
478:
479: switch (tp->t_state) {
480:
481: case TCPS_CLOSED:
482: case TCPS_LISTEN:
483: case TCPS_SYN_SENT:
484: tp->t_state = TCPS_CLOSED;
485: tp = tcp_close(tp);
486: break;
487:
488: case TCPS_SYN_RECEIVED:
489: case TCPS_ESTABLISHED:
490: tp->t_state = TCPS_FIN_WAIT_1;
491: break;
492:
493: case TCPS_CLOSE_WAIT:
494: tp->t_state = TCPS_LAST_ACK;
495: break;
496: }
497: if (tp && tp->t_state >= TCPS_FIN_WAIT_2)
498: soisdisconnected(tp->t_inpcb->inp_socket);
499: return (tp);
500: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.