Date: Mon, 26 Dec 2016 21:09:03 +0000 (UTC) From: "Andrey V. Elsukov" <ae@FreeBSD.org> To: src-committers@freebsd.org, svn-src-projects@freebsd.org Subject: svn commit: r310619 - in projects/ipsec/sys: conf modules modules/ipsec modules/tcp/tcpmd5 netipsec Message-ID: <201612262109.uBQL939W008208@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: ae Date: Mon Dec 26 21:09:02 2016 New Revision: 310619 URL: https://svnweb.freebsd.org/changeset/base/310619 Log: Make IPsec and TCP-MD5 support loadable. ipsec_support.h declares different macros and structures depending from defined kernel options. There are several ponters to structures, that contains IPsec methods implementations. When IPsec support is build in the kernel, IPsec methods are called directly using these pointers. For example: struct ipsec_support { const u_int enabled; const struct ipsec_methods * const methods; }; extern const struct ipsec_support * const ipv4_ipsec_support; extern const struct ipsec_support * const ipv6_ipsec_support; #define IPSEC_INPUT(proto, m, ...) \ (*(proto ## _ipsec_support)->methods->input)(m, __VA_ARGS__) When IPsec support is build as module, these look like: struct ipsec_support { volatile u_int enabled; const struct ipsec_methods * volatile methods; }; extern struct ipsec_support * const ipv4_ipsec_support; extern struct ipsec_support * const ipv6_ipsec_support; #define IPSEC_INPUT(proto, ...) \ ipsec_kmod_input(proto ## _ipsec_support, __VA_ARGS__) IPsec methods are called via wrappers. The wrapper uses atomic operations to do reference counting to prevent access to methods when they are unloaded. Added: projects/ipsec/sys/modules/ipsec/ projects/ipsec/sys/modules/ipsec/Makefile (contents, props changed) projects/ipsec/sys/modules/tcp/tcpmd5/ projects/ipsec/sys/modules/tcp/tcpmd5/Makefile (contents, props changed) projects/ipsec/sys/netipsec/ipsec_mod.c (contents, props changed) Modified: projects/ipsec/sys/conf/files projects/ipsec/sys/modules/Makefile projects/ipsec/sys/netipsec/ipsec.h projects/ipsec/sys/netipsec/ipsec6.h projects/ipsec/sys/netipsec/ipsec_mbuf.c projects/ipsec/sys/netipsec/ipsec_pcb.c projects/ipsec/sys/netipsec/ipsec_support.h projects/ipsec/sys/netipsec/subr_ipsec.c projects/ipsec/sys/netipsec/xform_ipcomp.c projects/ipsec/sys/netipsec/xform_tcp.c Modified: projects/ipsec/sys/conf/files ============================================================================== --- projects/ipsec/sys/conf/files Mon Dec 26 20:36:37 2016 (r310618) +++ projects/ipsec/sys/conf/files Mon Dec 26 21:09:02 2016 (r310619) @@ -4157,6 +4157,7 @@ netinet6/udp6_usrreq.c optional inet6 netipsec/ipsec.c optional ipsec inet | ipsec inet6 netipsec/ipsec_input.c optional ipsec inet | ipsec inet6 netipsec/ipsec_mbuf.c optional ipsec inet | ipsec inet6 +netipsec/ipsec_mod.c optional ipsec inet | ipsec inet6 netipsec/ipsec_output.c optional ipsec inet | ipsec inet6 netipsec/ipsec_pcb.c optional ipsec inet | ipsec inet6 | \ ipsec_support inet | ipsec_support inet6 Modified: projects/ipsec/sys/modules/Makefile ============================================================================== --- projects/ipsec/sys/modules/Makefile Mon Dec 26 20:36:37 2016 (r310618) +++ projects/ipsec/sys/modules/Makefile Mon Dec 26 21:09:02 2016 (r310619) @@ -179,6 +179,7 @@ SUBDIR= \ ip6_mroute_mod \ ip_mroute_mod \ ${_ips} \ + ${_ipsec} \ ${_ipw} \ ${_ipwfw} \ ${_isci} \ @@ -361,6 +362,7 @@ SUBDIR= \ sysvipc \ ${_ti} \ ${_tcp_fastpath} \ + ${_tcpmd5} \ tests/framework \ tests/callout_test \ tl \ @@ -451,6 +453,10 @@ _toecore= toecore _if_enc= if_enc _if_gif= if_gif _if_gre= if_gre +.if ${MK_IPSEC_SUPPORT} != "no" +_ipsec= ipsec +_tcpmd5= tcp/tcpmd5 +.endif .endif .if (${MK_INET_SUPPORT} != "no" && ${MK_INET6_SUPPORT} != "no") || \ Added: projects/ipsec/sys/modules/ipsec/Makefile ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ projects/ipsec/sys/modules/ipsec/Makefile Mon Dec 26 21:09:02 2016 (r310619) @@ -0,0 +1,13 @@ +# $FreeBSD$ + +.PATH: ${.CURDIR}/../../net ${.CURDIR}/../../netipsec + +KMOD= ipsec +SRCS= if_ipsec.c ipsec.c ipsec_input.c ipsec_mbuf.c ipsec_mod.c \ + ipsec_output.c udpencap.c xform_ah.c xform_esp.c xform_ipcomp.c \ + opt_inet.h opt_inet6.h opt_ipsec.h opt_sctp.h + +opt_ipsec.h: + @echo "#define IPSEC_SUPPORT 1" > ${.TARGET} + +.include <bsd.kmod.mk> Added: projects/ipsec/sys/modules/tcp/tcpmd5/Makefile ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ projects/ipsec/sys/modules/tcp/tcpmd5/Makefile Mon Dec 26 21:09:02 2016 (r310619) @@ -0,0 +1,11 @@ +# $FreeBSD$ + +.PATH: ${.CURDIR}/../../../netipsec + +KMOD= tcpmd5 +SRCS= xform_tcp.c opt_inet.h opt_inet6.h opt_ipsec.h + +opt_ipsec.h: + @echo "#define IPSEC_SUPPORT 1" > ${.TARGET} + +.include <bsd.kmod.mk> Modified: projects/ipsec/sys/netipsec/ipsec.h ============================================================================== --- projects/ipsec/sys/netipsec/ipsec.h Mon Dec 26 20:36:37 2016 (r310618) +++ projects/ipsec/sys/netipsec/ipsec.h Mon Dec 26 21:09:02 2016 (r310619) @@ -313,6 +313,8 @@ u_int ipsec_get_reqlevel(struct secpolic void udp_ipsec_adjust_cksum(struct mbuf *, struct secasvar *, int, int); int udp_ipsec_output(struct mbuf *, struct secasvar *); +int udp_ipsec_input(struct mbuf *, int, int); +int udp_ipsec_pcbctl(struct inpcb *, struct sockopt *); int ipsec_chkreplay(uint32_t, struct secasvar *); int ipsec_updatereplay(uint32_t, struct secasvar *); @@ -323,6 +325,7 @@ void ipsec4_setsockaddrs(const struct mb int ipsec4_in_reject(const struct mbuf *, struct inpcb *); int ipsec4_input(struct mbuf *, int, int); int ipsec4_forward(struct mbuf *); +int ipsec4_pcbctl(struct inpcb *, struct sockopt *); int ipsec4_output(struct mbuf *, struct inpcb *); int ipsec4_capability(struct mbuf *, u_int); int ipsec4_common_input_cb(struct mbuf *, struct secasvar *, int, int); Modified: projects/ipsec/sys/netipsec/ipsec6.h ============================================================================== --- projects/ipsec/sys/netipsec/ipsec6.h Mon Dec 26 20:36:37 2016 (r310618) +++ projects/ipsec/sys/netipsec/ipsec6.h Mon Dec 26 21:09:02 2016 (r310619) @@ -67,6 +67,7 @@ void ipsec6_setsockaddrs(const struct mb int ipsec6_input(struct mbuf *, int, int); int ipsec6_in_reject(const struct mbuf *, struct inpcb *); int ipsec6_forward(struct mbuf *); +int ipsec6_pcbctl(struct inpcb *, struct sockopt *); int ipsec6_output(struct mbuf *, struct inpcb *); int ipsec6_capability(struct mbuf *, u_int); int ipsec6_common_input_cb(struct mbuf *, struct secasvar *, int, int); Modified: projects/ipsec/sys/netipsec/ipsec_mbuf.c ============================================================================== --- projects/ipsec/sys/netipsec/ipsec_mbuf.c Mon Dec 26 20:36:37 2016 (r310618) +++ projects/ipsec/sys/netipsec/ipsec_mbuf.c Mon Dec 26 21:09:02 2016 (r310619) @@ -30,8 +30,6 @@ * IPsec-specific mbuf routines. */ -#include "opt_param.h" - #include <sys/param.h> #include <sys/systm.h> #include <sys/malloc.h> Added: projects/ipsec/sys/netipsec/ipsec_mod.c ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ projects/ipsec/sys/netipsec/ipsec_mod.c Mon Dec 26 21:09:02 2016 (r310619) @@ -0,0 +1,146 @@ +/*- + * Copyright (c) 2016 Andrey V. Elsukov <ae@FreeBSD.org> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "opt_inet.h" +#include "opt_inet6.h" +#include "opt_ipsec.h" + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/kernel.h> +#include <sys/lock.h> +#include <sys/malloc.h> +#include <sys/mbuf.h> +#include <sys/module.h> +#include <sys/priv.h> +#include <sys/rmlock.h> +#include <sys/socket.h> +#include <sys/sockopt.h> +#include <sys/syslog.h> +#include <sys/proc.h> + +#include <netinet/in.h> +#include <netinet/in_pcb.h> + +#include <netipsec/ipsec.h> +#include <netipsec/ipsec6.h> +#include <netipsec/key.h> +#include <netipsec/key_debug.h> + +#include <netipsec/ipsec_support.h> + +#ifdef INET +static const struct ipsec_methods ipv4_methods = { + .input = ipsec4_input, + .forward = ipsec4_forward, + .output = ipsec4_output, + .pcbctl = ipsec4_pcbctl, + .capability = ipsec4_capability, + .check_policy = ipsec4_in_reject, + .hdrsize = ipsec_hdrsiz_inpcb, + .udp_input = udp_ipsec_input, + .udp_pcbctl = udp_ipsec_pcbctl, +}; +#ifndef KLD_MODULE +static const struct ipsec_support ipv4_ipsec = { + .enabled = 1, + .methods = &ipv4_methods +}; +const struct ipsec_support * const ipv4_ipsec_support = &ipv4_ipsec; +#endif /* !KLD_MODULE */ +#endif /* INET */ + +#ifdef INET6 +static const struct ipsec_methods ipv6_methods = { + .input = ipsec6_input, + .forward = ipsec6_forward, + .output = ipsec6_output, + .pcbctl = ipsec6_pcbctl, + .capability = ipsec6_capability, + .check_policy = ipsec6_in_reject, + .hdrsize = ipsec_hdrsiz_inpcb, +}; +#ifndef KLD_MODULE +static const struct ipsec_support ipv6_ipsec = { + .enabled = 1, + .methods = &ipv6_methods +}; +const struct ipsec_support * const ipv6_ipsec_support = &ipv6_ipsec; +#endif /* !KLD_MODULE */ +#endif /* INET6 */ + +/* + * Always register ipsec module. + * Even when IPsec is build in the kernel, we need to have + * module registered. This will prevent to load ipsec.ko. + */ +static int +ipsec_modevent(module_t mod, int type, void *data) +{ + + switch (type) { + case MOD_LOAD: + /* All xforms are registered via SYSINIT */ +#ifdef KLD_MODULE +#ifdef INET + ipsec_support_enable(ipv4_ipsec_support, &ipv4_methods); +#endif +#ifdef INET6 + ipsec_support_enable(ipv6_ipsec_support, &ipv6_methods); +#endif +#endif /* KLD_MODULE */ + break; + case MOD_UNLOAD: + /* All xforms are unregistered via SYSUNINIT */ +#ifdef KLD_MODULE +#ifdef INET + ipsec_support_disable(ipv4_ipsec_support); +#endif +#ifdef INET6 + ipsec_support_disable(ipv6_ipsec_support); +#endif +#endif /* KLD_MODULE */ + break; + default: + return (EOPNOTSUPP); + } + return (0); +} + +static moduledata_t ipsec_mod = { + "ipsec", + ipsec_modevent, + 0 +}; + +DECLARE_MODULE(ipsec, ipsec_mod, SI_SUB_PROTO_DOMAIN, SI_ORDER_ANY); +MODULE_VERSION(ipsec, 1); +#ifdef KLD_MODULE +MODULE_DEPEND(ipsec, ipsec_support, 1, 1, 1); +#endif Modified: projects/ipsec/sys/netipsec/ipsec_pcb.c ============================================================================== --- projects/ipsec/sys/netipsec/ipsec_pcb.c Mon Dec 26 20:36:37 2016 (r310618) +++ projects/ipsec/sys/netipsec/ipsec_pcb.c Mon Dec 26 21:09:02 2016 (r310619) @@ -47,6 +47,7 @@ __FBSDID("$FreeBSD$"); #include <netinet/in_pcb.h> #include <netipsec/ipsec.h> +#include <netipsec/ipsec6.h> #include <netipsec/ipsec_support.h> #include <netipsec/key.h> #include <netipsec/key_debug.h> Modified: projects/ipsec/sys/netipsec/ipsec_support.h ============================================================================== --- projects/ipsec/sys/netipsec/ipsec_support.h Mon Dec 26 20:36:37 2016 (r310618) +++ projects/ipsec/sys/netipsec/ipsec_support.h Mon Dec 26 21:09:02 2016 (r310619) @@ -36,15 +36,15 @@ struct inpcb; struct tcphdr; struct sockopt; struct sockaddr; +struct ipsec_support; +struct tcpmd5_support; size_t ipsec_hdrsiz_inpcb(struct inpcb *); int ipsec_init_pcbpolicy(struct inpcb *); int ipsec_delete_pcbpolicy(struct inpcb *); int ipsec_copy_pcbpolicy(struct inpcb *, struct inpcb *); -int ipsec4_pcbctl(struct inpcb *, struct sockopt *); -int ipsec6_pcbctl(struct inpcb *, struct sockopt *); -struct ipsec_support { +struct ipsec_methods { int (*input)(struct mbuf *, int, int); int (*check_policy)(const struct mbuf *, struct inpcb *); int (*forward)(struct mbuf *); @@ -53,113 +53,138 @@ struct ipsec_support { size_t (*hdrsize)(struct inpcb *); int (*capability)(struct mbuf *, u_int); int (*ctlinput)(int, struct sockaddr *, void *); + + int (*udp_input)(struct mbuf *, int, int); + int (*udp_pcbctl)(struct inpcb *, struct sockopt *); }; #define IPSEC_CAP_OPERABLE 1 #define IPSEC_CAP_BYPASS_FILTER 2 -#ifdef TCP_SIGNATURE -extern const int tcp_ipsec_support; - -int tcp_ipsec_pcbctl(struct inpcb *, struct sockopt *); -int tcp_ipsec_input(struct mbuf *, struct tcphdr *, u_char *); -int tcp_ipsec_output(struct mbuf *, struct tcphdr *, u_char *); -#define TCPMD5_INPUT(m, ...) tcp_ipsec_input(m, __VA_ARGS__) -#define TCPMD5_OUTPUT(m, ...) tcp_ipsec_output(m, __VA_ARGS__) -#define TCPMD5_PCBCTL(inp, sopt) tcp_ipsec_pcbctl(inp, sopt) -#else -struct tcpmd5_support { +struct tcpmd5_methods { int (*input)(struct mbuf *, struct tcphdr *, u_char *); int (*output)(struct mbuf *, struct tcphdr *, u_char *); int (*pcbctl)(struct inpcb *, struct sockopt *); }; -extern volatile int tcp_ipsec_support; -extern const struct tcpmd5_support * volatile tcp_ipsec_methods; -int tcpmd5_kmod_pcbctl(struct inpcb *, struct sockopt *); -int tcpmd5_kmod_input(struct mbuf *, struct tcphdr *, u_char *); -int tcpmd5_kmod_output(struct mbuf *, struct tcphdr *, u_char *); -#define TCPMD5_INPUT(m, ...) tcpmd5_kmod_input(m, __VA_ARGS__) -#define TCPMD5_OUTPUT(m, ...) tcpmd5_kmod_output(m, __VA_ARGS__) -#define TCPMD5_PCBCTL(inp, sopt) tcpmd5_kmod_pcbctl(inp, sopt) -#endif +#define IPSEC_MODULE_ENABLED 0x0001 +#define IPSEC_ENABLED(proto) \ + ((proto ## _ipsec_support)->enabled & IPSEC_MODULE_ENABLED) +#define TCPMD5_ENABLED() IPSEC_ENABLED(tcp) -#define IPSEC_ENABLED(proto) ((proto ## _ipsec_support) != 0) -#define TCPMD5_ENABLED() (tcp_ipsec_support != 0) -#endif /* IPSEC || IPSEC_SUPPORT */ +#ifdef TCP_SIGNATURE +/* TCP-MD5 build in the kernel */ +struct tcpmd5_support { + const u_int enabled; + const struct tcpmd5_methods * const methods; +}; +extern const struct tcpmd5_support * const tcp_ipsec_support; -#if defined(IPSEC) +#define TCPMD5_INPUT(m, ...) \ + (*tcp_ipsec_support->methods->input)(m, __VA_ARGS__) +#define TCPMD5_OUTPUT(m, ...) \ + (*tcp_ipsec_support->methods->output)(m, __VA_ARGS__) +#define TCPMD5_PCBCTL(inp, sopt) \ + (*tcp_ipsec_support->methods->pcbctl)(inp, sopt) +#elif defined(IPSEC_SUPPORT) +/* TCP-MD5 build as module */ +struct tcpmd5_support { + volatile u_int enabled; + const struct tcpmd5_methods * volatile methods; +}; +extern struct tcpmd5_support * const tcp_ipsec_support; -extern const int ipv4_ipsec_support; -extern const struct ipsec_support * const ipv4_ipsec_methods; +void tcpmd5_support_enable(const struct tcpmd5_methods * const); +void tcpmd5_support_disable(void); -int udp_ipsec_pcbctl(struct inpcb *, struct sockopt *); -int udp_ipsec_input(struct mbuf *, int, int); -#define UDPENCAP_INPUT(m, ...) udp_ipsec_input(m, __VA_ARGS__) -#define UDPENCAP_PCBCTL(inp, sopt) udp_ipsec_pcbctl(inp, sopt) +int tcpmd5_kmod_pcbctl(struct tcpmd5_support * const, struct inpcb *, + struct sockopt *); +int tcpmd5_kmod_input(struct tcpmd5_support * const, struct mbuf *, + struct tcphdr *, u_char *); +int tcpmd5_kmod_output(struct tcpmd5_support * const, struct mbuf *, + struct tcphdr *, u_char *); +#define TCPMD5_INPUT(m, ...) \ + tcpmd5_kmod_input(tcp_ipsec_support, m, __VA_ARGS__) +#define TCPMD5_OUTPUT(m, ...) \ + tcpmd5_kmod_output(tcp_ipsec_support, m, __VA_ARGS__) +#define TCPMD5_PCBCTL(inp, sopt) \ + tcpmd5_kmod_pcbctl(tcp_ipsec_support, inp, sopt) +#endif -extern const int ipv6_ipsec_support; -extern const struct ipsec_support * const ipv6_ipsec_methods; +#endif /* IPSEC || IPSEC_SUPPORT */ + +#if defined(IPSEC) +struct ipsec_support { + const u_int enabled; + const struct ipsec_methods * const methods; +}; +extern const struct ipsec_support * const ipv4_ipsec_support; +extern const struct ipsec_support * const ipv6_ipsec_support; #define IPSEC_INPUT(proto, m, ...) \ - (*(proto ## _ipsec_methods)->input)(m, __VA_ARGS__) + (*(proto ## _ipsec_support)->methods->input)(m, __VA_ARGS__) #define IPSEC_CHECK_POLICY(proto, m, ...) \ - (*(proto ## _ipsec_methods)->check_policy)(m, __VA_ARGS__) + (*(proto ## _ipsec_support)->methods->check_policy)(m, __VA_ARGS__) #define IPSEC_FORWARD(proto, m) \ - (*(proto ## _ipsec_methods)->forward)(m) + (*(proto ## _ipsec_support)->methods->forward)(m) #define IPSEC_OUTPUT(proto, m, ...) \ - (*(proto ## _ipsec_methods)->output)(m, __VA_ARGS__) -#define IPSEC_PCBCTL(proto, m, ...) \ - (*(proto ## _ipsec_methods)->pcbctl)(m, __VA_ARGS__) + (*(proto ## _ipsec_support)->methods->output)(m, __VA_ARGS__) +#define IPSEC_PCBCTL(proto, inp, sopt) \ + (*(proto ## _ipsec_support)->methods->pcbctl)(inp, sopt) #define IPSEC_CAPS(proto, m, ...) \ - (*(proto ## _ipsec_methods)->capability)(m, __VA_ARGS__) + (*(proto ## _ipsec_support)->methods->capability)(m, __VA_ARGS__) #define IPSEC_HDRSIZE(proto, inp) \ - (*(proto ## _ipsec_methods)->hdrsize)(inp) + (*(proto ## _ipsec_support)->methods->hdrsize)(inp) -#elif defined(IPSEC_SUPPORT) +#define UDPENCAP_INPUT(m, ...) \ + (*ipv4_ipsec_support->methods->udp_input)(m, __VA_ARGS__) +#define UDPENCAP_PCBCTL(inp, sopt) \ + (*ipv4_ipsec_support->methods->udp_pcbctl)(inp, sopt) -struct udpencap_support { - int (*input)(struct mbuf *, int, int); - int (*pcbctl)(struct inpcb *, struct sockopt *); +#elif defined(IPSEC_SUPPORT) +struct ipsec_support { + volatile u_int enabled; + const struct ipsec_methods * volatile methods; }; +extern struct ipsec_support * const ipv4_ipsec_support; +extern struct ipsec_support * const ipv6_ipsec_support; -extern volatile int ipv4_ipsec_support; -extern const struct ipsec_support * volatile ipv4_ipsec_methods; -extern const struct udpencap_support * volatile udp_ipsec_methods; - -int udpencap_kmod_pcbctl(struct inpcb *, struct sockopt *); -int udpencap_kmod_input(struct mbuf *, int, int); -#define UDPENCAP_INPUT(m, ...) udpencap_kmod_input(m, __VA_ARGS__) -#define UDPENCAP_PCBCTL(inp, sopt) udpencap_kmod_pcbctl(inp, sopt) - -extern volatile int ipv6_ipsec_support; -extern const struct ipsec_support * volatile ipv6_ipsec_methods; - -extern struct rmlock ipsec_kmod_lock; -int ipsec_kmod_input(const struct ipsec_support *, struct mbuf *, int, int); -int ipsec_kmod_check_policy(const struct ipsec_support *, struct mbuf *, +void ipsec_support_enable(struct ipsec_support * const, + const struct ipsec_methods * const); +void ipsec_support_disable(struct ipsec_support * const); + +int ipsec_kmod_input(struct ipsec_support * const, struct mbuf *, int, int); +int ipsec_kmod_check_policy(struct ipsec_support * const, struct mbuf *, struct inpcb *); -int ipsec_kmod_forward(const struct ipsec_support *, struct mbuf *); -int ipsec_kmod_output(const struct ipsec_support *, struct mbuf *, +int ipsec_kmod_forward(struct ipsec_support * const, struct mbuf *); +int ipsec_kmod_output(struct ipsec_support * const, struct mbuf *, struct inpcb *); -int ipsec_kmod_pcbctl(const struct ipsec_support *, struct inpcb *, +int ipsec_kmod_pcbctl(struct ipsec_support * const, struct inpcb *, + struct sockopt *); +int ipsec_kmod_capability(struct ipsec_support * const, struct mbuf *, u_int); +size_t ipsec_kmod_hdrsize(struct ipsec_support * const, struct inpcb *); +int ipsec_kmod_udp_input(struct ipsec_support * const, struct mbuf *, int, int); +int ipsec_kmod_udp_pcbctl(struct ipsec_support * const, struct inpcb *, struct sockopt *); -int ipsec_kmod_capability(const struct ipsec_support *, struct mbuf *, u_int); -size_t ipsec_kmod_hdrsize(const struct ipsec_support *, struct inpcb *); + +#define UDPENCAP_INPUT(m, ...) \ + ipsec_kmod_udp_input(ipv4_ipsec_support, m, __VA_ARGS__) +#define UDPENCAP_PCBCTL(inp, sopt) \ + ipsec_kmod_udp_pcbctl(ipv4_ipsec_support, inp, sopt) #define IPSEC_INPUT(proto, ...) \ - ipsec_kmod_input(proto ## _ipsec_methods, __VA_ARGS__) + ipsec_kmod_input(proto ## _ipsec_support, __VA_ARGS__) #define IPSEC_CHECK_POLICY(proto, ...) \ - ipsec_kmod_check_policy(proto ## _ipsec_methods, __VA_ARGS__) + ipsec_kmod_check_policy(proto ## _ipsec_support, __VA_ARGS__) #define IPSEC_FORWARD(proto, ...) \ - ipsec_kmod_forward(proto ## _ipsec_methods, __VA_ARGS__) + ipsec_kmod_forward(proto ## _ipsec_support, __VA_ARGS__) #define IPSEC_OUTPUT(proto, ...) \ - ipsec_kmod_output(proto ## _ipsec_methods, __VA_ARGS__) + ipsec_kmod_output(proto ## _ipsec_support, __VA_ARGS__) #define IPSEC_PCBCTL(proto, ...) \ - ipsec_kmod_pcbctl(proto ## _ipsec_methods, __VA_ARGS__) + ipsec_kmod_pcbctl(proto ## _ipsec_support, __VA_ARGS__) #define IPSEC_CAPS(proto, ...) \ - ipsec_kmod_capability(proto ## _ipsec_methods, __VA_ARGS__) + ipsec_kmod_capability(proto ## _ipsec_support, __VA_ARGS__) #define IPSEC_HDRSIZE(proto, ...) \ - ipsec_kmod_hdrsize(proto ## _ipsec_methods, __VA_ARGS__) + ipsec_kmod_hdrsize(proto ## _ipsec_support, __VA_ARGS__) #endif /* IPSEC_SUPPORT */ #endif /* _KERNEL */ #endif /* _NETIPSEC_IPSEC_SUPPORT_H_ */ Modified: projects/ipsec/sys/netipsec/subr_ipsec.c ============================================================================== --- projects/ipsec/sys/netipsec/subr_ipsec.c Mon Dec 26 20:36:37 2016 (r310618) +++ projects/ipsec/sys/netipsec/subr_ipsec.c Mon Dec 26 21:09:02 2016 (r310619) @@ -39,7 +39,6 @@ __FBSDID("$FreeBSD$"); #include <sys/mbuf.h> #include <sys/module.h> #include <sys/priv.h> -#include <sys/rmlock.h> #include <sys/socket.h> #include <sys/sockopt.h> #include <sys/syslog.h> @@ -56,56 +55,12 @@ __FBSDID("$FreeBSD$"); #include <netipsec/key.h> #include <netipsec/key_debug.h> +#include <machine/atomic.h> /* * This file is build in the kernel only when 'options IPSEC' or * 'options IPSEC_SUPPORT' is enabled. */ -struct rmlock ipsec_kmod_lock; -RM_SYSINIT(ipsec_kmod_lock, &ipsec_kmod_lock, "IPsec KLD lock"); - -#define METHOD_DECL(...) __VA_ARGS__ -#define METHOD_ARGS(...) __VA_ARGS__ -#define IPSEC_KMOD_METHOD(type, name, sc, method, decl, args) \ -type name (decl) \ -{ \ - struct rm_priotracker tracker; \ - type ret; \ - IPSEC_ASSERT(sc != NULL, ("called with NULL methods")); \ - rm_rlock(&ipsec_kmod_lock, &tracker); \ - ret = (*sc->method)(args); \ - rm_runlock(&ipsec_kmod_lock, &tracker); \ - return (ret); \ -} - -static int -ipsec_support_modevent(module_t mod, int type, void *data) -{ - - switch (type) { - case MOD_LOAD: - return (0); - case MOD_UNLOAD: - return (EBUSY); - default: - return (EOPNOTSUPP); - } -} - -static moduledata_t ipsec_support_mod = { - "ipsec_support", - ipsec_support_modevent, - 0 -}; - -/* - * Declare IPSEC_SUPPORT as module to be able add dependency in - * ipsec.ko and tcpmd5.ko - */ -DECLARE_MODULE(ipsec_support, ipsec_support_mod, - SI_SUB_PROTO_DOMAIN, SI_ORDER_ANY); -MODULE_VERSION(ipsec_support, 1); - #ifdef INET void ipsec4_setsockaddrs(const struct mbuf *m, union sockaddr_union *src, @@ -169,138 +124,227 @@ ipsec6_setsockaddrs(const struct mbuf *m } #endif -#ifdef TCP_SIGNATURE -const int tcp_ipsec_support = 1; -#else #ifdef IPSEC_SUPPORT -volatile int tcp_ipsec_support = 0; -const struct tcpmd5_support * volatile tcp_ipsec_methods = NULL; +/* + * Declare IPSEC_SUPPORT as module even if IPSEC is defined. + * tcpmd5.ko module depends from IPSEC_SUPPORT. + */ +#define IPSEC_MODULE_INCR 2 +static int +ipsec_kmod_enter(volatile u_int *cntr) +{ + u_int old, new; -IPSEC_KMOD_METHOD(int, tcpmd5_kmod_input, - tcp_ipsec_methods, - input, METHOD_DECL(struct mbuf *m, struct tcphdr *th, u_char *buf), - METHOD_ARGS(m, th, buf) + do { + old = *cntr; + if ((old & IPSEC_MODULE_ENABLED) == 0) + return (ENXIO); + new = old + IPSEC_MODULE_INCR; + } while(atomic_cmpset_acq_int(cntr, old, new) == 0); + return (0); +} + +static void +ipsec_kmod_exit(volatile u_int *cntr) +{ + u_int old, new; + + do { + old = *cntr; + new = old - IPSEC_MODULE_INCR; + } while (atomic_cmpset_rel_int(cntr, old, new) == 0); +} + +static void +ipsec_kmod_drain(volatile u_int *cntr) +{ + u_int old, new; + + do { + old = *cntr; + new = old & ~IPSEC_MODULE_ENABLED; + } while (atomic_cmpset_acq_int(cntr, old, new) == 0); + while (atomic_cmpset_int(cntr, 0, 0) == 0) + pause("ipsecd", hz/2); +} + +#define METHOD_DECL(...) __VA_ARGS__ +#define METHOD_ARGS(...) __VA_ARGS__ +#define IPSEC_KMOD_METHOD(type, name, sc, method, decl, args) \ +type name (decl) \ +{ \ + type ret = (type)ipsec_kmod_enter(&sc->enabled); \ + if (ret == 0) { \ + ret = (*sc->methods->method)(args); \ + ipsec_kmod_exit(&sc->enabled); \ + } \ + return (ret); \ +} + +#ifndef TCP_SIGNATURE +/* Declare TCP-MD5 support as kernel module. */ +static struct tcpmd5_support tcpmd5_ipsec = { + .enabled = 0, + .methods = NULL +}; +struct tcpmd5_support * const tcp_ipsec_support = &tcpmd5_ipsec; + +IPSEC_KMOD_METHOD(int, tcpmd5_kmod_input, sc, + input, METHOD_DECL(struct tcpmd5_support * const sc, struct mbuf *m, + struct tcphdr *th, u_char *buf), METHOD_ARGS(m, th, buf) ) -IPSEC_KMOD_METHOD(int, tcpmd5_kmod_output, - tcp_ipsec_methods, - output, METHOD_DECL(struct mbuf *m, struct tcphdr *th, u_char *buf), - METHOD_ARGS(m, th, buf) +IPSEC_KMOD_METHOD(int, tcpmd5_kmod_output, sc, + output, METHOD_DECL(struct tcpmd5_support * const sc, struct mbuf *m, + struct tcphdr *th, u_char *buf), METHOD_ARGS(m, th, buf) ) -IPSEC_KMOD_METHOD(int, tcpmd5_kmod_pcbctl, - tcp_ipsec_methods, - pcbctl, METHOD_DECL(struct inpcb *inp, struct sockopt *sopt), - METHOD_ARGS(inp, sopt) +IPSEC_KMOD_METHOD(int, tcpmd5_kmod_pcbctl, sc, + pcbctl, METHOD_DECL(struct tcpmd5_support * const sc, struct inpcb *inp, + struct sockopt *sopt), METHOD_ARGS(inp, sopt) ) -#endif -#endif -#ifdef IPSEC -/* - * IPsec support is build in the kernel. Additional locking isn't required. - */ -#ifdef INET -static struct ipsec_support ipv4_ipsec = { - .input = ipsec4_input, - .forward = ipsec4_forward, - .output = ipsec4_output, - .pcbctl = ipsec4_pcbctl, - .capability = ipsec4_capability, - .check_policy = ipsec4_in_reject, - .hdrsize = ipsec_hdrsiz_inpcb -}; -const int ipv4_ipsec_support = 1; -const struct ipsec_support * const ipv4_ipsec_methods = &ipv4_ipsec; +void +tcpmd5_support_enable(const struct tcpmd5_methods * const methods) +{ + + KASSERT(tcp_ipsec_support->enabled == 0, ("TCP-MD5 already enabled")); + tcp_ipsec_support->methods = methods; + tcp_ipsec_support->enabled |= IPSEC_MODULE_ENABLED; +} + +void +tcpmd5_support_disable(void) +{ + + if (tcp_ipsec_support->enabled & IPSEC_MODULE_ENABLED) { + ipsec_kmod_drain(&tcp_ipsec_support->enabled); + tcp_ipsec_support->methods = NULL; + } +} #endif -#ifdef INET6 -static struct ipsec_support ipv6_ipsec = { - .input = ipsec6_input, - .forward = ipsec6_forward, - .output = ipsec6_output, - .pcbctl = ipsec6_pcbctl, - .capability = ipsec6_capability, - .check_policy = ipsec6_in_reject, - .hdrsize = ipsec_hdrsiz_inpcb +static int +ipsec_support_modevent(module_t mod, int type, void *data) +{ + + switch (type) { + case MOD_LOAD: + return (0); + case MOD_UNLOAD: + return (EBUSY); + default: + return (EOPNOTSUPP); + } +} + +static moduledata_t ipsec_support_mod = { + "ipsec_support", + ipsec_support_modevent, + 0 }; -const int ipv6_ipsec_support = 1; -const struct ipsec_support * const ipv6_ipsec_methods = &ipv6_ipsec; -#endif -#else /* IPSEC_SUPPORT */ +DECLARE_MODULE(ipsec_support, ipsec_support_mod, SI_SUB_PROTO_DOMAIN, + SI_ORDER_ANY); +MODULE_VERSION(ipsec_support, 1); + +#ifndef IPSEC /* * IPsec support is build as kernel module. */ #ifdef INET -volatile int ipv4_ipsec_support = 0; -const struct ipsec_support * volatile ipv4_ipsec_methods = NULL; -const struct udpencap_support * volatile udp_ipsec_methods = NULL; - -IPSEC_KMOD_METHOD(int, udpencap_kmod_input, - udp_ipsec_methods, - input, METHOD_DECL(struct mbuf *m, int off, int af), - METHOD_ARGS(m, off, af) +static struct ipsec_support ipv4_ipsec = { + .enabled = 0, + .methods = NULL +}; +struct ipsec_support * const ipv4_ipsec_support = &ipv4_ipsec; + +IPSEC_KMOD_METHOD(int, ipsec_kmod_udp_input, sc, + udp_input, METHOD_DECL(struct ipsec_support * const sc, struct mbuf *m, + int off, int af), METHOD_ARGS(m, off, af) ) -IPSEC_KMOD_METHOD(int, udpencap_kmod_pcbctl, - udp_ipsec_methods, - pcbctl, METHOD_DECL(struct inpcb *inp, struct sockopt *sopt), - METHOD_ARGS(inp, sopt) +IPSEC_KMOD_METHOD(int, ipsec_kmod_udp_pcbctl, sc, + udp_pcbctl, METHOD_DECL(struct ipsec_support * const sc, struct inpcb *inp, + struct sockopt *sopt), METHOD_ARGS(inp, sopt) ) #endif #ifdef INET6 -volatile int ipv6_ipsec_support = 0; -const struct ipsec_support * volatile ipv6_ipsec_methods = NULL; +static struct ipsec_support ipv6_ipsec = { + .enabled = 0, + .methods = NULL +}; +struct ipsec_support * const ipv6_ipsec_support = &ipv6_ipsec; #endif IPSEC_KMOD_METHOD(int, ipsec_kmod_input, sc, - input, METHOD_DECL(const struct ipsec_support *sc, struct mbuf *m, + input, METHOD_DECL(struct ipsec_support * const sc, struct mbuf *m, int offset, int proto), METHOD_ARGS(m, offset, proto) ) IPSEC_KMOD_METHOD(int, ipsec_kmod_check_policy, sc, - check_policy, METHOD_DECL(const struct ipsec_support *sc, struct mbuf *m, + check_policy, METHOD_DECL(struct ipsec_support * const sc, struct mbuf *m, struct inpcb *inp), METHOD_ARGS(m, inp) ) IPSEC_KMOD_METHOD(int, ipsec_kmod_forward, sc, - forward, METHOD_DECL(const struct ipsec_support *sc, struct mbuf *m), + forward, METHOD_DECL(struct ipsec_support * const sc, struct mbuf *m), (m) ) IPSEC_KMOD_METHOD(int, ipsec_kmod_output, sc, - output, METHOD_DECL(const struct ipsec_support *sc, struct mbuf *m, + output, METHOD_DECL(struct ipsec_support * const sc, struct mbuf *m, struct inpcb *inp), METHOD_ARGS(m, inp) ) IPSEC_KMOD_METHOD(int, ipsec_kmod_pcbctl, sc, - pcbctl, METHOD_DECL(const struct ipsec_support *sc, struct inpcb *inp, + pcbctl, METHOD_DECL(struct ipsec_support * const sc, struct inpcb *inp, struct sockopt *sopt), METHOD_ARGS(inp, sopt) ) IPSEC_KMOD_METHOD(size_t, ipsec_kmod_hdrsize, sc, - hdrsize, METHOD_DECL(const struct ipsec_support *sc, struct inpcb *inp), + hdrsize, METHOD_DECL(struct ipsec_support * const sc, struct inpcb *inp), (inp) ) static IPSEC_KMOD_METHOD(int, ipsec_kmod_caps, sc, - capability, METHOD_DECL(const struct ipsec_support *sc, struct mbuf *m, + capability, METHOD_DECL(struct ipsec_support * const sc, struct mbuf *m, u_int cap), METHOD_ARGS(m, cap) ) int -ipsec_kmod_capability(const struct ipsec_support *sc, struct mbuf *m, +ipsec_kmod_capability(struct ipsec_support * const sc, struct mbuf *m, u_int cap) { /* - * Since PF_KEY is build in the kernel, we can use key_havesp() - * without taking the lock. + * Since PF_KEY is build in the kernel, we can directly + * call key_havesp() without additional synchronizations. */ if (cap == IPSEC_CAP_OPERABLE) return (key_havesp(IPSEC_DIR_INBOUND) != 0 || key_havesp(IPSEC_DIR_OUTBOUND) != 0); return (ipsec_kmod_caps(sc, m, cap)); } -#endif + +void +ipsec_support_enable(struct ipsec_support * const sc, + const struct ipsec_methods * const methods) +{ + + KASSERT(sc->enabled == 0, ("IPsec already enabled")); + sc->methods = methods; + sc->enabled |= IPSEC_MODULE_ENABLED; +} + +void +ipsec_support_disable(struct ipsec_support * const sc) +{ + + if (sc->enabled & IPSEC_MODULE_ENABLED) { + ipsec_kmod_drain(&sc->enabled); + sc->methods = NULL; + } +} +#endif /* !IPSEC */ +#endif /* IPSEC_SUPPORT */ Modified: projects/ipsec/sys/netipsec/xform_ipcomp.c ============================================================================== --- projects/ipsec/sys/netipsec/xform_ipcomp.c Mon Dec 26 20:36:37 2016 (r310618) +++ projects/ipsec/sys/netipsec/xform_ipcomp.c Mon Dec 26 21:09:02 2016 (r310619) @@ -763,7 +763,7 @@ ipcomp_detach(void) #ifdef INET6 encap_detach(ipe6_cookie); #endif - xform_attach(&ipcomp_xformsw); + xform_detach(&ipcomp_xformsw); } SYSINIT(ipcomp_xform_init, SI_SUB_PROTO_DOMAIN, SI_ORDER_MIDDLE, Modified: projects/ipsec/sys/netipsec/xform_tcp.c ============================================================================== --- projects/ipsec/sys/netipsec/xform_tcp.c Mon Dec 26 20:36:37 2016 (r310618) +++ projects/ipsec/sys/netipsec/xform_tcp.c Mon Dec 26 21:09:02 2016 (r310619) @@ -32,16 +32,18 @@ __FBSDID("$FreeBSD$"); #include "opt_inet.h" #include "opt_inet6.h" +#include "opt_ipsec.h" #include <sys/param.h> #include <sys/systm.h> #include <sys/mbuf.h> #include <sys/lock.h> #include <sys/md5.h> -#include <sys/rwlock.h> +#include <sys/rmlock.h> #include <sys/socket.h> #include <sys/sockopt.h> #include <sys/kernel.h> +#include <sys/module.h> #include <sys/protosw.h> #include <netinet/in.h> @@ -55,6 +57,7 @@ __FBSDID("$FreeBSD$"); #include <net/vnet.h> #include <netipsec/ipsec.h> +#include <netipsec/ipsec_support.h> #include <netipsec/xform.h> #ifdef INET6 @@ -65,8 +68,6 @@ __FBSDID("$FreeBSD$"); #include <netipsec/key.h> #include <netipsec/key_debug.h> -#ifdef TCP_SIGNATURE - #define TCP_SIGLEN 16 /* length of computed digest in bytes */ #define TCP_KEYLEN_MIN 1 /* minimum length of TCP-MD5 key */ #define TCP_KEYLEN_MAX 80 /* maximum length of TCP-MD5 key */ @@ -81,7 +82,7 @@ tcp_fields_to_net(struct tcphdr *th) th->th_urp = htons(th->th_urp); } -int +static int tcp_ipsec_pcbctl(struct inpcb *inp, struct sockopt *sopt) { struct tcpcb *tp; @@ -258,7 +259,7 @@ setsockaddrs(const struct mbuf *m, union * * Return 0 if successful, otherwise return -1. */ -int +static int tcp_ipsec_input(struct mbuf *m, struct tcphdr *th, u_char *buf) { char tmpdigest[TCP_SIGLEN]; @@ -299,7 +300,7 @@ tcp_ipsec_input(struct mbuf *m, struct t * * Return 0 if successful, otherwise return error code. */ -int +static int tcp_ipsec_output(struct mbuf *m, struct tcphdr *th, u_char *buf) { struct secasindex saidx; @@ -318,16 +319,6 @@ tcp_ipsec_output(struct mbuf *m, struct key_freesav(&sav); return (0); } -#else /* TCP_SIGNATURE */ - -int -tcp_ipsec_pcbctl(struct inpcb *inp, struct sockopt *sopt) -{ - - INP_WUNLOCK(inp); - return (ENOPROTOOPT); -} -#endif /* !TCP_SIGNATURE*/ /* * Initialize a TCP-MD5 SA. Called when the SA is being set up. @@ -369,65 +360,76 @@ tcpsignature_init(struct secasvar *sav, DPRINTF(("%s: invalid key length %u\n", __func__, keylen)); return (EINVAL); } - + sav->tdb_xform = xsp; return (0); } /* - * Paranoia. - * * Called when the SA is deleted. */ static int tcpsignature_zeroize(struct secasvar *sav) { - if (sav->key_auth) + if (sav->key_auth != NULL) bzero(sav->key_auth->key_data, _KEYLEN(sav->key_auth)); - - sav->tdb_cryptoid = 0; - sav->tdb_authalgxform = NULL; sav->tdb_xform = NULL; - return (0); } -/* - * Verify that an input packet passes authentication. - * Called from the ipsec layer. - * We do this from within tcp itself, so this routine is just a stub. - */ -static int -tcpsignature_input(struct mbuf *m, struct secasvar *sav, int skip, - int protoff) -{ *** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201612262109.uBQL939W008208>