1*4803Swnj /* tcp_input.c 1.21 81/11/08 */ 24601Swnj 34601Swnj #include "../h/param.h" 44601Swnj #include "../h/systm.h" 54663Swnj #include "../h/mbuf.h" 64663Swnj #include "../h/socket.h" 7*4803Swnj #include "../h/socketvar.h" 8*4803Swnj #include "../net/inet_cksum.h" 9*4803Swnj #include "../net/inet.h" 10*4803Swnj #include "../net/inet_systm.h" 11*4803Swnj #include "../net/imp.h" 12*4803Swnj #include "../net/inet_host.h" 13*4803Swnj #include "../net/ip.h" 14*4803Swnj #include "../net/tcp.h" 15*4803Swnj #include "../net/tcp_fsm.h" 16*4803Swnj #include "../net/tcp_var.h" 17*4803Swnj #include "/usr/include/errno.h" 184601Swnj 194679Swnj int tcpcksum = 1; 204601Swnj 21*4803Swnj tcp_advise(mp) 22*4803Swnj struct mbuf *mp; 23*4803Swnj { 24*4803Swnj 25*4803Swnj } 26*4803Swnj 274601Swnj tcp_input(mp) 284601Swnj register struct mbuf *mp; 294601Swnj { 304673Swnj register struct th *n; /* known to be r10 */ 314697Swnj register int j; 324601Swnj register struct tcb *tp; 33*4803Swnj register int thflags; 344601Swnj int nstate; 354601Swnj struct mbuf *m; 36*4803Swnj struct socket *so; 374673Swnj int hlen, tlen; 384601Swnj u_short lport, fport; 394601Swnj #ifdef TCPDEBUG 404601Swnj struct tcp_debug tdb; 414601Swnj #endif 424601Swnj COUNT(TCP_INPUT); 434601Swnj 444601Swnj /* 454601Swnj * Build extended tcp header 464601Swnj */ 47*4803Swnj n = mtod(mp, struct th *); 48*4803Swnj thflags = n->th_flags; 494601Swnj tlen = ((struct ip *)n)->ip_len; 504601Swnj n->t_len = htons(tlen); 514601Swnj n->t_next = NULL; 524601Swnj n->t_prev = NULL; 534601Swnj n->t_x1 = 0; 544601Swnj lport = ntohs(n->t_dst); 554601Swnj fport = ntohs(n->t_src); 564601Swnj 574601Swnj /* WONT BE POSSIBLE WHEN MBUFS ARE 256 BYTES */ 584601Swnj if ((hlen = n->t_off << 2) > mp->m_len) 594601Swnj { printf("tcp header overflow\n"); m_freem(mp); return; } 604601Swnj 614679Swnj if (tcpcksum) { 624679Swnj /* 634679Swnj * Checksum extended header and data 644679Swnj */ 654718Swnj CKSUM_TCPCHK(mp, n, r10, sizeof (struct ip) + tlen); 664718Swnj if (n->t_sum != 0) { 674679Swnj netstat.t_badsum++; 684601Swnj m_freem(mp); 694601Swnj return; 704601Swnj } 714601Swnj } 724601Swnj 734601Swnj /* 744601Swnj * Find tcb for message (SHOULDN'T USE LINEAR SEARCH!) 754601Swnj */ 76*4803Swnj tp = tcb.tcb_next; 77*4803Swnj for (; tp != (struct tcb *)&tcb; tp = tp->tcb_hd.tcb_next) 784601Swnj if (tp->t_lport == lport && tp->t_fport == fport && 79*4803Swnj tp->t_host->h_addr.s_addr == n->t_s.s_addr) 804601Swnj goto found; 81*4803Swnj tp = tcb.tcb_next; 82*4803Swnj for (; tp != (struct tcb *)&tcb; tp = tp->tcb_hd.tcb_next) 834601Swnj if (tp->t_lport == lport && 844601Swnj (tp->t_fport==fport || tp->t_fport==0) && 85*4803Swnj (tp->t_host->h_addr.s_addr == n->t_s.s_addr || 86*4803Swnj tp->t_host->h_addr.s_addr == 0)) 874601Swnj goto found; 884601Swnj goto notwanted; 894601Swnj found: 904601Swnj 914601Swnj /* 924601Swnj * Byte swap header 934601Swnj */ 944601Swnj n->t_len = tlen - hlen; 954601Swnj n->t_src = fport; 964601Swnj n->t_dst = lport; 974601Swnj n->t_seq = ntohl(n->t_seq); 984601Swnj n->t_ackno = ntohl(n->t_ackno); 994601Swnj n->t_win = ntohs(n->t_win); 1004601Swnj n->t_urp = ntohs(n->t_urp); 1014601Swnj 1024601Swnj /* 1034601Swnj * Check segment seq # and do rst processing 1044601Swnj */ 1054601Swnj switch (tp->t_state) { 1064601Swnj 1074601Swnj case LISTEN: 108*4803Swnj if ((thflags&TH_ACK) || !syn_ok(tp, n)) { 1094675Swnj tcp_sndrst(tp, n); 1104601Swnj goto badseg; 1114601Swnj } 112*4803Swnj if (thflags&TH_RST) 1134601Swnj goto badseg; 1144601Swnj goto goodseg; 1154601Swnj 1164601Swnj case SYN_SENT: 1174601Swnj if (!ack_ok(tp, n) || !syn_ok(tp, n)) { 1184675Swnj tcp_sndrst(tp, n); /* 71,72,75 */ 1194601Swnj goto badseg; 1204601Swnj } 121*4803Swnj if (thflags&TH_RST) { 122*4803Swnj tcp_error(tp, ENETRESET); 123*4803Swnj tcp_detach(tp); /* 70 */ 1244601Swnj tp->t_state = CLOSED; 1254601Swnj goto badseg; 1264601Swnj } 1274601Swnj goto goodseg; 1284601Swnj 1294601Swnj default: 130*4803Swnj if ((thflags&TH_RST) == 0) 1314601Swnj goto common; 1324601Swnj if (n->t_seq < tp->rcv_nxt) /* bad rst */ 1334601Swnj goto badseg; /* 69 */ 1344601Swnj switch (tp->t_state) { 1354601Swnj 1364601Swnj case L_SYN_RCVD: 1374601Swnj if (ack_ok(tp, n) == 0) 1384601Swnj goto badseg; /* 69 */ 1394601Swnj tp->t_rexmt = 0; 1404601Swnj tp->t_rexmttl = 0; 1414601Swnj tp->t_persist = 0; 142*4803Swnj h_free(tp->t_host); 143*4803Swnj tp->t_host = 0; 1444601Swnj tp->t_state = LISTEN; 1454601Swnj goto badseg; 1464601Swnj 1474601Swnj default: 148*4803Swnj tcp_error(tp, ENETRESET); 149*4803Swnj tcp_detach(tp); /* 66 */ 1504601Swnj tp->t_state = CLOSED; 1514601Swnj goto badseg; 1524601Swnj } 1534601Swnj /*NOTREACHED*/ 1544601Swnj 1554601Swnj case SYN_RCVD: 1564601Swnj common: 1574601Swnj if (ack_ok(tp, n) == 0) { 1584675Swnj tcp_sndrst(tp, n); /* 74 */ 1594601Swnj goto badseg; 1604601Swnj } 1614601Swnj if (syn_ok(tp, n) && n->t_seq != tp->irs) { 1624679Swnj tcp_sndnull(tp); /* 74 */ 1634601Swnj goto badseg; 1644601Swnj } 1654601Swnj goto goodseg; 1664601Swnj } 1674601Swnj badseg: 1684601Swnj m_freem(mp); 1694601Swnj return; 1704601Swnj 1714601Swnj goodseg: 1724601Swnj /* 1734601Swnj * Defer processing if no buffer space for this connection. 1744601Swnj */ 175*4803Swnj so = tp->t_socket; 176*4803Swnj if (so->so_rcv.sb_cc >= so->so_rcv.sb_hiwat && 177*4803Swnj n->t_len != 0 && mbstat.m_bufs < mbstat.m_lowat) { 178*4803Swnj /* 1794601Swnj mp->m_act = (struct mbuf *)0; 180*4803Swnj if ((m = tp->seg_unack) != NULL) { 1814601Swnj while (m->m_act != NULL) 1824601Swnj m = m->m_act; 1834601Swnj m->m_act = mp; 1844601Swnj } else 185*4803Swnj tp->seg_unack = mp; 186*4803Swnj */ 187*4803Swnj m_freem(mp); 1884601Swnj return; 1894601Swnj } 1904601Swnj 1914601Swnj /* 1924601Swnj * Discard ip header, and do tcp input processing. 1934601Swnj */ 1944601Swnj hlen += sizeof(struct ip); 1954601Swnj mp->m_off += hlen; 1964601Swnj mp->m_len -= hlen; 1974601Swnj nstate = tp->t_state; 1984601Swnj tp->tc_flags &= ~TC_NET_KEEP; 1994770Swnj #ifdef KPROF 2004601Swnj acounts[tp->t_state][INRECV]++; 2014770Swnj #endif 2024601Swnj #ifdef TCPDEBUG 203*4803Swnj if ((tp->t_socket->so_options & SO_DEBUG) || tcpconsdebug) { 2044604Swnj tdb_setup(tp, n, INRECV, &tdb); 2054601Swnj } else 2064601Swnj tdb.td_tod = 0; 2074601Swnj #endif 2084601Swnj switch (tp->t_state) { 2094601Swnj 2104601Swnj case LISTEN: 2114601Swnj if (!syn_ok(tp, n) || 212*4803Swnj ((tp->t_host = h_make(&n->t_s)) == 0)) { 2134601Swnj nstate = EFAILEC; 2144601Swnj goto done; 2154601Swnj } 2164601Swnj tp->t_fport = n->t_src; 2174733Swnj tp->t_template = tcp_template(tp); 2184675Swnj tcp_ctldat(tp, n, 1); 2194601Swnj if (tp->tc_flags&TC_FIN_RCVD) { 2204601Swnj tp->t_finack = T_2ML; /* 3 */ 2214601Swnj tp->tc_flags &= ~TC_WAITED_2_ML; 2224601Swnj nstate = CLOSE_WAIT; 2234601Swnj } else { 224*4803Swnj /* XXX */ /* tp->t_init = T_INIT / 2; */ /* 4 */ 2254601Swnj nstate = L_SYN_RCVD; 2264601Swnj } 2274601Swnj goto done; 2284601Swnj 2294601Swnj case SYN_SENT: 2304601Swnj if (!syn_ok(tp, n)) { 2314601Swnj nstate = EFAILEC; 2324601Swnj goto done; 2334601Swnj } 2344675Swnj tcp_ctldat(tp, n, 1); 2354601Swnj if (tp->tc_flags&TC_FIN_RCVD) { 236*4803Swnj if ((thflags&TH_ACK) == 0) { 2374601Swnj tp->t_finack = T_2ML; /* 9 */ 2384601Swnj tp->tc_flags &= ~TC_WAITED_2_ML; 2394601Swnj } 2404601Swnj nstate = CLOSE_WAIT; 2414601Swnj goto done; 2424601Swnj } 243*4803Swnj nstate = (thflags&TH_ACK) ? ESTAB : SYN_RCVD; /* 11:8 */ 2444601Swnj goto done; 2454601Swnj 2464601Swnj case SYN_RCVD: 2474601Swnj case L_SYN_RCVD: 248*4803Swnj if ((thflags&TH_ACK) == 0 || 249*4803Swnj (thflags&TH_ACK) && n->t_ackno <= tp->iss) { 2504601Swnj nstate = EFAILEC; 2514601Swnj goto done; 2524601Swnj } 2534601Swnj goto input; 2544601Swnj 2554601Swnj case ESTAB: 2564601Swnj case FIN_W1: 2574601Swnj case FIN_W2: 2584601Swnj case TIME_WAIT: 2594601Swnj input: 2604675Swnj tcp_ctldat(tp, n, 1); /* 39 */ 2614601Swnj switch (tp->t_state) { 2624601Swnj 2634601Swnj case ESTAB: 2644601Swnj if (tp->tc_flags&TC_FIN_RCVD) 2654601Swnj nstate = CLOSE_WAIT; 2664601Swnj break; 2674601Swnj 2684601Swnj case SYN_RCVD: 2694601Swnj case L_SYN_RCVD: 2704601Swnj nstate = (tp->tc_flags&TC_FIN_RCVD) ? 2714601Swnj CLOSE_WAIT : ESTAB; /* 33:5 */ 2724601Swnj break; 2734601Swnj 2744601Swnj case FIN_W1: 2754601Swnj j = ack_fin(tp, n); 2764601Swnj if ((tp->tc_flags & TC_FIN_RCVD) == 0) { 2774601Swnj if (j) 2784601Swnj nstate = FIN_W2; /* 27 */ 2794601Swnj break; 2804601Swnj } 2814601Swnj tp->t_finack = T_2ML; 2824601Swnj tp->tc_flags &= ~TC_WAITED_2_ML; 2834730Swnj nstate = j ? TIME_WAIT : CLOSING; /* 28:26 */ 2844601Swnj break; 2854601Swnj 2864601Swnj case FIN_W2: 2874601Swnj if (tp->tc_flags&TC_FIN_RCVD) { 2884601Swnj tp->t_finack = T_2ML; /* 29 */ 2894601Swnj tp->tc_flags &= ~TC_WAITED_2_ML; 2904601Swnj nstate = TIME_WAIT; 2914601Swnj break; 2924601Swnj } 2934601Swnj break; 2944601Swnj } 2954601Swnj goto done; 2964601Swnj 2974601Swnj case CLOSE_WAIT: 298*4803Swnj if (thflags&TH_FIN) { 299*4803Swnj if ((thflags&TH_ACK) && 3004601Swnj n->t_ackno <= tp->seq_fin) { 3014675Swnj tcp_ctldat(tp, n, 0); /* 30 */ 3024601Swnj tp->t_finack = T_2ML; 3034601Swnj tp->tc_flags &= ~TC_WAITED_2_ML; 3044601Swnj } else 3054675Swnj tcp_sndctl(tp); /* 31 */ 3064601Swnj goto done; 3074601Swnj } 3084601Swnj goto input; 3094601Swnj 3104730Swnj case CLOSING: 3114601Swnj j = ack_fin(tp, n); 312*4803Swnj if (thflags&TH_FIN) { 3134675Swnj tcp_ctldat(tp, n, 0); 3144601Swnj tp->t_finack = T_2ML; 3154601Swnj tp->tc_flags &= ~TC_WAITED_2_ML; 3164601Swnj if (j) 3174601Swnj nstate = TIME_WAIT; /* 23 */ 3184601Swnj goto done; 3194601Swnj } 3204601Swnj if (j) { 3214601Swnj if (tp->tc_flags&TC_WAITED_2_ML) 3224601Swnj if (rcv_empty(tp)) { 323*4803Swnj sowakeup(tp->t_socket); /* ### */ 324*4803Swnj nstate = CLOSED; /* 15 */ 3254601Swnj } else 3264601Swnj nstate = RCV_WAIT; /* 18 */ 3274601Swnj else 3284601Swnj nstate = TIME_WAIT; 3294601Swnj goto done; 3304601Swnj } 3314601Swnj goto input; 3324601Swnj 3334730Swnj case LAST_ACK: 3344601Swnj if (ack_fin(tp, n)) { 3354601Swnj if (rcv_empty(tp)) { /* 16 */ 336*4803Swnj sowakeup(tp->t_socket); /* ### */ 337*4803Swnj /* XXX */ /* tcp_close(tp, UCLOSED); */ 3384601Swnj nstate = CLOSED; 3394601Swnj } else 3404601Swnj nstate = RCV_WAIT; /* 19 */ 3414601Swnj goto done; 3424601Swnj } 343*4803Swnj if (thflags&TH_FIN) { 3444675Swnj tcp_sndctl(tp); /* 31 */ 3454601Swnj goto done; 3464601Swnj } 3474601Swnj goto input; 3484601Swnj 3494601Swnj case RCV_WAIT: 350*4803Swnj if ((thflags&TH_FIN) && (thflags&TH_ACK) && 3514601Swnj n->t_ackno <= tp->seq_fin) { 3524675Swnj tcp_ctldat(tp, n, 0); 3534601Swnj tp->t_finack = T_2ML; 3544601Swnj tp->tc_flags &= ~TC_WAITED_2_ML; /* 30 */ 3554601Swnj } 3564601Swnj goto done; 3574601Swnj } 3584601Swnj panic("tcp_input"); 3594601Swnj done: 3604601Swnj 3614601Swnj /* 3624601Swnj * Done with state*input specific processing. 3634601Swnj * Form trace records, free input if not needed, 3644601Swnj * and enter new state. 3654601Swnj */ 3664601Swnj #ifdef TCPDEBUG 3674604Swnj if (tdb.td_tod) 3684604Swnj tdb_stuff(&tdb, nstate); 3694601Swnj #endif 3704601Swnj switch (nstate) { 3714601Swnj 3724601Swnj case EFAILEC: 3734601Swnj m_freem(mp); 3744601Swnj return; 3754601Swnj 3764601Swnj default: 3774601Swnj tp->t_state = nstate; 3784601Swnj /* fall into ... */ 3794601Swnj 3804601Swnj case CLOSED: 3814601Swnj /* IF CLOSED CANT LOOK AT tc_flags */ 3824601Swnj if ((tp->tc_flags&TC_NET_KEEP) == 0) 3834690Swnj /* inline expansion of m_freem */ 3844690Swnj while (mp) { 3854690Swnj MFREE(mp, m); 3864690Swnj mp = m; 3874690Swnj } 3884601Swnj return; 3894601Swnj } 3904601Swnj /* NOTREACHED */ 3914601Swnj 3924601Swnj /* 3934601Swnj * Unwanted packed; free everything 3944601Swnj * but the header and return an rst. 3954601Swnj */ 3964601Swnj notwanted: 3974601Swnj m_freem(mp->m_next); 3984601Swnj mp->m_next = NULL; 3994601Swnj mp->m_len = sizeof(struct th); 4004601Swnj #define xchg(a,b) j=a; a=b; b=j 4014601Swnj xchg(n->t_d.s_addr, n->t_s.s_addr); xchg(n->t_dst, n->t_src); 4024601Swnj #undef xchg 403*4803Swnj if (thflags&TH_ACK) 4044601Swnj n->t_seq = n->t_ackno; 4054601Swnj else { 4064601Swnj n->t_ackno = htonl(ntohl(n->t_seq) + tlen - hlen); 4074601Swnj n->t_seq = 0; 4084601Swnj } 409*4803Swnj n->th_flags = ((thflags & TH_ACK) ? 0 : TH_ACK) | TH_RST; 4104601Swnj n->t_len = htons(TCPSIZE); 4114601Swnj n->t_off = 5; 4124718Swnj n->t_sum = inet_cksum(mp, sizeof(struct th)); 4134601Swnj ((struct ip *)n)->ip_len = sizeof(struct th); 4144601Swnj ip_output(mp); 4154601Swnj netstat.t_badsegs++; 4164601Swnj } 4174601Swnj 4184675Swnj tcp_ctldat(tp, n, dataok) 4194601Swnj register struct tcb *tp; 4204601Swnj register struct th *n; 4214601Swnj { 4224679Swnj register struct mbuf *m; 423*4803Swnj register int thflags = n->th_flags; 4244679Swnj int sent; 4254679Swnj COUNT(TCP_CTLDAT); 4264601Swnj 4274601Swnj tp->tc_flags &= ~(TC_DROPPED_TXT|TC_ACK_DUE|TC_NEW_WINDOW); 4284601Swnj /* syn */ 429*4803Swnj if ((tp->tc_flags&TC_SYN_RCVD) == 0 && (thflags&TH_SYN)) { 4304601Swnj tp->irs = n->t_seq; 4314601Swnj tp->rcv_nxt = n->t_seq + 1; 4324601Swnj tp->snd_wl = tp->rcv_urp = tp->irs; 4334601Swnj tp->tc_flags |= (TC_SYN_RCVD|TC_ACK_DUE); 4344601Swnj } 4354601Swnj /* ack */ 436*4803Swnj if ((thflags&TH_ACK) && (tp->tc_flags&TC_SYN_RCVD) && 4374601Swnj n->t_ackno > tp->snd_una) { 4384679Swnj register struct mbuf *mn; 439*4803Swnj register struct socket *so; 4404690Swnj int len; 4414679Swnj 442*4803Swnj so = tp->t_socket; 4434601Swnj 4444601Swnj /* update snd_una and snd_nxt */ 4454601Swnj tp->snd_una = n->t_ackno; 4464601Swnj if (tp->snd_una > tp->snd_nxt) 4474601Swnj tp->snd_nxt = tp->snd_una; 4484601Swnj /* if timed msg acked, set retrans time value */ 4494601Swnj if ((tp->tc_flags&TC_SYN_ACKED) && 4504601Swnj tp->snd_una > tp->t_xmt_val) { 4514601Swnj tp->t_xmtime = (tp->t_xmt != 0 ? tp->t_xmt : T_REXMT); 4524601Swnj if (tp->t_xmtime > T_REMAX) 4534601Swnj tp->t_xmtime = T_REMAX; 4544601Swnj } 4554601Swnj 4564601Swnj /* remove acked data from send buf */ 4574601Swnj len = tp->snd_una - tp->snd_off; 458*4803Swnj m = so->so_snd.sb_mb; 4594601Swnj while (len > 0 && m != NULL) 4604601Swnj if (m->m_len <= len) { 4614601Swnj len -= m->m_len; 4624601Swnj if (m->m_off > MMAXOFF) 463*4803Swnj so->so_snd.sb_mbcnt -= NMBPG; 4644601Swnj MFREE(m, mn); 4654601Swnj m = mn; 466*4803Swnj so->so_snd.sb_mbcnt--; 467*4803Swnj if (so->so_snd.sb_mbcnt <= 0) 468*4803Swnj panic("tcp_ctldat"); 4694601Swnj } else { 4704601Swnj m->m_len -= len; 4714601Swnj m->m_off += len; 4724601Swnj break; 4734601Swnj } 474*4803Swnj so->so_snd.sb_mb = m; 4754601Swnj tp->snd_off = tp->snd_una; 4764601Swnj if ((tp->tc_flags&TC_SYN_ACKED) == 0 && 4774601Swnj (tp->snd_una > tp->iss)) { 4784601Swnj tp->tc_flags |= TC_SYN_ACKED; 4794601Swnj tp->t_init = 0; 4804601Swnj } 4814601Swnj if (tp->seq_fin != tp->iss && tp->snd_una > tp->seq_fin) 4824601Swnj tp->tc_flags &= ~TC_SND_FIN; 4834601Swnj tp->t_rexmt = 0; 4844601Swnj tp->t_rexmttl = 0; 4854601Swnj tp->tc_flags |= TC_CANCELLED; 486*4803Swnj sowakeup(tp->t_socket); /* wasteful */ 4874601Swnj } 4884601Swnj /* win */ 4894601Swnj if ((tp->tc_flags & TC_SYN_RCVD) && n->t_seq >= tp->snd_wl) { 4904601Swnj tp->snd_wl = n->t_seq; 4914601Swnj tp->snd_wnd = n->t_win; 4924601Swnj tp->tc_flags |= TC_NEW_WINDOW; 4934601Swnj tp->t_persist = 0; 4944601Swnj } 4954679Swnj if (dataok == 0) 4964679Swnj goto ctlonly; 4974601Swnj /* text */ 4984679Swnj if (n->t_len == 0) 4994679Swnj goto notext; 5004679Swnj { register int i; 5014679Swnj register struct th *p, *q; 5024679Swnj register struct mbuf *m; 5034679Swnj int overage; 5044601Swnj 5054645Swnj /* 5064645Swnj * Discard duplicate data already passed to user. 5074645Swnj */ 5084648Swnj if (SEQ_LT(n->t_seq, tp->rcv_nxt)) { 5094645Swnj i = tp->rcv_nxt - n->t_seq; 5104645Swnj if (i >= n->t_len) 5114679Swnj goto notext; 5124645Swnj n->t_seq += i; 5134645Swnj n->t_len -= i; 5144645Swnj m_adj(dtom(n), i); 5154601Swnj } 5164601Swnj 5174645Swnj /* 5184645Swnj * Find a segment which begins after this one does. 5194645Swnj */ 520*4803Swnj for (q = tp->tcb_hd.seg_next; q != (struct th *)tp; q = q->t_next) 5214648Swnj if (SEQ_GT(q->t_seq, n->t_seq)) 5224645Swnj break; 5234601Swnj 5244645Swnj /* 5254645Swnj * If there is a preceding segment, it may provide some of 5264645Swnj * our data already. If so, drop the data from the incoming 5274645Swnj * segment. If it provides all of our data, drop us. 5284645Swnj */ 5294645Swnj if (q->t_prev != (struct th *)tp) { 5304648Swnj /* conversion to int (in i) handles seq wraparound */ 5314645Swnj i = q->t_prev->t_seq + q->t_prev->t_len - n->t_seq; 5324645Swnj if (i > 0) { 5334645Swnj if (i >= n->t_len) 5344679Swnj goto notext; /* w/o setting TC_NET_KEEP */ 5354645Swnj m_adj(dtom(tp), i); 5364645Swnj n->t_len -= i; 5374645Swnj n->t_seq += i; 5384601Swnj } 5394601Swnj } 5404601Swnj 5414645Swnj /* 5424645Swnj * While we overlap succeeding segments trim them or, 5434645Swnj * if they are completely covered, dequeue them. 5444645Swnj */ 5454648Swnj while (q != (struct th *)tp && SEQ_GT(n->t_seq + n->t_len, q->t_seq)) { 5464645Swnj i = (n->t_seq + n->t_len) - q->t_seq; 5474645Swnj if (i < q->t_len) { 5484645Swnj q->t_len -= i; 5494645Swnj m_adj(dtom(q), i); 5504645Swnj break; 5514601Swnj } 5524645Swnj q = q->t_next; 5534645Swnj m_freem(dtom(q->t_prev)); 5544645Swnj remque(q->t_prev); 5554645Swnj } 5564601Swnj 5574645Swnj /* 5584645Swnj * Stick new segment in its place. 5594645Swnj */ 5604645Swnj insque(n, q->t_prev); 5614656Swnj tp->seqcnt += n->t_len; 5624601Swnj 5634645Swnj /* 5644645Swnj * Calculate available space and discard segments for 5654645Swnj * which there is too much. 5664645Swnj */ 567*4803Swnj q = tp->tcb_hd.seg_prev; 5684648Swnj overage = 569*4803Swnj (tp->t_socket->so_rcv.sb_cc /* + tp->rcv_seqcnt XXX */) - 570*4803Swnj tp->t_socket->so_rcv.sb_hiwat; 5714645Swnj if (overage > 0) 5724645Swnj for (;;) { 5734645Swnj i = MIN(q->t_len, overage); 5744645Swnj overage -= i; 5754645Swnj q->t_len -= i; 5764645Swnj m_adj(q, -i); 5774645Swnj if (q == n) 5784645Swnj tp->tc_flags |= TC_DROPPED_TXT; 5794645Swnj if (q->t_len) 5804645Swnj break; 5814645Swnj if (q == n) 5824648Swnj panic("tcp_text dropall"); 5834645Swnj q = q->t_prev; 5844645Swnj remque(q->t_next); 5854645Swnj } 5864601Swnj 5874645Swnj /* 5884648Swnj * Advance rcv_next through 5894648Swnj * newly completed sequence space 5904648Swnj * and return forcing an ack. 5914645Swnj */ 5924645Swnj while (n->t_seq == tp->rcv_nxt) { 5934648Swnj /* present data belongs here */ 5944645Swnj tp->rcv_nxt += n->t_len; 5954645Swnj n = n->t_next; 5964645Swnj if (n == (struct th *)tp) 5974645Swnj break; 5984645Swnj } 5994645Swnj tp->tc_flags |= (TC_ACK_DUE|TC_NET_KEEP); 6004679Swnj } 6014679Swnj notext: 6024679Swnj /* urg */ 6034601Swnj 604*4803Swnj if (thflags & (TH_URG|TH_EOL|TH_FIN)) { 605*4803Swnj if (thflags&TH_URG) { 606*4803Swnj unsigned urgent; 607*4803Swnj 608*4803Swnj urgent = n->t_urp + n->t_seq; 609*4803Swnj if (tp->rcv_nxt < urgent) { 610*4803Swnj if (tp->rcv_urp <= tp->rcv_nxt) { 611*4803Swnj /* DO SOMETHING WITH URGENT!!! ### */ 612*4803Swnj } 613*4803Swnj tp->rcv_urp = urgent; 614*4803Swnj } 6154679Swnj } 6164679Swnj /* eol */ 617*4803Swnj if ((thflags&TH_EOL) && 618*4803Swnj (tp->tc_flags&TC_DROPPED_TXT) == 0 && 619*4803Swnj tp->tcb_hd.seg_prev != (struct th *)tp) { 620*4803Swnj /* mark last mbuf */ 621*4803Swnj m = dtom(tp->tcb_hd.seg_prev); 622*4803Swnj if (m != NULL) { 623*4803Swnj while (m->m_next != NULL) 624*4803Swnj m = m->m_next; 625*4803Swnj m->m_act = 626*4803Swnj (struct mbuf *)(m->m_off + m->m_len - 1); 627*4803Swnj } 6284679Swnj } 6294679Swnj ctlonly: 6304679Swnj /* fin */ 631*4803Swnj if ((thflags&TH_FIN) && 632*4803Swnj (tp->tc_flags&TC_DROPPED_TXT) == 0) { 633*4803Swnj seq_t last; 6344679Swnj 635*4803Swnj if ((tp->tc_flags&TC_FIN_RCVD) == 0) { 636*4803Swnj /* do we really have fin ? */ 637*4803Swnj last = firstempty(tp); 638*4803Swnj if (tp->tcb_hd.seg_prev == (struct th *)tp || 639*4803Swnj last == t_end(tp->tcb_hd.seg_prev)) { 640*4803Swnj tp->tc_flags |= TC_FIN_RCVD; 641*4803Swnj sowakeup(tp->t_socket); /* ### */ 642*4803Swnj } 643*4803Swnj if ((tp->tc_flags&TC_FIN_RCVD) && 644*4803Swnj tp->rcv_nxt >= last) { 645*4803Swnj tp->rcv_nxt = last + 1; 646*4803Swnj tp->tc_flags |= TC_ACK_DUE; 647*4803Swnj } 648*4803Swnj } else 6494679Swnj tp->tc_flags |= TC_ACK_DUE; 650*4803Swnj } 6514679Swnj } 6524679Swnj /* respond */ 6534679Swnj sent = 0; 6544679Swnj if (tp->tc_flags&TC_ACK_DUE) 6554679Swnj sent = tcp_sndctl(tp); 656*4803Swnj else if ((tp->tc_flags&TC_NEW_WINDOW)) 657*4803Swnj if (tp->snd_nxt <= tp->snd_off + tp->t_socket->so_snd.sb_cc || 658*4803Swnj (tp->tc_flags&TC_SND_FIN)) 6594679Swnj sent = tcp_send(tp); 6604679Swnj 6614679Swnj /* set for retrans */ 6624679Swnj if (!sent && tp->snd_una < tp->snd_nxt && 6634679Swnj (tp->tc_flags&TC_CANCELLED)) { 6644679Swnj tp->t_rexmt = tp->t_xmtime; 6654679Swnj tp->t_rexmttl = T_REXMTTL; 6664679Swnj tp->t_rexmt_val = tp->t_rtl_val = tp->snd_lst; 6674679Swnj tp->tc_flags &= ~TC_CANCELLED; 6684679Swnj } 6694690Swnj /* present data to user */ 6704690Swnj { register struct mbuf **mp; 671*4803Swnj register struct socket *so = tp->t_socket; 6724690Swnj seq_t ready; 6734601Swnj 6744601Swnj /* connection must be synced and data available for user */ 6754656Swnj if ((tp->tc_flags&TC_SYN_ACKED) == 0) 6764601Swnj return; 677*4803Swnj so = tp->t_socket; 678*4803Swnj mp = &so->so_rcv.sb_mb; 6794601Swnj while (*mp) 6804601Swnj mp = &(*mp)->m_next; 681*4803Swnj n = tp->tcb_hd.seg_next; 6824656Swnj /* SHOULD PACK DATA IN HERE */ 6834690Swnj while (n != (struct th *)tp && n->t_seq < tp->rcv_nxt) { 6844690Swnj remque(n); 6854690Swnj m = dtom(n); 686*4803Swnj so->so_rcv.sb_cc += n->t_len; 6874690Swnj tp->seqcnt -= n->t_len; 6884656Swnj if (tp->seqcnt < 0) panic("present_data"); 6894690Swnj n = n->t_next; 6904601Swnj while (m) { 6914601Swnj if (m->m_len == 0) { 6924692Swnj MFREE(m, *mp); 6934692Swnj } else { 6944692Swnj *mp = m; 6954692Swnj mp = &m->m_next; 6964601Swnj } 6974601Swnj m = *mp; 6984601Swnj } 6994601Swnj } 700*4803Swnj sowakeup(so); /* should be macro/conditional */ 7014690Swnj } 7024601Swnj } 703*4803Swnj 704*4803Swnj tcp_drain() 705*4803Swnj { 706*4803Swnj 707*4803Swnj } 708