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