summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/net/if_enc.c85
-rw-r--r--sys/netipsec/ipsec.h11
-rw-r--r--sys/netipsec/ipsec_input.c23
-rw-r--r--sys/netipsec/ipsec_output.c26
-rw-r--r--sys/netipsec/xform.h3
-rw-r--r--sys/netipsec/xform_ipip.c16
6 files changed, 146 insertions, 18 deletions
diff --git a/sys/net/if_enc.c b/sys/net/if_enc.c
index e8d279c..3ab9081 100644
--- a/sys/net/if_enc.c
+++ b/sys/net/if_enc.c
@@ -60,7 +60,9 @@
#include <netinet6/ip6_var.h>
#endif
+#include "opt_enc.h"
#include <netipsec/ipsec.h>
+#include <netipsec/xform.h>
#define ENCMTU (1024+512)
@@ -90,6 +92,32 @@ static void enc_clone_destroy(struct ifnet *);
IFC_SIMPLE_DECLARE(enc, 1);
+/*
+ * Sysctls.
+ */
+
+/*
+ * Before and after are relative to when we are stripping the
+ * outer IP header.
+ */
+SYSCTL_NODE(_net, OID_AUTO, enc, CTLFLAG_RW, 0, "enc sysctl");
+
+SYSCTL_NODE(_net_enc, OID_AUTO, in, CTLFLAG_RW, 0, "enc input sysctl");
+static int ipsec_filter_mask_in = ENC_BEFORE;
+SYSCTL_XINT(_net_enc_in, OID_AUTO, ipsec_filter_mask, CTLFLAG_RW,
+ &ipsec_filter_mask_in, 0, "IPsec input firewall filter mask");
+static int ipsec_bpf_mask_in = ENC_BEFORE;
+SYSCTL_XINT(_net_enc_in, OID_AUTO, ipsec_bpf_mask, CTLFLAG_RW,
+ &ipsec_bpf_mask_in, 0, "IPsec input bpf mask");
+
+SYSCTL_NODE(_net_enc, OID_AUTO, out, CTLFLAG_RW, 0, "enc output sysctl");
+static int ipsec_filter_mask_out = ENC_BEFORE;
+SYSCTL_XINT(_net_enc_out, OID_AUTO, ipsec_filter_mask, CTLFLAG_RW,
+ &ipsec_filter_mask_out, 0, "IPsec output firewall filter mask");
+static int ipsec_bpf_mask_out = ENC_BEFORE|ENC_AFTER;
+SYSCTL_XINT(_net_enc_out, OID_AUTO, ipsec_bpf_mask, CTLFLAG_RW,
+ &ipsec_bpf_mask_out, 0, "IPsec output bpf mask");
+
static void
enc_clone_destroy(struct ifnet *ifp)
{
@@ -194,16 +222,26 @@ enc_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
}
int
-ipsec_filter(struct mbuf **mp, int dir)
+ipsec_filter(struct mbuf **mp, int dir, int flags)
{
int error, i;
struct ip *ip;
KASSERT(encif != NULL, ("%s: encif is null", __func__));
+ KASSERT(flags & (ENC_IN|ENC_OUT),
+ ("%s: invalid flags: %04x", __func__, flags));
if ((encif->if_drv_flags & IFF_DRV_RUNNING) == 0)
return (0);
+ if (flags & ENC_IN) {
+ if ((flags & ipsec_filter_mask_in) == 0)
+ return (0);
+ } else {
+ if ((flags & ipsec_filter_mask_out) == 0)
+ return (0);
+ }
+
/* Skip pfil(9) if no filters are loaded */
if (!(PFIL_HOOKED(&inet_pfil_hook)
#ifdef INET6
@@ -269,23 +307,48 @@ bad:
}
void
-ipsec_bpf(struct mbuf *m, struct secasvar *sav, int af)
+ipsec_bpf(struct mbuf *m, struct secasvar *sav, int af, int flags)
{
- int flags;
+ int mflags;
struct enchdr hdr;
KASSERT(encif != NULL, ("%s: encif is null", __func__));
- KASSERT(sav != NULL, ("%s: sav is null", __func__));
+ KASSERT(flags & (ENC_IN|ENC_OUT),
+ ("%s: invalid flags: %04x", __func__, flags));
if ((encif->if_drv_flags & IFF_DRV_RUNNING) == 0)
return;
+ if (flags & ENC_IN) {
+ if ((flags & ipsec_bpf_mask_in) == 0)
+ return;
+ } else {
+ if ((flags & ipsec_bpf_mask_out) == 0)
+ return;
+ }
+
if (bpf_peers_present(encif->if_bpf)) {
- flags = 0;
- if (sav->alg_enc != SADB_EALG_NONE)
- flags |= M_CONF;
- if (sav->alg_auth != SADB_AALG_NONE)
- flags |= M_AUTH;
+ mflags = 0;
+ hdr.spi = 0;
+ if (!sav) {
+ struct m_tag *mtag;
+ mtag = m_tag_find(m, PACKET_TAG_IPSEC_IN_DONE, NULL);
+ if (mtag != NULL) {
+ struct tdb_ident *tdbi;
+ tdbi = (struct tdb_ident *) (mtag + 1);
+ if (tdbi->alg_enc != SADB_EALG_NONE)
+ mflags |= M_CONF;
+ if (tdbi->alg_auth != SADB_AALG_NONE)
+ mflags |= M_AUTH;
+ hdr.spi = tdbi->spi;
+ }
+ } else {
+ if (sav->alg_enc != SADB_EALG_NONE)
+ mflags |= M_CONF;
+ if (sav->alg_auth != SADB_AALG_NONE)
+ mflags |= M_AUTH;
+ hdr.spi = sav->spi;
+ }
/*
* We need to prepend the address family as a four byte
@@ -295,8 +358,8 @@ ipsec_bpf(struct mbuf *m, struct secasvar *sav, int af)
* to it).
*/
hdr.af = af;
- hdr.spi = sav->spi;
- hdr.flags = flags;
+ /* hdr.spi already set above */
+ hdr.flags = mflags;
bpf_mtap2(encif->if_bpf, &hdr, sizeof(hdr), m);
}
diff --git a/sys/netipsec/ipsec.h b/sys/netipsec/ipsec.h
index 1464014..6efacc6 100644
--- a/sys/netipsec/ipsec.h
+++ b/sys/netipsec/ipsec.h
@@ -410,8 +410,15 @@ extern void m_checkalignment(const char* where, struct mbuf *m0,
extern struct mbuf *m_makespace(struct mbuf *m0, int skip, int hlen, int *off);
extern caddr_t m_pad(struct mbuf *m, int n);
extern int m_striphdr(struct mbuf *m, int skip, int hlen);
-extern int ipsec_filter(struct mbuf **, int);
-extern void ipsec_bpf(struct mbuf *, struct secasvar *, int);
+
+#ifdef DEV_ENC
+#define ENC_BEFORE 0x0001
+#define ENC_AFTER 0x0002
+#define ENC_IN 0x0100
+#define ENC_OUT 0x0200
+extern int ipsec_filter(struct mbuf **, int, int);
+extern void ipsec_bpf(struct mbuf *, struct secasvar *, int, int);
+#endif
#endif /* _KERNEL */
#ifndef _KERNEL
diff --git a/sys/netipsec/ipsec_input.c b/sys/netipsec/ipsec_input.c
index cea8aff..63677ec 100644
--- a/sys/netipsec/ipsec_input.c
+++ b/sys/netipsec/ipsec_input.c
@@ -444,6 +444,9 @@ ipsec4_common_input_cb(struct mbuf *m, struct secasvar *sav,
bcopy(&saidx->dst, &tdbi->dst, saidx->dst.sa.sa_len);
tdbi->proto = sproto;
tdbi->spi = sav->spi;
+ /* Cache those two for enc(4) in xform_ipip. */
+ tdbi->alg_auth = sav->alg_auth;
+ tdbi->alg_enc = sav->alg_enc;
m_tag_prepend(m, mtag);
} else if (mt != NULL) {
@@ -458,10 +461,10 @@ ipsec4_common_input_cb(struct mbuf *m, struct secasvar *sav,
* 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);
+ ipsec_bpf(m, sav, AF_INET, ENC_IN|ENC_BEFORE);
if (prot != IPPROTO_IPIP)
- if ((error = ipsec_filter(&m, PFIL_IN)) != 0)
+ if ((error = ipsec_filter(&m, PFIL_IN, ENC_IN|ENC_BEFORE)) != 0)
return (error);
#endif
@@ -703,6 +706,9 @@ ipsec6_common_input_cb(struct mbuf *m, struct secasvar *sav, int skip, int proto
bcopy(&saidx->dst, &tdbi->dst, sizeof(union sockaddr_union));
tdbi->proto = sproto;
tdbi->spi = sav->spi;
+ /* Cache those two for enc(4) in xform_ipip. */
+ tdbi->alg_auth = sav->alg_auth;
+ tdbi->alg_enc = sav->alg_enc;
m_tag_prepend(m, mtag);
} else {
@@ -713,6 +719,19 @@ ipsec6_common_input_cb(struct mbuf *m, struct secasvar *sav, int skip, int proto
key_sa_recordxfer(sav, m);
+#ifdef DEV_ENC
+ /*
+ * 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
+
/* Retrieve new protocol */
m_copydata(m, protoff, sizeof(u_int8_t), (caddr_t) &nxt8);
diff --git a/sys/netipsec/ipsec_output.c b/sys/netipsec/ipsec_output.c
index 27ad224..ae7c08b 100644
--- a/sys/netipsec/ipsec_output.c
+++ b/sys/netipsec/ipsec_output.c
@@ -362,8 +362,10 @@ ipsec4_process_packet(
sav = isr->sav;
#ifdef DEV_ENC
+ /* pass the mbuf to enc0 for bpf processing */
+ ipsec_bpf(m, sav, AF_INET, ENC_OUT|ENC_BEFORE);
/* pass the mbuf to enc0 for packet filtering */
- if ((error = ipsec_filter(&m, PFIL_OUT)) != 0)
+ if ((error = ipsec_filter(&m, PFIL_OUT, ENC_OUT|ENC_BEFORE)) != 0)
goto bad;
#endif
@@ -466,7 +468,10 @@ ipsec4_process_packet(
#ifdef DEV_ENC
/* pass the mbuf to enc0 for bpf processing */
- ipsec_bpf(m, sav, AF_INET);
+ ipsec_bpf(m, sav, AF_INET, ENC_OUT|ENC_AFTER);
+ /* pass the mbuf to enc0 for packet filtering */
+ if ((error = ipsec_filter(&m, PFIL_OUT, ENC_OUT|ENC_AFTER)) != 0)
+ goto bad;
#endif
/*
@@ -710,6 +715,14 @@ ipsec6_output_tunnel(struct ipsec_output_state *state, struct secpolicy *sp, int
if (isr == NULL)
goto bad;
+#ifdef DEV_ENC
+ /* pass the mbuf to enc0 for bpf processing */
+ ipsec_bpf(m, isr->sav, AF_INET6, ENC_OUT|ENC_BEFORE);
+ /* pass the mbuf to enc0 for packet filtering */
+ if ((error = ipsec_filter(&m, PFIL_OUT, ENC_OUT|ENC_BEFORE)) != 0)
+ goto bad;
+#endif
+
/*
* There may be the case that SA status will be changed when
* we are refering to one. So calling splsoftnet().
@@ -778,6 +791,15 @@ ipsec6_output_tunnel(struct ipsec_output_state *state, struct secpolicy *sp, int
goto bad;
}
ip6 = mtod(m, struct ip6_hdr *);
+
+#ifdef DEV_ENC
+ /* pass the mbuf to enc0 for bpf processing */
+ ipsec_bpf(m, isr->sav, AF_INET6, ENC_OUT|ENC_AFTER);
+ /* pass the mbuf to enc0 for packet filtering */
+ if ((error = ipsec_filter(&m, PFIL_OUT, ENC_OUT|ENC_AFTER)) != 0)
+ goto bad;
+#endif
+
error = (*isr->sav->tdb_xform->xf_output)(m, isr, NULL,
sizeof (struct ip6_hdr),
offsetof(struct ip6_hdr, ip6_nxt));
diff --git a/sys/netipsec/xform.h b/sys/netipsec/xform.h
index 58509c5..92f7866 100644
--- a/sys/netipsec/xform.h
+++ b/sys/netipsec/xform.h
@@ -57,6 +57,9 @@ struct tdb_ident {
u_int32_t spi;
union sockaddr_union dst;
u_int8_t proto;
+ /* Cache those two for enc(4) in xform_ipip. */
+ u_int8_t alg_auth;
+ u_int8_t alg_enc;
};
/*
diff --git a/sys/netipsec/xform_ipip.c b/sys/netipsec/xform_ipip.c
index 80fafd2..e0f54f5 100644
--- a/sys/netipsec/xform_ipip.c
+++ b/sys/netipsec/xform_ipip.c
@@ -348,8 +348,22 @@ _ipip_input(struct mbuf *m, int iphlen, struct ifnet *gifp)
ipipstat.ipips_ibytes += m->m_pkthdr.len - iphlen;
#ifdef DEV_ENC
+ switch (v >> 4) {
+#ifdef INET
+ case 4:
+ ipsec_bpf(m, NULL, AF_INET, ENC_IN|ENC_AFTER);
+ break;
+#endif
+#ifdef INET6
+ case 6:
+ ipsec_bpf(m, NULL, AF_INET6, ENC_IN|ENC_AFTER);
+ break;
+#endif
+ default:
+ panic("%s: bogus ip version %u", __func__, v>>4);
+ }
/* pass the mbuf to enc0 for packet filtering */
- if (ipsec_filter(&m, PFIL_IN) != 0)
+ if (ipsec_filter(&m, PFIL_IN, ENC_IN|ENC_AFTER) != 0)
return;
#endif
OpenPOWER on IntegriCloud