[BACK]Return to pfkey.c CVS log [TXT][DIR] Up to [local] / sys / net

Annotation of sys/net/pfkey.c, Revision 1.1.1.1

1.1       nbrk        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: }

CVSweb