diff options
Diffstat (limited to 'sys/netinet/ip_ipip.c')
-rw-r--r-- | sys/netinet/ip_ipip.c | 87 |
1 files changed, 51 insertions, 36 deletions
diff --git a/sys/netinet/ip_ipip.c b/sys/netinet/ip_ipip.c index b67f20a566a..6a48e52bb0b 100644 --- a/sys/netinet/ip_ipip.c +++ b/sys/netinet/ip_ipip.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ip_ipip.c,v 1.46 2010/04/20 22:05:43 tedu Exp $ */ +/* $OpenBSD: ip_ipip.c,v 1.47 2010/05/11 09:36:07 claudio Exp $ */ /* * The authors of this code are John Ioannidis (ji@tla.org), * Angelos D. Keromytis (kermit@csd.uch.gr) and @@ -103,7 +103,7 @@ ip4_input6(struct mbuf **m, int *offp, int proto) return IPPROTO_DONE; } - ipip_input(*m, *offp, NULL); + ipip_input(*m, *offp, NULL, proto); return IPPROTO_DONE; } #endif /* INET6 */ @@ -115,6 +115,7 @@ ip4_input6(struct mbuf **m, int *offp, int proto) void ip4_input(struct mbuf *m, ...) { + struct ip *ip; va_list ap; int iphlen; @@ -130,7 +131,9 @@ ip4_input(struct mbuf *m, ...) iphlen = va_arg(ap, int); va_end(ap); - ipip_input(m, iphlen, NULL); + ip = mtod(m, struct ip *); + + ipip_input(m, iphlen, NULL, ip->ip_p); } #endif /* INET */ @@ -142,7 +145,7 @@ ip4_input(struct mbuf *m, ...) */ void -ipip_input(struct mbuf *m, int iphlen, struct ifnet *gifp) +ipip_input(struct mbuf *m, int iphlen, struct ifnet *gifp, int proto) { struct sockaddr_in *sin; struct ifnet *ifp; @@ -152,13 +155,14 @@ ipip_input(struct mbuf *m, int iphlen, struct ifnet *gifp) u_int rdomain; #ifdef INET6 struct sockaddr_in6 *sin6; - struct ip6_hdr *ip6 = NULL; + struct ip6_hdr *ip6; u_int8_t itos; #endif int isr; + int hlen, s; u_int8_t otos; u_int8_t v; - int hlen, s; + sa_family_t af; ipipstat.ipips_ipackets++; @@ -166,16 +170,16 @@ ipip_input(struct mbuf *m, int iphlen, struct ifnet *gifp) switch (v >> 4) { #ifdef INET - case 4: + case 4: hlen = sizeof(struct ip); break; #endif /* INET */ #ifdef INET6 - case 6: + case 6: hlen = sizeof(struct ip6_hdr); break; #endif - default: + default: ipipstat.ipips_family++; m_freem(m); return /* EAFNOSUPPORT */; @@ -190,18 +194,19 @@ ipip_input(struct mbuf *m, int iphlen, struct ifnet *gifp) } } - ipo = mtod(m, struct ip *); /* Keep outer ecn field. */ switch (v >> 4) { #ifdef INET case 4: + ipo = mtod(m, struct ip *); otos = ipo->ip_tos; break; #endif /* INET */ #ifdef INET6 case 6: - otos = (ntohl(mtod(m, struct ip6_hdr *)->ip6_flow) >> 20) & 0xff; + ip6 = mtod(m, struct ip6_hdr *); + otos = (ntohl(ip6->ip6_flow) >> 20) & 0xff; break; #endif default: @@ -218,17 +223,15 @@ ipip_input(struct mbuf *m, int iphlen, struct ifnet *gifp) return; } - m_copydata(m, 0, 1, &v); - - switch (v >> 4) { + switch (proto) { #ifdef INET - case 4: + case IPPROTO_IPV4: hlen = sizeof(struct ip); break; #endif /* INET */ #ifdef INET6 - case 6: + case IPPROTO_IPV6: hlen = sizeof(struct ip6_hdr); break; #endif @@ -239,7 +242,7 @@ ipip_input(struct mbuf *m, int iphlen, struct ifnet *gifp) } /* - * Bring the inner IP header in the first mbuf, if not there already. + * Bring the inner header into the first mbuf, if not there already. */ if (m->m_len < hlen) { if ((m = m_pullup(m, hlen)) == NULL) { @@ -256,19 +259,25 @@ ipip_input(struct mbuf *m, int iphlen, struct ifnet *gifp) */ /* Some sanity checks in the inner IP header */ - switch (v >> 4) { + switch (proto) { #ifdef INET - case 4: - ipo = mtod(m, struct ip *); + case IPPROTO_IPV4: + ipo = mtod(m, struct ip *); +#ifdef INET6 + ip6 = NULL; +#endif if (!ip_ecn_egress(ECN_ALLOWED, &otos, &ipo->ip_tos)) { m_freem(m); return; } - break; + break; #endif /* INET */ #ifdef INET6 - case 6: - ip6 = (struct ip6_hdr *) ipo; + case IPPROTO_IPV6: +#ifdef INET + ipo = NULL; +#endif + ip6 = mtod(m, struct ip6_hdr *); itos = (ntohl(ip6->ip6_flow) >> 20) & 0xff; if (!ip_ecn_egress(ECN_ALLOWED, &otos, &itos)) { m_freem(m); @@ -276,10 +285,15 @@ ipip_input(struct mbuf *m, int iphlen, struct ifnet *gifp) } ip6->ip6_flow &= ~htonl(0xff << 20); ip6->ip6_flow |= htonl((u_int32_t) itos << 20); - break; + break; #endif default: - panic("ipip_input: should never reach here"); +#ifdef INET + ipo = NULL; +#endif +#ifdef INET6 + ip6 = NULL; +#endif } /* Check for local address spoofing. */ @@ -297,8 +311,8 @@ ipip_input(struct mbuf *m, int iphlen, struct ifnet *gifp) AF_INET) continue; - sin = (struct sockaddr_in *) ifa->ifa_addr; - + sin = (struct sockaddr_in *) + ifa->ifa_addr; if (sin->sin_addr.s_addr == ipo->ip_src.s_addr) { ipipstat.ipips_spoof++; @@ -307,16 +321,16 @@ ipip_input(struct mbuf *m, int iphlen, struct ifnet *gifp) } } #endif /* INET */ - #ifdef INET6 if (ip6) { if (ifa->ifa_addr->sa_family != AF_INET6) continue; - sin6 = (struct sockaddr_in6 *) ifa->ifa_addr; - - if (IN6_ARE_ADDR_EQUAL(&sin6->sin6_addr, &ip6->ip6_src)) { + sin6 = (struct sockaddr_in6 *) + ifa->ifa_addr; + if (IN6_ARE_ADDR_EQUAL(&sin6->sin6_addr, + &ip6->ip6_src)) { ipipstat.ipips_spoof++; m_freem(m); return; @@ -339,17 +353,19 @@ ipip_input(struct mbuf *m, int iphlen, struct ifnet *gifp) * untrusted packets. */ - switch (v >> 4) { + switch (proto) { #ifdef INET - case 4: + case IPPROTO_IPV4: ifq = &ipintrq; isr = NETISR_IP; + af = AF_INET; break; #endif #ifdef INET6 - case 6: + case IPPROTO_IPV6: ifq = &ip6intrq; isr = NETISR_IPV6; + af = AF_INET6; break; #endif default: @@ -358,8 +374,7 @@ ipip_input(struct mbuf *m, int iphlen, struct ifnet *gifp) #if NBPFILTER > 0 if (gifp && gifp->if_bpf) - bpf_mtap_af(gifp->if_bpf, ifq == &ipintrq ? AF_INET : AF_INET6, - m, BPF_DIRECTION_IN); + bpf_mtap_af(gifp->if_bpf, af, m, BPF_DIRECTION_IN); #endif #if NPF > 0 pf_pkt_addr_changed(m); |