1*fcf59617SAndrey V. Elsukov /*- 2*fcf59617SAndrey V. Elsukov * Copyright (c) 2016 Andrey V. Elsukov <ae@FreeBSD.org> 3*fcf59617SAndrey V. Elsukov * All rights reserved. 4*fcf59617SAndrey V. Elsukov * 5*fcf59617SAndrey V. Elsukov * Redistribution and use in source and binary forms, with or without 6*fcf59617SAndrey V. Elsukov * modification, are permitted provided that the following conditions 7*fcf59617SAndrey V. Elsukov * are met: 8*fcf59617SAndrey V. Elsukov * 9*fcf59617SAndrey V. Elsukov * 1. Redistributions of source code must retain the above copyright 10*fcf59617SAndrey V. Elsukov * notice, this list of conditions and the following disclaimer. 11*fcf59617SAndrey V. Elsukov * 2. Redistributions in binary form must reproduce the above copyright 12*fcf59617SAndrey V. Elsukov * notice, this list of conditions and the following disclaimer in the 13*fcf59617SAndrey V. Elsukov * documentation and/or other materials provided with the distribution. 14*fcf59617SAndrey V. Elsukov * 15*fcf59617SAndrey V. Elsukov * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16*fcf59617SAndrey V. Elsukov * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17*fcf59617SAndrey V. Elsukov * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18*fcf59617SAndrey V. Elsukov * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19*fcf59617SAndrey V. Elsukov * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20*fcf59617SAndrey V. Elsukov * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21*fcf59617SAndrey V. Elsukov * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22*fcf59617SAndrey V. Elsukov * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23*fcf59617SAndrey V. Elsukov * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24*fcf59617SAndrey V. Elsukov * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25*fcf59617SAndrey V. Elsukov */ 26*fcf59617SAndrey V. Elsukov 27*fcf59617SAndrey V. Elsukov #include "opt_inet.h" 28*fcf59617SAndrey V. Elsukov #include "opt_inet6.h" 29*fcf59617SAndrey V. Elsukov #include "opt_ipsec.h" 30*fcf59617SAndrey V. Elsukov 31*fcf59617SAndrey V. Elsukov #include <sys/cdefs.h> 32*fcf59617SAndrey V. Elsukov __FBSDID("$FreeBSD$"); 33*fcf59617SAndrey V. Elsukov 34*fcf59617SAndrey V. Elsukov #include <sys/param.h> 35*fcf59617SAndrey V. Elsukov #include <sys/systm.h> 36*fcf59617SAndrey V. Elsukov #include <sys/kernel.h> 37*fcf59617SAndrey V. Elsukov #include <sys/lock.h> 38*fcf59617SAndrey V. Elsukov #include <sys/malloc.h> 39*fcf59617SAndrey V. Elsukov #include <sys/mbuf.h> 40*fcf59617SAndrey V. Elsukov #include <sys/module.h> 41*fcf59617SAndrey V. Elsukov #include <sys/priv.h> 42*fcf59617SAndrey V. Elsukov #include <sys/socket.h> 43*fcf59617SAndrey V. Elsukov #include <sys/sockopt.h> 44*fcf59617SAndrey V. Elsukov #include <sys/syslog.h> 45*fcf59617SAndrey V. Elsukov #include <sys/proc.h> 46*fcf59617SAndrey V. Elsukov 47*fcf59617SAndrey V. Elsukov #include <netinet/in.h> 48*fcf59617SAndrey V. Elsukov #include <netinet/in_pcb.h> 49*fcf59617SAndrey V. Elsukov #include <netinet/ip.h> 50*fcf59617SAndrey V. Elsukov #include <netinet/ip6.h> 51*fcf59617SAndrey V. Elsukov 52*fcf59617SAndrey V. Elsukov #include <netipsec/ipsec_support.h> 53*fcf59617SAndrey V. Elsukov #include <netipsec/ipsec.h> 54*fcf59617SAndrey V. Elsukov #include <netipsec/ipsec6.h> 55*fcf59617SAndrey V. Elsukov #include <netipsec/key.h> 56*fcf59617SAndrey V. Elsukov #include <netipsec/key_debug.h> 57*fcf59617SAndrey V. Elsukov 58*fcf59617SAndrey V. Elsukov #include <machine/atomic.h> 59*fcf59617SAndrey V. Elsukov /* 60*fcf59617SAndrey V. Elsukov * This file is build in the kernel only when 'options IPSEC' or 61*fcf59617SAndrey V. Elsukov * 'options IPSEC_SUPPORT' is enabled. 62*fcf59617SAndrey V. Elsukov */ 63*fcf59617SAndrey V. Elsukov 64*fcf59617SAndrey V. Elsukov #ifdef INET 65*fcf59617SAndrey V. Elsukov void 66*fcf59617SAndrey V. Elsukov ipsec4_setsockaddrs(const struct mbuf *m, union sockaddr_union *src, 67*fcf59617SAndrey V. Elsukov union sockaddr_union *dst) 68*fcf59617SAndrey V. Elsukov { 69*fcf59617SAndrey V. Elsukov static const struct sockaddr_in template = { 70*fcf59617SAndrey V. Elsukov sizeof (struct sockaddr_in), 71*fcf59617SAndrey V. Elsukov AF_INET, 72*fcf59617SAndrey V. Elsukov 0, { 0 }, { 0, 0, 0, 0, 0, 0, 0, 0 } 73*fcf59617SAndrey V. Elsukov }; 74*fcf59617SAndrey V. Elsukov 75*fcf59617SAndrey V. Elsukov src->sin = template; 76*fcf59617SAndrey V. Elsukov dst->sin = template; 77*fcf59617SAndrey V. Elsukov 78*fcf59617SAndrey V. Elsukov if (m->m_len < sizeof (struct ip)) { 79*fcf59617SAndrey V. Elsukov m_copydata(m, offsetof(struct ip, ip_src), 80*fcf59617SAndrey V. Elsukov sizeof (struct in_addr), 81*fcf59617SAndrey V. Elsukov (caddr_t) &src->sin.sin_addr); 82*fcf59617SAndrey V. Elsukov m_copydata(m, offsetof(struct ip, ip_dst), 83*fcf59617SAndrey V. Elsukov sizeof (struct in_addr), 84*fcf59617SAndrey V. Elsukov (caddr_t) &dst->sin.sin_addr); 85*fcf59617SAndrey V. Elsukov } else { 86*fcf59617SAndrey V. Elsukov const struct ip *ip = mtod(m, const struct ip *); 87*fcf59617SAndrey V. Elsukov src->sin.sin_addr = ip->ip_src; 88*fcf59617SAndrey V. Elsukov dst->sin.sin_addr = ip->ip_dst; 89*fcf59617SAndrey V. Elsukov } 90*fcf59617SAndrey V. Elsukov } 91*fcf59617SAndrey V. Elsukov #endif 92*fcf59617SAndrey V. Elsukov #ifdef INET6 93*fcf59617SAndrey V. Elsukov void 94*fcf59617SAndrey V. Elsukov ipsec6_setsockaddrs(const struct mbuf *m, union sockaddr_union *src, 95*fcf59617SAndrey V. Elsukov union sockaddr_union *dst) 96*fcf59617SAndrey V. Elsukov { 97*fcf59617SAndrey V. Elsukov struct ip6_hdr ip6buf; 98*fcf59617SAndrey V. Elsukov const struct ip6_hdr *ip6; 99*fcf59617SAndrey V. Elsukov 100*fcf59617SAndrey V. Elsukov if (m->m_len >= sizeof(*ip6)) 101*fcf59617SAndrey V. Elsukov ip6 = mtod(m, const struct ip6_hdr *); 102*fcf59617SAndrey V. Elsukov else { 103*fcf59617SAndrey V. Elsukov m_copydata(m, 0, sizeof(ip6buf), (caddr_t)&ip6buf); 104*fcf59617SAndrey V. Elsukov ip6 = &ip6buf; 105*fcf59617SAndrey V. Elsukov } 106*fcf59617SAndrey V. Elsukov 107*fcf59617SAndrey V. Elsukov bzero(&src->sin6, sizeof(struct sockaddr_in6)); 108*fcf59617SAndrey V. Elsukov src->sin6.sin6_family = AF_INET6; 109*fcf59617SAndrey V. Elsukov src->sin6.sin6_len = sizeof(struct sockaddr_in6); 110*fcf59617SAndrey V. Elsukov bcopy(&ip6->ip6_src, &src->sin6.sin6_addr, sizeof(ip6->ip6_src)); 111*fcf59617SAndrey V. Elsukov if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_src)) { 112*fcf59617SAndrey V. Elsukov src->sin6.sin6_addr.s6_addr16[1] = 0; 113*fcf59617SAndrey V. Elsukov src->sin6.sin6_scope_id = ntohs(ip6->ip6_src.s6_addr16[1]); 114*fcf59617SAndrey V. Elsukov } 115*fcf59617SAndrey V. Elsukov 116*fcf59617SAndrey V. Elsukov bzero(&dst->sin6, sizeof(struct sockaddr_in6)); 117*fcf59617SAndrey V. Elsukov dst->sin6.sin6_family = AF_INET6; 118*fcf59617SAndrey V. Elsukov dst->sin6.sin6_len = sizeof(struct sockaddr_in6); 119*fcf59617SAndrey V. Elsukov bcopy(&ip6->ip6_dst, &dst->sin6.sin6_addr, sizeof(ip6->ip6_dst)); 120*fcf59617SAndrey V. Elsukov if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_dst)) { 121*fcf59617SAndrey V. Elsukov dst->sin6.sin6_addr.s6_addr16[1] = 0; 122*fcf59617SAndrey V. Elsukov dst->sin6.sin6_scope_id = ntohs(ip6->ip6_dst.s6_addr16[1]); 123*fcf59617SAndrey V. Elsukov } 124*fcf59617SAndrey V. Elsukov } 125*fcf59617SAndrey V. Elsukov #endif 126*fcf59617SAndrey V. Elsukov 127*fcf59617SAndrey V. Elsukov #ifdef IPSEC_SUPPORT 128*fcf59617SAndrey V. Elsukov /* 129*fcf59617SAndrey V. Elsukov * Declare IPSEC_SUPPORT as module even if IPSEC is defined. 130*fcf59617SAndrey V. Elsukov * tcpmd5.ko module depends from IPSEC_SUPPORT. 131*fcf59617SAndrey V. Elsukov */ 132*fcf59617SAndrey V. Elsukov #define IPSEC_MODULE_INCR 2 133*fcf59617SAndrey V. Elsukov static int 134*fcf59617SAndrey V. Elsukov ipsec_kmod_enter(volatile u_int *cntr) 135*fcf59617SAndrey V. Elsukov { 136*fcf59617SAndrey V. Elsukov u_int old, new; 137*fcf59617SAndrey V. Elsukov 138*fcf59617SAndrey V. Elsukov do { 139*fcf59617SAndrey V. Elsukov old = *cntr; 140*fcf59617SAndrey V. Elsukov if ((old & IPSEC_MODULE_ENABLED) == 0) 141*fcf59617SAndrey V. Elsukov return (ENXIO); 142*fcf59617SAndrey V. Elsukov new = old + IPSEC_MODULE_INCR; 143*fcf59617SAndrey V. Elsukov } while(atomic_cmpset_acq_int(cntr, old, new) == 0); 144*fcf59617SAndrey V. Elsukov return (0); 145*fcf59617SAndrey V. Elsukov } 146*fcf59617SAndrey V. Elsukov 147*fcf59617SAndrey V. Elsukov static void 148*fcf59617SAndrey V. Elsukov ipsec_kmod_exit(volatile u_int *cntr) 149*fcf59617SAndrey V. Elsukov { 150*fcf59617SAndrey V. Elsukov u_int old, new; 151*fcf59617SAndrey V. Elsukov 152*fcf59617SAndrey V. Elsukov do { 153*fcf59617SAndrey V. Elsukov old = *cntr; 154*fcf59617SAndrey V. Elsukov new = old - IPSEC_MODULE_INCR; 155*fcf59617SAndrey V. Elsukov } while (atomic_cmpset_rel_int(cntr, old, new) == 0); 156*fcf59617SAndrey V. Elsukov } 157*fcf59617SAndrey V. Elsukov 158*fcf59617SAndrey V. Elsukov static void 159*fcf59617SAndrey V. Elsukov ipsec_kmod_drain(volatile u_int *cntr) 160*fcf59617SAndrey V. Elsukov { 161*fcf59617SAndrey V. Elsukov u_int old, new; 162*fcf59617SAndrey V. Elsukov 163*fcf59617SAndrey V. Elsukov do { 164*fcf59617SAndrey V. Elsukov old = *cntr; 165*fcf59617SAndrey V. Elsukov new = old & ~IPSEC_MODULE_ENABLED; 166*fcf59617SAndrey V. Elsukov } while (atomic_cmpset_acq_int(cntr, old, new) == 0); 167*fcf59617SAndrey V. Elsukov while (atomic_cmpset_int(cntr, 0, 0) == 0) 168*fcf59617SAndrey V. Elsukov pause("ipsecd", hz/2); 169*fcf59617SAndrey V. Elsukov } 170*fcf59617SAndrey V. Elsukov 171*fcf59617SAndrey V. Elsukov #define METHOD_DECL(...) __VA_ARGS__ 172*fcf59617SAndrey V. Elsukov #define METHOD_ARGS(...) __VA_ARGS__ 173*fcf59617SAndrey V. Elsukov #define IPSEC_KMOD_METHOD(type, name, sc, method, decl, args) \ 174*fcf59617SAndrey V. Elsukov type name (decl) \ 175*fcf59617SAndrey V. Elsukov { \ 176*fcf59617SAndrey V. Elsukov type ret = (type)ipsec_kmod_enter(&sc->enabled); \ 177*fcf59617SAndrey V. Elsukov if (ret == 0) { \ 178*fcf59617SAndrey V. Elsukov ret = (*sc->methods->method)(args); \ 179*fcf59617SAndrey V. Elsukov ipsec_kmod_exit(&sc->enabled); \ 180*fcf59617SAndrey V. Elsukov } \ 181*fcf59617SAndrey V. Elsukov return (ret); \ 182*fcf59617SAndrey V. Elsukov } 183*fcf59617SAndrey V. Elsukov 184*fcf59617SAndrey V. Elsukov #ifndef TCP_SIGNATURE 185*fcf59617SAndrey V. Elsukov /* Declare TCP-MD5 support as kernel module. */ 186*fcf59617SAndrey V. Elsukov static struct tcpmd5_support tcpmd5_ipsec = { 187*fcf59617SAndrey V. Elsukov .enabled = 0, 188*fcf59617SAndrey V. Elsukov .methods = NULL 189*fcf59617SAndrey V. Elsukov }; 190*fcf59617SAndrey V. Elsukov struct tcpmd5_support * const tcp_ipsec_support = &tcpmd5_ipsec; 191*fcf59617SAndrey V. Elsukov 192*fcf59617SAndrey V. Elsukov IPSEC_KMOD_METHOD(int, tcpmd5_kmod_input, sc, 193*fcf59617SAndrey V. Elsukov input, METHOD_DECL(struct tcpmd5_support * const sc, struct mbuf *m, 194*fcf59617SAndrey V. Elsukov struct tcphdr *th, u_char *buf), METHOD_ARGS(m, th, buf) 195*fcf59617SAndrey V. Elsukov ) 196*fcf59617SAndrey V. Elsukov 197*fcf59617SAndrey V. Elsukov IPSEC_KMOD_METHOD(int, tcpmd5_kmod_output, sc, 198*fcf59617SAndrey V. Elsukov output, METHOD_DECL(struct tcpmd5_support * const sc, struct mbuf *m, 199*fcf59617SAndrey V. Elsukov struct tcphdr *th, u_char *buf), METHOD_ARGS(m, th, buf) 200*fcf59617SAndrey V. Elsukov ) 201*fcf59617SAndrey V. Elsukov 202*fcf59617SAndrey V. Elsukov IPSEC_KMOD_METHOD(int, tcpmd5_kmod_pcbctl, sc, 203*fcf59617SAndrey V. Elsukov pcbctl, METHOD_DECL(struct tcpmd5_support * const sc, struct inpcb *inp, 204*fcf59617SAndrey V. Elsukov struct sockopt *sopt), METHOD_ARGS(inp, sopt) 205*fcf59617SAndrey V. Elsukov ) 206*fcf59617SAndrey V. Elsukov 207*fcf59617SAndrey V. Elsukov void 208*fcf59617SAndrey V. Elsukov tcpmd5_support_enable(const struct tcpmd5_methods * const methods) 209*fcf59617SAndrey V. Elsukov { 210*fcf59617SAndrey V. Elsukov 211*fcf59617SAndrey V. Elsukov KASSERT(tcp_ipsec_support->enabled == 0, ("TCP-MD5 already enabled")); 212*fcf59617SAndrey V. Elsukov tcp_ipsec_support->methods = methods; 213*fcf59617SAndrey V. Elsukov tcp_ipsec_support->enabled |= IPSEC_MODULE_ENABLED; 214*fcf59617SAndrey V. Elsukov } 215*fcf59617SAndrey V. Elsukov 216*fcf59617SAndrey V. Elsukov void 217*fcf59617SAndrey V. Elsukov tcpmd5_support_disable(void) 218*fcf59617SAndrey V. Elsukov { 219*fcf59617SAndrey V. Elsukov 220*fcf59617SAndrey V. Elsukov if (tcp_ipsec_support->enabled & IPSEC_MODULE_ENABLED) { 221*fcf59617SAndrey V. Elsukov ipsec_kmod_drain(&tcp_ipsec_support->enabled); 222*fcf59617SAndrey V. Elsukov tcp_ipsec_support->methods = NULL; 223*fcf59617SAndrey V. Elsukov } 224*fcf59617SAndrey V. Elsukov } 225*fcf59617SAndrey V. Elsukov #endif 226*fcf59617SAndrey V. Elsukov 227*fcf59617SAndrey V. Elsukov static int 228*fcf59617SAndrey V. Elsukov ipsec_support_modevent(module_t mod, int type, void *data) 229*fcf59617SAndrey V. Elsukov { 230*fcf59617SAndrey V. Elsukov 231*fcf59617SAndrey V. Elsukov switch (type) { 232*fcf59617SAndrey V. Elsukov case MOD_LOAD: 233*fcf59617SAndrey V. Elsukov return (0); 234*fcf59617SAndrey V. Elsukov case MOD_UNLOAD: 235*fcf59617SAndrey V. Elsukov return (EBUSY); 236*fcf59617SAndrey V. Elsukov default: 237*fcf59617SAndrey V. Elsukov return (EOPNOTSUPP); 238*fcf59617SAndrey V. Elsukov } 239*fcf59617SAndrey V. Elsukov } 240*fcf59617SAndrey V. Elsukov 241*fcf59617SAndrey V. Elsukov static moduledata_t ipsec_support_mod = { 242*fcf59617SAndrey V. Elsukov "ipsec_support", 243*fcf59617SAndrey V. Elsukov ipsec_support_modevent, 244*fcf59617SAndrey V. Elsukov 0 245*fcf59617SAndrey V. Elsukov }; 246*fcf59617SAndrey V. Elsukov DECLARE_MODULE(ipsec_support, ipsec_support_mod, SI_SUB_PROTO_DOMAIN, 247*fcf59617SAndrey V. Elsukov SI_ORDER_ANY); 248*fcf59617SAndrey V. Elsukov MODULE_VERSION(ipsec_support, 1); 249*fcf59617SAndrey V. Elsukov 250*fcf59617SAndrey V. Elsukov #ifndef IPSEC 251*fcf59617SAndrey V. Elsukov /* 252*fcf59617SAndrey V. Elsukov * IPsec support is build as kernel module. 253*fcf59617SAndrey V. Elsukov */ 254*fcf59617SAndrey V. Elsukov #ifdef INET 255*fcf59617SAndrey V. Elsukov static struct ipsec_support ipv4_ipsec = { 256*fcf59617SAndrey V. Elsukov .enabled = 0, 257*fcf59617SAndrey V. Elsukov .methods = NULL 258*fcf59617SAndrey V. Elsukov }; 259*fcf59617SAndrey V. Elsukov struct ipsec_support * const ipv4_ipsec_support = &ipv4_ipsec; 260*fcf59617SAndrey V. Elsukov 261*fcf59617SAndrey V. Elsukov IPSEC_KMOD_METHOD(int, ipsec_kmod_udp_input, sc, 262*fcf59617SAndrey V. Elsukov udp_input, METHOD_DECL(struct ipsec_support * const sc, struct mbuf *m, 263*fcf59617SAndrey V. Elsukov int off, int af), METHOD_ARGS(m, off, af) 264*fcf59617SAndrey V. Elsukov ) 265*fcf59617SAndrey V. Elsukov 266*fcf59617SAndrey V. Elsukov IPSEC_KMOD_METHOD(int, ipsec_kmod_udp_pcbctl, sc, 267*fcf59617SAndrey V. Elsukov udp_pcbctl, METHOD_DECL(struct ipsec_support * const sc, struct inpcb *inp, 268*fcf59617SAndrey V. Elsukov struct sockopt *sopt), METHOD_ARGS(inp, sopt) 269*fcf59617SAndrey V. Elsukov ) 270*fcf59617SAndrey V. Elsukov #endif 271*fcf59617SAndrey V. Elsukov 272*fcf59617SAndrey V. Elsukov #ifdef INET6 273*fcf59617SAndrey V. Elsukov static struct ipsec_support ipv6_ipsec = { 274*fcf59617SAndrey V. Elsukov .enabled = 0, 275*fcf59617SAndrey V. Elsukov .methods = NULL 276*fcf59617SAndrey V. Elsukov }; 277*fcf59617SAndrey V. Elsukov struct ipsec_support * const ipv6_ipsec_support = &ipv6_ipsec; 278*fcf59617SAndrey V. Elsukov #endif 279*fcf59617SAndrey V. Elsukov 280*fcf59617SAndrey V. Elsukov IPSEC_KMOD_METHOD(int, ipsec_kmod_input, sc, 281*fcf59617SAndrey V. Elsukov input, METHOD_DECL(struct ipsec_support * const sc, struct mbuf *m, 282*fcf59617SAndrey V. Elsukov int offset, int proto), METHOD_ARGS(m, offset, proto) 283*fcf59617SAndrey V. Elsukov ) 284*fcf59617SAndrey V. Elsukov 285*fcf59617SAndrey V. Elsukov IPSEC_KMOD_METHOD(int, ipsec_kmod_check_policy, sc, 286*fcf59617SAndrey V. Elsukov check_policy, METHOD_DECL(struct ipsec_support * const sc, struct mbuf *m, 287*fcf59617SAndrey V. Elsukov struct inpcb *inp), METHOD_ARGS(m, inp) 288*fcf59617SAndrey V. Elsukov ) 289*fcf59617SAndrey V. Elsukov 290*fcf59617SAndrey V. Elsukov IPSEC_KMOD_METHOD(int, ipsec_kmod_forward, sc, 291*fcf59617SAndrey V. Elsukov forward, METHOD_DECL(struct ipsec_support * const sc, struct mbuf *m), 292*fcf59617SAndrey V. Elsukov (m) 293*fcf59617SAndrey V. Elsukov ) 294*fcf59617SAndrey V. Elsukov 295*fcf59617SAndrey V. Elsukov IPSEC_KMOD_METHOD(int, ipsec_kmod_output, sc, 296*fcf59617SAndrey V. Elsukov output, METHOD_DECL(struct ipsec_support * const sc, struct mbuf *m, 297*fcf59617SAndrey V. Elsukov struct inpcb *inp), METHOD_ARGS(m, inp) 298*fcf59617SAndrey V. Elsukov ) 299*fcf59617SAndrey V. Elsukov 300*fcf59617SAndrey V. Elsukov IPSEC_KMOD_METHOD(int, ipsec_kmod_pcbctl, sc, 301*fcf59617SAndrey V. Elsukov pcbctl, METHOD_DECL(struct ipsec_support * const sc, struct inpcb *inp, 302*fcf59617SAndrey V. Elsukov struct sockopt *sopt), METHOD_ARGS(inp, sopt) 303*fcf59617SAndrey V. Elsukov ) 304*fcf59617SAndrey V. Elsukov 305*fcf59617SAndrey V. Elsukov IPSEC_KMOD_METHOD(size_t, ipsec_kmod_hdrsize, sc, 306*fcf59617SAndrey V. Elsukov hdrsize, METHOD_DECL(struct ipsec_support * const sc, struct inpcb *inp), 307*fcf59617SAndrey V. Elsukov (inp) 308*fcf59617SAndrey V. Elsukov ) 309*fcf59617SAndrey V. Elsukov 310*fcf59617SAndrey V. Elsukov static IPSEC_KMOD_METHOD(int, ipsec_kmod_caps, sc, 311*fcf59617SAndrey V. Elsukov capability, METHOD_DECL(struct ipsec_support * const sc, struct mbuf *m, 312*fcf59617SAndrey V. Elsukov u_int cap), METHOD_ARGS(m, cap) 313*fcf59617SAndrey V. Elsukov ) 314*fcf59617SAndrey V. Elsukov 315*fcf59617SAndrey V. Elsukov int 316*fcf59617SAndrey V. Elsukov ipsec_kmod_capability(struct ipsec_support * const sc, struct mbuf *m, 317*fcf59617SAndrey V. Elsukov u_int cap) 318*fcf59617SAndrey V. Elsukov { 319*fcf59617SAndrey V. Elsukov 320*fcf59617SAndrey V. Elsukov /* 321*fcf59617SAndrey V. Elsukov * Since PF_KEY is build in the kernel, we can directly 322*fcf59617SAndrey V. Elsukov * call key_havesp() without additional synchronizations. 323*fcf59617SAndrey V. Elsukov */ 324*fcf59617SAndrey V. Elsukov if (cap == IPSEC_CAP_OPERABLE) 325*fcf59617SAndrey V. Elsukov return (key_havesp(IPSEC_DIR_INBOUND) != 0 || 326*fcf59617SAndrey V. Elsukov key_havesp(IPSEC_DIR_OUTBOUND) != 0); 327*fcf59617SAndrey V. Elsukov return (ipsec_kmod_caps(sc, m, cap)); 328*fcf59617SAndrey V. Elsukov } 329*fcf59617SAndrey V. Elsukov 330*fcf59617SAndrey V. Elsukov void 331*fcf59617SAndrey V. Elsukov ipsec_support_enable(struct ipsec_support * const sc, 332*fcf59617SAndrey V. Elsukov const struct ipsec_methods * const methods) 333*fcf59617SAndrey V. Elsukov { 334*fcf59617SAndrey V. Elsukov 335*fcf59617SAndrey V. Elsukov KASSERT(sc->enabled == 0, ("IPsec already enabled")); 336*fcf59617SAndrey V. Elsukov sc->methods = methods; 337*fcf59617SAndrey V. Elsukov sc->enabled |= IPSEC_MODULE_ENABLED; 338*fcf59617SAndrey V. Elsukov } 339*fcf59617SAndrey V. Elsukov 340*fcf59617SAndrey V. Elsukov void 341*fcf59617SAndrey V. Elsukov ipsec_support_disable(struct ipsec_support * const sc) 342*fcf59617SAndrey V. Elsukov { 343*fcf59617SAndrey V. Elsukov 344*fcf59617SAndrey V. Elsukov if (sc->enabled & IPSEC_MODULE_ENABLED) { 345*fcf59617SAndrey V. Elsukov ipsec_kmod_drain(&sc->enabled); 346*fcf59617SAndrey V. Elsukov sc->methods = NULL; 347*fcf59617SAndrey V. Elsukov } 348*fcf59617SAndrey V. Elsukov } 349*fcf59617SAndrey V. Elsukov #endif /* !IPSEC */ 350*fcf59617SAndrey V. Elsukov #endif /* IPSEC_SUPPORT */ 351