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-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*      $NetBSD: keysock.c,v 1.16 2008/04/24 11:38:38 ad 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.16 2008/04/24 11:38:38 ad 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 #include <netipsec/ipsec_private.h>
   65 
   66 #include <machine/stdarg.h>
   67 
   68 typedef int     pr_output_t (struct mbuf *, struct socket *);
   69 
   70 struct key_cb {
   71         int key_count;
   72         int any_count;
   73 };
   74 static struct key_cb key_cb;
   75 
   76 static struct sockaddr key_dst = {
   77     .sa_len = 2,
   78     .sa_family = PF_KEY,
   79 };
   80 static struct sockaddr key_src = {
   81     .sa_len = 2,
   82     .sa_family = PF_KEY,
   83 };
   84 
   85 
   86 static int key_sendup0 __P((struct rawcb *, struct mbuf *, int, int));
   87 
   88 int key_registered_sb_max = (NMBCLUSTERS * MHLEN); /* XXX arbitrary */
   89 
   90 /* XXX sysctl */
   91 #ifdef __FreeBSD__
   92 SYSCTL_INT(_net_key, OID_AUTO, registered_sbmax, CTLFLAG_RD,
   93     &key_registered_sb_max , 0, "Maximum kernel-to-user PFKEY datagram size");
   94 #endif
   95 
   96 /*
   97  * key_output()
   98  */
   99 int
  100 key_output(struct mbuf *m, ...)
  101 {
  102         struct sadb_msg *msg;
  103         int len, error = 0;
  104         int s;
  105         struct socket *so;
  106         va_list ap;
  107 
  108         va_start(ap, m);
  109         so = va_arg(ap, struct socket *);
  110         va_end(ap);
  111 
  112         if (m == 0)
  113                 panic("key_output: NULL pointer was passed");
  114 
  115         {
  116                 uint64_t *ps = PFKEY_STAT_GETREF();
  117                 ps[PFKEY_STAT_OUT_TOTAL]++;
  118                 ps[PFKEY_STAT_OUT_BYTES] += m->m_pkthdr.len;
  119                 PFKEY_STAT_PUTREF();
  120         }
  121 
  122         len = m->m_pkthdr.len;
  123         if (len < sizeof(struct sadb_msg)) {
  124                 PFKEY_STATINC(PFKEY_STAT_OUT_TOOSHORT);
  125                 error = EINVAL;
  126                 goto end;
  127         }
  128 
  129         if (m->m_len < sizeof(struct sadb_msg)) {
  130                 if ((m = m_pullup(m, sizeof(struct sadb_msg))) == 0) {
  131                         PFKEY_STATINC(PFKEY_STAT_OUT_NOMEM);
  132                         error = ENOBUFS;
  133                         goto end;
  134                 }
  135         }
  136 
  137         if ((m->m_flags & M_PKTHDR) == 0)
  138                 panic("key_output: not M_PKTHDR ??");
  139 
  140         KEYDEBUG(KEYDEBUG_KEY_DUMP, kdebug_mbuf(m));
  141 
  142         msg = mtod(m, struct sadb_msg *);
  143         PFKEY_STATINC(PFKEY_STAT_OUT_MSGTYPE + msg->sadb_msg_type);
  144         if (len != PFKEY_UNUNIT64(msg->sadb_msg_len)) {
  145                 PFKEY_STATINC(PFKEY_STAT_OUT_INVLEN);
  146                 error = EINVAL;
  147                 goto end;
  148         }
  149 
  150         /*XXX giant lock*/
  151         s = splsoftnet();
  152         error = key_parse(m, so);
  153         m = NULL;
  154         splx(s);
  155 end:
  156         if (m)
  157                 m_freem(m);
  158         return error;
  159 }
  160 
  161 /*
  162  * send message to the socket.
  163  */
  164 static int
  165 key_sendup0(
  166     struct rawcb *rp,
  167     struct mbuf *m,
  168     int promisc,
  169     int sbprio
  170 )
  171 {
  172         int error;
  173         int ok;
  174 
  175         if (promisc) {
  176                 struct sadb_msg *pmsg;
  177 
  178                 M_PREPEND(m, sizeof(struct sadb_msg), M_DONTWAIT);
  179                 if (m && m->m_len < sizeof(struct sadb_msg))
  180                         m = m_pullup(m, sizeof(struct sadb_msg));
  181                 if (!m) {
  182                         PFKEY_STATINC(PFKEY_STAT_IN_NOMEM);
  183                         m_freem(m);
  184                         return ENOBUFS;
  185                 }
  186                 m->m_pkthdr.len += sizeof(*pmsg);
  187 
  188                 pmsg = mtod(m, struct sadb_msg *);
  189                 bzero(pmsg, sizeof(*pmsg));
  190                 pmsg->sadb_msg_version = PF_KEY_V2;
  191                 pmsg->sadb_msg_type = SADB_X_PROMISC;
  192                 pmsg->sadb_msg_len = PFKEY_UNIT64(m->m_pkthdr.len);
  193                 /* pid and seq? */
  194 
  195                 PFKEY_STATINC(PFKEY_STAT_IN_MSGTYPE + pmsg->sadb_msg_type);
  196         }
  197 
  198         if (sbprio == 0)
  199                 ok = sbappendaddr(&rp->rcb_socket->so_rcv,
  200                                (struct sockaddr *)&key_src, m, NULL);
  201         else
  202                 ok = sbappendaddrchain(&rp->rcb_socket->so_rcv,
  203                                (struct sockaddr *)&key_src, m, sbprio);
  204 
  205           if (!ok) {
  206                 PFKEY_STATINC(PFKEY_STAT_IN_NOMEM);
  207                 m_freem(m);
  208                 error = ENOBUFS;
  209         } else
  210                 error = 0;
  211         sorwakeup(rp->rcb_socket);
  212         return error;
  213 }
  214 
  215 /* XXX this interface should be obsoleted. */
  216 int
  217 key_sendup(struct socket *so, struct sadb_msg *msg, u_int len,
  218            int target)  /*target of the resulting message*/
  219 {
  220         struct mbuf *m, *n, *mprev;
  221         int tlen;
  222 
  223         /* sanity check */
  224         if (so == 0 || msg == 0)
  225                 panic("key_sendup: NULL pointer was passed");
  226 
  227         KEYDEBUG(KEYDEBUG_KEY_DUMP,
  228                 printf("key_sendup: \n");
  229                 kdebug_sadb(msg));
  230 
  231         /*
  232          * we increment statistics here, just in case we have ENOBUFS
  233          * in this function.
  234          */
  235         {
  236                 uint64_t *ps = PFKEY_STAT_GETREF();
  237                 ps[PFKEY_STAT_IN_TOTAL]++;
  238                 ps[PFKEY_STAT_IN_BYTES] += len;
  239                 ps[PFKEY_STAT_IN_MSGTYPE + msg->sadb_msg_type]++;
  240                 PFKEY_STAT_PUTREF();
  241         }
  242 
  243         /*
  244          * Get mbuf chain whenever possible (not clusters),
  245          * to save socket buffer.  We'll be generating many SADB_ACQUIRE
  246          * messages to listening key sockets.  If we simply allocate clusters,
  247          * sbappendaddr() will raise ENOBUFS due to too little sbspace().
  248          * sbspace() computes # of actual data bytes AND mbuf region.
  249          *
  250          * TODO: SADB_ACQUIRE filters should be implemented.
  251          */
  252         tlen = len;
  253         m = mprev = NULL;
  254         while (tlen > 0) {
  255                 if (tlen == len) {
  256                         MGETHDR(n, M_DONTWAIT, MT_DATA);
  257                         n->m_len = MHLEN;
  258                 } else {
  259                         MGET(n, M_DONTWAIT, MT_DATA);
  260                         n->m_len = MLEN;
  261                 }
  262                 if (!n) {
  263                         PFKEY_STATINC(PFKEY_STAT_IN_NOMEM);
  264                         return ENOBUFS;
  265                 }
  266                 if (tlen >= MCLBYTES) { /*XXX better threshold? */
  267                         MCLGET(n, M_DONTWAIT);
  268                         if ((n->m_flags & M_EXT) == 0) {
  269                                 m_free(n);
  270                                 m_freem(m);
  271                                 PFKEY_STATINC(PFKEY_STAT_IN_NOMEM);
  272                                 return ENOBUFS;
  273                         }
  274                         n->m_len = MCLBYTES;
  275                 }
  276 
  277                 if (tlen < n->m_len)
  278                         n->m_len = tlen;
  279                 n->m_next = NULL;
  280                 if (m == NULL)
  281                         m = mprev = n;
  282                 else {
  283                         mprev->m_next = n;
  284                         mprev = n;
  285                 }
  286                 tlen -= n->m_len;
  287                 n = NULL;
  288         }
  289         m->m_pkthdr.len = len;
  290         m->m_pkthdr.rcvif = NULL;
  291         m_copyback(m, 0, len, msg);
  292 
  293         /* avoid duplicated statistics */
  294         {
  295                 uint64_t *ps = PFKEY_STAT_GETREF();
  296                 ps[PFKEY_STAT_IN_TOTAL]--;
  297                 ps[PFKEY_STAT_IN_BYTES] -= len;
  298                 ps[PFKEY_STAT_IN_MSGTYPE + msg->sadb_msg_type]--;
  299                 PFKEY_STAT_PUTREF();
  300         }
  301 
  302         return key_sendup_mbuf(so, m, target);
  303 }
  304 
  305 /* so can be NULL if target != KEY_SENDUP_ONE */
  306 int
  307 key_sendup_mbuf(struct socket *so, struct mbuf *m,
  308                 int target/*, sbprio */)
  309 {
  310         struct mbuf *n;
  311         struct keycb *kp;
  312         int sendup;
  313         struct rawcb *rp;
  314         int error = 0;
  315         int sbprio = 0; /* XXX should be a parameter */
  316 
  317         if (m == NULL)
  318                 panic("key_sendup_mbuf: NULL pointer was passed");
  319         if (so == NULL && target == KEY_SENDUP_ONE)
  320                 panic("key_sendup_mbuf: NULL pointer was passed");
  321 
  322         /*
  323          * RFC 2367 says ACQUIRE and other kernel-generated messages
  324          * are special. We treat all KEY_SENDUP_REGISTERED messages
  325          * as special, delivering them to all registered sockets
  326          * even if the socket is at or above its so->so_rcv.sb_max limits.
  327          * The only constraint is that the  so_rcv data fall below
  328          * key_registered_sb_max.
  329          * Doing that check here avoids reworking every key_sendup_mbuf()
  330          * in the short term. . The rework will be done after a technical
  331          * conensus that this approach is appropriate.
  332          */
  333         if (target == KEY_SENDUP_REGISTERED) {
  334                 sbprio = SB_PRIO_BESTEFFORT;
  335         }
  336 
  337         {
  338                 uint64_t *ps = PFKEY_STAT_GETREF();
  339                 ps[PFKEY_STAT_IN_TOTAL]++;
  340                 ps[PFKEY_STAT_IN_BYTES] += m->m_pkthdr.len;
  341                 PFKEY_STAT_PUTREF();
  342         }
  343         if (m->m_len < sizeof(struct sadb_msg)) {
  344 #if 1
  345                 m = m_pullup(m, sizeof(struct sadb_msg));
  346                 if (m == NULL) {
  347                         PFKEY_STATINC(PFKEY_STAT_IN_NOMEM);
  348                         return ENOBUFS;
  349                 }
  350 #else
  351                 /* don't bother pulling it up just for stats */
  352 #endif
  353         }
  354         if (m->m_len >= sizeof(struct sadb_msg)) {
  355                 struct sadb_msg *msg;
  356                 msg = mtod(m, struct sadb_msg *);
  357                 PFKEY_STATINC(PFKEY_STAT_IN_MSGTYPE + msg->sadb_msg_type);
  358         }
  359 
  360         LIST_FOREACH(rp, &rawcb_list, rcb_list)
  361         {
  362                 struct socket * kso = rp->rcb_socket;
  363                 if (rp->rcb_proto.sp_family != PF_KEY)
  364                         continue;
  365                 if (rp->rcb_proto.sp_protocol
  366                  && rp->rcb_proto.sp_protocol != PF_KEY_V2) {
  367                         continue;
  368                 }
  369 
  370                 kp = (struct keycb *)rp;
  371 
  372                 /*
  373                  * If you are in promiscuous mode, and when you get broadcasted
  374                  * reply, you'll get two PF_KEY messages.
  375                  * (based on pf_key@inner.net message on 14 Oct 1998)
  376                  */
  377                 if (((struct keycb *)rp)->kp_promisc) {
  378                         if ((n = m_copy(m, 0, (int)M_COPYALL)) != NULL) {
  379                                 (void)key_sendup0(rp, n, 1, 0);
  380                                 n = NULL;
  381                         }
  382                 }
  383 
  384                 /* the exact target will be processed later */
  385                 if (so && sotorawcb(so) == rp)
  386                         continue;
  387 
  388                 sendup = 0;
  389                 switch (target) {
  390                 case KEY_SENDUP_ONE:
  391                         /* the statement has no effect */
  392                         if (so && sotorawcb(so) == rp)
  393                                 sendup++;
  394                         break;
  395                 case KEY_SENDUP_ALL:
  396                         sendup++;
  397                         break;
  398                 case KEY_SENDUP_REGISTERED:
  399                         if (kp->kp_registered) {
  400                                 if (kso->so_rcv.sb_cc <= key_registered_sb_max)
  401                                         sendup++;
  402                                 else
  403                                         printf("keysock: "
  404                                                "registered sendup dropped, "
  405                                                "sb_cc %ld max %d\n",
  406                                                kso->so_rcv.sb_cc,
  407                                                key_registered_sb_max);
  408                         }
  409                         break;
  410                 }
  411                 PFKEY_STATINC(PFKEY_STAT_IN_MSGTARGET + target);
  412 
  413                 if (!sendup)
  414                         continue;
  415 
  416                 if ((n = m_copy(m, 0, (int)M_COPYALL)) == NULL) {
  417                         m_freem(m);
  418                         PFKEY_STATINC(PFKEY_STAT_IN_NOMEM);
  419                         return ENOBUFS;
  420                 }
  421 
  422                 if ((error = key_sendup0(rp, n, 0, 0)) != 0) {
  423                         m_freem(m);
  424                         return error;
  425                 }
  426 
  427                 n = NULL;
  428         }
  429 
  430         /* The 'later' time for processing the exact target has arrived */
  431         if (so) {
  432                 error = key_sendup0(sotorawcb(so), m, 0, sbprio);
  433                 m = NULL;
  434         } else {
  435                 error = 0;
  436                 m_freem(m);
  437         }
  438         return error;
  439 }
  440 
  441 #ifdef __FreeBSD__
  442 
  443 /*
  444  * key_abort()
  445  * derived from net/rtsock.c:rts_abort()
  446  */
  447 static int
  448 key_abort(struct socket *so)
  449 {
  450         int s, error;
  451         s = splnet();   /* FreeBSD */
  452         error = raw_usrreqs.pru_abort(so);
  453         splx(s);
  454         return error;
  455 }
  456 
  457 /*
  458  * key_attach()
  459  * derived from net/rtsock.c:rts_attach()
  460  */
  461 static int
  462 key_attach(struct socket *so, int proto, struct proc *td)
  463 {
  464         struct keycb *kp;
  465         int s, error;
  466 
  467         if (sotorawcb(so) != 0)
  468                 return EISCONN; /* XXX panic? */
  469         kp = (struct keycb *)malloc(sizeof *kp, M_PCB, M_WAITOK|M_ZERO); /* XXX */
  470         if (kp == 0)
  471                 return ENOBUFS;
  472 
  473         /*
  474          * The spl[soft]net() is necessary to block protocols from sending
  475          * error notifications (like RTM_REDIRECT or RTM_LOSING) while
  476          * this PCB is extant but incompletely initialized.
  477          * Probably we should try to do more of this work beforehand and
  478          * eliminate the spl.
  479          */
  480         s = splnet();   /* FreeBSD */
  481         so->so_pcb = kp;
  482         error = raw_usrreqs.pru_attach(so, proto, td);
  483         kp = (struct keycb *)sotorawcb(so);
  484         if (error) {
  485                 free(kp, M_PCB);
  486                 so->so_pcb = NULL;
  487                 splx(s);
  488                 return error;
  489         }
  490 
  491         kp->kp_promisc = kp->kp_registered = 0;
  492 
  493         if (kp->kp_raw.rcb_proto.sp_protocol == PF_KEY) /* XXX: AF_KEY */
  494                 key_cb.key_count++;
  495         key_cb.any_count++;
  496         kp->kp_raw.rcb_laddr = &key_src;
  497         kp->kp_raw.rcb_faddr = &key_dst;
  498         soisconnected(so);
  499         so->so_options |= SO_USELOOPBACK;
  500 
  501         splx(s);
  502         return 0;
  503 }
  504 
  505 /*
  506  * key_bind()
  507  * derived from net/rtsock.c:rts_bind()
  508  */
  509 static int
  510 key_bind(struct socket *so, struct sockaddr *nam, struct proc *td)
  511 {
  512         int s, error;
  513         s = splnet();   /* FreeBSD */
  514         error = raw_usrreqs.pru_bind(so, nam, td); /* xxx just EINVAL */
  515         splx(s);
  516         return error;
  517 }
  518 
  519 /*
  520  * key_connect()
  521  * derived from net/rtsock.c:rts_connect()
  522  */
  523 static int
  524 key_connect(struct socket *so, struct sockaddr *nam, struct proc *td)
  525 {
  526         int s, error;
  527         s = splnet();   /* FreeBSD */
  528         error = raw_usrreqs.pru_connect(so, nam, td); /* XXX just EINVAL */
  529         splx(s);
  530         return error;
  531 }
  532 
  533 /*
  534  * key_detach()
  535  * derived from net/rtsock.c:rts_detach()
  536  */
  537 static int
  538 key_detach(struct socket *so)
  539 {
  540         struct keycb *kp = (struct keycb *)sotorawcb(so);
  541         int s, error;
  542 
  543         s = splnet();   /* FreeBSD */
  544         if (kp != 0) {
  545                 if (kp->kp_raw.rcb_proto.sp_protocol
  546                     == PF_KEY) /* XXX: AF_KEY */
  547                         key_cb.key_count--;
  548                 key_cb.any_count--;
  549 
  550                 key_freereg(so);
  551         }
  552         error = raw_usrreqs.pru_detach(so);
  553         splx(s);
  554         return error;
  555 }
  556 
  557 /*
  558  * key_disconnect()
  559  * derived from net/rtsock.c:key_disconnect()
  560  */
  561 static int
  562 key_disconnect(struct socket *so)
  563 {
  564         int s, error;
  565         s = splnet();   /* FreeBSD */
  566         error = raw_usrreqs.pru_disconnect(so);
  567         splx(s);
  568         return error;
  569 }
  570 
  571 /*
  572  * key_peeraddr()
  573  * derived from net/rtsock.c:rts_peeraddr()
  574  */
  575 static int
  576 key_peeraddr(struct socket *so, struct sockaddr **nam)
  577 {
  578         int s, error;
  579         s = splnet();   /* FreeBSD */
  580         error = raw_usrreqs.pru_peeraddr(so, nam);
  581         splx(s);
  582         return error;
  583 }
  584 
  585 /*
  586  * key_send()
  587  * derived from net/rtsock.c:rts_send()
  588  */
  589 static int
  590 key_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *nam,
  591          struct mbuf *control, struct proc *td)
  592 {
  593         int s, error;
  594         s = splnet();   /* FreeBSD */
  595         error = raw_usrreqs.pru_send(so, flags, m, nam, control, td);
  596         splx(s);
  597         return error;
  598 }
  599 
  600 /*
  601  * key_shutdown()
  602  * derived from net/rtsock.c:rts_shutdown()
  603  */
  604 static int
  605 key_shutdown(struct socket *so)
  606 {
  607         int s, error;
  608         s = splnet();   /* FreeBSD */
  609         error = raw_usrreqs.pru_shutdown(so);
  610         splx(s);
  611         return error;
  612 }
  613 
  614 /*
  615  * key_sockaddr()
  616  * derived from net/rtsock.c:rts_sockaddr()
  617  */
  618 static int
  619 key_sockaddr(struct socket *so, struct sockaddr **nam)
  620 {
  621         int s, error;
  622         s = splnet();   /* FreeBSD */
  623         error = raw_usrreqs.pru_sockaddr(so, nam);
  624         splx(s);
  625         return error;
  626 }
  627 #else /*!__FreeBSD__ -- traditional proto_usrreq() switch */
  628 
  629 /*
  630  * key_usrreq()
  631  * derived from net/rtsock.c:route_usrreq()
  632  */
  633 int
  634 key_usrreq(struct socket *so, int req,struct mbuf *m, struct mbuf *nam, 
  635            struct mbuf *control, struct lwp *l)
  636 {
  637         int error = 0;
  638         struct keycb *kp = (struct keycb *)sotorawcb(so);
  639         int s;
  640 
  641         s = splsoftnet();
  642         if (req == PRU_ATTACH) {
  643                 kp = (struct keycb *)malloc(sizeof(*kp), M_PCB, M_WAITOK);
  644                 sosetlock(so);
  645                 so->so_pcb = kp;
  646                 if (so->so_pcb)
  647                         bzero(so->so_pcb, sizeof(*kp));
  648         }
  649         if (req == PRU_DETACH && kp) {
  650                 int af = kp->kp_raw.rcb_proto.sp_protocol;
  651                 if (af == PF_KEY) /* XXX: AF_KEY */
  652                         key_cb.key_count--;
  653                 key_cb.any_count--;
  654 
  655                 key_freereg(so);
  656         }
  657 
  658         error = raw_usrreq(so, req, m, nam, control, l);
  659         m = control = NULL;     /* reclaimed in raw_usrreq */
  660         kp = (struct keycb *)sotorawcb(so);
  661         if (req == PRU_ATTACH && kp) {
  662                 int af = kp->kp_raw.rcb_proto.sp_protocol;
  663                 if (error) {
  664                         PFKEY_STATINC(PFKEY_STAT_SOCKERR);
  665                         free(kp, M_PCB);
  666                         so->so_pcb = NULL;
  667                         splx(s);
  668                         return (error);
  669                 }
  670 
  671                 kp->kp_promisc = kp->kp_registered = 0;
  672 
  673                 if (af == PF_KEY) /* XXX: AF_KEY */
  674                         key_cb.key_count++;
  675                 key_cb.any_count++;
  676                 kp->kp_raw.rcb_laddr = &key_src;
  677                 kp->kp_raw.rcb_faddr = &key_dst;
  678                 soisconnected(so);
  679                 so->so_options |= SO_USELOOPBACK;
  680         }
  681         splx(s);
  682         return (error);
  683 }
  684 #endif /*!__FreeBSD__*/
  685 
  686 /* sysctl */
  687 #ifdef SYSCTL_NODE
  688 SYSCTL_NODE(_net, PF_KEY, key, CTLFLAG_RW, 0, "Key Family");
  689 #endif /* SYSCTL_NODE */
  690 
  691 /*
  692  * Definitions of protocols supported in the KEY domain.
  693  */
  694 
  695 #ifdef __FreeBSD__
  696 extern struct domain keydomain;
  697 
  698 struct pr_usrreqs key_usrreqs = {
  699         key_abort, pru_accept_notsupp, key_attach, key_bind,
  700         key_connect,
  701         pru_connect2_notsupp, pru_control_notsupp, key_detach,
  702         key_disconnect, pru_listen_notsupp, key_peeraddr,
  703         pru_rcvd_notsupp,
  704         pru_rcvoob_notsupp, key_send, pru_sense_null, key_shutdown,
  705         key_sockaddr, sosend, soreceive, sopoll
  706 };
  707 
  708 struct protosw keysw[] = {
  709 { SOCK_RAW,     &keydomain,     PF_KEY_V2,      PR_ATOMIC|PR_ADDR,
  710   0,            (pr_output_t *)key_output,      raw_ctlinput, 0,
  711   0,
  712   raw_init,     0,              0,              0,
  713   &key_usrreqs
  714 }
  715 };
  716 
  717 static void
  718 key_init0(void)
  719 {
  720         bzero(&key_cb, sizeof(key_cb));
  721         key_init();
  722 }
  723 
  724 struct domain keydomain =
  725     { PF_KEY, "key", key_init0, 0, 0,
  726       keysw, &keysw[sizeof(keysw)/sizeof(keysw[0])] };
  727 
  728 DOMAIN_SET(key);
  729 
  730 #else /* !__FreeBSD__ */
  731 
  732 DOMAIN_DEFINE(keydomain);
  733 
  734 const struct protosw keysw[] = {
  735     {
  736         .pr_type = SOCK_RAW,
  737         .pr_domain = &keydomain,
  738         .pr_protocol = PF_KEY_V2,
  739         .pr_flags = PR_ATOMIC|PR_ADDR,
  740         .pr_output = key_output,
  741         .pr_ctlinput = raw_ctlinput,
  742         .pr_usrreq = key_usrreq,
  743         .pr_init = raw_init,
  744     }
  745 };
  746 
  747 struct domain keydomain = {
  748     .dom_family = PF_KEY,
  749     .dom_name = "key",
  750     .dom_init = key_init,
  751     .dom_protosw = keysw,
  752     .dom_protoswNPROTOSW = &keysw[__arraycount(keysw)],
  753 };
  754 
  755 #endif

Cache object: 31a2825178652e0ca5cb2c0338bc667f


[ 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.