-/* $OpenBSD: ip_input.c,v 1.313 2017/06/26 19:06:12 bluhm Exp $ */
+/* $OpenBSD: ip_input.c,v 1.314 2017/07/05 11:34:10 bluhm Exp $ */
/* $NetBSD: ip_input.c,v 1.30 1996/03/16 23:53:58 christos Exp $ */
/*
#include <netinet/ip_var.h>
#include <netinet/ip_icmp.h>
+#ifdef INET6
+#include <netinet6/ip6protosw.h>
+#include <netinet6/ip6_var.h>
+#endif
+
#if NPF > 0
#include <net/pfvar.h>
#endif
int
ip_ours(struct mbuf **mp, int *offp, int nxt, int af)
{
+ /* We are already in a IPv4/IPv6 local deliver loop. */
+ if (af != AF_UNSPEC)
+ return ip_local(mp, offp, nxt, af);
+
niq_enqueue(&ipintrq, *mp);
*mp = NULL;
return IPPROTO_DONE;
}
*offp = hlen;
- return ip_deliver(mp, offp, ip->ip_p, AF_INET);
+ nxt = ip->ip_p;
+ /* Check wheter we are already in a IPv4/IPv6 local deliver loop. */
+ if (af == AF_UNSPEC)
+ nxt = ip_deliver(mp, offp, nxt, AF_INET);
+ return nxt;
bad:
m_freemp(mp);
return IPPROTO_DONE;
}
+#ifndef INET6
+#define IPSTAT_INC(name) ipstat_inc(ips_##name)
+#else
+#define IPSTAT_INC(name) (af == AF_INET ? \
+ ipstat_inc(ips_##name) : ip6stat_inc(ip6s_##name))
+#endif
+
int
ip_deliver(struct mbuf **mp, int *offp, int nxt, int af)
{
+ struct protosw *psw;
+ int naf = af;
+#ifdef INET6
+ int nest = 0;
+#endif /* INET6 */
+
KERNEL_ASSERT_LOCKED();
/* pf might have modified stuff, might have to chksum */
- in_proto_cksum_out(*mp, NULL);
+ switch (af) {
+ case AF_INET:
+ in_proto_cksum_out(*mp, NULL);
+ break;
+#ifdef INET6
+ case AF_INET6:
+ in6_proto_cksum_out(*mp, NULL);
+ break;
+#endif /* INET6 */
+ }
-#ifdef IPSEC
- if (ipsec_in_use) {
- if (ipsec_local_check(*mp, *offp, nxt, af) != 0) {
- ipstat_inc(ips_cantforward);
+ /*
+ * Tell launch routine the next header
+ */
+ IPSTAT_INC(delivered);
+
+ while (nxt != IPPROTO_DONE) {
+#ifdef INET6
+ if (af == AF_INET6 &&
+ ip6_hdrnestlimit && (++nest > ip6_hdrnestlimit)) {
+ ip6stat_inc(ip6s_toomanyhdr);
goto bad;
}
- }
- /* Otherwise, just fall through and deliver the packet */
+#endif /* INET6 */
+
+ /*
+ * protection against faulty packet - there should be
+ * more sanity checks in header chain processing.
+ */
+ if ((*mp)->m_pkthdr.len < *offp) {
+ IPSTAT_INC(tooshort);
+ goto bad;
+ }
+
+#ifdef INET6
+ /* draft-itojun-ipv6-tcp-to-anycast */
+ if (af == AF_INET6 &&
+ ISSET((*mp)->m_flags, M_ACAST) && (nxt == IPPROTO_TCP)) {
+ if ((*mp)->m_len >= sizeof(struct ip6_hdr)) {
+ icmp6_error(*mp, ICMP6_DST_UNREACH,
+ ICMP6_DST_UNREACH_ADDR,
+ offsetof(struct ip6_hdr, ip6_dst));
+ *mp = NULL;
+ }
+ goto bad;
+ }
+#endif /* INET6 */
+
+#ifdef IPSEC
+ if (ipsec_in_use) {
+ if (ipsec_local_check(*mp, *offp, nxt, af) != 0) {
+ IPSTAT_INC(cantforward);
+ goto bad;
+ }
+ }
+ /* Otherwise, just fall through and deliver the packet */
#endif /* IPSEC */
- /*
- * Switch out to protocol's input routine.
- */
- ipstat_inc(ips_delivered);
- nxt = (*inetsw[ip_protox[nxt]].pr_input)(mp, offp, nxt, af);
- KASSERT(nxt == IPPROTO_DONE);
+ switch (nxt) {
+ case IPPROTO_IPV4:
+ naf = AF_INET;
+ ipstat_inc(ips_delivered);
+ break;
+#ifdef INET6
+ case IPPROTO_IPV6:
+ naf = AF_INET6;
+ ip6stat_inc(ip6s_delivered);
+ break;
+#endif /* INET6 */
+ }
+ switch (af) {
+ case AF_INET:
+ psw = &inetsw[ip_protox[nxt]];
+ break;
+#ifdef INET6
+ case AF_INET6:
+ psw = &inet6sw[ip6_protox[nxt]];
+ break;
+#endif /* INET6 */
+ }
+ nxt = (*psw->pr_input)(mp, offp, nxt, af);
+ af = naf;
+ }
return nxt;
#ifdef IPSEC
bad:
m_freemp(mp);
return IPPROTO_DONE;
}
+#undef IPSTAT_INC
int
in_ouraddr(struct mbuf *m, struct ifnet *ifp, struct rtentry **prt)
-/* $OpenBSD: ip_ipip.c,v 1.85 2017/06/20 11:12:13 bluhm Exp $ */
+/* $OpenBSD: ip_ipip.c,v 1.86 2017/07/05 11:34:10 bluhm Exp $ */
/*
* The authors of this code are John Ioannidis (ji@tla.org),
* Angelos D. Keromytis (kermit@csd.uch.gr) and
switch (proto) {
case IPPROTO_IPV4:
- ipv4_input(ifp, m);
- *mp = NULL;
- return IPPROTO_DONE;
+ return ip_input_if(mp, offp, proto, oaf, ifp);
#ifdef INET6
case IPPROTO_IPV6:
- ipv6_input(ifp, m);
- *mp = NULL;
- return IPPROTO_DONE;
+ return ip6_input_if(mp, offp, proto, oaf, ifp);
#endif
}
bad:
-/* $OpenBSD: ipsec_input.c,v 1.155 2017/06/19 17:58:49 bluhm Exp $ */
+/* $OpenBSD: ipsec_input.c,v 1.156 2017/07/05 11:34:10 bluhm Exp $ */
/*
* The authors of this code are John Ioannidis (ji@tla.org),
* Angelos D. Keromytis (kermit@csd.uch.gr) and
}
#endif
/* Call the appropriate IPsec transform callback. */
- switch (af) {
- case AF_INET:
- ip_deliver(&m, &skip, prot, af);
- return;
-#ifdef INET6
- case AF_INET6:
- ip6_deliver(&m, &skip, prot, af);
- return;
-#endif /* INET6 */
- default:
- DPRINTF(("ipsec_common_input_cb(): unknown/unsupported "
- "protocol family %d\n", af));
- m_freem(m);
- return;
- }
+ ip_deliver(&m, &skip, prot, af);
#undef IPSEC_ISTAT
}
-/* $OpenBSD: ip6_input.c,v 1.197 2017/06/27 13:28:02 bluhm Exp $ */
+/* $OpenBSD: ip6_input.c,v 1.198 2017/07/05 11:34:10 bluhm Exp $ */
/* $KAME: ip6_input.c,v 1.188 2001/03/29 05:34:31 itojun Exp $ */
/*
int
ip6_ours(struct mbuf **mp, int *offp, int nxt, int af)
{
+ /* We are already in a IPv4/IPv6 local deliver loop. */
+ if (af != AF_UNSPEC)
+ return ip6_local(mp, offp, nxt, af);
+
niq_enqueue(&ip6intrq, *mp);
*mp = NULL;
return IPPROTO_DONE;
}
if (ours) {
- KERNEL_LOCK();
- nxt = ip6_deliver(mp, offp, nxt, AF_INET6);
- KERNEL_UNLOCK();
+ if (af == AF_UNSPEC) {
+ KERNEL_LOCK();
+ nxt = ip_deliver(mp, offp, nxt,
+ AF_INET6);
+ KERNEL_UNLOCK();
+ }
goto out;
}
goto bad;
goto out;
if (ours) {
- KERNEL_LOCK();
- nxt = ip6_deliver(mp, offp, nxt, AF_INET6);
- KERNEL_UNLOCK();
+ if (af == AF_UNSPEC) {
+ KERNEL_LOCK();
+ nxt = ip_deliver(mp, offp, nxt, AF_INET6);
+ KERNEL_UNLOCK();
+ }
goto out;
}
if (ip6_hbhchcheck(*mp, offp, &nxt, NULL))
return IPPROTO_DONE;
- return ip6_deliver(mp, offp, nxt, AF_INET6);
-}
-
-int
-ip6_deliver(struct mbuf **mp, int *offp, int nxt, int af)
-{
- int nest = 0;
-
- KERNEL_ASSERT_LOCKED();
-
- /* pf might have changed things */
- in6_proto_cksum_out(*mp, NULL);
-
- /*
- * Tell launch routine the next header
- */
- ip6stat_inc(ip6s_delivered);
-
- while (nxt != IPPROTO_DONE) {
- if (ip6_hdrnestlimit && (++nest > ip6_hdrnestlimit)) {
- ip6stat_inc(ip6s_toomanyhdr);
- goto bad;
- }
-
- /*
- * protection against faulty packet - there should be
- * more sanity checks in header chain processing.
- */
- if ((*mp)->m_pkthdr.len < *offp) {
- ip6stat_inc(ip6s_tooshort);
- goto bad;
- }
-
- /* draft-itojun-ipv6-tcp-to-anycast */
- if (ISSET((*mp)->m_flags, M_ACAST) && (nxt == IPPROTO_TCP)) {
- if ((*mp)->m_len >= sizeof(struct ip6_hdr)) {
- icmp6_error(*mp, ICMP6_DST_UNREACH,
- ICMP6_DST_UNREACH_ADDR,
- offsetof(struct ip6_hdr, ip6_dst));
- *mp = NULL;
- }
- goto bad;
- }
-
-#ifdef IPSEC
- if (ipsec_in_use) {
- if (ipsec_local_check(*mp, *offp, nxt, af) != 0) {
- ip6stat_inc(ip6s_cantforward);
- goto bad;
- }
- }
- /* Otherwise, just fall through and deliver the packet */
-#endif /* IPSEC */
-
- nxt = (*inet6sw[ip6_protox[nxt]].pr_input)(mp, offp, nxt, af);
- }
+ /* Check wheter we are already in a IPv4/IPv6 local deliver loop. */
+ if (af == AF_UNSPEC)
+ nxt = ip_deliver(mp, offp, nxt, AF_INET6);
return nxt;
- bad:
- m_freemp(mp);
- return IPPROTO_DONE;
}
int
-/* $OpenBSD: ip6_var.h,v 1.76 2017/06/27 13:28:02 bluhm Exp $ */
+/* $OpenBSD: ip6_var.h,v 1.77 2017/07/05 11:34:10 bluhm Exp $ */
/* $KAME: ip6_var.h,v 1.33 2000/06/11 14:59:20 jinmei Exp $ */
/*
void ip6_init(void);
void ip6intr(void);
int ip6_input_if(struct mbuf **, int *, int, int, struct ifnet *);
-int ip6_deliver(struct mbuf **, int *, int, int);
void ip6_freepcbopts(struct ip6_pktopts *);
void ip6_freemoptions(struct ip6_moptions *);
int ip6_unknown_opt(u_int8_t *, struct mbuf *, int);