summaryrefslogtreecommitdiffstats
path: root/sys/netipsec/ipsec_input.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/netipsec/ipsec_input.c')
-rw-r--r--sys/netipsec/ipsec_input.c136
1 files changed, 89 insertions, 47 deletions
diff --git a/sys/netipsec/ipsec_input.c b/sys/netipsec/ipsec_input.c
index f019581..40ac8d9 100644
--- a/sys/netipsec/ipsec_input.c
+++ b/sys/netipsec/ipsec_input.c
@@ -296,7 +296,7 @@ int
ipsec4_common_input_cb(struct mbuf *m, struct secasvar *sav,
int skip, int protoff, struct m_tag *mt)
{
- int prot, af, sproto;
+ int prot, af, sproto, isr_prot;
struct ip *ip;
struct m_tag *mtag;
struct tdb_ident *tdbi;
@@ -350,20 +350,33 @@ ipsec4_common_input_cb(struct mbuf *m, struct secasvar *sav,
}
prot = ip->ip_p;
-#ifdef notyet
+#ifdef DEV_ENC
+ encif->if_ipackets++;
+ encif->if_ibytes += m->m_pkthdr.len;
+
+ /*
+ * Pass the mbuf to enc0 for bpf and pfil. We will filter the IPIP
+ * packet later after it has been decapsulated.
+ */
+ ipsec_bpf(m, sav, AF_INET, ENC_IN|ENC_BEFORE);
+
+ if (prot != IPPROTO_IPIP)
+ if ((error = ipsec_filter(&m, PFIL_IN, ENC_IN|ENC_BEFORE)) != 0)
+ return (error);
+#endif /* DEV_ENC */
+
/* IP-in-IP encapsulation */
if (prot == IPPROTO_IPIP) {
- struct ip ipn;
if (m->m_pkthdr.len - skip < sizeof(struct ip)) {
IPSEC_ISTAT(sproto, hdrops);
error = EINVAL;
goto bad;
}
- /* ipn will now contain the inner IPv4 header */
- m_copydata(m, ip->ip_hl << 2, sizeof(struct ip),
- (caddr_t) &ipn);
+ /* enc0: strip outer IPv4 header */
+ m_striphdr(m, 0, ip->ip_hl << 2);
+#ifdef notyet
/* XXX PROXY address isn't recorded in SAH */
/*
* Check that the inner source address is the same as
@@ -389,21 +402,20 @@ ipsec4_common_input_cb(struct mbuf *m, struct secasvar *sav,
error = EACCES;
goto bad;
}
+#endif /* notyet */
}
#ifdef INET6
/* IPv6-in-IP encapsulation. */
if (prot == IPPROTO_IPV6) {
- struct ip6_hdr ip6n;
if (m->m_pkthdr.len - skip < sizeof(struct ip6_hdr)) {
IPSEC_ISTAT(sproto, hdrops);
error = EINVAL;
goto bad;
}
- /* ip6n will now contain the inner IPv6 header. */
- m_copydata(m, ip->ip_hl << 2, sizeof(struct ip6_hdr),
- (caddr_t) &ip6n);
-
+ /* enc0: strip IPv4 header, keep IPv6 header only */
+ m_striphdr(m, 0, ip->ip_hl << 2);
+#ifdef notyet
/*
* Check that the inner source address is the same as
* the proxy address, if available.
@@ -427,9 +439,9 @@ ipsec4_common_input_cb(struct mbuf *m, struct secasvar *sav,
error = EACCES;
goto bad;
}
+#endif /* notyet */
}
#endif /* INET6 */
-#endif /*XXX*/
/*
* Record what we've done to the packet (under what SA it was
@@ -466,24 +478,43 @@ ipsec4_common_input_cb(struct mbuf *m, struct secasvar *sav,
key_sa_recordxfer(sav, m); /* record data transfer */
#ifdef DEV_ENC
- encif->if_ipackets++;
- encif->if_ibytes += m->m_pkthdr.len;
-
/*
- * Pass the mbuf to enc0 for bpf and pfil. We will filter the IPIP
- * packet later after it has been decapsulated.
+ * Pass the mbuf to enc0 for bpf and pfil.
*/
- ipsec_bpf(m, sav, AF_INET, ENC_IN|ENC_BEFORE);
-
- if (prot != IPPROTO_IPIP)
- if ((error = ipsec_filter(&m, PFIL_IN, ENC_IN|ENC_BEFORE)) != 0)
- return (error);
+ if (prot == IPPROTO_IPIP)
+ ipsec_bpf(m, sav, AF_INET, ENC_IN|ENC_AFTER);
+#ifdef INET6
+ if (prot == IPPROTO_IPV6)
+ ipsec_bpf(m, sav, AF_INET6, ENC_IN|ENC_AFTER);
#endif
+ if ((error = ipsec_filter(&m, PFIL_IN, ENC_IN|ENC_AFTER)) != 0)
+ return (error);
+#endif /* DEV_ENC */
+
/*
* Re-dispatch via software interrupt.
*/
- if ((error = netisr_queue_src(NETISR_IP, (uintptr_t)sav->spi, m))) {
+
+ switch (prot) {
+ case IPPROTO_IPIP:
+ isr_prot = NETISR_IP;
+ break;
+#ifdef INET6
+ case IPPROTO_IPV6:
+ isr_prot = NETISR_IPV6;
+ break;
+#endif
+ default:
+ DPRINTF(("%s: cannot handle inner ip proto %d\n",
+ __func__, prot));
+ IPSEC_ISTAT(sproto, nopf);
+ error = EPFNOSUPPORT;
+ goto bad;
+ }
+
+ error = netisr_queue_src(isr_prot, (uintptr_t)sav->spi, m);
+ if (error) {
IPSEC_ISTAT(sproto, qfull);
DPRINTF(("%s: queue full; proto %u packet dropped\n",
__func__, sproto));
@@ -606,20 +637,34 @@ ipsec6_common_input_cb(struct mbuf *m, struct secasvar *sav, int skip, int proto
prot = 0;
m_copydata(m, protoff, 1, (unsigned char *) &prot);
-#ifdef notyet
+#ifdef DEV_ENC
+ encif->if_ipackets++;
+ encif->if_ibytes += m->m_pkthdr.len;
+
+ /*
+ * Pass the mbuf to enc0 for bpf and pfil. We will filter the IPIP
+ * packet later after it has been decapsulated.
+ */
+ ipsec_bpf(m, sav, AF_INET6, ENC_IN|ENC_BEFORE);
+
+ /* XXX-BZ does not make sense. */
+ if (prot != IPPROTO_IPIP)
+ if ((error = ipsec_filter(&m, PFIL_IN, ENC_IN|ENC_BEFORE)) != 0)
+ return (error);
+#endif /* DEV_ENC */
+
#ifdef INET
/* IP-in-IP encapsulation */
if (prot == IPPROTO_IPIP) {
- struct ip ipn;
-
if (m->m_pkthdr.len - skip < sizeof(struct ip)) {
IPSEC_ISTAT(sproto, hdrops);
error = EINVAL;
goto bad;
}
/* ipn will now contain the inner IPv4 header */
- m_copydata(m, skip, sizeof(struct ip), (caddr_t) &ipn);
-
+ m_striphdr(m, 0, skip);
+ skip = 0;
+#ifdef notyet
/*
* Check that the inner source address is the same as
* the proxy address, if available.
@@ -642,22 +687,20 @@ ipsec6_common_input_cb(struct mbuf *m, struct secasvar *sav, int skip, int proto
error = EACCES;
goto bad;
}
+#endif /* notyet */
}
#endif /* INET */
-
/* IPv6-in-IP encapsulation */
if (prot == IPPROTO_IPV6) {
- struct ip6_hdr ip6n;
-
if (m->m_pkthdr.len - skip < sizeof(struct ip6_hdr)) {
IPSEC_ISTAT(sproto, hdrops);
error = EINVAL;
goto bad;
}
/* ip6n will now contain the inner IPv6 header. */
- m_copydata(m, skip, sizeof(struct ip6_hdr),
- (caddr_t) &ip6n);
-
+ m_striphdr(m, 0, skip);
+ skip = 0;
+#ifdef notyet
/*
* Check that the inner source address is the same as
* the proxy address, if available.
@@ -681,8 +724,8 @@ ipsec6_common_input_cb(struct mbuf *m, struct secasvar *sav, int skip, int proto
error = EACCES;
goto bad;
}
+#endif /* notyet */
}
-#endif /*XXX*/
/*
* Record what we've done to the packet (under what SA it was
@@ -720,23 +763,22 @@ ipsec6_common_input_cb(struct mbuf *m, struct secasvar *sav, int skip, int proto
key_sa_recordxfer(sav, m);
#ifdef DEV_ENC
- encif->if_ipackets++;
- encif->if_ibytes += m->m_pkthdr.len;
-
/*
- * Pass the mbuf to enc0 for bpf and pfil. We will filter the IPIP
- * packet later after it has been decapsulated.
+ * Pass the mbuf to enc0 for bpf and pfil.
*/
- ipsec_bpf(m, sav, AF_INET6, ENC_IN|ENC_BEFORE);
-
- /* XXX-BZ does not make sense. */
- if (prot != IPPROTO_IPIP)
- if ((error = ipsec_filter(&m, PFIL_IN, ENC_IN|ENC_BEFORE)) != 0)
- return (error);
+#ifdef INET
+ if (prot == IPPROTO_IPIP)
+ ipsec_bpf(m, sav, AF_INET, ENC_IN|ENC_AFTER);
#endif
+ if (prot == IPPROTO_IPV6)
+ ipsec_bpf(m, sav, AF_INET6, ENC_IN|ENC_AFTER);
+ if ((error = ipsec_filter(&m, PFIL_IN, ENC_IN|ENC_AFTER)) != 0)
+ return (error);
+#endif /* DEV_ENC */
/* Retrieve new protocol */
- m_copydata(m, protoff, sizeof(u_int8_t), (caddr_t) &nxt8);
+ /* We have stripped the IP6 header from the mbuf, we have to use the backuped proto value instead */
+ nxt8 = prot;
/*
* See the end of ip6_input for this logic.
OpenPOWER on IntegriCloud