188768458SSam Leffler /* $FreeBSD$ */ 288768458SSam Leffler /* $KAME: keysock.c,v 1.25 2001/08/13 20:07:41 itojun Exp $ */ 388768458SSam Leffler 4c398230bSWarner Losh /*- 588768458SSam Leffler * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. 688768458SSam Leffler * All rights reserved. 788768458SSam Leffler * 888768458SSam Leffler * Redistribution and use in source and binary forms, with or without 988768458SSam Leffler * modification, are permitted provided that the following conditions 1088768458SSam Leffler * are met: 1188768458SSam Leffler * 1. Redistributions of source code must retain the above copyright 1288768458SSam Leffler * notice, this list of conditions and the following disclaimer. 1388768458SSam Leffler * 2. Redistributions in binary form must reproduce the above copyright 1488768458SSam Leffler * notice, this list of conditions and the following disclaimer in the 1588768458SSam Leffler * documentation and/or other materials provided with the distribution. 1688768458SSam Leffler * 3. Neither the name of the project nor the names of its contributors 1788768458SSam Leffler * may be used to endorse or promote products derived from this software 1888768458SSam Leffler * without specific prior written permission. 1988768458SSam Leffler * 2088768458SSam Leffler * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 2188768458SSam Leffler * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2288768458SSam Leffler * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2388768458SSam Leffler * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 2488768458SSam Leffler * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2588768458SSam Leffler * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2688768458SSam Leffler * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2788768458SSam Leffler * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2888768458SSam Leffler * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2988768458SSam Leffler * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3088768458SSam Leffler * SUCH DAMAGE. 3188768458SSam Leffler */ 3288768458SSam Leffler 3388768458SSam Leffler #include "opt_ipsec.h" 3488768458SSam Leffler 3588768458SSam Leffler /* This code has derived from sys/net/rtsock.c on FreeBSD2.2.5 */ 3688768458SSam Leffler 3788768458SSam Leffler #include <sys/types.h> 3888768458SSam Leffler #include <sys/param.h> 3988768458SSam Leffler #include <sys/domain.h> 4088768458SSam Leffler #include <sys/errno.h> 4188768458SSam Leffler #include <sys/kernel.h> 428eafa045SBruce M Simpson #include <sys/lock.h> 4388768458SSam Leffler #include <sys/malloc.h> 4488768458SSam Leffler #include <sys/mbuf.h> 458eafa045SBruce M Simpson #include <sys/mutex.h> 46190320e2SBjoern A. Zeeb #include <sys/priv.h> 4788768458SSam Leffler #include <sys/protosw.h> 4888768458SSam Leffler #include <sys/signalvar.h> 4988768458SSam Leffler #include <sys/socket.h> 5088768458SSam Leffler #include <sys/socketvar.h> 5188768458SSam Leffler #include <sys/sysctl.h> 5288768458SSam Leffler #include <sys/systm.h> 5388768458SSam Leffler 548b615593SMarko Zec #include <net/if.h> 55eedc7fd9SGleb Smirnoff #include <net/vnet.h> 5688768458SSam Leffler #include <net/raw_cb.h> 5788768458SSam Leffler 588b615593SMarko Zec #include <netinet/in.h> 598b615593SMarko Zec 6088768458SSam Leffler #include <net/pfkeyv2.h> 6188768458SSam Leffler #include <netipsec/key.h> 6288768458SSam Leffler #include <netipsec/keysock.h> 6388768458SSam Leffler #include <netipsec/key_debug.h> 648b615593SMarko Zec #include <netipsec/ipsec.h> 6588768458SSam Leffler 6688768458SSam Leffler #include <machine/stdarg.h> 6788768458SSam Leffler 68eddfbb76SRobert Watson struct key_cb { 69eddfbb76SRobert Watson int key_count; 70eddfbb76SRobert Watson int any_count; 71eddfbb76SRobert Watson }; 723e288e62SDimitry Andric static VNET_DEFINE(struct key_cb, key_cb); 731e77c105SRobert Watson #define V_key_cb VNET(key_cb) 7488768458SSam Leffler 75eddfbb76SRobert Watson static struct sockaddr key_src = { 2, PF_KEY, }; 7688768458SSam Leffler 7718961126SAndrey V. Elsukov static int key_sendup0(struct rawcb *, struct mbuf *, int); 7888768458SSam Leffler 79db8c0879SAndrey V. Elsukov VNET_PCPUSTAT_DEFINE(struct pfkeystat, pfkeystat); 80db8c0879SAndrey V. Elsukov VNET_PCPUSTAT_SYSINIT(pfkeystat); 81db8c0879SAndrey V. Elsukov 82db8c0879SAndrey V. Elsukov #ifdef VIMAGE 83db8c0879SAndrey V. Elsukov VNET_PCPUSTAT_SYSUNINIT(pfkeystat); 84db8c0879SAndrey V. Elsukov #endif /* VIMAGE */ 85eddfbb76SRobert Watson 8688768458SSam Leffler /* 8788768458SSam Leffler * key_output() 8888768458SSam Leffler */ 8988768458SSam Leffler int 9073d76e77SKevin Lo key_output(struct mbuf *m, struct socket *so, ...) 9188768458SSam Leffler { 9288768458SSam Leffler struct sadb_msg *msg; 9388768458SSam Leffler int len, error = 0; 9488768458SSam Leffler 9588768458SSam Leffler if (m == 0) 969ffa9677SSam Leffler panic("%s: NULL pointer was passed.\n", __func__); 9788768458SSam Leffler 98a04d64d8SAndrey V. Elsukov PFKEYSTAT_INC(out_total); 99a04d64d8SAndrey V. Elsukov PFKEYSTAT_ADD(out_bytes, m->m_pkthdr.len); 10088768458SSam Leffler 10188768458SSam Leffler len = m->m_pkthdr.len; 10288768458SSam Leffler if (len < sizeof(struct sadb_msg)) { 103a04d64d8SAndrey V. Elsukov PFKEYSTAT_INC(out_tooshort); 10488768458SSam Leffler error = EINVAL; 10588768458SSam Leffler goto end; 10688768458SSam Leffler } 10788768458SSam Leffler 10888768458SSam Leffler if (m->m_len < sizeof(struct sadb_msg)) { 10988768458SSam Leffler if ((m = m_pullup(m, sizeof(struct sadb_msg))) == 0) { 110a04d64d8SAndrey V. Elsukov PFKEYSTAT_INC(out_nomem); 11188768458SSam Leffler error = ENOBUFS; 11288768458SSam Leffler goto end; 11388768458SSam Leffler } 11488768458SSam Leffler } 11588768458SSam Leffler 116fe584538SDag-Erling Smørgrav M_ASSERTPKTHDR(m); 11788768458SSam Leffler 11888768458SSam Leffler KEYDEBUG(KEYDEBUG_KEY_DUMP, kdebug_mbuf(m)); 11988768458SSam Leffler 12088768458SSam Leffler msg = mtod(m, struct sadb_msg *); 121a04d64d8SAndrey V. Elsukov PFKEYSTAT_INC(out_msgtype[msg->sadb_msg_type]); 12288768458SSam Leffler if (len != PFKEY_UNUNIT64(msg->sadb_msg_len)) { 123a04d64d8SAndrey V. Elsukov PFKEYSTAT_INC(out_invlen); 12488768458SSam Leffler error = EINVAL; 12588768458SSam Leffler goto end; 12688768458SSam Leffler } 12788768458SSam Leffler 12888768458SSam Leffler error = key_parse(m, so); 12988768458SSam Leffler m = NULL; 13088768458SSam Leffler end: 13188768458SSam Leffler if (m) 13288768458SSam Leffler m_freem(m); 13388768458SSam Leffler return error; 13488768458SSam Leffler } 13588768458SSam Leffler 13688768458SSam Leffler /* 13788768458SSam Leffler * send message to the socket. 13888768458SSam Leffler */ 13988768458SSam Leffler static int 1402e84e6eaSAndrey V. Elsukov key_sendup0(struct rawcb *rp, struct mbuf *m, int promisc) 14188768458SSam Leffler { 14288768458SSam Leffler int error; 14388768458SSam Leffler 14488768458SSam Leffler if (promisc) { 14588768458SSam Leffler struct sadb_msg *pmsg; 14688768458SSam Leffler 147eb1b1807SGleb Smirnoff M_PREPEND(m, sizeof(struct sadb_msg), M_NOWAIT); 148*3d6aff56SAndrey V. Elsukov if (m == NULL) { 149a04d64d8SAndrey V. Elsukov PFKEYSTAT_INC(in_nomem); 150*3d6aff56SAndrey V. Elsukov return (ENOBUFS); 15188768458SSam Leffler } 152*3d6aff56SAndrey V. Elsukov m->m_pkthdr.len += sizeof(*pmsg); /* XXX: is this correct? */ 15388768458SSam Leffler 15488768458SSam Leffler pmsg = mtod(m, struct sadb_msg *); 15588768458SSam Leffler bzero(pmsg, sizeof(*pmsg)); 15688768458SSam Leffler pmsg->sadb_msg_version = PF_KEY_V2; 15788768458SSam Leffler pmsg->sadb_msg_type = SADB_X_PROMISC; 15888768458SSam Leffler pmsg->sadb_msg_len = PFKEY_UNIT64(m->m_pkthdr.len); 15988768458SSam Leffler /* pid and seq? */ 16088768458SSam Leffler 161a04d64d8SAndrey V. Elsukov PFKEYSTAT_INC(in_msgtype[pmsg->sadb_msg_type]); 16288768458SSam Leffler } 16388768458SSam Leffler 16497021c24SMarko Zec if (!sbappendaddr(&rp->rcb_socket->so_rcv, (struct sockaddr *)&key_src, 16588768458SSam Leffler m, NULL)) { 166a04d64d8SAndrey V. Elsukov PFKEYSTAT_INC(in_nomem); 16788768458SSam Leffler m_freem(m); 16888768458SSam Leffler error = ENOBUFS; 16988768458SSam Leffler } else 17088768458SSam Leffler error = 0; 17188768458SSam Leffler sorwakeup(rp->rcb_socket); 17288768458SSam Leffler return error; 17388768458SSam Leffler } 17488768458SSam Leffler 17588768458SSam Leffler /* XXX this interface should be obsoleted. */ 17688768458SSam Leffler int 1772e84e6eaSAndrey V. Elsukov key_sendup(struct socket *so, struct sadb_msg *msg, u_int len, int target) 17888768458SSam Leffler { 17988768458SSam Leffler struct mbuf *m, *n, *mprev; 18088768458SSam Leffler int tlen; 18188768458SSam Leffler 18288768458SSam Leffler /* sanity check */ 18388768458SSam Leffler if (so == 0 || msg == 0) 1849ffa9677SSam Leffler panic("%s: NULL pointer was passed.\n", __func__); 18588768458SSam Leffler 18688768458SSam Leffler KEYDEBUG(KEYDEBUG_KEY_DUMP, 1879ffa9677SSam Leffler printf("%s: \n", __func__); 18888768458SSam Leffler kdebug_sadb(msg)); 18988768458SSam Leffler 19088768458SSam Leffler /* 19188768458SSam Leffler * we increment statistics here, just in case we have ENOBUFS 19288768458SSam Leffler * in this function. 19388768458SSam Leffler */ 194a04d64d8SAndrey V. Elsukov PFKEYSTAT_INC(in_total); 195a04d64d8SAndrey V. Elsukov PFKEYSTAT_ADD(in_bytes, len); 196a04d64d8SAndrey V. Elsukov PFKEYSTAT_INC(in_msgtype[msg->sadb_msg_type]); 19788768458SSam Leffler 19888768458SSam Leffler /* 19988768458SSam Leffler * Get mbuf chain whenever possible (not clusters), 20088768458SSam Leffler * to save socket buffer. We'll be generating many SADB_ACQUIRE 20188768458SSam Leffler * messages to listening key sockets. If we simply allocate clusters, 20288768458SSam Leffler * sbappendaddr() will raise ENOBUFS due to too little sbspace(). 20388768458SSam Leffler * sbspace() computes # of actual data bytes AND mbuf region. 20488768458SSam Leffler * 20588768458SSam Leffler * TODO: SADB_ACQUIRE filters should be implemented. 20688768458SSam Leffler */ 20788768458SSam Leffler tlen = len; 20888768458SSam Leffler m = mprev = NULL; 20988768458SSam Leffler while (tlen > 0) { 21088768458SSam Leffler if (tlen == len) { 211eb1b1807SGleb Smirnoff MGETHDR(n, M_NOWAIT, MT_DATA); 2122cb64cb2SGeorge V. Neville-Neil if (n == NULL) { 213a04d64d8SAndrey V. Elsukov PFKEYSTAT_INC(in_nomem); 2142cb64cb2SGeorge V. Neville-Neil return ENOBUFS; 2152cb64cb2SGeorge V. Neville-Neil } 21688768458SSam Leffler n->m_len = MHLEN; 21788768458SSam Leffler } else { 218eb1b1807SGleb Smirnoff MGET(n, M_NOWAIT, MT_DATA); 2192cb64cb2SGeorge V. Neville-Neil if (n == NULL) { 220a04d64d8SAndrey V. Elsukov PFKEYSTAT_INC(in_nomem); 22188768458SSam Leffler return ENOBUFS; 22288768458SSam Leffler } 2232cb64cb2SGeorge V. Neville-Neil n->m_len = MLEN; 2242cb64cb2SGeorge V. Neville-Neil } 22588768458SSam Leffler if (tlen >= MCLBYTES) { /*XXX better threshold? */ 226eb1b1807SGleb Smirnoff MCLGET(n, M_NOWAIT); 22788768458SSam Leffler if ((n->m_flags & M_EXT) == 0) { 22888768458SSam Leffler m_free(n); 22988768458SSam Leffler m_freem(m); 230a04d64d8SAndrey V. Elsukov PFKEYSTAT_INC(in_nomem); 23188768458SSam Leffler return ENOBUFS; 23288768458SSam Leffler } 23388768458SSam Leffler n->m_len = MCLBYTES; 23488768458SSam Leffler } 23588768458SSam Leffler 23688768458SSam Leffler if (tlen < n->m_len) 23788768458SSam Leffler n->m_len = tlen; 23888768458SSam Leffler n->m_next = NULL; 23988768458SSam Leffler if (m == NULL) 24088768458SSam Leffler m = mprev = n; 24188768458SSam Leffler else { 24288768458SSam Leffler mprev->m_next = n; 24388768458SSam Leffler mprev = n; 24488768458SSam Leffler } 24588768458SSam Leffler tlen -= n->m_len; 24688768458SSam Leffler n = NULL; 24788768458SSam Leffler } 24888768458SSam Leffler m->m_pkthdr.len = len; 24988768458SSam Leffler m->m_pkthdr.rcvif = NULL; 25088768458SSam Leffler m_copyback(m, 0, len, (caddr_t)msg); 25188768458SSam Leffler 25288768458SSam Leffler /* avoid duplicated statistics */ 253a04d64d8SAndrey V. Elsukov PFKEYSTAT_ADD(in_total, -1); 254a04d64d8SAndrey V. Elsukov PFKEYSTAT_ADD(in_bytes, -len); 255a04d64d8SAndrey V. Elsukov PFKEYSTAT_ADD(in_msgtype[msg->sadb_msg_type], -1); 25688768458SSam Leffler 25788768458SSam Leffler return key_sendup_mbuf(so, m, target); 25888768458SSam Leffler } 25988768458SSam Leffler 26088768458SSam Leffler /* so can be NULL if target != KEY_SENDUP_ONE */ 26188768458SSam Leffler int 2622e84e6eaSAndrey V. Elsukov key_sendup_mbuf(struct socket *so, struct mbuf *m, int target) 26388768458SSam Leffler { 26488768458SSam Leffler struct mbuf *n; 26588768458SSam Leffler struct keycb *kp; 26688768458SSam Leffler int sendup; 26788768458SSam Leffler struct rawcb *rp; 26888768458SSam Leffler int error = 0; 26988768458SSam Leffler 27088768458SSam Leffler if (m == NULL) 27188768458SSam Leffler panic("key_sendup_mbuf: NULL pointer was passed.\n"); 27288768458SSam Leffler if (so == NULL && target == KEY_SENDUP_ONE) 2739ffa9677SSam Leffler panic("%s: NULL pointer was passed.\n", __func__); 27488768458SSam Leffler 275a04d64d8SAndrey V. Elsukov PFKEYSTAT_INC(in_total); 276a04d64d8SAndrey V. Elsukov PFKEYSTAT_ADD(in_bytes, m->m_pkthdr.len); 27788768458SSam Leffler if (m->m_len < sizeof(struct sadb_msg)) { 27888768458SSam Leffler m = m_pullup(m, sizeof(struct sadb_msg)); 27988768458SSam Leffler if (m == NULL) { 280a04d64d8SAndrey V. Elsukov PFKEYSTAT_INC(in_nomem); 28188768458SSam Leffler return ENOBUFS; 28288768458SSam Leffler } 28388768458SSam Leffler } 28488768458SSam Leffler if (m->m_len >= sizeof(struct sadb_msg)) { 28588768458SSam Leffler struct sadb_msg *msg; 28688768458SSam Leffler msg = mtod(m, struct sadb_msg *); 287a04d64d8SAndrey V. Elsukov PFKEYSTAT_INC(in_msgtype[msg->sadb_msg_type]); 28888768458SSam Leffler } 2892cb64cb2SGeorge V. Neville-Neil mtx_lock(&rawcb_mtx); 290603724d3SBjoern A. Zeeb LIST_FOREACH(rp, &V_rawcb_list, list) 29188768458SSam Leffler { 29288768458SSam Leffler if (rp->rcb_proto.sp_family != PF_KEY) 29388768458SSam Leffler continue; 29488768458SSam Leffler if (rp->rcb_proto.sp_protocol 29588768458SSam Leffler && rp->rcb_proto.sp_protocol != PF_KEY_V2) { 29688768458SSam Leffler continue; 29788768458SSam Leffler } 29888768458SSam Leffler 29988768458SSam Leffler kp = (struct keycb *)rp; 30088768458SSam Leffler 30188768458SSam Leffler /* 30288768458SSam Leffler * If you are in promiscuous mode, and when you get broadcasted 30388768458SSam Leffler * reply, you'll get two PF_KEY messages. 30488768458SSam Leffler * (based on pf_key@inner.net message on 14 Oct 1998) 30588768458SSam Leffler */ 30688768458SSam Leffler if (((struct keycb *)rp)->kp_promisc) { 30788768458SSam Leffler if ((n = m_copy(m, 0, (int)M_COPYALL)) != NULL) { 30888768458SSam Leffler (void)key_sendup0(rp, n, 1); 30988768458SSam Leffler n = NULL; 31088768458SSam Leffler } 31188768458SSam Leffler } 31288768458SSam Leffler 31388768458SSam Leffler /* the exact target will be processed later */ 31488768458SSam Leffler if (so && sotorawcb(so) == rp) 31588768458SSam Leffler continue; 31688768458SSam Leffler 31788768458SSam Leffler sendup = 0; 31888768458SSam Leffler switch (target) { 31988768458SSam Leffler case KEY_SENDUP_ONE: 32088768458SSam Leffler /* the statement has no effect */ 32188768458SSam Leffler if (so && sotorawcb(so) == rp) 32288768458SSam Leffler sendup++; 32388768458SSam Leffler break; 32488768458SSam Leffler case KEY_SENDUP_ALL: 32588768458SSam Leffler sendup++; 32688768458SSam Leffler break; 32788768458SSam Leffler case KEY_SENDUP_REGISTERED: 32888768458SSam Leffler if (kp->kp_registered) 32988768458SSam Leffler sendup++; 33088768458SSam Leffler break; 33188768458SSam Leffler } 332a04d64d8SAndrey V. Elsukov PFKEYSTAT_INC(in_msgtarget[target]); 33388768458SSam Leffler 33488768458SSam Leffler if (!sendup) 33588768458SSam Leffler continue; 33688768458SSam Leffler 33788768458SSam Leffler if ((n = m_copy(m, 0, (int)M_COPYALL)) == NULL) { 33888768458SSam Leffler m_freem(m); 339a04d64d8SAndrey V. Elsukov PFKEYSTAT_INC(in_nomem); 3402cb64cb2SGeorge V. Neville-Neil mtx_unlock(&rawcb_mtx); 34188768458SSam Leffler return ENOBUFS; 34288768458SSam Leffler } 34388768458SSam Leffler 34488768458SSam Leffler if ((error = key_sendup0(rp, n, 0)) != 0) { 34588768458SSam Leffler m_freem(m); 3462cb64cb2SGeorge V. Neville-Neil mtx_unlock(&rawcb_mtx); 34788768458SSam Leffler return error; 34888768458SSam Leffler } 34988768458SSam Leffler 35088768458SSam Leffler n = NULL; 35188768458SSam Leffler } 35288768458SSam Leffler 35388768458SSam Leffler if (so) { 35488768458SSam Leffler error = key_sendup0(sotorawcb(so), m, 0); 35588768458SSam Leffler m = NULL; 35688768458SSam Leffler } else { 35788768458SSam Leffler error = 0; 35888768458SSam Leffler m_freem(m); 35988768458SSam Leffler } 3602cb64cb2SGeorge V. Neville-Neil mtx_unlock(&rawcb_mtx); 36188768458SSam Leffler return error; 36288768458SSam Leffler } 36388768458SSam Leffler 36488768458SSam Leffler /* 36588768458SSam Leffler * key_abort() 36688768458SSam Leffler * derived from net/rtsock.c:rts_abort() 36788768458SSam Leffler */ 368ac45e92fSRobert Watson static void 36988768458SSam Leffler key_abort(struct socket *so) 37088768458SSam Leffler { 371ac45e92fSRobert Watson raw_usrreqs.pru_abort(so); 37288768458SSam Leffler } 37388768458SSam Leffler 37488768458SSam Leffler /* 37588768458SSam Leffler * key_attach() 37688768458SSam Leffler * derived from net/rtsock.c:rts_attach() 37788768458SSam Leffler */ 37888768458SSam Leffler static int 37988768458SSam Leffler key_attach(struct socket *so, int proto, struct thread *td) 38088768458SSam Leffler { 38188768458SSam Leffler struct keycb *kp; 3822cb64cb2SGeorge V. Neville-Neil int error; 38388768458SSam Leffler 3842cb64cb2SGeorge V. Neville-Neil KASSERT(so->so_pcb == NULL, ("key_attach: so_pcb != NULL")); 3852cb64cb2SGeorge V. Neville-Neil 386cf94a6a9SBjoern A. Zeeb if (td != NULL) { 387cf94a6a9SBjoern A. Zeeb error = priv_check(td, PRIV_NET_RAW); 388cf94a6a9SBjoern A. Zeeb if (error) 389cf94a6a9SBjoern A. Zeeb return error; 390cf94a6a9SBjoern A. Zeeb } 391cf94a6a9SBjoern A. Zeeb 3922cb64cb2SGeorge V. Neville-Neil /* XXX */ 3931ede983cSDag-Erling Smørgrav kp = malloc(sizeof *kp, M_PCB, M_WAITOK | M_ZERO); 39488768458SSam Leffler if (kp == 0) 39588768458SSam Leffler return ENOBUFS; 39688768458SSam Leffler 39788768458SSam Leffler so->so_pcb = (caddr_t)kp; 3982cb64cb2SGeorge V. Neville-Neil error = raw_attach(so, proto); 39988768458SSam Leffler kp = (struct keycb *)sotorawcb(so); 40088768458SSam Leffler if (error) { 40188768458SSam Leffler free(kp, M_PCB); 40288768458SSam Leffler so->so_pcb = (caddr_t) 0; 40388768458SSam Leffler return error; 40488768458SSam Leffler } 40588768458SSam Leffler 40688768458SSam Leffler kp->kp_promisc = kp->kp_registered = 0; 40788768458SSam Leffler 40888768458SSam Leffler if (kp->kp_raw.rcb_proto.sp_protocol == PF_KEY) /* XXX: AF_KEY */ 409603724d3SBjoern A. Zeeb V_key_cb.key_count++; 410603724d3SBjoern A. Zeeb V_key_cb.any_count++; 41188768458SSam Leffler soisconnected(so); 41288768458SSam Leffler so->so_options |= SO_USELOOPBACK; 41388768458SSam Leffler 41488768458SSam Leffler return 0; 41588768458SSam Leffler } 41688768458SSam Leffler 41788768458SSam Leffler /* 41888768458SSam Leffler * key_bind() 41988768458SSam Leffler * derived from net/rtsock.c:rts_bind() 42088768458SSam Leffler */ 42188768458SSam Leffler static int 42288768458SSam Leffler key_bind(struct socket *so, struct sockaddr *nam, struct thread *td) 42388768458SSam Leffler { 4242cb64cb2SGeorge V. Neville-Neil return EINVAL; 42588768458SSam Leffler } 42688768458SSam Leffler 42788768458SSam Leffler /* 428a152f8a3SRobert Watson * key_close() 429a152f8a3SRobert Watson * derived from net/rtsock.c:rts_close(). 430a152f8a3SRobert Watson */ 431a152f8a3SRobert Watson static void 43287b4dfd5SGeorge V. Neville-Neil key_close(struct socket *so) 433a152f8a3SRobert Watson { 434a152f8a3SRobert Watson 435a152f8a3SRobert Watson raw_usrreqs.pru_close(so); 436a152f8a3SRobert Watson } 437a152f8a3SRobert Watson 438a152f8a3SRobert Watson /* 43988768458SSam Leffler * key_connect() 44088768458SSam Leffler * derived from net/rtsock.c:rts_connect() 44188768458SSam Leffler */ 44288768458SSam Leffler static int 44388768458SSam Leffler key_connect(struct socket *so, struct sockaddr *nam, struct thread *td) 44488768458SSam Leffler { 4452cb64cb2SGeorge V. Neville-Neil return EINVAL; 44688768458SSam Leffler } 44788768458SSam Leffler 44888768458SSam Leffler /* 44988768458SSam Leffler * key_detach() 45088768458SSam Leffler * derived from net/rtsock.c:rts_detach() 45188768458SSam Leffler */ 452bc725eafSRobert Watson static void 45388768458SSam Leffler key_detach(struct socket *so) 45488768458SSam Leffler { 45588768458SSam Leffler struct keycb *kp = (struct keycb *)sotorawcb(so); 45688768458SSam Leffler 457bc725eafSRobert Watson KASSERT(kp != NULL, ("key_detach: kp == NULL")); 45888768458SSam Leffler if (kp->kp_raw.rcb_proto.sp_protocol 45988768458SSam Leffler == PF_KEY) /* XXX: AF_KEY */ 460603724d3SBjoern A. Zeeb V_key_cb.key_count--; 461603724d3SBjoern A. Zeeb V_key_cb.any_count--; 46288768458SSam Leffler 46388768458SSam Leffler key_freereg(so); 464bc725eafSRobert Watson raw_usrreqs.pru_detach(so); 46588768458SSam Leffler } 46688768458SSam Leffler 46788768458SSam Leffler /* 46888768458SSam Leffler * key_disconnect() 46988768458SSam Leffler * derived from net/rtsock.c:key_disconnect() 47088768458SSam Leffler */ 47188768458SSam Leffler static int 47288768458SSam Leffler key_disconnect(struct socket *so) 47388768458SSam Leffler { 4742cb64cb2SGeorge V. Neville-Neil return(raw_usrreqs.pru_disconnect(so)); 47588768458SSam Leffler } 47688768458SSam Leffler 47788768458SSam Leffler /* 47888768458SSam Leffler * key_peeraddr() 47988768458SSam Leffler * derived from net/rtsock.c:rts_peeraddr() 48088768458SSam Leffler */ 48188768458SSam Leffler static int 48288768458SSam Leffler key_peeraddr(struct socket *so, struct sockaddr **nam) 48388768458SSam Leffler { 4842cb64cb2SGeorge V. Neville-Neil return(raw_usrreqs.pru_peeraddr(so, nam)); 48588768458SSam Leffler } 48688768458SSam Leffler 48788768458SSam Leffler /* 48888768458SSam Leffler * key_send() 48988768458SSam Leffler * derived from net/rtsock.c:rts_send() 49088768458SSam Leffler */ 49188768458SSam Leffler static int 49288768458SSam Leffler key_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *nam, 49388768458SSam Leffler struct mbuf *control, struct thread *td) 49488768458SSam Leffler { 4952cb64cb2SGeorge V. Neville-Neil return(raw_usrreqs.pru_send(so, flags, m, nam, control, td)); 49688768458SSam Leffler } 49788768458SSam Leffler 49888768458SSam Leffler /* 49988768458SSam Leffler * key_shutdown() 50088768458SSam Leffler * derived from net/rtsock.c:rts_shutdown() 50188768458SSam Leffler */ 50288768458SSam Leffler static int 50388768458SSam Leffler key_shutdown(struct socket *so) 50488768458SSam Leffler { 5052cb64cb2SGeorge V. Neville-Neil return(raw_usrreqs.pru_shutdown(so)); 50688768458SSam Leffler } 50788768458SSam Leffler 50888768458SSam Leffler /* 50988768458SSam Leffler * key_sockaddr() 51088768458SSam Leffler * derived from net/rtsock.c:rts_sockaddr() 51188768458SSam Leffler */ 51288768458SSam Leffler static int 51388768458SSam Leffler key_sockaddr(struct socket *so, struct sockaddr **nam) 51488768458SSam Leffler { 5152cb64cb2SGeorge V. Neville-Neil return(raw_usrreqs.pru_sockaddr(so, nam)); 51688768458SSam Leffler } 51788768458SSam Leffler 51888768458SSam Leffler struct pr_usrreqs key_usrreqs = { 519756d52a1SPoul-Henning Kamp .pru_abort = key_abort, 520756d52a1SPoul-Henning Kamp .pru_attach = key_attach, 521756d52a1SPoul-Henning Kamp .pru_bind = key_bind, 522756d52a1SPoul-Henning Kamp .pru_connect = key_connect, 523756d52a1SPoul-Henning Kamp .pru_detach = key_detach, 524756d52a1SPoul-Henning Kamp .pru_disconnect = key_disconnect, 525756d52a1SPoul-Henning Kamp .pru_peeraddr = key_peeraddr, 526756d52a1SPoul-Henning Kamp .pru_send = key_send, 527756d52a1SPoul-Henning Kamp .pru_shutdown = key_shutdown, 528756d52a1SPoul-Henning Kamp .pru_sockaddr = key_sockaddr, 529a152f8a3SRobert Watson .pru_close = key_close, 53088768458SSam Leffler }; 53188768458SSam Leffler 53288768458SSam Leffler /* sysctl */ 53388768458SSam Leffler SYSCTL_NODE(_net, PF_KEY, key, CTLFLAG_RW, 0, "Key Family"); 53488768458SSam Leffler 53588768458SSam Leffler /* 53688768458SSam Leffler * Definitions of protocols supported in the KEY domain. 53788768458SSam Leffler */ 53888768458SSam Leffler 53988768458SSam Leffler extern struct domain keydomain; 54088768458SSam Leffler 54188768458SSam Leffler struct protosw keysw[] = { 542303989a2SRuslan Ermilov { 543303989a2SRuslan Ermilov .pr_type = SOCK_RAW, 544303989a2SRuslan Ermilov .pr_domain = &keydomain, 545303989a2SRuslan Ermilov .pr_protocol = PF_KEY_V2, 546303989a2SRuslan Ermilov .pr_flags = PR_ATOMIC|PR_ADDR, 5473f2e28feSBjoern A. Zeeb .pr_output = key_output, 548303989a2SRuslan Ermilov .pr_ctlinput = raw_ctlinput, 549303989a2SRuslan Ermilov .pr_init = raw_init, 550303989a2SRuslan Ermilov .pr_usrreqs = &key_usrreqs 55188768458SSam Leffler } 55288768458SSam Leffler }; 55388768458SSam Leffler 55488768458SSam Leffler static void 55588768458SSam Leffler key_init0(void) 55688768458SSam Leffler { 55744e33a07SMarko Zec 558603724d3SBjoern A. Zeeb bzero((caddr_t)&V_key_cb, sizeof(V_key_cb)); 55988768458SSam Leffler key_init(); 56088768458SSam Leffler } 56188768458SSam Leffler 562303989a2SRuslan Ermilov struct domain keydomain = { 563303989a2SRuslan Ermilov .dom_family = PF_KEY, 564303989a2SRuslan Ermilov .dom_name = "key", 565303989a2SRuslan Ermilov .dom_init = key_init0, 566bc29160dSMarko Zec #ifdef VIMAGE 567bc29160dSMarko Zec .dom_destroy = key_destroy, 568bc29160dSMarko Zec #endif 569303989a2SRuslan Ermilov .dom_protosw = keysw, 570303989a2SRuslan Ermilov .dom_protoswNPROTOSW = &keysw[sizeof(keysw)/sizeof(keysw[0])] 571303989a2SRuslan Ermilov }; 57288768458SSam Leffler 573d0728d71SRobert Watson VNET_DOMAIN_SET(key); 574