summaryrefslogtreecommitdiffstats
path: root/sys/netipsec
diff options
context:
space:
mode:
authorae <ae@FreeBSD.org>2015-11-25 07:31:59 +0000
committerae <ae@FreeBSD.org>2015-11-25 07:31:59 +0000
commitd81208c9488e0efbf99f327d11bbd7bc055c5b1b (patch)
tree180d9bca9c02ba401375a447b28937f28cfb981d /sys/netipsec
parentda001d5bf7a7acfef070a8f605c3ec452d374d09 (diff)
downloadFreeBSD-src-d81208c9488e0efbf99f327d11bbd7bc055c5b1b.zip
FreeBSD-src-d81208c9488e0efbf99f327d11bbd7bc055c5b1b.tar.gz
Overhaul if_enc(4) and make it loadable in run-time.
Use hhook(9) framework to achieve ability of loading and unloading if_enc(4) kernel module. INET and INET6 code on initialization registers two helper hooks points in the kernel. if_enc(4) module uses these helper hook points and registers its hooks. IPSEC code uses these hhook points to call helper hooks implemented in if_enc(4).
Diffstat (limited to 'sys/netipsec')
-rw-r--r--sys/netipsec/ipsec.c30
-rw-r--r--sys/netipsec/ipsec.h17
-rw-r--r--sys/netipsec/ipsec_input.c74
-rw-r--r--sys/netipsec/ipsec_output.c61
4 files changed, 80 insertions, 102 deletions
diff --git a/sys/netipsec/ipsec.c b/sys/netipsec/ipsec.c
index 9172347..68a67a7 100644
--- a/sys/netipsec/ipsec.c
+++ b/sys/netipsec/ipsec.c
@@ -48,6 +48,7 @@
#include <sys/socket.h>
#include <sys/socketvar.h>
#include <sys/errno.h>
+#include <sys/hhook.h>
#include <sys/time.h>
#include <sys/kernel.h>
#include <sys/syslog.h>
@@ -55,6 +56,7 @@
#include <sys/proc.h>
#include <net/if.h>
+#include <net/if_enc.h>
#include <net/if_var.h>
#include <net/vnet.h>
@@ -806,6 +808,34 @@ ipsec6_setspidx_ipaddr(struct mbuf *m, struct secpolicyindex *spidx)
}
#endif
+int
+ipsec_run_hhooks(struct ipsec_ctx_data *ctx, int type)
+{
+ int idx;
+
+ switch (ctx->af) {
+#ifdef INET
+ case AF_INET:
+ idx = HHOOK_IPSEC_INET;
+ break;
+#endif
+#ifdef INET6
+ case AF_INET6:
+ idx = HHOOK_IPSEC_INET6;
+ break;
+#endif
+ default:
+ return (EPFNOSUPPORT);
+ }
+ if (type == HHOOK_TYPE_IPSEC_IN)
+ HHOOKS_RUN_IF(V_ipsec_hhh_in[idx], ctx, NULL);
+ else
+ HHOOKS_RUN_IF(V_ipsec_hhh_out[idx], ctx, NULL);
+ if (*ctx->mp == NULL)
+ return (EACCES);
+ return (0);
+}
+
static void
ipsec_delpcbpolicy(struct inpcbpolicy *p)
{
diff --git a/sys/netipsec/ipsec.h b/sys/netipsec/ipsec.h
index c01e54f..9a12c50 100644
--- a/sys/netipsec/ipsec.h
+++ b/sys/netipsec/ipsec.h
@@ -258,6 +258,15 @@ struct ipsecstat {
#ifdef _KERNEL
#include <sys/counter.h>
+struct ipsec_ctx_data;
+#define IPSEC_INIT_CTX(_ctx, _mp, _sav, _af, _enc) do { \
+ (_ctx)->mp = (_mp); \
+ (_ctx)->sav = (_sav); \
+ (_ctx)->af = (_af); \
+ (_ctx)->enc = (_enc); \
+} while(0)
+int ipsec_run_hhooks(struct ipsec_ctx_data *ctx, int direction);
+
VNET_DECLARE(int, ipsec_debug);
#define V_ipsec_debug VNET(ipsec_debug)
@@ -352,14 +361,6 @@ 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);
-#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 6a41ad9..063096f 100644
--- a/sys/netipsec/ipsec_input.c
+++ b/sys/netipsec/ipsec_input.c
@@ -43,7 +43,6 @@
#include "opt_inet.h"
#include "opt_inet6.h"
#include "opt_ipsec.h"
-#include "opt_enc.h"
#include <sys/param.h>
#include <sys/systm.h>
@@ -53,11 +52,12 @@
#include <sys/protosw.h>
#include <sys/socket.h>
#include <sys/errno.h>
+#include <sys/hhook.h>
#include <sys/syslog.h>
#include <net/if.h>
#include <net/if_var.h>
-#include <net/pfil.h>
+#include <net/if_enc.h>
#include <net/netisr.h>
#include <net/vnet.h>
@@ -94,10 +94,6 @@
#include <machine/in_cksum.h>
#include <machine/stdarg.h>
-#ifdef DEV_ENC
-#include <net/if_enc.h>
-#endif
-
#define IPSEC_ISTAT(proto, name) do { \
if ((proto) == IPPROTO_ESP) \
@@ -314,6 +310,7 @@ ipsec4_common_input_cb(struct mbuf *m, struct secasvar *sav, int skip,
int protoff)
{
char buf[INET6_ADDRSTRLEN];
+ struct ipsec_ctx_data ctx;
int prot, af, sproto, isr_prot;
struct ip *ip;
struct m_tag *mtag;
@@ -368,16 +365,10 @@ ipsec4_common_input_cb(struct mbuf *m, struct secasvar *sav, int skip,
}
prot = ip->ip_p;
-#ifdef DEV_ENC
- if_inc_counter(encif, IFCOUNTER_IPACKETS, 1);
- if_inc_counter(encif, IFCOUNTER_IBYTES, m->m_pkthdr.len);
-
- /* Pass the mbuf to enc0 for bpf and pfil. */
- ipsec_bpf(m, sav, AF_INET, ENC_IN|ENC_BEFORE);
- if ((error = ipsec_filter(&m, PFIL_IN, ENC_IN|ENC_BEFORE)) != 0)
- return (error);
+ IPSEC_INIT_CTX(&ctx, &m, sav, AF_INET, IPSEC_ENC_BEFORE);
+ if ((error = ipsec_run_hhooks(&ctx, HHOOK_TYPE_IPSEC_IN)) != 0)
+ goto bad;
ip = mtod(m, struct ip *);
-#endif /* DEV_ENC */
/* IP-in-IP encapsulation */
if (prot == IPPROTO_IPIP &&
@@ -501,32 +492,18 @@ ipsec4_common_input_cb(struct mbuf *m, struct secasvar *sav, int skip,
*/
if (saidx->mode == IPSEC_MODE_TRANSPORT)
prot = IPPROTO_IPIP;
-#ifdef DEV_ENC
- /*
- * Pass the mbuf to enc0 for bpf and pfil.
- */
- 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.
*/
-
switch (prot) {
case IPPROTO_IPIP:
isr_prot = NETISR_IP;
+ af = AF_INET;
break;
#ifdef INET6
case IPPROTO_IPV6:
isr_prot = NETISR_IPV6;
+ af = AF_INET6;
break;
#endif
default:
@@ -537,6 +514,9 @@ ipsec4_common_input_cb(struct mbuf *m, struct secasvar *sav, int skip,
goto bad;
}
+ IPSEC_INIT_CTX(&ctx, &m, sav, af, IPSEC_ENC_AFTER);
+ if ((error = ipsec_run_hhooks(&ctx, HHOOK_TYPE_IPSEC_IN)) != 0)
+ goto bad;
error = netisr_queue_src(isr_prot, (uintptr_t)sav->spi, m);
if (error) {
IPSEC_ISTAT(sproto, qfull);
@@ -611,6 +591,7 @@ ipsec6_common_input_cb(struct mbuf *m, struct secasvar *sav, int skip,
int protoff)
{
char buf[INET6_ADDRSTRLEN];
+ struct ipsec_ctx_data ctx;
int prot, af, sproto;
struct ip6_hdr *ip6;
struct m_tag *mtag;
@@ -658,20 +639,13 @@ ipsec6_common_input_cb(struct mbuf *m, struct secasvar *sav, int skip,
ip6 = mtod(m, struct ip6_hdr *);
ip6->ip6_plen = htons(m->m_pkthdr.len - sizeof(struct ip6_hdr));
+ IPSEC_INIT_CTX(&ctx, &m, sav, af, IPSEC_ENC_BEFORE);
+ if ((error = ipsec_run_hhooks(&ctx, HHOOK_TYPE_IPSEC_IN)) != 0)
+ goto bad;
/* Save protocol */
m_copydata(m, protoff, 1, &nxt8);
prot = nxt8;
-#ifdef DEV_ENC
- if_inc_counter(encif, IFCOUNTER_IPACKETS, 1);
- if_inc_counter(encif, IFCOUNTER_IBYTES, m->m_pkthdr.len);
-
- /* Pass the mbuf to enc0 for bpf and pfil. */
- ipsec_bpf(m, sav, AF_INET6, ENC_IN|ENC_BEFORE);
- if ((error = ipsec_filter(&m, PFIL_IN, ENC_IN|ENC_BEFORE)) != 0)
- return (error);
-#endif /* DEV_ENC */
-
/* IPv6-in-IP encapsulation */
if (prot == IPPROTO_IPV6 &&
saidx->mode != IPSEC_MODE_TRANSPORT) {
@@ -778,20 +752,16 @@ ipsec6_common_input_cb(struct mbuf *m, struct secasvar *sav, int skip,
key_sa_recordxfer(sav, m);
-#ifdef DEV_ENC
- /*
- * Pass the mbuf to enc0 for bpf and pfil.
- */
+
#ifdef INET
if (prot == IPPROTO_IPIP)
- ipsec_bpf(m, sav, AF_INET, ENC_IN|ENC_AFTER);
+ af = AF_INET;
+ else
#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 */
+ af = AF_INET6;
+ IPSEC_INIT_CTX(&ctx, &m, sav, af, IPSEC_ENC_AFTER);
+ if ((error = ipsec_run_hhooks(&ctx, HHOOK_TYPE_IPSEC_IN)) != 0)
+ goto bad;
if (skip == 0) {
/*
* We stripped outer IPv6 header.
diff --git a/sys/netipsec/ipsec_output.c b/sys/netipsec/ipsec_output.c
index f5cdf5a..1523e0b 100644
--- a/sys/netipsec/ipsec_output.c
+++ b/sys/netipsec/ipsec_output.c
@@ -32,7 +32,6 @@
#include "opt_inet.h"
#include "opt_inet6.h"
#include "opt_ipsec.h"
-#include "opt_enc.h"
#include <sys/param.h>
#include <sys/systm.h>
@@ -41,11 +40,12 @@
#include <sys/protosw.h>
#include <sys/socket.h>
#include <sys/errno.h>
+#include <sys/hhook.h>
#include <sys/syslog.h>
#include <net/if.h>
+#include <net/if_enc.h>
#include <net/if_var.h>
-#include <net/pfil.h>
#include <net/vnet.h>
#include <netinet/in.h>
@@ -88,11 +88,6 @@
#include <netinet/udp.h>
#endif
-#ifdef DEV_ENC
-#include <net/if_enc.h>
-#endif
-
-
int
ipsec_process_done(struct mbuf *m, struct ipsecrequest *isr)
{
@@ -531,6 +526,7 @@ int
ipsec4_process_packet(struct mbuf *m, struct ipsecrequest *isr)
{
char sbuf[INET6_ADDRSTRLEN], dbuf[INET6_ADDRSTRLEN];
+ struct ipsec_ctx_data ctx;
union sockaddr_union *dst;
struct secasindex saidx;
struct secasvar *sav;
@@ -555,19 +551,13 @@ ipsec4_process_packet(struct mbuf *m, struct ipsecrequest *isr)
error = ENOBUFS;
goto bad;
}
- ip = mtod(m, struct ip *);
- dst = &sav->sah->saidx.dst;
-#ifdef DEV_ENC
- if_inc_counter(encif, IFCOUNTER_OPACKETS, 1);
- if_inc_counter(encif, IFCOUNTER_OBYTES, m->m_pkthdr.len);
-
- /* 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, ENC_OUT|ENC_BEFORE)) != 0)
+
+ IPSEC_INIT_CTX(&ctx, &m, sav, AF_INET, IPSEC_ENC_BEFORE);
+ if ((error = ipsec_run_hhooks(&ctx, HHOOK_TYPE_IPSEC_OUT)) != 0)
goto bad;
+
ip = mtod(m, struct ip *);
-#endif
+ dst = &sav->sah->saidx.dst;
/* Do the appropriate encapsulation, if necessary */
if (isr->saidx.mode == IPSEC_MODE_TUNNEL || /* Tunnel requ'd */
dst->sa.sa_family != AF_INET || /* PF mismatch */
@@ -589,13 +579,10 @@ ipsec4_process_packet(struct mbuf *m, struct ipsecrequest *isr)
goto bad;
}
}
-#ifdef DEV_ENC
- /* pass the mbuf to enc0 for bpf processing */
- ipsec_bpf(m, sav, sav->sah->saidx.dst.sa.sa_family, ENC_OUT|ENC_AFTER);
- /* pass the mbuf to enc0 for packet filtering */
- if ((error = ipsec_filter(&m, PFIL_OUT, ENC_OUT|ENC_AFTER)) != 0)
+
+ IPSEC_INIT_CTX(&ctx, &m, sav, dst->sa.sa_family, IPSEC_ENC_AFTER);
+ if ((error = ipsec_run_hhooks(&ctx, HHOOK_TYPE_IPSEC_OUT)) != 0)
goto bad;
-#endif
/*
* Dispatch to the appropriate IPsec transform logic. The
@@ -657,6 +644,7 @@ int
ipsec6_process_packet(struct mbuf *m, struct ipsecrequest *isr)
{
char sbuf[INET6_ADDRSTRLEN], dbuf[INET6_ADDRSTRLEN];
+ struct ipsec_ctx_data ctx;
struct secasindex saidx;
struct secasvar *sav;
struct ip6_hdr *ip6;
@@ -677,19 +665,12 @@ ipsec6_process_packet(struct mbuf *m, struct ipsecrequest *isr)
sav = isr->sav;
dst = &sav->sah->saidx.dst;
- ip6 = mtod(m, struct ip6_hdr *);
- ip6->ip6_plen = htons(m->m_pkthdr.len - sizeof(*ip6));
-#ifdef DEV_ENC
- if_inc_counter(encif, IFCOUNTER_OPACKETS, 1);
- if_inc_counter(encif, IFCOUNTER_OBYTES, m->m_pkthdr.len);
-
- /* 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)
+ IPSEC_INIT_CTX(&ctx, &m, sav, AF_INET6, IPSEC_ENC_BEFORE);
+ if ((error = ipsec_run_hhooks(&ctx, HHOOK_TYPE_IPSEC_OUT)) != 0)
goto bad;
+
ip6 = mtod(m, struct ip6_hdr *);
-#endif /* DEV_ENC */
+ ip6->ip6_plen = htons(m->m_pkthdr.len - sizeof(*ip6));
/* Do the appropriate encapsulation, if necessary */
if (isr->saidx.mode == IPSEC_MODE_TUNNEL || /* Tunnel requ'd */
@@ -715,12 +696,9 @@ ipsec6_process_packet(struct mbuf *m, struct ipsecrequest *isr)
}
}
-#ifdef DEV_ENC
- ipsec_bpf(m, isr->sav, dst->sa.sa_family, ENC_OUT|ENC_AFTER);
- /* pass the mbuf to enc0 for packet filtering */
- if ((error = ipsec_filter(&m, PFIL_OUT, ENC_OUT|ENC_AFTER)) != 0)
+ IPSEC_INIT_CTX(&ctx, &m, sav, dst->sa.sa_family, IPSEC_ENC_AFTER);
+ if ((error = ipsec_run_hhooks(&ctx, HHOOK_TYPE_IPSEC_OUT)) != 0)
goto bad;
-#endif /* DEV_ENC */
switch(dst->sa.sa_family) {
#ifdef INET
@@ -741,14 +719,13 @@ ipsec6_process_packet(struct mbuf *m, struct ipsecrequest *isr)
DPRINTF(("%s: unsupported protocol family %u\n",
__func__, dst->sa.sa_family));
error = EPFNOSUPPORT;
- IPSEC6STAT_INC(ips_out_inval);
goto bad;
}
error = (*sav->tdb_xform->xf_output)(m, isr, NULL, i, off);
IPSECREQUEST_UNLOCK(isr);
return error;
bad:
-
+ IPSEC6STAT_INC(ips_out_inval);
if (isr)
IPSECREQUEST_UNLOCK(isr);
if (m)
OpenPOWER on IntegriCloud