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/param.h> 32fcf59617SAndrey V. Elsukov #include <sys/systm.h> 33fcf59617SAndrey V. Elsukov #include <sys/kernel.h> 34fcf59617SAndrey V. Elsukov #include <sys/lock.h> 35fcf59617SAndrey V. Elsukov #include <sys/malloc.h> 36fcf59617SAndrey V. Elsukov #include <sys/mbuf.h> 37fcf59617SAndrey V. Elsukov #include <sys/module.h> 38fcf59617SAndrey V. Elsukov #include <sys/priv.h> 39fcf59617SAndrey V. Elsukov #include <sys/socket.h> 40fcf59617SAndrey V. Elsukov #include <sys/sockopt.h> 41fcf59617SAndrey V. Elsukov #include <sys/syslog.h> 42fcf59617SAndrey V. Elsukov #include <sys/proc.h> 43fcf59617SAndrey V. Elsukov 44fcf59617SAndrey V. Elsukov #include <netinet/in.h> 45fcf59617SAndrey V. Elsukov #include <netinet/in_pcb.h> 46fcf59617SAndrey V. Elsukov #include <netinet/ip.h> 47fcf59617SAndrey V. Elsukov #include <netinet/ip6.h> 48fcf59617SAndrey V. Elsukov 49fcf59617SAndrey V. Elsukov #include <netipsec/ipsec_support.h> 50fcf59617SAndrey V. Elsukov #include <netipsec/ipsec.h> 51fcf59617SAndrey V. Elsukov #include <netipsec/ipsec6.h> 52fcf59617SAndrey V. Elsukov #include <netipsec/key.h> 53fcf59617SAndrey V. Elsukov #include <netipsec/key_debug.h> 540ddfd867SAndrey V. Elsukov #include <netipsec/xform.h> 55fcf59617SAndrey V. Elsukov 56fcf59617SAndrey V. Elsukov #include <machine/atomic.h> 57fcf59617SAndrey V. Elsukov /* 58fcf59617SAndrey V. Elsukov * This file is build in the kernel only when 'options IPSEC' or 59fcf59617SAndrey V. Elsukov * 'options IPSEC_SUPPORT' is enabled. 60fcf59617SAndrey V. Elsukov */ 61fcf59617SAndrey V. Elsukov 62fcf59617SAndrey V. Elsukov #ifdef INET 63fcf59617SAndrey V. Elsukov void 64*0ff2d00dSKonstantin Belousov ipsec4_setsockaddrs(const struct mbuf *m, const struct ip *ip1, 65*0ff2d00dSKonstantin Belousov union sockaddr_union *src, union sockaddr_union *dst) 66fcf59617SAndrey V. Elsukov { 67fcf59617SAndrey V. Elsukov static const struct sockaddr_in template = { 68fcf59617SAndrey V. Elsukov sizeof (struct sockaddr_in), 69fcf59617SAndrey V. Elsukov AF_INET, 70fcf59617SAndrey V. Elsukov 0, { 0 }, { 0, 0, 0, 0, 0, 0, 0, 0 } 71fcf59617SAndrey V. Elsukov }; 72fcf59617SAndrey V. Elsukov 73fcf59617SAndrey V. Elsukov src->sin = template; 74fcf59617SAndrey V. Elsukov dst->sin = template; 75fcf59617SAndrey V. Elsukov 76*0ff2d00dSKonstantin Belousov src->sin.sin_addr = ip1->ip_src; 77*0ff2d00dSKonstantin Belousov dst->sin.sin_addr = ip1->ip_dst; 78fcf59617SAndrey V. Elsukov } 79fcf59617SAndrey V. Elsukov #endif 80fcf59617SAndrey V. Elsukov #ifdef INET6 81fcf59617SAndrey V. Elsukov void 82fcf59617SAndrey V. Elsukov ipsec6_setsockaddrs(const struct mbuf *m, union sockaddr_union *src, 83fcf59617SAndrey V. Elsukov union sockaddr_union *dst) 84fcf59617SAndrey V. Elsukov { 85fcf59617SAndrey V. Elsukov struct ip6_hdr ip6buf; 86fcf59617SAndrey V. Elsukov const struct ip6_hdr *ip6; 87fcf59617SAndrey V. Elsukov 88fcf59617SAndrey V. Elsukov if (m->m_len >= sizeof(*ip6)) 89fcf59617SAndrey V. Elsukov ip6 = mtod(m, const struct ip6_hdr *); 90fcf59617SAndrey V. Elsukov else { 91fcf59617SAndrey V. Elsukov m_copydata(m, 0, sizeof(ip6buf), (caddr_t)&ip6buf); 92fcf59617SAndrey V. Elsukov ip6 = &ip6buf; 93fcf59617SAndrey V. Elsukov } 94fcf59617SAndrey V. Elsukov 95fcf59617SAndrey V. Elsukov bzero(&src->sin6, sizeof(struct sockaddr_in6)); 96fcf59617SAndrey V. Elsukov src->sin6.sin6_family = AF_INET6; 97fcf59617SAndrey V. Elsukov src->sin6.sin6_len = sizeof(struct sockaddr_in6); 98fcf59617SAndrey V. Elsukov bcopy(&ip6->ip6_src, &src->sin6.sin6_addr, sizeof(ip6->ip6_src)); 99fcf59617SAndrey V. Elsukov if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_src)) { 100fcf59617SAndrey V. Elsukov src->sin6.sin6_addr.s6_addr16[1] = 0; 101fcf59617SAndrey V. Elsukov src->sin6.sin6_scope_id = ntohs(ip6->ip6_src.s6_addr16[1]); 102fcf59617SAndrey V. Elsukov } 103fcf59617SAndrey V. Elsukov 104fcf59617SAndrey V. Elsukov bzero(&dst->sin6, sizeof(struct sockaddr_in6)); 105fcf59617SAndrey V. Elsukov dst->sin6.sin6_family = AF_INET6; 106fcf59617SAndrey V. Elsukov dst->sin6.sin6_len = sizeof(struct sockaddr_in6); 107fcf59617SAndrey V. Elsukov bcopy(&ip6->ip6_dst, &dst->sin6.sin6_addr, sizeof(ip6->ip6_dst)); 108fcf59617SAndrey V. Elsukov if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_dst)) { 109fcf59617SAndrey V. Elsukov dst->sin6.sin6_addr.s6_addr16[1] = 0; 110fcf59617SAndrey V. Elsukov dst->sin6.sin6_scope_id = ntohs(ip6->ip6_dst.s6_addr16[1]); 111fcf59617SAndrey V. Elsukov } 112fcf59617SAndrey V. Elsukov } 113fcf59617SAndrey V. Elsukov #endif 114fcf59617SAndrey V. Elsukov 115fcf59617SAndrey V. Elsukov #define IPSEC_MODULE_INCR 2 116fcf59617SAndrey V. Elsukov static int 117fcf59617SAndrey V. Elsukov ipsec_kmod_enter(volatile u_int *cntr) 118fcf59617SAndrey V. Elsukov { 119fcf59617SAndrey V. Elsukov u_int old, new; 120fcf59617SAndrey V. Elsukov 121fcf59617SAndrey V. Elsukov do { 122fcf59617SAndrey V. Elsukov old = *cntr; 123fcf59617SAndrey V. Elsukov if ((old & IPSEC_MODULE_ENABLED) == 0) 124fcf59617SAndrey V. Elsukov return (ENXIO); 125fcf59617SAndrey V. Elsukov new = old + IPSEC_MODULE_INCR; 126fcf59617SAndrey V. Elsukov } while(atomic_cmpset_acq_int(cntr, old, new) == 0); 127fcf59617SAndrey V. Elsukov return (0); 128fcf59617SAndrey V. Elsukov } 129fcf59617SAndrey V. Elsukov 130fcf59617SAndrey V. Elsukov static void 131fcf59617SAndrey V. Elsukov ipsec_kmod_exit(volatile u_int *cntr) 132fcf59617SAndrey V. Elsukov { 133fcf59617SAndrey V. Elsukov u_int old, new; 134fcf59617SAndrey V. Elsukov 135fcf59617SAndrey V. Elsukov do { 136fcf59617SAndrey V. Elsukov old = *cntr; 137fcf59617SAndrey V. Elsukov new = old - IPSEC_MODULE_INCR; 138fcf59617SAndrey V. Elsukov } while (atomic_cmpset_rel_int(cntr, old, new) == 0); 139fcf59617SAndrey V. Elsukov } 140fcf59617SAndrey V. Elsukov 141fcf59617SAndrey V. Elsukov static void 142fcf59617SAndrey V. Elsukov ipsec_kmod_drain(volatile u_int *cntr) 143fcf59617SAndrey V. Elsukov { 144fcf59617SAndrey V. Elsukov u_int old, new; 145fcf59617SAndrey V. Elsukov 146fcf59617SAndrey V. Elsukov do { 147fcf59617SAndrey V. Elsukov old = *cntr; 148fcf59617SAndrey V. Elsukov new = old & ~IPSEC_MODULE_ENABLED; 149fcf59617SAndrey V. Elsukov } while (atomic_cmpset_acq_int(cntr, old, new) == 0); 150fcf59617SAndrey V. Elsukov while (atomic_cmpset_int(cntr, 0, 0) == 0) 151fcf59617SAndrey V. Elsukov pause("ipsecd", hz/2); 152fcf59617SAndrey V. Elsukov } 153fcf59617SAndrey V. Elsukov 1540ddfd867SAndrey V. Elsukov static LIST_HEAD(xforms_list, xformsw) xforms = LIST_HEAD_INITIALIZER(); 1550ddfd867SAndrey V. Elsukov static struct mtx xforms_lock; 1560ddfd867SAndrey V. Elsukov MTX_SYSINIT(xfroms_list, &xforms_lock, "IPsec transforms list", MTX_DEF); 1570ddfd867SAndrey V. Elsukov #define XFORMS_LOCK() mtx_lock(&xforms_lock) 1580ddfd867SAndrey V. Elsukov #define XFORMS_UNLOCK() mtx_unlock(&xforms_lock) 1590ddfd867SAndrey V. Elsukov 1600ddfd867SAndrey V. Elsukov void 1610ddfd867SAndrey V. Elsukov xform_attach(void *data) 1620ddfd867SAndrey V. Elsukov { 1630ddfd867SAndrey V. Elsukov struct xformsw *xsp, *entry; 1640ddfd867SAndrey V. Elsukov 1650ddfd867SAndrey V. Elsukov xsp = (struct xformsw *)data; 1660ddfd867SAndrey V. Elsukov XFORMS_LOCK(); 1670ddfd867SAndrey V. Elsukov LIST_FOREACH(entry, &xforms, chain) { 1680ddfd867SAndrey V. Elsukov if (entry->xf_type == xsp->xf_type) { 1690ddfd867SAndrey V. Elsukov XFORMS_UNLOCK(); 1700ddfd867SAndrey V. Elsukov printf("%s: failed to register %s xform\n", 1710ddfd867SAndrey V. Elsukov __func__, xsp->xf_name); 1720ddfd867SAndrey V. Elsukov return; 1730ddfd867SAndrey V. Elsukov } 1740ddfd867SAndrey V. Elsukov } 1750ddfd867SAndrey V. Elsukov LIST_INSERT_HEAD(&xforms, xsp, chain); 1760ddfd867SAndrey V. Elsukov xsp->xf_cntr = IPSEC_MODULE_ENABLED; 1770ddfd867SAndrey V. Elsukov XFORMS_UNLOCK(); 1780ddfd867SAndrey V. Elsukov } 1790ddfd867SAndrey V. Elsukov 1800ddfd867SAndrey V. Elsukov void 1810ddfd867SAndrey V. Elsukov xform_detach(void *data) 1820ddfd867SAndrey V. Elsukov { 1830ddfd867SAndrey V. Elsukov struct xformsw *xsp = (struct xformsw *)data; 1840ddfd867SAndrey V. Elsukov 1850ddfd867SAndrey V. Elsukov XFORMS_LOCK(); 1860ddfd867SAndrey V. Elsukov LIST_REMOVE(xsp, chain); 1870ddfd867SAndrey V. Elsukov XFORMS_UNLOCK(); 1880ddfd867SAndrey V. Elsukov 1890ddfd867SAndrey V. Elsukov /* Delete all SAs related to this xform. */ 1900ddfd867SAndrey V. Elsukov key_delete_xform(xsp); 1910ddfd867SAndrey V. Elsukov if (xsp->xf_cntr & IPSEC_MODULE_ENABLED) 1920ddfd867SAndrey V. Elsukov ipsec_kmod_drain(&xsp->xf_cntr); 1930ddfd867SAndrey V. Elsukov } 1940ddfd867SAndrey V. Elsukov 1950ddfd867SAndrey V. Elsukov /* 1960ddfd867SAndrey V. Elsukov * Initialize transform support in an sav. 1970ddfd867SAndrey V. Elsukov */ 1980ddfd867SAndrey V. Elsukov int 1990ddfd867SAndrey V. Elsukov xform_init(struct secasvar *sav, u_short xftype) 2000ddfd867SAndrey V. Elsukov { 2010ddfd867SAndrey V. Elsukov struct xformsw *entry; 2020ddfd867SAndrey V. Elsukov int ret; 2030ddfd867SAndrey V. Elsukov 2040ddfd867SAndrey V. Elsukov IPSEC_ASSERT(sav->tdb_xform == NULL, 2050ddfd867SAndrey V. Elsukov ("tdb_xform is already initialized")); 2060ddfd867SAndrey V. Elsukov 2070ddfd867SAndrey V. Elsukov XFORMS_LOCK(); 2080ddfd867SAndrey V. Elsukov LIST_FOREACH(entry, &xforms, chain) { 2090ddfd867SAndrey V. Elsukov if (entry->xf_type == xftype) { 2100ddfd867SAndrey V. Elsukov ret = ipsec_kmod_enter(&entry->xf_cntr); 2110ddfd867SAndrey V. Elsukov XFORMS_UNLOCK(); 2120ddfd867SAndrey V. Elsukov if (ret != 0) 2130ddfd867SAndrey V. Elsukov return (ret); 2140ddfd867SAndrey V. Elsukov ret = (*entry->xf_init)(sav, entry); 2150ddfd867SAndrey V. Elsukov ipsec_kmod_exit(&entry->xf_cntr); 2160ddfd867SAndrey V. Elsukov return (ret); 2170ddfd867SAndrey V. Elsukov } 2180ddfd867SAndrey V. Elsukov } 2190ddfd867SAndrey V. Elsukov XFORMS_UNLOCK(); 2200ddfd867SAndrey V. Elsukov return (EINVAL); 2210ddfd867SAndrey V. Elsukov } 2220ddfd867SAndrey V. Elsukov 2230ddfd867SAndrey V. Elsukov #ifdef IPSEC_SUPPORT 2240ddfd867SAndrey V. Elsukov /* 2250ddfd867SAndrey V. Elsukov * IPSEC_SUPPORT - loading of ipsec.ko and tcpmd5.ko is supported. 2260ddfd867SAndrey V. Elsukov * IPSEC + IPSEC_SUPPORT - loading tcpmd5.ko is supported. 2270ddfd867SAndrey V. Elsukov * IPSEC + TCP_SIGNATURE - all is build in the kernel, do not build 2280ddfd867SAndrey V. Elsukov * IPSEC_SUPPORT. 2290ddfd867SAndrey V. Elsukov */ 2300ddfd867SAndrey V. Elsukov #if !defined(IPSEC) || !defined(TCP_SIGNATURE) 231fcf59617SAndrey V. Elsukov #define METHOD_DECL(...) __VA_ARGS__ 232fcf59617SAndrey V. Elsukov #define METHOD_ARGS(...) __VA_ARGS__ 233fcf59617SAndrey V. Elsukov #define IPSEC_KMOD_METHOD(type, name, sc, method, decl, args) \ 234fcf59617SAndrey V. Elsukov type name (decl) \ 235fcf59617SAndrey V. Elsukov { \ 236fcf59617SAndrey V. Elsukov type ret = (type)ipsec_kmod_enter(&sc->enabled); \ 237fcf59617SAndrey V. Elsukov if (ret == 0) { \ 238fcf59617SAndrey V. Elsukov ret = (*sc->methods->method)(args); \ 239fcf59617SAndrey V. Elsukov ipsec_kmod_exit(&sc->enabled); \ 240fcf59617SAndrey V. Elsukov } \ 241fcf59617SAndrey V. Elsukov return (ret); \ 242fcf59617SAndrey V. Elsukov } 243fcf59617SAndrey V. Elsukov 244ddc9f8e8SAndrey V. Elsukov static int 245ddc9f8e8SAndrey V. Elsukov ipsec_support_modevent(module_t mod, int type, void *data) 246ddc9f8e8SAndrey V. Elsukov { 247ddc9f8e8SAndrey V. Elsukov 248ddc9f8e8SAndrey V. Elsukov switch (type) { 249ddc9f8e8SAndrey V. Elsukov case MOD_LOAD: 250ddc9f8e8SAndrey V. Elsukov return (0); 251ddc9f8e8SAndrey V. Elsukov case MOD_UNLOAD: 252ddc9f8e8SAndrey V. Elsukov return (EBUSY); 253ddc9f8e8SAndrey V. Elsukov default: 254ddc9f8e8SAndrey V. Elsukov return (EOPNOTSUPP); 255ddc9f8e8SAndrey V. Elsukov } 256ddc9f8e8SAndrey V. Elsukov } 257ddc9f8e8SAndrey V. Elsukov 258ddc9f8e8SAndrey V. Elsukov static moduledata_t ipsec_support_mod = { 259ddc9f8e8SAndrey V. Elsukov "ipsec_support", 260ddc9f8e8SAndrey V. Elsukov ipsec_support_modevent, 261ddc9f8e8SAndrey V. Elsukov 0 262ddc9f8e8SAndrey V. Elsukov }; 263ddc9f8e8SAndrey V. Elsukov DECLARE_MODULE(ipsec_support, ipsec_support_mod, SI_SUB_PROTO_DOMAIN, 264ddc9f8e8SAndrey V. Elsukov SI_ORDER_ANY); 265ddc9f8e8SAndrey V. Elsukov MODULE_VERSION(ipsec_support, 1); 266ddc9f8e8SAndrey V. Elsukov #endif /* !IPSEC || !TCP_SIGNATURE */ 267ddc9f8e8SAndrey V. Elsukov 268fcf59617SAndrey V. Elsukov #ifndef TCP_SIGNATURE 269fcf59617SAndrey V. Elsukov /* Declare TCP-MD5 support as kernel module. */ 270fcf59617SAndrey V. Elsukov static struct tcpmd5_support tcpmd5_ipsec = { 271fcf59617SAndrey V. Elsukov .enabled = 0, 272fcf59617SAndrey V. Elsukov .methods = NULL 273fcf59617SAndrey V. Elsukov }; 274fcf59617SAndrey V. Elsukov struct tcpmd5_support * const tcp_ipsec_support = &tcpmd5_ipsec; 275fcf59617SAndrey V. Elsukov 276fcf59617SAndrey V. Elsukov IPSEC_KMOD_METHOD(int, tcpmd5_kmod_input, sc, 277fcf59617SAndrey V. Elsukov input, METHOD_DECL(struct tcpmd5_support * const sc, struct mbuf *m, 278fcf59617SAndrey V. Elsukov struct tcphdr *th, u_char *buf), METHOD_ARGS(m, th, buf) 279fcf59617SAndrey V. Elsukov ) 280fcf59617SAndrey V. Elsukov 281fcf59617SAndrey V. Elsukov IPSEC_KMOD_METHOD(int, tcpmd5_kmod_output, sc, 282fcf59617SAndrey V. Elsukov output, METHOD_DECL(struct tcpmd5_support * const sc, struct mbuf *m, 283fcf59617SAndrey V. Elsukov struct tcphdr *th, u_char *buf), METHOD_ARGS(m, th, buf) 284fcf59617SAndrey V. Elsukov ) 285fcf59617SAndrey V. Elsukov 286fcf59617SAndrey V. Elsukov IPSEC_KMOD_METHOD(int, tcpmd5_kmod_pcbctl, sc, 287fcf59617SAndrey V. Elsukov pcbctl, METHOD_DECL(struct tcpmd5_support * const sc, struct inpcb *inp, 288fcf59617SAndrey V. Elsukov struct sockopt *sopt), METHOD_ARGS(inp, sopt) 289fcf59617SAndrey V. Elsukov ) 290fcf59617SAndrey V. Elsukov 291fcf59617SAndrey V. Elsukov void 292fcf59617SAndrey V. Elsukov tcpmd5_support_enable(const struct tcpmd5_methods * const methods) 293fcf59617SAndrey V. Elsukov { 294fcf59617SAndrey V. Elsukov 295fcf59617SAndrey V. Elsukov KASSERT(tcp_ipsec_support->enabled == 0, ("TCP-MD5 already enabled")); 296fcf59617SAndrey V. Elsukov tcp_ipsec_support->methods = methods; 297fcf59617SAndrey V. Elsukov tcp_ipsec_support->enabled |= IPSEC_MODULE_ENABLED; 298fcf59617SAndrey V. Elsukov } 299fcf59617SAndrey V. Elsukov 300fcf59617SAndrey V. Elsukov void 301fcf59617SAndrey V. Elsukov tcpmd5_support_disable(void) 302fcf59617SAndrey V. Elsukov { 303fcf59617SAndrey V. Elsukov 304fcf59617SAndrey V. Elsukov if (tcp_ipsec_support->enabled & IPSEC_MODULE_ENABLED) { 305fcf59617SAndrey V. Elsukov ipsec_kmod_drain(&tcp_ipsec_support->enabled); 306fcf59617SAndrey V. Elsukov tcp_ipsec_support->methods = NULL; 307fcf59617SAndrey V. Elsukov } 308fcf59617SAndrey V. Elsukov } 309ddc9f8e8SAndrey V. Elsukov #endif /* !TCP_SIGNATURE */ 310fcf59617SAndrey V. Elsukov 311fcf59617SAndrey V. Elsukov #ifndef IPSEC 312fcf59617SAndrey V. Elsukov /* 313fcf59617SAndrey V. Elsukov * IPsec support is build as kernel module. 314fcf59617SAndrey V. Elsukov */ 315fcf59617SAndrey V. Elsukov #ifdef INET 316fcf59617SAndrey V. Elsukov static struct ipsec_support ipv4_ipsec = { 317fcf59617SAndrey V. Elsukov .enabled = 0, 318fcf59617SAndrey V. Elsukov .methods = NULL 319fcf59617SAndrey V. Elsukov }; 320fcf59617SAndrey V. Elsukov struct ipsec_support * const ipv4_ipsec_support = &ipv4_ipsec; 321122dd78cSLexi Winter #endif 322122dd78cSLexi Winter 323122dd78cSLexi Winter #ifdef INET6 324122dd78cSLexi Winter static struct ipsec_support ipv6_ipsec = { 325122dd78cSLexi Winter .enabled = 0, 326122dd78cSLexi Winter .methods = NULL 327122dd78cSLexi Winter }; 328122dd78cSLexi Winter struct ipsec_support * const ipv6_ipsec_support = &ipv6_ipsec; 329122dd78cSLexi Winter #endif 330fcf59617SAndrey V. Elsukov 331fcf59617SAndrey V. Elsukov IPSEC_KMOD_METHOD(int, ipsec_kmod_udp_input, sc, 332fcf59617SAndrey V. Elsukov udp_input, METHOD_DECL(struct ipsec_support * const sc, struct mbuf *m, 333fcf59617SAndrey V. Elsukov int off, int af), METHOD_ARGS(m, off, af) 334fcf59617SAndrey V. Elsukov ) 335fcf59617SAndrey V. Elsukov 336fcf59617SAndrey V. Elsukov IPSEC_KMOD_METHOD(int, ipsec_kmod_udp_pcbctl, sc, 337fcf59617SAndrey V. Elsukov udp_pcbctl, METHOD_DECL(struct ipsec_support * const sc, struct inpcb *inp, 338fcf59617SAndrey V. Elsukov struct sockopt *sopt), METHOD_ARGS(inp, sopt) 339fcf59617SAndrey V. Elsukov ) 340fcf59617SAndrey V. Elsukov 341fcf59617SAndrey V. Elsukov IPSEC_KMOD_METHOD(int, ipsec_kmod_input, sc, 342fcf59617SAndrey V. Elsukov input, METHOD_DECL(struct ipsec_support * const sc, struct mbuf *m, 343fcf59617SAndrey V. Elsukov int offset, int proto), METHOD_ARGS(m, offset, proto) 344fcf59617SAndrey V. Elsukov ) 345fcf59617SAndrey V. Elsukov 346fcf59617SAndrey V. Elsukov IPSEC_KMOD_METHOD(int, ipsec_kmod_check_policy, sc, 347fcf59617SAndrey V. Elsukov check_policy, METHOD_DECL(struct ipsec_support * const sc, struct mbuf *m, 348fcf59617SAndrey V. Elsukov struct inpcb *inp), METHOD_ARGS(m, inp) 349fcf59617SAndrey V. Elsukov ) 350fcf59617SAndrey V. Elsukov 351fcf59617SAndrey V. Elsukov IPSEC_KMOD_METHOD(int, ipsec_kmod_forward, sc, 352fcf59617SAndrey V. Elsukov forward, METHOD_DECL(struct ipsec_support * const sc, struct mbuf *m), 353fcf59617SAndrey V. Elsukov (m) 354fcf59617SAndrey V. Elsukov ) 355fcf59617SAndrey V. Elsukov 356d9d59bb1SWojciech Macek IPSEC_KMOD_METHOD(int, ipsec_kmod_ctlinput, sc, 3579f69c0b8SHans Petter Selasky ctlinput, METHOD_DECL(struct ipsec_support * const sc, 3589f69c0b8SHans Petter Selasky ipsec_ctlinput_param_t param), METHOD_ARGS(param) 359d9d59bb1SWojciech Macek ) 360d9d59bb1SWojciech Macek 36100524fd4SKonstantin Belousov IPSEC_KMOD_METHOD(int, ipsec_kmod_output, sc, output, 36200524fd4SKonstantin Belousov METHOD_DECL(struct ipsec_support * const sc, struct ifnet *ifp, 36300524fd4SKonstantin Belousov struct mbuf *m, struct inpcb *inp, u_long mtu), 36400524fd4SKonstantin Belousov METHOD_ARGS(ifp, m, inp, mtu) 365fcf59617SAndrey V. Elsukov ) 366fcf59617SAndrey V. Elsukov 367fcf59617SAndrey V. Elsukov IPSEC_KMOD_METHOD(int, ipsec_kmod_pcbctl, sc, 368fcf59617SAndrey V. Elsukov pcbctl, METHOD_DECL(struct ipsec_support * const sc, struct inpcb *inp, 369fcf59617SAndrey V. Elsukov struct sockopt *sopt), METHOD_ARGS(inp, sopt) 370fcf59617SAndrey V. Elsukov ) 371fcf59617SAndrey V. Elsukov 372fcf59617SAndrey V. Elsukov IPSEC_KMOD_METHOD(size_t, ipsec_kmod_hdrsize, sc, 373fcf59617SAndrey V. Elsukov hdrsize, METHOD_DECL(struct ipsec_support * const sc, struct inpcb *inp), 374fcf59617SAndrey V. Elsukov (inp) 375fcf59617SAndrey V. Elsukov ) 376fcf59617SAndrey V. Elsukov 377fcf59617SAndrey V. Elsukov static IPSEC_KMOD_METHOD(int, ipsec_kmod_caps, sc, 378fcf59617SAndrey V. Elsukov capability, METHOD_DECL(struct ipsec_support * const sc, struct mbuf *m, 379fcf59617SAndrey V. Elsukov u_int cap), METHOD_ARGS(m, cap) 380fcf59617SAndrey V. Elsukov ) 381fcf59617SAndrey V. Elsukov 382fcf59617SAndrey V. Elsukov int 383fcf59617SAndrey V. Elsukov ipsec_kmod_capability(struct ipsec_support * const sc, struct mbuf *m, 384fcf59617SAndrey V. Elsukov u_int cap) 385fcf59617SAndrey V. Elsukov { 386fcf59617SAndrey V. Elsukov 387fcf59617SAndrey V. Elsukov /* 388fcf59617SAndrey V. Elsukov * Since PF_KEY is build in the kernel, we can directly 389fcf59617SAndrey V. Elsukov * call key_havesp() without additional synchronizations. 390fcf59617SAndrey V. Elsukov */ 391fcf59617SAndrey V. Elsukov if (cap == IPSEC_CAP_OPERABLE) 392c1bfe8c5SMateusz Guzik return (key_havesp_any()); 393fcf59617SAndrey V. Elsukov return (ipsec_kmod_caps(sc, m, cap)); 394fcf59617SAndrey V. Elsukov } 395fcf59617SAndrey V. Elsukov 396fcf59617SAndrey V. Elsukov void 397fcf59617SAndrey V. Elsukov ipsec_support_enable(struct ipsec_support * const sc, 398fcf59617SAndrey V. Elsukov const struct ipsec_methods * const methods) 399fcf59617SAndrey V. Elsukov { 400fcf59617SAndrey V. Elsukov 401fcf59617SAndrey V. Elsukov KASSERT(sc->enabled == 0, ("IPsec already enabled")); 402fcf59617SAndrey V. Elsukov sc->methods = methods; 403fcf59617SAndrey V. Elsukov sc->enabled |= IPSEC_MODULE_ENABLED; 404fcf59617SAndrey V. Elsukov } 405fcf59617SAndrey V. Elsukov 406fcf59617SAndrey V. Elsukov void 407fcf59617SAndrey V. Elsukov ipsec_support_disable(struct ipsec_support * const sc) 408fcf59617SAndrey V. Elsukov { 409fcf59617SAndrey V. Elsukov 410fcf59617SAndrey V. Elsukov if (sc->enabled & IPSEC_MODULE_ENABLED) { 411fcf59617SAndrey V. Elsukov ipsec_kmod_drain(&sc->enabled); 412fcf59617SAndrey V. Elsukov sc->methods = NULL; 413fcf59617SAndrey V. Elsukov } 414fcf59617SAndrey V. Elsukov } 415fcf59617SAndrey V. Elsukov #endif /* !IPSEC */ 416fcf59617SAndrey V. Elsukov #endif /* IPSEC_SUPPORT */ 417