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