diff options
author | Niels Provos <provos@cvs.openbsd.org> | 1999-07-17 23:41:47 +0000 |
---|---|---|
committer | Niels Provos <provos@cvs.openbsd.org> | 1999-07-17 23:41:47 +0000 |
commit | f6a17bf360416ac496a7450da97334fddd8be6c7 (patch) | |
tree | 63dbf1cef07bcbdea23cd5454ab4ccab234211a5 /sys/netinet/tcp_input.c | |
parent | 5c17fbcfd5e5aa3f34351dcabe619f16c8d4ed50 (diff) |
revert tcp_input.c to before 07/01/1999 - this seems to solve the mysterious
data corruptions and panics that people have experienced. by reverting
we loose tcp signatures and ipv6 cleanups, the code looked correct to me.
Diffstat (limited to 'sys/netinet/tcp_input.c')
-rw-r--r-- | sys/netinet/tcp_input.c | 815 |
1 files changed, 272 insertions, 543 deletions
diff --git a/sys/netinet/tcp_input.c b/sys/netinet/tcp_input.c index 6ad3623a7ee..4eb50c0a275 100644 --- a/sys/netinet/tcp_input.c +++ b/sys/netinet/tcp_input.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tcp_input.c,v 1.41 1999/07/13 21:57:42 deraadt Exp $ */ +/* $OpenBSD: tcp_input.c,v 1.42 1999/07/17 23:41:46 provos Exp $ */ /* $NetBSD: tcp_input.c,v 1.23 1996/02/13 23:43:44 christos Exp $ */ /* @@ -48,12 +48,6 @@ You should have received a copy of the license with this software. If you didn't get a copy, you may request one from <license@ipv6.nrl.navy.mil>. */ -/* - * XXX - At this point, the TUBA support is likely to be hopelessly broken. - * That's the bad news. The good news is that doing it again and doing it - * right shouldn't be hard now that the IPv4 dependencies are isolated. - */ - #ifndef TUBA_INCLUDE #include <sys/param.h> #include <sys/systm.h> @@ -94,19 +88,17 @@ didn't get a copy, you may request one from <license@ipv6.nrl.navy.mil>. #include <netinet6/ipv6_var.h> #include <netinet6/tcpipv6.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 ipv6)) #define M_V4_LEN(m) (M_PH_LEN(m) - sizeof(struct ip)) #endif /* INET6 */ -#ifdef INET6 -char tcp_savebuf[sizeof(struct ipv6) + sizeof(struct tcphdr)]; -#else /* INET6 */ -char tcp_savebuf[sizeof(struct ip) + sizeof(struct tcphdr)]; -#endif /* INET6 */ - int tcprexmtthresh = 3; +struct tcpiphdr tcp_saveti; int tcptv_keep_init = TCPTV_KEEP_INIT; extern u_long sb_max; @@ -313,9 +305,9 @@ tcp_input(struct mbuf *m, ...) #else tcp_input(m, va_alist) register struct mbuf *m; - va_dcl #endif { + register struct tcpiphdr *ti; register struct inpcb *inp; caddr_t optp = NULL; int optlen = 0; @@ -325,6 +317,7 @@ tcp_input(m, va_alist) struct socket *so = NULL; int todrop, acked, ourfinisacked, needoutput = 0; short ostate = 0; + struct in_addr laddr; int dropsocket = 0; int iss = 0; u_long tiwin; @@ -333,19 +326,14 @@ tcp_input(m, va_alist) int iphlen; va_list ap; register struct tcphdr *th; - unsigned int pf; #ifdef IPSEC struct tdb *tdb = NULL; #endif /* IPSEC */ - union { - caddr_t p; -#ifdef INET - struct ip *ip; -#endif /* INET */ #ifdef INET6 - struct ipv6 *ipv6; -#endif /* INET */ - } nhu; + struct in6_addr laddr6; + unsigned short is_ipv6; /* Type of incoming datagram. */ + struct ipv6 *ipv6 = NULL; +#endif /* INET6 */ va_start(ap, m); iphlen = va_arg(ap, int); @@ -362,113 +350,87 @@ tcp_input(m, va_alist) m->m_pkthdr.tdbi = NULL; } #endif /* IPSEC */ - +#ifdef INET6 /* - * Before we do ANYTHING, we have to figure out what network protocol - * is underneath the TCP header in this packet. - * - * For IPv4 and IPv6, options don't really do anything at this layer - * and therefore are stripped off. + * Before we do ANYTHING, we have to figure out if it's TCP/IPv6 or + * TCP/IPv4. */ -#if defined(INET) && defined(INET6) - switch (mtod(m, struct ip *)->ip_v) { -#else /* defined(INET) && defined(INET6) */ - switch (-1) { - case -1: -#endif /* defined(INET) && defined(INET6) */ -#ifdef INET - case 4: - pf = PF_INET; - -#ifdef DIAGNOSTIC - if (iphlen < sizeof(struct ip)) { - m_freem(m); - return; - } -#endif /* DIAGNOSTIC */ - - if (iphlen > sizeof(struct ip)) { - ip_stripoptions(m, (struct mbuf *)0); - iphlen = sizeof(struct ip); - } - break; -#endif /* INET */ -#ifdef INET6 - case 6: - pf = PF_INET6; - -#ifdef DIAGNOSTIC - if (iphlen < sizeof(struct ipv6)) { - m_freem(m); - return; - } -#endif /* DIAGNOSTIC */ - - if (iphlen > sizeof(struct ipv6)) { - ipv6_stripoptions(m, iphlen); - iphlen = sizeof(struct ipv6); - } - break; + is_ipv6 = mtod(m, struct ip *)->ip_v == 6; #endif /* INET6 */ - default: - m_freem(m); - return; - } /* * Get IP and TCP header together in first mbuf. * Note: IP leaves IP header in first mbuf. */ +#ifndef INET6 + ti = mtod(m, struct tcpiphdr *); +#else /* INET6 */ + if (!is_ipv6) +#endif /* INET6 */ + if (iphlen > sizeof (struct ip)) + ip_stripoptions(m, (struct mbuf *)0); if (m->m_len < iphlen + sizeof(struct tcphdr)) { if ((m = m_pullup2(m, iphlen + sizeof(struct tcphdr))) == 0) { tcpstat.tcps_rcvshort++; return; } +#ifndef INET6 + ti = mtod(m, struct tcpiphdr *); +#endif /* INET6 */ } tlen = m->m_pkthdr.len - iphlen; +#ifdef INET6 /* - * Checksum extended TCP header and data. + * After that, do initial segment processing which is still very + * dependent on what IP version you're using. */ -#if defined(INET) && defined(INET6) - switch (pf) { -#else /* defined(INET) && defined(INET6) */ - switch (-1) { - case -1: -#endif /* defined(INET) && defined(INET6) */ -#ifdef INET - case PF_INET: - { - struct ipovly *ipovly; - ipovly = mtod(m, struct ipovly *); + if (is_ipv6) { +#ifdef DIAGNOSTIC + if (iphlen < sizeof(struct ipv6)) { + m_freem(m); + return; + } +#endif /* DIAGNOSTIC */ - len = sizeof (struct ip) + tlen; - bzero(ipovly->ih_x1, sizeof ipovly->ih_x1); - ipovly->ih_len = (u_int16_t)tlen; - HTONS(ipovly->ih_len); + /* strip off any options */ + if (iphlen > sizeof(struct ipv6)) { + ipv6_stripoptions(m, iphlen); + iphlen = sizeof(struct ipv6); + } - if (in_cksum(m, len)) { - tcpstat.tcps_rcvbadsum++; - goto drop; - } - } - break; -#endif /* INET */ -#ifdef INET6 - case PF_INET6: - if (in6_cksum(m, IPPROTO_TCP, tlen, sizeof(struct ipv6))) { - tcpstat.tcps_rcvbadsum++; - goto drop; - } /* endif in6_cksum */ - break; + ti = NULL; + ipv6 = mtod(m, struct ipv6 *); + + if (in6_cksum(m, IPPROTO_TCP, tlen, sizeof(struct ipv6))) { + tcpstat.tcps_rcvbadsum++; + goto drop; + } /* endif in6_cksum */ + } else { + ti = mtod(m, struct tcpiphdr *); #endif /* INET6 */ - } + /* + * Checksum extended TCP header and data. + */ +#ifndef INET6 + tlen = ((struct ip *)ti)->ip_len; +#endif /* INET6 */ + 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 ((ti->ti_sum = in_cksum(m, len)) != 0) { + tcpstat.tcps_rcvbadsum++; + goto drop; + } +#ifdef INET6 + } +#endif /* INET6 */ #endif /* TUBA_INCLUDE */ - nhu.p = mtod(m, caddr_t); th = (struct tcphdr *)(mtod(m, caddr_t) + iphlen); /* @@ -487,6 +449,12 @@ tcp_input(m, va_alist) tcpstat.tcps_rcvshort++; return; } +#ifdef INET6 + if (is_ipv6) + ipv6 = mtod(m, struct ipv6 *); + else +#endif /* INET6 */ + ti = mtod(m, struct tcpiphdr *); th = (struct tcphdr *)(mtod(m, caddr_t) + iphlen); } optlen = off - sizeof (struct tcphdr); @@ -523,51 +491,25 @@ tcp_input(m, va_alist) * Locate pcb for segment. */ findpcb: -#if defined(INET) && defined(INET6) - switch (pf) { -#else /* defined(INET) && defined(INET6) */ - switch (-1) { - case -1: -#endif /* defined(INET) && defined(INET6) */ -#ifdef INET - case PF_INET: - inp = in_pcbhashlookup(&tcbtable, nhu.ip->ip_src, - th->th_sport, nhu.ip->ip_dst, th->th_dport); - break; -#endif /* INET */ #ifdef INET6 - case PF_INET6: - inp = in6_pcbhashlookup(&tcbtable, &nhu.ipv6->ipv6_src, - th->th_sport, &nhu.ipv6->ipv6_dst, th->th_dport); - break; + if (is_ipv6) { + inp = in6_pcbhashlookup(&tcbtable, &ipv6->ipv6_src, th->th_sport, + &ipv6->ipv6_dst, th->th_dport); + } else #endif /* INET6 */ - } - + inp = in_pcbhashlookup(&tcbtable, ti->ti_src, ti->ti_sport, + ti->ti_dst, ti->ti_dport); if (inp == 0) { ++tcpstat.tcps_pcbhashmiss; -#if defined(INET) && defined(INET6) - switch (pf) { -#else /* defined(INET) && defined(INET6) */ - switch (-1) { - case -1: -#endif /* defined(INET) && defined(INET6) */ -#ifdef INET - case PF_INET: - inp = in_pcblookup(&tcbtable, &nhu.ip->ip_src, - th->th_sport, &nhu.ip->ip_dst, th->th_dport, - INPLOOKUP_WILDCARD); - break; -#endif /* INET */ #ifdef INET6 - case PF_INET6: - inp = in_pcblookup(&tcbtable, &nhu.ipv6->ipv6_src, - th->th_sport, &nhu.ipv6->ipv6_dst, - th->th_dport, - INPLOOKUP_WILDCARD | INPLOOKUP_IPV6); - break; + if (is_ipv6) + inp = in_pcblookup(&tcbtable, &ipv6->ipv6_src, + th->th_sport, &ipv6->ipv6_dst, th->th_dport, + INPLOOKUP_WILDCARD | INPLOOKUP_IPV6); + else #endif /* INET6 */ - } - + inp = in_pcblookup(&tcbtable, &ti->ti_src, ti->ti_sport, + &ti->ti_dst, ti->ti_dport, INPLOOKUP_WILDCARD); /* * If the state is CLOSED (i.e., TCB does not exist) then * all data in the incoming segment is discarded. @@ -596,8 +538,12 @@ findpcb: if (so->so_options & (SO_DEBUG|SO_ACCEPTCONN)) { if (so->so_options & SO_DEBUG) { ostate = tp->t_state; - bcopy(mtod(m, caddr_t), tcp_savebuf, - iphlen + sizeof(struct tcphdr)); +#ifdef INET6 + if (is_ipv6) + tcp_saveti6 = *(mtod(m, struct tcpipv6hdr *)); + else +#endif /* INET6 */ + tcp_saveti = *ti; } if (so->so_options & SO_ACCEPTCONN) { struct socket *so1; @@ -645,57 +591,48 @@ findpcb: * to the new one. */ { - int flags = inp->inp_flags; - struct inpcb *oldinpcb = inp; + int flags = inp->inp_flags; + struct inpcb *oldinpcb = inp; - inp = (struct inpcb *)so->so_pcb; - inp->inp_flags |= - (flags & (INP_IPV6 | INP_IPV6_UNDEC - | INP_IPV6_MAPPED)); - if ((inp->inp_flags & INP_IPV6) && - !(inp->inp_flags & - INP_IPV6_MAPPED)) { - inp->inp_ipv6.ipv6_hoplimit = - oldinpcb->inp_ipv6. - ipv6_hoplimit; - inp->inp_ipv6.ipv6_versfl = - oldinpcb->inp_ipv6.ipv6_versfl; - } + inp = (struct inpcb *)so->so_pcb; + inp->inp_flags |= (flags & (INP_IPV6 | INP_IPV6_UNDEC + | INP_IPV6_MAPPED)); + if ((inp->inp_flags & INP_IPV6) && + !(inp->inp_flags & INP_IPV6_MAPPED)) { + inp->inp_ipv6.ipv6_hoplimit = + oldinpcb->inp_ipv6.ipv6_hoplimit; + inp->inp_ipv6.ipv6_versfl = + oldinpcb->inp_ipv6.ipv6_versfl; + } } #else /* INET6 */ inp = (struct inpcb *)so->so_pcb; #endif /* INET6 */ inp->inp_lport = th->th_dport; -#if defined(INET) && defined(INET6) - switch (pf) { -#else /* defined(INET) && defined(INET6) */ - switch (-1) { - case -1: -#endif /* defined(INET) && defined(INET6) */ -#ifdef INET - case PF_INET: #ifdef INET6 - if (inp->inp_flags & INP_IPV6) { - /* v4 to v6 socket */ - CREATE_IPV6_MAPPED(inp->inp_laddr6, - nhu.ip->ip_dst.s_addr); - } else + if (is_ipv6) { + inp->inp_laddr6 = ipv6->ipv6_dst; + inp->inp_fflowinfo = htonl(0x0fffffff) & + ipv6->ipv6_versfl; + + /*inp->inp_options = ipv6_srcroute();*/ /* soon. */ + /* still need to tweak outbound options + processing to include this mbuf in + the right place and put the correct + NextHdr values in the right places. + XXX rja */ + } else { + if (inp->inp_flags & INP_IPV6) {/* v4 to v6 socket */ + CREATE_IPV6_MAPPED(inp->inp_laddr6, + ti->ti_dst.s_addr); + } else { #endif /* INET6 */ - { - inp->inp_laddr = nhu.ip->ip_dst; - inp->inp_options = ip_srcroute(); - } - break; -#endif /* INET */ -#ifdef INET6 - case PF_INET6: - inp->inp_laddr6 = nhu.ipv6->ipv6_dst; - inp->inp_fflowinfo = htonl(0x0fffffff) & - nhu.ipv6->ipv6_versfl; - break; + inp->inp_laddr = ti->ti_dst; + inp->inp_options = ip_srcroute(); +#if INET6 + } + }; #endif /* INET6 */ - } - in_pcbrehash(inp); tp = intotcpcb(inp); tp->t_state = TCPS_LISTEN; @@ -703,8 +640,7 @@ findpcb: /* Compute proper scaling value from buffer space */ while (tp->request_r_scale < TCP_MAX_WINSHIFT && - TCP_MAXWIN << tp->request_r_scale < - so->so_rcv.sb_hiwat) + TCP_MAXWIN << tp->request_r_scale < so->so_rcv.sb_hiwat) tp->request_r_scale++; } } @@ -716,23 +652,12 @@ findpcb: (inp->inp_seclevel[SL_ESP_TRANS] >= IPSEC_LEVEL_REQUIRE && !(m->m_flags & M_CONF))) { #ifdef notyet -#if defined(INET) && defined(INET6) - switch (pf) { -#else /* defined(INET) && defined(INET6) */ - switch (-1) { - case -1: -#endif /* defined(INET) && defined(INET6) */ -#ifdef INET - case PF_INET: - icmp_error(m, ICMP_BLAH, ICMP_BLAH, 0, 0); - break; -#endif /* INET */ #ifdef INET6 - case PF_INET6: + if (is_ipv6) ipv6_icmp_error(m, ICMPV6_BLAH, ICMPV6_BLAH, 0); - break; + else #endif /* INET6 */ - } + icmp_error(m, ICMP_BLAH, ICMP_BLAH, 0, 0); #endif /* notyet */ tcpstat.tcps_rcvnosec++; goto drop; @@ -759,15 +684,9 @@ findpcb: * Process options if not in LISTEN state, * else do it below (after getting remote address). */ - if (tp->t_state != TCPS_LISTEN) -#ifdef TCP_SIGNATURE - if (optp || (tp->t_flags & TF_SIGNATURE)) -#else /* TCP_SIGNATURE */ - if (optp) -#endif /* TCP_SIGNATURE */ - if (tcp_dooptions(tp, optp, optlen, th, m, iphlen, - &ts_present, &ts_val, &ts_ecr)) - goto drop; + if (optp && tp->t_state != TCPS_LISTEN) + tcp_dooptions(tp, optp, optlen, th, + &ts_present, &ts_val, &ts_ecr); #ifdef TCP_SACK if (!tp->sack_disable) { @@ -930,6 +849,10 @@ findpcb: */ case TCPS_LISTEN: { struct mbuf *am; + register struct sockaddr_in *sin; +#ifdef INET6 + register struct sockaddr_in6 *sin6; +#endif /* INET6 */ if (tiflags & TH_RST) goto drop; @@ -938,27 +861,17 @@ findpcb: if ((tiflags & TH_SYN) == 0) goto drop; if (th->th_dport == th->th_sport) { -#if defined(INET) && defined(INET6) - switch (pf) { -#else /* defined(INET) && defined(INET6) */ - switch (-1) { - case -1: -#endif /* defined(INET) && defined(INET6) */ -#ifdef INET - case PF_INET: - if (nhu.ip->ip_src.s_addr == - nhu.ip->ip_dst.s_addr) - goto drop; - break; -#endif /* INET */ #ifdef INET6 - case PF_INET6: - if (IN6_ARE_ADDR_EQUAL(&nhu.ipv6->ipv6_src, - &nhu.ipv6->ipv6_dst)) - goto drop; - break; + if (is_ipv6) { + if (IN6_ARE_ADDR_EQUAL(&ipv6->ipv6_src, &ipv6->ipv6_dst)) + goto drop; + } else { +#endif /* INET6 */ + if (ti->ti_dst.s_addr == ti->ti_src.s_addr) + goto drop; +#ifdef INET6 + } #endif /* INET6 */ - } } /* @@ -968,172 +881,118 @@ findpcb: */ if (m->m_flags & (M_BCAST|M_MCAST)) goto drop; -#if defined(INET) && defined(INET6) - switch (pf) { -#else /* defined(INET) && defined(INET6) */ - switch (-1) { - case -1: -#endif /* defined(INET) && defined(INET6) */ -#ifdef INET - case PF_INET: - if (nhu.ip->ip_dst.s_addr == INADDR_BROADCAST) - goto drop; - if (IN_MULTICAST(nhu.ip->ip_dst.s_addr)) - goto drop; - break; -#endif /* INET */ #ifdef INET6 - case PF_INET6: - if (IN6_IS_ADDR_MULTICAST(&nhu.ipv6->ipv6_dst)) + if (is_ipv6) { + /* XXX What about IPv6 Anycasting ?? :-( rja */ + if (IN6_IS_ADDR_MULTICAST(&ipv6->ipv6_dst)) goto drop; - break; + } else #endif /* INET6 */ - } - + if (IN_MULTICAST(ti->ti_dst.s_addr)) + goto drop; am = m_get(M_DONTWAIT, MT_SONAME); /* XXX */ if (am == NULL) goto drop; - -#if defined(INET) && defined(INET6) - switch (pf) { -#else /* defined(INET) && defined(INET6) */ - switch (-1) { - case -1: -#endif /* defined(INET) && defined(INET6) */ -#ifdef INET - case PF_INET: #ifdef INET6 - /* - * Letting v4 incoming datagrams to reach valid - * PF_INET6 sockets causes some overhead here. - */ - if (inp->inp_flags & INP_IPV6) { - struct sockaddr_in6 *sin6; - struct in6_addr laddr6; - - if (!(inp->inp_flags & (INP_IPV6_UNDEC | - INP_IPV6_MAPPED))) { - m_freem(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(struct sockaddr_in6); - CREATE_IPV6_MAPPED(sin6->sin6_addr, - nhu.ip->ip_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) - break; - CREATE_IPV6_MAPPED(inp->inp_laddr6, - nhu.ip->ip_dst.s_addr); - - /* - * The pcb initially has the v6 default hop - * limit 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; - m_freem(am); - goto drop; - } - } else /* (inp->inp_flags & INP_IPV6) */ + 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->ipv6_src; + sin6->sin6_port = th->th_sport; + sin6->sin6_flowinfo = htonl(0x0fffffff) & + inp->inp_ipv6.ipv6_versfl; + laddr6 = inp->inp_laddr6; + if (IN6_IS_ADDR_UNSPECIFIED(&inp->inp_laddr6)) + inp->inp_laddr6 = ipv6->ipv6_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 */ - { - struct sockaddr_in *sin; - struct in_addr laddr; - - am->m_len = sizeof(struct sockaddr_in); - sin = mtod(am, struct sockaddr_in *); - sin->sin_family = AF_INET; - sin->sin_len = sizeof(struct sockaddr_in); - sin->sin_addr = nhu.ip->ip_src; - sin->sin_port = th->th_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 = nhu.ip->ip_dst; - if (in_pcbconnect(inp, am)) { - inp->inp_laddr = laddr; - m_free(am); - goto drop; - } - } /* (inp->inp_flags & INP_IPV6) */ - tp->pf = PF_INET; - break; -#endif /* INET */ + 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); #ifdef INET6 - case PF_INET6: - { - struct sockaddr_in6 *sin6; - struct in6_addr laddr6; - - /* - * 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. - */ - - 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 = nhu.ipv6->ipv6_src; - sin6->sin6_port = th->th_sport; - sin6->sin6_flowinfo = htonl(0x0fffffff) & - inp->inp_ipv6.ipv6_versfl; - laddr6 = inp->inp_laddr6; - - if (IN6_IS_ADDR_UNSPECIFIED(&inp->inp_laddr6)) - inp->inp_laddr6 = nhu.ipv6->ipv6_dst; - /* This is a good optimization. */ - if (in6_pcbconnect(inp, am)) { - inp->inp_laddr6 = laddr6; - m_free(am); - goto drop; - } - } - - tp->pf = PF_INET6; - break; + } /* if (inp->inp_flags & INP_IPV6) */ + } /* if (is_ipv6) */ #endif /* INET6 */ - } - - m_free(am); tp->t_template = tcp_template(tp); if (tp->t_template == 0) { tp = tcp_drop(tp, ENOBUFS); dropsocket = 0; /* socket is already gone */ goto drop; } - -#ifdef TCP_SIGNATURE - if (optp || (tp->t_flags & TF_SIGNATURE)) { -#else /* TCP_SIGNATURE */ - if (optp) { -#endif /* TCP_SIGNATURE */ - m->m_data -= iphlen + off; - m->m_len += iphlen + off; - if (tcp_dooptions(tp, optp, optlen, th, m, iphlen, - &ts_present, &ts_val, &ts_ecr)) - goto drop; - m->m_data += iphlen + off; - m->m_len -= iphlen + off; - } - + if (optp) + tcp_dooptions(tp, optp, optlen, th, + &ts_present, &ts_val, &ts_ecr); #ifdef TCP_SACK /* * If peer did not send a SACK_PERMITTED option (i.e., if @@ -1434,7 +1293,7 @@ trimthenstep6: * Close the tcb. */ if (tiflags & TH_RST) { - if (th->th_seq != tp->last_ack_sent) + if (ti->ti_seq != tp->last_ack_sent) goto drop; switch (tp->t_state) { @@ -2060,9 +1919,14 @@ dodata: /* XXX */ break; } } - - if (so->so_options & SO_DEBUG) - tcp_trace(TA_INPUT, ostate, tp, tcp_savebuf, 0, tlen); + if (so->so_options & SO_DEBUG) { +#ifdef INET6 + if (tp->pf == PF_INET6) + tcp_trace(TA_INPUT, ostate, tp, (caddr_t) &tcp_saveti6, 0, tlen); + else +#endif /* INET6 */ + tcp_trace(TA_INPUT, ostate, tp, (caddr_t) &tcp_saveti, 0, tlen); + } /* * Return any desired output. @@ -2103,36 +1967,26 @@ dropwithreset: */ if ((tiflags & TH_RST) || m->m_flags & (M_BCAST|M_MCAST)) goto drop; -#if defined(INET) && defined(INET6) - switch (pf) { -#else /* defined(INET) && defined(INET6) */ - switch (-1) { - case -1: -#endif /* defined(INET) && defined(INET6) */ -#ifdef INET - case PF_INET: - if (mtod(m, struct ip *)->ip_dst.s_addr == INADDR_BROADCAST) - goto drop; - if (IN_MULTICAST(mtod(m, struct ip *)->ip_dst.s_addr)) - goto drop; - break; -#endif /* INET */ #ifdef INET6 - case PF_INET6: - if (IN6_IS_ADDR_MULTICAST(&mtod(m, struct ipv6 *)->ipv6_dst)) - goto drop; - break; + if (is_ipv6) { + /* For following calls to tcp_respond */ + ti = mtod(m, struct tcpiphdr *); + if (IN6_IS_ADDR_MULTICAST(&ipv6->ipv6_dst)) + goto drop; + } else { #endif /* INET6 */ + if (IN_MULTICAST(ti->ti_dst.s_addr)) + goto drop; +#ifdef INET6 } - +#endif /* INET6 */ if (tiflags & TH_ACK) - tcp_respond(tp, mtod(m, caddr_t), m, (tcp_seq)0, th->th_ack, - TH_RST); + tcp_respond(tp, (caddr_t) ti, m, (tcp_seq)0, th->th_ack, TH_RST); else { if (tiflags & TH_SYN) tlen++; - tcp_respond(tp, mtod(m, caddr_t), m, th->th_seq+tlen, - (tcp_seq)0, TH_RST|TH_ACK); + tcp_respond(tp, (caddr_t) ti, m, th->th_seq+tlen, (tcp_seq)0, + TH_RST|TH_ACK); } /* destroy temporarily created socket */ if (dropsocket) @@ -2143,8 +1997,14 @@ 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_savebuf, 0, tlen); + if (tp && (tp->t_inpcb->inp_socket->so_options & SO_DEBUG)) { +#ifdef INET6 + if (tp->pf == PF_INET6) + tcp_trace(TA_DROP, ostate, tp, (caddr_t) &tcp_saveti6, 0, tlen); + else +#endif /* INET6 */ + tcp_trace(TA_DROP, ostate, tp, (caddr_t) &tcp_saveti, 0, tlen); + } m_freem(m); /* destroy temporarily created socket */ @@ -2154,22 +2014,17 @@ drop: #ifndef TUBA_INCLUDE } -int -tcp_dooptions(tp, cp, cnt, th, m, iphlen, ts_present, ts_val, ts_ecr) +void +tcp_dooptions(tp, cp, cnt, th, ts_present, ts_val, ts_ecr) struct tcpcb *tp; u_char *cp; int cnt; struct tcphdr *th; - struct mbuf *m; - int iphlen; int *ts_present; u_int32_t *ts_val, *ts_ecr; { u_int16_t mss = 0; int opt, optlen; -#ifdef TCP_SIGNATURE - caddr_t sigp = NULL; -#endif /* TCP_SIGNATURE */ for (; cnt > 0; cnt -= optlen, cp += optlen) { opt = cp[0]; @@ -2238,137 +2093,11 @@ tcp_dooptions(tp, cp, cnt, th, m, iphlen, ts_present, ts_val, ts_ecr) continue; break; #endif -#ifdef TCP_SIGNATURE - case TCPOPT_SIGNATURE: - if (optlen != TCPOLEN_SIGNATURE) - continue; - - if (sigp && bcmp(sigp, cp + 2, 16)) - return -1; - - sigp = cp + 2; - break; -#endif /* TCP_SIGNATURE */ } } - -#ifdef TCP_SIGNATURE - if ((sigp ? TF_SIGNATURE : 0) ^ (tp->t_flags & TF_SIGNATURE)) { - tcpstat.tcps_rcvbadsig++; - return -1; - } - - if (sigp) { - MD5_CTX ctx; - union sockaddr_union sa; - struct tdb *tdb; - char sig[16]; - - memset(&sa, 0, sizeof(union sockaddr_union)); - - switch (tp->pf) { - case 0: - case AF_INET: - sa.sa.sa_len = sizeof(struct sockaddr_in); - sa.sa.sa_family = AF_INET; - sa.sin.sin_addr = tp->t_inpcb->inp_laddr; - break; -#ifdef INET6 - case AF_INET6: - sa.sa.sa_len = sizeof(struct sockaddr_in6); - sa.sa.sa_family = AF_INET6; - sa.sin6.sin6_addr = tp->t_inpcb->inp_laddr6; - break; -#endif /* INET6 */ - } - - tdb = gettdb(0, &sa, IPPROTO_TCP); - if (tdb == NULL) { - printf("tdb miss\n"); - tcpstat.tcps_rcvbadsig++; - return -1; - } - - MD5Init(&ctx); - - switch(tp->pf) { - case 0: -#ifdef INET - case AF_INET: - { - struct ippseudo ippseudo; - - ippseudo.ippseudo_src = - tp->t_inpcb->inp_faddr; - ippseudo.ippseudo_dst = - tp->t_inpcb->inp_laddr; - ippseudo.ippseudo_pad = 0; - ippseudo.ippseudo_p = IPPROTO_TCP; - ippseudo.ippseudo_len = htons( - m->m_pkthdr.len - iphlen); - - MD5Update(&ctx, (char *)&ippseudo, - sizeof(struct ippseudo)); - } - break; -#endif /* INET */ -#ifdef INET6 - case AF_INET6: - { - static int printed = 0; - - if (!printed) { - printf("error: TCP MD5 support" - " for IPv6 not yet" - " implemented.\n"); - printed = 1; - } - } - break -#endif /* INET6 */ - } - - { - struct tcphdr tcphdr; - - tcphdr.th_sport = th->th_sport; - tcphdr.th_dport = th->th_dport; - tcphdr.th_seq = htonl(th->th_seq); - tcphdr.th_ack = htonl(th->th_ack); - tcphdr.th_off = th->th_off; - tcphdr.th_x2 = th->th_x2; - tcphdr.th_flags = th->th_flags; - tcphdr.th_win = htons(th->th_win); - tcphdr.th_sum = 0; - tcphdr.th_urp = htons(th->th_urp); - - MD5Update(&ctx, (char *)&tcphdr, - sizeof(struct tcphdr)); - } - - if (m_apply(m, iphlen + th->th_off * sizeof(uint32_t), - m->m_pkthdr.len - (iphlen + th->th_off * - sizeof(uint32_t)), tcp_signature_apply, - (caddr_t)&ctx)) - return (-1); - - MD5Update(&ctx, tdb->tdb_amxkey, tdb->tdb_amxkeylen); - MD5Final(sig, &ctx); - - if (bcmp(sig, sigp, 16)) { - tcpstat.tcps_rcvbadsig++; - return (-1); - } - - tcpstat.tcps_rcvgoodsig++; - }; -#endif /* TCP_SIGNATURE */ - /* Update t_maxopd and t_maxseg after all options are processed */ if (th->th_flags & TH_SYN) (void) tcp_mss(tp, mss); /* sets t_maxseg */ - - return (0); } #if defined(TCP_SACK) || defined(TCP_NEWRENO) |