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