diff options
author | claudio <claudio@openbsd.org> | 2010-05-11 09:36:07 +0000 |
---|---|---|
committer | claudio <claudio@openbsd.org> | 2010-05-11 09:36:07 +0000 |
commit | 21579e10e33c565e4f3a5853ddfcf80a7656605e (patch) | |
tree | fc9b81fa977d4940cd7be10d7e2bbf890d741faa /sys/netinet/ip_ipip.c | |
parent | Add IPPROTO_MPLS for MPLS in gif(4) encapsulation. (diff) | |
download | wireguard-openbsd-21579e10e33c565e4f3a5853ddfcf80a7656605e.tar.xz wireguard-openbsd-21579e10e33c565e4f3a5853ddfcf80a7656605e.zip |
Massiv cleanup of the gif(4) mess. Move encapsulation into gif_output()
where it is not necessary to guess protocols by looking at the first nibble.
in_gif_output() will encapsulate the packet but not send it. Because of
etherip support and the way the bridge works a minimal hack is needed in
gif_start() to ensure that the bridged packets are encapsulated as well.
This actually started with the idea to add MPLS support but that turned out
to be not as simple as in the gre(4) case.
Tested by myself (IP, IPv6, etherip, MPLS), sthen@ (IP, IPv6), naddy (IPv6)
OK sthen@
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); |