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