diff options
Diffstat (limited to 'sys')
-rw-r--r-- | sys/netinet/tcp_input.c | 815 | ||||
-rw-r--r-- | sys/netinet/tcp_var.h | 6 |
2 files changed, 275 insertions, 546 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) diff --git a/sys/netinet/tcp_var.h b/sys/netinet/tcp_var.h index 7b583c5fae5..9ac7ef96eed 100644 --- a/sys/netinet/tcp_var.h +++ b/sys/netinet/tcp_var.h @@ -1,4 +1,4 @@ -/* $OpenBSD: tcp_var.h,v 1.21 1999/07/06 20:17:53 cmetz Exp $ */ +/* $OpenBSD: tcp_var.h,v 1.22 1999/07/17 23:41:46 provos Exp $ */ /* $NetBSD: tcp_var.h,v 1.17 1996/02/13 23:44:24 christos Exp $ */ /* @@ -330,8 +330,8 @@ struct tcpcb * tcp_disconnect __P((struct tcpcb *)); struct tcpcb * tcp_drop __P((struct tcpcb *, int)); -int tcp_dooptions __P((struct tcpcb *, u_char *, int, struct tcphdr *, - struct mbuf *, int, int *, u_int32_t *, u_int32_t *)); +void tcp_dooptions __P((struct tcpcb *, u_char *, int, struct tcphdr *, + int *, u_int32_t *, u_int32_t *)); void tcp_drain __P((void)); void tcp_fasttimo __P((void)); void tcp_init __P((void)); |