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/netkey/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 /*      $KAME: keysock.c,v 1.32 2003/08/22 05:45:08 itojun Exp $        */
    2 
    3 /*-
    4  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
    5  * All rights reserved.
    6  *
    7  * Redistribution and use in source and binary forms, with or without
    8  * modification, are permitted provided that the following conditions
    9  * are met:
   10  * 1. Redistributions of source code must retain the above copyright
   11  *    notice, this list of conditions and the following disclaimer.
   12  * 2. Redistributions in binary form must reproduce the above copyright
   13  *    notice, this list of conditions and the following disclaimer in the
   14  *    documentation and/or other materials provided with the distribution.
   15  * 3. Neither the name of the project nor the names of its contributors
   16  *    may be used to endorse or promote products derived from this software
   17  *    without specific prior written permission.
   18  *
   19  * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
   20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   22  * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
   23  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   24  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   25  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   27  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   28  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   29  * SUCH DAMAGE.
   30  */
   31 
   32 #include <sys/cdefs.h>
   33 __FBSDID("$FreeBSD: releng/6.0/sys/netkey/keysock.c 139823 2005-01-07 01:45:51Z imp $");
   34 
   35 #include "opt_ipsec.h"
   36 
   37 /* This code has derived from sys/net/rtsock.c on FreeBSD 2.2.5 */
   38 
   39 #include <sys/types.h>
   40 #include <sys/param.h>
   41 #include <sys/domain.h>
   42 #include <sys/errno.h>
   43 #include <sys/kernel.h>
   44 #include <sys/lock.h>
   45 #include <sys/malloc.h>
   46 #include <sys/mbuf.h>
   47 #include <sys/mutex.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 #include <netinet/in.h>
   58 
   59 #include <net/pfkeyv2.h>
   60 #include <netkey/keydb.h>
   61 #include <netkey/key.h>
   62 #include <netkey/keysock.h>
   63 #include <netkey/key_debug.h>
   64 
   65 #include <machine/stdarg.h>
   66 
   67 struct sockaddr key_dst = { 2, PF_KEY, };
   68 struct sockaddr key_src = { 2, PF_KEY, };
   69 
   70 static int key_sendup0(struct rawcb *, struct mbuf *, int);
   71 
   72 struct pfkeystat pfkeystat;
   73 
   74 /*
   75  * key_output()
   76  */
   77 int
   78 #if __STDC__
   79 key_output(struct mbuf *m, ...)
   80 #else
   81 key_output(m, va_alist)
   82         struct mbuf *m;
   83         va_dcl
   84 #endif
   85 {
   86         struct sadb_msg *msg;
   87         int len, error = 0;
   88         int s;
   89         struct socket *so;
   90         va_list ap;
   91 
   92         va_start(ap, m);
   93         so = va_arg(ap, struct socket *);
   94         va_end(ap);
   95 
   96         if (m == 0)
   97                 panic("key_output: NULL pointer was passed.");
   98 
   99         pfkeystat.out_total++;
  100         pfkeystat.out_bytes += m->m_pkthdr.len;
  101 
  102         len = m->m_pkthdr.len;
  103         if (len < sizeof(struct sadb_msg)) {
  104                 pfkeystat.out_tooshort++;
  105                 error = EINVAL;
  106                 goto end;
  107         }
  108 
  109         if (m->m_len < sizeof(struct sadb_msg)) {
  110                 if ((m = m_pullup(m, sizeof(struct sadb_msg))) == 0) {
  111                         pfkeystat.out_nomem++;
  112                         error = ENOBUFS;
  113                         goto end;
  114                 }
  115         }
  116 
  117         M_ASSERTPKTHDR(m);
  118 
  119         KEYDEBUG(KEYDEBUG_KEY_DUMP, kdebug_mbuf(m));
  120 
  121         msg = mtod(m, struct sadb_msg *);
  122         pfkeystat.out_msgtype[msg->sadb_msg_type]++;
  123         if (len != PFKEY_UNUNIT64(msg->sadb_msg_len)) {
  124                 pfkeystat.out_invlen++;
  125                 error = EINVAL;
  126                 goto end;
  127         }
  128 
  129         /*XXX giant lock*/
  130         s = splnet();
  131         error = key_parse(m, so);
  132         m = NULL;
  133         splx(s);
  134 end:
  135         if (m)
  136                 m_freem(m);
  137         return error;
  138 }
  139 
  140 /*
  141  * send message to the socket.
  142  */
  143 static int
  144 key_sendup0(rp, m, promisc)
  145         struct rawcb *rp;
  146         struct mbuf *m;
  147         int promisc;
  148 {
  149         int error;
  150 
  151         if (promisc) {
  152                 struct sadb_msg *pmsg;
  153 
  154                 M_PREPEND(m, sizeof(struct sadb_msg), M_DONTWAIT);
  155                 if (m && m->m_len < sizeof(struct sadb_msg))
  156                         m = m_pullup(m, sizeof(struct sadb_msg));
  157                 if (!m) {
  158                         pfkeystat.in_nomem++;
  159                         return ENOBUFS;
  160                 }
  161                 m->m_pkthdr.len += sizeof(*pmsg);
  162 
  163                 pmsg = mtod(m, struct sadb_msg *);
  164                 bzero(pmsg, sizeof(*pmsg));
  165                 pmsg->sadb_msg_version = PF_KEY_V2;
  166                 pmsg->sadb_msg_type = SADB_X_PROMISC;
  167                 pmsg->sadb_msg_len = PFKEY_UNIT64(m->m_pkthdr.len);
  168                 /* pid and seq? */
  169 
  170                 pfkeystat.in_msgtype[pmsg->sadb_msg_type]++;
  171         }
  172 
  173         if (!sbappendaddr(&rp->rcb_socket->so_rcv, (struct sockaddr *)&key_src,
  174             m, NULL)) {
  175                 pfkeystat.in_nomem++;
  176                 m_freem(m);
  177                 error = ENOBUFS;
  178         } else
  179                 error = 0;
  180         sorwakeup(rp->rcb_socket);
  181         return error;
  182 }
  183 
  184 /* so can be NULL if target != KEY_SENDUP_ONE */
  185 int
  186 key_sendup_mbuf(so, m, target)
  187         struct socket *so;
  188         struct mbuf *m;
  189         int target;
  190 {
  191         struct mbuf *n;
  192         struct keycb *kp;
  193         int sendup;
  194         struct rawcb *rp;
  195         int error = 0;
  196 
  197         if (m == NULL)
  198                 panic("key_sendup_mbuf: NULL pointer was passed.");
  199         if (so == NULL && target == KEY_SENDUP_ONE)
  200                 panic("key_sendup_mbuf: NULL pointer was passed.");
  201 
  202         pfkeystat.in_total++;
  203         pfkeystat.in_bytes += m->m_pkthdr.len;
  204         if (m->m_len < sizeof(struct sadb_msg)) {
  205                 m = m_pullup(m, sizeof(struct sadb_msg));
  206                 if (m == NULL) {
  207                         pfkeystat.in_nomem++;
  208                         return ENOBUFS;
  209                 }
  210         }
  211         if (m->m_len >= sizeof(struct sadb_msg)) {
  212                 struct sadb_msg *msg;
  213                 msg = mtod(m, struct sadb_msg *);
  214                 pfkeystat.in_msgtype[msg->sadb_msg_type]++;
  215         }
  216 
  217         LIST_FOREACH(rp, &rawcb_list, list) {
  218                 if (rp->rcb_proto.sp_family != PF_KEY)
  219                         continue;
  220                 if (rp->rcb_proto.sp_protocol &&
  221                     rp->rcb_proto.sp_protocol != PF_KEY_V2) {
  222                         continue;
  223                 }
  224 
  225                 kp = (struct keycb *)rp;
  226 
  227                 /*
  228                  * If you are in promiscuous mode, and when you get broadcasted
  229                  * reply, you'll get two PF_KEY messages.
  230                  * (based on pf_key@inner.net message on 14 Oct 1998)
  231                  */
  232                 if (((struct keycb *)rp)->kp_promisc) {
  233                         if ((n = m_copy(m, 0, (int)M_COPYALL)) != NULL) {
  234                                 (void)key_sendup0(rp, n, 1);
  235                                 n = NULL;
  236                         }
  237                 }
  238 
  239                 /* the exact target will be processed later */
  240                 if (so && sotorawcb(so) == rp)
  241                         continue;
  242 
  243                 sendup = 0;
  244                 switch (target) {
  245                 case KEY_SENDUP_ONE:
  246                         /* the statement has no effect */
  247                         if (so && sotorawcb(so) == rp)
  248                                 sendup++;
  249                         break;
  250                 case KEY_SENDUP_ALL:
  251                         sendup++;
  252                         break;
  253                 case KEY_SENDUP_REGISTERED:
  254                         if (kp->kp_registered)
  255                                 sendup++;
  256                         break;
  257                 }
  258                 pfkeystat.in_msgtarget[target]++;
  259 
  260                 if (!sendup)
  261                         continue;
  262 
  263                 if ((n = m_copy(m, 0, (int)M_COPYALL)) == NULL) {
  264                         m_freem(m);
  265                         pfkeystat.in_nomem++;
  266                         return ENOBUFS;
  267                 }
  268 
  269                 /*
  270                  * ignore error even if queue is full.  PF_KEY does not
  271                  * guarantee the delivery of the message.
  272                  * this is important when target == KEY_SENDUP_ALL.
  273                  */
  274                 key_sendup0(rp, n, 0);
  275 
  276                 n = NULL;
  277         }
  278 
  279         if (so) {
  280                 error = key_sendup0(sotorawcb(so), m, 0);
  281                 m = NULL;
  282         } else {
  283                 error = 0;
  284                 m_freem(m);
  285         }
  286         return error;
  287 }
  288 
  289 /*
  290  * key_abort()
  291  * derived from net/rtsock.c:rts_abort()
  292  */
  293 static int
  294 key_abort(struct socket *so)
  295 {
  296         int s, error;
  297         s = splnet();
  298         error = raw_usrreqs.pru_abort(so);
  299         splx(s);
  300         return error;
  301 }
  302 
  303 /*
  304  * key_attach()
  305  * derived from net/rtsock.c:rts_attach()
  306  */
  307 static int
  308 key_attach(struct socket *so, int proto, struct thread *p)
  309 {
  310         struct keycb *kp;
  311         int s, error;
  312 
  313         if (sotorawcb(so) != 0)
  314                 return EISCONN; /* XXX panic? */
  315         kp = (struct keycb *)malloc(sizeof *kp, M_PCB, M_WAITOK); /* XXX */
  316         if (kp == 0)
  317                 return ENOBUFS;
  318         bzero(kp, sizeof *kp);
  319 
  320         /*
  321          * The splnet() is necessary to block protocols from sending
  322          * error notifications (like RTM_REDIRECT or RTM_LOSING) while
  323          * this PCB is extant but incompletely initialized.
  324          * Probably we should try to do more of this work beforehand and
  325          * eliminate the spl.
  326          */
  327         s = splnet();
  328         so->so_pcb = (caddr_t)kp;
  329         error = raw_usrreqs.pru_attach(so, proto, p);
  330         kp = (struct keycb *)sotorawcb(so);
  331         if (error) {
  332                 free(kp, M_PCB);
  333                 so->so_pcb = (caddr_t) 0;
  334                 splx(s);
  335                 return error;
  336         }
  337 
  338         kp->kp_promisc = kp->kp_registered = 0;
  339 
  340         if (kp->kp_raw.rcb_proto.sp_protocol == PF_KEY) /* XXX: AF_KEY */
  341                 key_cb.key_count++;
  342         key_cb.any_count++;
  343         kp->kp_raw.rcb_laddr = &key_src;
  344         kp->kp_raw.rcb_faddr = &key_dst;
  345         soisconnected(so);
  346         so->so_options |= SO_USELOOPBACK;
  347 
  348         splx(s);
  349         return 0;
  350 }
  351 
  352 /*
  353  * key_bind()
  354  * derived from net/rtsock.c:rts_bind()
  355  */
  356 static int
  357 key_bind(struct socket *so, struct sockaddr *nam, struct thread *p)
  358 {
  359         int s, error;
  360         s = splnet();
  361         error = raw_usrreqs.pru_bind(so, nam, p); /* xxx just EINVAL */
  362         splx(s);
  363         return error;
  364 }
  365 
  366 /*
  367  * key_connect()
  368  * derived from net/rtsock.c:rts_connect()
  369  */
  370 static int
  371 key_connect(struct socket *so, struct sockaddr *nam, struct thread *p)
  372 {
  373         int s, error;
  374         s = splnet();
  375         error = raw_usrreqs.pru_connect(so, nam, p); /* XXX just EINVAL */
  376         splx(s);
  377         return error;
  378 }
  379 
  380 /*
  381  * key_detach()
  382  * derived from net/rtsock.c:rts_detach()
  383  */
  384 static int
  385 key_detach(struct socket *so)
  386 {
  387         struct keycb *kp = (struct keycb *)sotorawcb(so);
  388         int s, error;
  389 
  390         s = splnet();
  391         if (kp != 0) {
  392                 if (kp->kp_raw.rcb_proto.sp_protocol
  393                     == PF_KEY) /* XXX: AF_KEY */
  394                         key_cb.key_count--;
  395                 key_cb.any_count--;
  396 
  397                 key_freereg(so);
  398         }
  399         error = raw_usrreqs.pru_detach(so);
  400         splx(s);
  401         return error;
  402 }
  403 
  404 /*
  405  * key_disconnect()
  406  * derived from net/rtsock.c:key_disconnect()
  407  */
  408 static int
  409 key_disconnect(struct socket *so)
  410 {
  411         int s, error;
  412         s = splnet();
  413         error = raw_usrreqs.pru_disconnect(so);
  414         splx(s);
  415         return error;
  416 }
  417 
  418 /*
  419  * key_peeraddr()
  420  * derived from net/rtsock.c:rts_peeraddr()
  421  */
  422 static int
  423 key_peeraddr(struct socket *so, struct sockaddr **nam)
  424 {
  425         int s, error;
  426         s = splnet();
  427         error = raw_usrreqs.pru_peeraddr(so, nam);
  428         splx(s);
  429         return error;
  430 }
  431 
  432 /*
  433  * key_send()
  434  * derived from net/rtsock.c:rts_send()
  435  */
  436 static int
  437 key_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *nam,
  438          struct mbuf *control, struct thread *p)
  439 {
  440         int s, error;
  441         s = splnet();
  442         error = raw_usrreqs.pru_send(so, flags, m, nam, control, p);
  443         splx(s);
  444         return error;
  445 }
  446 
  447 /*
  448  * key_shutdown()
  449  * derived from net/rtsock.c:rts_shutdown()
  450  */
  451 static int
  452 key_shutdown(struct socket *so)
  453 {
  454         int s, error;
  455         s = splnet();
  456         error = raw_usrreqs.pru_shutdown(so);
  457         splx(s);
  458         return error;
  459 }
  460 
  461 /*
  462  * key_sockaddr()
  463  * derived from net/rtsock.c:rts_sockaddr()
  464  */
  465 static int
  466 key_sockaddr(struct socket *so, struct sockaddr **nam)
  467 {
  468         int s, error;
  469         s = splnet();
  470         error = raw_usrreqs.pru_sockaddr(so, nam);
  471         splx(s);
  472         return error;
  473 }
  474 
  475 struct pr_usrreqs key_usrreqs = {
  476         .pru_abort =            key_abort,
  477         .pru_attach =           key_attach,
  478         .pru_bind =             key_bind,
  479         .pru_connect =          key_connect,
  480         .pru_detach =           key_detach,
  481         .pru_disconnect =       key_disconnect,
  482         .pru_peeraddr =         key_peeraddr,
  483         .pru_send =             key_send,
  484         .pru_shutdown =         key_shutdown,
  485         .pru_sockaddr =         key_sockaddr,
  486 };
  487 
  488 /* sysctl */
  489 SYSCTL_NODE(_net, PF_KEY, key, CTLFLAG_RW, 0, "Key Family");
  490 
  491 /*
  492  * Definitions of protocols supported in the KEY domain.
  493  */
  494 
  495 extern struct domain keydomain;
  496 
  497 struct protosw keysw[] = {
  498 { SOCK_RAW,     &keydomain,     PF_KEY_V2,      PR_ATOMIC|PR_ADDR,
  499   0,            (pr_output_t *)key_output, raw_ctlinput, 0,
  500   0,
  501   raw_init,     0,              0,              0,
  502   &key_usrreqs
  503 }
  504 };
  505 
  506 struct domain keydomain =
  507     { PF_KEY, "key", key_init, 0, 0,
  508       keysw, &keysw[sizeof(keysw)/sizeof(keysw[0])] };
  509 
  510 DOMAIN_SET(key);

Cache object: b030122e0cb37ead52fffc227751f3b4


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