|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1982, 1986, 1988, 1990, 1993, 1994 ! 3: * The Regents of the University of California. All rights reserved. ! 4: * ! 5: * Redistribution and use in source and binary forms, with or without ! 6: * modification, are permitted provided that the following conditions ! 7: * are met: ! 8: * 1. Redistributions of source code must retain the above copyright ! 9: * notice, this list of conditions and the following disclaimer. ! 10: * 2. Redistributions in binary form must reproduce the above copyright ! 11: * notice, this list of conditions and the following disclaimer in the ! 12: * documentation and/or other materials provided with the distribution. ! 13: * 3. All advertising materials mentioning features or use of this software ! 14: * must display the following acknowledgement: ! 15: * This product includes software developed by the University of ! 16: * California, Berkeley and its contributors. ! 17: * 4. Neither the name of the University nor the names of its contributors ! 18: * may be used to endorse or promote products derived from this software ! 19: * without specific prior written permission. ! 20: * ! 21: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ! 22: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ! 23: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ! 24: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE ! 25: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ! 26: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ! 27: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ! 28: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ! 29: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ! 30: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ! 31: * SUCH DAMAGE. ! 32: * ! 33: * @(#)tcp_input.c 8.5 (Berkeley) 4/10/94 ! 34: * tcp_input.c,v 1.10 1994/10/13 18:36:32 wollman Exp ! 35: */ ! 36: ! 37: /* ! 38: * Changes and additions relating to SLiRP ! 39: * Copyright (c) 1995 Danny Gasparovski. ! 40: * ! 41: * Please read the file COPYRIGHT for the ! 42: * terms and conditions of the copyright. ! 43: */ ! 44: ! 45: #include <slirp.h> ! 46: #include "ip_icmp.h" ! 47: ! 48: struct socket tcb; ! 49: ! 50: int tcprexmtthresh = 3; ! 51: struct socket *tcp_last_so = &tcb; ! 52: ! 53: tcp_seq tcp_iss; /* tcp initial send seq # */ ! 54: ! 55: #define TCP_PAWS_IDLE (24 * 24 * 60 * 60 * PR_SLOWHZ) ! 56: ! 57: /* for modulo comparisons of timestamps */ ! 58: #define TSTMP_LT(a,b) ((int)((a)-(b)) < 0) ! 59: #define TSTMP_GEQ(a,b) ((int)((a)-(b)) >= 0) ! 60: ! 61: /* ! 62: * Insert segment ti into reassembly queue of tcp with ! 63: * control block tp. Return TH_FIN if reassembly now includes ! 64: * a segment with FIN. The macro form does the common case inline ! 65: * (segment is the next to be received on an established connection, ! 66: * and the queue is empty), avoiding linkage into and removal ! 67: * from the queue and repetition of various conversions. ! 68: * Set DELACK for segments received in order, but ack immediately ! 69: * when segments are out of order (so fast retransmit can work). ! 70: */ ! 71: #ifdef TCP_ACK_HACK ! 72: #define TCP_REASS(tp, ti, m, so, flags) {\ ! 73: if ((ti)->ti_seq == (tp)->rcv_nxt && \ ! 74: (tp)->seg_next == (tcpiphdrp_32)(tp) && \ ! 75: (tp)->t_state == TCPS_ESTABLISHED) {\ ! 76: if (ti->ti_flags & TH_PUSH) \ ! 77: tp->t_flags |= TF_ACKNOW; \ ! 78: else \ ! 79: tp->t_flags |= TF_DELACK; \ ! 80: (tp)->rcv_nxt += (ti)->ti_len; \ ! 81: flags = (ti)->ti_flags & TH_FIN; \ ! 82: tcpstat.tcps_rcvpack++;\ ! 83: tcpstat.tcps_rcvbyte += (ti)->ti_len;\ ! 84: if (so->so_emu) { \ ! 85: if (tcp_emu((so),(m))) sbappend((so), (m)); \ ! 86: } else \ ! 87: sbappend((so), (m)); \ ! 88: /* sorwakeup(so); */ \ ! 89: } else {\ ! 90: (flags) = tcp_reass((tp), (ti), (m)); \ ! 91: tp->t_flags |= TF_ACKNOW; \ ! 92: } \ ! 93: } ! 94: #else ! 95: #define TCP_REASS(tp, ti, m, so, flags) { \ ! 96: if ((ti)->ti_seq == (tp)->rcv_nxt && \ ! 97: (tp)->seg_next == (tcpiphdrp_32)(tp) && \ ! 98: (tp)->t_state == TCPS_ESTABLISHED) { \ ! 99: tp->t_flags |= TF_DELACK; \ ! 100: (tp)->rcv_nxt += (ti)->ti_len; \ ! 101: flags = (ti)->ti_flags & TH_FIN; \ ! 102: tcpstat.tcps_rcvpack++;\ ! 103: tcpstat.tcps_rcvbyte += (ti)->ti_len;\ ! 104: if (so->so_emu) { \ ! 105: if (tcp_emu((so),(m))) sbappend(so, (m)); \ ! 106: } else \ ! 107: sbappend((so), (m)); \ ! 108: /* sorwakeup(so); */ \ ! 109: } else { \ ! 110: (flags) = tcp_reass((tp), (ti), (m)); \ ! 111: tp->t_flags |= TF_ACKNOW; \ ! 112: } \ ! 113: } ! 114: #endif ! 115: ! 116: int ! 117: tcp_reass(tp, ti, m) ! 118: register struct tcpcb *tp; ! 119: register struct tcpiphdr *ti; ! 120: struct mbuf *m; ! 121: { ! 122: register struct tcpiphdr *q; ! 123: struct socket *so = tp->t_socket; ! 124: int flags; ! 125: ! 126: /* ! 127: * Call with ti==0 after become established to ! 128: * force pre-ESTABLISHED data up to user socket. ! 129: */ ! 130: if (ti == 0) ! 131: goto present; ! 132: ! 133: /* ! 134: * Find a segment which begins after this one does. ! 135: */ ! 136: for (q = (struct tcpiphdr *)tp->seg_next; q != (struct tcpiphdr *)tp; ! 137: q = (struct tcpiphdr *)q->ti_next) ! 138: if (SEQ_GT(q->ti_seq, ti->ti_seq)) ! 139: break; ! 140: ! 141: /* ! 142: * If there is a preceding segment, it may provide some of ! 143: * our data already. If so, drop the data from the incoming ! 144: * segment. If it provides all of our data, drop us. ! 145: */ ! 146: if ((struct tcpiphdr *)q->ti_prev != (struct tcpiphdr *)tp) { ! 147: register int i; ! 148: q = (struct tcpiphdr *)q->ti_prev; ! 149: /* conversion to int (in i) handles seq wraparound */ ! 150: i = q->ti_seq + q->ti_len - ti->ti_seq; ! 151: if (i > 0) { ! 152: if (i >= ti->ti_len) { ! 153: tcpstat.tcps_rcvduppack++; ! 154: tcpstat.tcps_rcvdupbyte += ti->ti_len; ! 155: m_freem(m); ! 156: /* ! 157: * Try to present any queued data ! 158: * at the left window edge to the user. ! 159: * This is needed after the 3-WHS ! 160: * completes. ! 161: */ ! 162: goto present; /* ??? */ ! 163: } ! 164: m_adj(m, i); ! 165: ti->ti_len -= i; ! 166: ti->ti_seq += i; ! 167: } ! 168: q = (struct tcpiphdr *)(q->ti_next); ! 169: } ! 170: tcpstat.tcps_rcvoopack++; ! 171: tcpstat.tcps_rcvoobyte += ti->ti_len; ! 172: REASS_MBUF(ti) = (mbufp_32) m; /* XXX */ ! 173: ! 174: /* ! 175: * While we overlap succeeding segments trim them or, ! 176: * if they are completely covered, dequeue them. ! 177: */ ! 178: while (q != (struct tcpiphdr *)tp) { ! 179: register int i = (ti->ti_seq + ti->ti_len) - q->ti_seq; ! 180: if (i <= 0) ! 181: break; ! 182: if (i < q->ti_len) { ! 183: q->ti_seq += i; ! 184: q->ti_len -= i; ! 185: m_adj((struct mbuf *) REASS_MBUF(q), i); ! 186: break; ! 187: } ! 188: q = (struct tcpiphdr *)q->ti_next; ! 189: m = (struct mbuf *) REASS_MBUF((struct tcpiphdr *)q->ti_prev); ! 190: remque_32((void *)(q->ti_prev)); ! 191: m_freem(m); ! 192: } ! 193: ! 194: /* ! 195: * Stick new segment in its place. ! 196: */ ! 197: insque_32(ti, (void *)(q->ti_prev)); ! 198: ! 199: present: ! 200: /* ! 201: * Present data to user, advancing rcv_nxt through ! 202: * completed sequence space. ! 203: */ ! 204: if (!TCPS_HAVEESTABLISHED(tp->t_state)) ! 205: return (0); ! 206: ti = (struct tcpiphdr *) tp->seg_next; ! 207: if (ti == (struct tcpiphdr *)tp || ti->ti_seq != tp->rcv_nxt) ! 208: return (0); ! 209: if (tp->t_state == TCPS_SYN_RECEIVED && ti->ti_len) ! 210: return (0); ! 211: do { ! 212: tp->rcv_nxt += ti->ti_len; ! 213: flags = ti->ti_flags & TH_FIN; ! 214: remque_32(ti); ! 215: m = (struct mbuf *) REASS_MBUF(ti); /* XXX */ ! 216: ti = (struct tcpiphdr *)ti->ti_next; ! 217: /* if (so->so_state & SS_FCANTRCVMORE) */ ! 218: if (so->so_state & SS_FCANTSENDMORE) ! 219: m_freem(m); ! 220: else { ! 221: if (so->so_emu) { ! 222: if (tcp_emu(so,m)) sbappend(so, m); ! 223: } else ! 224: sbappend(so, m); ! 225: } ! 226: } while (ti != (struct tcpiphdr *)tp && ti->ti_seq == tp->rcv_nxt); ! 227: /* sorwakeup(so); */ ! 228: return (flags); ! 229: } ! 230: ! 231: /* ! 232: * TCP input routine, follows pages 65-76 of the ! 233: * protocol specification dated September, 1981 very closely. ! 234: */ ! 235: void ! 236: tcp_input(m, iphlen, inso) ! 237: register struct mbuf *m; ! 238: int iphlen; ! 239: struct socket *inso; ! 240: { ! 241: struct ip save_ip, *ip; ! 242: register struct tcpiphdr *ti; ! 243: caddr_t optp = NULL; ! 244: int optlen = 0; ! 245: int len, tlen, off; ! 246: register struct tcpcb *tp = 0; ! 247: register int tiflags; ! 248: struct socket *so = 0; ! 249: int todrop, acked, ourfinisacked, needoutput = 0; ! 250: /* int dropsocket = 0; */ ! 251: int iss = 0; ! 252: u_long tiwin; ! 253: int ret; ! 254: /* int ts_present = 0; */ ! 255: ! 256: DEBUG_CALL("tcp_input"); ! 257: DEBUG_ARGS((dfd," m = %8lx iphlen = %2d inso = %lx\n", ! 258: (long )m, iphlen, (long )inso )); ! 259: ! 260: /* ! 261: * If called with m == 0, then we're continuing the connect ! 262: */ ! 263: if (m == NULL) { ! 264: so = inso; ! 265: ! 266: /* Re-set a few variables */ ! 267: tp = sototcpcb(so); ! 268: m = so->so_m; ! 269: so->so_m = 0; ! 270: ti = so->so_ti; ! 271: tiwin = ti->ti_win; ! 272: tiflags = ti->ti_flags; ! 273: ! 274: goto cont_conn; ! 275: } ! 276: ! 277: ! 278: tcpstat.tcps_rcvtotal++; ! 279: /* ! 280: * Get IP and TCP header together in first mbuf. ! 281: * Note: IP leaves IP header in first mbuf. ! 282: */ ! 283: ti = mtod(m, struct tcpiphdr *); ! 284: if (iphlen > sizeof(struct ip )) { ! 285: ip_stripoptions(m, (struct mbuf *)0); ! 286: iphlen=sizeof(struct ip ); ! 287: } ! 288: /* XXX Check if too short */ ! 289: ! 290: ! 291: /* ! 292: * Save a copy of the IP header in case we want restore it ! 293: * for sending an ICMP error message in response. ! 294: */ ! 295: ip=mtod(m, struct ip *); ! 296: save_ip = *ip; ! 297: save_ip.ip_len+= iphlen; ! 298: ! 299: /* ! 300: * Checksum extended TCP header and data. ! 301: */ ! 302: tlen = ((struct ip *)ti)->ip_len; ! 303: ti->ti_next = ti->ti_prev = 0; ! 304: ti->ti_x1 = 0; ! 305: ti->ti_len = htons((u_int16_t)tlen); ! 306: len = sizeof(struct ip ) + tlen; ! 307: /* keep checksum for ICMP reply ! 308: * ti->ti_sum = cksum(m, len); ! 309: * if (ti->ti_sum) { */ ! 310: if(cksum(m, len)) { ! 311: tcpstat.tcps_rcvbadsum++; ! 312: goto drop; ! 313: } ! 314: ! 315: /* ! 316: * Check that TCP offset makes sense, ! 317: * pull out TCP options and adjust length. XXX ! 318: */ ! 319: off = ti->ti_off << 2; ! 320: if (off < sizeof (struct tcphdr) || off > tlen) { ! 321: tcpstat.tcps_rcvbadoff++; ! 322: goto drop; ! 323: } ! 324: tlen -= off; ! 325: ti->ti_len = tlen; ! 326: if (off > sizeof (struct tcphdr)) { ! 327: optlen = off - sizeof (struct tcphdr); ! 328: optp = mtod(m, caddr_t) + sizeof (struct tcpiphdr); ! 329: ! 330: /* ! 331: * Do quick retrieval of timestamp options ("options ! 332: * prediction?"). If timestamp is the only option and it's ! 333: * formatted as recommended in RFC 1323 appendix A, we ! 334: * quickly get the values now and not bother calling ! 335: * tcp_dooptions(), etc. ! 336: */ ! 337: /* if ((optlen == TCPOLEN_TSTAMP_APPA || ! 338: * (optlen > TCPOLEN_TSTAMP_APPA && ! 339: * optp[TCPOLEN_TSTAMP_APPA] == TCPOPT_EOL)) && ! 340: * *(u_int32_t *)optp == htonl(TCPOPT_TSTAMP_HDR) && ! 341: * (ti->ti_flags & TH_SYN) == 0) { ! 342: * ts_present = 1; ! 343: * ts_val = ntohl(*(u_int32_t *)(optp + 4)); ! 344: * ts_ecr = ntohl(*(u_int32_t *)(optp + 8)); ! 345: * optp = NULL; / * we've parsed the options * / ! 346: * } ! 347: */ ! 348: } ! 349: tiflags = ti->ti_flags; ! 350: ! 351: /* ! 352: * Convert TCP protocol specific fields to host format. ! 353: */ ! 354: NTOHL(ti->ti_seq); ! 355: NTOHL(ti->ti_ack); ! 356: NTOHS(ti->ti_win); ! 357: NTOHS(ti->ti_urp); ! 358: ! 359: /* ! 360: * Drop TCP, IP headers and TCP options. ! 361: */ ! 362: m->m_data += sizeof(struct tcpiphdr)+off-sizeof(struct tcphdr); ! 363: m->m_len -= sizeof(struct tcpiphdr)+off-sizeof(struct tcphdr); ! 364: ! 365: /* ! 366: * Locate pcb for segment. ! 367: */ ! 368: findso: ! 369: so = tcp_last_so; ! 370: if (so->so_fport != ti->ti_dport || ! 371: so->so_lport != ti->ti_sport || ! 372: so->so_laddr.s_addr != ti->ti_src.s_addr || ! 373: so->so_faddr.s_addr != ti->ti_dst.s_addr) { ! 374: so = solookup(&tcb, ti->ti_src, ti->ti_sport, ! 375: ti->ti_dst, ti->ti_dport); ! 376: if (so) ! 377: tcp_last_so = so; ! 378: ++tcpstat.tcps_socachemiss; ! 379: } ! 380: ! 381: /* ! 382: * If the state is CLOSED (i.e., TCB does not exist) then ! 383: * all data in the incoming segment is discarded. ! 384: * If the TCB exists but is in CLOSED state, it is embryonic, ! 385: * but should either do a listen or a connect soon. ! 386: * ! 387: * state == CLOSED means we've done socreate() but haven't ! 388: * attached it to a protocol yet... ! 389: * ! 390: * XXX If a TCB does not exist, and the TH_SYN flag is ! 391: * the only flag set, then create a session, mark it ! 392: * as if it was LISTENING, and continue... ! 393: */ ! 394: if (so == 0) { ! 395: if ((tiflags & (TH_SYN|TH_FIN|TH_RST|TH_URG|TH_ACK)) != TH_SYN) ! 396: goto dropwithreset; ! 397: ! 398: if ((so = socreate()) == NULL) ! 399: goto dropwithreset; ! 400: if (tcp_attach(so) < 0) { ! 401: free(so); /* Not sofree (if it failed, it's not insqued) */ ! 402: goto dropwithreset; ! 403: } ! 404: ! 405: sbreserve(&so->so_snd, tcp_sndspace); ! 406: sbreserve(&so->so_rcv, tcp_rcvspace); ! 407: ! 408: /* tcp_last_so = so; */ /* XXX ? */ ! 409: /* tp = sototcpcb(so); */ ! 410: ! 411: so->so_laddr = ti->ti_src; ! 412: so->so_lport = ti->ti_sport; ! 413: so->so_faddr = ti->ti_dst; ! 414: so->so_fport = ti->ti_dport; ! 415: ! 416: if ((so->so_iptos = tcp_tos(so)) == 0) ! 417: so->so_iptos = ((struct ip *)ti)->ip_tos; ! 418: ! 419: tp = sototcpcb(so); ! 420: tp->t_state = TCPS_LISTEN; ! 421: } ! 422: ! 423: /* ! 424: * If this is a still-connecting socket, this probably ! 425: * a retransmit of the SYN. Whether it's a retransmit SYN ! 426: * or something else, we nuke it. ! 427: */ ! 428: if (so->so_state & SS_ISFCONNECTING) ! 429: goto drop; ! 430: ! 431: tp = sototcpcb(so); ! 432: ! 433: /* XXX Should never fail */ ! 434: if (tp == 0) ! 435: goto dropwithreset; ! 436: if (tp->t_state == TCPS_CLOSED) ! 437: goto drop; ! 438: ! 439: /* Unscale the window into a 32-bit value. */ ! 440: /* if ((tiflags & TH_SYN) == 0) ! 441: * tiwin = ti->ti_win << tp->snd_scale; ! 442: * else ! 443: */ ! 444: tiwin = ti->ti_win; ! 445: ! 446: /* ! 447: * Segment received on connection. ! 448: * Reset idle time and keep-alive timer. ! 449: */ ! 450: tp->t_idle = 0; ! 451: if (so_options) ! 452: tp->t_timer[TCPT_KEEP] = tcp_keepintvl; ! 453: else ! 454: tp->t_timer[TCPT_KEEP] = tcp_keepidle; ! 455: ! 456: /* ! 457: * Process options if not in LISTEN state, ! 458: * else do it below (after getting remote address). ! 459: */ ! 460: if (optp && tp->t_state != TCPS_LISTEN) ! 461: tcp_dooptions(tp, (u_char *)optp, optlen, ti); ! 462: /* , */ ! 463: /* &ts_present, &ts_val, &ts_ecr); */ ! 464: ! 465: /* ! 466: * Header prediction: check for the two common cases ! 467: * of a uni-directional data xfer. If the packet has ! 468: * no control flags, is in-sequence, the window didn't ! 469: * change and we're not retransmitting, it's a ! 470: * candidate. If the length is zero and the ack moved ! 471: * forward, we're the sender side of the xfer. Just ! 472: * free the data acked & wake any higher level process ! 473: * that was blocked waiting for space. If the length ! 474: * is non-zero and the ack didn't move, we're the ! 475: * receiver side. If we're getting packets in-order ! 476: * (the reassembly queue is empty), add the data to ! 477: * the socket buffer and note that we need a delayed ack. ! 478: * ! 479: * XXX Some of these tests are not needed ! 480: * eg: the tiwin == tp->snd_wnd prevents many more ! 481: * predictions.. with no *real* advantage.. ! 482: */ ! 483: if (tp->t_state == TCPS_ESTABLISHED && ! 484: (tiflags & (TH_SYN|TH_FIN|TH_RST|TH_URG|TH_ACK)) == TH_ACK && ! 485: /* (!ts_present || TSTMP_GEQ(ts_val, tp->ts_recent)) && */ ! 486: ti->ti_seq == tp->rcv_nxt && ! 487: tiwin && tiwin == tp->snd_wnd && ! 488: tp->snd_nxt == tp->snd_max) { ! 489: /* ! 490: * If last ACK falls within this segment's sequence numbers, ! 491: * record the timestamp. ! 492: */ ! 493: /* if (ts_present && SEQ_LEQ(ti->ti_seq, tp->last_ack_sent) && ! 494: * SEQ_LT(tp->last_ack_sent, ti->ti_seq + ti->ti_len)) { ! 495: * tp->ts_recent_age = tcp_now; ! 496: * tp->ts_recent = ts_val; ! 497: * } ! 498: */ ! 499: if (ti->ti_len == 0) { ! 500: if (SEQ_GT(ti->ti_ack, tp->snd_una) && ! 501: SEQ_LEQ(ti->ti_ack, tp->snd_max) && ! 502: tp->snd_cwnd >= tp->snd_wnd) { ! 503: /* ! 504: * this is a pure ack for outstanding data. ! 505: */ ! 506: ++tcpstat.tcps_predack; ! 507: /* if (ts_present) ! 508: * tcp_xmit_timer(tp, tcp_now-ts_ecr+1); ! 509: * else ! 510: */ if (tp->t_rtt && ! 511: SEQ_GT(ti->ti_ack, tp->t_rtseq)) ! 512: tcp_xmit_timer(tp, tp->t_rtt); ! 513: acked = ti->ti_ack - tp->snd_una; ! 514: tcpstat.tcps_rcvackpack++; ! 515: tcpstat.tcps_rcvackbyte += acked; ! 516: sbdrop(&so->so_snd, acked); ! 517: tp->snd_una = ti->ti_ack; ! 518: m_freem(m); ! 519: ! 520: /* ! 521: * If all outstanding data are acked, stop ! 522: * retransmit timer, otherwise restart timer ! 523: * using current (possibly backed-off) value. ! 524: * If process is waiting for space, ! 525: * wakeup/selwakeup/signal. If data ! 526: * are ready to send, let tcp_output ! 527: * decide between more output or persist. ! 528: */ ! 529: if (tp->snd_una == tp->snd_max) ! 530: tp->t_timer[TCPT_REXMT] = 0; ! 531: else if (tp->t_timer[TCPT_PERSIST] == 0) ! 532: tp->t_timer[TCPT_REXMT] = tp->t_rxtcur; ! 533: ! 534: /* ! 535: * There's room in so_snd, sowwakup will read() ! 536: * from the socket if we can ! 537: */ ! 538: /* if (so->so_snd.sb_flags & SB_NOTIFY) ! 539: * sowwakeup(so); ! 540: */ ! 541: /* ! 542: * This is called because sowwakeup might have ! 543: * put data into so_snd. Since we don't so sowwakeup, ! 544: * we don't need this.. XXX??? ! 545: */ ! 546: if (so->so_snd.sb_cc) ! 547: (void) tcp_output(tp); ! 548: ! 549: return; ! 550: } ! 551: } else if (ti->ti_ack == tp->snd_una && ! 552: tp->seg_next == (tcpiphdrp_32)tp && ! 553: ti->ti_len <= sbspace(&so->so_rcv)) { ! 554: /* ! 555: * this is a pure, in-sequence data packet ! 556: * with nothing on the reassembly queue and ! 557: * we have enough buffer space to take it. ! 558: */ ! 559: ++tcpstat.tcps_preddat; ! 560: tp->rcv_nxt += ti->ti_len; ! 561: tcpstat.tcps_rcvpack++; ! 562: tcpstat.tcps_rcvbyte += ti->ti_len; ! 563: /* ! 564: * Add data to socket buffer. ! 565: */ ! 566: if (so->so_emu) { ! 567: if (tcp_emu(so,m)) sbappend(so, m); ! 568: } else ! 569: sbappend(so, m); ! 570: ! 571: /* ! 572: * XXX This is called when data arrives. Later, check ! 573: * if we can actually write() to the socket ! 574: * XXX Need to check? It's be NON_BLOCKING ! 575: */ ! 576: /* sorwakeup(so); */ ! 577: ! 578: /* ! 579: * If this is a short packet, then ACK now - with Nagel ! 580: * congestion avoidance sender won't send more until ! 581: * he gets an ACK. ! 582: * ! 583: * Here are 3 interpretations of what should happen. ! 584: * The best (for me) is to delay-ack everything except ! 585: * if it's a one-byte packet containing an ESC ! 586: * (this means it's an arrow key (or similar) sent using ! 587: * Nagel, hence there will be no echo) ! 588: * The first of these is the original, the second is the ! 589: * middle ground between the other 2 ! 590: */ ! 591: /* if (((unsigned)ti->ti_len < tp->t_maxseg)) { ! 592: */ ! 593: /* if (((unsigned)ti->ti_len < tp->t_maxseg && ! 594: * (so->so_iptos & IPTOS_LOWDELAY) == 0) || ! 595: * ((so->so_iptos & IPTOS_LOWDELAY) && ! 596: * ((struct tcpiphdr_2 *)ti)->first_char == (char)27)) { ! 597: */ ! 598: if ((unsigned)ti->ti_len == 1 && ! 599: ((struct tcpiphdr_2 *)ti)->first_char == (char)27) { ! 600: tp->t_flags |= TF_ACKNOW; ! 601: tcp_output(tp); ! 602: } else { ! 603: tp->t_flags |= TF_DELACK; ! 604: } ! 605: return; ! 606: } ! 607: } /* header prediction */ ! 608: /* ! 609: * Calculate amount of space in receive window, ! 610: * and then do TCP input processing. ! 611: * Receive window is amount of space in rcv queue, ! 612: * but not less than advertised window. ! 613: */ ! 614: { int win; ! 615: win = sbspace(&so->so_rcv); ! 616: if (win < 0) ! 617: win = 0; ! 618: tp->rcv_wnd = max(win, (int)(tp->rcv_adv - tp->rcv_nxt)); ! 619: } ! 620: ! 621: switch (tp->t_state) { ! 622: ! 623: /* ! 624: * If the state is LISTEN then ignore segment if it contains an RST. ! 625: * If the segment contains an ACK then it is bad and send a RST. ! 626: * If it does not contain a SYN then it is not interesting; drop it. ! 627: * Don't bother responding if the destination was a broadcast. ! 628: * Otherwise initialize tp->rcv_nxt, and tp->irs, select an initial ! 629: * tp->iss, and send a segment: ! 630: * <SEQ=ISS><ACK=RCV_NXT><CTL=SYN,ACK> ! 631: * Also initialize tp->snd_nxt to tp->iss+1 and tp->snd_una to tp->iss. ! 632: * Fill in remote peer address fields if not previously specified. ! 633: * Enter SYN_RECEIVED state, and process any other fields of this ! 634: * segment in this state. ! 635: */ ! 636: case TCPS_LISTEN: { ! 637: ! 638: if (tiflags & TH_RST) ! 639: goto drop; ! 640: if (tiflags & TH_ACK) ! 641: goto dropwithreset; ! 642: if ((tiflags & TH_SYN) == 0) ! 643: goto drop; ! 644: ! 645: /* ! 646: * This has way too many gotos... ! 647: * But a bit of spaghetti code never hurt anybody :) ! 648: */ ! 649: ! 650: /* ! 651: * If this is destined for the control address, then flag to ! 652: * tcp_ctl once connected, otherwise connect ! 653: */ ! 654: if ((so->so_faddr.s_addr&htonl(0xffffff00)) == special_addr.s_addr) { ! 655: int lastbyte=ntohl(so->so_faddr.s_addr) & 0xff; ! 656: if (lastbyte!=CTL_ALIAS && lastbyte!=CTL_DNS) { ! 657: #if 0 ! 658: if(lastbyte==CTL_CMD || lastbyte==CTL_EXEC) { ! 659: /* Command or exec adress */ ! 660: so->so_state |= SS_CTL; ! 661: } else ! 662: #endif ! 663: { ! 664: /* May be an add exec */ ! 665: struct ex_list *ex_ptr; ! 666: for(ex_ptr = exec_list; ex_ptr; ex_ptr = ex_ptr->ex_next) { ! 667: if(ex_ptr->ex_fport == so->so_fport && ! 668: lastbyte == ex_ptr->ex_addr) { ! 669: so->so_state |= SS_CTL; ! 670: break; ! 671: } ! 672: } ! 673: } ! 674: if(so->so_state & SS_CTL) goto cont_input; ! 675: } ! 676: /* CTL_ALIAS: Do nothing, tcp_fconnect will be called on it */ ! 677: } ! 678: ! 679: if (so->so_emu & EMU_NOCONNECT) { ! 680: so->so_emu &= ~EMU_NOCONNECT; ! 681: goto cont_input; ! 682: } ! 683: ! 684: if((tcp_fconnect(so) == -1) && (errno != EINPROGRESS) && (errno != EWOULDBLOCK)) { ! 685: u_char code=ICMP_UNREACH_NET; ! 686: DEBUG_MISC((dfd," tcp fconnect errno = %d-%s\n", ! 687: errno,strerror(errno))); ! 688: if(errno == ECONNREFUSED) { ! 689: /* ACK the SYN, send RST to refuse the connection */ ! 690: tcp_respond(tp, ti, m, ti->ti_seq+1, (tcp_seq)0, ! 691: TH_RST|TH_ACK); ! 692: } else { ! 693: if(errno == EHOSTUNREACH) code=ICMP_UNREACH_HOST; ! 694: HTONL(ti->ti_seq); /* restore tcp header */ ! 695: HTONL(ti->ti_ack); ! 696: HTONS(ti->ti_win); ! 697: HTONS(ti->ti_urp); ! 698: m->m_data -= sizeof(struct tcpiphdr)+off-sizeof(struct tcphdr); ! 699: m->m_len += sizeof(struct tcpiphdr)+off-sizeof(struct tcphdr); ! 700: *ip=save_ip; ! 701: icmp_error(m, ICMP_UNREACH,code, 0,strerror(errno)); ! 702: } ! 703: tp = tcp_close(tp); ! 704: m_free(m); ! 705: } else { ! 706: /* ! 707: * Haven't connected yet, save the current mbuf ! 708: * and ti, and return ! 709: * XXX Some OS's don't tell us whether the connect() ! 710: * succeeded or not. So we must time it out. ! 711: */ ! 712: so->so_m = m; ! 713: so->so_ti = ti; ! 714: tp->t_timer[TCPT_KEEP] = TCPTV_KEEP_INIT; ! 715: tp->t_state = TCPS_SYN_RECEIVED; ! 716: } ! 717: return; ! 718: ! 719: cont_conn: ! 720: /* m==NULL ! 721: * Check if the connect succeeded ! 722: */ ! 723: if (so->so_state & SS_NOFDREF) { ! 724: tp = tcp_close(tp); ! 725: goto dropwithreset; ! 726: } ! 727: cont_input: ! 728: tcp_template(tp); ! 729: ! 730: if (optp) ! 731: tcp_dooptions(tp, (u_char *)optp, optlen, ti); ! 732: /* , */ ! 733: /* &ts_present, &ts_val, &ts_ecr); */ ! 734: ! 735: if (iss) ! 736: tp->iss = iss; ! 737: else ! 738: tp->iss = tcp_iss; ! 739: tcp_iss += TCP_ISSINCR/2; ! 740: tp->irs = ti->ti_seq; ! 741: tcp_sendseqinit(tp); ! 742: tcp_rcvseqinit(tp); ! 743: tp->t_flags |= TF_ACKNOW; ! 744: tp->t_state = TCPS_SYN_RECEIVED; ! 745: tp->t_timer[TCPT_KEEP] = TCPTV_KEEP_INIT; ! 746: tcpstat.tcps_accepts++; ! 747: goto trimthenstep6; ! 748: } /* case TCPS_LISTEN */ ! 749: ! 750: /* ! 751: * If the state is SYN_SENT: ! 752: * if seg contains an ACK, but not for our SYN, drop the input. ! 753: * if seg contains a RST, then drop the connection. ! 754: * if seg does not contain SYN, then drop it. ! 755: * Otherwise this is an acceptable SYN segment ! 756: * initialize tp->rcv_nxt and tp->irs ! 757: * if seg contains ack then advance tp->snd_una ! 758: * if SYN has been acked change to ESTABLISHED else SYN_RCVD state ! 759: * arrange for segment to be acked (eventually) ! 760: * continue processing rest of data/controls, beginning with URG ! 761: */ ! 762: case TCPS_SYN_SENT: ! 763: if ((tiflags & TH_ACK) && ! 764: (SEQ_LEQ(ti->ti_ack, tp->iss) || ! 765: SEQ_GT(ti->ti_ack, tp->snd_max))) ! 766: goto dropwithreset; ! 767: ! 768: if (tiflags & TH_RST) { ! 769: if (tiflags & TH_ACK) ! 770: tp = tcp_drop(tp,0); /* XXX Check t_softerror! */ ! 771: goto drop; ! 772: } ! 773: ! 774: if ((tiflags & TH_SYN) == 0) ! 775: goto drop; ! 776: if (tiflags & TH_ACK) { ! 777: tp->snd_una = ti->ti_ack; ! 778: if (SEQ_LT(tp->snd_nxt, tp->snd_una)) ! 779: tp->snd_nxt = tp->snd_una; ! 780: } ! 781: ! 782: tp->t_timer[TCPT_REXMT] = 0; ! 783: tp->irs = ti->ti_seq; ! 784: tcp_rcvseqinit(tp); ! 785: tp->t_flags |= TF_ACKNOW; ! 786: if (tiflags & TH_ACK && SEQ_GT(tp->snd_una, tp->iss)) { ! 787: tcpstat.tcps_connects++; ! 788: soisfconnected(so); ! 789: tp->t_state = TCPS_ESTABLISHED; ! 790: ! 791: /* Do window scaling on this connection? */ ! 792: /* if ((tp->t_flags & (TF_RCVD_SCALE|TF_REQ_SCALE)) == ! 793: * (TF_RCVD_SCALE|TF_REQ_SCALE)) { ! 794: * tp->snd_scale = tp->requested_s_scale; ! 795: * tp->rcv_scale = tp->request_r_scale; ! 796: * } ! 797: */ ! 798: (void) tcp_reass(tp, (struct tcpiphdr *)0, ! 799: (struct mbuf *)0); ! 800: /* ! 801: * if we didn't have to retransmit the SYN, ! 802: * use its rtt as our initial srtt & rtt var. ! 803: */ ! 804: if (tp->t_rtt) ! 805: tcp_xmit_timer(tp, tp->t_rtt); ! 806: } else ! 807: tp->t_state = TCPS_SYN_RECEIVED; ! 808: ! 809: trimthenstep6: ! 810: /* ! 811: * Advance ti->ti_seq to correspond to first data byte. ! 812: * If data, trim to stay within window, ! 813: * dropping FIN if necessary. ! 814: */ ! 815: ti->ti_seq++; ! 816: if (ti->ti_len > tp->rcv_wnd) { ! 817: todrop = ti->ti_len - tp->rcv_wnd; ! 818: m_adj(m, -todrop); ! 819: ti->ti_len = tp->rcv_wnd; ! 820: tiflags &= ~TH_FIN; ! 821: tcpstat.tcps_rcvpackafterwin++; ! 822: tcpstat.tcps_rcvbyteafterwin += todrop; ! 823: } ! 824: tp->snd_wl1 = ti->ti_seq - 1; ! 825: tp->rcv_up = ti->ti_seq; ! 826: goto step6; ! 827: } /* switch tp->t_state */ ! 828: /* ! 829: * States other than LISTEN or SYN_SENT. ! 830: * First check timestamp, if present. ! 831: * Then check that at least some bytes of segment are within ! 832: * receive window. If segment begins before rcv_nxt, ! 833: * drop leading data (and SYN); if nothing left, just ack. ! 834: * ! 835: * RFC 1323 PAWS: If we have a timestamp reply on this segment ! 836: * and it's less than ts_recent, drop it. ! 837: */ ! 838: /* if (ts_present && (tiflags & TH_RST) == 0 && tp->ts_recent && ! 839: * TSTMP_LT(ts_val, tp->ts_recent)) { ! 840: * ! 841: */ /* Check to see if ts_recent is over 24 days old. */ ! 842: /* if ((int)(tcp_now - tp->ts_recent_age) > TCP_PAWS_IDLE) { ! 843: */ /* ! 844: * * Invalidate ts_recent. If this segment updates ! 845: * * ts_recent, the age will be reset later and ts_recent ! 846: * * will get a valid value. If it does not, setting ! 847: * * ts_recent to zero will at least satisfy the ! 848: * * requirement that zero be placed in the timestamp ! 849: * * echo reply when ts_recent isn't valid. The ! 850: * * age isn't reset until we get a valid ts_recent ! 851: * * because we don't want out-of-order segments to be ! 852: * * dropped when ts_recent is old. ! 853: * */ ! 854: /* tp->ts_recent = 0; ! 855: * } else { ! 856: * tcpstat.tcps_rcvduppack++; ! 857: * tcpstat.tcps_rcvdupbyte += ti->ti_len; ! 858: * tcpstat.tcps_pawsdrop++; ! 859: * goto dropafterack; ! 860: * } ! 861: * } ! 862: */ ! 863: ! 864: todrop = tp->rcv_nxt - ti->ti_seq; ! 865: if (todrop > 0) { ! 866: if (tiflags & TH_SYN) { ! 867: tiflags &= ~TH_SYN; ! 868: ti->ti_seq++; ! 869: if (ti->ti_urp > 1) ! 870: ti->ti_urp--; ! 871: else ! 872: tiflags &= ~TH_URG; ! 873: todrop--; ! 874: } ! 875: /* ! 876: * Following if statement from Stevens, vol. 2, p. 960. ! 877: */ ! 878: if (todrop > ti->ti_len ! 879: || (todrop == ti->ti_len && (tiflags & TH_FIN) == 0)) { ! 880: /* ! 881: * Any valid FIN must be to the left of the window. ! 882: * At this point the FIN must be a duplicate or out ! 883: * of sequence; drop it. ! 884: */ ! 885: tiflags &= ~TH_FIN; ! 886: ! 887: /* ! 888: * Send an ACK to resynchronize and drop any data. ! 889: * But keep on processing for RST or ACK. ! 890: */ ! 891: tp->t_flags |= TF_ACKNOW; ! 892: todrop = ti->ti_len; ! 893: tcpstat.tcps_rcvduppack++; ! 894: tcpstat.tcps_rcvdupbyte += todrop; ! 895: } else { ! 896: tcpstat.tcps_rcvpartduppack++; ! 897: tcpstat.tcps_rcvpartdupbyte += todrop; ! 898: } ! 899: m_adj(m, todrop); ! 900: ti->ti_seq += todrop; ! 901: ti->ti_len -= todrop; ! 902: if (ti->ti_urp > todrop) ! 903: ti->ti_urp -= todrop; ! 904: else { ! 905: tiflags &= ~TH_URG; ! 906: ti->ti_urp = 0; ! 907: } ! 908: } ! 909: /* ! 910: * If new data are received on a connection after the ! 911: * user processes are gone, then RST the other end. ! 912: */ ! 913: if ((so->so_state & SS_NOFDREF) && ! 914: tp->t_state > TCPS_CLOSE_WAIT && ti->ti_len) { ! 915: tp = tcp_close(tp); ! 916: tcpstat.tcps_rcvafterclose++; ! 917: goto dropwithreset; ! 918: } ! 919: ! 920: /* ! 921: * If segment ends after window, drop trailing data ! 922: * (and PUSH and FIN); if nothing left, just ACK. ! 923: */ ! 924: todrop = (ti->ti_seq+ti->ti_len) - (tp->rcv_nxt+tp->rcv_wnd); ! 925: if (todrop > 0) { ! 926: tcpstat.tcps_rcvpackafterwin++; ! 927: if (todrop >= ti->ti_len) { ! 928: tcpstat.tcps_rcvbyteafterwin += ti->ti_len; ! 929: /* ! 930: * If a new connection request is received ! 931: * while in TIME_WAIT, drop the old connection ! 932: * and start over if the sequence numbers ! 933: * are above the previous ones. ! 934: */ ! 935: if (tiflags & TH_SYN && ! 936: tp->t_state == TCPS_TIME_WAIT && ! 937: SEQ_GT(ti->ti_seq, tp->rcv_nxt)) { ! 938: iss = tp->rcv_nxt + TCP_ISSINCR; ! 939: tp = tcp_close(tp); ! 940: goto findso; ! 941: } ! 942: /* ! 943: * If window is closed can only take segments at ! 944: * window edge, and have to drop data and PUSH from ! 945: * incoming segments. Continue processing, but ! 946: * remember to ack. Otherwise, drop segment ! 947: * and ack. ! 948: */ ! 949: if (tp->rcv_wnd == 0 && ti->ti_seq == tp->rcv_nxt) { ! 950: tp->t_flags |= TF_ACKNOW; ! 951: tcpstat.tcps_rcvwinprobe++; ! 952: } else ! 953: goto dropafterack; ! 954: } else ! 955: tcpstat.tcps_rcvbyteafterwin += todrop; ! 956: m_adj(m, -todrop); ! 957: ti->ti_len -= todrop; ! 958: tiflags &= ~(TH_PUSH|TH_FIN); ! 959: } ! 960: ! 961: /* ! 962: * If last ACK falls within this segment's sequence numbers, ! 963: * record its timestamp. ! 964: */ ! 965: /* if (ts_present && SEQ_LEQ(ti->ti_seq, tp->last_ack_sent) && ! 966: * SEQ_LT(tp->last_ack_sent, ti->ti_seq + ti->ti_len + ! 967: * ((tiflags & (TH_SYN|TH_FIN)) != 0))) { ! 968: * tp->ts_recent_age = tcp_now; ! 969: * tp->ts_recent = ts_val; ! 970: * } ! 971: */ ! 972: ! 973: /* ! 974: * If the RST bit is set examine the state: ! 975: * SYN_RECEIVED STATE: ! 976: * If passive open, return to LISTEN state. ! 977: * If active open, inform user that connection was refused. ! 978: * ESTABLISHED, FIN_WAIT_1, FIN_WAIT2, CLOSE_WAIT STATES: ! 979: * Inform user that connection was reset, and close tcb. ! 980: * CLOSING, LAST_ACK, TIME_WAIT STATES ! 981: * Close the tcb. ! 982: */ ! 983: if (tiflags&TH_RST) switch (tp->t_state) { ! 984: ! 985: case TCPS_SYN_RECEIVED: ! 986: /* so->so_error = ECONNREFUSED; */ ! 987: goto close; ! 988: ! 989: case TCPS_ESTABLISHED: ! 990: case TCPS_FIN_WAIT_1: ! 991: case TCPS_FIN_WAIT_2: ! 992: case TCPS_CLOSE_WAIT: ! 993: /* so->so_error = ECONNRESET; */ ! 994: close: ! 995: tp->t_state = TCPS_CLOSED; ! 996: tcpstat.tcps_drops++; ! 997: tp = tcp_close(tp); ! 998: goto drop; ! 999: ! 1000: case TCPS_CLOSING: ! 1001: case TCPS_LAST_ACK: ! 1002: case TCPS_TIME_WAIT: ! 1003: tp = tcp_close(tp); ! 1004: goto drop; ! 1005: } ! 1006: ! 1007: /* ! 1008: * If a SYN is in the window, then this is an ! 1009: * error and we send an RST and drop the connection. ! 1010: */ ! 1011: if (tiflags & TH_SYN) { ! 1012: tp = tcp_drop(tp,0); ! 1013: goto dropwithreset; ! 1014: } ! 1015: ! 1016: /* ! 1017: * If the ACK bit is off we drop the segment and return. ! 1018: */ ! 1019: if ((tiflags & TH_ACK) == 0) goto drop; ! 1020: ! 1021: /* ! 1022: * Ack processing. ! 1023: */ ! 1024: switch (tp->t_state) { ! 1025: /* ! 1026: * In SYN_RECEIVED state if the ack ACKs our SYN then enter ! 1027: * ESTABLISHED state and continue processing, otherwise ! 1028: * send an RST. una<=ack<=max ! 1029: */ ! 1030: case TCPS_SYN_RECEIVED: ! 1031: ! 1032: if (SEQ_GT(tp->snd_una, ti->ti_ack) || ! 1033: SEQ_GT(ti->ti_ack, tp->snd_max)) ! 1034: goto dropwithreset; ! 1035: tcpstat.tcps_connects++; ! 1036: tp->t_state = TCPS_ESTABLISHED; ! 1037: /* ! 1038: * The sent SYN is ack'ed with our sequence number +1 ! 1039: * The first data byte already in the buffer will get ! 1040: * lost if no correction is made. This is only needed for ! 1041: * SS_CTL since the buffer is empty otherwise. ! 1042: * tp->snd_una++; or: ! 1043: */ ! 1044: tp->snd_una=ti->ti_ack; ! 1045: if (so->so_state & SS_CTL) { ! 1046: /* So tcp_ctl reports the right state */ ! 1047: ret = tcp_ctl(so); ! 1048: if (ret == 1) { ! 1049: soisfconnected(so); ! 1050: so->so_state &= ~SS_CTL; /* success XXX */ ! 1051: } else if (ret == 2) { ! 1052: so->so_state = SS_NOFDREF; /* CTL_CMD */ ! 1053: } else { ! 1054: needoutput = 1; ! 1055: tp->t_state = TCPS_FIN_WAIT_1; ! 1056: } ! 1057: } else { ! 1058: soisfconnected(so); ! 1059: } ! 1060: ! 1061: /* Do window scaling? */ ! 1062: /* if ((tp->t_flags & (TF_RCVD_SCALE|TF_REQ_SCALE)) == ! 1063: * (TF_RCVD_SCALE|TF_REQ_SCALE)) { ! 1064: * tp->snd_scale = tp->requested_s_scale; ! 1065: * tp->rcv_scale = tp->request_r_scale; ! 1066: * } ! 1067: */ ! 1068: (void) tcp_reass(tp, (struct tcpiphdr *)0, (struct mbuf *)0); ! 1069: tp->snd_wl1 = ti->ti_seq - 1; ! 1070: /* Avoid ack processing; snd_una==ti_ack => dup ack */ ! 1071: goto synrx_to_est; ! 1072: /* fall into ... */ ! 1073: ! 1074: /* ! 1075: * In ESTABLISHED state: drop duplicate ACKs; ACK out of range ! 1076: * ACKs. If the ack is in the range ! 1077: * tp->snd_una < ti->ti_ack <= tp->snd_max ! 1078: * then advance tp->snd_una to ti->ti_ack and drop ! 1079: * data from the retransmission queue. If this ACK reflects ! 1080: * more up to date window information we update our window information. ! 1081: */ ! 1082: case TCPS_ESTABLISHED: ! 1083: case TCPS_FIN_WAIT_1: ! 1084: case TCPS_FIN_WAIT_2: ! 1085: case TCPS_CLOSE_WAIT: ! 1086: case TCPS_CLOSING: ! 1087: case TCPS_LAST_ACK: ! 1088: case TCPS_TIME_WAIT: ! 1089: ! 1090: if (SEQ_LEQ(ti->ti_ack, tp->snd_una)) { ! 1091: if (ti->ti_len == 0 && tiwin == tp->snd_wnd) { ! 1092: tcpstat.tcps_rcvdupack++; ! 1093: DEBUG_MISC((dfd," dup ack m = %lx so = %lx \n", ! 1094: (long )m, (long )so)); ! 1095: /* ! 1096: * If we have outstanding data (other than ! 1097: * a window probe), this is a completely ! 1098: * duplicate ack (ie, window info didn't ! 1099: * change), the ack is the biggest we've ! 1100: * seen and we've seen exactly our rexmt ! 1101: * threshold of them, assume a packet ! 1102: * has been dropped and retransmit it. ! 1103: * Kludge snd_nxt & the congestion ! 1104: * window so we send only this one ! 1105: * packet. ! 1106: * ! 1107: * We know we're losing at the current ! 1108: * window size so do congestion avoidance ! 1109: * (set ssthresh to half the current window ! 1110: * and pull our congestion window back to ! 1111: * the new ssthresh). ! 1112: * ! 1113: * Dup acks mean that packets have left the ! 1114: * network (they're now cached at the receiver) ! 1115: * so bump cwnd by the amount in the receiver ! 1116: * to keep a constant cwnd packets in the ! 1117: * network. ! 1118: */ ! 1119: if (tp->t_timer[TCPT_REXMT] == 0 || ! 1120: ti->ti_ack != tp->snd_una) ! 1121: tp->t_dupacks = 0; ! 1122: else if (++tp->t_dupacks == tcprexmtthresh) { ! 1123: tcp_seq onxt = tp->snd_nxt; ! 1124: u_int win = ! 1125: min(tp->snd_wnd, tp->snd_cwnd) / 2 / ! 1126: tp->t_maxseg; ! 1127: ! 1128: if (win < 2) ! 1129: win = 2; ! 1130: tp->snd_ssthresh = win * tp->t_maxseg; ! 1131: tp->t_timer[TCPT_REXMT] = 0; ! 1132: tp->t_rtt = 0; ! 1133: tp->snd_nxt = ti->ti_ack; ! 1134: tp->snd_cwnd = tp->t_maxseg; ! 1135: (void) tcp_output(tp); ! 1136: tp->snd_cwnd = tp->snd_ssthresh + ! 1137: tp->t_maxseg * tp->t_dupacks; ! 1138: if (SEQ_GT(onxt, tp->snd_nxt)) ! 1139: tp->snd_nxt = onxt; ! 1140: goto drop; ! 1141: } else if (tp->t_dupacks > tcprexmtthresh) { ! 1142: tp->snd_cwnd += tp->t_maxseg; ! 1143: (void) tcp_output(tp); ! 1144: goto drop; ! 1145: } ! 1146: } else ! 1147: tp->t_dupacks = 0; ! 1148: break; ! 1149: } ! 1150: synrx_to_est: ! 1151: /* ! 1152: * If the congestion window was inflated to account ! 1153: * for the other side's cached packets, retract it. ! 1154: */ ! 1155: if (tp->t_dupacks > tcprexmtthresh && ! 1156: tp->snd_cwnd > tp->snd_ssthresh) ! 1157: tp->snd_cwnd = tp->snd_ssthresh; ! 1158: tp->t_dupacks = 0; ! 1159: if (SEQ_GT(ti->ti_ack, tp->snd_max)) { ! 1160: tcpstat.tcps_rcvacktoomuch++; ! 1161: goto dropafterack; ! 1162: } ! 1163: acked = ti->ti_ack - tp->snd_una; ! 1164: tcpstat.tcps_rcvackpack++; ! 1165: tcpstat.tcps_rcvackbyte += acked; ! 1166: ! 1167: /* ! 1168: * If we have a timestamp reply, update smoothed ! 1169: * round trip time. If no timestamp is present but ! 1170: * transmit timer is running and timed sequence ! 1171: * number was acked, update smoothed round trip time. ! 1172: * Since we now have an rtt measurement, cancel the ! 1173: * timer backoff (cf., Phil Karn's retransmit alg.). ! 1174: * Recompute the initial retransmit timer. ! 1175: */ ! 1176: /* if (ts_present) ! 1177: * tcp_xmit_timer(tp, tcp_now-ts_ecr+1); ! 1178: * else ! 1179: */ ! 1180: if (tp->t_rtt && SEQ_GT(ti->ti_ack, tp->t_rtseq)) ! 1181: tcp_xmit_timer(tp,tp->t_rtt); ! 1182: ! 1183: /* ! 1184: * If all outstanding data is acked, stop retransmit ! 1185: * timer and remember to restart (more output or persist). ! 1186: * If there is more data to be acked, restart retransmit ! 1187: * timer, using current (possibly backed-off) value. ! 1188: */ ! 1189: if (ti->ti_ack == tp->snd_max) { ! 1190: tp->t_timer[TCPT_REXMT] = 0; ! 1191: needoutput = 1; ! 1192: } else if (tp->t_timer[TCPT_PERSIST] == 0) ! 1193: tp->t_timer[TCPT_REXMT] = tp->t_rxtcur; ! 1194: /* ! 1195: * When new data is acked, open the congestion window. ! 1196: * If the window gives us less than ssthresh packets ! 1197: * in flight, open exponentially (maxseg per packet). ! 1198: * Otherwise open linearly: maxseg per window ! 1199: * (maxseg^2 / cwnd per packet). ! 1200: */ ! 1201: { ! 1202: register u_int cw = tp->snd_cwnd; ! 1203: register u_int incr = tp->t_maxseg; ! 1204: ! 1205: if (cw > tp->snd_ssthresh) ! 1206: incr = incr * incr / cw; ! 1207: tp->snd_cwnd = min(cw + incr, TCP_MAXWIN<<tp->snd_scale); ! 1208: } ! 1209: if (acked > so->so_snd.sb_cc) { ! 1210: tp->snd_wnd -= so->so_snd.sb_cc; ! 1211: sbdrop(&so->so_snd, (int )so->so_snd.sb_cc); ! 1212: ourfinisacked = 1; ! 1213: } else { ! 1214: sbdrop(&so->so_snd, acked); ! 1215: tp->snd_wnd -= acked; ! 1216: ourfinisacked = 0; ! 1217: } ! 1218: /* ! 1219: * XXX sowwakup is called when data is acked and there's room for ! 1220: * for more data... it should read() the socket ! 1221: */ ! 1222: /* if (so->so_snd.sb_flags & SB_NOTIFY) ! 1223: * sowwakeup(so); ! 1224: */ ! 1225: tp->snd_una = ti->ti_ack; ! 1226: if (SEQ_LT(tp->snd_nxt, tp->snd_una)) ! 1227: tp->snd_nxt = tp->snd_una; ! 1228: ! 1229: switch (tp->t_state) { ! 1230: ! 1231: /* ! 1232: * In FIN_WAIT_1 STATE in addition to the processing ! 1233: * for the ESTABLISHED state if our FIN is now acknowledged ! 1234: * then enter FIN_WAIT_2. ! 1235: */ ! 1236: case TCPS_FIN_WAIT_1: ! 1237: if (ourfinisacked) { ! 1238: /* ! 1239: * If we can't receive any more ! 1240: * data, then closing user can proceed. ! 1241: * Starting the timer is contrary to the ! 1242: * specification, but if we don't get a FIN ! 1243: * we'll hang forever. ! 1244: */ ! 1245: if (so->so_state & SS_FCANTRCVMORE) { ! 1246: soisfdisconnected(so); ! 1247: tp->t_timer[TCPT_2MSL] = tcp_maxidle; ! 1248: } ! 1249: tp->t_state = TCPS_FIN_WAIT_2; ! 1250: } ! 1251: break; ! 1252: ! 1253: /* ! 1254: * In CLOSING STATE in addition to the processing for ! 1255: * the ESTABLISHED state if the ACK acknowledges our FIN ! 1256: * then enter the TIME-WAIT state, otherwise ignore ! 1257: * the segment. ! 1258: */ ! 1259: case TCPS_CLOSING: ! 1260: if (ourfinisacked) { ! 1261: tp->t_state = TCPS_TIME_WAIT; ! 1262: tcp_canceltimers(tp); ! 1263: tp->t_timer[TCPT_2MSL] = 2 * TCPTV_MSL; ! 1264: soisfdisconnected(so); ! 1265: } ! 1266: break; ! 1267: ! 1268: /* ! 1269: * In LAST_ACK, we may still be waiting for data to drain ! 1270: * and/or to be acked, as well as for the ack of our FIN. ! 1271: * If our FIN is now acknowledged, delete the TCB, ! 1272: * enter the closed state and return. ! 1273: */ ! 1274: case TCPS_LAST_ACK: ! 1275: if (ourfinisacked) { ! 1276: tp = tcp_close(tp); ! 1277: goto drop; ! 1278: } ! 1279: break; ! 1280: ! 1281: /* ! 1282: * In TIME_WAIT state the only thing that should arrive ! 1283: * is a retransmission of the remote FIN. Acknowledge ! 1284: * it and restart the finack timer. ! 1285: */ ! 1286: case TCPS_TIME_WAIT: ! 1287: tp->t_timer[TCPT_2MSL] = 2 * TCPTV_MSL; ! 1288: goto dropafterack; ! 1289: } ! 1290: } /* switch(tp->t_state) */ ! 1291: ! 1292: step6: ! 1293: /* ! 1294: * Update window information. ! 1295: * Don't look at window if no ACK: TAC's send garbage on first SYN. ! 1296: */ ! 1297: if ((tiflags & TH_ACK) && ! 1298: (SEQ_LT(tp->snd_wl1, ti->ti_seq) || ! 1299: (tp->snd_wl1 == ti->ti_seq && (SEQ_LT(tp->snd_wl2, ti->ti_ack) || ! 1300: (tp->snd_wl2 == ti->ti_ack && tiwin > tp->snd_wnd))))) { ! 1301: /* keep track of pure window updates */ ! 1302: if (ti->ti_len == 0 && ! 1303: tp->snd_wl2 == ti->ti_ack && tiwin > tp->snd_wnd) ! 1304: tcpstat.tcps_rcvwinupd++; ! 1305: tp->snd_wnd = tiwin; ! 1306: tp->snd_wl1 = ti->ti_seq; ! 1307: tp->snd_wl2 = ti->ti_ack; ! 1308: if (tp->snd_wnd > tp->max_sndwnd) ! 1309: tp->max_sndwnd = tp->snd_wnd; ! 1310: needoutput = 1; ! 1311: } ! 1312: ! 1313: /* ! 1314: * Process segments with URG. ! 1315: */ ! 1316: if ((tiflags & TH_URG) && ti->ti_urp && ! 1317: TCPS_HAVERCVDFIN(tp->t_state) == 0) { ! 1318: /* ! 1319: * This is a kludge, but if we receive and accept ! 1320: * random urgent pointers, we'll crash in ! 1321: * soreceive. It's hard to imagine someone ! 1322: * actually wanting to send this much urgent data. ! 1323: */ ! 1324: if (ti->ti_urp + so->so_rcv.sb_cc > so->so_rcv.sb_datalen) { ! 1325: ti->ti_urp = 0; ! 1326: tiflags &= ~TH_URG; ! 1327: goto dodata; ! 1328: } ! 1329: /* ! 1330: * If this segment advances the known urgent pointer, ! 1331: * then mark the data stream. This should not happen ! 1332: * in CLOSE_WAIT, CLOSING, LAST_ACK or TIME_WAIT STATES since ! 1333: * a FIN has been received from the remote side. ! 1334: * In these states we ignore the URG. ! 1335: * ! 1336: * According to RFC961 (Assigned Protocols), ! 1337: * the urgent pointer points to the last octet ! 1338: * of urgent data. We continue, however, ! 1339: * to consider it to indicate the first octet ! 1340: * of data past the urgent section as the original ! 1341: * spec states (in one of two places). ! 1342: */ ! 1343: if (SEQ_GT(ti->ti_seq+ti->ti_urp, tp->rcv_up)) { ! 1344: tp->rcv_up = ti->ti_seq + ti->ti_urp; ! 1345: so->so_urgc = so->so_rcv.sb_cc + ! 1346: (tp->rcv_up - tp->rcv_nxt); /* -1; */ ! 1347: tp->rcv_up = ti->ti_seq + ti->ti_urp; ! 1348: ! 1349: } ! 1350: } else ! 1351: /* ! 1352: * If no out of band data is expected, ! 1353: * pull receive urgent pointer along ! 1354: * with the receive window. ! 1355: */ ! 1356: if (SEQ_GT(tp->rcv_nxt, tp->rcv_up)) ! 1357: tp->rcv_up = tp->rcv_nxt; ! 1358: dodata: ! 1359: ! 1360: /* ! 1361: * Process the segment text, merging it into the TCP sequencing queue, ! 1362: * and arranging for acknowledgment of receipt if necessary. ! 1363: * This process logically involves adjusting tp->rcv_wnd as data ! 1364: * is presented to the user (this happens in tcp_usrreq.c, ! 1365: * case PRU_RCVD). If a FIN has already been received on this ! 1366: * connection then we just ignore the text. ! 1367: */ ! 1368: if ((ti->ti_len || (tiflags&TH_FIN)) && ! 1369: TCPS_HAVERCVDFIN(tp->t_state) == 0) { ! 1370: TCP_REASS(tp, ti, m, so, tiflags); ! 1371: /* ! 1372: * Note the amount of data that peer has sent into ! 1373: * our window, in order to estimate the sender's ! 1374: * buffer size. ! 1375: */ ! 1376: len = so->so_rcv.sb_datalen - (tp->rcv_adv - tp->rcv_nxt); ! 1377: } else { ! 1378: m_free(m); ! 1379: tiflags &= ~TH_FIN; ! 1380: } ! 1381: ! 1382: /* ! 1383: * If FIN is received ACK the FIN and let the user know ! 1384: * that the connection is closing. ! 1385: */ ! 1386: if (tiflags & TH_FIN) { ! 1387: if (TCPS_HAVERCVDFIN(tp->t_state) == 0) { ! 1388: /* ! 1389: * If we receive a FIN we can't send more data, ! 1390: * set it SS_FDRAIN ! 1391: * Shutdown the socket if there is no rx data in the ! 1392: * buffer. ! 1393: * soread() is called on completion of shutdown() and ! 1394: * will got to TCPS_LAST_ACK, and use tcp_output() ! 1395: * to send the FIN. ! 1396: */ ! 1397: /* sofcantrcvmore(so); */ ! 1398: sofwdrain(so); ! 1399: ! 1400: tp->t_flags |= TF_ACKNOW; ! 1401: tp->rcv_nxt++; ! 1402: } ! 1403: switch (tp->t_state) { ! 1404: ! 1405: /* ! 1406: * In SYN_RECEIVED and ESTABLISHED STATES ! 1407: * enter the CLOSE_WAIT state. ! 1408: */ ! 1409: case TCPS_SYN_RECEIVED: ! 1410: case TCPS_ESTABLISHED: ! 1411: if(so->so_emu == EMU_CTL) /* no shutdown on socket */ ! 1412: tp->t_state = TCPS_LAST_ACK; ! 1413: else ! 1414: tp->t_state = TCPS_CLOSE_WAIT; ! 1415: break; ! 1416: ! 1417: /* ! 1418: * If still in FIN_WAIT_1 STATE FIN has not been acked so ! 1419: * enter the CLOSING state. ! 1420: */ ! 1421: case TCPS_FIN_WAIT_1: ! 1422: tp->t_state = TCPS_CLOSING; ! 1423: break; ! 1424: ! 1425: /* ! 1426: * In FIN_WAIT_2 state enter the TIME_WAIT state, ! 1427: * starting the time-wait timer, turning off the other ! 1428: * standard timers. ! 1429: */ ! 1430: case TCPS_FIN_WAIT_2: ! 1431: tp->t_state = TCPS_TIME_WAIT; ! 1432: tcp_canceltimers(tp); ! 1433: tp->t_timer[TCPT_2MSL] = 2 * TCPTV_MSL; ! 1434: soisfdisconnected(so); ! 1435: break; ! 1436: ! 1437: /* ! 1438: * In TIME_WAIT state restart the 2 MSL time_wait timer. ! 1439: */ ! 1440: case TCPS_TIME_WAIT: ! 1441: tp->t_timer[TCPT_2MSL] = 2 * TCPTV_MSL; ! 1442: break; ! 1443: } ! 1444: } ! 1445: ! 1446: /* ! 1447: * If this is a small packet, then ACK now - with Nagel ! 1448: * congestion avoidance sender won't send more until ! 1449: * he gets an ACK. ! 1450: * ! 1451: * See above. ! 1452: */ ! 1453: /* if (ti->ti_len && (unsigned)ti->ti_len < tp->t_maxseg) { ! 1454: */ ! 1455: /* if ((ti->ti_len && (unsigned)ti->ti_len < tp->t_maxseg && ! 1456: * (so->so_iptos & IPTOS_LOWDELAY) == 0) || ! 1457: * ((so->so_iptos & IPTOS_LOWDELAY) && ! 1458: * ((struct tcpiphdr_2 *)ti)->first_char == (char)27)) { ! 1459: */ ! 1460: if (ti->ti_len && (unsigned)ti->ti_len <= 5 && ! 1461: ((struct tcpiphdr_2 *)ti)->first_char == (char)27) { ! 1462: tp->t_flags |= TF_ACKNOW; ! 1463: } ! 1464: ! 1465: /* ! 1466: * Return any desired output. ! 1467: */ ! 1468: if (needoutput || (tp->t_flags & TF_ACKNOW)) { ! 1469: (void) tcp_output(tp); ! 1470: } ! 1471: return; ! 1472: ! 1473: dropafterack: ! 1474: /* ! 1475: * Generate an ACK dropping incoming segment if it occupies ! 1476: * sequence space, where the ACK reflects our state. ! 1477: */ ! 1478: if (tiflags & TH_RST) ! 1479: goto drop; ! 1480: m_freem(m); ! 1481: tp->t_flags |= TF_ACKNOW; ! 1482: (void) tcp_output(tp); ! 1483: return; ! 1484: ! 1485: dropwithreset: ! 1486: /* reuses m if m!=NULL, m_free() unnecessary */ ! 1487: if (tiflags & TH_ACK) ! 1488: tcp_respond(tp, ti, m, (tcp_seq)0, ti->ti_ack, TH_RST); ! 1489: else { ! 1490: if (tiflags & TH_SYN) ti->ti_len++; ! 1491: tcp_respond(tp, ti, m, ti->ti_seq+ti->ti_len, (tcp_seq)0, ! 1492: TH_RST|TH_ACK); ! 1493: } ! 1494: ! 1495: return; ! 1496: ! 1497: drop: ! 1498: /* ! 1499: * Drop space held by incoming segment and return. ! 1500: */ ! 1501: m_free(m); ! 1502: ! 1503: return; ! 1504: } ! 1505: ! 1506: /* , ts_present, ts_val, ts_ecr) */ ! 1507: /* int *ts_present; ! 1508: * u_int32_t *ts_val, *ts_ecr; ! 1509: */ ! 1510: void ! 1511: tcp_dooptions(tp, cp, cnt, ti) ! 1512: struct tcpcb *tp; ! 1513: u_char *cp; ! 1514: int cnt; ! 1515: struct tcpiphdr *ti; ! 1516: { ! 1517: u_int16_t mss; ! 1518: int opt, optlen; ! 1519: ! 1520: DEBUG_CALL("tcp_dooptions"); ! 1521: DEBUG_ARGS((dfd," tp = %lx cnt=%i \n", (long )tp, cnt)); ! 1522: ! 1523: for (; cnt > 0; cnt -= optlen, cp += optlen) { ! 1524: opt = cp[0]; ! 1525: if (opt == TCPOPT_EOL) ! 1526: break; ! 1527: if (opt == TCPOPT_NOP) ! 1528: optlen = 1; ! 1529: else { ! 1530: optlen = cp[1]; ! 1531: if (optlen <= 0) ! 1532: break; ! 1533: } ! 1534: switch (opt) { ! 1535: ! 1536: default: ! 1537: continue; ! 1538: ! 1539: case TCPOPT_MAXSEG: ! 1540: if (optlen != TCPOLEN_MAXSEG) ! 1541: continue; ! 1542: if (!(ti->ti_flags & TH_SYN)) ! 1543: continue; ! 1544: memcpy((char *) &mss, (char *) cp + 2, sizeof(mss)); ! 1545: NTOHS(mss); ! 1546: (void) tcp_mss(tp, mss); /* sets t_maxseg */ ! 1547: break; ! 1548: ! 1549: /* case TCPOPT_WINDOW: ! 1550: * if (optlen != TCPOLEN_WINDOW) ! 1551: * continue; ! 1552: * if (!(ti->ti_flags & TH_SYN)) ! 1553: * continue; ! 1554: * tp->t_flags |= TF_RCVD_SCALE; ! 1555: * tp->requested_s_scale = min(cp[2], TCP_MAX_WINSHIFT); ! 1556: * break; ! 1557: */ ! 1558: /* case TCPOPT_TIMESTAMP: ! 1559: * if (optlen != TCPOLEN_TIMESTAMP) ! 1560: * continue; ! 1561: * *ts_present = 1; ! 1562: * memcpy((char *) ts_val, (char *)cp + 2, sizeof(*ts_val)); ! 1563: * NTOHL(*ts_val); ! 1564: * memcpy((char *) ts_ecr, (char *)cp + 6, sizeof(*ts_ecr)); ! 1565: * NTOHL(*ts_ecr); ! 1566: * ! 1567: */ /* ! 1568: * * A timestamp received in a SYN makes ! 1569: * * it ok to send timestamp requests and replies. ! 1570: * */ ! 1571: /* if (ti->ti_flags & TH_SYN) { ! 1572: * tp->t_flags |= TF_RCVD_TSTMP; ! 1573: * tp->ts_recent = *ts_val; ! 1574: * tp->ts_recent_age = tcp_now; ! 1575: * } ! 1576: */ break; ! 1577: } ! 1578: } ! 1579: } ! 1580: ! 1581: ! 1582: /* ! 1583: * Pull out of band byte out of a segment so ! 1584: * it doesn't appear in the user's data queue. ! 1585: * It is still reflected in the segment length for ! 1586: * sequencing purposes. ! 1587: */ ! 1588: ! 1589: #ifdef notdef ! 1590: ! 1591: void ! 1592: tcp_pulloutofband(so, ti, m) ! 1593: struct socket *so; ! 1594: struct tcpiphdr *ti; ! 1595: register struct mbuf *m; ! 1596: { ! 1597: int cnt = ti->ti_urp - 1; ! 1598: ! 1599: while (cnt >= 0) { ! 1600: if (m->m_len > cnt) { ! 1601: char *cp = mtod(m, caddr_t) + cnt; ! 1602: struct tcpcb *tp = sototcpcb(so); ! 1603: ! 1604: tp->t_iobc = *cp; ! 1605: tp->t_oobflags |= TCPOOB_HAVEDATA; ! 1606: memcpy(sp, cp+1, (unsigned)(m->m_len - cnt - 1)); ! 1607: m->m_len--; ! 1608: return; ! 1609: } ! 1610: cnt -= m->m_len; ! 1611: m = m->m_next; /* XXX WRONG! Fix it! */ ! 1612: if (m == 0) ! 1613: break; ! 1614: } ! 1615: panic("tcp_pulloutofband"); ! 1616: } ! 1617: ! 1618: #endif /* notdef */ ! 1619: ! 1620: /* ! 1621: * Collect new round-trip time estimate ! 1622: * and update averages and current timeout. ! 1623: */ ! 1624: ! 1625: void ! 1626: tcp_xmit_timer(tp, rtt) ! 1627: register struct tcpcb *tp; ! 1628: int rtt; ! 1629: { ! 1630: register short delta; ! 1631: ! 1632: DEBUG_CALL("tcp_xmit_timer"); ! 1633: DEBUG_ARG("tp = %lx", (long)tp); ! 1634: DEBUG_ARG("rtt = %d", rtt); ! 1635: ! 1636: tcpstat.tcps_rttupdated++; ! 1637: if (tp->t_srtt != 0) { ! 1638: /* ! 1639: * srtt is stored as fixed point with 3 bits after the ! 1640: * binary point (i.e., scaled by 8). The following magic ! 1641: * is equivalent to the smoothing algorithm in rfc793 with ! 1642: * an alpha of .875 (srtt = rtt/8 + srtt*7/8 in fixed ! 1643: * point). Adjust rtt to origin 0. ! 1644: */ ! 1645: delta = rtt - 1 - (tp->t_srtt >> TCP_RTT_SHIFT); ! 1646: if ((tp->t_srtt += delta) <= 0) ! 1647: tp->t_srtt = 1; ! 1648: /* ! 1649: * We accumulate a smoothed rtt variance (actually, a ! 1650: * smoothed mean difference), then set the retransmit ! 1651: * timer to smoothed rtt + 4 times the smoothed variance. ! 1652: * rttvar is stored as fixed point with 2 bits after the ! 1653: * binary point (scaled by 4). The following is ! 1654: * equivalent to rfc793 smoothing with an alpha of .75 ! 1655: * (rttvar = rttvar*3/4 + |delta| / 4). This replaces ! 1656: * rfc793's wired-in beta. ! 1657: */ ! 1658: if (delta < 0) ! 1659: delta = -delta; ! 1660: delta -= (tp->t_rttvar >> TCP_RTTVAR_SHIFT); ! 1661: if ((tp->t_rttvar += delta) <= 0) ! 1662: tp->t_rttvar = 1; ! 1663: } else { ! 1664: /* ! 1665: * No rtt measurement yet - use the unsmoothed rtt. ! 1666: * Set the variance to half the rtt (so our first ! 1667: * retransmit happens at 3*rtt). ! 1668: */ ! 1669: tp->t_srtt = rtt << TCP_RTT_SHIFT; ! 1670: tp->t_rttvar = rtt << (TCP_RTTVAR_SHIFT - 1); ! 1671: } ! 1672: tp->t_rtt = 0; ! 1673: tp->t_rxtshift = 0; ! 1674: ! 1675: /* ! 1676: * the retransmit should happen at rtt + 4 * rttvar. ! 1677: * Because of the way we do the smoothing, srtt and rttvar ! 1678: * will each average +1/2 tick of bias. When we compute ! 1679: * the retransmit timer, we want 1/2 tick of rounding and ! 1680: * 1 extra tick because of +-1/2 tick uncertainty in the ! 1681: * firing of the timer. The bias will give us exactly the ! 1682: * 1.5 tick we need. But, because the bias is ! 1683: * statistical, we have to test that we don't drop below ! 1684: * the minimum feasible timer (which is 2 ticks). ! 1685: */ ! 1686: TCPT_RANGESET(tp->t_rxtcur, TCP_REXMTVAL(tp), ! 1687: (short)tp->t_rttmin, TCPTV_REXMTMAX); /* XXX */ ! 1688: ! 1689: /* ! 1690: * We received an ack for a packet that wasn't retransmitted; ! 1691: * it is probably safe to discard any error indications we've ! 1692: * received recently. This isn't quite right, but close enough ! 1693: * for now (a route might have failed after we sent a segment, ! 1694: * and the return path might not be symmetrical). ! 1695: */ ! 1696: tp->t_softerror = 0; ! 1697: } ! 1698: ! 1699: /* ! 1700: * Determine a reasonable value for maxseg size. ! 1701: * If the route is known, check route for mtu. ! 1702: * If none, use an mss that can be handled on the outgoing ! 1703: * interface without forcing IP to fragment; if bigger than ! 1704: * an mbuf cluster (MCLBYTES), round down to nearest multiple of MCLBYTES ! 1705: * to utilize large mbufs. If no route is found, route has no mtu, ! 1706: * or the destination isn't local, use a default, hopefully conservative ! 1707: * size (usually 512 or the default IP max size, but no more than the mtu ! 1708: * of the interface), as we can't discover anything about intervening ! 1709: * gateways or networks. We also initialize the congestion/slow start ! 1710: * window to be a single segment if the destination isn't local. ! 1711: * While looking at the routing entry, we also initialize other path-dependent ! 1712: * parameters from pre-set or cached values in the routing entry. ! 1713: */ ! 1714: ! 1715: int ! 1716: tcp_mss(tp, offer) ! 1717: register struct tcpcb *tp; ! 1718: u_int offer; ! 1719: { ! 1720: struct socket *so = tp->t_socket; ! 1721: int mss; ! 1722: ! 1723: DEBUG_CALL("tcp_mss"); ! 1724: DEBUG_ARG("tp = %lx", (long)tp); ! 1725: DEBUG_ARG("offer = %d", offer); ! 1726: ! 1727: mss = min(if_mtu, if_mru) - sizeof(struct tcpiphdr); ! 1728: if (offer) ! 1729: mss = min(mss, offer); ! 1730: mss = max(mss, 32); ! 1731: if (mss < tp->t_maxseg || offer != 0) ! 1732: tp->t_maxseg = mss; ! 1733: ! 1734: tp->snd_cwnd = mss; ! 1735: ! 1736: sbreserve(&so->so_snd, tcp_sndspace+((tcp_sndspace%mss)?(mss-(tcp_sndspace%mss)):0)); ! 1737: sbreserve(&so->so_rcv, tcp_rcvspace+((tcp_rcvspace%mss)?(mss-(tcp_rcvspace%mss)):0)); ! 1738: ! 1739: DEBUG_MISC((dfd, " returning mss = %d\n", mss)); ! 1740: ! 1741: return mss; ! 1742: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.