|
|
1.1 root 1: /* tcp_input.c 6.1 83/07/29 */
2:
3: #include "../h/param.h"
4: #include "../h/systm.h"
5: #include "../h/mbuf.h"
6: #include "../h/protosw.h"
7: #include "../h/socket.h"
8: #include "../h/socketvar.h"
9: #include "../h/errno.h"
10:
11: #include "../net/if.h"
12: #include "../net/route.h"
13:
14: #include "../netinet/in.h"
15: #include "../netinet/in_pcb.h"
16: #include "../netinet/in_systm.h"
17: #include "../netinet/ip.h"
18: #include "../netinet/ip_var.h"
19: #include "../netinet/tcp.h"
20: #include "../netinet/tcp_fsm.h"
21: #include "../netinet/tcp_seq.h"
22: #include "../netinet/tcp_timer.h"
23: #include "../netinet/tcp_var.h"
24: #include "../netinet/tcpip.h"
25: #include "../netinet/tcp_debug.h"
26:
27: #ifdef NET_PERF
28: # define TCPSTUDY(X) {X}
29: #else NET_PERF
30: # define TCPSTUDY(X)
31: #endif
32:
33: int tcptrace; /* debug trace flag */
34: int tcpprintfs = 0;
35: int tcpcksum = 1;
36: struct tcpiphdr tcp_saveti;
37: extern int tcpnodelack;
38:
39: struct tcpcb *tcp_newtcpcb();
40:
41: /*
42: * Changes:
43: *
44: * . from Usenet: turn on 2MSL timer when entering FIN_WAIT_2
45: * state to ensure the connection eventually drops.
46: *
47: * . from Usenet: fix TCP max seg size option handling.
48: * set default segmentation length based on the mtu of the
49: * underlying network interface.
50: */
51: /*
52: * TCP input routine, follows pages 65-76 of the
53: * protocol specification dated September, 1981 very closely.
54: */
55: tcp_input(m0)
56: struct mbuf *m0;
57: {
58: register struct tcpiphdr *ti;
59: struct inpcb *inp;
60: register struct mbuf *m;
61: struct mbuf *om = 0;
62: int len, tlen, off;
63: register struct tcpcb *tp = 0;
64: register int tiflags;
65: struct socket *so;
66: int todrop, acked;
67: short ostate;
68: struct in_addr laddr;
69: int dropsocket = 0;
1.1.1.2 ! root 70: struct ifnet *ifp, *ifnet;
1.1 root 71: struct ifnet *tcp_getif();
72: u_short ifmss;
73:
74: /*
75: * Get IP and TCP header together in first mbuf.
76: * Note: IP leaves IP header in first mbuf.
77: */
78: m = m0;
79: ti = mtod(m, struct tcpiphdr *);
80: if (((struct ip *)ti)->ip_hl > (sizeof (struct ip) >> 2))
81: ip_stripoptions((struct ip *)ti, (struct mbuf *)0);
82: if (m->m_off > MMAXOFF || m->m_len < sizeof (struct tcpiphdr)) {
83: if ((m = m_pullup(m, sizeof (struct tcpiphdr))) == 0) {
84: tcpstat.tcps_hdrops++;
85: return;
86: }
87: ti = mtod(m, struct tcpiphdr *);
88: }
89:
90: /*
91: * Checksum extended TCP header and data.
92: */
93: tlen = ((struct ip *)ti)->ip_len;
94: len = sizeof (struct ip) + tlen;
95: if (tcpcksum) {
96: ti->ti_next = ti->ti_prev = 0;
97: ti->ti_x1 = 0;
98: ti->ti_len = (u_short)tlen;
99: ti->ti_len = htons((u_short)ti->ti_len);
100: if (ti->ti_sum = in_cksum(m, len)) {
101: if (tcpprintfs)
102: printf("tcp sum: src %x, len %d\n", ti->ti_src,len);
103: tcpstat.tcps_badsum++;
104: goto drop;
105: }
106: }
107:
108: /*
109: * Check that TCP offset makes sense,
110: * pull out TCP options and adjust length.
111: */
112: off = ti->ti_off << 2;
113: if (off < sizeof (struct tcphdr) || off > tlen) {
114: if (tcpprintfs)
115: printf("tcp off: src %x off %d\n", ti->ti_src, off);
116: tcpstat.tcps_badoff++;
117: goto drop;
118: }
119: tlen -= off;
120: ti->ti_len = tlen;
121: if (off > sizeof (struct tcphdr)) {
122: if ((m = m_pullup(m, sizeof (struct ip) + off)) == 0) {
123: tcpstat.tcps_hdrops++;
124: return;
125: }
126: ti = mtod(m, struct tcpiphdr *);
127: om = m_get(M_DONTWAIT, MT_DATA);
128: MBUFNULL(11, om); /* for debugging */
129: if (om == 0)
130: goto drop;
131: om->m_len = off - sizeof (struct tcphdr);
132: { caddr_t op = mtod(m, caddr_t) + sizeof (struct tcpiphdr);
133: bcopy(op, mtod(om, caddr_t), (unsigned)om->m_len);
134: m->m_len -= om->m_len;
135: bcopy(op+om->m_len, op,
136: (unsigned)(m->m_len-sizeof (struct tcpiphdr)));
137: }
138: }
139: tiflags = ti->ti_flags;
140:
141: /*
142: * Drop TCP and IP headers.
143: */
144: off += sizeof (struct ip);
1.1.1.2 ! root 145: m->m_off += sizeof(struct tcpiphdr);
! 146: m->m_len -= sizeof(struct tcpiphdr);
1.1 root 147:
148: /*
149: * Convert TCP protocol specific fields to host format.
150: */
151: ti->ti_seq = ntohl(ti->ti_seq);
152: ti->ti_ack = ntohl(ti->ti_ack);
153: ti->ti_win = ntohs(ti->ti_win);
154: ti->ti_urp = ntohs(ti->ti_urp);
155:
156: /*
157: * Locate pcb for segment.
158: */
159: inp = in_pcblookup
160: (&tcb, ti->ti_src, ti->ti_sport, ti->ti_dst, ti->ti_dport,
161: INPLOOKUP_WILDCARD);
162:
163: /*
164: * If the state is CLOSED (i.e., TCB does not exist) then
165: * all data in the incoming segment is discarded.
166: */
167: if (inp == 0) {
168: TCPSTUDY(tcpstudy.tcps_notinpcb++;)
169: goto dropwithreset;
170: }
171: tp = intotcpcb(inp);
172: if (tp == 0) {
173: TCPSTUDY(tcpstudy.tcps_notcpcb++;)
174: goto dropwithreset;
175: }
176: so = inp->inp_socket;
177: if (so->so_options & SO_DEBUG) {
178: ostate = tp->t_state;
179: tcp_saveti = *ti;
180: }
181: if (so->so_options & SO_ACCEPTCONN) {
182: so = sonewconn(so);
183: if (so == 0)
184: goto drop;
185: /*
186: * This is ugly, but ....
187: *
188: * Mark socket as temporary until we're
189: * committed to keeping it. The code at
190: * ``drop'' and ``dropwithreset'' check the
191: * flag dropsocket to see if the temporary
192: * socket created here should be discarded.
193: * We mark the socket as discardable until
194: * we're committed to it below in TCPS_LISTEN.
195: */
196: dropsocket++;
197: inp = (struct inpcb *)so->so_pcb;
198: inp->inp_laddr = ti->ti_dst;
199: inp->inp_lport = ti->ti_dport;
200: tp = intotcpcb(inp);
201: tp->t_state = TCPS_LISTEN;
202: }
203:
204: /*
205: * Segment received on connection.
206: * Reset idle time and keep-alive timer.
207: */
208: tp->t_idle = 0;
209: tp->t_timer[TCPT_KEEP] = TCPTV_KEEP;
210:
211: /*
212: * Process options.
213: */
214: if (om) {
215: /* if in LISTEN, template has not been filled in yet.
216: delay processing of options */
217: if (tp->t_state != TCPS_LISTEN) {
218: tcp_dooptions(tp, ti, om);
219: om = 0;
220: }
221: }
222:
223: /*
224: * Calculate amount of space in receive window,
225: * and then do TCP input processing.
226: */
227: tp->rcv_wnd = sbspace(&so->so_rcv);
228: if (tp->rcv_wnd < 0)
229: tp->rcv_wnd = 0;
230:
231: switch (tp->t_state) {
232:
233: /*
234: * If the state is LISTEN then ignore segment if it contains an RST.
235: * If the segment contains an ACK then it is bad and send a RST.
236: * If it does not contain a SYN then it is not interesting; drop it.
237: * Otherwise initialize tp->rcv_nxt, and tp->irs, select an initial
238: * tp->iss, and send a segment:
239: * <SEQ=ISS><ACK=RCV_NXT><CTL=SYN,ACK>
240: * Also initialize tp->snd_nxt to tp->iss+1 and tp->snd_una to tp->iss.
241: * Fill in remote peer address fields if not previously specified.
242: * Enter SYN_RECEIVED state, and process any other fields of this
243: * segment in this state.
244: */
245: case TCPS_LISTEN: {
246: struct mbuf *am;
247: register struct sockaddr_in *sin;
248:
249: if (tiflags & TH_RST) {
250: TCPSTUDY(tcpstudy.tcps_badstate++;)
251: goto drop;
252: }
253: if (tiflags & TH_ACK) {
254: TCPSTUDY(tcpstudy.tcps_badstate++;)
255: goto dropwithreset;
256: }
257: if ((tiflags & TH_SYN) == 0) {
258: TCPSTUDY(tcpstudy.tcps_badstate++;)
259: goto drop;
260: }
261: am = m_get(M_DONTWAIT, MT_SONAME);
262: MBUFNULL(12, am); /* for debugging */
263: if (am == NULL)
264: goto drop;
265: am->m_len = sizeof (struct sockaddr_in);
266: sin = mtod(am, struct sockaddr_in *);
267: sin->sin_family = AF_INET;
268: sin->sin_addr = ti->ti_src;
269: sin->sin_port = ti->ti_sport;
270: laddr = inp->inp_laddr;
271: if (inp->inp_laddr.s_addr == INADDR_ANY)
272: inp->inp_laddr = ti->ti_dst;
273: if (in_pcbconnect(inp, am)) {
274: inp->inp_laddr = laddr;
275: (void) m_free(am);
276: TCPSTUDY(tcpstudy.tcps_noconnect++;)
277: goto drop;
278: }
279: (void) m_free(am);
280: tp->t_template = tcp_template(tp);
281: if (tp->t_template == 0) {
282: in_pcbdisconnect(inp);
283: inp->inp_laddr = laddr;
284: tp = 0;
285: goto drop;
286: }
287: /* finally we can do the options */
288: if (om) {
289: tcp_dooptions(tp, ti, om);
290: om = 0;
291: }
292: tp->iss = tcp_iss; tcp_iss += TCP_ISSINCR/2;
293: tp->irs = ti->ti_seq;
294: tcp_sendseqinit(tp);
295: tcp_rcvseqinit(tp);
296: tp->t_state = TCPS_SYN_RECEIVED;
297: tp->t_timer[TCPT_KEEP] = TCPTV_KEEP;
298: dropsocket = 0; /* committed to socket */
299: goto trimthenstep6;
300: }
301:
302: /*
303: * If the state is SYN_SENT:
304: * if seg contains an ACK, but not for our SYN, drop the input.
305: * if seg contains a RST, then drop the connection.
306: * if seg does not contain SYN, then drop it.
307: * Otherwise this is an acceptable SYN segment
308: * initialize tp->rcv_nxt and tp->irs
309: * if seg contains ack then advance tp->snd_una
310: * if SYN has been acked change to ESTABLISHED else SYN_RCVD state
311: * arrange for segment to be acked (eventually)
312: * continue processing rest of data/controls, beginning with URG
313: */
314: case TCPS_SYN_SENT:
315: if ((tiflags & TH_ACK) &&
316: /* this should be SEQ_LT; is SEQ_LEQ for BBN vax TCP only */
317: (SEQ_LT(ti->ti_ack, tp->iss) ||
318: SEQ_GT(ti->ti_ack, tp->snd_max))) {
319: TCPSTUDY(tcpstudy.tcps_ackoutofseq++;)
320: goto dropwithreset;
321: }
322: if (tiflags & TH_RST) {
323: if (tiflags & TH_ACK)
324: tp = tcp_drop(tp, ECONNREFUSED);
325: goto drop;
326: }
327: if ((tiflags & TH_SYN) == 0)
328: goto drop;
329: tp->snd_una = ti->ti_ack;
330: if (SEQ_LT(tp->snd_nxt, tp->snd_una))
331: tp->snd_nxt = tp->snd_una;
332: tp->t_timer[TCPT_REXMT] = 0;
333: tp->irs = ti->ti_seq;
334: tcp_rcvseqinit(tp);
335: tp->t_flags |= TF_ACKNOW;
336: if (SEQ_GT(tp->snd_una, tp->iss)) {
337: soisconnected(so);
338: tp->t_state = TCPS_ESTABLISHED;
339: (void) tcp_reass(tp, (struct tcpiphdr *)0);
340: /*
341: * Tune maximum TCP segment size to interface mtu
342: */
343: ifp = (struct ifnet *) tcp_getif(tp);
344: if (ifp != (struct ifnet *)0) {
345: ifmss = ifp->if_mtu - sizeof(struct tcpiphdr);
346: if (tcpprintfs)
347: printf( "tcp trim1 (mtu, ms)==(%d,%d) ->",
348: ifmss, tp->t_maxseg);
349: tp->t_maxseg = MIN(ifmss, tp->t_maxseg);
350: if (tcpprintfs)
351: printf("%d\n", tp->t_maxseg);
352: }
353: } else
354: tp->t_state = TCPS_SYN_RECEIVED;
355: goto trimthenstep6;
356:
357: trimthenstep6:
358: /*
359: * Advance ti->ti_seq to correspond to first data byte.
360: * If data, trim to stay within window,
361: * dropping FIN if necessary.
362: */
363: ti->ti_seq++;
364: if (ti->ti_len > tp->rcv_wnd) {
365: todrop = ti->ti_len - tp->rcv_wnd;
366: m_adj(m, -todrop);
367: ti->ti_len = tp->rcv_wnd;
368: ti->ti_flags &= ~TH_FIN;
369: }
370: tp->snd_wl1 = ti->ti_seq - 1;
371: goto step6;
372: }
373:
374: /*
375: * States other than LISTEN or SYN_SENT.
376: * First check that at least some bytes of segment are within
377: * receive window.
378: */
379: if (tp->rcv_wnd == 0) {
380: /*
381: * If window is closed can only take segments at
382: * window edge, and have to drop data and PUSH from
383: * incoming segments.
384: */
385: if (tp->rcv_nxt != ti->ti_seq) {
386: TCPSTUDY(tcpstudy.tcps_outwinedge++;)
387: goto dropafterack;
388: }
389: if (ti->ti_len > 0) {
390: m_adj(m, ti->ti_len);
391: ti->ti_len = 0;
392: ti->ti_flags &= ~(TH_PUSH|TH_FIN);
393: }
394: } else {
395: /*
396: * If segment begins before rcv_nxt, drop leading
397: * data (and SYN); if nothing left, just ack.
398: */
399: todrop = tp->rcv_nxt - ti->ti_seq;
400: if (todrop > 0) {
401: if (tiflags & TH_SYN) {
402: tiflags &= ~TH_SYN;
403: ti->ti_flags &= ~TH_SYN;
404: ti->ti_seq++;
405: if (ti->ti_urp > 1)
406: ti->ti_urp--;
407: else
408: tiflags &= ~TH_URG;
409: todrop--;
410: }
411: if (todrop > ti->ti_len ||
412: todrop == ti->ti_len && (tiflags&TH_FIN) == 0)
413: goto dropafterack;
414: m_adj(m, todrop);
415: ti->ti_seq += todrop;
416: ti->ti_len -= todrop;
417: if (ti->ti_urp > todrop)
418: ti->ti_urp -= todrop;
419: else {
420: tiflags &= ~TH_URG;
421: ti->ti_flags &= ~TH_URG;
422: ti->ti_urp = 0;
423: }
424: }
425: /*
426: * If segment ends after window, drop trailing data
427: * (and PUSH and FIN); if nothing left, just ACK.
428: */
429: todrop = (ti->ti_seq+ti->ti_len) - (tp->rcv_nxt+tp->rcv_wnd);
430: if (todrop > 0) {
431: if (todrop >= ti->ti_len) {
432: TCPSTUDY(tcpstudy.tcps_outwinedge++;)
433: goto dropafterack;
434: }
435: m_adj(m, -todrop);
436: ti->ti_len -= todrop;
437: ti->ti_flags &= ~(TH_PUSH|TH_FIN);
438: }
439: }
440:
441: /*
442: * If data is received on a connection after the
443: * user processes are gone, then RST the other end.
444: */
445: if ((so->so_state & SS_NOFDREF) && tp->t_state > TCPS_CLOSE_WAIT &&
446: ti->ti_len) {
447: tp = tcp_close(tp);
448: goto dropwithreset;
449: }
450:
451: /*
452: * If the RST bit is set examine the state:
453: * SYN_RECEIVED STATE:
454: * If passive open, return to LISTEN state.
455: * If active open, inform user that connection was refused.
456: * ESTABLISHED, FIN_WAIT_1, FIN_WAIT2, CLOSE_WAIT STATES:
457: * Inform user that connection was reset, and close tcb.
458: * CLOSING, LAST_ACK, TIME_WAIT STATES
459: * Close the tcb.
460: */
461: if (tiflags&TH_RST) switch (tp->t_state) {
462:
463: case TCPS_SYN_RECEIVED:
464: tp = tcp_drop(tp, ECONNREFUSED);
465: goto drop;
466:
467: case TCPS_ESTABLISHED:
468: case TCPS_FIN_WAIT_1:
469: case TCPS_FIN_WAIT_2:
470: case TCPS_CLOSE_WAIT:
471: tp = tcp_drop(tp, ECONNRESET);
472: goto drop;
473:
474: case TCPS_CLOSING:
475: case TCPS_LAST_ACK:
476: case TCPS_TIME_WAIT:
477: tp = tcp_close(tp);
478: goto drop;
479: }
480:
481: /*
482: * If a SYN is in the window, then this is an
483: * error and we send an RST and drop the connection.
484: */
485: if (tiflags & TH_SYN) {
486: tp = tcp_drop(tp, ECONNRESET);
487: goto dropwithreset;
488: }
489:
490: /*
491: * If the ACK bit is off we drop the segment and return.
492: */
493: if ((tiflags & TH_ACK) == 0)
494: goto drop;
495:
496: /*
497: * Ack processing.
498: */
499: switch (tp->t_state) {
500:
501: /*
502: * In SYN_RECEIVED state if the ack ACKs our SYN then enter
503: * ESTABLISHED state and continue processing, othewise
504: * send an RST.
505: */
506: case TCPS_SYN_RECEIVED:
507: if (SEQ_GT(tp->snd_una, ti->ti_ack) ||
508: SEQ_GT(ti->ti_ack, tp->snd_max)) {
509: TCPSTUDY(tcpstudy.tcps_ackoutofseq++;)
510: goto dropwithreset;
511: }
512: tp->snd_una++; /* SYN acked */
513: if (SEQ_LT(tp->snd_nxt, tp->snd_una))
514: tp->snd_nxt = tp->snd_una;
515: tp->t_timer[TCPT_REXMT] = 0;
516: soisconnected(so);
517: tp->t_state = TCPS_ESTABLISHED;
518: (void) tcp_reass(tp, (struct tcpiphdr *)0);
519: ifp = (struct ifnet *) tcp_getif(tp);
520: if (ifp != (struct ifnet *)0) {
521: ifmss = ifp->if_mtu - sizeof(struct tcpiphdr);
522: if (tcpprintfs)
523: printf( "tcp trim2 (mtu, ms)==(%d,%d) ->",
524: ifmss, tp->t_maxseg);
525: tp->t_maxseg = MIN(ifmss, tp->t_maxseg);
526: if (tcpprintfs)
527: printf("%d\n", tp->t_maxseg);
528: }
529: tp->snd_wl1 = ti->ti_seq - 1;
530: /* fall into ... */
531:
532: /*
533: * In ESTABLISHED state: drop duplicate ACKs; ACK out of range
534: * ACKs. If the ack is in the range
535: * tp->snd_una < ti->ti_ack <= tp->snd_max
536: * then advance tp->snd_una to ti->ti_ack and drop
537: * data from the retransmission queue. If this ACK reflects
538: * more up to date window information we update our window information.
539: */
540: case TCPS_ESTABLISHED:
541: case TCPS_FIN_WAIT_1:
542: case TCPS_FIN_WAIT_2:
543: case TCPS_CLOSE_WAIT:
544: case TCPS_CLOSING:
545: case TCPS_LAST_ACK:
546: case TCPS_TIME_WAIT:
547: #define ourfinisacked (acked > 0)
548:
549: if (SEQ_LEQ(ti->ti_ack, tp->snd_una))
550: break;
551: if (SEQ_GT(ti->ti_ack, tp->snd_max)) {
552: TCPSTUDY(tcpstudy.tcps_ackoutofseq++;)
553: goto dropafterack;
554: }
555: acked = ti->ti_ack - tp->snd_una;
556:
557: /*
558: * If transmit timer is running and timed sequence
559: * number was acked, update smoothed round trip time.
560: */
561: if (tp->t_rtt && SEQ_GT(ti->ti_ack, tp->t_rtseq)) {
562: if (tp->t_srtt == 0)
563: tp->t_srtt = tp->t_rtt;
564: else
565: tp->t_srtt =
566: tcp_alpha * tp->t_srtt +
567: (1 - tcp_alpha) * tp->t_rtt;
1.1.1.2 ! root 568: /*
! 569: * Kludge. We adjust the srtt value for x25/l2 interface
! 570: * or serial line to reduce the number of retries when
! 571: * the line is loaded. The value is proportional to
! 572: * the load, i.e., the route's reference count.
! 573: */
! 574: if (tp->t_inpcb->inp_route.ro_rt) {
! 575: ifnet = tp->t_inpcb->inp_route.ro_rt->rt_ifp;
! 576: if (tp->t_srtt &&
! 577: ifnet &&
! 578: ifnet->if_name[0] == 's' &&
! 579: (ifnet->if_name[1] == 'd' ||
! 580: ifnet->if_name[1] == 'l')) {
! 581: tp->t_srtt += tp->t_inpcb->inp_route.ro_rt->rt_refcnt;
! 582: }
! 583: }
1.1 root 584: tp->t_rtt = 0;
585: }
586:
587: if (ti->ti_ack == tp->snd_max)
588: tp->t_timer[TCPT_REXMT] = 0;
589: else {
590: TCPT_RANGESET(tp->t_timer[TCPT_REXMT],
591: tcp_beta * tp->t_srtt, TCPTV_MIN, TCPTV_MAX);
592: tp->t_rtt = 1;
1.1.1.2 ! root 593: tp->t_rtseq = ti->ti_ack;
1.1 root 594: tp->t_rxtshift = 0;
595: }
596: if (acked > so->so_snd.sb_cc) {
597: sbdrop(&so->so_snd, so->so_snd.sb_cc);
598: tp->snd_wnd -= so->so_snd.sb_cc;
599: } else {
600: sbdrop(&so->so_snd, acked);
601: tp->snd_wnd -= acked;
602: acked = 0;
603: }
604: if ((so->so_snd.sb_flags & SB_WAIT) || so->so_snd.sb_sel)
605: sowwakeup(so);
606: tp->snd_una = ti->ti_ack;
607: if (SEQ_LT(tp->snd_nxt, tp->snd_una))
608: tp->snd_nxt = tp->snd_una;
609:
610: switch (tp->t_state) {
611:
612: /*
613: * In FIN_WAIT_1 STATE in addition to the processing
614: * for the ESTABLISHED state if our FIN is now acknowledged
615: * then enter FIN_WAIT_2.
616: */
617: case TCPS_FIN_WAIT_1:
618: if (ourfinisacked) {
619: /*
620: * If we can't receive any more
621: * data, then closing user can proceed.
622: */
623: if (so->so_state & SS_CANTRCVMORE)
624: soisdisconnected(so);
625: tp->t_state = TCPS_FIN_WAIT_2;
626: tp->t_timer[TCPT_2MSL] = 2 * TCPTV_MSL;
627: }
628: break;
629:
630: /*
631: * In CLOSING STATE in addition to the processing for
632: * the ESTABLISHED state if the ACK acknowledges our FIN
633: * then enter the TIME-WAIT state, otherwise ignore
634: * the segment.
635: */
636: case TCPS_CLOSING:
637: if (ourfinisacked) {
638: tp->t_state = TCPS_TIME_WAIT;
639: tcp_canceltimers(tp);
640: tp->t_timer[TCPT_2MSL] = 2 * TCPTV_MSL;
641: soisdisconnected(so);
642: }
643: break;
644:
645: /*
646: * The only thing that can arrive in LAST_ACK state
647: * is an acknowledgment of our FIN. If our FIN is now
648: * acknowledged, delete the TCB, enter the closed state
649: * and return.
650: */
651: case TCPS_LAST_ACK:
652: if (ourfinisacked)
653: tp = tcp_close(tp);
654: goto drop;
655:
656: /*
657: * In TIME_WAIT state the only thing that should arrive
658: * is a retransmission of the remote FIN. Acknowledge
659: * it and restart the finack timer.
660: */
661: case TCPS_TIME_WAIT:
662: tp->t_timer[TCPT_2MSL] = 2 * TCPTV_MSL;
663: goto dropafterack;
664: }
665: #undef ourfinisacked
666: }
667:
668: step6:
669: /*
670: * Update window information.
671: */
672: if (SEQ_LT(tp->snd_wl1, ti->ti_seq) || tp->snd_wl1 == ti->ti_seq &&
673: (SEQ_LT(tp->snd_wl2, ti->ti_ack) ||
674: tp->snd_wl2 == ti->ti_ack && ti->ti_win > tp->snd_wnd)) {
675: tp->snd_wnd = ti->ti_win;
676: tp->snd_wl1 = ti->ti_seq;
677: tp->snd_wl2 = ti->ti_ack;
678: if (tp->snd_wnd != 0)
679: tp->t_timer[TCPT_PERSIST] = 0;
680: }
681:
682: /*
683: * Process segments with URG.
684: */
685: if ((tiflags & TH_URG) && ti->ti_urp &&
686: TCPS_HAVERCVDFIN(tp->t_state) == 0) {
687: /*
688: * This is a kludge, but if we receive accept
689: * random urgent pointers, we'll crash in
690: * soreceive. It's hard to imagine someone
691: * actually wanting to send this much urgent data.
692: */
693: if (ti->ti_urp > tp->t_maxseg) { /* XXX */
694: ti->ti_urp = 0; /* XXX */
695: tiflags &= ~TH_URG; /* XXX */
696: ti->ti_flags &= ~TH_URG; /* XXX */
697: goto badurp; /* XXX */
698: }
699: /*
700: * If this segment advances the known urgent pointer,
701: * then mark the data stream. This should not happen
702: * in CLOSE_WAIT, CLOSING, LAST_ACK or TIME_WAIT STATES since
703: * a FIN has been received from the remote side.
704: * In these states we ignore the URG.
705: */
706: if (SEQ_GT(ti->ti_seq+ti->ti_urp, tp->rcv_up)) {
707: tp->rcv_up = ti->ti_seq + ti->ti_urp;
708: so->so_oobmark = so->so_rcv.sb_cc +
709: (tp->rcv_up - tp->rcv_nxt) - 1;
710: if (so->so_oobmark == 0)
711: so->so_state |= SS_RCVATMARK;
712: sohasoutofband(so);
713: tp->t_oobflags &= ~TCPOOB_HAVEDATA;
714: }
715: /*
716: * Remove out of band data so doesn't get presented to user.
717: * This can happen independent of advancing the URG pointer,
718: * but if two URG's are pending at once, some out-of-band
719: * data may creep in... ick.
720: */
721: if (ti->ti_urp <= ti->ti_len)
722: tcp_pulloutofband(so, ti);
723: }
724: badurp: /* XXX */
725:
726: /*
727: * Process the segment text, merging it into the TCP sequencing queue,
728: * and arranging for acknowledgment of receipt if necessary.
729: * This process logically involves adjusting tp->rcv_wnd as data
730: * is presented to the user (this happens in tcp_usrreq.c,
731: * case PRU_RCVD). If a FIN has already been received on this
732: * connection then we just ignore the text.
733: */
734: if ((ti->ti_len || (tiflags&TH_FIN)) &&
735: TCPS_HAVERCVDFIN(tp->t_state) == 0) {
736: tiflags = tcp_reass(tp, ti);
737: if (tcpnodelack == 0)
738: tp->t_flags |= TF_DELACK;
739: else
740: tp->t_flags |= TF_ACKNOW;
741: } else {
742: m_freem(m);
743: tiflags &= ~TH_FIN;
744: }
745:
746: /*
747: * If FIN is received ACK the FIN and let the user know
748: * that the connection is closing.
749: */
750: if (tiflags & TH_FIN) {
751: if (TCPS_HAVERCVDFIN(tp->t_state) == 0) {
752: socantrcvmore(so);
753: tp->t_flags |= TF_ACKNOW;
754: tp->rcv_nxt++;
755: }
756: switch (tp->t_state) {
757:
758: /*
759: * In SYN_RECEIVED and ESTABLISHED STATES
760: * enter the CLOSE_WAIT state.
761: */
762: case TCPS_SYN_RECEIVED:
763: case TCPS_ESTABLISHED:
764: tp->t_state = TCPS_CLOSE_WAIT;
765: break;
766:
767: /*
768: * If still in FIN_WAIT_1 STATE FIN has not been acked so
769: * enter the CLOSING state.
770: */
771: case TCPS_FIN_WAIT_1:
772: tp->t_state = TCPS_CLOSING;
773: break;
774:
775: /*
776: * In FIN_WAIT_2 state enter the TIME_WAIT state,
777: * starting the time-wait timer, turning off the other
778: * standard timers.
779: */
780: case TCPS_FIN_WAIT_2:
781: tp->t_state = TCPS_TIME_WAIT;
782: tcp_canceltimers(tp);
783: tp->t_timer[TCPT_2MSL] = 2 * TCPTV_MSL;
784: soisdisconnected(so);
785: break;
786:
787: /*
788: * In TIME_WAIT state restart the 2 MSL time_wait timer.
789: */
790: case TCPS_TIME_WAIT:
791: tp->t_timer[TCPT_2MSL] = 2 * TCPTV_MSL;
792: break;
793: }
794: }
795: if (so->so_options & SO_DEBUG || tcptrace)
796: {
797: tcp_trace(TA_INPUT, ostate, tp, &tcp_saveti, 0);
798: }
799:
800: /*
801: * Return any desired output.
802: */
803: (void) tcp_output(tp);
804: return;
805:
806: dropafterack:
807: /*
808: * Generate an ACK dropping incoming segment if it occupies
809: * sequence space, where the ACK reflects our state.
810: */
811: if ((tiflags&TH_RST) ||
812: tlen == 0 && (tiflags&(TH_SYN|TH_FIN)) == 0)
813: goto drop;
814: if (tp->t_inpcb->inp_socket->so_options & SO_DEBUG || tcptrace)
815: {
816: tcp_trace(TA_RESPOND, ostate, tp, &tcp_saveti, 0);
817: }
818: tcp_respond(tp, ti, tp->rcv_nxt, tp->snd_nxt, TH_ACK);
819: return;
820:
821: dropwithreset:
822: if (om) {
823: (void) m_free(om);
824: om = 0;
825: }
826: /*
827: * Generate a RST, dropping incoming segment.
828: * Make ACK acceptable to originator of segment.
829: */
830: if (tiflags & TH_RST)
831: goto drop;
832: if (tiflags & TH_ACK)
833: tcp_respond(tp, ti, (tcp_seq)0, ti->ti_ack, TH_RST);
834: else {
835: if (tiflags & TH_SYN)
836: ti->ti_len++;
837: tcp_respond(tp, ti, ti->ti_seq+ti->ti_len, (tcp_seq)0,
838: TH_RST|TH_ACK);
839: }
840: /* destroy temporarily created socket */
841: if (dropsocket)
842: (void) soabort(so);
843: return;
844:
845: drop:
846: if (om)
847: (void) m_free(om);
848: /*
849: * Drop space held by incoming segment and return.
850: */
851: if (tp && (tp->t_inpcb->inp_socket->so_options & SO_DEBUG) || tcptrace)
852: {
853: tcp_trace(TA_DROP, ostate, tp, &tcp_saveti, 0);
854: }
855: m_freem(m);
856: /* destroy temporarily created socket */
857: if (dropsocket)
858: (void) soabort(so);
859: return;
860: }
861:
862: tcp_dooptions(tp, ti, om)
863: struct tcpcb *tp;
864: struct tcpiphdr *ti;
865: struct mbuf *om;
866: {
867: register u_char *cp;
868: int opt, optlen, cnt;
869:
870: cp = mtod(om, u_char *);
871: cnt = om->m_len;
872: for (; cnt > 0; cnt -= optlen, cp += optlen) {
873: opt = cp[0];
874: if (opt == TCPOPT_EOL)
875: break;
876: if (opt == TCPOPT_NOP)
877: optlen = 1;
878: else {
879: optlen = cp[1];
880: if (optlen <= 0)
881: break;
882: }
883: switch (opt) {
884:
885: default:
886: break;
887:
888: case TCPOPT_MAXSEG:
889: if (optlen != 4)
890: continue;
891: if ((ti->ti_flags & TH_SYN) != TH_SYN)
892: continue;
893: tp->t_maxseg = *(u_short *)(cp + 2);
894: tp->t_maxseg = ntohs((u_short)tp->t_maxseg);
895: if (tcpprintfs)
896: printf("tcp_dooptions: maxseg %d\n",tp->t_maxseg);
897: break;
898: }
899: }
900: (void) m_free(om);
901: }
902:
903: /*
904: * Pull out of band byte out of a segment so
905: * it doesn't appear in the user's data queue.
906: * It is still reflected in the segment length for
907: * sequencing purposes.
908: */
909: tcp_pulloutofband(so, ti)
910: struct socket *so;
911: struct tcpiphdr *ti;
912: {
913: register struct mbuf *m;
914: int cnt = ti->ti_urp - 1;
915:
916: m = dtom(ti);
917: while (cnt >= 0) {
918: if (m->m_len > cnt) {
919: char *cp = mtod(m, caddr_t) + cnt;
920: struct tcpcb *tp = sototcpcb(so);
921:
922: tp->t_iobc = *cp;
923: tp->t_oobflags |= TCPOOB_HAVEDATA;
924: bcopy(cp+1, cp, (unsigned)(m->m_len - cnt - 1));
925: m->m_len--;
926: return;
927: }
928: cnt -= m->m_len;
929: m = m->m_next;
930: if (m == 0)
931: break;
932: }
933: panic("tcp_pulloutofband");
934: }
935:
936: /*
937: * Insert segment ti into reassembly queue of tcp with
938: * control block tp. Return TH_FIN if reassembly now includes
939: * a segment with FIN.
940: */
941: tcp_reass(tp, ti)
942: register struct tcpcb *tp;
943: register struct tcpiphdr *ti;
944: {
945: register struct tcpiphdr *q;
946: struct socket *so = tp->t_inpcb->inp_socket;
947: struct mbuf *m;
948: int flags;
949:
950: /*
951: * Call with ti==0 after become established to
952: * force pre-ESTABLISHED data up to user socket.
953: */
954: if (ti == 0)
955: goto present;
956:
957: /*
958: * Find a segment which begins after this one does.
959: */
960: for (q = tp->seg_next; q != (struct tcpiphdr *)tp;
961: q = (struct tcpiphdr *)q->ti_next)
962: if (SEQ_GT(q->ti_seq, ti->ti_seq))
963: break;
964:
965: /*
966: * If there is a preceding segment, it may provide some of
967: * our data already. If so, drop the data from the incoming
968: * segment. If it provides all of our data, drop us.
969: */
970: if ((struct tcpiphdr *)q->ti_prev != (struct tcpiphdr *)tp) {
971: register int i;
972: q = (struct tcpiphdr *)q->ti_prev;
973: /* conversion to int (in i) handles seq wraparound */
974: i = q->ti_seq + q->ti_len - ti->ti_seq;
975: if (i > 0) {
976: if (i >= ti->ti_len)
977: goto drop;
978: m_adj(dtom(ti), i);
979: ti->ti_len -= i;
980: ti->ti_seq += i;
981: }
982: q = (struct tcpiphdr *)(q->ti_next);
983: }
984:
985: /*
986: * While we overlap succeeding segments trim them or,
987: * if they are completely covered, dequeue them.
988: */
989: while (q != (struct tcpiphdr *)tp) {
990: register int i = (ti->ti_seq + ti->ti_len) - q->ti_seq;
991: if (i <= 0)
992: break;
993: if (i < q->ti_len) {
994: q->ti_seq += i;
995: q->ti_len -= i;
996: m_adj(dtom(q), i);
997: break;
998: }
999: q = (struct tcpiphdr *)q->ti_next;
1000: m = dtom(q->ti_prev);
1001: remque(q->ti_prev);
1002: m_freem(m);
1003: }
1004:
1005: /*
1006: * Stick new segment in its place.
1007: */
1008: insque(ti, q->ti_prev);
1009:
1010: present:
1011: /*
1012: * Present data to user, advancing rcv_nxt through
1013: * completed sequence space.
1014: */
1015: if (TCPS_HAVERCVDSYN(tp->t_state) == 0)
1016: return (0);
1017: ti = tp->seg_next;
1018: if (ti == (struct tcpiphdr *)tp || ti->ti_seq != tp->rcv_nxt)
1019: return (0);
1020: if (tp->t_state == TCPS_SYN_RECEIVED && ti->ti_len)
1021: return (0);
1022: do {
1023: tp->rcv_nxt += ti->ti_len;
1024: flags = ti->ti_flags & TH_FIN;
1025: remque(ti);
1026: m = dtom(ti);
1027: ti = (struct tcpiphdr *)ti->ti_next;
1028: if (so->so_state & SS_CANTRCVMORE)
1029: m_freem(m);
1030: else
1031: sbappend(&so->so_rcv, m);
1032: } while (ti != (struct tcpiphdr *)tp && ti->ti_seq == tp->rcv_nxt);
1033: sorwakeup(so);
1034: return (flags);
1035: drop:
1036: m_freem(dtom(ti));
1037: return (0);
1038: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.