root/net/pfkey.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. pfkey_register
  2. pfkey_unregister
  3. pfkey_sendup
  4. pfkey_output
  5. pfkey_attach
  6. pfkey_detach
  7. pfkey_usrreq
  8. pfkey_buildprotosw
  9. pfkey_init

    1 /*      $OpenBSD: pfkey.c,v 1.16 2004/11/26 18:02:22 markus Exp $       */
    2 
    3 /*
    4  *      @(#)COPYRIGHT   1.1 (NRL) 17 January 1995
    5  * 
    6  * NRL grants permission for redistribution and use in source and binary
    7  * forms, with or without modification, of the software and documentation
    8  * created at NRL provided that the following conditions are met:
    9  * 
   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. All advertising materials mentioning features or use of this software
   16  *    must display the following acknowledgements:
   17  *      This product includes software developed by the University of
   18  *      California, Berkeley and its contributors.
   19  *      This product includes software developed at the Information
   20  *      Technology Division, US Naval Research Laboratory.
   21  * 4. Neither the name of the NRL nor the names of its contributors
   22  *    may be used to endorse or promote products derived from this software
   23  *    without specific prior written permission.
   24  * 
   25  * THE SOFTWARE PROVIDED BY NRL IS PROVIDED BY NRL AND CONTRIBUTORS ``AS
   26  * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
   27  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
   28  * PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL NRL OR
   29  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
   30  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
   31  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
   32  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
   33  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
   34  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
   35  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   36  * 
   37  * The views and conclusions contained in the software and documentation
   38  * are those of the authors and should not be interpreted as representing
   39  * official policies, either expressed or implied, of the US Naval
   40  * Research Laboratory (NRL).
   41  */
   42 
   43 /*
   44  * Copyright (c) 1995, 1996, 1997, 1998, 1999 Craig Metz. All rights reserved.
   45  *
   46  * Redistribution and use in source and binary forms, with or without
   47  * modification, are permitted provided that the following conditions
   48  * are met:
   49  * 1. Redistributions of source code must retain the above copyright
   50  *    notice, this list of conditions and the following disclaimer.
   51  * 2. Redistributions in binary form must reproduce the above copyright
   52  *    notice, this list of conditions and the following disclaimer in the
   53  *    documentation and/or other materials provided with the distribution.
   54  * 3. Neither the name of the author nor the names of any contributors
   55  *    may be used to endorse or promote products derived from this software
   56  *    without specific prior written permission.
   57  *
   58  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   59  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   60  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   61  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   62  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   63  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   64  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   65  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   66  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   67  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   68  * SUCH DAMAGE.
   69  */
   70 
   71 #include <sys/types.h>
   72 #include <sys/param.h>
   73 #include <sys/systm.h>
   74 #include <sys/socket.h>
   75 #include <sys/mbuf.h>
   76 #include <sys/socketvar.h>
   77 #include <net/route.h>
   78 #include <netinet/ip_ipsp.h>
   79 #include <net/pfkeyv2.h>
   80 
   81 #include <sys/protosw.h>
   82 #include <sys/domain.h>
   83 #include <net/raw_cb.h>
   84 
   85 #define PFKEY_PROTOCOL_MAX 3
   86 static struct pfkey_version *pfkey_versions[PFKEY_PROTOCOL_MAX+1] =
   87     { NULL, NULL, NULL, NULL };
   88 
   89 #define PFKEY_MSG_MAXSZ 4096
   90 
   91 struct sockaddr pfkey_addr = { 2, PF_KEY, };
   92 
   93 /* static struct domain pfkey_domain; */
   94 static int pfkey_usrreq(struct socket *socket, int req, struct mbuf *mbuf,
   95     struct mbuf *nam, struct mbuf *control);
   96 static int pfkey_output(struct mbuf *mbuf, struct socket *socket);
   97 
   98 int pfkey_register(struct pfkey_version *version);
   99 int pfkey_unregister(struct pfkey_version *version);
  100 int pfkey_sendup(struct socket *socket, struct mbuf *packet, int more);
  101 void pfkey_init(void);
  102 int pfkey_buildprotosw(void);
  103 
  104 int
  105 pfkey_register(struct pfkey_version *version)
  106 {
  107         int rval;
  108 
  109         if ((version->protocol > PFKEY_PROTOCOL_MAX) ||
  110             (version->protocol < 0))
  111                 return (EPROTONOSUPPORT);
  112 
  113         if (pfkey_versions[version->protocol])
  114                 return (EADDRINUSE);
  115 
  116         pfkey_versions[version->protocol] = version;
  117 
  118         if ((rval = pfkey_buildprotosw()) != 0) {
  119                 pfkey_versions[version->protocol] = NULL;
  120                 return (rval);
  121         }
  122 
  123         return (0);
  124 }
  125 
  126 int
  127 pfkey_unregister(struct pfkey_version *version)
  128 {
  129         int rval;
  130 
  131         if ((rval = pfkey_buildprotosw()) != 0)
  132                 return (rval);
  133 
  134         pfkey_versions[version->protocol] = NULL;
  135         return (0);
  136 }
  137 
  138 int
  139 pfkey_sendup(struct socket *socket, struct mbuf *packet, int more)
  140 {
  141         struct mbuf *packet2;
  142         int s;
  143 
  144         if (more) {
  145                 if (!(packet2 = m_copym2(packet, 0, M_COPYALL, M_DONTWAIT)))
  146                         return (ENOMEM);
  147         } else
  148           packet2 = packet;
  149 
  150         s = spltdb();
  151         if (!sbappendaddr(&socket->so_rcv, &pfkey_addr, packet2, NULL)) {
  152                 m_freem(packet2);
  153                 splx(s);
  154                 return (ENOBUFS);
  155         }
  156         splx(s);
  157 
  158         sorwakeup(socket);
  159         return (0);
  160 }
  161 
  162 static int
  163 pfkey_output(struct mbuf *mbuf, struct socket *socket)
  164 {
  165         void *message;
  166         int error = 0;
  167 
  168 #ifdef DIAGNOSTIC
  169         if (!mbuf || !(mbuf->m_flags & M_PKTHDR)) {
  170                 error = EINVAL;
  171                 goto ret;
  172         }
  173 #endif /* DIAGNOSTIC */
  174 
  175         if (mbuf->m_pkthdr.len > PFKEY_MSG_MAXSZ) {
  176                 error = EMSGSIZE;
  177                 goto ret;
  178         }
  179 
  180         if (!(message = malloc((unsigned long) mbuf->m_pkthdr.len,
  181             M_PFKEY, M_DONTWAIT))) {
  182                 error = ENOMEM;
  183                 goto ret;
  184         }
  185 
  186         m_copydata(mbuf, 0, mbuf->m_pkthdr.len, message);
  187 
  188         error = pfkey_versions[socket->so_proto->pr_protocol]->send(socket,
  189             message, mbuf->m_pkthdr.len);
  190 
  191 ret:
  192         if (mbuf)
  193                 m_freem (mbuf);
  194         return (error);
  195 }
  196 
  197 static int
  198 pfkey_attach(struct socket *socket, struct mbuf *proto)
  199 {
  200         int rval;
  201         int s;
  202 
  203         if (!(socket->so_pcb = malloc(sizeof(struct rawcb),
  204             M_PCB, M_DONTWAIT)))
  205                 return (ENOMEM);
  206         bzero(socket->so_pcb, sizeof(struct rawcb));
  207 
  208         s = splnet();
  209         rval = raw_usrreq(socket, PRU_ATTACH, NULL, proto, NULL);
  210         splx(s);
  211         if (rval)
  212                 goto ret;
  213 
  214         ((struct rawcb *)socket->so_pcb)->rcb_faddr = &pfkey_addr;
  215         soisconnected(socket);
  216 
  217         socket->so_options |= SO_USELOOPBACK;
  218         if ((rval =
  219             pfkey_versions[socket->so_proto->pr_protocol]->create(socket)) != 0)
  220                 goto ret;
  221 
  222         return (0);
  223 
  224 ret:
  225         free(socket->so_pcb, M_PCB);
  226         return (rval);
  227 }
  228 
  229 static int
  230 pfkey_detach(struct socket *socket)
  231 {
  232         int rval, i, s;
  233 
  234         rval = pfkey_versions[socket->so_proto->pr_protocol]->release(socket);
  235         s = splnet();
  236         i = raw_usrreq(socket, PRU_DETACH, NULL, NULL, NULL);
  237         splx(s);
  238 
  239         if (!rval)
  240                 rval = i;
  241 
  242         return (rval);
  243 }
  244 
  245 static int
  246 pfkey_usrreq(struct socket *socket, int req, struct mbuf *mbuf,
  247     struct mbuf *nam, struct mbuf *control)
  248 {
  249         int rval;
  250         int s;
  251 
  252         if ((socket->so_proto->pr_protocol > PFKEY_PROTOCOL_MAX) ||
  253             (socket->so_proto->pr_protocol < 0) ||
  254             !pfkey_versions[socket->so_proto->pr_protocol])
  255                 return (EPROTONOSUPPORT);
  256 
  257         switch (req) {
  258         case PRU_ATTACH:
  259                 return (pfkey_attach(socket, nam));
  260 
  261         case PRU_DETACH:
  262                 return (pfkey_detach(socket));
  263 
  264         default:
  265                 s = splnet();
  266                 rval = raw_usrreq(socket, req, mbuf, nam, control);
  267                 splx(s);
  268         }
  269 
  270         return (rval);
  271 }
  272 
  273 static struct domain pfkey_domain = {
  274         PF_KEY,
  275         "PF_KEY",
  276         NULL, /* init */
  277         NULL, /* externalize */
  278         NULL, /* dispose */
  279         NULL, /* protosw */
  280         NULL, /* protoswNPROTOSW */
  281         NULL, /* dom_next */
  282         rn_inithead, /* dom_rtattach */
  283         16, /* rtoffset */
  284         sizeof(struct sockaddr_encap)  /* maxrtkey */
  285 };
  286 
  287 static struct protosw pfkey_protosw_template = {
  288         SOCK_RAW,
  289         &pfkey_domain,
  290         -1, /* protocol */
  291         PR_ATOMIC | PR_ADDR,
  292         (void *) raw_input,
  293         (void *) pfkey_output,
  294         (void *) raw_ctlinput,
  295         NULL, /* ctloutput */
  296         pfkey_usrreq,
  297         NULL, /* init */
  298         NULL, /* fasttimo */
  299         NULL, /* slowtimo */
  300         NULL, /* drain */
  301         NULL    /* sysctl */
  302 };
  303 
  304 int
  305 pfkey_buildprotosw(void)
  306 {
  307         struct protosw *protosw, *p;
  308         int i, j;
  309 
  310         for (i = j = 0; i <= PFKEY_PROTOCOL_MAX; i++)
  311                 if (pfkey_versions[i])
  312                         j++;
  313 
  314         if (j) {
  315                 if (!(protosw = malloc(j * sizeof(struct protosw),
  316                     M_PFKEY, M_DONTWAIT)))
  317                         return (ENOMEM);
  318 
  319                 for (i = 0, p = protosw; i <= PFKEY_PROTOCOL_MAX; i++)
  320                         if (pfkey_versions[i]) {
  321                                 bcopy(&pfkey_protosw_template, p,
  322                                     sizeof(struct protosw));
  323                                 p->pr_protocol = pfkey_versions[i]->protocol;
  324                                 p->pr_sysctl = pfkey_versions[i]->sysctl;
  325                                 p++;
  326                         }
  327 
  328                 if (pfkey_domain.dom_protosw)
  329                         free(pfkey_domain.dom_protosw, M_PFKEY);
  330 
  331                 pfkey_domain.dom_protosw = protosw;
  332                 pfkey_domain.dom_protoswNPROTOSW = p;
  333         } else {
  334                 if (!(protosw = malloc(sizeof(struct protosw), M_PFKEY,
  335                     M_DONTWAIT)))
  336                         return (ENOMEM);
  337 
  338                 bcopy(&pfkey_protosw_template, protosw,
  339                     sizeof(struct protosw));
  340 
  341                 if (pfkey_domain.dom_protosw)
  342                         free(pfkey_domain.dom_protosw, M_PFKEY);
  343 
  344                 pfkey_domain.dom_protosw = protosw;
  345                 pfkey_domain.dom_protoswNPROTOSW = protosw;
  346         }
  347 
  348         return (0);
  349 }
  350 
  351 void
  352 pfkey_init(void)
  353 {
  354         if (pfkey_buildprotosw() != 0)
  355                 return;
  356 
  357         pfkey_domain.dom_next = domains;
  358         domains = &pfkey_domain;
  359         pfkeyv2_init();
  360 }

/* [<][>][^][v][top][bottom][index][help] */