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