diff options
author | Jun-ichiro itojun Hagino <itojun@cvs.openbsd.org> | 2003-05-29 00:35:19 +0000 |
---|---|---|
committer | Jun-ichiro itojun Hagino <itojun@cvs.openbsd.org> | 2003-05-29 00:35:19 +0000 |
commit | b420256ef32af4714b7678f09fab90aed7a10e41 (patch) | |
tree | 7b0e0f381b4d3b3b3e88a239bfcb250627bedf02 /sys/netinet | |
parent | a8dcbc5cc46a0135bded5e71bcc4d4e98a608a87 (diff) |
use m_pulldown not m_pullup2. fix some bugs in IPv6 tcp_trace().
Diffstat (limited to 'sys/netinet')
-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, 125 insertions, 154 deletions
diff --git a/sys/netinet/tcp_debug.c b/sys/netinet/tcp_debug.c index 09ab874665b..f604cf2d5ae 100644 --- a/sys/netinet/tcp_debug.c +++ b/sys/netinet/tcp_debug.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tcp_debug.c,v 1.14 2003/05/14 01:12:27 jason Exp $ */ +/* $OpenBSD: tcp_debug.c,v 1.15 2003/05/29 00:35:18 itojun Exp $ */ /* $NetBSD: tcp_debug.c,v 1.10 1996/02/13 23:43:36 christos Exp $ */ /* @@ -113,16 +113,16 @@ int tcpconsdebug = 0; #endif struct tcp_debug tcp_debug[TCP_NDEBUG]; -int tcp_debx; +int tcp_debx = 0; /* * Tcp debug routines */ void -tcp_trace(act, ostate, tp, headers, req, len) +tcp_trace(act, ostate, tp, m, req, len) short act, ostate; struct tcpcb *tp; - caddr_t headers; + struct mbuf *m; int req; int len; { @@ -130,15 +130,27 @@ tcp_trace(act, ostate, tp, headers, req, len) tcp_seq seq, ack; int flags; #endif - struct tcp_debug *td = &tcp_debug[tcp_debx++]; - struct tcpiphdr *ti = (struct tcpiphdr *)headers; + caddr_t headers; + struct tcp_debug *td; + struct tcpiphdr *ti; 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; @@ -150,7 +162,7 @@ tcp_trace(act, ostate, tp, headers, req, len) switch (tp->pf) { #ifdef INET6 case PF_INET6: - if (ti) { + if (ti6) { th = &ti6->ti6_t; td->td_ti6 = *ti6; } else diff --git a/sys/netinet/tcp_input.c b/sys/netinet/tcp_input.c index 950094c7264..940f09d267d 100644 --- a/sys/netinet/tcp_input.c +++ b/sys/netinet/tcp_input.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tcp_input.c,v 1.127 2003/05/19 02:03:28 dhartmei Exp $ */ +/* $OpenBSD: tcp_input.c,v 1.128 2003/05/29 00:35:18 itojun Exp $ */ /* $NetBSD: tcp_input.c,v 1.23 1996/02/13 23:43:44 christos Exp $ */ /* @@ -101,9 +101,6 @@ #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)) @@ -111,7 +108,6 @@ struct tcpipv6hdr tcp_saveti6; #endif /* INET6 */ int tcprexmtthresh = 3; -struct tcpiphdr tcp_saveti; int tcptv_keep_init = TCPTV_KEEP_INIT; extern u_long sb_max; @@ -417,7 +413,7 @@ tcp_input(struct mbuf *m, ...) u_long tiwin; u_int32_t ts_val, ts_ecr; int ts_present = 0; - int iphlen; + int iphlen, toff; va_list ap; struct tcphdr *th; #ifdef INET6 @@ -431,12 +427,13 @@ 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); - iphlen = va_arg(ap, int); + toff = va_arg(ap, int); va_end(ap); tcpstat.tcps_rcvtotal++; @@ -466,38 +463,68 @@ tcp_input(struct mbuf *m, ...) switch (af) { case AF_INET: #ifdef DIAGNOSTIC - if (iphlen < sizeof(struct ip)) { + if (toff < sizeof(struct ip)) { m_freem(m); return; } #endif /* DIAGNOSTIC */ - if (iphlen > sizeof(struct ip)) { -#if 0 /*XXX*/ - ip_stripoptions(m, (struct mbuf *)0); - iphlen = sizeof(struct ip); -#else - m_freem(m); + 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++; return; -#endif } + 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 (iphlen < sizeof(struct ip6_hdr)) { + if (toff < sizeof(struct ip6_hdr)) { m_freem(m); return; } #endif /* DIAGNOSTIC */ - if (iphlen > sizeof(struct ip6_hdr)) { -#if 0 /*XXX*/ - ipv6_stripoptions(m, iphlen); - iphlen = sizeof(struct ip6_hdr); -#else - m_freem(m); + 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++; 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: @@ -505,49 +532,19 @@ 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. */ - len = sizeof(struct ip) + tlen; - bzero(ti->ti_x1, sizeof ti->ti_x1); - ti->ti_len = (u_int16_t)tlen; - HTONS(ti->ti_len); + HTONS(ip->ip_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 ((ti->ti_sum = in_cksum(m, len)) != 0) { + if (in4_cksum(m, IPPROTO_TCP, toff, tlen) != 0) { tcpstat.tcps_rcvbadsum++; goto drop; } @@ -556,35 +553,8 @@ 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. */ @@ -597,8 +567,6 @@ 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 @@ -610,25 +578,13 @@ tcp_input(struct mbuf *m, ...) } tlen -= off; if (off > sizeof(struct tcphdr)) { - 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); + IP6_EXTHDR_GET(th, struct tcphdr *, m, toff, off); + if (th == NULL) { + tcpstat.tcps_rcvshort++; + return; } optlen = off - sizeof(struct tcphdr); - optp = mtod(m, u_int8_t *) + iphlen + sizeof(struct tcphdr); + optp = mtod(m, u_int8_t *) + toff + sizeof(struct tcphdr); /* * Do quick retrieval of timestamp options ("options * prediction?"). If timestamp is the only option and it's @@ -716,16 +672,28 @@ findpcb: if (so->so_options & (SO_DEBUG|SO_ACCEPTCONN)) { if (so->so_options & SO_DEBUG) { ostate = tp->t_state; - switch (af) { -#ifdef INET6 - case AF_INET6: - tcp_saveti6 = *(mtod(m, struct tcpipv6hdr *)); - break; + 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; + } #endif - case AF_INET: - tcp_saveti = *(mtod(m, struct tcpiphdr *)); - break; + 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; + } } + 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; @@ -883,7 +851,7 @@ findpcb: tdb = gettdb(tdbi->spi, &tdbi->dst, tdbi->proto); } else tdb = NULL; - ipsp_spd_lookup(m, af, iphlen, &error, IPSP_DIRECTION_IN, + ipsp_spd_lookup(m, af, toff, &error, IPSP_DIRECTION_IN, tdb, inp); if (error) { splx(s); @@ -1080,7 +1048,7 @@ findpcb: if (so->so_state & SS_CANTRCVMORE) m_freem(m); else { - m_adj(m, iphlen + off); + m_adj(m, toff + off); sbappendstream(&so->so_rcv, m); } sorwakeup(so); @@ -1094,7 +1062,7 @@ findpcb: /* * Compute mbuf offset to TCP data segment. */ - hdroptlen = iphlen + off; + hdroptlen = toff + off; /* * Calculate amount of space in receive window, @@ -2242,20 +2210,8 @@ dodata: /* XXX */ break; } } - 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; - } - } + if (so->so_options & SO_DEBUG) + tcp_trace(TA_INPUT, ostate, tp, tcp_saveti, 0, tlen); /* * Return any desired output. @@ -2263,6 +2219,7 @@ dodata: /* XXX */ if (needoutput || (tp->t_flags & TF_ACKNOW)) { (void) tcp_output(tp); } + m_freem(tcp_saveti); return; dropafterack: @@ -2275,6 +2232,7 @@ dropafterack: m_freem(m); tp->t_flags |= TF_ACKNOW; (void) tcp_output(tp); + m_freem(tcp_saveti); return; dropwithreset_ratelim: @@ -2324,27 +2282,17 @@ 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)) { - 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; - } - } + if (tp && (tp->t_inpcb->inp_socket->so_options & SO_DEBUG)) + tcp_trace(TA_DROP, ostate, tp, tcp_saveti, 0, tlen); + 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 7ce63727feb..0a0ec985d6f 100644 --- a/sys/netinet/tcp_output.c +++ b/sys/netinet/tcp_output.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tcp_output.c,v 1.54 2003/01/25 15:27:29 markus Exp $ */ +/* $OpenBSD: tcp_output.c,v 1.55 2003/05/29 00:35:18 itojun Exp $ */ /* $NetBSD: tcp_output.c,v 1.16 1997/06/03 16:17:09 kml Exp $ */ /* @@ -1071,9 +1071,20 @@ send: /* * Trace. */ - if (so->so_options & SO_DEBUG) - tcp_trace(TA_OUTPUT, tp->t_state, tp, mtod(m, caddr_t), 0, - len); + 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); + } /* * 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 0cb17be3322..a23daa6280c 100644 --- a/sys/netinet/tcp_usrreq.c +++ b/sys/netinet/tcp_usrreq.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tcp_usrreq.c,v 1.68 2003/02/12 14:41:08 jason Exp $ */ +/* $OpenBSD: tcp_usrreq.c,v 1.69 2003/05/29 00:35:18 itojun Exp $ */ /* $NetBSD: tcp_usrreq.c,v 1.20 1996/02/13 23:44:16 christos Exp $ */ /* @@ -488,7 +488,7 @@ tcp_usrreq(so, req, m, nam, control) panic("tcp_usrreq"); } if (tp && (so->so_options & SO_DEBUG)) - tcp_trace(TA_USER, ostate, tp, (caddr_t)0, req, 0); + tcp_trace(TA_USER, ostate, tp, NULL, req, 0); splx(s); return (error); } diff --git a/sys/netinet/tcp_var.h b/sys/netinet/tcp_var.h index c695c1cbf98..c15dc9a00b1 100644 --- a/sys/netinet/tcp_var.h +++ b/sys/netinet/tcp_var.h @@ -1,4 +1,4 @@ -/* $OpenBSD: tcp_var.h,v 1.48 2003/05/26 05:01:55 itojun Exp $ */ +/* $OpenBSD: tcp_var.h,v 1.49 2003/05/29 00:35:18 itojun Exp $ */ /* $NetBSD: tcp_var.h,v 1.17 1996/02/13 23:44:24 christos Exp $ */ /* @@ -424,7 +424,7 @@ void tcp_setpersist(struct tcpcb *); void tcp_slowtimo(void); struct mbuf * tcp_template(struct tcpcb *); -void tcp_trace(int, int, struct tcpcb *, caddr_t, int, int); +void tcp_trace(int, int, struct tcpcb *, struct mbuf *, int, int); struct tcpcb * tcp_usrclosed(struct tcpcb *); int tcp_sysctl(int *, u_int, void *, size_t *, void *, size_t); |