The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/netipsec/keysock.c

Version: -  FREEBSD  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-2  -  FREEBSD-11-1  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-4  -  FREEBSD-10-3  -  FREEBSD-10-2  -  FREEBSD-10-1  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-3  -  FREEBSD-9-2  -  FREEBSD-9-1  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-4  -  FREEBSD-8-3  -  FREEBSD-8-2  -  FREEBSD-8-1  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-4  -  FREEBSD-7-3  -  FREEBSD-7-2  -  FREEBSD-7-1  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-4  -  FREEBSD-6-3  -  FREEBSD-6-2  -  FREEBSD-6-1  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-5  -  FREEBSD-5-4  -  FREEBSD-5-3  -  FREEBSD-5-2  -  FREEBSD-5-1  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  linux-2.6  -  linux-2.4.22  -  MK83  -  MK84  -  PLAN9  -  DFBSD  -  NETBSD  -  NETBSD5  -  NETBSD4  -  NETBSD3  -  NETBSD20  -  OPENBSD  -  xnu-517  -  xnu-792  -  xnu-792.6.70  -  xnu-1228  -  xnu-1456.1.26  -  xnu-1699.24.8  -  xnu-2050.18.24  -  OPENSOLARIS  -  minix-3-1-1 
SearchContext: -  none  -  3  -  10 

    1 /*      $NetBSD: keysock.c,v 1.7 2005/02/26 22:45:13 perry Exp $        */
    2 /*      $FreeBSD: src/sys/netipsec/keysock.c,v 1.3.2.1 2003/01/24 05:11:36 sam Exp $    */
    3 /*      $KAME: keysock.c,v 1.25 2001/08/13 20:07:41 itojun Exp $        */
    4 
    5 /*
    6  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
    7  * All rights reserved.
    8  *
    9  * Redistribution and use in source and binary forms, with or without
   10  * modification, are permitted provided that the following conditions
   11  * are met:
   12  * 1. Redistributions of source code must retain the above copyright
   13  *    notice, this list of conditions and the following disclaimer.
   14  * 2. Redistributions in binary form must reproduce the above copyright
   15  *    notice, this list of conditions and the following disclaimer in the
   16  *    documentation and/or other materials provided with the distribution.
   17  * 3. Neither the name of the project nor the names of its contributors
   18  *    may be used to endorse or promote products derived from this software
   19  *    without specific prior written permission.
   20  *
   21  * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
   22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
   25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   31  * SUCH DAMAGE.
   32  */
   33 
   34 #include <sys/cdefs.h>
   35 __KERNEL_RCSID(0, "$NetBSD: keysock.c,v 1.7 2005/02/26 22:45:13 perry Exp $");
   36 
   37 #include "opt_ipsec.h"
   38 
   39 /* This code has derived from sys/net/rtsock.c on FreeBSD2.2.5 */
   40 
   41 #include <sys/types.h>
   42 #include <sys/param.h>
   43 #include <sys/domain.h>
   44 #include <sys/errno.h>
   45 #include <sys/kernel.h>
   46 #include <sys/malloc.h>
   47 #include <sys/mbuf.h>
   48 #include <sys/protosw.h>
   49 #include <sys/signalvar.h>
   50 #include <sys/socket.h>
   51 #include <sys/socketvar.h>
   52 #include <sys/sysctl.h>
   53 #include <sys/systm.h>
   54 
   55 #include <net/raw_cb.h>
   56 #include <net/route.h>
   57 
   58 #include <net/pfkeyv2.h>
   59 #include <netipsec/key.h>
   60 #include <netipsec/keysock.h>
   61 #include <netipsec/key_debug.h>
   62 
   63 #include <netipsec/ipsec_osdep.h>
   64 
   65 #include <machine/stdarg.h>
   66 
   67 typedef int     pr_output_t (struct mbuf *, struct socket *);
   68 
   69 struct key_cb {
   70         int key_count;
   71         int any_count;
   72 };
   73 static struct key_cb key_cb;
   74 
   75 static struct sockaddr key_dst = { 2, PF_KEY, };
   76 static struct sockaddr key_src = { 2, PF_KEY, };
   77 
   78 
   79 static int key_sendup0 __P((struct rawcb *, struct mbuf *, int, int));
   80 
   81 struct pfkeystat pfkeystat;
   82 
   83 int key_registered_sb_max = (NMBCLUSTERS * MHLEN); /* XXX arbitrary */
   84 
   85 /* XXX sysctl */
   86 #ifdef __FreeBSD__
   87 SYSCTL_INT(_net_key, OID_AUTO, registered_sbmax, CTLFLAG_RD,
   88     &key_registered_sb_max , 0, "Maximum kernel-to-user PFKEY datagram size");
   89 #endif
   90 
   91 /*
   92  * key_output()
   93  */
   94 int
   95 key_output(struct mbuf *m, ...)
   96 {
   97         struct sadb_msg *msg;
   98         int len, error = 0;
   99         int s;
  100         struct socket *so;
  101         va_list ap;
  102 
  103         va_start(ap, m);
  104         so = va_arg(ap, struct socket *);
  105         va_end(ap);
  106 
  107         if (m == 0)
  108                 panic("key_output: NULL pointer was passed.\n");
  109 
  110         pfkeystat.out_total++;
  111         pfkeystat.out_bytes += m->m_pkthdr.len;
  112 
  113         len = m->m_pkthdr.len;
  114         if (len < sizeof(struct sadb_msg)) {
  115                 pfkeystat.out_tooshort++;
  116                 error = EINVAL;
  117                 goto end;
  118         }
  119 
  120         if (m->m_len < sizeof(struct sadb_msg)) {
  121                 if ((m = m_pullup(m, sizeof(struct sadb_msg))) == 0) {
  122                         pfkeystat.out_nomem++;
  123                         error = ENOBUFS;
  124                         goto end;
  125                 }
  126         }
  127 
  128         if ((m->m_flags & M_PKTHDR) == 0)
  129                 panic("key_output: not M_PKTHDR ??");
  130 
  131         KEYDEBUG(KEYDEBUG_KEY_DUMP, kdebug_mbuf(m));
  132 
  133         msg = mtod(m, struct sadb_msg *);
  134         pfkeystat.out_msgtype[msg->sadb_msg_type]++;
  135         if (len != PFKEY_UNUNIT64(msg->sadb_msg_len)) {
  136                 pfkeystat.out_invlen++;
  137                 error = EINVAL;
  138                 goto end;
  139         }
  140 
  141         /*XXX giant lock*/
  142         s = splsoftnet();
  143         error = key_parse(m, so);
  144         m = NULL;
  145         splx(s);
  146 end:
  147         if (m)
  148                 m_freem(m);
  149         return error;
  150 }
  151 
  152 /*
  153  * send message to the socket.
  154  */
  155 static int
  156 key_sendup0(rp, m, promisc, sbprio)
  157         struct rawcb *rp;
  158         struct mbuf *m;
  159         int promisc;
  160 {
  161         int error;
  162         int ok;
  163 
  164         if (promisc) {
  165                 struct sadb_msg *pmsg;
  166 
  167                 M_PREPEND(m, sizeof(struct sadb_msg), M_DONTWAIT);
  168                 if (m && m->m_len < sizeof(struct sadb_msg))
  169                         m = m_pullup(m, sizeof(struct sadb_msg));
  170                 if (!m) {
  171                         pfkeystat.in_nomem++;
  172                         m_freem(m);
  173                         return ENOBUFS;
  174                 }
  175                 m->m_pkthdr.len += sizeof(*pmsg);
  176 
  177                 pmsg = mtod(m, struct sadb_msg *);
  178                 bzero(pmsg, sizeof(*pmsg));
  179                 pmsg->sadb_msg_version = PF_KEY_V2;
  180                 pmsg->sadb_msg_type = SADB_X_PROMISC;
  181                 pmsg->sadb_msg_len = PFKEY_UNIT64(m->m_pkthdr.len);
  182                 /* pid and seq? */
  183 
  184                 pfkeystat.in_msgtype[pmsg->sadb_msg_type]++;
  185         }
  186 
  187         if (sbprio == 0)
  188                 ok = sbappendaddr(&rp->rcb_socket->so_rcv,
  189                                (struct sockaddr *)&key_src, m, NULL);
  190         else
  191                 ok = sbappendaddrchain(&rp->rcb_socket->so_rcv,
  192                                (struct sockaddr *)&key_src, m, sbprio);
  193 
  194           if (!ok) {
  195                 pfkeystat.in_nomem++;
  196                 m_freem(m);
  197                 error = ENOBUFS;
  198         } else
  199                 error = 0;
  200         sorwakeup(rp->rcb_socket);
  201         return error;
  202 }
  203 
  204 /* XXX this interface should be obsoleted. */
  205 int
  206 key_sendup(so, msg, len, target)
  207         struct socket *so;
  208         struct sadb_msg *msg;
  209         u_int len;
  210         int target;     /*target of the resulting message*/
  211 {
  212         struct mbuf *m, *n, *mprev;
  213         int tlen;
  214 
  215         /* sanity check */
  216         if (so == 0 || msg == 0)
  217                 panic("key_sendup: NULL pointer was passed.\n");
  218 
  219         KEYDEBUG(KEYDEBUG_KEY_DUMP,
  220                 printf("key_sendup: \n");
  221                 kdebug_sadb(msg));
  222 
  223         /*
  224          * we increment statistics here, just in case we have ENOBUFS
  225          * in this function.
  226          */
  227         pfkeystat.in_total++;
  228         pfkeystat.in_bytes += len;
  229         pfkeystat.in_msgtype[msg->sadb_msg_type]++;
  230 
  231         /*
  232          * Get mbuf chain whenever possible (not clusters),
  233          * to save socket buffer.  We'll be generating many SADB_ACQUIRE
  234          * messages to listening key sockets.  If we simply allocate clusters,
  235          * sbappendaddr() will raise ENOBUFS due to too little sbspace().
  236          * sbspace() computes # of actual data bytes AND mbuf region.
  237          *
  238          * TODO: SADB_ACQUIRE filters should be implemented.
  239          */
  240         tlen = len;
  241         m = mprev = NULL;
  242         while (tlen > 0) {
  243                 if (tlen == len) {
  244                         MGETHDR(n, M_DONTWAIT, MT_DATA);
  245                         n->m_len = MHLEN;
  246                 } else {
  247                         MGET(n, M_DONTWAIT, MT_DATA);
  248                         n->m_len = MLEN;
  249                 }
  250                 if (!n) {
  251                         pfkeystat.in_nomem++;
  252                         return ENOBUFS;
  253                 }
  254                 if (tlen >= MCLBYTES) { /*XXX better threshold? */
  255                         MCLGET(n, M_DONTWAIT);
  256                         if ((n->m_flags & M_EXT) == 0) {
  257                                 m_free(n);
  258                                 m_freem(m);
  259                                 pfkeystat.in_nomem++;
  260                                 return ENOBUFS;
  261                         }
  262                         n->m_len = MCLBYTES;
  263                 }
  264 
  265                 if (tlen < n->m_len)
  266                         n->m_len = tlen;
  267                 n->m_next = NULL;
  268                 if (m == NULL)
  269                         m = mprev = n;
  270                 else {
  271                         mprev->m_next = n;
  272                         mprev = n;
  273                 }
  274                 tlen -= n->m_len;
  275                 n = NULL;
  276         }
  277         m->m_pkthdr.len = len;
  278         m->m_pkthdr.rcvif = NULL;
  279         m_copyback(m, 0, len, (caddr_t)msg);
  280 
  281         /* avoid duplicated statistics */
  282         pfkeystat.in_total--;
  283         pfkeystat.in_bytes -= len;
  284         pfkeystat.in_msgtype[msg->sadb_msg_type]--;
  285 
  286         return key_sendup_mbuf(so, m, target);
  287 }
  288 
  289 /* so can be NULL if target != KEY_SENDUP_ONE */
  290 int
  291 key_sendup_mbuf(so, m, target /*, sbprio */)
  292         struct socket *so;
  293         struct mbuf *m;
  294         int target;
  295 {
  296         struct mbuf *n;
  297         struct keycb *kp;
  298         int sendup;
  299         struct rawcb *rp;
  300         int error = 0;
  301         int sbprio = 0; /* XXX should be a parameter */
  302 
  303         if (m == NULL)
  304                 panic("key_sendup_mbuf: NULL pointer was passed.\n");
  305         if (so == NULL && target == KEY_SENDUP_ONE)
  306                 panic("key_sendup_mbuf: NULL pointer was passed.\n");
  307 
  308         /*
  309          * RFC 2367 says ACQUIRE and other kernel-generated messages
  310          * are special. We treat all KEY_SENDUP_REGISTERED messages
  311          * as special, delivering them to all registered sockets
  312          * even if the socket is at or above its so->so_rcv.sb_max limits.
  313          * The only constraint is that the  so_rcv data fall below
  314          * key_registered_sb_max.
  315          * Doing that check here avoids reworking every key_sendup_mbuf()
  316          * in the short term. . The rework will be done after a technical
  317          * conensus that this approach is appropriate.
  318          */
  319         if (target == KEY_SENDUP_REGISTERED) {
  320                 sbprio = SB_PRIO_BESTEFFORT;
  321         }
  322 
  323         pfkeystat.in_total++;
  324         pfkeystat.in_bytes += m->m_pkthdr.len;
  325         if (m->m_len < sizeof(struct sadb_msg)) {
  326 #if 1
  327                 m = m_pullup(m, sizeof(struct sadb_msg));
  328                 if (m == NULL) {
  329                         pfkeystat.in_nomem++;
  330                         return ENOBUFS;
  331                 }
  332 #else
  333                 /* don't bother pulling it up just for stats */
  334 #endif
  335         }
  336         if (m->m_len >= sizeof(struct sadb_msg)) {
  337                 struct sadb_msg *msg;
  338                 msg = mtod(m, struct sadb_msg *);
  339                 pfkeystat.in_msgtype[msg->sadb_msg_type]++;
  340         }
  341 
  342         LIST_FOREACH(rp, &rawcb_list, rcb_list)
  343         {
  344                 struct socket * kso = rp->rcb_socket;
  345                 if (rp->rcb_proto.sp_family != PF_KEY)
  346                         continue;
  347                 if (rp->rcb_proto.sp_protocol
  348                  && rp->rcb_proto.sp_protocol != PF_KEY_V2) {
  349                         continue;
  350                 }
  351 
  352                 kp = (struct keycb *)rp;
  353 
  354                 /*
  355                  * If you are in promiscuous mode, and when you get broadcasted
  356                  * reply, you'll get two PF_KEY messages.
  357                  * (based on pf_key@inner.net message on 14 Oct 1998)
  358                  */
  359                 if (((struct keycb *)rp)->kp_promisc) {
  360                         if ((n = m_copy(m, 0, (int)M_COPYALL)) != NULL) {
  361                                 (void)key_sendup0(rp, n, 1, 0);
  362                                 n = NULL;
  363                         }
  364                 }
  365 
  366                 /* the exact target will be processed later */
  367                 if (so && sotorawcb(so) == rp)
  368                         continue;
  369 
  370                 sendup = 0;
  371                 switch (target) {
  372                 case KEY_SENDUP_ONE:
  373                         /* the statement has no effect */
  374                         if (so && sotorawcb(so) == rp)
  375                                 sendup++;
  376                         break;
  377                 case KEY_SENDUP_ALL:
  378                         sendup++;
  379                         break;
  380                 case KEY_SENDUP_REGISTERED:
  381                         if (kp->kp_registered) {
  382                                 if (kso->so_rcv.sb_cc <= key_registered_sb_max)
  383                                         sendup++;
  384                                 else
  385                                         printf("keysock: "
  386                                                "registered sendup dropped, "
  387                                                "sb_cc %ld max %d\n",
  388                                                kso->so_rcv.sb_cc,
  389                                                key_registered_sb_max);
  390                         }
  391                         break;
  392                 }
  393                 pfkeystat.in_msgtarget[target]++;
  394 
  395                 if (!sendup)
  396                         continue;
  397 
  398                 if ((n = m_copy(m, 0, (int)M_COPYALL)) == NULL) {
  399                         m_freem(m);
  400                         pfkeystat.in_nomem++;
  401                         return ENOBUFS;
  402                 }
  403 
  404                 if ((error = key_sendup0(rp, n, 0, 0)) != 0) {
  405                         m_freem(m);
  406                         return error;
  407                 }
  408 
  409                 n = NULL;
  410         }
  411 
  412         /* The 'later' time for processing the exact target has arrived */
  413         if (so) {
  414                 error = key_sendup0(sotorawcb(so), m, 0, sbprio);
  415                 m = NULL;
  416         } else {
  417                 error = 0;
  418                 m_freem(m);
  419         }
  420         return error;
  421 }
  422 
  423 #ifdef __FreeBSD__
  424 
  425 /*
  426  * key_abort()
  427  * derived from net/rtsock.c:rts_abort()
  428  */
  429 static int
  430 key_abort(struct socket *so)
  431 {
  432         int s, error;
  433         s = splnet();   /* FreeBSD */
  434         error = raw_usrreqs.pru_abort(so);
  435         splx(s);
  436         return error;
  437 }
  438 
  439 /*
  440  * key_attach()
  441  * derived from net/rtsock.c:rts_attach()
  442  */
  443 static int
  444 key_attach(struct socket *so, int proto, struct proc *td)
  445 {
  446         struct keycb *kp;
  447         int s, error;
  448 
  449         if (sotorawcb(so) != 0)
  450                 return EISCONN; /* XXX panic? */
  451         kp = (struct keycb *)malloc(sizeof *kp, M_PCB, M_WAITOK|M_ZERO); /* XXX */
  452         if (kp == 0)
  453                 return ENOBUFS;
  454 
  455         /*
  456          * The spl[soft]net() is necessary to block protocols from sending
  457          * error notifications (like RTM_REDIRECT or RTM_LOSING) while
  458          * this PCB is extant but incompletely initialized.
  459          * Probably we should try to do more of this work beforehand and
  460          * eliminate the spl.
  461          */
  462         s = splnet();   /* FreeBSD */
  463         so->so_pcb = (caddr_t)kp;
  464         error = raw_usrreqs.pru_attach(so, proto, td);
  465         kp = (struct keycb *)sotorawcb(so);
  466         if (error) {
  467                 free(kp, M_PCB);
  468                 so->so_pcb = (caddr_t) 0;
  469                 splx(s);
  470                 return error;
  471         }
  472 
  473         kp->kp_promisc = kp->kp_registered = 0;
  474 
  475         if (kp->kp_raw.rcb_proto.sp_protocol == PF_KEY) /* XXX: AF_KEY */
  476                 key_cb.key_count++;
  477         key_cb.any_count++;
  478         kp->kp_raw.rcb_laddr = &key_src;
  479         kp->kp_raw.rcb_faddr = &key_dst;
  480         soisconnected(so);
  481         so->so_options |= SO_USELOOPBACK;
  482 
  483         splx(s);
  484         return 0;
  485 }
  486 
  487 /*
  488  * key_bind()
  489  * derived from net/rtsock.c:rts_bind()
  490  */
  491 static int
  492 key_bind(struct socket *so, struct sockaddr *nam, struct proc *td)
  493 {
  494         int s, error;
  495         s = splnet();   /* FreeBSD */
  496         error = raw_usrreqs.pru_bind(so, nam, td); /* xxx just EINVAL */
  497         splx(s);
  498         return error;
  499 }
  500 
  501 /*
  502  * key_connect()
  503  * derived from net/rtsock.c:rts_connect()
  504  */
  505 static int
  506 key_connect(struct socket *so, struct sockaddr *nam, struct proc *td)
  507 {
  508         int s, error;
  509         s = splnet();   /* FreeBSD */
  510         error = raw_usrreqs.pru_connect(so, nam, td); /* XXX just EINVAL */
  511         splx(s);
  512         return error;
  513 }
  514 
  515 /*
  516  * key_detach()
  517  * derived from net/rtsock.c:rts_detach()
  518  */
  519 static int
  520 key_detach(struct socket *so)
  521 {
  522         struct keycb *kp = (struct keycb *)sotorawcb(so);
  523         int s, error;
  524 
  525         s = splnet();   /* FreeBSD */
  526         if (kp != 0) {
  527                 if (kp->kp_raw.rcb_proto.sp_protocol
  528                     == PF_KEY) /* XXX: AF_KEY */
  529                         key_cb.key_count--;
  530                 key_cb.any_count--;
  531 
  532                 key_freereg(so);
  533         }
  534         error = raw_usrreqs.pru_detach(so);
  535         splx(s);
  536         return error;
  537 }
  538 
  539 /*
  540  * key_disconnect()
  541  * derived from net/rtsock.c:key_disconnect()
  542  */
  543 static int
  544 key_disconnect(struct socket *so)
  545 {
  546         int s, error;
  547         s = splnet();   /* FreeBSD */
  548         error = raw_usrreqs.pru_disconnect(so);
  549         splx(s);
  550         return error;
  551 }
  552 
  553 /*
  554  * key_peeraddr()
  555  * derived from net/rtsock.c:rts_peeraddr()
  556  */
  557 static int
  558 key_peeraddr(struct socket *so, struct sockaddr **nam)
  559 {
  560         int s, error;
  561         s = splnet();   /* FreeBSD */
  562         error = raw_usrreqs.pru_peeraddr(so, nam);
  563         splx(s);
  564         return error;
  565 }
  566 
  567 /*
  568  * key_send()
  569  * derived from net/rtsock.c:rts_send()
  570  */
  571 static int
  572 key_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *nam,
  573          struct mbuf *control, struct proc *td)
  574 {
  575         int s, error;
  576         s = splnet();   /* FreeBSD */
  577         error = raw_usrreqs.pru_send(so, flags, m, nam, control, td);
  578         splx(s);
  579         return error;
  580 }
  581 
  582 /*
  583  * key_shutdown()
  584  * derived from net/rtsock.c:rts_shutdown()
  585  */
  586 static int
  587 key_shutdown(struct socket *so)
  588 {
  589         int s, error;
  590         s = splnet();   /* FreeBSD */
  591         error = raw_usrreqs.pru_shutdown(so);
  592         splx(s);
  593         return error;
  594 }
  595 
  596 /*
  597  * key_sockaddr()
  598  * derived from net/rtsock.c:rts_sockaddr()
  599  */
  600 static int
  601 key_sockaddr(struct socket *so, struct sockaddr **nam)
  602 {
  603         int s, error;
  604         s = splnet();   /* FreeBSD */
  605         error = raw_usrreqs.pru_sockaddr(so, nam);
  606         splx(s);
  607         return error;
  608 }
  609 #else /*!__FreeBSD__ -- traditional proto_usrreq() switch */
  610 
  611 /*
  612  * key_usrreq()
  613  * derived from net/rtsock.c:route_usrreq()
  614  */
  615 int
  616 key_usrreq(so, req, m, nam, control, p)
  617         struct socket *so;
  618         int req;
  619         struct mbuf *m, *nam, *control;
  620         struct proc *p;
  621 {
  622         int error = 0;
  623         struct keycb *kp = (struct keycb *)sotorawcb(so);
  624         int s;
  625 
  626         s = splsoftnet();
  627         if (req == PRU_ATTACH) {
  628                 kp = (struct keycb *)malloc(sizeof(*kp), M_PCB, M_WAITOK);
  629                 so->so_pcb = (caddr_t)kp;
  630                 if (so->so_pcb)
  631                         bzero(so->so_pcb, sizeof(*kp));
  632         }
  633         if (req == PRU_DETACH && kp) {
  634                 int af = kp->kp_raw.rcb_proto.sp_protocol;
  635                 if (af == PF_KEY) /* XXX: AF_KEY */
  636                         key_cb.key_count--;
  637                 key_cb.any_count--;
  638 
  639                 key_freereg(so);
  640         }
  641 
  642         error = raw_usrreq(so, req, m, nam, control, p);
  643         m = control = NULL;     /* reclaimed in raw_usrreq */
  644         kp = (struct keycb *)sotorawcb(so);
  645         if (req == PRU_ATTACH && kp) {
  646                 int af = kp->kp_raw.rcb_proto.sp_protocol;
  647                 if (error) {
  648                         pfkeystat.sockerr++;
  649                         free((caddr_t)kp, M_PCB);
  650                         so->so_pcb = (caddr_t) 0;
  651                         splx(s);
  652                         return (error);
  653                 }
  654 
  655                 kp->kp_promisc = kp->kp_registered = 0;
  656 
  657                 if (af == PF_KEY) /* XXX: AF_KEY */
  658                         key_cb.key_count++;
  659                 key_cb.any_count++;
  660                 kp->kp_raw.rcb_laddr = &key_src;
  661                 kp->kp_raw.rcb_faddr = &key_dst;
  662                 soisconnected(so);
  663                 so->so_options |= SO_USELOOPBACK;
  664         }
  665         splx(s);
  666         return (error);
  667 }
  668 #endif /*!__FreeBSD__*/
  669 
  670 /* sysctl */
  671 #ifdef SYSCTL_NODE
  672 SYSCTL_NODE(_net, PF_KEY, key, CTLFLAG_RW, 0, "Key Family");
  673 #endif /* SYSCTL_NODE */
  674 
  675 /*
  676  * Definitions of protocols supported in the KEY domain.
  677  */
  678 
  679 #ifdef __FreeBSD__
  680 extern struct domain keydomain;
  681 
  682 struct pr_usrreqs key_usrreqs = {
  683         key_abort, pru_accept_notsupp, key_attach, key_bind,
  684         key_connect,
  685         pru_connect2_notsupp, pru_control_notsupp, key_detach,
  686         key_disconnect, pru_listen_notsupp, key_peeraddr,
  687         pru_rcvd_notsupp,
  688         pru_rcvoob_notsupp, key_send, pru_sense_null, key_shutdown,
  689         key_sockaddr, sosend, soreceive, sopoll
  690 };
  691 
  692 struct protosw keysw[] = {
  693 { SOCK_RAW,     &keydomain,     PF_KEY_V2,      PR_ATOMIC|PR_ADDR,
  694   0,            (pr_output_t *)key_output,      raw_ctlinput, 0,
  695   0,
  696   raw_init,     0,              0,              0,
  697   &key_usrreqs
  698 }
  699 };
  700 
  701 static void
  702 key_init0(void)
  703 {
  704         bzero((caddr_t)&key_cb, sizeof(key_cb));
  705         key_init();
  706 }
  707 
  708 struct domain keydomain =
  709     { PF_KEY, "key", key_init0, 0, 0,
  710       keysw, &keysw[sizeof(keysw)/sizeof(keysw[0])] };
  711 
  712 DOMAIN_SET(key);
  713 
  714 #else /* !__FreeBSD__ */
  715 
  716 DOMAIN_DEFINE(keydomain);
  717 
  718 struct protosw keysw[] = {
  719 { SOCK_RAW,     &keydomain,     PF_KEY_V2,      PR_ATOMIC|PR_ADDR,
  720   0,            key_output,     raw_ctlinput,   0,
  721   key_usrreq,
  722   raw_init,     0,              0,              0,
  723   NULL,
  724 }
  725 };
  726 
  727 struct domain keydomain =
  728     { PF_KEY, "key", key_init, 0, 0,
  729       keysw, &keysw[sizeof(keysw)/sizeof(keysw[0])] };
  730 
  731 #endif

Cache object: 1b56134483ab51aea170ff47acb342c8


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.