diff options
author | Angelos D. Keromytis <angelos@cvs.openbsd.org> | 1999-12-09 03:52:38 +0000 |
---|---|---|
committer | Angelos D. Keromytis <angelos@cvs.openbsd.org> | 1999-12-09 03:52:38 +0000 |
commit | 0e4671308c6f93f232846a67f018eeb56aca2826 (patch) | |
tree | 287361b8d40d027c586ab759c00a62bb605173d6 | |
parent | 5863f2874f0bbbc1a0c419cae13aea3b642a276c (diff) |
ip4_input() can now handle either of IP-in-IP or IP-in-IPv6
encapsulation. Eventually, this routine will be made to deal with all
4 combinations of IP/IPv6 encapsulation.
gif interface support should be added here too (itojun :-), when the
packet has not been received over an IPsec tunnel. ECN handling should
also be done.
-rw-r--r-- | sys/netinet/ip_ip4.c | 188 |
1 files changed, 55 insertions, 133 deletions
diff --git a/sys/netinet/ip_ip4.c b/sys/netinet/ip_ip4.c index 66803a86adc..77ade818d2e 100644 --- a/sys/netinet/ip_ip4.c +++ b/sys/netinet/ip_ip4.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ip_ip4.c,v 1.35 1999/12/08 06:05:32 itojun Exp $ */ +/* $OpenBSD: ip_ip4.c,v 1.36 1999/12/09 03:52:37 angelos Exp $ */ /* * The authors of this code are John Ioannidis (ji@tla.org), @@ -117,15 +117,10 @@ ip4_input(m, va_alist) register struct ifnet *ifp; register struct ifaddr *ifa; struct ifqueue *ifq = NULL; - struct ip *ipo, *ipi; + struct ip *ipo; int s, iphlen; va_list ap; -#ifdef INET6 - register struct sockaddr_in6 *sin6; - struct ip6_hdr *ipv6; -#endif /* INET6 */ - va_start(ap, m); iphlen = va_arg(ap, int); va_end(ap); @@ -133,6 +128,20 @@ ip4_input(m, va_alist) ip4stat.ip4s_ipackets++; #ifdef MROUTING + /* XXX Make v6 compliant */ + + /* Bring the IP(v4) header in the first mbuf, if not there already */ + if (m->m_len < sizeof(struct ip)) + { + if ((m = m_pullup(m, sizeof(struct ip))) == 0) + { + DPRINTF(("ip4_input(): m_pullup() failed\n")); + ip4stat.ip4s_hdrops++; + m_freem(m); + return; + } + } + ipo = mtod(m, struct ip *); if (IN_MULTICAST(((struct ip *)((char *)ipo + iphlen))->ip_dst.s_addr)) { @@ -150,93 +159,53 @@ ip4_input(m, va_alist) return; } - /* - * Strip IP options, if any. - */ - if (iphlen > sizeof(struct ip)) - { - ip_stripoptions(m, (struct mbuf *) 0); - iphlen = sizeof(struct ip); - } - - /* - * Make sure next IP header is in the first mbuf. - * - * Careful here! we are receiving the packet from ipintr; - * this means that the ip_len field has been adjusted to - * not count the ip header, and is also in host order. - */ + /* Remove outter IP header */ + m_adj(m, iphlen); - ipo = mtod(m, struct ip *); - - if (m->m_len < iphlen + sizeof(struct ip)) + /* Bring the inner IP(v4) header in the first mbuf, if not there already */ + if (m->m_len < sizeof(struct ip)) { - if ((m = m_pullup(m, iphlen + sizeof(struct ip))) == 0) + if ((m = m_pullup(m, sizeof(struct ip))) == 0) { DPRINTF(("ip4_input(): m_pullup() failed\n")); ip4stat.ip4s_hdrops++; m_freem(m); return; } - - ipo = mtod(m, struct ip *); } + ipo = mtod(m, struct ip *); + /* * RFC 1853 specifies that the inner TTL should not be touched on * decapsulation. There's no reason this comment should be here, but * this is as good as any a position. */ - if (ipo->ip_p == IPPROTO_IPIP) - { - ipi = (struct ip *) ((caddr_t) ipo + iphlen); - - if (ipi->ip_v != IPVERSION) - { - DPRINTF(("ip4_input(): wrong version %d on packet from %s to %s (%s->%s)\n", ipi->ip_v, inet_ntoa4(ipo->ip_src), inet_ntoa4(ipo->ip_dst), inet_ntoa4(ipi->ip_src), inet_ntoa4(ipi->ip_dst))); - ip4stat.ip4s_notip4++; - m_freem(m); - return; - } - - /* - * If we do not accept IP4 other than as part of ESP & AH, we should - * not accept a packet with double ip4 headers neither. - */ - - if (!ip4_allow && - ((ipi->ip_p == IPPROTO_IPIP) || - (ipi->ip_p == IPPROTO_IPV6))) - { - DPRINTF(("ip4_input(): dropped due to policy\n")); - ip4stat.ip4s_pdrops++; - m_freem(m); - return; - } - } - -#ifdef INET6 - if (ipo->ip_p == IPPROTO_IPIP) + /* Some sanity checks in the inner IPv4 header */ + if (ipo->ip_v != IPVERSION) { - ipv6 = (struct ip6_hdr *) ((caddr_t) ipo + iphlen); - - if (ipv6->ip6_vfc != IPV6_VERSION) - { - DPRINTF(("ip4_input(): wrong version %d on packet from %s to %s (%s->%s)\n", ipi->ip_v, inet_ntoa4(ipo->ip_src), inet_ntoa4(ipo->ip_dst), inet6_ntoa4(ipv6->ip6_src), inet6_ntoa4(ipv6->ip6_dst))); - ip4stat.ip4s_notip4++; - m_freem(m); - return; - } - - /* XXX Do we need to check that we don't have double-headers ? */ + DPRINTF(("ip4_input(): wrong version %d on packet from %s to %s (%s->%s)\n", ipo->ip_v, inet_ntoa4(ipo->ip_src), inet_ntoa4(ipo->ip_dst), inet_ntoa4(ipo->ip_src), inet_ntoa4(ipo->ip_dst))); + ip4stat.ip4s_notip4++; + m_freem(m); + return; } -#endif /* INET6 */ /* - * Check remote packets for local address spoofing. + * If we do not accept IP4 other than as part of ESP & AH, we should + * not accept a packet with double ip4 headers neither. */ + + if (!ip4_allow && ((ipo->ip_p == IPPROTO_IPIP) || + (ipo->ip_p == IPPROTO_IPV6))) + { + DPRINTF(("ip4_input(): dropped due to policy\n")); + ip4stat.ip4s_pdrops++; + m_freem(m); + return; + } + /* Check for local address spoofing. */ if (m->m_pkthdr.rcvif == NULL || !(m->m_pkthdr.rcvif->if_flags & IFF_LOOPBACK)) { @@ -245,69 +214,27 @@ ip4_input(m, va_alist) ifa != 0; ifa = ifa->ifa_list.tqe_next) { - switch (ipo->ip_p) - { - case IPPROTO_IPIP: - if (ifa->ifa_addr->sa_family != AF_INET) - continue; - - sin = (struct sockaddr_in *) ifa->ifa_addr; - - if (sin->sin_addr.s_addr == ipi->ip_src.s_addr) - { - DPRINTF(("ip_input(): possible local address spoofing detected on packet from %s to %s (%s->%s)\n", inet_ntoa4(ipo->ip_src), inet_ntoa4(ipo->ip_dst), inet_ntoa4(ipi->ip_src), inet_ntoa4(ipi->ip_dst))); - ip4stat.ip4s_spoof++; - m_freem(m); - return; - } - - break; - -#ifdef INET6 - case IPPROTO_IPV6: - if (ifa->ifa_addr->sa_family != AF_INET6) - continue; + if (ifa->ifa_addr->sa_family != AF_INET) + continue; - sin6 = (struct sockaddr_in6 *) ifa->ifa_addr; + sin = (struct sockaddr_in *) ifa->ifa_addr; - if (IN6_ARE_ADDR_EQUAL(&sin6->sin6_addr, &ipv6->ip6_src)) - { - DPRINTF(("ip_input(): possible local address spoofing detected on packet from %s to %s (%s->%s)\n", inet_ntoa4(ipo->ip_src), inet_ntoa4(ipo->ip_dst), inet6_ntoa4(ipv6->ip6_src), inet6_ntoa4(ipv6->ip6_dst))); - ip4stat.ip4s_spoof++; - m_freem(m); - return; - } - - break; -#endif /* INET6 */ + if (sin->sin_addr.s_addr == ipo->ip_src.s_addr) + { + DPRINTF(("ip_input(): possible local address spoofing detected on packet from %s to %s (%s->%s)\n", inet_ntoa4(ipo->ip_src), inet_ntoa4(ipo->ip_dst), inet_ntoa4(ipo->ip_src), inet_ntoa4(ipo->ip_dst))); + ip4stat.ip4s_spoof++; + m_freem(m); + return; } - } } /* Statistics */ ip4stat.ip4s_ibytes += m->m_pkthdr.len - iphlen; - /* Determine whether we need to queue in IPv4 or IPv6 input queue */ - ifq = &ipintrq; - -#ifdef INET6 - if (ipo->ip_p == IPPROTO_IPV6) - ifq = &ip6intrq; -#endif - - /* - * Interface pointer is already in first mbuf; chop off the - * `outer' header and reschedule. - */ - - m->m_len -= iphlen; - m->m_pkthdr.len -= iphlen; - m->m_data += iphlen; - /* tdbi is only set in ESP or AH, if the next protocol is UDP or TCP */ if (m->m_flags & (M_CONF|M_AUTH)) - m->m_pkthdr.tdbi = NULL; + m->m_pkthdr.tdbi = NULL; /* * Interface pointer stays the same; if no IPsec processing has @@ -317,6 +244,8 @@ ip4_input(m, va_alist) * untrusted packets. */ + ifq = &ipintrq; + s = splimp(); /* isn't it already? */ if (IF_QFULL(ifq)) { @@ -330,16 +259,9 @@ ip4_input(m, va_alist) } IF_ENQUEUE(ifq, m); - - if (ifq == &ipintrq) - schednetisr(NETISR_IP); - -#ifdef INET6 - if (ifq == &ip6intrq) - schednetisr(NETISR_IPV6); -#endif /* INET6 */ - + schednetisr(NETISR_IP); splx(s); + return; } |