diff options
author | Jun-ichiro itojun Hagino <itojun@cvs.openbsd.org> | 2000-07-05 22:51:11 +0000 |
---|---|---|
committer | Jun-ichiro itojun Hagino <itojun@cvs.openbsd.org> | 2000-07-05 22:51:11 +0000 |
commit | 115a196a388cfb8c17ec6acb07d0a231f5e4269b (patch) | |
tree | 9a904d4cc4771d5acc22d55e1f23b8f36eb0e464 /sys/netinet | |
parent | d52022692cd6e495778e1992a1e586f0c2804c45 (diff) |
more cleanup for IPv4 mapped address support. there seem to be some
inconsistency in corner cases (from NRL I believe).
todd (fries) and I have seen panic, with the following call chain:
ip6_input -> tcp_input -> tcp_respond -> ip_input -> bang!
more cleanups should be done, to decrease complexity.
for example, INP_IPV6_MAPPED should be nuked.
Diffstat (limited to 'sys/netinet')
-rw-r--r-- | sys/netinet/tcp_input.c | 169 | ||||
-rw-r--r-- | sys/netinet/tcp_subr.c | 14 | ||||
-rw-r--r-- | sys/netinet/tcp_usrreq.c | 17 |
3 files changed, 90 insertions, 110 deletions
diff --git a/sys/netinet/tcp_input.c b/sys/netinet/tcp_input.c index ee7650e0487..f4f859523a8 100644 --- a/sys/netinet/tcp_input.c +++ b/sys/netinet/tcp_input.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tcp_input.c,v 1.61 2000/05/15 03:38:40 angelos Exp $ */ +/* $OpenBSD: tcp_input.c,v 1.62 2000/07/05 22:51:09 itojun Exp $ */ /* $NetBSD: tcp_input.c,v 1.23 1996/02/13 23:43:44 christos Exp $ */ /* @@ -987,96 +987,59 @@ findpcb: goto drop; #ifdef INET6 if (is_ipv6) { - /* - * This is probably the place to set the tp->pf value. - * (Don't forget to do it in the v4 code as well!) - * - * Also, remember to blank out things like flowlabel, or - * set flowlabel for accepted sockets in v6. - * - * FURTHERMORE, this is PROBABLY the place where the whole - * business of key munging is set up for passive - * connections. - */ - am->m_len = sizeof(struct sockaddr_in6); - sin6 = mtod(am, struct sockaddr_in6 *); - sin6->sin6_family = AF_INET6; - sin6->sin6_len = sizeof(struct sockaddr_in6); - sin6->sin6_addr = ipv6->ip6_src; - sin6->sin6_port = th->th_sport; - sin6->sin6_flowinfo = htonl(0x0fffffff) & - inp->inp_ipv6.ip6_flow; - laddr6 = inp->inp_laddr6; - if (IN6_IS_ADDR_UNSPECIFIED(&inp->inp_laddr6)) - inp->inp_laddr6 = ipv6->ip6_dst; - /* This is a good optimization. */ - if (in6_pcbconnect(inp, am)) { - inp->inp_laddr6 = laddr6; - (void) m_free(am); - goto drop; - } /* endif in6_pcbconnect() */ - tp->pf = PF_INET6; - } else { - /* - * Letting v4 incoming datagrams to reach valid - * PF_INET6 sockets causes some overhead here. - */ - if (inp->inp_flags & INP_IPV6) { - if (!(inp->inp_flags & (INP_IPV6_UNDEC|INP_IPV6_MAPPED))) { - (void) m_free(am); - goto drop; - } - - am->m_len = sizeof(struct sockaddr_in6); - - sin6 = mtod(am, struct sockaddr_in6 *); - sin6->sin6_family = AF_INET6; - sin6->sin6_len = sizeof(*sin6); - CREATE_IPV6_MAPPED(sin6->sin6_addr, ti->ti_src.s_addr); - sin6->sin6_port = th->th_sport; - sin6->sin6_flowinfo = 0; - - laddr6 = inp->inp_laddr6; - if (inp->inp_laddr.s_addr == INADDR_ANY) - CREATE_IPV6_MAPPED(inp->inp_laddr6, ti->ti_dst.s_addr); - - /* - * The pcb initially has the v6 default hoplimit - * set. We're sending v4 packets so we need to set - * the v4 ttl and tos. - */ - inp->inp_ip.ip_ttl = ip_defttl; - inp->inp_ip.ip_tos = 0; - - if (in6_pcbconnect(inp, am)) { - inp->inp_laddr6 = laddr6; - (void) m_freem(am); - goto drop; - } - tp->pf = PF_INET; - } else { -#endif /* INET6 */ - am->m_len = sizeof (struct sockaddr_in); - sin = mtod(am, struct sockaddr_in *); - sin->sin_family = AF_INET; - sin->sin_len = sizeof(*sin); - sin->sin_addr = ti->ti_src; - sin->sin_port = ti->ti_sport; - bzero((caddr_t)sin->sin_zero, sizeof(sin->sin_zero)); - laddr = inp->inp_laddr; - if (inp->inp_laddr.s_addr == INADDR_ANY) - inp->inp_laddr = ti->ti_dst; - if (in_pcbconnect(inp, am)) { - inp->inp_laddr = laddr; + /* + * This is probably the place to set the tp->pf value. + * (Don't forget to do it in the v4 code as well!) + * + * Also, remember to blank out things like flowlabel, or + * set flowlabel for accepted sockets in v6. + * + * FURTHERMORE, this is PROBABLY the place where the + * whole business of key munging is set up for passive + * connections. + */ + am->m_len = sizeof(struct sockaddr_in6); + sin6 = mtod(am, struct sockaddr_in6 *); + sin6->sin6_family = AF_INET6; + sin6->sin6_len = sizeof(struct sockaddr_in6); + sin6->sin6_addr = ipv6->ip6_src; + sin6->sin6_port = th->th_sport; + sin6->sin6_flowinfo = htonl(0x0fffffff) & + inp->inp_ipv6.ip6_flow; + laddr6 = inp->inp_laddr6; + if (IN6_IS_ADDR_UNSPECIFIED(&inp->inp_laddr6)) + inp->inp_laddr6 = ipv6->ip6_dst; + /* This is a good optimization. */ + if (in6_pcbconnect(inp, am)) { + inp->inp_laddr6 = laddr6; + (void) m_free(am); + goto drop; + } + } else +#endif + { + /* drop IPv4 packet to AF_INET6 socket */ + if (inp->inp_flags & INP_IPV6) { + (void) m_free(am); + goto drop; + } + am->m_len = sizeof (struct sockaddr_in); + sin = mtod(am, struct sockaddr_in *); + sin->sin_family = AF_INET; + sin->sin_len = sizeof(*sin); + sin->sin_addr = ti->ti_src; + sin->sin_port = ti->ti_sport; + bzero((caddr_t)sin->sin_zero, sizeof(sin->sin_zero)); + laddr = inp->inp_laddr; + if (inp->inp_laddr.s_addr == INADDR_ANY) + inp->inp_laddr = ti->ti_dst; + if (in_pcbconnect(inp, am)) { + inp->inp_laddr = laddr; + (void) m_free(am); + goto drop; + } (void) m_free(am); - goto drop; } - (void) m_free(am); - tp->pf = PF_INET; -#ifdef INET6 - } /* if (inp->inp_flags & INP_IPV6) */ - } /* if (is_ipv6) */ -#endif /* INET6 */ tp->t_template = tcp_template(tp); if (tp->t_template == 0) { tp = tcp_drop(tp, ENOBUFS); @@ -1995,12 +1958,18 @@ dodata: /* XXX */ } } if (so->so_options & SO_DEBUG) { + switch (tp->pf == PF_INET6) { #ifdef INET6 - if (tp->pf == PF_INET6) - tcp_trace(TA_INPUT, ostate, tp, (caddr_t) &tcp_saveti6, 0, tlen); - else + case PF_INET6: + tcp_trace(TA_INPUT, ostate, tp, (caddr_t) &tcp_saveti6, + 0, tlen); + break; #endif /* INET6 */ - tcp_trace(TA_INPUT, ostate, tp, (caddr_t) &tcp_saveti, 0, tlen); + case PF_INET: + tcp_trace(TA_INPUT, ostate, tp, (caddr_t) &tcp_saveti, + 0, tlen); + break; + } } /* @@ -2062,12 +2031,18 @@ 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 - if (tp->pf == PF_INET6) - tcp_trace(TA_DROP, ostate, tp, (caddr_t) &tcp_saveti6, 0, tlen); - else + case PF_INET6: + tcp_trace(TA_DROP, ostate, tp, (caddr_t) &tcp_saveti6, + 0, tlen); + break; #endif /* INET6 */ - tcp_trace(TA_DROP, ostate, tp, (caddr_t) &tcp_saveti, 0, tlen); + case PF_INET: + tcp_trace(TA_DROP, ostate, tp, (caddr_t) &tcp_saveti, + 0, tlen); + break; + } } m_freem(m); diff --git a/sys/netinet/tcp_subr.c b/sys/netinet/tcp_subr.c index 15d34f607bf..5096c5f7539 100644 --- a/sys/netinet/tcp_subr.c +++ b/sys/netinet/tcp_subr.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tcp_subr.c,v 1.27 2000/06/26 22:45:09 art Exp $ */ +/* $OpenBSD: tcp_subr.c,v 1.28 2000/07/05 22:51:10 itojun Exp $ */ /* $NetBSD: tcp_subr.c,v 1.22 1996/02/13 23:44:00 christos Exp $ */ /* @@ -446,15 +446,11 @@ tcp_newtcpcb(inp) tp->snd_cwnd = TCP_MAXWIN << TCP_MAX_WINSHIFT; tp->snd_ssthresh = TCP_MAXWIN << TCP_MAX_WINSHIFT; #ifdef INET6 - /* - * If we want to use tp->pf for a quick-n-easy way to determine - * the outbound dgram type, we cannot make this decision - * until a connection is established! Bzero() sets pf to zero, and - * that's the way we want it, unless, of course, it's an AF_INET - * socket... - */ + /* we disallow IPv4 mapped address completely. */ if ((inp->inp_flags & INP_IPV6) == 0) - tp->pf = PF_INET; /* If AF_INET socket, we can't do v6 from it. */ + tp->pf = PF_INET; + else + tp->pf = PF_INET6; #else tp->pf = PF_INET; #endif diff --git a/sys/netinet/tcp_usrreq.c b/sys/netinet/tcp_usrreq.c index 7bd8b4c6240..ad9c8b8cbb5 100644 --- a/sys/netinet/tcp_usrreq.c +++ b/sys/netinet/tcp_usrreq.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tcp_usrreq.c,v 1.43 2000/06/18 15:13:33 deraadt Exp $ */ +/* $OpenBSD: tcp_usrreq.c,v 1.44 2000/07/05 22:51:10 itojun Exp $ */ /* $NetBSD: tcp_usrreq.c,v 1.20 1996/02/13 23:44:16 christos Exp $ */ /* @@ -213,7 +213,7 @@ tcp_usrreq(so, req, m, nam, control) error = in_pcbbind(inp, nam); if (error) break; -#ifdef INET6 +#if 0 /*INET6*/ /* * If we bind to an address, set up the tp->pf accordingly! */ @@ -305,7 +305,7 @@ tcp_usrreq(so, req, m, nam, control) if (error) break; -#ifdef INET6 +#if 0 /*INET6*/ /* * With a connection, I now know the version of IP * is in use and hence can set tp->pf with authority. @@ -326,7 +326,7 @@ tcp_usrreq(so, req, m, nam, control) break; } -#ifdef INET6 +#if 0 /*INET6*/ if ((inp->inp_flags & INP_IPV6) && (tp->pf == PF_INET)) { inp->inp_ip.ip_ttl = ip_defttl; inp->inp_ip.ip_tos = 0; @@ -716,6 +716,15 @@ tcp_attach(so) return (ENOBUFS); } tp->t_state = TCPS_CLOSED; +#ifdef INET6 + /* we disallow IPv4 mapped address completely. */ + if (inp->inp_flags & INP_IPV6) + tp->pf = PF_INET6; + else + tp->pf = PF_INET; +#else + tp->pf = PF_INET; +#endif return (0); } |