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