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

Cache object: 668ccfa4c19485e79abf57ced968bbc5


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