diff options
author | 2000-07-05 22:51:09 +0000 | |
---|---|---|
committer | 2000-07-05 22:51:09 +0000 | |
commit | d4ec8fc2f215de34c7db1b87939e9f01986eee21 (patch) | |
tree | 6d42fdd31da81a98d8d1af09ef4133b40160136c /sys/netinet/tcp_input.c | |
parent | oops, late night typo (diff) | |
download | wireguard-openbsd-d4ec8fc2f215de34c7db1b87939e9f01986eee21.tar.xz wireguard-openbsd-d4ec8fc2f215de34c7db1b87939e9f01986eee21.zip |
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/tcp_input.c')
-rw-r--r-- | sys/netinet/tcp_input.c | 169 |
1 files changed, 72 insertions, 97 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); |