diff options
author | dfr <dfr@FreeBSD.org> | 1998-08-24 07:47:39 +0000 |
---|---|---|
committer | dfr <dfr@FreeBSD.org> | 1998-08-24 07:47:39 +0000 |
commit | b9492066e97d868408f504260ae6be723843e4e8 (patch) | |
tree | 39418968d5099f5b89b07632470056fe32935ec1 /sys/netinet | |
parent | 91d93c9726bff72d58cdc4eab23a032d9f461681 (diff) | |
download | FreeBSD-src-b9492066e97d868408f504260ae6be723843e4e8.zip FreeBSD-src-b9492066e97d868408f504260ae6be723843e4e8.tar.gz |
Re-implement tcp and ip fragment reassembly to not store pointers in the
ip header which can't work on alpha since pointers are too big.
Reviewed by: Garrett Wollman <wollman@khavrinen.lcs.mit.edu>
Diffstat (limited to 'sys/netinet')
-rw-r--r-- | sys/netinet/ip_input.c | 170 | ||||
-rw-r--r-- | sys/netinet/ip_var.h | 35 | ||||
-rw-r--r-- | sys/netinet/tcp_input.c | 87 | ||||
-rw-r--r-- | sys/netinet/tcp_reass.c | 87 | ||||
-rw-r--r-- | sys/netinet/tcp_subr.c | 27 | ||||
-rw-r--r-- | sys/netinet/tcp_timewait.c | 27 | ||||
-rw-r--r-- | sys/netinet/tcp_var.h | 15 | ||||
-rw-r--r-- | sys/netinet/udp_usrreq.c | 9 |
8 files changed, 210 insertions, 247 deletions
diff --git a/sys/netinet/ip_input.c b/sys/netinet/ip_input.c index 4527c08..ed54c71 100644 --- a/sys/netinet/ip_input.c +++ b/sys/netinet/ip_input.c @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * @(#)ip_input.c 8.2 (Berkeley) 1/4/94 - * $Id: ip_input.c,v 1.98 1998/08/17 01:05:24 bde Exp $ + * $Id: ip_input.c,v 1.99 1998/08/23 03:07:14 wollman Exp $ * $ANA: ip_input.c,v 1.5 1996/09/18 14:34:59 wollman Exp $ */ @@ -187,13 +187,11 @@ static u_short frag_divert_port; struct sockaddr_in *ip_fw_fwd_addr; static void save_rte __P((u_char *, struct in_addr)); -static void ip_deq __P((struct ipasfrag *)); static int ip_dooptions __P((struct mbuf *)); -static void ip_enq __P((struct ipasfrag *, struct ipasfrag *)); static void ip_forward __P((struct mbuf *, int)); static void ip_freef __P((struct ipq *)); static struct ip * - ip_reass __P((struct ipasfrag *, struct ipq *, struct ipq *)); + ip_reass __P((struct mbuf *, struct ipq *, struct ipq *)); static struct in_ifaddr * ip_rtaddr __P((struct in_addr)); static void ipintr __P((void)); @@ -250,8 +248,9 @@ ip_input(struct mbuf *m) { struct ip *ip; struct ipq *fp; + struct ipqent *ipqe; struct in_ifaddr *ia; - int i, hlen; + int i, hlen, mff; u_short sum; #ifdef DIAGNOSTIC @@ -564,9 +563,18 @@ found: * convert offset of this to bytes. */ ip->ip_len -= hlen; - ((struct ipasfrag *)ip)->ipf_mff &= ~1; - if (ip->ip_off & IP_MF) - ((struct ipasfrag *)ip)->ipf_mff |= 1; + mff = (ip->ip_off & IP_MF) != 0; + if (mff) { + /* + * Make sure that fragments have a data length + * that's a non-zero multiple of 8 bytes. + */ + if (ip->ip_len == 0 || (ip->ip_len & 0x7) != 0) { + ipstat.ips_toosmall++; /* XXX */ + goto bad; + } + m->m_flags |= M_FRAG; + } ip->ip_off <<= 3; /* @@ -574,9 +582,10 @@ found: * or if this is not the first fragment, * attempt reassembly; if it succeeds, proceed. */ - if (((struct ipasfrag *)ip)->ipf_mff & 1 || ip->ip_off) { + if (mff || ip->ip_off) { ipstat.ips_fragments++; - ip = ip_reass((struct ipasfrag *)ip, fp, &ipq[sum]); + m->m_pkthdr.header = ip; + ip = ip_reass(m, fp, &ipq[sum]); if (ip == 0) { #ifdef IPFIREWALL_FORWARD ip_fw_fwd_addr = NULL; @@ -673,15 +682,15 @@ NETISR_SET(NETISR_IP, ipintr); * is given as fp; otherwise have to make a chain. */ static struct ip * -ip_reass(ip, fp, where) - register struct ipasfrag *ip; +ip_reass(m, fp, where) + register struct mbuf *m; register struct ipq *fp; struct ipq *where; { - register struct mbuf *m = dtom(ip); - register struct ipasfrag *q; + struct ip *ip = mtod(m, struct ip *); + register struct mbuf *p = 0, *q, *nq; struct mbuf *t; - int hlen = ip->ip_hl << 2; + int hlen = IP_VHL_HL(ip->ip_vhl) << 2; int i, next; /* @@ -703,22 +712,24 @@ ip_reass(ip, fp, where) fp->ipq_ttl = IPFRAGTTL; fp->ipq_p = ip->ip_p; fp->ipq_id = ip->ip_id; - fp->ipq_next = fp->ipq_prev = (struct ipasfrag *)fp; - fp->ipq_src = ((struct ip *)ip)->ip_src; - fp->ipq_dst = ((struct ip *)ip)->ip_dst; + fp->ipq_src = ip->ip_src; + fp->ipq_dst = ip->ip_dst; + fp->ipq_frags = 0; #ifdef IPDIVERT fp->ipq_divert = 0; fp->ipq_div_cookie = 0; #endif - q = (struct ipasfrag *)fp; + q = 0; goto insert; } +#define GETIP(m) ((struct ip*)((m)->m_pkthdr.header)) + /* * Find a segment which begins after this one does. */ - for (q = fp->ipq_next; q != (struct ipasfrag *)fp; q = q->ipf_next) - if (q->ip_off > ip->ip_off) + for (p = NULL, q = fp->ipq_frags; q; p = q, q = q->m_nextpkt) + if (GETIP(q)->ip_off > ip->ip_off) break; /* @@ -726,8 +737,8 @@ ip_reass(ip, fp, where) * our data already. If so, drop the data from the incoming * segment. If it provides all of our data, drop us. */ - if (q->ipf_prev != (struct ipasfrag *)fp) { - i = q->ipf_prev->ip_off + q->ipf_prev->ip_len - ip->ip_off; + if (p) { + i = GETIP(p)->ip_off + GETIP(p)->ip_len - ip->ip_off; if (i > 0) { if (i >= ip->ip_len) goto dropfrag; @@ -741,21 +752,22 @@ ip_reass(ip, fp, where) * While we overlap succeeding segments trim them or, * if they are completely covered, dequeue them. */ - while (q != (struct ipasfrag *)fp && - ip->ip_off + ip->ip_len > q->ip_off) { - struct mbuf *m0; - - i = (ip->ip_off + ip->ip_len) - q->ip_off; - if (i < q->ip_len) { - q->ip_len -= i; - q->ip_off += i; - m_adj(dtom(q), i); + for (; q != NULL && ip->ip_off + ip->ip_len > GETIP(q)->ip_off; + p = q, q = nq) { + i = (ip->ip_off + ip->ip_len) - + GETIP(q)->ip_off; + if (i < GETIP(q)->ip_len) { + GETIP(q)->ip_len -= i; + GETIP(q)->ip_off += i; + m_adj(q, i); break; } - m0 = dtom(q); - q = q->ipf_next; - ip_deq(q->ipf_prev); - m_freem(m0); + nq = q->m_nextpkt; + if (p) + p->m_nextpkt = nq; + else + fp->ipq_frags = nq; + m_freem(q); } insert: @@ -776,21 +788,29 @@ insert: * Stick new segment in its place; * check for complete reassembly. */ - ip_enq(ip, q->ipf_prev); + if (p == NULL) { + m->m_nextpkt = fp->ipq_frags; + fp->ipq_frags = m; + } else { + m->m_nextpkt = p->m_nextpkt; + p->m_nextpkt = m; + } next = 0; - for (q = fp->ipq_next; q != (struct ipasfrag *)fp; q = q->ipf_next) { - if (q->ip_off != next) + for (p = NULL, q = fp->ipq_frags; q; p = q, q = q->m_nextpkt) { + if (GETIP(q)->ip_off != next) return (0); - next += q->ip_len; + next += GETIP(q)->ip_len; } - if (q->ipf_prev->ipf_mff & 1) + /* Make sure the last packet didn't have the IP_MF flag */ + if (p->m_flags & M_FRAG) return (0); /* * Reassembly is complete. Make sure the packet is a sane size. */ - if (next + (IP_VHL_HL(((struct ip *)fp->ipq_next)->ip_vhl) << 2) - > IP_MAXPACKET) { + q = fp->ipq_frags; + ip = GETIP(q); + if (next + (IP_VHL_HL(ip->ip_vhl) << 2) > IP_MAXPACKET) { ipstat.ips_toolong++; ip_freef(fp); return (0); @@ -799,16 +819,14 @@ insert: /* * Concatenate fragments. */ - q = fp->ipq_next; - m = dtom(q); + m = q; t = m->m_next; m->m_next = 0; m_cat(m, t); - q = q->ipf_next; - while (q != (struct ipasfrag *)fp) { - t = dtom(q); - q = q->ipf_next; - m_cat(m, t); + nq = q->m_nextpkt; + for (q = nq; q != NULL; q = nq) { + nq = q->m_nextpkt; + m_cat(m, q); } #ifdef IPDIVERT @@ -825,17 +843,14 @@ insert: * dequeue and discard fragment reassembly header. * Make header visible. */ - ip = fp->ipq_next; ip->ip_len = next; - ip->ipf_mff &= ~1; - ((struct ip *)ip)->ip_src = fp->ipq_src; - ((struct ip *)ip)->ip_dst = fp->ipq_dst; + ip->ip_src = fp->ipq_src; + ip->ip_dst = fp->ipq_dst; remque(fp); nipq--; (void) m_free(dtom(fp)); - m = dtom(ip); - m->m_len += (ip->ip_hl << 2); - m->m_data -= (ip->ip_hl << 2); + m->m_len += (IP_VHL_HL(ip->ip_vhl) << 2); + m->m_data -= (IP_VHL_HL(ip->ip_vhl) << 2); /* some debugging cruft by sklower, below, will go away soon */ if (m->m_flags & M_PKTHDR) { /* XXX this should be done elsewhere */ register int plen = 0; @@ -843,7 +858,7 @@ insert: plen += m->m_len; t->m_pkthdr.len = plen; } - return ((struct ip *)ip); + return (ip); dropfrag: #ifdef IPDIVERT @@ -853,6 +868,8 @@ dropfrag: ipstat.ips_fragdropped++; m_freem(m); return (0); + +#undef GETIP } /* @@ -863,12 +880,12 @@ static void ip_freef(fp) struct ipq *fp; { - register struct ipasfrag *q, *p; + register struct mbuf *q; - for (q = fp->ipq_next; q != (struct ipasfrag *)fp; q = p) { - p = q->ipf_next; - ip_deq(q); - m_freem(dtom(q)); + while (fp->ipq_frags) { + q = fp->ipq_frags; + fp->ipq_frags = q->m_nextpkt; + m_freem(q); } remque(fp); (void) m_free(dtom(fp)); @@ -876,33 +893,6 @@ ip_freef(fp) } /* - * Put an ip fragment on a reassembly chain. - * Like insque, but pointers in middle of structure. - */ -static void -ip_enq(p, prev) - register struct ipasfrag *p, *prev; -{ - - p->ipf_prev = prev; - p->ipf_next = prev->ipf_next; - prev->ipf_next->ipf_prev = p; - prev->ipf_next = p; -} - -/* - * To ip_enq as remque is to insque. - */ -static void -ip_deq(p) - register struct ipasfrag *p; -{ - - p->ipf_prev->ipf_next = p->ipf_next; - p->ipf_next->ipf_prev = p->ipf_prev; -} - -/* * IP timer processing; * if a timer expires on a reassembly * queue, discard it. diff --git a/sys/netinet/ip_var.h b/sys/netinet/ip_var.h index 16e66fc..1de2664 100644 --- a/sys/netinet/ip_var.h +++ b/sys/netinet/ip_var.h @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * @(#)ip_var.h 8.2 (Berkeley) 1/9/95 - * $Id: ip_var.h,v 1.43 1998/07/13 12:20:07 bde Exp $ + * $Id: ip_var.h,v 1.44 1998/08/23 03:07:14 wollman Exp $ */ #ifndef _NETINET_IP_VAR_H_ @@ -41,8 +41,7 @@ * Overlay for ip header used by other protocols (tcp, udp). */ struct ipovly { - caddr_t ih_next, ih_prev; /* for protocol sequence q's */ - u_char ih_x1; /* (unused) */ + u_char ih_x1[9]; /* (unused) */ u_char ih_pr; /* protocol */ u_short ih_len; /* protocol length */ struct in_addr ih_src; /* source internet address */ @@ -60,8 +59,7 @@ struct ipq { u_char ipq_ttl; /* time for reass q to live */ u_char ipq_p; /* protocol of this fragment */ u_short ipq_id; /* sequence id for reassembly */ - struct ipasfrag *ipq_next,*ipq_prev; - /* to ip headers of fragments */ + struct mbuf *ipq_frags; /* to ip headers of fragments */ struct in_addr ipq_src,ipq_dst; #ifdef IPDIVERT u_short ipq_divert; /* divert protocol port */ @@ -70,33 +68,6 @@ struct ipq { }; /* - * Ip header, when holding a fragment. - * - * Note: ipf_next must be at same offset as ipq_next above - */ -struct ipasfrag { -#if BYTE_ORDER == LITTLE_ENDIAN - u_int ip_hl:4, - ip_v:4; -#endif -#if BYTE_ORDER == BIG_ENDIAN - u_int ip_v:4, - ip_hl:4; -#endif - u_char ipf_mff; /* XXX overlays ip_tos: use low bit - * to avoid destroying tos; - * copied from (ip_off&IP_MF) */ - u_short ip_len; - u_short ip_id; - u_short ip_off; - u_char ip_ttl; - u_char ip_p; - u_short ip_sum; - struct ipasfrag *ipf_next; /* next fragment */ - struct ipasfrag *ipf_prev; /* previous fragment */ -}; - -/* * Structure stored in mbuf in inpcb.ip_options * and passed to ip_output when ip options are in use. * The actual length of the options (including ipopt_dst) diff --git a/sys/netinet/tcp_input.c b/sys/netinet/tcp_input.c index 75aef2a..16eb79b 100644 --- a/sys/netinet/tcp_input.c +++ b/sys/netinet/tcp_input.c @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * @(#)tcp_input.c 8.12 (Berkeley) 5/24/95 - * $Id: tcp_input.c,v 1.78 1998/05/31 18:42:49 peter Exp $ + * $Id: tcp_input.c,v 1.79 1998/07/06 03:20:19 julian Exp $ */ #include "opt_ipfw.h" /* for ipfw_fwd */ @@ -110,7 +110,7 @@ static void tcp_xmit_timer __P((struct tcpcb *, int)); */ #define TCP_REASS(tp, ti, m, so, flags) { \ if ((ti)->ti_seq == (tp)->rcv_nxt && \ - (tp)->seg_next == (struct tcpiphdr *)(tp) && \ + (tp)->t_segq == NULL && \ (tp)->t_state == TCPS_ESTABLISHED) { \ if (tcp_delack_enabled) \ tp->t_flags |= TF_DELACK; \ @@ -134,10 +134,14 @@ tcp_reass(tp, ti, m) register struct tcpiphdr *ti; struct mbuf *m; { - register struct tcpiphdr *q; + struct mbuf *q; + struct mbuf *p; + struct mbuf *nq; struct socket *so = tp->t_inpcb->inp_socket; int flags; +#define GETTCP(m) ((struct tcpiphdr *)m->m_pkthdr.header) + /* * Call with ti==0 after become established to * force pre-ESTABLISHED data up to user socket. @@ -145,12 +149,13 @@ tcp_reass(tp, ti, m) if (ti == 0) goto present; + m->m_pkthdr.header = ti; + /* * Find a segment which begins after this one does. */ - for (q = tp->seg_next; q != (struct tcpiphdr *)tp; - q = (struct tcpiphdr *)q->ti_next) - if (SEQ_GT(q->ti_seq, ti->ti_seq)) + for (q = tp->t_segq, p = NULL; q; p = q, q = q->m_nextpkt) + if (SEQ_GT(GETTCP(q)->ti_seq, ti->ti_seq)) break; /* @@ -158,11 +163,10 @@ tcp_reass(tp, ti, m) * our data already. If so, drop the data from the incoming * segment. If it provides all of our data, drop us. */ - if ((struct tcpiphdr *)q->ti_prev != (struct tcpiphdr *)tp) { + if (p != NULL) { register int i; - q = (struct tcpiphdr *)q->ti_prev; /* conversion to int (in i) handles seq wraparound */ - i = q->ti_seq + q->ti_len - ti->ti_seq; + i = GETTCP(p)->ti_seq + GETTCP(p)->ti_len - ti->ti_seq; if (i > 0) { if (i >= ti->ti_len) { tcpstat.tcps_rcvduppack++; @@ -180,36 +184,41 @@ tcp_reass(tp, ti, m) ti->ti_len -= i; ti->ti_seq += i; } - q = (struct tcpiphdr *)(q->ti_next); } tcpstat.tcps_rcvoopack++; tcpstat.tcps_rcvoobyte += ti->ti_len; - REASS_MBUF(ti) = m; /* XXX */ /* * While we overlap succeeding segments trim them or, * if they are completely covered, dequeue them. */ - while (q != (struct tcpiphdr *)tp) { - register int i = (ti->ti_seq + ti->ti_len) - q->ti_seq; + while (q) { + register int i = (ti->ti_seq + ti->ti_len) - GETTCP(q)->ti_seq; if (i <= 0) break; - if (i < q->ti_len) { - q->ti_seq += i; - q->ti_len -= i; - m_adj(REASS_MBUF(q), i); + if (i < GETTCP(q)->ti_len) { + GETTCP(q)->ti_seq += i; + GETTCP(q)->ti_len -= i; + m_adj(q, i); break; } - q = (struct tcpiphdr *)q->ti_next; - m = REASS_MBUF((struct tcpiphdr *)q->ti_prev); - remque(q->ti_prev); - m_freem(m); + + nq = q->m_nextpkt; + if (p) + p->m_nextpkt = nq; + else + tp->t_segq = nq; + m_freem(q); + q = nq; } - /* - * Stick new segment in its place. - */ - insque(ti, q->ti_prev); + if (p == NULL) { + m->m_nextpkt = tp->t_segq; + tp->t_segq = m; + } else { + m->m_nextpkt = p->m_nextpkt; + p->m_nextpkt = m; + } present: /* @@ -218,22 +227,25 @@ present: */ if (!TCPS_HAVEESTABLISHED(tp->t_state)) return (0); - ti = tp->seg_next; - if (ti == (struct tcpiphdr *)tp || ti->ti_seq != tp->rcv_nxt) + q = tp->t_segq; + if (!q || GETTCP(q)->ti_seq != tp->rcv_nxt) return (0); do { - tp->rcv_nxt += ti->ti_len; - flags = ti->ti_flags & TH_FIN; - remque(ti); - m = REASS_MBUF(ti); - ti = (struct tcpiphdr *)ti->ti_next; + tp->rcv_nxt += GETTCP(q)->ti_len; + flags = GETTCP(q)->ti_flags & TH_FIN; + nq = q->m_nextpkt; + tp->t_segq = nq; + q->m_nextpkt = NULL; if (so->so_state & SS_CANTRCVMORE) - m_freem(m); + m_freem(q); else - sbappend(&so->so_rcv, m); - } while (ti != (struct tcpiphdr *)tp && ti->ti_seq == tp->rcv_nxt); + sbappend(&so->so_rcv, q); + q = nq; + } while (q && GETTCP(q)->ti_seq == tp->rcv_nxt); sorwakeup(so); return (flags); + +#undef GETTCP } /* @@ -288,8 +300,7 @@ tcp_input(m, iphlen) */ tlen = ((struct ip *)ti)->ip_len; len = sizeof (struct ip) + tlen; - ti->ti_next = ti->ti_prev = 0; - ti->ti_x1 = 0; + bzero(ti->ti_x1, sizeof(ti->ti_x1)); ti->ti_len = (u_short)tlen; HTONS(ti->ti_len); ti->ti_sum = in_cksum(m, len); @@ -572,7 +583,7 @@ findpcb: return; } } else if (ti->ti_ack == tp->snd_una && - tp->seg_next == (struct tcpiphdr *)tp && + tp->t_segq == NULL && ti->ti_len <= sbspace(&so->so_rcv)) { /* * this is a pure, in-sequence data packet diff --git a/sys/netinet/tcp_reass.c b/sys/netinet/tcp_reass.c index 75aef2a..16eb79b 100644 --- a/sys/netinet/tcp_reass.c +++ b/sys/netinet/tcp_reass.c @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * @(#)tcp_input.c 8.12 (Berkeley) 5/24/95 - * $Id: tcp_input.c,v 1.78 1998/05/31 18:42:49 peter Exp $ + * $Id: tcp_input.c,v 1.79 1998/07/06 03:20:19 julian Exp $ */ #include "opt_ipfw.h" /* for ipfw_fwd */ @@ -110,7 +110,7 @@ static void tcp_xmit_timer __P((struct tcpcb *, int)); */ #define TCP_REASS(tp, ti, m, so, flags) { \ if ((ti)->ti_seq == (tp)->rcv_nxt && \ - (tp)->seg_next == (struct tcpiphdr *)(tp) && \ + (tp)->t_segq == NULL && \ (tp)->t_state == TCPS_ESTABLISHED) { \ if (tcp_delack_enabled) \ tp->t_flags |= TF_DELACK; \ @@ -134,10 +134,14 @@ tcp_reass(tp, ti, m) register struct tcpiphdr *ti; struct mbuf *m; { - register struct tcpiphdr *q; + struct mbuf *q; + struct mbuf *p; + struct mbuf *nq; struct socket *so = tp->t_inpcb->inp_socket; int flags; +#define GETTCP(m) ((struct tcpiphdr *)m->m_pkthdr.header) + /* * Call with ti==0 after become established to * force pre-ESTABLISHED data up to user socket. @@ -145,12 +149,13 @@ tcp_reass(tp, ti, m) if (ti == 0) goto present; + m->m_pkthdr.header = ti; + /* * Find a segment which begins after this one does. */ - for (q = tp->seg_next; q != (struct tcpiphdr *)tp; - q = (struct tcpiphdr *)q->ti_next) - if (SEQ_GT(q->ti_seq, ti->ti_seq)) + for (q = tp->t_segq, p = NULL; q; p = q, q = q->m_nextpkt) + if (SEQ_GT(GETTCP(q)->ti_seq, ti->ti_seq)) break; /* @@ -158,11 +163,10 @@ tcp_reass(tp, ti, m) * our data already. If so, drop the data from the incoming * segment. If it provides all of our data, drop us. */ - if ((struct tcpiphdr *)q->ti_prev != (struct tcpiphdr *)tp) { + if (p != NULL) { register int i; - q = (struct tcpiphdr *)q->ti_prev; /* conversion to int (in i) handles seq wraparound */ - i = q->ti_seq + q->ti_len - ti->ti_seq; + i = GETTCP(p)->ti_seq + GETTCP(p)->ti_len - ti->ti_seq; if (i > 0) { if (i >= ti->ti_len) { tcpstat.tcps_rcvduppack++; @@ -180,36 +184,41 @@ tcp_reass(tp, ti, m) ti->ti_len -= i; ti->ti_seq += i; } - q = (struct tcpiphdr *)(q->ti_next); } tcpstat.tcps_rcvoopack++; tcpstat.tcps_rcvoobyte += ti->ti_len; - REASS_MBUF(ti) = m; /* XXX */ /* * While we overlap succeeding segments trim them or, * if they are completely covered, dequeue them. */ - while (q != (struct tcpiphdr *)tp) { - register int i = (ti->ti_seq + ti->ti_len) - q->ti_seq; + while (q) { + register int i = (ti->ti_seq + ti->ti_len) - GETTCP(q)->ti_seq; if (i <= 0) break; - if (i < q->ti_len) { - q->ti_seq += i; - q->ti_len -= i; - m_adj(REASS_MBUF(q), i); + if (i < GETTCP(q)->ti_len) { + GETTCP(q)->ti_seq += i; + GETTCP(q)->ti_len -= i; + m_adj(q, i); break; } - q = (struct tcpiphdr *)q->ti_next; - m = REASS_MBUF((struct tcpiphdr *)q->ti_prev); - remque(q->ti_prev); - m_freem(m); + + nq = q->m_nextpkt; + if (p) + p->m_nextpkt = nq; + else + tp->t_segq = nq; + m_freem(q); + q = nq; } - /* - * Stick new segment in its place. - */ - insque(ti, q->ti_prev); + if (p == NULL) { + m->m_nextpkt = tp->t_segq; + tp->t_segq = m; + } else { + m->m_nextpkt = p->m_nextpkt; + p->m_nextpkt = m; + } present: /* @@ -218,22 +227,25 @@ present: */ if (!TCPS_HAVEESTABLISHED(tp->t_state)) return (0); - ti = tp->seg_next; - if (ti == (struct tcpiphdr *)tp || ti->ti_seq != tp->rcv_nxt) + q = tp->t_segq; + if (!q || GETTCP(q)->ti_seq != tp->rcv_nxt) return (0); do { - tp->rcv_nxt += ti->ti_len; - flags = ti->ti_flags & TH_FIN; - remque(ti); - m = REASS_MBUF(ti); - ti = (struct tcpiphdr *)ti->ti_next; + tp->rcv_nxt += GETTCP(q)->ti_len; + flags = GETTCP(q)->ti_flags & TH_FIN; + nq = q->m_nextpkt; + tp->t_segq = nq; + q->m_nextpkt = NULL; if (so->so_state & SS_CANTRCVMORE) - m_freem(m); + m_freem(q); else - sbappend(&so->so_rcv, m); - } while (ti != (struct tcpiphdr *)tp && ti->ti_seq == tp->rcv_nxt); + sbappend(&so->so_rcv, q); + q = nq; + } while (q && GETTCP(q)->ti_seq == tp->rcv_nxt); sorwakeup(so); return (flags); + +#undef GETTCP } /* @@ -288,8 +300,7 @@ tcp_input(m, iphlen) */ tlen = ((struct ip *)ti)->ip_len; len = sizeof (struct ip) + tlen; - ti->ti_next = ti->ti_prev = 0; - ti->ti_x1 = 0; + bzero(ti->ti_x1, sizeof(ti->ti_x1)); ti->ti_len = (u_short)tlen; HTONS(ti->ti_len); ti->ti_sum = in_cksum(m, len); @@ -572,7 +583,7 @@ findpcb: return; } } else if (ti->ti_ack == tp->snd_una && - tp->seg_next == (struct tcpiphdr *)tp && + tp->t_segq == NULL && ti->ti_len <= sbspace(&so->so_rcv)) { /* * this is a pure, in-sequence data packet diff --git a/sys/netinet/tcp_subr.c b/sys/netinet/tcp_subr.c index 43139ca..74c630b 100644 --- a/sys/netinet/tcp_subr.c +++ b/sys/netinet/tcp_subr.c @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * @(#)tcp_subr.c 8.2 (Berkeley) 5/24/95 - * $Id: tcp_subr.c,v 1.44 1998/03/28 10:18:24 bde Exp $ + * $Id: tcp_subr.c,v 1.45 1998/05/15 20:11:35 wollman Exp $ */ #include "opt_compat.h" @@ -162,8 +162,7 @@ tcp_template(tp) m->m_len = sizeof (struct tcpiphdr); n = mtod(m, struct tcpiphdr *); } - n->ti_next = n->ti_prev = 0; - n->ti_x1 = 0; + bzero(n->ti_x1, sizeof(n->ti_x1)); n->ti_pr = IPPROTO_TCP; n->ti_len = htons(sizeof (struct tcpiphdr) - sizeof (struct ip)); n->ti_src = inp->inp_laddr; @@ -236,8 +235,8 @@ tcp_respond(tp, ti, m, ack, seq, flags) m->m_len = sizeof (struct tcpiphdr); tlen = 0; #define xchg(a,b,type) { type t; t=a; a=b; b=t; } - xchg(ti->ti_dst.s_addr, ti->ti_src.s_addr, u_long); - xchg(ti->ti_dport, ti->ti_sport, u_short); + xchg(ti->ti_dst.s_addr, ti->ti_src.s_addr, n_long); + xchg(ti->ti_dport, ti->ti_sport, n_short); #undef xchg } ti->ti_len = htons((u_short)(sizeof (struct tcphdr) + tlen)); @@ -245,8 +244,7 @@ tcp_respond(tp, ti, m, ack, seq, flags) m->m_len = tlen; m->m_pkthdr.len = tlen; m->m_pkthdr.rcvif = (struct ifnet *) 0; - ti->ti_next = ti->ti_prev = 0; - ti->ti_x1 = 0; + bzero(ti->ti_x1, sizeof(ti->ti_x1)); ti->ti_seq = htonl(seq); ti->ti_ack = htonl(ack); ti->ti_x2 = 0; @@ -287,7 +285,7 @@ tcp_newtcpcb(inp) it = (struct inp_tp *)inp; tp = &it->tcb; bzero((char *) tp, sizeof(struct tcpcb)); - tp->seg_next = tp->seg_prev = (struct tcpiphdr *)tp; + tp->t_segq = NULL; tp->t_maxseg = tp->t_maxopd = tcp_mssdflt; if (tcp_do_rfc1323) @@ -345,7 +343,8 @@ struct tcpcb * tcp_close(tp) register struct tcpcb *tp; { - register struct tcpiphdr *t; + register struct mbuf *q; + register struct mbuf *nq; struct inpcb *inp = tp->t_inpcb; struct socket *so = inp->inp_socket; register struct mbuf *m; @@ -433,12 +432,10 @@ tcp_close(tp) } } /* free the reassembly queue, if any */ - t = tp->seg_next; - while (t != (struct tcpiphdr *)tp) { - t = (struct tcpiphdr *)t->ti_next; - m = REASS_MBUF((struct tcpiphdr *)t->ti_prev); - remque(t->ti_prev); - m_freem(m); + for (q = tp->t_segq; q; q = nq) { + nq = q->m_nextpkt; + tp->t_segq = nq; + m_freem(q); } if (tp->t_template) (void) m_free(dtom(tp->t_template)); diff --git a/sys/netinet/tcp_timewait.c b/sys/netinet/tcp_timewait.c index 43139ca..74c630b 100644 --- a/sys/netinet/tcp_timewait.c +++ b/sys/netinet/tcp_timewait.c @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * @(#)tcp_subr.c 8.2 (Berkeley) 5/24/95 - * $Id: tcp_subr.c,v 1.44 1998/03/28 10:18:24 bde Exp $ + * $Id: tcp_subr.c,v 1.45 1998/05/15 20:11:35 wollman Exp $ */ #include "opt_compat.h" @@ -162,8 +162,7 @@ tcp_template(tp) m->m_len = sizeof (struct tcpiphdr); n = mtod(m, struct tcpiphdr *); } - n->ti_next = n->ti_prev = 0; - n->ti_x1 = 0; + bzero(n->ti_x1, sizeof(n->ti_x1)); n->ti_pr = IPPROTO_TCP; n->ti_len = htons(sizeof (struct tcpiphdr) - sizeof (struct ip)); n->ti_src = inp->inp_laddr; @@ -236,8 +235,8 @@ tcp_respond(tp, ti, m, ack, seq, flags) m->m_len = sizeof (struct tcpiphdr); tlen = 0; #define xchg(a,b,type) { type t; t=a; a=b; b=t; } - xchg(ti->ti_dst.s_addr, ti->ti_src.s_addr, u_long); - xchg(ti->ti_dport, ti->ti_sport, u_short); + xchg(ti->ti_dst.s_addr, ti->ti_src.s_addr, n_long); + xchg(ti->ti_dport, ti->ti_sport, n_short); #undef xchg } ti->ti_len = htons((u_short)(sizeof (struct tcphdr) + tlen)); @@ -245,8 +244,7 @@ tcp_respond(tp, ti, m, ack, seq, flags) m->m_len = tlen; m->m_pkthdr.len = tlen; m->m_pkthdr.rcvif = (struct ifnet *) 0; - ti->ti_next = ti->ti_prev = 0; - ti->ti_x1 = 0; + bzero(ti->ti_x1, sizeof(ti->ti_x1)); ti->ti_seq = htonl(seq); ti->ti_ack = htonl(ack); ti->ti_x2 = 0; @@ -287,7 +285,7 @@ tcp_newtcpcb(inp) it = (struct inp_tp *)inp; tp = &it->tcb; bzero((char *) tp, sizeof(struct tcpcb)); - tp->seg_next = tp->seg_prev = (struct tcpiphdr *)tp; + tp->t_segq = NULL; tp->t_maxseg = tp->t_maxopd = tcp_mssdflt; if (tcp_do_rfc1323) @@ -345,7 +343,8 @@ struct tcpcb * tcp_close(tp) register struct tcpcb *tp; { - register struct tcpiphdr *t; + register struct mbuf *q; + register struct mbuf *nq; struct inpcb *inp = tp->t_inpcb; struct socket *so = inp->inp_socket; register struct mbuf *m; @@ -433,12 +432,10 @@ tcp_close(tp) } } /* free the reassembly queue, if any */ - t = tp->seg_next; - while (t != (struct tcpiphdr *)tp) { - t = (struct tcpiphdr *)t->ti_next; - m = REASS_MBUF((struct tcpiphdr *)t->ti_prev); - remque(t->ti_prev); - m_freem(m); + for (q = tp->t_segq; q; q = nq) { + nq = q->m_nextpkt; + tp->t_segq = nq; + m_freem(q); } if (tp->t_template) (void) m_free(dtom(tp->t_template)); diff --git a/sys/netinet/tcp_var.h b/sys/netinet/tcp_var.h index 15291c2..4e8d88c 100644 --- a/sys/netinet/tcp_var.h +++ b/sys/netinet/tcp_var.h @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * @(#)tcp_var.h 8.4 (Berkeley) 5/24/95 - * $Id: tcp_var.h,v 1.46 1998/07/13 11:09:52 bde Exp $ + * $Id: tcp_var.h,v 1.47 1998/08/23 03:07:15 wollman Exp $ */ #ifndef _NETINET_TCP_VAR_H_ @@ -45,8 +45,7 @@ * Organized for 16 byte cacheline efficiency. */ struct tcpcb { - struct tcpiphdr *seg_next; /* sequencing queue */ - struct tcpiphdr *seg_prev; + struct mbuf *t_segq; int t_dupacks; /* consecutive dup acks recd */ struct tcpiphdr *t_template; /* skeletal packet for transmit */ @@ -206,16 +205,6 @@ struct rmxp_tao { max((tp)->t_rttmin, (((tp)->t_srtt >> (TCP_RTT_SHIFT - TCP_DELTA_SHIFT)) \ + (tp)->t_rttvar) >> TCP_DELTA_SHIFT) -/* XXX - * We want to avoid doing m_pullup on incoming packets but that - * means avoiding dtom on the tcp reassembly code. That in turn means - * keeping an mbuf pointer in the reassembly queue (since we might - * have a cluster). As a quick hack, the source & destination - * port numbers (which are no longer needed once we've located the - * tcpcb) are overlayed with an mbuf pointer. - */ -#define REASS_MBUF(ti) (*(struct mbuf **)&((ti)->ti_t)) - /* * TCP statistics. * Many of these should be kept per connection, diff --git a/sys/netinet/udp_usrreq.c b/sys/netinet/udp_usrreq.c index 107fd06..d5eae08 100644 --- a/sys/netinet/udp_usrreq.c +++ b/sys/netinet/udp_usrreq.c @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * @(#)udp_usrreq.c 8.6 (Berkeley) 5/23/95 - * $Id: udp_usrreq.c,v 1.46 1998/03/28 10:18:26 bde Exp $ + * $Id: udp_usrreq.c,v 1.47 1998/05/15 20:11:35 wollman Exp $ */ #include <sys/param.h> @@ -166,9 +166,7 @@ udp_input(m, iphlen) * Checksum extended UDP header and data. */ if (uh->uh_sum) { - ((struct ipovly *)ip)->ih_next = 0; - ((struct ipovly *)ip)->ih_prev = 0; - ((struct ipovly *)ip)->ih_x1 = 0; + bzero(((struct ipovly *)ip)->ih_x1, 9); ((struct ipovly *)ip)->ih_len = uh->uh_ulen; uh->uh_sum = in_cksum(m, len + sizeof (struct ip)); if (uh->uh_sum) { @@ -507,8 +505,7 @@ udp_output(inp, m, addr, control, p) * and addresses and length put into network format. */ ui = mtod(m, struct udpiphdr *); - ui->ui_next = ui->ui_prev = 0; - ui->ui_x1 = 0; + bzero(ui->ui_x1, sizeof(ui->ui_x1)); ui->ui_pr = IPPROTO_UDP; ui->ui_len = htons((u_short)len + sizeof (struct udphdr)); ui->ui_src = inp->inp_laddr; |