From d81208c9488e0efbf99f327d11bbd7bc055c5b1b Mon Sep 17 00:00:00 2001 From: ae Date: Wed, 25 Nov 2015 07:31:59 +0000 Subject: 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). --- sys/netipsec/ipsec.c | 30 ++++++++++++++++++ sys/netipsec/ipsec.h | 17 ++++++----- sys/netipsec/ipsec_input.c | 74 ++++++++++++++------------------------------- sys/netipsec/ipsec_output.c | 61 ++++++++++++------------------------- 4 files changed, 80 insertions(+), 102 deletions(-) (limited to 'sys/netipsec') 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 #include #include +#include #include #include #include @@ -55,6 +56,7 @@ #include #include +#include #include #include @@ -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 +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 #include @@ -53,11 +52,12 @@ #include #include #include +#include #include #include #include -#include +#include #include #include @@ -94,10 +94,6 @@ #include #include -#ifdef DEV_ENC -#include -#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 #include @@ -41,11 +40,12 @@ #include #include #include +#include #include #include +#include #include -#include #include #include @@ -88,11 +88,6 @@ #include #endif -#ifdef DEV_ENC -#include -#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) -- cgit v1.1