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