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 /*      $FreeBSD$       */
    2 /*      $KAME: keysock.c,v 1.25 2001/08/13 20:07:41 itojun Exp $        */
    3 
    4 /*-
    5  * SPDX-License-Identifier: BSD-3-Clause
    6  *
    7  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
    8  * All rights reserved.
    9  *
   10  * Redistribution and use in source and binary forms, with or without
   11  * modification, are permitted provided that the following conditions
   12  * are met:
   13  * 1. Redistributions of source code must retain the above copyright
   14  *    notice, this list of conditions and the following disclaimer.
   15  * 2. Redistributions in binary form must reproduce the above copyright
   16  *    notice, this list of conditions and the following disclaimer in the
   17  *    documentation and/or other materials provided with the distribution.
   18  * 3. Neither the name of the project nor the names of its contributors
   19  *    may be used to endorse or promote products derived from this software
   20  *    without specific prior written permission.
   21  *
   22  * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
   23  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   24  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   25  * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
   26  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   27  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   28  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   29  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   31  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   32  * SUCH DAMAGE.
   33  */
   34 
   35 #include "opt_ipsec.h"
   36 
   37 /* This code has derived from sys/net/rtsock.c on FreeBSD2.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/priv.h>
   49 #include <sys/protosw.h>
   50 #include <sys/signalvar.h>
   51 #include <sys/socket.h>
   52 #include <sys/socketvar.h>
   53 #include <sys/sysctl.h>
   54 #include <sys/systm.h>
   55 
   56 #include <net/if.h>
   57 #include <net/vnet.h>
   58 
   59 #include <netinet/in.h>
   60 
   61 #include <net/pfkeyv2.h>
   62 #include <netipsec/key.h>
   63 #include <netipsec/keysock.h>
   64 #include <netipsec/key_debug.h>
   65 #include <netipsec/ipsec.h>
   66 
   67 #include <machine/stdarg.h>
   68 
   69 static struct mtx keysock_mtx;
   70 MTX_SYSINIT(keysock, &keysock_mtx, "key socket pcb list", MTX_DEF);
   71 
   72 #define KEYSOCK_LOCK()          mtx_lock(&keysock_mtx)
   73 #define KEYSOCK_UNLOCK()        mtx_unlock(&keysock_mtx)
   74 
   75 VNET_DEFINE_STATIC(LIST_HEAD(, keycb), keycb_list) =
   76     LIST_HEAD_INITIALIZER(keycb_list);
   77 #define V_keycb_list            VNET(keycb_list)
   78 
   79 static struct sockaddr key_src = { 2, PF_KEY, };
   80 
   81 static int key_sendup0(struct keycb *, struct mbuf *, int);
   82 
   83 VNET_PCPUSTAT_DEFINE(struct pfkeystat, pfkeystat);
   84 VNET_PCPUSTAT_SYSINIT(pfkeystat);
   85 
   86 #ifdef VIMAGE
   87 VNET_PCPUSTAT_SYSUNINIT(pfkeystat);
   88 #endif /* VIMAGE */
   89 
   90 static int
   91 key_send(struct socket *so, int flags, struct mbuf *m,
   92     struct sockaddr *nam, struct mbuf *control, struct thread *td)
   93 {
   94         struct sadb_msg *msg;
   95         int len, error = 0;
   96 
   97         if ((flags & PRUS_OOB) || control != NULL) {
   98                 m_freem(m);
   99                 if (control != NULL)
  100                         m_freem(control);
  101                 return (EOPNOTSUPP);
  102         }
  103 
  104         PFKEYSTAT_INC(out_total);
  105         PFKEYSTAT_ADD(out_bytes, m->m_pkthdr.len);
  106 
  107         len = m->m_pkthdr.len;
  108         if (len < sizeof(struct sadb_msg)) {
  109                 PFKEYSTAT_INC(out_tooshort);
  110                 error = EINVAL;
  111                 goto end;
  112         }
  113 
  114         if (m->m_len < sizeof(struct sadb_msg)) {
  115                 if ((m = m_pullup(m, sizeof(struct sadb_msg))) == NULL) {
  116                         PFKEYSTAT_INC(out_nomem);
  117                         error = ENOBUFS;
  118                         goto end;
  119                 }
  120         }
  121 
  122         M_ASSERTPKTHDR(m);
  123 
  124         KEYDBG(KEY_DUMP, kdebug_mbuf(m));
  125 
  126         msg = mtod(m, struct sadb_msg *);
  127         PFKEYSTAT_INC(out_msgtype[msg->sadb_msg_type]);
  128         if (len != PFKEY_UNUNIT64(msg->sadb_msg_len)) {
  129                 PFKEYSTAT_INC(out_invlen);
  130                 error = EINVAL;
  131                 goto end;
  132         }
  133 
  134         error = key_parse(m, so);
  135         m = NULL;
  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(struct keycb *kp, struct mbuf *m, int promisc)
  147 {
  148 
  149         if (promisc) {
  150                 struct sadb_msg *pmsg;
  151 
  152                 M_PREPEND(m, sizeof(struct sadb_msg), M_NOWAIT);
  153                 if (m == NULL) {
  154                         PFKEYSTAT_INC(in_nomem);
  155                         return (ENOBUFS);
  156                 }
  157                 pmsg = mtod(m, struct sadb_msg *);
  158                 bzero(pmsg, sizeof(*pmsg));
  159                 pmsg->sadb_msg_version = PF_KEY_V2;
  160                 pmsg->sadb_msg_type = SADB_X_PROMISC;
  161                 pmsg->sadb_msg_len = PFKEY_UNIT64(m->m_pkthdr.len);
  162                 /* pid and seq? */
  163 
  164                 PFKEYSTAT_INC(in_msgtype[pmsg->sadb_msg_type]);
  165         }
  166 
  167         if (!sbappendaddr(&kp->kp_socket->so_rcv, &key_src, m, NULL)) {
  168                 PFKEYSTAT_INC(in_nomem);
  169                 m_freem(m);
  170                 soroverflow(kp->kp_socket);
  171                 return ENOBUFS;
  172         }
  173 
  174         sorwakeup(kp->kp_socket);
  175         return 0;
  176 }
  177 
  178 /* so can be NULL if target != KEY_SENDUP_ONE */
  179 int
  180 key_sendup_mbuf(struct socket *so, struct mbuf *m, int target)
  181 {
  182         struct mbuf *n;
  183         struct keycb *kp;
  184         int error = 0;
  185 
  186         KASSERT(m != NULL, ("NULL mbuf pointer was passed."));
  187         KASSERT(so != NULL || target != KEY_SENDUP_ONE,
  188             ("NULL socket pointer was passed."));
  189         KASSERT(target == KEY_SENDUP_ONE || target == KEY_SENDUP_ALL ||
  190             target == KEY_SENDUP_REGISTERED, ("Wrong target %d", target));
  191 
  192         PFKEYSTAT_INC(in_total);
  193         PFKEYSTAT_ADD(in_bytes, m->m_pkthdr.len);
  194         if (m->m_len < sizeof(struct sadb_msg)) {
  195                 m = m_pullup(m, sizeof(struct sadb_msg));
  196                 if (m == NULL) {
  197                         PFKEYSTAT_INC(in_nomem);
  198                         return ENOBUFS;
  199                 }
  200         }
  201         if (m->m_len >= sizeof(struct sadb_msg)) {
  202                 struct sadb_msg *msg;
  203                 msg = mtod(m, struct sadb_msg *);
  204                 PFKEYSTAT_INC(in_msgtype[msg->sadb_msg_type]);
  205         }
  206         KEYSOCK_LOCK();
  207         LIST_FOREACH(kp, &V_keycb_list, kp_next) {
  208                 /*
  209                  * If you are in promiscuous mode, and when you get broadcasted
  210                  * reply, you'll get two PF_KEY messages.
  211                  * (based on pf_key@inner.net message on 14 Oct 1998)
  212                  */
  213                 if (kp->kp_promisc) {
  214                         n = m_copym(m, 0, M_COPYALL, M_NOWAIT);
  215                         if (n != NULL)
  216                                 key_sendup0(kp, n, 1);
  217                         else
  218                                 PFKEYSTAT_INC(in_nomem);
  219                 }
  220 
  221                 /* the exact target will be processed later */
  222                 if (so != NULL && so->so_pcb == kp)
  223                         continue;
  224 
  225                 if (target == KEY_SENDUP_ONE || (
  226                     target == KEY_SENDUP_REGISTERED && kp->kp_registered == 0))
  227                         continue;
  228 
  229                 /* KEY_SENDUP_ALL + KEY_SENDUP_REGISTERED */
  230                 n = m_copym(m, 0, M_COPYALL, M_NOWAIT);
  231                 if (n == NULL) {
  232                         PFKEYSTAT_INC(in_nomem);
  233                         /* Try send to another socket */
  234                         continue;
  235                 }
  236 
  237                 if (key_sendup0(kp, n, 0) == 0)
  238                         PFKEYSTAT_INC(in_msgtarget[target]);
  239         }
  240 
  241         if (so) { /* KEY_SENDUP_ONE */
  242                 error = key_sendup0(so->so_pcb, m, 0);
  243                 if (error == 0)
  244                         PFKEYSTAT_INC(in_msgtarget[KEY_SENDUP_ONE]);
  245         } else {
  246                 error = 0;
  247                 m_freem(m);
  248         }
  249         KEYSOCK_UNLOCK();
  250         return (error);
  251 }
  252 
  253 static u_long key_sendspace = 8192;
  254 SYSCTL_ULONG(_net_key, OID_AUTO, sendspace, CTLFLAG_RW, &key_sendspace, 0,
  255     "Default key socket send space");
  256 static u_long key_recvspace = 8192;
  257 SYSCTL_ULONG(_net_key, OID_AUTO, recvspace, CTLFLAG_RW, &key_recvspace, 0,
  258     "Default key socket receive space");
  259 
  260 static int
  261 key_attach(struct socket *so, int proto, struct thread *td)
  262 {
  263         struct keycb *kp;
  264         int error;
  265 
  266         KASSERT(so->so_pcb == NULL, ("key_attach: so_pcb != NULL"));
  267 
  268         if (td != NULL) {
  269                 error = priv_check(td, PRIV_NET_RAW);
  270                 if (error)
  271                         return error;
  272         }
  273 
  274         error = soreserve(so, key_sendspace, key_recvspace);
  275         if (error)
  276                 return (error);
  277 
  278         kp = malloc(sizeof(*kp), M_PCB, M_WAITOK);
  279         kp->kp_socket = so;
  280         kp->kp_promisc = kp->kp_registered = 0;
  281 
  282         so->so_pcb = kp;
  283         so->so_options |= SO_USELOOPBACK;
  284 
  285         KEYSOCK_LOCK();
  286         LIST_INSERT_HEAD(&V_keycb_list, kp, kp_next);
  287         KEYSOCK_UNLOCK();
  288         soisconnected(so);
  289 
  290         return (0);
  291 }
  292 
  293 static void
  294 key_close(struct socket *so)
  295 {
  296 
  297         soisdisconnected(so);
  298 }
  299 
  300 static void
  301 key_detach(struct socket *so)
  302 {
  303         struct keycb *kp = so->so_pcb;
  304 
  305         key_freereg(so);
  306         KEYSOCK_LOCK();
  307         LIST_REMOVE(kp, kp_next);
  308         KEYSOCK_UNLOCK();
  309         free(kp, M_PCB);
  310         so->so_pcb = NULL;
  311 }
  312 
  313 static int
  314 key_shutdown(struct socket *so)
  315 {
  316 
  317         socantsendmore(so);
  318         return (0);
  319 }
  320 
  321 SYSCTL_NODE(_net, PF_KEY, key, CTLFLAG_RW | CTLFLAG_MPSAFE, 0,
  322     "Key Family");
  323 
  324 static struct protosw keysw = {
  325         .pr_type =              SOCK_RAW,
  326         .pr_protocol =          PF_KEY_V2,
  327         .pr_flags =             PR_ATOMIC|PR_ADDR,
  328         .pr_abort =             key_close,
  329         .pr_attach =            key_attach,
  330         .pr_detach =            key_detach,
  331         .pr_send =              key_send,
  332         .pr_shutdown =          key_shutdown,
  333         .pr_close =             key_close,
  334 };
  335 
  336 static struct domain keydomain = {
  337         .dom_family =           PF_KEY,
  338         .dom_name =             "key",
  339         .dom_nprotosw =         1,
  340         .dom_protosw =          { &keysw },
  341 };
  342 DOMAIN_SET(key);

Cache object: bea0384ffce077aca6ded4801ca480f0


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