188768458SSam Leffler /* $FreeBSD$ */ 288768458SSam Leffler /* $KAME: keysock.c,v 1.25 2001/08/13 20:07:41 itojun Exp $ */ 388768458SSam Leffler 488768458SSam Leffler /* 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> 4688768458SSam Leffler #include <sys/protosw.h> 4788768458SSam Leffler #include <sys/signalvar.h> 4888768458SSam Leffler #include <sys/socket.h> 4988768458SSam Leffler #include <sys/socketvar.h> 5088768458SSam Leffler #include <sys/sysctl.h> 5188768458SSam Leffler #include <sys/systm.h> 5288768458SSam Leffler 5388768458SSam Leffler #include <net/raw_cb.h> 5488768458SSam Leffler #include <net/route.h> 5588768458SSam Leffler 5688768458SSam Leffler #include <net/pfkeyv2.h> 5788768458SSam Leffler #include <netipsec/key.h> 5888768458SSam Leffler #include <netipsec/keysock.h> 5988768458SSam Leffler #include <netipsec/key_debug.h> 6088768458SSam Leffler 6188768458SSam Leffler #include <machine/stdarg.h> 6288768458SSam Leffler 6388768458SSam Leffler struct key_cb { 6488768458SSam Leffler int key_count; 6588768458SSam Leffler int any_count; 6688768458SSam Leffler }; 6788768458SSam Leffler static struct key_cb key_cb; 6888768458SSam Leffler 6988768458SSam Leffler static struct sockaddr key_dst = { 2, PF_KEY, }; 7088768458SSam Leffler static struct sockaddr key_src = { 2, PF_KEY, }; 7188768458SSam Leffler 7288768458SSam Leffler static int key_sendup0 __P((struct rawcb *, struct mbuf *, int)); 7388768458SSam Leffler 7488768458SSam Leffler struct pfkeystat pfkeystat; 7588768458SSam Leffler 7688768458SSam Leffler /* 7788768458SSam Leffler * key_output() 7888768458SSam Leffler */ 7988768458SSam Leffler int 8088768458SSam Leffler #if __STDC__ 8188768458SSam Leffler key_output(struct mbuf *m, ...) 8288768458SSam Leffler #else 8388768458SSam Leffler key_output(m, va_alist) 8488768458SSam Leffler struct mbuf *m; 8588768458SSam Leffler va_dcl 8688768458SSam Leffler #endif 8788768458SSam Leffler { 8888768458SSam Leffler struct sadb_msg *msg; 8988768458SSam Leffler int len, error = 0; 9088768458SSam Leffler int s; 9188768458SSam Leffler struct socket *so; 9288768458SSam Leffler va_list ap; 9388768458SSam Leffler 9488768458SSam Leffler va_start(ap, m); 9588768458SSam Leffler so = va_arg(ap, struct socket *); 9688768458SSam Leffler va_end(ap); 9788768458SSam Leffler 9888768458SSam Leffler if (m == 0) 999ffa9677SSam Leffler panic("%s: NULL pointer was passed.\n", __func__); 10088768458SSam Leffler 10188768458SSam Leffler pfkeystat.out_total++; 10288768458SSam Leffler pfkeystat.out_bytes += m->m_pkthdr.len; 10388768458SSam Leffler 10488768458SSam Leffler len = m->m_pkthdr.len; 10588768458SSam Leffler if (len < sizeof(struct sadb_msg)) { 10688768458SSam Leffler pfkeystat.out_tooshort++; 10788768458SSam Leffler error = EINVAL; 10888768458SSam Leffler goto end; 10988768458SSam Leffler } 11088768458SSam Leffler 11188768458SSam Leffler if (m->m_len < sizeof(struct sadb_msg)) { 11288768458SSam Leffler if ((m = m_pullup(m, sizeof(struct sadb_msg))) == 0) { 11388768458SSam Leffler pfkeystat.out_nomem++; 11488768458SSam Leffler error = ENOBUFS; 11588768458SSam Leffler goto end; 11688768458SSam Leffler } 11788768458SSam Leffler } 11888768458SSam Leffler 119fe584538SDag-Erling Smørgrav M_ASSERTPKTHDR(m); 12088768458SSam Leffler 12188768458SSam Leffler KEYDEBUG(KEYDEBUG_KEY_DUMP, kdebug_mbuf(m)); 12288768458SSam Leffler 12388768458SSam Leffler msg = mtod(m, struct sadb_msg *); 12488768458SSam Leffler pfkeystat.out_msgtype[msg->sadb_msg_type]++; 12588768458SSam Leffler if (len != PFKEY_UNUNIT64(msg->sadb_msg_len)) { 12688768458SSam Leffler pfkeystat.out_invlen++; 12788768458SSam Leffler error = EINVAL; 12888768458SSam Leffler goto end; 12988768458SSam Leffler } 13088768458SSam Leffler 13188768458SSam Leffler /*XXX giant lock*/ 13288768458SSam Leffler s = splnet(); 13388768458SSam Leffler error = key_parse(m, so); 13488768458SSam Leffler m = NULL; 13588768458SSam Leffler splx(s); 13688768458SSam Leffler end: 13788768458SSam Leffler if (m) 13888768458SSam Leffler m_freem(m); 13988768458SSam Leffler return error; 14088768458SSam Leffler } 14188768458SSam Leffler 14288768458SSam Leffler /* 14388768458SSam Leffler * send message to the socket. 14488768458SSam Leffler */ 14588768458SSam Leffler static int 14688768458SSam Leffler key_sendup0(rp, m, promisc) 14788768458SSam Leffler struct rawcb *rp; 14888768458SSam Leffler struct mbuf *m; 14988768458SSam Leffler int promisc; 15088768458SSam Leffler { 15188768458SSam Leffler int error; 15288768458SSam Leffler 15388768458SSam Leffler if (promisc) { 15488768458SSam Leffler struct sadb_msg *pmsg; 15588768458SSam Leffler 156a163d034SWarner Losh M_PREPEND(m, sizeof(struct sadb_msg), M_DONTWAIT); 15788768458SSam Leffler if (m && m->m_len < sizeof(struct sadb_msg)) 15888768458SSam Leffler m = m_pullup(m, sizeof(struct sadb_msg)); 15988768458SSam Leffler if (!m) { 16088768458SSam Leffler pfkeystat.in_nomem++; 16188768458SSam Leffler m_freem(m); 16288768458SSam Leffler return ENOBUFS; 16388768458SSam Leffler } 16488768458SSam Leffler m->m_pkthdr.len += sizeof(*pmsg); 16588768458SSam Leffler 16688768458SSam Leffler pmsg = mtod(m, struct sadb_msg *); 16788768458SSam Leffler bzero(pmsg, sizeof(*pmsg)); 16888768458SSam Leffler pmsg->sadb_msg_version = PF_KEY_V2; 16988768458SSam Leffler pmsg->sadb_msg_type = SADB_X_PROMISC; 17088768458SSam Leffler pmsg->sadb_msg_len = PFKEY_UNIT64(m->m_pkthdr.len); 17188768458SSam Leffler /* pid and seq? */ 17288768458SSam Leffler 17388768458SSam Leffler pfkeystat.in_msgtype[pmsg->sadb_msg_type]++; 17488768458SSam Leffler } 17588768458SSam Leffler 17688768458SSam Leffler if (!sbappendaddr(&rp->rcb_socket->so_rcv, (struct sockaddr *)&key_src, 17788768458SSam Leffler m, NULL)) { 17888768458SSam Leffler pfkeystat.in_nomem++; 17988768458SSam Leffler m_freem(m); 18088768458SSam Leffler error = ENOBUFS; 18188768458SSam Leffler } else 18288768458SSam Leffler error = 0; 18388768458SSam Leffler sorwakeup(rp->rcb_socket); 18488768458SSam Leffler return error; 18588768458SSam Leffler } 18688768458SSam Leffler 18788768458SSam Leffler /* XXX this interface should be obsoleted. */ 18888768458SSam Leffler int 18988768458SSam Leffler key_sendup(so, msg, len, target) 19088768458SSam Leffler struct socket *so; 19188768458SSam Leffler struct sadb_msg *msg; 19288768458SSam Leffler u_int len; 19388768458SSam Leffler int target; /*target of the resulting message*/ 19488768458SSam Leffler { 19588768458SSam Leffler struct mbuf *m, *n, *mprev; 19688768458SSam Leffler int tlen; 19788768458SSam Leffler 19888768458SSam Leffler /* sanity check */ 19988768458SSam Leffler if (so == 0 || msg == 0) 2009ffa9677SSam Leffler panic("%s: NULL pointer was passed.\n", __func__); 20188768458SSam Leffler 20288768458SSam Leffler KEYDEBUG(KEYDEBUG_KEY_DUMP, 2039ffa9677SSam Leffler printf("%s: \n", __func__); 20488768458SSam Leffler kdebug_sadb(msg)); 20588768458SSam Leffler 20688768458SSam Leffler /* 20788768458SSam Leffler * we increment statistics here, just in case we have ENOBUFS 20888768458SSam Leffler * in this function. 20988768458SSam Leffler */ 21088768458SSam Leffler pfkeystat.in_total++; 21188768458SSam Leffler pfkeystat.in_bytes += len; 21288768458SSam Leffler pfkeystat.in_msgtype[msg->sadb_msg_type]++; 21388768458SSam Leffler 21488768458SSam Leffler /* 21588768458SSam Leffler * Get mbuf chain whenever possible (not clusters), 21688768458SSam Leffler * to save socket buffer. We'll be generating many SADB_ACQUIRE 21788768458SSam Leffler * messages to listening key sockets. If we simply allocate clusters, 21888768458SSam Leffler * sbappendaddr() will raise ENOBUFS due to too little sbspace(). 21988768458SSam Leffler * sbspace() computes # of actual data bytes AND mbuf region. 22088768458SSam Leffler * 22188768458SSam Leffler * TODO: SADB_ACQUIRE filters should be implemented. 22288768458SSam Leffler */ 22388768458SSam Leffler tlen = len; 22488768458SSam Leffler m = mprev = NULL; 22588768458SSam Leffler while (tlen > 0) { 22688768458SSam Leffler if (tlen == len) { 227a163d034SWarner Losh MGETHDR(n, M_DONTWAIT, MT_DATA); 22888768458SSam Leffler n->m_len = MHLEN; 22988768458SSam Leffler } else { 230a163d034SWarner Losh MGET(n, M_DONTWAIT, MT_DATA); 23188768458SSam Leffler n->m_len = MLEN; 23288768458SSam Leffler } 23388768458SSam Leffler if (!n) { 23488768458SSam Leffler pfkeystat.in_nomem++; 23588768458SSam Leffler return ENOBUFS; 23688768458SSam Leffler } 23788768458SSam Leffler if (tlen >= MCLBYTES) { /*XXX better threshold? */ 238a163d034SWarner Losh MCLGET(n, M_DONTWAIT); 23988768458SSam Leffler if ((n->m_flags & M_EXT) == 0) { 24088768458SSam Leffler m_free(n); 24188768458SSam Leffler m_freem(m); 24288768458SSam Leffler pfkeystat.in_nomem++; 24388768458SSam Leffler return ENOBUFS; 24488768458SSam Leffler } 24588768458SSam Leffler n->m_len = MCLBYTES; 24688768458SSam Leffler } 24788768458SSam Leffler 24888768458SSam Leffler if (tlen < n->m_len) 24988768458SSam Leffler n->m_len = tlen; 25088768458SSam Leffler n->m_next = NULL; 25188768458SSam Leffler if (m == NULL) 25288768458SSam Leffler m = mprev = n; 25388768458SSam Leffler else { 25488768458SSam Leffler mprev->m_next = n; 25588768458SSam Leffler mprev = n; 25688768458SSam Leffler } 25788768458SSam Leffler tlen -= n->m_len; 25888768458SSam Leffler n = NULL; 25988768458SSam Leffler } 26088768458SSam Leffler m->m_pkthdr.len = len; 26188768458SSam Leffler m->m_pkthdr.rcvif = NULL; 26288768458SSam Leffler m_copyback(m, 0, len, (caddr_t)msg); 26388768458SSam Leffler 26488768458SSam Leffler /* avoid duplicated statistics */ 26588768458SSam Leffler pfkeystat.in_total--; 26688768458SSam Leffler pfkeystat.in_bytes -= len; 26788768458SSam Leffler pfkeystat.in_msgtype[msg->sadb_msg_type]--; 26888768458SSam Leffler 26988768458SSam Leffler return key_sendup_mbuf(so, m, target); 27088768458SSam Leffler } 27188768458SSam Leffler 27288768458SSam Leffler /* so can be NULL if target != KEY_SENDUP_ONE */ 27388768458SSam Leffler int 27488768458SSam Leffler key_sendup_mbuf(so, m, target) 27588768458SSam Leffler struct socket *so; 27688768458SSam Leffler struct mbuf *m; 27788768458SSam Leffler int target; 27888768458SSam Leffler { 27988768458SSam Leffler struct mbuf *n; 28088768458SSam Leffler struct keycb *kp; 28188768458SSam Leffler int sendup; 28288768458SSam Leffler struct rawcb *rp; 28388768458SSam Leffler int error = 0; 28488768458SSam Leffler 28588768458SSam Leffler if (m == NULL) 28688768458SSam Leffler panic("key_sendup_mbuf: NULL pointer was passed.\n"); 28788768458SSam Leffler if (so == NULL && target == KEY_SENDUP_ONE) 2889ffa9677SSam Leffler panic("%s: NULL pointer was passed.\n", __func__); 28988768458SSam Leffler 29088768458SSam Leffler pfkeystat.in_total++; 29188768458SSam Leffler pfkeystat.in_bytes += m->m_pkthdr.len; 29288768458SSam Leffler if (m->m_len < sizeof(struct sadb_msg)) { 29388768458SSam Leffler #if 1 29488768458SSam Leffler m = m_pullup(m, sizeof(struct sadb_msg)); 29588768458SSam Leffler if (m == NULL) { 29688768458SSam Leffler pfkeystat.in_nomem++; 29788768458SSam Leffler return ENOBUFS; 29888768458SSam Leffler } 29988768458SSam Leffler #else 30088768458SSam Leffler /* don't bother pulling it up just for stats */ 30188768458SSam Leffler #endif 30288768458SSam Leffler } 30388768458SSam Leffler if (m->m_len >= sizeof(struct sadb_msg)) { 30488768458SSam Leffler struct sadb_msg *msg; 30588768458SSam Leffler msg = mtod(m, struct sadb_msg *); 30688768458SSam Leffler pfkeystat.in_msgtype[msg->sadb_msg_type]++; 30788768458SSam Leffler } 30888768458SSam Leffler 30988768458SSam Leffler LIST_FOREACH(rp, &rawcb_list, list) 31088768458SSam Leffler { 31188768458SSam Leffler if (rp->rcb_proto.sp_family != PF_KEY) 31288768458SSam Leffler continue; 31388768458SSam Leffler if (rp->rcb_proto.sp_protocol 31488768458SSam Leffler && rp->rcb_proto.sp_protocol != PF_KEY_V2) { 31588768458SSam Leffler continue; 31688768458SSam Leffler } 31788768458SSam Leffler 31888768458SSam Leffler kp = (struct keycb *)rp; 31988768458SSam Leffler 32088768458SSam Leffler /* 32188768458SSam Leffler * If you are in promiscuous mode, and when you get broadcasted 32288768458SSam Leffler * reply, you'll get two PF_KEY messages. 32388768458SSam Leffler * (based on pf_key@inner.net message on 14 Oct 1998) 32488768458SSam Leffler */ 32588768458SSam Leffler if (((struct keycb *)rp)->kp_promisc) { 32688768458SSam Leffler if ((n = m_copy(m, 0, (int)M_COPYALL)) != NULL) { 32788768458SSam Leffler (void)key_sendup0(rp, n, 1); 32888768458SSam Leffler n = NULL; 32988768458SSam Leffler } 33088768458SSam Leffler } 33188768458SSam Leffler 33288768458SSam Leffler /* the exact target will be processed later */ 33388768458SSam Leffler if (so && sotorawcb(so) == rp) 33488768458SSam Leffler continue; 33588768458SSam Leffler 33688768458SSam Leffler sendup = 0; 33788768458SSam Leffler switch (target) { 33888768458SSam Leffler case KEY_SENDUP_ONE: 33988768458SSam Leffler /* the statement has no effect */ 34088768458SSam Leffler if (so && sotorawcb(so) == rp) 34188768458SSam Leffler sendup++; 34288768458SSam Leffler break; 34388768458SSam Leffler case KEY_SENDUP_ALL: 34488768458SSam Leffler sendup++; 34588768458SSam Leffler break; 34688768458SSam Leffler case KEY_SENDUP_REGISTERED: 34788768458SSam Leffler if (kp->kp_registered) 34888768458SSam Leffler sendup++; 34988768458SSam Leffler break; 35088768458SSam Leffler } 35188768458SSam Leffler pfkeystat.in_msgtarget[target]++; 35288768458SSam Leffler 35388768458SSam Leffler if (!sendup) 35488768458SSam Leffler continue; 35588768458SSam Leffler 35688768458SSam Leffler if ((n = m_copy(m, 0, (int)M_COPYALL)) == NULL) { 35788768458SSam Leffler m_freem(m); 35888768458SSam Leffler pfkeystat.in_nomem++; 35988768458SSam Leffler return ENOBUFS; 36088768458SSam Leffler } 36188768458SSam Leffler 36288768458SSam Leffler if ((error = key_sendup0(rp, n, 0)) != 0) { 36388768458SSam Leffler m_freem(m); 36488768458SSam Leffler return error; 36588768458SSam Leffler } 36688768458SSam Leffler 36788768458SSam Leffler n = NULL; 36888768458SSam Leffler } 36988768458SSam Leffler 37088768458SSam Leffler if (so) { 37188768458SSam Leffler error = key_sendup0(sotorawcb(so), m, 0); 37288768458SSam Leffler m = NULL; 37388768458SSam Leffler } else { 37488768458SSam Leffler error = 0; 37588768458SSam Leffler m_freem(m); 37688768458SSam Leffler } 37788768458SSam Leffler return error; 37888768458SSam Leffler } 37988768458SSam Leffler 38088768458SSam Leffler /* 38188768458SSam Leffler * key_abort() 38288768458SSam Leffler * derived from net/rtsock.c:rts_abort() 38388768458SSam Leffler */ 38488768458SSam Leffler static int 38588768458SSam Leffler key_abort(struct socket *so) 38688768458SSam Leffler { 38788768458SSam Leffler int s, error; 38888768458SSam Leffler s = splnet(); 38988768458SSam Leffler error = raw_usrreqs.pru_abort(so); 39088768458SSam Leffler splx(s); 39188768458SSam Leffler return error; 39288768458SSam Leffler } 39388768458SSam Leffler 39488768458SSam Leffler /* 39588768458SSam Leffler * key_attach() 39688768458SSam Leffler * derived from net/rtsock.c:rts_attach() 39788768458SSam Leffler */ 39888768458SSam Leffler static int 39988768458SSam Leffler key_attach(struct socket *so, int proto, struct thread *td) 40088768458SSam Leffler { 40188768458SSam Leffler struct keycb *kp; 40288768458SSam Leffler int s, error; 40388768458SSam Leffler 40488768458SSam Leffler if (sotorawcb(so) != 0) 40588768458SSam Leffler return EISCONN; /* XXX panic? */ 406a163d034SWarner Losh kp = (struct keycb *)malloc(sizeof *kp, M_PCB, M_WAITOK|M_ZERO); /* XXX */ 40788768458SSam Leffler if (kp == 0) 40888768458SSam Leffler return ENOBUFS; 40988768458SSam Leffler 41088768458SSam Leffler /* 41188768458SSam Leffler * The splnet() is necessary to block protocols from sending 41288768458SSam Leffler * error notifications (like RTM_REDIRECT or RTM_LOSING) while 41388768458SSam Leffler * this PCB is extant but incompletely initialized. 41488768458SSam Leffler * Probably we should try to do more of this work beforehand and 41588768458SSam Leffler * eliminate the spl. 41688768458SSam Leffler */ 41788768458SSam Leffler s = splnet(); 41888768458SSam Leffler so->so_pcb = (caddr_t)kp; 41988768458SSam Leffler error = raw_usrreqs.pru_attach(so, proto, td); 42088768458SSam Leffler kp = (struct keycb *)sotorawcb(so); 42188768458SSam Leffler if (error) { 42288768458SSam Leffler free(kp, M_PCB); 42388768458SSam Leffler so->so_pcb = (caddr_t) 0; 42488768458SSam Leffler splx(s); 42588768458SSam Leffler return error; 42688768458SSam Leffler } 42788768458SSam Leffler 42888768458SSam Leffler kp->kp_promisc = kp->kp_registered = 0; 42988768458SSam Leffler 43088768458SSam Leffler if (kp->kp_raw.rcb_proto.sp_protocol == PF_KEY) /* XXX: AF_KEY */ 43188768458SSam Leffler key_cb.key_count++; 43288768458SSam Leffler key_cb.any_count++; 43388768458SSam Leffler kp->kp_raw.rcb_laddr = &key_src; 43488768458SSam Leffler kp->kp_raw.rcb_faddr = &key_dst; 43588768458SSam Leffler soisconnected(so); 43688768458SSam Leffler so->so_options |= SO_USELOOPBACK; 43788768458SSam Leffler 43888768458SSam Leffler splx(s); 43988768458SSam Leffler return 0; 44088768458SSam Leffler } 44188768458SSam Leffler 44288768458SSam Leffler /* 44388768458SSam Leffler * key_bind() 44488768458SSam Leffler * derived from net/rtsock.c:rts_bind() 44588768458SSam Leffler */ 44688768458SSam Leffler static int 44788768458SSam Leffler key_bind(struct socket *so, struct sockaddr *nam, struct thread *td) 44888768458SSam Leffler { 44988768458SSam Leffler int s, error; 45088768458SSam Leffler s = splnet(); 45188768458SSam Leffler error = raw_usrreqs.pru_bind(so, nam, td); /* xxx just EINVAL */ 45288768458SSam Leffler splx(s); 45388768458SSam Leffler return error; 45488768458SSam Leffler } 45588768458SSam Leffler 45688768458SSam Leffler /* 45788768458SSam Leffler * key_connect() 45888768458SSam Leffler * derived from net/rtsock.c:rts_connect() 45988768458SSam Leffler */ 46088768458SSam Leffler static int 46188768458SSam Leffler key_connect(struct socket *so, struct sockaddr *nam, struct thread *td) 46288768458SSam Leffler { 46388768458SSam Leffler int s, error; 46488768458SSam Leffler s = splnet(); 46588768458SSam Leffler error = raw_usrreqs.pru_connect(so, nam, td); /* XXX just EINVAL */ 46688768458SSam Leffler splx(s); 46788768458SSam Leffler return error; 46888768458SSam Leffler } 46988768458SSam Leffler 47088768458SSam Leffler /* 47188768458SSam Leffler * key_detach() 47288768458SSam Leffler * derived from net/rtsock.c:rts_detach() 47388768458SSam Leffler */ 47488768458SSam Leffler static int 47588768458SSam Leffler key_detach(struct socket *so) 47688768458SSam Leffler { 47788768458SSam Leffler struct keycb *kp = (struct keycb *)sotorawcb(so); 47888768458SSam Leffler int s, error; 47988768458SSam Leffler 48088768458SSam Leffler s = splnet(); 48188768458SSam Leffler if (kp != 0) { 48288768458SSam Leffler if (kp->kp_raw.rcb_proto.sp_protocol 48388768458SSam Leffler == PF_KEY) /* XXX: AF_KEY */ 48488768458SSam Leffler key_cb.key_count--; 48588768458SSam Leffler key_cb.any_count--; 48688768458SSam Leffler 48788768458SSam Leffler key_freereg(so); 48888768458SSam Leffler } 48988768458SSam Leffler error = raw_usrreqs.pru_detach(so); 49088768458SSam Leffler splx(s); 49188768458SSam Leffler return error; 49288768458SSam Leffler } 49388768458SSam Leffler 49488768458SSam Leffler /* 49588768458SSam Leffler * key_disconnect() 49688768458SSam Leffler * derived from net/rtsock.c:key_disconnect() 49788768458SSam Leffler */ 49888768458SSam Leffler static int 49988768458SSam Leffler key_disconnect(struct socket *so) 50088768458SSam Leffler { 50188768458SSam Leffler int s, error; 50288768458SSam Leffler s = splnet(); 50388768458SSam Leffler error = raw_usrreqs.pru_disconnect(so); 50488768458SSam Leffler splx(s); 50588768458SSam Leffler return error; 50688768458SSam Leffler } 50788768458SSam Leffler 50888768458SSam Leffler /* 50988768458SSam Leffler * key_peeraddr() 51088768458SSam Leffler * derived from net/rtsock.c:rts_peeraddr() 51188768458SSam Leffler */ 51288768458SSam Leffler static int 51388768458SSam Leffler key_peeraddr(struct socket *so, struct sockaddr **nam) 51488768458SSam Leffler { 51588768458SSam Leffler int s, error; 51688768458SSam Leffler s = splnet(); 51788768458SSam Leffler error = raw_usrreqs.pru_peeraddr(so, nam); 51888768458SSam Leffler splx(s); 51988768458SSam Leffler return error; 52088768458SSam Leffler } 52188768458SSam Leffler 52288768458SSam Leffler /* 52388768458SSam Leffler * key_send() 52488768458SSam Leffler * derived from net/rtsock.c:rts_send() 52588768458SSam Leffler */ 52688768458SSam Leffler static int 52788768458SSam Leffler key_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *nam, 52888768458SSam Leffler struct mbuf *control, struct thread *td) 52988768458SSam Leffler { 53088768458SSam Leffler int s, error; 53188768458SSam Leffler s = splnet(); 53288768458SSam Leffler error = raw_usrreqs.pru_send(so, flags, m, nam, control, td); 53388768458SSam Leffler splx(s); 53488768458SSam Leffler return error; 53588768458SSam Leffler } 53688768458SSam Leffler 53788768458SSam Leffler /* 53888768458SSam Leffler * key_shutdown() 53988768458SSam Leffler * derived from net/rtsock.c:rts_shutdown() 54088768458SSam Leffler */ 54188768458SSam Leffler static int 54288768458SSam Leffler key_shutdown(struct socket *so) 54388768458SSam Leffler { 54488768458SSam Leffler int s, error; 54588768458SSam Leffler s = splnet(); 54688768458SSam Leffler error = raw_usrreqs.pru_shutdown(so); 54788768458SSam Leffler splx(s); 54888768458SSam Leffler return error; 54988768458SSam Leffler } 55088768458SSam Leffler 55188768458SSam Leffler /* 55288768458SSam Leffler * key_sockaddr() 55388768458SSam Leffler * derived from net/rtsock.c:rts_sockaddr() 55488768458SSam Leffler */ 55588768458SSam Leffler static int 55688768458SSam Leffler key_sockaddr(struct socket *so, struct sockaddr **nam) 55788768458SSam Leffler { 55888768458SSam Leffler int s, error; 55988768458SSam Leffler s = splnet(); 56088768458SSam Leffler error = raw_usrreqs.pru_sockaddr(so, nam); 56188768458SSam Leffler splx(s); 56288768458SSam Leffler return error; 56388768458SSam Leffler } 56488768458SSam Leffler 56588768458SSam Leffler struct pr_usrreqs key_usrreqs = { 56688768458SSam Leffler key_abort, pru_accept_notsupp, key_attach, key_bind, 56788768458SSam Leffler key_connect, 56888768458SSam Leffler pru_connect2_notsupp, pru_control_notsupp, key_detach, 56988768458SSam Leffler key_disconnect, pru_listen_notsupp, key_peeraddr, 57088768458SSam Leffler pru_rcvd_notsupp, 57188768458SSam Leffler pru_rcvoob_notsupp, key_send, pru_sense_null, key_shutdown, 572a557af22SRobert Watson key_sockaddr, sosend, soreceive, sopoll, 573a557af22SRobert Watson pru_sosetlabel_null 57488768458SSam Leffler }; 57588768458SSam Leffler 57688768458SSam Leffler /* sysctl */ 57788768458SSam Leffler SYSCTL_NODE(_net, PF_KEY, key, CTLFLAG_RW, 0, "Key Family"); 57888768458SSam Leffler 57988768458SSam Leffler /* 58088768458SSam Leffler * Definitions of protocols supported in the KEY domain. 58188768458SSam Leffler */ 58288768458SSam Leffler 58388768458SSam Leffler extern struct domain keydomain; 58488768458SSam Leffler 58588768458SSam Leffler struct protosw keysw[] = { 58688768458SSam Leffler { SOCK_RAW, &keydomain, PF_KEY_V2, PR_ATOMIC|PR_ADDR, 58788768458SSam Leffler 0, (pr_output_t *)key_output, raw_ctlinput, 0, 58888768458SSam Leffler 0, 58988768458SSam Leffler raw_init, 0, 0, 0, 59088768458SSam Leffler &key_usrreqs 59188768458SSam Leffler } 59288768458SSam Leffler }; 59388768458SSam Leffler 59488768458SSam Leffler static void 59588768458SSam Leffler key_init0(void) 59688768458SSam Leffler { 59788768458SSam Leffler bzero((caddr_t)&key_cb, sizeof(key_cb)); 59888768458SSam Leffler key_init(); 59988768458SSam Leffler } 60088768458SSam Leffler 60188768458SSam Leffler struct domain keydomain = 60288768458SSam Leffler { PF_KEY, "key", key_init0, 0, 0, 60388768458SSam Leffler keysw, &keysw[sizeof(keysw)/sizeof(keysw[0])] }; 60488768458SSam Leffler 60588768458SSam Leffler DOMAIN_SET(key); 606