diff options
author | Jun-ichiro itojun Hagino <itojun@cvs.openbsd.org> | 2003-06-09 07:40:26 +0000 |
---|---|---|
committer | Jun-ichiro itojun Hagino <itojun@cvs.openbsd.org> | 2003-06-09 07:40:26 +0000 |
commit | 8d1676992f6c6f897fde850e52a016d4c3cfc1fe (patch) | |
tree | b9eca6af623fc55075d32e2b5733943ab20e7ee5 /sys | |
parent | bc786f06fee201918acb3f6ca1e5864d8c58e2bf (diff) |
backout following:
>use m_pulldown not m_pullup2. fix some bugs in IPv6 tcp_trace().
PR 3283 fixed (confirmed)
Diffstat (limited to 'sys')
-rw-r--r-- | sys/netinet/tcp_debug.c | 26 | ||||
-rw-r--r-- | sys/netinet/tcp_input.c | 226 | ||||
-rw-r--r-- | sys/netinet/tcp_output.c | 19 | ||||
-rw-r--r-- | sys/netinet/tcp_usrreq.c | 4 | ||||
-rw-r--r-- | sys/netinet/tcp_var.h | 4 |
5 files changed, 154 insertions, 125 deletions
diff --git a/sys/netinet/tcp_debug.c b/sys/netinet/tcp_debug.c index 81a8b0fc837..b18e0715b52 100644 --- a/sys/netinet/tcp_debug.c +++ b/sys/netinet/tcp_debug.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tcp_debug.c,v 1.16 2003/06/02 23:28:14 millert Exp $ */ +/* $OpenBSD: tcp_debug.c,v 1.17 2003/06/09 07:40:25 itojun Exp $ */ /* $NetBSD: tcp_debug.c,v 1.10 1996/02/13 23:43:36 christos Exp $ */ /* @@ -109,16 +109,16 @@ int tcpconsdebug = 0; #endif struct tcp_debug tcp_debug[TCP_NDEBUG]; -int tcp_debx = 0; +int tcp_debx; /* * Tcp debug routines */ void -tcp_trace(act, ostate, tp, m, req, len) +tcp_trace(act, ostate, tp, headers, req, len) short act, ostate; struct tcpcb *tp; - struct mbuf *m; + caddr_t headers; int req; int len; { @@ -126,27 +126,15 @@ tcp_trace(act, ostate, tp, m, req, len) tcp_seq seq, ack; int flags; #endif - caddr_t headers; - struct tcp_debug *td; - struct tcpiphdr *ti; + struct tcp_debug *td = &tcp_debug[tcp_debx++]; + struct tcpiphdr *ti = (struct tcpiphdr *)headers; struct tcphdr *th; #ifdef INET6 struct tcpipv6hdr *ti6 = (struct tcpipv6hdr *)ti; #endif - td = &tcp_debug[tcp_debx++]; if (tcp_debx == TCP_NDEBUG) tcp_debx = 0; - - if (m) - headers = mtod(m, caddr_t); - else - headers = NULL; - ti = (struct tcpiphdr *)headers; -#ifdef INET6 - ti6 = (struct tcpipv6hdr *)headers; -#endif - td->td_time = iptime(); td->td_act = act; td->td_ostate = ostate; @@ -158,7 +146,7 @@ tcp_trace(act, ostate, tp, m, req, len) switch (tp->pf) { #ifdef INET6 case PF_INET6: - if (ti6) { + if (ti) { th = &ti6->ti6_t; td->td_ti6 = *ti6; } else diff --git a/sys/netinet/tcp_input.c b/sys/netinet/tcp_input.c index ae06e434ce7..02866771153 100644 --- a/sys/netinet/tcp_input.c +++ b/sys/netinet/tcp_input.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tcp_input.c,v 1.130 2003/06/02 23:28:14 millert Exp $ */ +/* $OpenBSD: tcp_input.c,v 1.131 2003/06/09 07:40:25 itojun Exp $ */ /* $NetBSD: tcp_input.c,v 1.23 1996/02/13 23:43:44 christos Exp $ */ /* @@ -97,6 +97,9 @@ #include <netinet6/in6_var.h> #include <netinet6/nd6.h> +struct tcpiphdr tcp_saveti; +struct tcpipv6hdr tcp_saveti6; + /* for the packet header length in the mbuf */ #define M_PH_LEN(m) (((struct mbuf *)(m))->m_pkthdr.len) #define M_V6_LEN(m) (M_PH_LEN(m) - sizeof(struct ip6_hdr)) @@ -104,6 +107,7 @@ #endif /* INET6 */ int tcprexmtthresh = 3; +struct tcpiphdr tcp_saveti; int tcptv_keep_init = TCPTV_KEEP_INIT; extern u_long sb_max; @@ -409,7 +413,7 @@ tcp_input(struct mbuf *m, ...) u_long tiwin; u_int32_t ts_val, ts_ecr; int ts_present = 0; - int iphlen, toff; + int iphlen; va_list ap; struct tcphdr *th; #ifdef INET6 @@ -423,13 +427,12 @@ tcp_input(struct mbuf *m, ...) int error, s; #endif /* IPSEC */ int af; - struct mbuf *tcp_saveti = NULL; #ifdef TCP_ECN u_char iptos; #endif va_start(ap, m); - toff = va_arg(ap, int); + iphlen = va_arg(ap, int); va_end(ap); tcpstat.tcps_rcvtotal++; @@ -459,68 +462,38 @@ tcp_input(struct mbuf *m, ...) switch (af) { case AF_INET: #ifdef DIAGNOSTIC - if (toff < sizeof(struct ip)) { + if (iphlen < sizeof(struct ip)) { m_freem(m); return; } #endif /* DIAGNOSTIC */ - ip = mtod(m, struct ip *); - iphlen = sizeof(*ip); - IP6_EXTHDR_GET(th, struct tcphdr *, m, toff, - sizeof(struct tcphdr)); - if (th == NULL) { - tcpstat.tcps_rcvshort++; + if (iphlen > sizeof(struct ip)) { +#if 0 /*XXX*/ + ip_stripoptions(m, (struct mbuf *)0); + iphlen = sizeof(struct ip); +#else + m_freem(m); return; - } - len = m->m_pkthdr.len; - tlen = len - toff; -#ifdef TCP_ECN - /* save ip_tos before clearing it for checksum */ - iptos = ip->ip_tos; #endif + } break; #ifdef INET6 case AF_INET6: #ifdef DIAGNOSTIC - if (toff < sizeof(struct ip6_hdr)) { + if (iphlen < sizeof(struct ip6_hdr)) { m_freem(m); return; } #endif /* DIAGNOSTIC */ - ip6 = mtod(m, struct ip6_hdr *); - iphlen = sizeof(*ip6); - IP6_EXTHDR_GET(th, struct tcphdr *, m, toff, - sizeof(struct tcphdr)); - if (th == NULL) { - tcpstat.tcps_rcvshort++; + if (iphlen > sizeof(struct ip6_hdr)) { +#if 0 /*XXX*/ + ipv6_stripoptions(m, iphlen); + iphlen = sizeof(struct ip6_hdr); +#else + m_freem(m); return; - } - len = m->m_pkthdr.len; - tlen = len - toff; -#ifdef TCP_ECN - iptos = (ntohl(ip6->ip6_flow) >> 20) & 0xff; #endif - - /* Be proactive about malicious use of IPv4 mapped address */ - if (IN6_IS_ADDR_V4MAPPED(&ip6->ip6_src) || - IN6_IS_ADDR_V4MAPPED(&ip6->ip6_dst)) { - /* XXX stat */ - goto drop; } - - /* - * Be proactive about unspecified IPv6 address in source. - * As we use all-zero to indicate unbounded/unconnected pcb, - * unspecified IPv6 address can be used to confuse us. - * - * Note that packets with unspecified IPv6 destination is - * already dropped in ip6_input. - */ - if (IN6_IS_ADDR_UNSPECIFIED(&ip6->ip6_src)) { - /* XXX stat */ - goto drop; - } - break; #endif default: @@ -528,19 +501,49 @@ tcp_input(struct mbuf *m, ...) return; } + if (m->m_len < iphlen + sizeof(struct tcphdr)) { + m = m_pullup2(m, iphlen + sizeof(struct tcphdr)); + if (m == NULL) { + tcpstat.tcps_rcvshort++; + return; + } + } + + ip = NULL; +#ifdef INET6 + ip6 = NULL; +#endif switch (af) { case AF_INET: + { + struct tcpiphdr *ti; + + ip = mtod(m, struct ip *); +#if 1 + tlen = m->m_pkthdr.len - iphlen; +#else + tlen = ((struct ip *)ti)->ip_len; +#endif + ti = mtod(m, struct tcpiphdr *); + +#ifdef TCP_ECN + /* save ip_tos before clearing it for checksum */ + iptos = ip->ip_tos; +#endif /* * Checksum extended TCP header and data. */ - HTONS(ip->ip_len); + len = sizeof(struct ip) + tlen; + bzero(ti->ti_x1, sizeof ti->ti_x1); + ti->ti_len = (u_int16_t)tlen; + HTONS(ti->ti_len); if ((m->m_pkthdr.csum & M_TCP_CSUM_IN_OK) == 0) { if (m->m_pkthdr.csum & M_TCP_CSUM_IN_BAD) { tcpstat.tcps_inhwcsum++; tcpstat.tcps_rcvbadsum++; goto drop; } - if (in4_cksum(m, IPPROTO_TCP, toff, tlen) != 0) { + if ((ti->ti_sum = in_cksum(m, len)) != 0) { tcpstat.tcps_rcvbadsum++; goto drop; } @@ -549,8 +552,35 @@ tcp_input(struct mbuf *m, ...) tcpstat.tcps_inhwcsum++; } break; + } #ifdef INET6 case AF_INET6: + ip6 = mtod(m, struct ip6_hdr *); + tlen = m->m_pkthdr.len - iphlen; +#ifdef TCP_ECN + iptos = (ntohl(ip6->ip6_flow) >> 20) & 0xff; +#endif + + /* Be proactive about malicious use of IPv4 mapped address */ + if (IN6_IS_ADDR_V4MAPPED(&ip6->ip6_src) || + IN6_IS_ADDR_V4MAPPED(&ip6->ip6_dst)) { + /* XXX stat */ + goto drop; + } + + /* + * Be proactive about unspecified IPv6 address in source. + * As we use all-zero to indicate unbounded/unconnected pcb, + * unspecified IPv6 address can be used to confuse us. + * + * Note that packets with unspecified IPv6 destination is + * already dropped in ip6_input. + */ + if (IN6_IS_ADDR_UNSPECIFIED(&ip6->ip6_src)) { + /* XXX stat */ + goto drop; + } + /* * Checksum extended TCP header and data. */ @@ -563,6 +593,8 @@ tcp_input(struct mbuf *m, ...) } #endif /* TUBA_INCLUDE */ + th = (struct tcphdr *)(mtod(m, caddr_t) + iphlen); + /* * Check that TCP offset makes sense, * pull out TCP options and adjust length. XXX @@ -574,13 +606,25 @@ tcp_input(struct mbuf *m, ...) } tlen -= off; if (off > sizeof(struct tcphdr)) { - IP6_EXTHDR_GET(th, struct tcphdr *, m, toff, off); - if (th == NULL) { - tcpstat.tcps_rcvshort++; - return; + if (m->m_len < iphlen + off) { + if ((m = m_pullup2(m, iphlen + off)) == NULL) { + tcpstat.tcps_rcvshort++; + return; + } + switch (af) { + case AF_INET: + ip = mtod(m, struct ip *); + break; +#ifdef INET6 + case AF_INET6: + ip6 = mtod(m, struct ip6_hdr *); + break; +#endif + } + th = (struct tcphdr *)(mtod(m, caddr_t) + iphlen); } optlen = off - sizeof(struct tcphdr); - optp = mtod(m, u_int8_t *) + toff + sizeof(struct tcphdr); + optp = mtod(m, u_int8_t *) + iphlen + sizeof(struct tcphdr); /* * Do quick retrieval of timestamp options ("options * prediction?"). If timestamp is the only option and it's @@ -668,28 +712,16 @@ findpcb: if (so->so_options & (SO_DEBUG|SO_ACCEPTCONN)) { if (so->so_options & SO_DEBUG) { ostate = tp->t_state; - tcp_saveti = NULL; - MGETHDR(tcp_saveti, M_DONTWAIT, MT_HEADER); - if (!tcp_saveti) - goto nosave; -#ifdef DIAGNOSTIC - if (iphlen + sizeof(struct tcphdr) > MCLBYTES) { - printf("cannot save to tcp_saveti\n"); - goto nosave; - } + switch (af) { +#ifdef INET6 + case AF_INET6: + tcp_saveti6 = *(mtod(m, struct tcpipv6hdr *)); + break; #endif - if (iphlen + sizeof(struct tcphdr) > MHLEN) { - MCLGET(tcp_saveti, M_DONTWAIT); - if ((tcp_saveti->m_flags & M_EXT) == 0) { - m_freem(tcp_saveti); - tcp_saveti = NULL; - goto nosave; - } + case AF_INET: + tcp_saveti = *(mtod(m, struct tcpiphdr *)); + break; } - m_copydata(m, 0, iphlen, mtod(tcp_saveti, caddr_t)); - m_copydata(m, toff, sizeof(struct tcphdr), - mtod(tcp_saveti, caddr_t) + iphlen); - nosave:; } if (so->so_options & SO_ACCEPTCONN) { struct socket *so1; @@ -847,7 +879,7 @@ findpcb: tdb = gettdb(tdbi->spi, &tdbi->dst, tdbi->proto); } else tdb = NULL; - ipsp_spd_lookup(m, af, toff, &error, IPSP_DIRECTION_IN, + ipsp_spd_lookup(m, af, iphlen, &error, IPSP_DIRECTION_IN, tdb, inp); if (error) { splx(s); @@ -1044,7 +1076,7 @@ findpcb: if (so->so_state & SS_CANTRCVMORE) m_freem(m); else { - m_adj(m, toff + off); + m_adj(m, iphlen + off); sbappendstream(&so->so_rcv, m); } sorwakeup(so); @@ -1058,7 +1090,7 @@ findpcb: /* * Compute mbuf offset to TCP data segment. */ - hdroptlen = toff + off; + hdroptlen = iphlen + off; /* * Calculate amount of space in receive window, @@ -2206,8 +2238,20 @@ dodata: /* XXX */ break; } } - if (so->so_options & SO_DEBUG) - tcp_trace(TA_INPUT, ostate, tp, tcp_saveti, 0, tlen); + if (so->so_options & SO_DEBUG) { + switch (tp->pf) { +#ifdef INET6 + case PF_INET6: + tcp_trace(TA_INPUT, ostate, tp, (caddr_t) &tcp_saveti6, + 0, tlen); + break; +#endif /* INET6 */ + case PF_INET: + tcp_trace(TA_INPUT, ostate, tp, (caddr_t) &tcp_saveti, + 0, tlen); + break; + } + } /* * Return any desired output. @@ -2215,7 +2259,6 @@ dodata: /* XXX */ if (needoutput || (tp->t_flags & TF_ACKNOW)) { (void) tcp_output(tp); } - m_freem(tcp_saveti); return; dropafterack: @@ -2228,7 +2271,6 @@ dropafterack: m_freem(m); tp->t_flags |= TF_ACKNOW; (void) tcp_output(tp); - m_freem(tcp_saveti); return; dropwithreset_ratelim: @@ -2278,17 +2320,27 @@ dropwithreset: /* destroy temporarily created socket */ if (dropsocket) (void) soabort(so); - m_freem(tcp_saveti); return; drop: /* * Drop space held by incoming segment and return. */ - if (tp && (tp->t_inpcb->inp_socket->so_options & SO_DEBUG)) - tcp_trace(TA_DROP, ostate, tp, tcp_saveti, 0, tlen); + if (tp && (tp->t_inpcb->inp_socket->so_options & SO_DEBUG)) { + switch (tp->pf) { +#ifdef INET6 + case PF_INET6: + tcp_trace(TA_DROP, ostate, tp, (caddr_t) &tcp_saveti6, + 0, tlen); + break; +#endif /* INET6 */ + case PF_INET: + tcp_trace(TA_DROP, ostate, tp, (caddr_t) &tcp_saveti, + 0, tlen); + break; + } + } - m_freem(tcp_saveti); m_freem(m); /* destroy temporarily created socket */ if (dropsocket) diff --git a/sys/netinet/tcp_output.c b/sys/netinet/tcp_output.c index facb432fbfd..80c927bc06a 100644 --- a/sys/netinet/tcp_output.c +++ b/sys/netinet/tcp_output.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tcp_output.c,v 1.56 2003/06/02 23:28:14 millert Exp $ */ +/* $OpenBSD: tcp_output.c,v 1.57 2003/06/09 07:40:25 itojun Exp $ */ /* $NetBSD: tcp_output.c,v 1.16 1997/06/03 16:17:09 kml Exp $ */ /* @@ -1067,20 +1067,9 @@ send: /* * Trace. */ - if (so->so_options & SO_DEBUG) { - /* TCP template does not fill ip version, so fill it in here */ - struct ip *sip; - sip = mtod(m, struct ip *); - switch (tp->pf) { - case AF_INET: - sip->ip_v = 4; - break; - case AF_INET6: - sip->ip_v = 6; - break; - } - tcp_trace(TA_OUTPUT, tp->t_state, tp, m, 0, len); - } + if (so->so_options & SO_DEBUG) + tcp_trace(TA_OUTPUT, tp->t_state, tp, mtod(m, caddr_t), 0, + len); /* * Fill in IP length and desired time to live and diff --git a/sys/netinet/tcp_usrreq.c b/sys/netinet/tcp_usrreq.c index 26f2f659623..501efc21a7b 100644 --- a/sys/netinet/tcp_usrreq.c +++ b/sys/netinet/tcp_usrreq.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tcp_usrreq.c,v 1.70 2003/06/02 23:28:15 millert Exp $ */ +/* $OpenBSD: tcp_usrreq.c,v 1.71 2003/06/09 07:40:25 itojun Exp $ */ /* $NetBSD: tcp_usrreq.c,v 1.20 1996/02/13 23:44:16 christos Exp $ */ /* @@ -484,7 +484,7 @@ tcp_usrreq(so, req, m, nam, control) panic("tcp_usrreq"); } if (tp && (so->so_options & SO_DEBUG)) - tcp_trace(TA_USER, ostate, tp, NULL, req, 0); + tcp_trace(TA_USER, ostate, tp, (caddr_t)0, req, 0); splx(s); return (error); } diff --git a/sys/netinet/tcp_var.h b/sys/netinet/tcp_var.h index 264f1df2be7..3acccd04282 100644 --- a/sys/netinet/tcp_var.h +++ b/sys/netinet/tcp_var.h @@ -1,4 +1,4 @@ -/* $OpenBSD: tcp_var.h,v 1.50 2003/06/02 23:28:15 millert Exp $ */ +/* $OpenBSD: tcp_var.h,v 1.51 2003/06/09 07:40:25 itojun Exp $ */ /* $NetBSD: tcp_var.h,v 1.17 1996/02/13 23:44:24 christos Exp $ */ /* @@ -420,7 +420,7 @@ void tcp_setpersist(struct tcpcb *); void tcp_slowtimo(void); struct mbuf * tcp_template(struct tcpcb *); -void tcp_trace(int, int, struct tcpcb *, struct mbuf *, int, int); +void tcp_trace(int, int, struct tcpcb *, caddr_t, int, int); struct tcpcb * tcp_usrclosed(struct tcpcb *); int tcp_sysctl(int *, u_int, void *, size_t *, void *, size_t); |