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