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

Annotation of sys/net/pfkeyv2.c, Revision 1.1

1.1     ! nbrk        1: /* $OpenBSD: pfkeyv2.c,v 1.115 2007/06/22 12:14:05 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 "pf.h"
        !            72:
        !            73: #include <sys/types.h>
        !            74: #include <sys/param.h>
        !            75: #include <sys/socket.h>
        !            76: #include <sys/systm.h>
        !            77: #include <sys/mbuf.h>
        !            78: #include <sys/kernel.h>
        !            79: #include <sys/proc.h>
        !            80: #include <net/route.h>
        !            81: #include <netinet/ip_ipsp.h>
        !            82: #include <net/pfkeyv2.h>
        !            83: #include <netinet/ip_ah.h>
        !            84: #include <netinet/ip_esp.h>
        !            85: #include <netinet/ip_ipcomp.h>
        !            86: #include <crypto/blf.h>
        !            87:
        !            88: #if NPF > 0
        !            89: #include <net/if.h>
        !            90: #include <net/pfvar.h>
        !            91: #endif
        !            92:
        !            93: #define PFKEYV2_PROTOCOL 2
        !            94: #define GETSPI_TRIES 10
        !            95:
        !            96: /* Static globals */
        !            97: static struct pfkeyv2_socket *pfkeyv2_sockets = NULL;
        !            98: static struct pfkey_version pfkeyv2_version;
        !            99: static uint32_t pfkeyv2_seq = 1;
        !           100: static int nregistered = 0;
        !           101: static int npromisc = 0;
        !           102:
        !           103: static const struct sadb_alg ealgs[] = {
        !           104:        { SADB_EALG_NULL, 0, 0, 0 },
        !           105:        { SADB_EALG_DESCBC, 64, 64, 64 },
        !           106:        { SADB_EALG_3DESCBC, 64, 192, 192 },
        !           107:        { SADB_X_EALG_BLF, 64, 40, BLF_MAXKEYLEN * 8},
        !           108:        { SADB_X_EALG_CAST, 64, 40, 128},
        !           109:        { SADB_X_EALG_SKIPJACK, 64, 80, 80},
        !           110:        { SADB_X_EALG_AES, 128, 128, 256},
        !           111:        { SADB_X_EALG_AESCTR, 128, 128 + 32, 256 + 32}
        !           112: };
        !           113:
        !           114: static const struct sadb_alg aalgs[] = {
        !           115:        { SADB_AALG_SHA1HMAC, 0, 160, 160 },
        !           116:        { SADB_AALG_MD5HMAC, 0, 128, 128 },
        !           117:        { SADB_X_AALG_RIPEMD160HMAC, 0, 160, 160 },
        !           118:        { SADB_X_AALG_SHA2_256, 0, 256, 256 },
        !           119:        { SADB_X_AALG_SHA2_384, 0, 384, 384 },
        !           120:        { SADB_X_AALG_SHA2_512, 0, 512, 512 }
        !           121: };
        !           122:
        !           123: static const struct sadb_alg calgs[] = {
        !           124:        { SADB_X_CALG_DEFLATE, 0, 0, 0},
        !           125:        { SADB_X_CALG_LZS, 0, 0, 0}
        !           126: };
        !           127:
        !           128: extern uint64_t sadb_exts_allowed_out[SADB_MAX+1];
        !           129: extern uint64_t sadb_exts_required_out[SADB_MAX+1];
        !           130:
        !           131: extern struct pool ipsec_policy_pool;
        !           132:
        !           133: /*
        !           134:  * Wrapper around m_devget(); copy data from contiguous buffer to mbuf
        !           135:  * chain.
        !           136:  */
        !           137: int
        !           138: pfdatatopacket(void *data, int len, struct mbuf **packet)
        !           139: {
        !           140:        if (!(*packet = m_devget(data, len, 0, NULL, NULL)))
        !           141:                return (ENOMEM);
        !           142:        return (0);
        !           143: }
        !           144:
        !           145: /*
        !           146:  * Create a new PF_KEYv2 socket.
        !           147:  */
        !           148: int
        !           149: pfkeyv2_create(struct socket *socket)
        !           150: {
        !           151:        struct pfkeyv2_socket *pfkeyv2_socket;
        !           152:
        !           153:        if (!(pfkeyv2_socket = malloc(sizeof(struct pfkeyv2_socket),
        !           154:            M_PFKEY, M_DONTWAIT)))
        !           155:                return (ENOMEM);
        !           156:
        !           157:        bzero(pfkeyv2_socket, sizeof(struct pfkeyv2_socket));
        !           158:        pfkeyv2_socket->next = pfkeyv2_sockets;
        !           159:        pfkeyv2_socket->socket = socket;
        !           160:        pfkeyv2_socket->pid = curproc->p_pid;
        !           161:
        !           162:        pfkeyv2_sockets = pfkeyv2_socket;
        !           163:
        !           164:        return (0);
        !           165: }
        !           166:
        !           167: /*
        !           168:  * Close a PF_KEYv2 socket.
        !           169:  */
        !           170: int
        !           171: pfkeyv2_release(struct socket *socket)
        !           172: {
        !           173:        struct pfkeyv2_socket **pp;
        !           174:
        !           175:        for (pp = &pfkeyv2_sockets; *pp && ((*pp)->socket != socket);
        !           176:            pp = &((*pp)->next))
        !           177:                /*EMPTY*/;
        !           178:
        !           179:        if (*pp) {
        !           180:                struct pfkeyv2_socket *pfkeyv2_socket;
        !           181:
        !           182:                pfkeyv2_socket = *pp;
        !           183:                *pp = (*pp)->next;
        !           184:
        !           185:                if (pfkeyv2_socket->flags & PFKEYV2_SOCKETFLAGS_REGISTERED)
        !           186:                        nregistered--;
        !           187:
        !           188:                if (pfkeyv2_socket->flags & PFKEYV2_SOCKETFLAGS_PROMISC)
        !           189:                        npromisc--;
        !           190:
        !           191:                free(pfkeyv2_socket, M_PFKEY);
        !           192:        }
        !           193:
        !           194:        return (0);
        !           195: }
        !           196:
        !           197: /*
        !           198:  * Send a PFKEYv2 message, possibly to many receivers, based on the
        !           199:  * satype of the socket (which is set by the REGISTER message), and the
        !           200:  * third argument.
        !           201:  */
        !           202: int
        !           203: pfkeyv2_sendmessage(void **headers, int mode, struct socket *socket,
        !           204:     u_int8_t satype, int count)
        !           205: {
        !           206:        int i, j, rval;
        !           207:        void *p, *buffer = NULL;
        !           208:        struct mbuf *packet;
        !           209:        struct pfkeyv2_socket *s;
        !           210:        struct sadb_msg *smsg;
        !           211:
        !           212:        /* Find out how much space we'll need... */
        !           213:        j = sizeof(struct sadb_msg);
        !           214:
        !           215:        for (i = 1; i <= SADB_EXT_MAX; i++)
        !           216:                if (headers[i])
        !           217:                        j += ((struct sadb_ext *)headers[i])->sadb_ext_len *
        !           218:                            sizeof(uint64_t);
        !           219:
        !           220:        /* ...and allocate it */
        !           221:        if (!(buffer = malloc(j + sizeof(struct sadb_msg), M_PFKEY,
        !           222:            M_DONTWAIT))) {
        !           223:                rval = ENOMEM;
        !           224:                goto ret;
        !           225:        }
        !           226:
        !           227:        p = buffer + sizeof(struct sadb_msg);
        !           228:        bcopy(headers[0], p, sizeof(struct sadb_msg));
        !           229:        ((struct sadb_msg *) p)->sadb_msg_len = j / sizeof(uint64_t);
        !           230:        p += sizeof(struct sadb_msg);
        !           231:
        !           232:        /* Copy payloads in the packet */
        !           233:        for (i = 1; i <= SADB_EXT_MAX; i++)
        !           234:                if (headers[i]) {
        !           235:                        ((struct sadb_ext *) headers[i])->sadb_ext_type = i;
        !           236:                        bcopy(headers[i], p, EXTLEN(headers[i]));
        !           237:                        p += EXTLEN(headers[i]);
        !           238:                }
        !           239:
        !           240:        if ((rval = pfdatatopacket(buffer + sizeof(struct sadb_msg),
        !           241:            j, &packet)) != 0)
        !           242:                goto ret;
        !           243:
        !           244:        switch (mode) {
        !           245:        case PFKEYV2_SENDMESSAGE_UNICAST:
        !           246:                /*
        !           247:                 * Send message to the specified socket, plus all
        !           248:                 * promiscuous listeners.
        !           249:                 */
        !           250:                pfkey_sendup(socket, packet, 0);
        !           251:
        !           252:                /*
        !           253:                 * Promiscuous messages contain the original message
        !           254:                 * encapsulated in another sadb_msg header.
        !           255:                 */
        !           256:                bzero(buffer, sizeof(struct sadb_msg));
        !           257:                smsg = (struct sadb_msg *) buffer;
        !           258:                smsg->sadb_msg_version = PF_KEY_V2;
        !           259:                smsg->sadb_msg_type = SADB_X_PROMISC;
        !           260:                smsg->sadb_msg_len = (sizeof(struct sadb_msg) + j) /
        !           261:                    sizeof(uint64_t);
        !           262:                smsg->sadb_msg_seq = 0;
        !           263:
        !           264:                /* Copy to mbuf chain */
        !           265:                if ((rval = pfdatatopacket(buffer, sizeof(struct sadb_msg) + j,
        !           266:                    &packet)) != 0)
        !           267:                        goto ret;
        !           268:
        !           269:                /*
        !           270:                 * Search for promiscuous listeners, skipping the
        !           271:                 * original destination.
        !           272:                 */
        !           273:                for (s = pfkeyv2_sockets; s; s = s->next)
        !           274:                        if ((s->flags & PFKEYV2_SOCKETFLAGS_PROMISC) &&
        !           275:                            (s->socket != socket))
        !           276:                                pfkey_sendup(s->socket, packet, 1);
        !           277:
        !           278:                /* Done, let's be a bit paranoid */
        !           279:                m_zero(packet);
        !           280:                m_freem(packet);
        !           281:                break;
        !           282:
        !           283:        case PFKEYV2_SENDMESSAGE_REGISTERED:
        !           284:                /*
        !           285:                 * Send the message to all registered sockets that match
        !           286:                 * the specified satype (e.g., all IPSEC-ESP negotiators)
        !           287:                 */
        !           288:                for (s = pfkeyv2_sockets; s; s = s->next)
        !           289:                        if (s->flags & PFKEYV2_SOCKETFLAGS_REGISTERED) {
        !           290:                                if (!satype)    /* Just send to everyone registered */
        !           291:                                        pfkey_sendup(s->socket, packet, 1);
        !           292:                                else {
        !           293:                                        /* Check for specified satype */
        !           294:                                        if ((1 << satype) & s->registration)
        !           295:                                                pfkey_sendup(s->socket, packet, 1);
        !           296:                                }
        !           297:                        }
        !           298:
        !           299:                /* Free last/original copy of the packet */
        !           300:                m_freem(packet);
        !           301:
        !           302:                /* Encapsulate the original message "inside" an sadb_msg header */
        !           303:                bzero(buffer, sizeof(struct sadb_msg));
        !           304:                smsg = (struct sadb_msg *) buffer;
        !           305:                smsg->sadb_msg_version = PF_KEY_V2;
        !           306:                smsg->sadb_msg_type = SADB_X_PROMISC;
        !           307:                smsg->sadb_msg_len = (sizeof(struct sadb_msg) + j) /
        !           308:                    sizeof(uint64_t);
        !           309:                smsg->sadb_msg_seq = 0;
        !           310:
        !           311:                /* Convert to mbuf chain */
        !           312:                if ((rval = pfdatatopacket(buffer, sizeof(struct sadb_msg) + j,
        !           313:                    &packet)) != 0)
        !           314:                        goto ret;
        !           315:
        !           316:                /* Send to all registered promiscuous listeners */
        !           317:                for (s = pfkeyv2_sockets; s; s = s->next)
        !           318:                        if ((s->flags & PFKEYV2_SOCKETFLAGS_PROMISC) &&
        !           319:                            !(s->flags & PFKEYV2_SOCKETFLAGS_REGISTERED))
        !           320:                                pfkey_sendup(s->socket, packet, 1);
        !           321:
        !           322:                m_freem(packet);
        !           323:                break;
        !           324:
        !           325:        case PFKEYV2_SENDMESSAGE_BROADCAST:
        !           326:                /* Send message to all sockets */
        !           327:                for (s = pfkeyv2_sockets; s; s = s->next)
        !           328:                        pfkey_sendup(s->socket, packet, 1);
        !           329:
        !           330:                m_freem(packet);
        !           331:                break;
        !           332:        }
        !           333:
        !           334: ret:
        !           335:        if (buffer != NULL) {
        !           336:                bzero(buffer, j + sizeof(struct sadb_msg));
        !           337:                free(buffer, M_PFKEY);
        !           338:        }
        !           339:
        !           340:        return (rval);
        !           341: }
        !           342:
        !           343: /*
        !           344:  * Get SPD information for an ACQUIRE. We setup the message such that
        !           345:  * the SRC/DST payloads are relative to us (regardless of whether the
        !           346:  * SPD rule was for incoming or outgoing packets).
        !           347:  */
        !           348: int
        !           349: pfkeyv2_policy(struct ipsec_acquire *ipa, void **headers, void **buffer)
        !           350: {
        !           351:        union sockaddr_union sunion;
        !           352:        struct sadb_protocol *sp;
        !           353:        int rval, i, dir;
        !           354:        void *p;
        !           355:
        !           356:        /* Find out how big a buffer we need */
        !           357:        i = 4 * sizeof(struct sadb_address) + sizeof(struct sadb_protocol);
        !           358:        bzero(&sunion, sizeof(union sockaddr_union));
        !           359:
        !           360:        switch (ipa->ipa_info.sen_type) {
        !           361: #ifdef INET
        !           362:        case SENT_IP4:
        !           363:                i += 4 * PADUP(sizeof(struct sockaddr_in));
        !           364:                sunion.sa.sa_family = AF_INET;
        !           365:                sunion.sa.sa_len = sizeof(struct sockaddr_in);
        !           366:                dir = ipa->ipa_info.sen_direction;
        !           367:                break;
        !           368: #endif /* INET */
        !           369:
        !           370: #ifdef INET6
        !           371:        case SENT_IP6:
        !           372:                i += 4 * PADUP(sizeof(struct sockaddr_in6));
        !           373:                sunion.sa.sa_family = AF_INET6;
        !           374:                sunion.sa.sa_len = sizeof(struct sockaddr_in6);
        !           375:                dir = ipa->ipa_info.sen_ip6_direction;
        !           376:                break;
        !           377: #endif /* INET6 */
        !           378:
        !           379:        default:
        !           380:                return (EINVAL);
        !           381:        }
        !           382:
        !           383:        if (!(p = malloc(i, M_PFKEY, M_DONTWAIT))) {
        !           384:                rval = ENOMEM;
        !           385:                goto ret;
        !           386:        } else {
        !           387:                *buffer = p;
        !           388:                bzero(p, i);
        !           389:        }
        !           390:
        !           391:        if (dir == IPSP_DIRECTION_OUT)
        !           392:                headers[SADB_X_EXT_SRC_FLOW] = p;
        !           393:        else
        !           394:                headers[SADB_X_EXT_DST_FLOW] = p;
        !           395:        switch (sunion.sa.sa_family) {
        !           396: #ifdef INET
        !           397:        case AF_INET:
        !           398:                sunion.sin.sin_addr = ipa->ipa_info.sen_ip_src;
        !           399:                sunion.sin.sin_port = ipa->ipa_info.sen_sport;
        !           400:                break;
        !           401: #endif /* INET */
        !           402:
        !           403: #ifdef INET6
        !           404:        case AF_INET6:
        !           405:                sunion.sin6.sin6_addr = ipa->ipa_info.sen_ip6_src;
        !           406:                sunion.sin6.sin6_port = ipa->ipa_info.sen_ip6_sport;
        !           407:                break;
        !           408: #endif /* INET6 */
        !           409:        }
        !           410:        export_address(&p, (struct sockaddr *) &sunion);
        !           411:
        !           412:        if (dir == IPSP_DIRECTION_OUT)
        !           413:                headers[SADB_X_EXT_SRC_MASK] = p;
        !           414:        else
        !           415:                headers[SADB_X_EXT_DST_MASK] = p;
        !           416:        switch (sunion.sa.sa_family) {
        !           417: #ifdef INET
        !           418:        case AF_INET:
        !           419:                sunion.sin.sin_addr = ipa->ipa_mask.sen_ip_src;
        !           420:                sunion.sin.sin_port = ipa->ipa_mask.sen_sport;
        !           421:                break;
        !           422: #endif /* INET */
        !           423:
        !           424: #ifdef INET6
        !           425:        case AF_INET6:
        !           426:                sunion.sin6.sin6_addr = ipa->ipa_mask.sen_ip6_src;
        !           427:                sunion.sin6.sin6_port = ipa->ipa_mask.sen_ip6_sport;
        !           428:                break;
        !           429: #endif /* INET6 */
        !           430:        }
        !           431:        export_address(&p, (struct sockaddr *) &sunion);
        !           432:
        !           433:        if (dir == IPSP_DIRECTION_OUT)
        !           434:                headers[SADB_X_EXT_DST_FLOW] = p;
        !           435:        else
        !           436:                headers[SADB_X_EXT_SRC_FLOW] = p;
        !           437:        switch (sunion.sa.sa_family) {
        !           438: #ifdef INET
        !           439:        case AF_INET:
        !           440:                sunion.sin.sin_addr = ipa->ipa_info.sen_ip_dst;
        !           441:                sunion.sin.sin_port = ipa->ipa_info.sen_dport;
        !           442:                break;
        !           443: #endif /* INET */
        !           444:
        !           445: #ifdef INET6
        !           446:        case AF_INET6:
        !           447:                sunion.sin6.sin6_addr = ipa->ipa_info.sen_ip6_dst;
        !           448:                sunion.sin6.sin6_port = ipa->ipa_info.sen_ip6_dport;
        !           449:                break;
        !           450: #endif /* INET6 */
        !           451:        }
        !           452:        export_address(&p, (struct sockaddr *) &sunion);
        !           453:
        !           454:        if (dir == IPSP_DIRECTION_OUT)
        !           455:                headers[SADB_X_EXT_DST_MASK] = p;
        !           456:        else
        !           457:                headers[SADB_X_EXT_SRC_MASK] = p;
        !           458:        switch (sunion.sa.sa_family) {
        !           459: #ifdef INET
        !           460:        case AF_INET:
        !           461:                sunion.sin.sin_addr = ipa->ipa_mask.sen_ip_dst;
        !           462:                sunion.sin.sin_port = ipa->ipa_mask.sen_dport;
        !           463:                break;
        !           464: #endif /* INET */
        !           465:
        !           466: #ifdef INET6
        !           467:        case AF_INET6:
        !           468:                sunion.sin6.sin6_addr = ipa->ipa_mask.sen_ip6_dst;
        !           469:                sunion.sin6.sin6_port = ipa->ipa_mask.sen_ip6_dport;
        !           470:                break;
        !           471: #endif /* INET6 */
        !           472:        }
        !           473:        export_address(&p, (struct sockaddr *) &sunion);
        !           474:
        !           475:        headers[SADB_X_EXT_FLOW_TYPE] = p;
        !           476:        sp = p;
        !           477:        sp->sadb_protocol_len = sizeof(struct sadb_protocol) /
        !           478:            sizeof(u_int64_t);
        !           479:        switch (sunion.sa.sa_family) {
        !           480: #ifdef INET
        !           481:        case AF_INET:
        !           482:                if (ipa->ipa_mask.sen_proto)
        !           483:                        sp->sadb_protocol_proto = ipa->ipa_info.sen_proto;
        !           484:                sp->sadb_protocol_direction = ipa->ipa_info.sen_direction;
        !           485:                break;
        !           486: #endif /* INET */
        !           487:
        !           488: #ifdef INET6
        !           489:        case AF_INET6:
        !           490:                if (ipa->ipa_mask.sen_ip6_proto)
        !           491:                        sp->sadb_protocol_proto = ipa->ipa_info.sen_ip6_proto;
        !           492:                sp->sadb_protocol_direction = ipa->ipa_info.sen_ip6_direction;
        !           493:                break;
        !           494: #endif /* INET6 */
        !           495:        }
        !           496:
        !           497:        rval = 0;
        !           498:
        !           499: ret:
        !           500:        return (rval);
        !           501: }
        !           502:
        !           503: /*
        !           504:  * Get all the information contained in an SA to a PFKEYV2 message.
        !           505:  */
        !           506: int
        !           507: pfkeyv2_get(struct tdb *sa, void **headers, void **buffer, int *lenp)
        !           508: {
        !           509:        int rval, i;
        !           510:        void *p;
        !           511:
        !           512:        /* Find how much space we need */
        !           513:        i = sizeof(struct sadb_sa) + sizeof(struct sadb_lifetime);
        !           514:
        !           515:        if (sa->tdb_soft_allocations || sa->tdb_soft_bytes ||
        !           516:            sa->tdb_soft_timeout || sa->tdb_soft_first_use)
        !           517:                i += sizeof(struct sadb_lifetime);
        !           518:
        !           519:        if (sa->tdb_exp_allocations || sa->tdb_exp_bytes ||
        !           520:            sa->tdb_exp_timeout || sa->tdb_exp_first_use)
        !           521:                i += sizeof(struct sadb_lifetime);
        !           522:
        !           523:        if (sa->tdb_last_used)
        !           524:                i += sizeof(struct sadb_lifetime);
        !           525:
        !           526:        if (sa->tdb_src.sa.sa_family)
        !           527:                i += sizeof(struct sadb_address) + PADUP(SA_LEN(&sa->tdb_src.sa));
        !           528:
        !           529:        if (sa->tdb_dst.sa.sa_family)
        !           530:                i += sizeof(struct sadb_address) + PADUP(SA_LEN(&sa->tdb_dst.sa));
        !           531:
        !           532:        if (sa->tdb_proxy.sa.sa_family)
        !           533:                i += sizeof(struct sadb_address) + PADUP(SA_LEN(&sa->tdb_proxy.sa));
        !           534:
        !           535:        if (sa->tdb_srcid)
        !           536:                i += PADUP(sa->tdb_srcid->ref_len) + sizeof(struct sadb_ident);
        !           537:
        !           538:        if (sa->tdb_dstid)
        !           539:                i += PADUP(sa->tdb_dstid->ref_len) + sizeof(struct sadb_ident);
        !           540:
        !           541:        if (sa->tdb_local_cred)
        !           542:                i += PADUP(sa->tdb_local_cred->ref_len) + sizeof(struct sadb_x_cred);
        !           543:
        !           544:        if (sa->tdb_remote_cred)
        !           545:                i += PADUP(sa->tdb_remote_cred->ref_len) + sizeof(struct sadb_x_cred);
        !           546:
        !           547:        if (sa->tdb_local_auth)
        !           548:                i += PADUP(sa->tdb_local_auth->ref_len) + sizeof(struct sadb_x_cred);
        !           549:
        !           550:        if (sa->tdb_remote_auth)
        !           551:                i += PADUP(sa->tdb_remote_auth->ref_len) + sizeof(struct sadb_x_cred);
        !           552:
        !           553:        if (sa->tdb_amxkey)
        !           554:                i+= PADUP(sa->tdb_amxkeylen) + sizeof(struct sadb_key);
        !           555:
        !           556:        if (sa->tdb_emxkey)
        !           557:                i+= PADUP(sa->tdb_emxkeylen) + sizeof(struct sadb_key);
        !           558:
        !           559:        if (sa->tdb_filter.sen_type) {
        !           560:                i += 2 * sizeof(struct sadb_protocol);
        !           561:
        !           562:                /* We'll need four of them: src, src mask, dst, dst mask. */
        !           563:                switch (sa->tdb_filter.sen_type) {
        !           564: #ifdef INET
        !           565:                case SENT_IP4:
        !           566:                        i += 4 * PADUP(sizeof(struct sockaddr_in));
        !           567:                        i += 4 * sizeof(struct sadb_address);
        !           568:                        break;
        !           569: #endif /* INET */
        !           570: #ifdef INET6
        !           571:                case SENT_IP6:
        !           572:                        i += 4 * PADUP(sizeof(struct sockaddr_in6));
        !           573:                        i += 4 * sizeof(struct sadb_address);
        !           574:                        break;
        !           575: #endif /* INET6 */
        !           576:                default:
        !           577:                        rval = EINVAL;
        !           578:                        goto ret;
        !           579:                }
        !           580:        }
        !           581:
        !           582:        if (sa->tdb_udpencap_port)
        !           583:                i+= sizeof(struct sadb_x_udpencap);
        !           584:
        !           585: #if NPF > 0
        !           586:        if (sa->tdb_tag)
        !           587:                i+= PADUP(PF_TAG_NAME_SIZE) + sizeof(struct sadb_x_tag);
        !           588: #endif
        !           589:
        !           590:        if (lenp)
        !           591:                *lenp = i;
        !           592:
        !           593:        if (buffer == NULL) {
        !           594:                rval = 0;
        !           595:                goto ret;
        !           596:        }
        !           597:
        !           598:        if (!(p = malloc(i, M_PFKEY, M_DONTWAIT))) {
        !           599:                rval = ENOMEM;
        !           600:                goto ret;
        !           601:        } else {
        !           602:                *buffer = p;
        !           603:                bzero(p, i);
        !           604:        }
        !           605:
        !           606:        headers[SADB_EXT_SA] = p;
        !           607:
        !           608:        export_sa(&p, sa);  /* Export SA information (mostly flags) */
        !           609:
        !           610:        /* Export lifetimes where applicable */
        !           611:        headers[SADB_EXT_LIFETIME_CURRENT] = p;
        !           612:        export_lifetime(&p, sa, PFKEYV2_LIFETIME_CURRENT);
        !           613:
        !           614:        if (sa->tdb_soft_allocations || sa->tdb_soft_bytes ||
        !           615:            sa->tdb_soft_first_use || sa->tdb_soft_timeout) {
        !           616:                headers[SADB_EXT_LIFETIME_SOFT] = p;
        !           617:                export_lifetime(&p, sa, PFKEYV2_LIFETIME_SOFT);
        !           618:        }
        !           619:
        !           620:        if (sa->tdb_exp_allocations || sa->tdb_exp_bytes ||
        !           621:            sa->tdb_exp_first_use || sa->tdb_exp_timeout) {
        !           622:                headers[SADB_EXT_LIFETIME_HARD] = p;
        !           623:                export_lifetime(&p, sa, PFKEYV2_LIFETIME_HARD);
        !           624:        }
        !           625:
        !           626:        if (sa->tdb_last_used) {
        !           627:                headers[SADB_X_EXT_LIFETIME_LASTUSE] = p;
        !           628:                export_lifetime(&p, sa, PFKEYV2_LIFETIME_LASTUSE);
        !           629:        }
        !           630:
        !           631:        /* Export TDB source address */
        !           632:        headers[SADB_EXT_ADDRESS_SRC] = p;
        !           633:        export_address(&p, (struct sockaddr *) &sa->tdb_src);
        !           634:
        !           635:        /* Export TDB destination address */
        !           636:        headers[SADB_EXT_ADDRESS_DST] = p;
        !           637:        export_address(&p, (struct sockaddr *) &sa->tdb_dst);
        !           638:
        !           639:        /* Export TDB proxy address, if present */
        !           640:        if (SA_LEN(&sa->tdb_proxy.sa)) {
        !           641:                headers[SADB_EXT_ADDRESS_PROXY] = p;
        !           642:                export_address(&p, (struct sockaddr *) &sa->tdb_proxy);
        !           643:        }
        !           644:
        !           645:        /* Export source identity, if present */
        !           646:        if (sa->tdb_srcid) {
        !           647:                headers[SADB_EXT_IDENTITY_SRC] = p;
        !           648:                export_identity(&p, sa, PFKEYV2_IDENTITY_SRC);
        !           649:        }
        !           650:
        !           651:        /* Export destination identity, if present */
        !           652:        if (sa->tdb_dstid) {
        !           653:                headers[SADB_EXT_IDENTITY_DST] = p;
        !           654:                export_identity(&p, sa, PFKEYV2_IDENTITY_DST);
        !           655:        }
        !           656:
        !           657:        /* Export credentials, if present */
        !           658:        if (sa->tdb_local_cred) {
        !           659:                headers[SADB_X_EXT_LOCAL_CREDENTIALS] = p;
        !           660:                export_credentials(&p, sa, PFKEYV2_CRED_LOCAL);
        !           661:        }
        !           662:
        !           663:        if (sa->tdb_remote_cred) {
        !           664:                headers[SADB_X_EXT_REMOTE_CREDENTIALS] = p;
        !           665:                export_credentials(&p, sa, PFKEYV2_CRED_REMOTE);
        !           666:        }
        !           667:
        !           668:        /* Export authentication information, if present */
        !           669:        if (sa->tdb_local_auth) {
        !           670:                headers[SADB_X_EXT_LOCAL_AUTH] = p;
        !           671:                export_auth(&p, sa, PFKEYV2_AUTH_LOCAL);
        !           672:        }
        !           673:
        !           674:        if (sa->tdb_remote_auth) {
        !           675:                headers[SADB_X_EXT_REMOTE_AUTH] = p;
        !           676:                export_auth(&p, sa, PFKEYV2_AUTH_REMOTE);
        !           677:        }
        !           678:
        !           679:        /* Export authentication key, if present */
        !           680:        if (sa->tdb_amxkey) {
        !           681:                headers[SADB_EXT_KEY_AUTH] = p;
        !           682:                export_key(&p, sa, PFKEYV2_AUTHENTICATION_KEY);
        !           683:        }
        !           684:
        !           685:        /* Export encryption key, if present */
        !           686:        if (sa->tdb_emxkey) {
        !           687:                headers[SADB_EXT_KEY_ENCRYPT] = p;
        !           688:                export_key(&p, sa, PFKEYV2_ENCRYPTION_KEY);
        !           689:        }
        !           690:
        !           691:        /* Export flow/filter, if present */
        !           692:        if (sa->tdb_filter.sen_type)
        !           693:                export_flow(&p, IPSP_IPSEC_USE, &sa->tdb_filter,
        !           694:                    &sa->tdb_filtermask, headers);
        !           695:
        !           696:        /* Export UDP encapsulation port, if present */
        !           697:        if (sa->tdb_udpencap_port) {
        !           698:                headers[SADB_X_EXT_UDPENCAP] = p;
        !           699:                export_udpencap(&p, sa);
        !           700:        }
        !           701:
        !           702: #if NPF > 0
        !           703:        /* Export tag information, if present */
        !           704:        if (sa->tdb_tag) {
        !           705:                headers[SADB_X_EXT_TAG] = p;
        !           706:                export_tag(&p, sa);
        !           707:        }
        !           708: #endif
        !           709:
        !           710:        rval = 0;
        !           711:
        !           712:  ret:
        !           713:        return (rval);
        !           714: }
        !           715:
        !           716: /*
        !           717:  * Dump a TDB.
        !           718:  */
        !           719: int
        !           720: pfkeyv2_dump_walker(struct tdb *sa, void *state, int last)
        !           721: {
        !           722:        struct dump_state *dump_state = (struct dump_state *) state;
        !           723:        void *headers[SADB_EXT_MAX+1], *buffer;
        !           724:        int rval;
        !           725:
        !           726:        /* If not satype was specified, dump all TDBs */
        !           727:        if (!dump_state->sadb_msg->sadb_msg_satype ||
        !           728:            (sa->tdb_satype == dump_state->sadb_msg->sadb_msg_satype)) {
        !           729:                bzero(headers, sizeof(headers));
        !           730:                headers[0] = (void *) dump_state->sadb_msg;
        !           731:
        !           732:                /* Get the information from the TDB to a PFKEYv2 message */
        !           733:                if ((rval = pfkeyv2_get(sa, headers, &buffer, NULL)) != 0)
        !           734:                        return (rval);
        !           735:
        !           736:                if (last)
        !           737:                        ((struct sadb_msg *)headers[0])->sadb_msg_seq = 0;
        !           738:
        !           739:                /* Send the message to the specified socket */
        !           740:                rval = pfkeyv2_sendmessage(headers,
        !           741:                    PFKEYV2_SENDMESSAGE_UNICAST, dump_state->socket, 0, 0);
        !           742:
        !           743:                free(buffer, M_PFKEY);
        !           744:                if (rval)
        !           745:                        return (rval);
        !           746:        }
        !           747:
        !           748:        return (0);
        !           749: }
        !           750:
        !           751: /*
        !           752:  * Delete an SA.
        !           753:  */
        !           754: int
        !           755: pfkeyv2_flush_walker(struct tdb *sa, void *satype_vp, int last)
        !           756: {
        !           757:        if (!(*((u_int8_t *) satype_vp)) ||
        !           758:            sa->tdb_satype == *((u_int8_t *) satype_vp))
        !           759:                tdb_delete(sa);
        !           760:        return (0);
        !           761: }
        !           762:
        !           763: /*
        !           764:  * Convert between SATYPEs and IPsec protocols, taking into consideration
        !           765:  * sysctl variables enabling/disabling ESP/AH and the presence of the old
        !           766:  * IPsec transforms.
        !           767:  */
        !           768: int
        !           769: pfkeyv2_get_proto_alg(u_int8_t satype, u_int8_t *sproto, int *alg)
        !           770: {
        !           771:        switch (satype) {
        !           772: #ifdef IPSEC
        !           773:        case SADB_SATYPE_AH:
        !           774:                if (!ah_enable)
        !           775:                        return (EOPNOTSUPP);
        !           776:
        !           777:                *sproto = IPPROTO_AH;
        !           778:
        !           779:                if(alg != NULL)
        !           780:                        *alg = satype = XF_AH;
        !           781:
        !           782:                break;
        !           783:
        !           784:        case SADB_SATYPE_ESP:
        !           785:                if (!esp_enable)
        !           786:                        return (EOPNOTSUPP);
        !           787:
        !           788:                *sproto = IPPROTO_ESP;
        !           789:
        !           790:                if(alg != NULL)
        !           791:                        *alg = satype = XF_ESP;
        !           792:
        !           793:                break;
        !           794:
        !           795:        case SADB_X_SATYPE_IPIP:
        !           796:                *sproto = IPPROTO_IPIP;
        !           797:
        !           798:                if (alg != NULL)
        !           799:                        *alg = XF_IP4;
        !           800:
        !           801:                break;
        !           802:
        !           803:        case SADB_X_SATYPE_IPCOMP:
        !           804:                if (!ipcomp_enable)
        !           805:                        return (EOPNOTSUPP);
        !           806:
        !           807:                *sproto = IPPROTO_IPCOMP;
        !           808:
        !           809:                if(alg != NULL)
        !           810:                        *alg = satype = XF_IPCOMP;
        !           811:
        !           812:                break;
        !           813: #endif /* IPSEC */
        !           814: #ifdef TCP_SIGNATURE
        !           815:        case SADB_X_SATYPE_TCPSIGNATURE:
        !           816:                *sproto = IPPROTO_TCP;
        !           817:
        !           818:                if (alg != NULL)
        !           819:                        *alg = XF_TCPSIGNATURE;
        !           820:
        !           821:                break;
        !           822: #endif /* TCP_SIGNATURE */
        !           823:
        !           824:        default: /* Nothing else supported */
        !           825:                return (EOPNOTSUPP);
        !           826:        }
        !           827:
        !           828:        return (0);
        !           829: }
        !           830:
        !           831: /*
        !           832:  * Handle all messages from userland to kernel.
        !           833:  */
        !           834: int
        !           835: pfkeyv2_send(struct socket *socket, void *message, int len)
        !           836: {
        !           837:        int i, j, rval = 0, mode = PFKEYV2_SENDMESSAGE_BROADCAST;
        !           838:        int delflag = 0, s;
        !           839:        struct sockaddr_encap encapdst, encapnetmask, encapgw;
        !           840:        struct ipsec_policy *ipo, *tmpipo;
        !           841:        struct ipsec_acquire *ipa;
        !           842:
        !           843:        struct pfkeyv2_socket *pfkeyv2_socket, *so = NULL;
        !           844:
        !           845:        void *freeme = NULL, *bckptr = NULL;
        !           846:        void *headers[SADB_EXT_MAX + 1];
        !           847:
        !           848:        union sockaddr_union *sunionp;
        !           849:
        !           850:        struct tdb sa, *sa2 = NULL;
        !           851:
        !           852:        struct sadb_msg *smsg;
        !           853:        struct sadb_spirange *sprng;
        !           854:        struct sadb_sa *ssa;
        !           855:        struct sadb_supported *ssup;
        !           856:        struct sadb_ident *sid;
        !           857:
        !           858:        /* Verify that we received this over a legitimate pfkeyv2 socket */
        !           859:        bzero(headers, sizeof(headers));
        !           860:
        !           861:        for (pfkeyv2_socket = pfkeyv2_sockets; pfkeyv2_socket;
        !           862:            pfkeyv2_socket = pfkeyv2_socket->next)
        !           863:                if (pfkeyv2_socket->socket == socket)
        !           864:                        break;
        !           865:
        !           866:        if (!pfkeyv2_socket) {
        !           867:                rval = EINVAL;
        !           868:                goto ret;
        !           869:        }
        !           870:
        !           871:        /* If we have any promiscuous listeners, send them a copy of the message */
        !           872:        if (npromisc) {
        !           873:                struct mbuf *packet;
        !           874:
        !           875:                if (!(freeme = malloc(sizeof(struct sadb_msg) + len, M_PFKEY,
        !           876:                    M_DONTWAIT))) {
        !           877:                        rval = ENOMEM;
        !           878:                        goto ret;
        !           879:                }
        !           880:
        !           881:                /* Initialize encapsulating header */
        !           882:                bzero(freeme, sizeof(struct sadb_msg));
        !           883:                smsg = (struct sadb_msg *) freeme;
        !           884:                smsg->sadb_msg_version = PF_KEY_V2;
        !           885:                smsg->sadb_msg_type = SADB_X_PROMISC;
        !           886:                smsg->sadb_msg_len = (sizeof(struct sadb_msg) + len) /
        !           887:                    sizeof(uint64_t);
        !           888:                smsg->sadb_msg_seq = curproc->p_pid;
        !           889:
        !           890:                bcopy(message, freeme + sizeof(struct sadb_msg), len);
        !           891:
        !           892:                /* Convert to mbuf chain */
        !           893:                if ((rval = pfdatatopacket(freeme,
        !           894:                    sizeof(struct sadb_msg) + len, &packet)) != 0)
        !           895:                        goto ret;
        !           896:
        !           897:                /* Send to all promiscuous listeners */
        !           898:                for (so = pfkeyv2_sockets; so; so = so->next)
        !           899:                        if (so->flags & PFKEYV2_SOCKETFLAGS_PROMISC)
        !           900:                                pfkey_sendup(so->socket, packet, 1);
        !           901:
        !           902:                /* Paranoid */
        !           903:                m_zero(packet);
        !           904:                m_freem(packet);
        !           905:
        !           906:                /* Even more paranoid */
        !           907:                bzero(freeme, sizeof(struct sadb_msg) + len);
        !           908:                free(freeme, M_PFKEY);
        !           909:                freeme = NULL;
        !           910:        }
        !           911:
        !           912:        /* Validate message format */
        !           913:        if ((rval = pfkeyv2_parsemessage(message, len, headers)) != 0)
        !           914:                goto ret;
        !           915:
        !           916:        smsg = (struct sadb_msg *) headers[0];
        !           917:        switch (smsg->sadb_msg_type) {
        !           918:        case SADB_GETSPI:  /* Reserve an SPI */
        !           919:                bzero(&sa, sizeof(struct tdb));
        !           920:
        !           921:                sa.tdb_satype = smsg->sadb_msg_satype;
        !           922:                if ((rval = pfkeyv2_get_proto_alg(sa.tdb_satype,
        !           923:                    &sa.tdb_sproto, 0)))
        !           924:                        goto ret;
        !           925:
        !           926:                import_address((struct sockaddr *) &sa.tdb_src,
        !           927:                    headers[SADB_EXT_ADDRESS_SRC]);
        !           928:                import_address((struct sockaddr *) &sa.tdb_dst,
        !           929:                    headers[SADB_EXT_ADDRESS_DST]);
        !           930:
        !           931:                /* Find an unused SA identifier */
        !           932:                sprng = (struct sadb_spirange *) headers[SADB_EXT_SPIRANGE];
        !           933:                sa.tdb_spi = reserve_spi(sprng->sadb_spirange_min,
        !           934:                    sprng->sadb_spirange_max, &sa.tdb_src, &sa.tdb_dst,
        !           935:                    sa.tdb_sproto, &rval);
        !           936:                if (sa.tdb_spi == 0)
        !           937:                        goto ret;
        !           938:
        !           939:                /* Send a message back telling what the SA (the SPI really) is */
        !           940:                if (!(freeme = malloc(sizeof(struct sadb_sa), M_PFKEY,
        !           941:                    M_DONTWAIT))) {
        !           942:                        rval = ENOMEM;
        !           943:                        goto ret;
        !           944:                }
        !           945:
        !           946:                bzero(freeme, sizeof(struct sadb_sa));
        !           947:                headers[SADB_EXT_SPIRANGE] = NULL;
        !           948:                headers[SADB_EXT_SA] = freeme;
        !           949:                bckptr = freeme;
        !           950:
        !           951:                /* We really only care about the SPI, but we'll export the SA */
        !           952:                export_sa((void **) &bckptr, &sa);
        !           953:                break;
        !           954:
        !           955:        case SADB_UPDATE:
        !           956:                ssa = (struct sadb_sa *) headers[SADB_EXT_SA];
        !           957:                sunionp = (union sockaddr_union *) (headers[SADB_EXT_ADDRESS_DST] +
        !           958:                    sizeof(struct sadb_address));
        !           959:
        !           960:                /* Either all or none of the flow must be included */
        !           961:                if ((headers[SADB_X_EXT_SRC_FLOW] ||
        !           962:                    headers[SADB_X_EXT_PROTOCOL] ||
        !           963:                    headers[SADB_X_EXT_FLOW_TYPE] ||
        !           964:                    headers[SADB_X_EXT_DST_FLOW] ||
        !           965:                    headers[SADB_X_EXT_SRC_MASK] ||
        !           966:                    headers[SADB_X_EXT_DST_MASK]) &&
        !           967:                    !(headers[SADB_X_EXT_SRC_FLOW] &&
        !           968:                    headers[SADB_X_EXT_PROTOCOL] &&
        !           969:                    headers[SADB_X_EXT_FLOW_TYPE] &&
        !           970:                    headers[SADB_X_EXT_DST_FLOW] &&
        !           971:                    headers[SADB_X_EXT_SRC_MASK] &&
        !           972:                    headers[SADB_X_EXT_DST_MASK])) {
        !           973:                        rval = EINVAL;
        !           974:                        goto ret;
        !           975:                }
        !           976: #ifdef IPSEC
        !           977:                /* UDP encap has to be enabled and is only supported for ESP */
        !           978:                if (headers[SADB_X_EXT_UDPENCAP] &&
        !           979:                    (!udpencap_enable ||
        !           980:                    smsg->sadb_msg_satype != SADB_SATYPE_ESP)) {
        !           981:                        rval = EINVAL;
        !           982:                        goto ret;
        !           983:                }
        !           984: #endif /* IPSEC */
        !           985:
        !           986:                s = spltdb();
        !           987:
        !           988:                /* Find TDB */
        !           989:                sa2 = gettdb(ssa->sadb_sa_spi, sunionp,
        !           990:                    SADB_X_GETSPROTO(smsg->sadb_msg_satype));
        !           991:
        !           992:                /* If there's no such SA, we're done */
        !           993:                if (sa2 == NULL) {
        !           994:                        rval = ESRCH;
        !           995:                        goto splxret;
        !           996:                }
        !           997:
        !           998:                /* If this is a reserved SA */
        !           999:                if (sa2->tdb_flags & TDBF_INVALID) {
        !          1000:                        struct tdb *newsa;
        !          1001:                        struct ipsecinit ii;
        !          1002:                        int alg;
        !          1003:
        !          1004:                        /* Create new TDB */
        !          1005:                        freeme = tdb_alloc();
        !          1006:                        bzero(&ii, sizeof(struct ipsecinit));
        !          1007:
        !          1008:                        newsa = (struct tdb *) freeme;
        !          1009:                        newsa->tdb_satype = smsg->sadb_msg_satype;
        !          1010:
        !          1011:                        if ((rval = pfkeyv2_get_proto_alg(newsa->tdb_satype,
        !          1012:                            &newsa->tdb_sproto, &alg))) {
        !          1013:                                tdb_free(freeme);
        !          1014:                                freeme = NULL;
        !          1015:                                goto splxret;
        !          1016:                        }
        !          1017:
        !          1018:                        /* Initialize SA */
        !          1019:                        import_sa(newsa, headers[SADB_EXT_SA], &ii);
        !          1020:                        import_address((struct sockaddr *) &newsa->tdb_src,
        !          1021:                            headers[SADB_EXT_ADDRESS_SRC]);
        !          1022:                        import_address((struct sockaddr *) &newsa->tdb_dst,
        !          1023:                            headers[SADB_EXT_ADDRESS_DST]);
        !          1024:                        import_address((struct sockaddr *) &newsa->tdb_proxy,
        !          1025:                            headers[SADB_EXT_ADDRESS_PROXY]);
        !          1026:                        import_lifetime(newsa,
        !          1027:                            headers[SADB_EXT_LIFETIME_CURRENT],
        !          1028:                            PFKEYV2_LIFETIME_CURRENT);
        !          1029:                        import_lifetime(newsa, headers[SADB_EXT_LIFETIME_SOFT],
        !          1030:                            PFKEYV2_LIFETIME_SOFT);
        !          1031:                        import_lifetime(newsa, headers[SADB_EXT_LIFETIME_HARD],
        !          1032:                            PFKEYV2_LIFETIME_HARD);
        !          1033:                        import_key(&ii, headers[SADB_EXT_KEY_AUTH],
        !          1034:                            PFKEYV2_AUTHENTICATION_KEY);
        !          1035:                        import_key(&ii, headers[SADB_EXT_KEY_ENCRYPT],
        !          1036:                            PFKEYV2_ENCRYPTION_KEY);
        !          1037:                        import_identity(newsa, headers[SADB_EXT_IDENTITY_SRC],
        !          1038:                            PFKEYV2_IDENTITY_SRC);
        !          1039:                        import_identity(newsa, headers[SADB_EXT_IDENTITY_DST],
        !          1040:                            PFKEYV2_IDENTITY_DST);
        !          1041:                        import_credentials(newsa,
        !          1042:                            headers[SADB_X_EXT_LOCAL_CREDENTIALS],
        !          1043:                            PFKEYV2_CRED_LOCAL);
        !          1044:                        import_credentials(newsa,
        !          1045:                            headers[SADB_X_EXT_REMOTE_CREDENTIALS],
        !          1046:                            PFKEYV2_CRED_REMOTE);
        !          1047:                        import_auth(newsa, headers[SADB_X_EXT_LOCAL_AUTH],
        !          1048:                            PFKEYV2_AUTH_LOCAL);
        !          1049:                        import_auth(newsa, headers[SADB_X_EXT_REMOTE_AUTH],
        !          1050:                            PFKEYV2_AUTH_REMOTE);
        !          1051:                        import_flow(&newsa->tdb_filter, &newsa->tdb_filtermask,
        !          1052:                            headers[SADB_X_EXT_SRC_FLOW],
        !          1053:                            headers[SADB_X_EXT_SRC_MASK],
        !          1054:                            headers[SADB_X_EXT_DST_FLOW],
        !          1055:                            headers[SADB_X_EXT_DST_MASK],
        !          1056:                            headers[SADB_X_EXT_PROTOCOL],
        !          1057:                            headers[SADB_X_EXT_FLOW_TYPE]);
        !          1058:                        import_udpencap(newsa, headers[SADB_X_EXT_UDPENCAP]);
        !          1059: #if NPF > 0
        !          1060:                        import_tag(newsa, headers[SADB_X_EXT_TAG]);
        !          1061: #endif
        !          1062:
        !          1063:                        headers[SADB_EXT_KEY_AUTH] = NULL;
        !          1064:                        headers[SADB_EXT_KEY_ENCRYPT] = NULL;
        !          1065:                        headers[SADB_X_EXT_LOCAL_AUTH] = NULL;
        !          1066:
        !          1067:                        newsa->tdb_seq = smsg->sadb_msg_seq;
        !          1068:
        !          1069:                        rval = tdb_init(newsa, alg, &ii);
        !          1070:                        if (rval) {
        !          1071:                                rval = EINVAL;
        !          1072:                                tdb_free(freeme);
        !          1073:                                freeme = NULL;
        !          1074:                                goto splxret;
        !          1075:                        }
        !          1076:
        !          1077:                        newsa->tdb_cur_allocations = sa2->tdb_cur_allocations;
        !          1078:
        !          1079:                        /* Delete old version of the SA, insert new one */
        !          1080:                        tdb_delete(sa2);
        !          1081:                        puttdb((struct tdb *) freeme);
        !          1082:                        sa2 = freeme = NULL;
        !          1083:                } else {
        !          1084:                        /*
        !          1085:                         * The SA is already initialized, so we're only allowed to
        !          1086:                         * change lifetimes and some other information; we're
        !          1087:                         * not allowed to change keys, addresses or identities.
        !          1088:                         */
        !          1089:                        if (headers[SADB_EXT_ADDRESS_PROXY] ||
        !          1090:                            headers[SADB_EXT_KEY_AUTH] ||
        !          1091:                            headers[SADB_EXT_KEY_ENCRYPT] ||
        !          1092:                            headers[SADB_EXT_IDENTITY_SRC] ||
        !          1093:                            headers[SADB_EXT_IDENTITY_DST] ||
        !          1094:                            headers[SADB_EXT_SENSITIVITY]) {
        !          1095:                                rval = EINVAL;
        !          1096:                                goto splxret;
        !          1097:                        }
        !          1098:
        !          1099:                        import_sa(sa2, headers[SADB_EXT_SA], NULL);
        !          1100:                        import_lifetime(sa2,
        !          1101:                            headers[SADB_EXT_LIFETIME_CURRENT],
        !          1102:                            PFKEYV2_LIFETIME_CURRENT);
        !          1103:                        import_lifetime(sa2, headers[SADB_EXT_LIFETIME_SOFT],
        !          1104:                            PFKEYV2_LIFETIME_SOFT);
        !          1105:                        import_lifetime(sa2, headers[SADB_EXT_LIFETIME_HARD],
        !          1106:                            PFKEYV2_LIFETIME_HARD);
        !          1107:                        import_udpencap(sa2, headers[SADB_X_EXT_UDPENCAP]);
        !          1108: #if NPF > 0
        !          1109:                        import_tag(sa2, headers[SADB_X_EXT_TAG]);
        !          1110: #endif
        !          1111:                }
        !          1112:
        !          1113:                splx(s);
        !          1114:                break;
        !          1115:        case SADB_ADD:
        !          1116:                ssa = (struct sadb_sa *) headers[SADB_EXT_SA];
        !          1117:                sunionp = (union sockaddr_union *) (headers[SADB_EXT_ADDRESS_DST] +
        !          1118:                    sizeof(struct sadb_address));
        !          1119:
        !          1120:                /* Either all or none of the flow must be included */
        !          1121:                if ((headers[SADB_X_EXT_SRC_FLOW] ||
        !          1122:                    headers[SADB_X_EXT_PROTOCOL] ||
        !          1123:                    headers[SADB_X_EXT_FLOW_TYPE] ||
        !          1124:                    headers[SADB_X_EXT_DST_FLOW] ||
        !          1125:                    headers[SADB_X_EXT_SRC_MASK] ||
        !          1126:                    headers[SADB_X_EXT_DST_MASK]) &&
        !          1127:                    !(headers[SADB_X_EXT_SRC_FLOW] &&
        !          1128:                    headers[SADB_X_EXT_PROTOCOL] &&
        !          1129:                    headers[SADB_X_EXT_FLOW_TYPE] &&
        !          1130:                    headers[SADB_X_EXT_DST_FLOW] &&
        !          1131:                    headers[SADB_X_EXT_SRC_MASK] &&
        !          1132:                    headers[SADB_X_EXT_DST_MASK])) {
        !          1133:                        rval = EINVAL;
        !          1134:                        goto ret;
        !          1135:                }
        !          1136: #ifdef IPSEC
        !          1137:                /* UDP encap has to be enabled and is only supported for ESP */
        !          1138:                if (headers[SADB_X_EXT_UDPENCAP] &&
        !          1139:                    (!udpencap_enable ||
        !          1140:                    smsg->sadb_msg_satype != SADB_SATYPE_ESP)) {
        !          1141:                        rval = EINVAL;
        !          1142:                        goto ret;
        !          1143:                }
        !          1144: #endif /* IPSEC */
        !          1145:
        !          1146:                s = spltdb();
        !          1147:
        !          1148:                sa2 = gettdb(ssa->sadb_sa_spi, sunionp,
        !          1149:                    SADB_X_GETSPROTO(smsg->sadb_msg_satype));
        !          1150:
        !          1151:                /* We can't add an existing SA! */
        !          1152:                if (sa2 != NULL) {
        !          1153:                        rval = EEXIST;
        !          1154:                        goto splxret;
        !          1155:                }
        !          1156:
        !          1157:                /* We can only add "mature" SAs */
        !          1158:                if (ssa->sadb_sa_state != SADB_SASTATE_MATURE) {
        !          1159:                        rval = EINVAL;
        !          1160:                        goto splxret;
        !          1161:                }
        !          1162:
        !          1163:                /* Allocate and initialize new TDB */
        !          1164:                freeme = tdb_alloc();
        !          1165:
        !          1166:                {
        !          1167:                        struct tdb *newsa = (struct tdb *) freeme;
        !          1168:                        struct ipsecinit ii;
        !          1169:                        int alg;
        !          1170:
        !          1171:                        bzero(&ii, sizeof(struct ipsecinit));
        !          1172:
        !          1173:                        newsa->tdb_satype = smsg->sadb_msg_satype;
        !          1174:                        if ((rval = pfkeyv2_get_proto_alg(newsa->tdb_satype,
        !          1175:                            &newsa->tdb_sproto, &alg))) {
        !          1176:                                tdb_free(freeme);
        !          1177:                                freeme = NULL;
        !          1178:                                goto splxret;
        !          1179:                        }
        !          1180:
        !          1181:                        import_sa(newsa, headers[SADB_EXT_SA], &ii);
        !          1182:                        import_address((struct sockaddr *) &newsa->tdb_src,
        !          1183:                            headers[SADB_EXT_ADDRESS_SRC]);
        !          1184:                        import_address((struct sockaddr *) &newsa->tdb_dst,
        !          1185:                            headers[SADB_EXT_ADDRESS_DST]);
        !          1186:                        import_address((struct sockaddr *) &newsa->tdb_proxy,
        !          1187:                            headers[SADB_EXT_ADDRESS_PROXY]);
        !          1188:
        !          1189:                        import_lifetime(newsa,
        !          1190:                            headers[SADB_EXT_LIFETIME_CURRENT],
        !          1191:                            PFKEYV2_LIFETIME_CURRENT);
        !          1192:                        import_lifetime(newsa, headers[SADB_EXT_LIFETIME_SOFT],
        !          1193:                            PFKEYV2_LIFETIME_SOFT);
        !          1194:                        import_lifetime(newsa, headers[SADB_EXT_LIFETIME_HARD],
        !          1195:                            PFKEYV2_LIFETIME_HARD);
        !          1196:
        !          1197:                        import_key(&ii, headers[SADB_EXT_KEY_AUTH],
        !          1198:                            PFKEYV2_AUTHENTICATION_KEY);
        !          1199:                        import_key(&ii, headers[SADB_EXT_KEY_ENCRYPT],
        !          1200:                            PFKEYV2_ENCRYPTION_KEY);
        !          1201:
        !          1202:                        import_identity(newsa, headers[SADB_EXT_IDENTITY_SRC],
        !          1203:                            PFKEYV2_IDENTITY_SRC);
        !          1204:                        import_identity(newsa, headers[SADB_EXT_IDENTITY_DST],
        !          1205:                            PFKEYV2_IDENTITY_DST);
        !          1206:
        !          1207:                        import_credentials(newsa,
        !          1208:                            headers[SADB_X_EXT_LOCAL_CREDENTIALS],
        !          1209:                            PFKEYV2_CRED_LOCAL);
        !          1210:                        import_credentials(newsa,
        !          1211:                            headers[SADB_X_EXT_REMOTE_CREDENTIALS],
        !          1212:                            PFKEYV2_CRED_REMOTE);
        !          1213:                        import_auth(newsa, headers[SADB_X_EXT_LOCAL_AUTH],
        !          1214:                            PFKEYV2_AUTH_LOCAL);
        !          1215:                        import_auth(newsa, headers[SADB_X_EXT_REMOTE_AUTH],
        !          1216:                            PFKEYV2_AUTH_REMOTE);
        !          1217:                        import_flow(&newsa->tdb_filter, &newsa->tdb_filtermask,
        !          1218:                            headers[SADB_X_EXT_SRC_FLOW],
        !          1219:                            headers[SADB_X_EXT_SRC_MASK],
        !          1220:                            headers[SADB_X_EXT_DST_FLOW],
        !          1221:                            headers[SADB_X_EXT_DST_MASK],
        !          1222:                            headers[SADB_X_EXT_PROTOCOL],
        !          1223:                            headers[SADB_X_EXT_FLOW_TYPE]);
        !          1224:                        import_udpencap(newsa, headers[SADB_X_EXT_UDPENCAP]);
        !          1225: #if NPF > 0
        !          1226:                        import_tag(newsa, headers[SADB_X_EXT_TAG]);
        !          1227: #endif
        !          1228:
        !          1229:                        headers[SADB_EXT_KEY_AUTH] = NULL;
        !          1230:                        headers[SADB_EXT_KEY_ENCRYPT] = NULL;
        !          1231:                        headers[SADB_X_EXT_LOCAL_AUTH] = NULL;
        !          1232:
        !          1233:                        newsa->tdb_seq = smsg->sadb_msg_seq;
        !          1234:
        !          1235:                        rval = tdb_init(newsa, alg, &ii);
        !          1236:                        if (rval) {
        !          1237:                                rval = EINVAL;
        !          1238:                                tdb_free(freeme);
        !          1239:                                freeme = NULL;
        !          1240:                                goto splxret;
        !          1241:                        }
        !          1242:                }
        !          1243:
        !          1244:                /* Add TDB in table */
        !          1245:                puttdb((struct tdb *) freeme);
        !          1246:
        !          1247:                splx(s);
        !          1248:
        !          1249:                freeme = NULL;
        !          1250:                break;
        !          1251:
        !          1252:        case SADB_DELETE:
        !          1253:                ssa = (struct sadb_sa *) headers[SADB_EXT_SA];
        !          1254:                sunionp =
        !          1255:                    (union sockaddr_union *)(headers[SADB_EXT_ADDRESS_DST] +
        !          1256:                        sizeof(struct sadb_address));
        !          1257:                s = spltdb();
        !          1258:
        !          1259:                sa2 = gettdb(ssa->sadb_sa_spi, sunionp,
        !          1260:                    SADB_X_GETSPROTO(smsg->sadb_msg_satype));
        !          1261:                if (sa2 == NULL) {
        !          1262:                        rval = ESRCH;
        !          1263:                        goto splxret;
        !          1264:                }
        !          1265:
        !          1266:                tdb_delete(sa2);
        !          1267:
        !          1268:                splx(s);
        !          1269:
        !          1270:                sa2 = NULL;
        !          1271:                break;
        !          1272:
        !          1273:        case SADB_X_ASKPOLICY:
        !          1274:                /* Get the relevant policy */
        !          1275:                ipa = ipsec_get_acquire(((struct sadb_x_policy *) headers[SADB_X_EXT_POLICY])->sadb_x_policy_seq);
        !          1276:                if (ipa == NULL) {
        !          1277:                        rval = ESRCH;
        !          1278:                        goto ret;
        !          1279:                }
        !          1280:
        !          1281:                rval = pfkeyv2_policy(ipa, headers, &freeme);
        !          1282:                if (rval)
        !          1283:                        mode = PFKEYV2_SENDMESSAGE_UNICAST;
        !          1284:
        !          1285:                break;
        !          1286:
        !          1287:        case SADB_GET:
        !          1288:                ssa = (struct sadb_sa *) headers[SADB_EXT_SA];
        !          1289:                sunionp =
        !          1290:                    (union sockaddr_union *)(headers[SADB_EXT_ADDRESS_DST] +
        !          1291:                        sizeof(struct sadb_address));
        !          1292:
        !          1293:                s = spltdb();
        !          1294:
        !          1295:                sa2 = gettdb(ssa->sadb_sa_spi, sunionp,
        !          1296:                    SADB_X_GETSPROTO(smsg->sadb_msg_satype));
        !          1297:                if (sa2 == NULL) {
        !          1298:                        rval = ESRCH;
        !          1299:                        goto splxret;
        !          1300:                }
        !          1301:
        !          1302:                rval = pfkeyv2_get(sa2, headers, &freeme, NULL);
        !          1303:                if (rval)
        !          1304:                        mode = PFKEYV2_SENDMESSAGE_UNICAST;
        !          1305:
        !          1306:                splx(s);
        !          1307:
        !          1308:                break;
        !          1309:
        !          1310:        case SADB_REGISTER:
        !          1311:                if (!(pfkeyv2_socket->flags & PFKEYV2_SOCKETFLAGS_REGISTERED)) {
        !          1312:                        pfkeyv2_socket->flags |= PFKEYV2_SOCKETFLAGS_REGISTERED;
        !          1313:                        nregistered++;
        !          1314:                }
        !          1315:
        !          1316:                i = sizeof(struct sadb_supported) + sizeof(ealgs);
        !          1317:
        !          1318:                if (!(freeme = malloc(i, M_PFKEY, M_DONTWAIT))) {
        !          1319:                        rval = ENOMEM;
        !          1320:                        goto ret;
        !          1321:                }
        !          1322:
        !          1323:                bzero(freeme, i);
        !          1324:
        !          1325:                ssup = (struct sadb_supported *) freeme;
        !          1326:                ssup->sadb_supported_len = i / sizeof(uint64_t);
        !          1327:
        !          1328:                {
        !          1329:                        void *p = freeme + sizeof(struct sadb_supported);
        !          1330:
        !          1331:                        bcopy(&ealgs[0], p, sizeof(ealgs));
        !          1332:                }
        !          1333:
        !          1334:                headers[SADB_EXT_SUPPORTED_ENCRYPT] = freeme;
        !          1335:
        !          1336:                i = sizeof(struct sadb_supported) + sizeof(aalgs);
        !          1337:
        !          1338:                if (!(freeme = malloc(i, M_PFKEY, M_DONTWAIT))) {
        !          1339:                        rval = ENOMEM;
        !          1340:                        goto ret;
        !          1341:                }
        !          1342:
        !          1343:                /* Keep track what this socket has registered for */
        !          1344:                pfkeyv2_socket->registration |= (1 << ((struct sadb_msg *)message)->sadb_msg_satype);
        !          1345:
        !          1346:                bzero(freeme, i);
        !          1347:
        !          1348:                ssup = (struct sadb_supported *) freeme;
        !          1349:                ssup->sadb_supported_len = i / sizeof(uint64_t);
        !          1350:
        !          1351:                {
        !          1352:                        void *p = freeme + sizeof(struct sadb_supported);
        !          1353:
        !          1354:                        bcopy(&aalgs[0], p, sizeof(aalgs));
        !          1355:                }
        !          1356:
        !          1357:                headers[SADB_EXT_SUPPORTED_AUTH] = freeme;
        !          1358:
        !          1359:                i = sizeof(struct sadb_supported) + sizeof(calgs);
        !          1360:
        !          1361:                if (!(freeme = malloc(i, M_PFKEY, M_DONTWAIT))) {
        !          1362:                        rval = ENOMEM;
        !          1363:                        goto ret;
        !          1364:                }
        !          1365:
        !          1366:                bzero(freeme, i);
        !          1367:
        !          1368:                ssup = (struct sadb_supported *) freeme;
        !          1369:                ssup->sadb_supported_len = i / sizeof(uint64_t);
        !          1370:
        !          1371:                {
        !          1372:                        void *p = freeme + sizeof(struct sadb_supported);
        !          1373:
        !          1374:                        bcopy(&calgs[0], p, sizeof(calgs));
        !          1375:                }
        !          1376:
        !          1377:                headers[SADB_X_EXT_SUPPORTED_COMP] = freeme;
        !          1378:
        !          1379:                break;
        !          1380:
        !          1381:        case SADB_ACQUIRE:
        !          1382:        case SADB_EXPIRE:
        !          1383:                /* Nothing to handle */
        !          1384:                rval = 0;
        !          1385:                break;
        !          1386:
        !          1387:        case SADB_FLUSH:
        !          1388:                rval = 0;
        !          1389:
        !          1390:                switch (smsg->sadb_msg_satype) {
        !          1391:                case SADB_SATYPE_UNSPEC:
        !          1392:                        s = spltdb();
        !          1393:
        !          1394:                        /*
        !          1395:                         * Go through the list of policies, delete those that
        !          1396:                         * are not socket-attached.
        !          1397:                         */
        !          1398:                        for (ipo = TAILQ_FIRST(&ipsec_policy_head);
        !          1399:                            ipo != NULL; ipo = tmpipo) {
        !          1400:                                tmpipo = TAILQ_NEXT(ipo, ipo_list);
        !          1401:                                if (!(ipo->ipo_flags & IPSP_POLICY_SOCKET))
        !          1402:                                        ipsec_delete_policy(ipo);
        !          1403:                        }
        !          1404:                        splx(s);
        !          1405:                        /* FALLTHROUGH */
        !          1406:                case SADB_SATYPE_AH:
        !          1407:                case SADB_SATYPE_ESP:
        !          1408:                case SADB_X_SATYPE_IPIP:
        !          1409:                case SADB_X_SATYPE_IPCOMP:
        !          1410: #ifdef TCP_SIGNATURE
        !          1411:                case SADB_X_SATYPE_TCPSIGNATURE:
        !          1412: #endif /* TCP_SIGNATURE */
        !          1413:                        s = spltdb();
        !          1414:
        !          1415:                        tdb_walk(pfkeyv2_flush_walker,
        !          1416:                            (u_int8_t *) &(smsg->sadb_msg_satype));
        !          1417:
        !          1418:                        splx(s);
        !          1419:                        break;
        !          1420:
        !          1421:                default:
        !          1422:                        rval = EINVAL; /* Unknown/unsupported type */
        !          1423:                }
        !          1424:
        !          1425:                break;
        !          1426:
        !          1427:        case SADB_DUMP:
        !          1428:        {
        !          1429:                struct dump_state dump_state;
        !          1430:                dump_state.sadb_msg = (struct sadb_msg *) headers[0];
        !          1431:                dump_state.socket = socket;
        !          1432:
        !          1433:                s = spltdb();
        !          1434:                rval = tdb_walk(pfkeyv2_dump_walker, &dump_state);
        !          1435:                splx(s);
        !          1436:
        !          1437:                if (!rval)
        !          1438:                        goto realret;
        !          1439:
        !          1440:                if ((rval == ENOMEM) || (rval == ENOBUFS))
        !          1441:                        rval = 0;
        !          1442:        }
        !          1443:        break;
        !          1444:
        !          1445:        case SADB_X_GRPSPIS:
        !          1446:        {
        !          1447:                struct tdb *tdb1, *tdb2, *tdb3;
        !          1448:                struct sadb_protocol *sa_proto;
        !          1449:
        !          1450:                ssa = (struct sadb_sa *) headers[SADB_EXT_SA];
        !          1451:                sunionp = (union sockaddr_union *) (headers[SADB_EXT_ADDRESS_DST] +
        !          1452:                    sizeof(struct sadb_address));
        !          1453:
        !          1454:                s = spltdb();
        !          1455:
        !          1456:                tdb1 = gettdb(ssa->sadb_sa_spi, sunionp,
        !          1457:                    SADB_X_GETSPROTO(smsg->sadb_msg_satype));
        !          1458:                if (tdb1 == NULL) {
        !          1459:                        rval = ESRCH;
        !          1460:                        goto splxret;
        !          1461:                }
        !          1462:
        !          1463:                ssa = (struct sadb_sa *) headers[SADB_X_EXT_SA2];
        !          1464:                sunionp = (union sockaddr_union *) (headers[SADB_X_EXT_DST2] +
        !          1465:                    sizeof(struct sadb_address));
        !          1466:                sa_proto = ((struct sadb_protocol *) headers[SADB_X_EXT_PROTOCOL]);
        !          1467:
        !          1468:                tdb2 = gettdb(ssa->sadb_sa_spi, sunionp,
        !          1469:                    SADB_X_GETSPROTO(sa_proto->sadb_protocol_proto));
        !          1470:                if (tdb2 == NULL) {
        !          1471:                        rval = ESRCH;
        !          1472:                        goto splxret;
        !          1473:                }
        !          1474:
        !          1475:                /* Detect cycles */
        !          1476:                for (tdb3 = tdb2; tdb3; tdb3 = tdb3->tdb_onext)
        !          1477:                        if (tdb3 == tdb1) {
        !          1478:                                rval = ESRCH;
        !          1479:                                goto splxret;
        !          1480:                        }
        !          1481:
        !          1482:                /* Maintenance */
        !          1483:                if ((tdb1->tdb_onext) &&
        !          1484:                    (tdb1->tdb_onext->tdb_inext == tdb1))
        !          1485:                        tdb1->tdb_onext->tdb_inext = NULL;
        !          1486:
        !          1487:                if ((tdb2->tdb_inext) &&
        !          1488:                    (tdb2->tdb_inext->tdb_onext == tdb2))
        !          1489:                        tdb2->tdb_inext->tdb_onext = NULL;
        !          1490:
        !          1491:                /* Link them */
        !          1492:                tdb1->tdb_onext = tdb2;
        !          1493:                tdb2->tdb_inext = tdb1;
        !          1494:
        !          1495:                splx(s);
        !          1496:        }
        !          1497:        break;
        !          1498:
        !          1499:        case SADB_X_DELFLOW:
        !          1500:                delflag = 1;
        !          1501:                /*FALLTHROUGH*/
        !          1502:        case SADB_X_ADDFLOW:
        !          1503:        {
        !          1504:                struct sadb_protocol *sab;
        !          1505:                union sockaddr_union *ssrc;
        !          1506:                struct route_enc re;
        !          1507:                int exists = 0;
        !          1508:
        !          1509:                sab = (struct sadb_protocol *) headers[SADB_X_EXT_FLOW_TYPE];
        !          1510:
        !          1511:                if ((sab->sadb_protocol_direction != IPSP_DIRECTION_IN) &&
        !          1512:                    (sab->sadb_protocol_direction != IPSP_DIRECTION_OUT)) {
        !          1513:                        rval = EINVAL;
        !          1514:                        goto ret;
        !          1515:                }
        !          1516:
        !          1517:                /* If the security protocol wasn't specified, pretend it was ESP */
        !          1518:                if (smsg->sadb_msg_satype == 0)
        !          1519:                        smsg->sadb_msg_satype = SADB_SATYPE_ESP;
        !          1520:
        !          1521:                if (headers[SADB_EXT_ADDRESS_DST])
        !          1522:                        sunionp = (union sockaddr_union *)
        !          1523:                            (headers[SADB_EXT_ADDRESS_DST] +
        !          1524:                                sizeof(struct sadb_address));
        !          1525:                else
        !          1526:                        sunionp = NULL;
        !          1527:
        !          1528:                if (headers[SADB_EXT_ADDRESS_SRC])
        !          1529:                        ssrc = (union sockaddr_union *)
        !          1530:                            (headers[SADB_EXT_ADDRESS_SRC] +
        !          1531:                                sizeof(struct sadb_address));
        !          1532:                else
        !          1533:                        ssrc = NULL;
        !          1534:
        !          1535:                import_flow(&encapdst, &encapnetmask,
        !          1536:                    headers[SADB_X_EXT_SRC_FLOW], headers[SADB_X_EXT_SRC_MASK],
        !          1537:                    headers[SADB_X_EXT_DST_FLOW], headers[SADB_X_EXT_DST_MASK],
        !          1538:                    headers[SADB_X_EXT_PROTOCOL], headers[SADB_X_EXT_FLOW_TYPE]);
        !          1539:
        !          1540:                /* Determine whether the exact same SPD entry already exists. */
        !          1541:                bzero(&encapgw, sizeof(struct sockaddr_encap));
        !          1542:                bzero(&re, sizeof(struct route_enc));
        !          1543:                bcopy(&encapdst, &re.re_dst, sizeof(struct sockaddr_encap));
        !          1544:
        !          1545:                s = spltdb();
        !          1546:
        !          1547:                rtalloc((struct route *) &re);
        !          1548:                if (re.re_rt != NULL) {
        !          1549:                        ipo = ((struct sockaddr_encap *) re.re_rt->rt_gateway)->sen_ipsp;
        !          1550:                        RTFREE(re.re_rt);
        !          1551:
        !          1552:                        /* Verify that the entry is identical */
        !          1553:                        if (bcmp(&ipo->ipo_addr, &encapdst,
        !          1554:                                sizeof(struct sockaddr_encap)) ||
        !          1555:                            bcmp(&ipo->ipo_mask, &encapnetmask,
        !          1556:                                sizeof(struct sockaddr_encap)))
        !          1557:                                ipo = NULL; /* Fall through */
        !          1558:                        else
        !          1559:                                exists = 1;
        !          1560:                } else
        !          1561:                        ipo = NULL;
        !          1562:
        !          1563:                /*
        !          1564:                 * If the existing policy is static, only delete or update
        !          1565:                 * it if the new one is also static.
        !          1566:                 */
        !          1567:                if (exists && (ipo->ipo_flags & IPSP_POLICY_STATIC)) {
        !          1568:                        if (!(sab->sadb_protocol_flags &
        !          1569:                                SADB_X_POLICYFLAGS_POLICY)) {
        !          1570:                                splx(s);
        !          1571:                                goto ret;
        !          1572:                        }
        !          1573:                }
        !          1574:
        !          1575:                /* Delete ? */
        !          1576:                if (delflag) {
        !          1577:                        if (exists) {
        !          1578:                                rval = ipsec_delete_policy(ipo);
        !          1579:                                splx(s);
        !          1580:                                goto ret;
        !          1581:                        }
        !          1582:
        !          1583:                        /* If we were asked to delete something non-existant, error. */
        !          1584:                        splx(s);
        !          1585:                        rval = ESRCH;
        !          1586:                        break;
        !          1587:                }
        !          1588:
        !          1589:                if (!exists) {
        !          1590:                        if (ipsec_policy_pool_initialized == 0) {
        !          1591:                                ipsec_policy_pool_initialized = 1;
        !          1592:                                pool_init(&ipsec_policy_pool,
        !          1593:                                    sizeof(struct ipsec_policy), 0, 0, 0,
        !          1594:                                    "ipsec policy", NULL);
        !          1595:                        }
        !          1596:
        !          1597:                        /* Allocate policy entry */
        !          1598:                        ipo = pool_get(&ipsec_policy_pool, 0);
        !          1599:                        if (ipo == NULL) {
        !          1600:                                splx(s);
        !          1601:                                rval = ENOMEM;
        !          1602:                                goto ret;
        !          1603:                        }
        !          1604:
        !          1605:                        bzero(ipo, sizeof(struct ipsec_policy));
        !          1606:                        ipo->ipo_ref_count = 1;
        !          1607:                        TAILQ_INIT(&ipo->ipo_acquires);
        !          1608:
        !          1609:                        /* Finish initialization of SPD entry */
        !          1610:                        encapgw.sen_len = SENT_LEN;
        !          1611:                        encapgw.sen_family = PF_KEY;
        !          1612:                        encapgw.sen_type = SENT_IPSP;
        !          1613:                        encapgw.sen_ipsp = ipo;
        !          1614:
        !          1615:                        /* Initialize policy entry */
        !          1616:                        bcopy(&encapdst, &ipo->ipo_addr,
        !          1617:                            sizeof(struct sockaddr_encap));
        !          1618:                        bcopy(&encapnetmask, &ipo->ipo_mask,
        !          1619:                            sizeof(struct sockaddr_encap));
        !          1620:                }
        !          1621:
        !          1622:                switch (((struct sadb_protocol *) headers[SADB_X_EXT_FLOW_TYPE])->sadb_protocol_proto) {
        !          1623:                case SADB_X_FLOW_TYPE_USE:
        !          1624:                        ipo->ipo_type = IPSP_IPSEC_USE;
        !          1625:                        break;
        !          1626:
        !          1627:                case SADB_X_FLOW_TYPE_ACQUIRE:
        !          1628:                        ipo->ipo_type = IPSP_IPSEC_ACQUIRE;
        !          1629:                        break;
        !          1630:
        !          1631:                case SADB_X_FLOW_TYPE_REQUIRE:
        !          1632:                        ipo->ipo_type = IPSP_IPSEC_REQUIRE;
        !          1633:                        break;
        !          1634:
        !          1635:                case SADB_X_FLOW_TYPE_DENY:
        !          1636:                        ipo->ipo_type = IPSP_DENY;
        !          1637:                        break;
        !          1638:
        !          1639:                case SADB_X_FLOW_TYPE_BYPASS:
        !          1640:                        ipo->ipo_type = IPSP_PERMIT;
        !          1641:                        break;
        !          1642:
        !          1643:                case SADB_X_FLOW_TYPE_DONTACQ:
        !          1644:                        ipo->ipo_type = IPSP_IPSEC_DONTACQ;
        !          1645:                        break;
        !          1646:
        !          1647:                default:
        !          1648:                        if (!exists)
        !          1649:                                pool_put(&ipsec_policy_pool, ipo);
        !          1650:                        else
        !          1651:                                ipsec_delete_policy(ipo);
        !          1652:
        !          1653:                        splx(s);
        !          1654:                        rval = EINVAL;
        !          1655:                        goto ret;
        !          1656:                }
        !          1657:
        !          1658:                if (sab->sadb_protocol_flags & SADB_X_POLICYFLAGS_POLICY)
        !          1659:                        ipo->ipo_flags |= IPSP_POLICY_STATIC;
        !          1660:
        !          1661:                if (sunionp)
        !          1662:                        bcopy(sunionp, &ipo->ipo_dst,
        !          1663:                            sizeof(union sockaddr_union));
        !          1664:                else
        !          1665:                        bzero(&ipo->ipo_dst, sizeof(union sockaddr_union));
        !          1666:
        !          1667:                if (ssrc)
        !          1668:                        bcopy(ssrc, &ipo->ipo_src,
        !          1669:                            sizeof(union sockaddr_union));
        !          1670:                else
        !          1671:                        bzero(&ipo->ipo_src, sizeof(union sockaddr_union));
        !          1672:
        !          1673:                ipo->ipo_sproto = SADB_X_GETSPROTO(smsg->sadb_msg_satype);
        !          1674:
        !          1675:                if (ipo->ipo_srcid) {
        !          1676:                        ipsp_reffree(ipo->ipo_srcid);
        !          1677:                        ipo->ipo_srcid = NULL;
        !          1678:                }
        !          1679:
        !          1680:                if (ipo->ipo_dstid) {
        !          1681:                        ipsp_reffree(ipo->ipo_dstid);
        !          1682:                        ipo->ipo_dstid = NULL;
        !          1683:                }
        !          1684:
        !          1685:                if ((sid = headers[SADB_EXT_IDENTITY_SRC]) != NULL) {
        !          1686:                        int clen =  (sid->sadb_ident_len * sizeof(u_int64_t)) -
        !          1687:                            sizeof(struct sadb_ident);
        !          1688:
        !          1689:                        MALLOC(ipo->ipo_srcid, struct ipsec_ref *, clen +
        !          1690:                            sizeof(struct ipsec_ref), M_CREDENTIALS, M_DONTWAIT);
        !          1691:                        if (ipo->ipo_srcid == NULL) {
        !          1692:                                if (exists)
        !          1693:                                        ipsec_delete_policy(ipo);
        !          1694:                                else
        !          1695:                                        pool_put(&ipsec_policy_pool, ipo);
        !          1696:                                splx(s);
        !          1697:                                rval = ENOBUFS;
        !          1698:                                goto ret;
        !          1699:                        }
        !          1700:                        ipo->ipo_srcid->ref_type = sid->sadb_ident_type;
        !          1701:                        ipo->ipo_srcid->ref_len = clen;
        !          1702:                        ipo->ipo_srcid->ref_count = 1;
        !          1703:                        ipo->ipo_srcid->ref_malloctype = M_CREDENTIALS;
        !          1704:                        bcopy(sid + 1, ipo->ipo_srcid + 1, ipo->ipo_srcid->ref_len);
        !          1705:                }
        !          1706:
        !          1707:                if ((sid = headers[SADB_EXT_IDENTITY_DST]) != NULL) {
        !          1708:                        int clen =  (sid->sadb_ident_len * sizeof(u_int64_t)) -
        !          1709:                            sizeof(struct sadb_ident);
        !          1710:
        !          1711:                        MALLOC(ipo->ipo_dstid, struct ipsec_ref *,
        !          1712:                            clen + sizeof(struct ipsec_ref),
        !          1713:                            M_CREDENTIALS, M_DONTWAIT);
        !          1714:                        if (ipo->ipo_dstid == NULL) {
        !          1715:                                if (exists)
        !          1716:                                        ipsec_delete_policy(ipo);
        !          1717:                                else {
        !          1718:                                        if (ipo->ipo_dstid)
        !          1719:                                                ipsp_reffree(ipo->ipo_dstid);
        !          1720:                                        pool_put(&ipsec_policy_pool, ipo);
        !          1721:                                }
        !          1722:
        !          1723:                                splx(s);
        !          1724:                                rval = ENOBUFS;
        !          1725:                                goto ret;
        !          1726:                        }
        !          1727:                        ipo->ipo_dstid->ref_type = sid->sadb_ident_type;
        !          1728:                        ipo->ipo_dstid->ref_len = clen;
        !          1729:                        ipo->ipo_dstid->ref_count = 1;
        !          1730:                        ipo->ipo_dstid->ref_malloctype = M_CREDENTIALS;
        !          1731:                        bcopy(sid + 1, ipo->ipo_dstid + 1,
        !          1732:                            ipo->ipo_dstid->ref_len);
        !          1733:                }
        !          1734:
        !          1735:                /* Flow type */
        !          1736:                if (!exists) {
        !          1737:                        /* Add SPD entry */
        !          1738:                        if ((rval = rtrequest(RTM_ADD,
        !          1739:                                 (struct sockaddr *) &encapdst,
        !          1740:                                 (struct sockaddr *) &encapgw,
        !          1741:                                 (struct sockaddr *) &encapnetmask,
        !          1742:                                 RTF_UP | RTF_GATEWAY | RTF_STATIC,
        !          1743:                                 (struct rtentry **) 0, 0)) != 0) {
        !          1744:                                /* Remove from linked list of policies on TDB */
        !          1745:                                if (ipo->ipo_tdb)
        !          1746:                                        TAILQ_REMOVE(&ipo->ipo_tdb->tdb_policy_head,
        !          1747:                                            ipo, ipo_tdb_next);
        !          1748:
        !          1749:                                if (ipo->ipo_srcid)
        !          1750:                                        ipsp_reffree(ipo->ipo_srcid);
        !          1751:                                if (ipo->ipo_dstid)
        !          1752:                                        ipsp_reffree(ipo->ipo_dstid);
        !          1753:                                pool_put(&ipsec_policy_pool, ipo);
        !          1754:
        !          1755:                                splx(s);
        !          1756:                                goto ret;
        !          1757:                        }
        !          1758:
        !          1759:                        TAILQ_INSERT_HEAD(&ipsec_policy_head, ipo, ipo_list);
        !          1760:                        ipsec_in_use++;
        !          1761:                } else {
        !          1762:                        ipo->ipo_last_searched = ipo->ipo_flags = 0;
        !          1763:                }
        !          1764:
        !          1765:                splx(s);
        !          1766:        }
        !          1767:        break;
        !          1768:
        !          1769:        case SADB_X_PROMISC:
        !          1770:                if (len >= 2 * sizeof(struct sadb_msg)) {
        !          1771:                        struct mbuf *packet;
        !          1772:
        !          1773:                        if ((rval = pfdatatopacket(message, len, &packet)) != 0)
        !          1774:                                goto ret;
        !          1775:
        !          1776:                        for (so = pfkeyv2_sockets; so; so = so->next)
        !          1777:                                if ((so != pfkeyv2_socket) &&
        !          1778:                                    (!smsg->sadb_msg_seq ||
        !          1779:                                    (smsg->sadb_msg_seq == pfkeyv2_socket->pid)))
        !          1780:                                        pfkey_sendup(so->socket, packet, 1);
        !          1781:
        !          1782:                        m_freem(packet);
        !          1783:                } else {
        !          1784:                        if (len != sizeof(struct sadb_msg)) {
        !          1785:                                rval = EINVAL;
        !          1786:                                goto ret;
        !          1787:                        }
        !          1788:
        !          1789:                        i = (pfkeyv2_socket->flags &
        !          1790:                            PFKEYV2_SOCKETFLAGS_PROMISC) ? 1 : 0;
        !          1791:                        j = smsg->sadb_msg_satype ? 1 : 0;
        !          1792:
        !          1793:                        if (i ^ j) {
        !          1794:                                if (j) {
        !          1795:                                        pfkeyv2_socket->flags |=
        !          1796:                                            PFKEYV2_SOCKETFLAGS_PROMISC;
        !          1797:                                        npromisc++;
        !          1798:                                } else {
        !          1799:                                        pfkeyv2_socket->flags &=
        !          1800:                                            ~PFKEYV2_SOCKETFLAGS_PROMISC;
        !          1801:                                        npromisc--;
        !          1802:                                }
        !          1803:                        }
        !          1804:                }
        !          1805:
        !          1806:
        !          1807:                break;
        !          1808:
        !          1809:        default:
        !          1810:                rval = EINVAL;
        !          1811:                goto ret;
        !          1812:        }
        !          1813:
        !          1814: ret:
        !          1815:        if (rval) {
        !          1816:                if ((rval == EINVAL) || (rval == ENOMEM) || (rval == ENOBUFS))
        !          1817:                        goto realret;
        !          1818:
        !          1819:                for (i = 1; i <= SADB_EXT_MAX; i++)
        !          1820:                        headers[i] = NULL;
        !          1821:
        !          1822:                smsg->sadb_msg_errno = abs(rval);
        !          1823:        } else {
        !          1824:                uint64_t seen = 0LL;
        !          1825:
        !          1826:                for (i = 1; i <= SADB_EXT_MAX; i++)
        !          1827:                        if (headers[i])
        !          1828:                                seen |= (1LL << i);
        !          1829:
        !          1830:                if ((seen & sadb_exts_allowed_out[smsg->sadb_msg_type])
        !          1831:                    != seen)
        !          1832:                        goto realret;
        !          1833:
        !          1834:                if ((seen & sadb_exts_required_out[smsg->sadb_msg_type]) !=
        !          1835:                    sadb_exts_required_out[smsg->sadb_msg_type])
        !          1836:                        goto realret;
        !          1837:        }
        !          1838:
        !          1839:        rval = pfkeyv2_sendmessage(headers, mode, socket, 0, 0);
        !          1840:
        !          1841: realret:
        !          1842:        if (freeme)
        !          1843:                free(freeme, M_PFKEY);
        !          1844:
        !          1845:        free(message, M_PFKEY);
        !          1846:
        !          1847:        return (rval);
        !          1848:
        !          1849: splxret:
        !          1850:        splx(s);
        !          1851:        goto ret;
        !          1852: }
        !          1853:
        !          1854: /*
        !          1855:  * Send an ACQUIRE message to key management, to get a new SA.
        !          1856:  */
        !          1857: int
        !          1858: pfkeyv2_acquire(struct ipsec_policy *ipo, union sockaddr_union *gw,
        !          1859:     union sockaddr_union *laddr, u_int32_t *seq, struct sockaddr_encap *ddst)
        !          1860: {
        !          1861:        void *p, *headers[SADB_EXT_MAX + 1], *buffer = NULL;
        !          1862:        struct sadb_ident *srcid, *dstid;
        !          1863:        struct sadb_x_cred *lcred, *lauth;
        !          1864:        struct sadb_comb *sadb_comb;
        !          1865:        struct sadb_address *sadd;
        !          1866:        struct sadb_prop *sa_prop;
        !          1867:        struct sadb_msg *smsg;
        !          1868:        int rval = 0;
        !          1869:        int i, j;
        !          1870:
        !          1871:        *seq = pfkeyv2_seq++;
        !          1872:
        !          1873:        if (!nregistered) {
        !          1874:                rval = ESRCH;
        !          1875:                goto ret;
        !          1876:        }
        !          1877:
        !          1878:        /* How large a buffer do we need... XXX we only do one proposal for now */
        !          1879:        i = sizeof(struct sadb_msg) +
        !          1880:            (laddr == NULL ? 0 : sizeof(struct sadb_address) +
        !          1881:                PADUP(SA_LEN(&ipo->ipo_src.sa))) +
        !          1882:            sizeof(struct sadb_address) + PADUP(SA_LEN(&gw->sa)) +
        !          1883:            sizeof(struct sadb_prop) + 1 * sizeof(struct sadb_comb);
        !          1884:
        !          1885:        if (ipo->ipo_srcid)
        !          1886:                i += sizeof(struct sadb_ident) + PADUP(ipo->ipo_srcid->ref_len);
        !          1887:
        !          1888:        if (ipo->ipo_dstid)
        !          1889:                i += sizeof(struct sadb_ident) + PADUP(ipo->ipo_dstid->ref_len);
        !          1890:
        !          1891:        if (ipo->ipo_local_cred)
        !          1892:                i += sizeof(struct sadb_x_cred) + PADUP(ipo->ipo_local_cred->ref_len);
        !          1893:
        !          1894:        if (ipo->ipo_local_auth)
        !          1895:                i += sizeof(struct sadb_x_cred) + PADUP(ipo->ipo_local_auth->ref_len);
        !          1896:
        !          1897:        /* Allocate */
        !          1898:        if (!(p = malloc(i, M_PFKEY, M_DONTWAIT))) {
        !          1899:                rval = ENOMEM;
        !          1900:                goto ret;
        !          1901:        }
        !          1902:
        !          1903:        bzero(headers, sizeof(headers));
        !          1904:
        !          1905:        buffer = p;
        !          1906:        bzero(p, i);
        !          1907:
        !          1908:        headers[0] = p;
        !          1909:        p += sizeof(struct sadb_msg);
        !          1910:
        !          1911:        smsg = (struct sadb_msg *) headers[0];
        !          1912:        smsg->sadb_msg_version = PF_KEY_V2;
        !          1913:        smsg->sadb_msg_type = SADB_ACQUIRE;
        !          1914:        smsg->sadb_msg_len = i / sizeof(uint64_t);
        !          1915:        smsg->sadb_msg_seq = *seq;
        !          1916:
        !          1917:        if (ipo->ipo_sproto == IPPROTO_ESP)
        !          1918:                smsg->sadb_msg_satype = SADB_SATYPE_ESP;
        !          1919:        else if (ipo->ipo_sproto == IPPROTO_AH)
        !          1920:                smsg->sadb_msg_satype = SADB_SATYPE_AH;
        !          1921:        else if (ipo->ipo_sproto == IPPROTO_IPCOMP)
        !          1922:                smsg->sadb_msg_satype = SADB_X_SATYPE_IPCOMP;
        !          1923:
        !          1924:        if (laddr) {
        !          1925:                headers[SADB_EXT_ADDRESS_SRC] = p;
        !          1926:                p += sizeof(struct sadb_address) + PADUP(SA_LEN(&laddr->sa));
        !          1927:                sadd = (struct sadb_address *) headers[SADB_EXT_ADDRESS_SRC];
        !          1928:                sadd->sadb_address_len = (sizeof(struct sadb_address) +
        !          1929:                    SA_LEN(&laddr->sa) + sizeof(uint64_t) - 1) /
        !          1930:                    sizeof(uint64_t);
        !          1931:                bcopy(laddr, headers[SADB_EXT_ADDRESS_SRC] +
        !          1932:                    sizeof(struct sadb_address), SA_LEN(&laddr->sa));
        !          1933:        }
        !          1934:
        !          1935:        headers[SADB_EXT_ADDRESS_DST] = p;
        !          1936:        p += sizeof(struct sadb_address) + PADUP(SA_LEN(&gw->sa));
        !          1937:        sadd = (struct sadb_address *) headers[SADB_EXT_ADDRESS_DST];
        !          1938:        sadd->sadb_address_len = (sizeof(struct sadb_address) +
        !          1939:            SA_LEN(&gw->sa) + sizeof(uint64_t) - 1) / sizeof(uint64_t);
        !          1940:        bcopy(gw, headers[SADB_EXT_ADDRESS_DST] + sizeof(struct sadb_address),
        !          1941:            SA_LEN(&gw->sa));
        !          1942:
        !          1943:        if (ipo->ipo_srcid) {
        !          1944:                headers[SADB_EXT_IDENTITY_SRC] = p;
        !          1945:                p += sizeof(struct sadb_ident) + PADUP(ipo->ipo_srcid->ref_len);
        !          1946:                srcid = (struct sadb_ident *) headers[SADB_EXT_IDENTITY_SRC];
        !          1947:                srcid->sadb_ident_len = (sizeof(struct sadb_ident) +
        !          1948:                    PADUP(ipo->ipo_srcid->ref_len)) / sizeof(u_int64_t);
        !          1949:                srcid->sadb_ident_type = ipo->ipo_srcid->ref_type;
        !          1950:                bcopy(ipo->ipo_srcid + 1, headers[SADB_EXT_IDENTITY_SRC] +
        !          1951:                    sizeof(struct sadb_ident), ipo->ipo_srcid->ref_len);
        !          1952:        }
        !          1953:
        !          1954:        if (ipo->ipo_dstid) {
        !          1955:                headers[SADB_EXT_IDENTITY_DST] = p;
        !          1956:                p += sizeof(struct sadb_ident) + PADUP(ipo->ipo_dstid->ref_len);
        !          1957:                dstid = (struct sadb_ident *) headers[SADB_EXT_IDENTITY_DST];
        !          1958:                dstid->sadb_ident_len = (sizeof(struct sadb_ident) +
        !          1959:                    PADUP(ipo->ipo_dstid->ref_len)) / sizeof(u_int64_t);
        !          1960:                dstid->sadb_ident_type = ipo->ipo_dstid->ref_type;
        !          1961:                bcopy(ipo->ipo_dstid + 1, headers[SADB_EXT_IDENTITY_DST] +
        !          1962:                    sizeof(struct sadb_ident), ipo->ipo_dstid->ref_len);
        !          1963:        }
        !          1964:
        !          1965:        if (ipo->ipo_local_cred) {
        !          1966:                headers[SADB_X_EXT_LOCAL_CREDENTIALS] = p;
        !          1967:                p += sizeof(struct sadb_x_cred) + PADUP(ipo->ipo_local_cred->ref_len);
        !          1968:                lcred = (struct sadb_x_cred *) headers[SADB_X_EXT_LOCAL_CREDENTIALS];
        !          1969:                lcred->sadb_x_cred_len = (sizeof(struct sadb_x_cred) +
        !          1970:                    PADUP(ipo->ipo_local_cred->ref_len)) / sizeof(u_int64_t);
        !          1971:                switch (ipo->ipo_local_cred->ref_type) {
        !          1972:                case IPSP_CRED_KEYNOTE:
        !          1973:                        lcred->sadb_x_cred_type = SADB_X_CREDTYPE_KEYNOTE;
        !          1974:                        break;
        !          1975:                case IPSP_CRED_X509:
        !          1976:                        lcred->sadb_x_cred_type = SADB_X_CREDTYPE_X509;
        !          1977:                        break;
        !          1978:                }
        !          1979:                bcopy(ipo->ipo_local_cred + 1, headers[SADB_X_EXT_LOCAL_CREDENTIALS] +
        !          1980:                    sizeof(struct sadb_x_cred), ipo->ipo_local_cred->ref_len);
        !          1981:        }
        !          1982:
        !          1983:        if (ipo->ipo_local_auth) {
        !          1984:                headers[SADB_X_EXT_LOCAL_AUTH] = p;
        !          1985:                p += sizeof(struct sadb_x_cred) + PADUP(ipo->ipo_local_auth->ref_len);
        !          1986:                lauth = (struct sadb_x_cred *) headers[SADB_X_EXT_LOCAL_AUTH];
        !          1987:                lauth->sadb_x_cred_len = (sizeof(struct sadb_x_cred) +
        !          1988:                    PADUP(ipo->ipo_local_auth->ref_len)) / sizeof(u_int64_t);
        !          1989:                switch (ipo->ipo_local_auth->ref_type) {
        !          1990:                case IPSP_AUTH_PASSPHRASE:
        !          1991:                        lauth->sadb_x_cred_type = SADB_X_AUTHTYPE_PASSPHRASE;
        !          1992:                        break;
        !          1993:                case IPSP_AUTH_RSA:
        !          1994:                        lauth->sadb_x_cred_type = SADB_X_AUTHTYPE_RSA;
        !          1995:                        break;
        !          1996:                }
        !          1997:
        !          1998:                bcopy(ipo->ipo_local_auth + 1, headers[SADB_X_EXT_LOCAL_AUTH] +
        !          1999:                    sizeof(struct sadb_x_cred), ipo->ipo_local_auth->ref_len);
        !          2000:        }
        !          2001:
        !          2002:        headers[SADB_EXT_PROPOSAL] = p;
        !          2003:        p += sizeof(struct sadb_prop);
        !          2004:        sa_prop = (struct sadb_prop *) headers[SADB_EXT_PROPOSAL];
        !          2005:        sa_prop->sadb_prop_num = 1; /* XXX One proposal only */
        !          2006:        sa_prop->sadb_prop_len = (sizeof(struct sadb_prop) +
        !          2007:            (sizeof(struct sadb_comb) * sa_prop->sadb_prop_num)) /
        !          2008:            sizeof(uint64_t);
        !          2009:
        !          2010:        sadb_comb = p;
        !          2011:
        !          2012:        /* XXX Should actually ask the crypto layer what's supported */
        !          2013:        for (j = 0; j < sa_prop->sadb_prop_num; j++) {
        !          2014:                sadb_comb->sadb_comb_flags = 0;
        !          2015:
        !          2016:                if (ipsec_require_pfs)
        !          2017:                        sadb_comb->sadb_comb_flags |= SADB_SAFLAGS_PFS;
        !          2018:
        !          2019:                /* Set the encryption algorithm */
        !          2020:                if (ipo->ipo_sproto == IPPROTO_ESP) {
        !          2021:                        if (!strncasecmp(ipsec_def_enc, "aes",
        !          2022:                            sizeof("aes"))) {
        !          2023:                                sadb_comb->sadb_comb_encrypt = SADB_X_EALG_AES;
        !          2024:                                sadb_comb->sadb_comb_encrypt_minbits = 128;
        !          2025:                                sadb_comb->sadb_comb_encrypt_maxbits = 256;
        !          2026:                        } else if (!strncasecmp(ipsec_def_enc, "aesctr",
        !          2027:                            sizeof("aesctr"))) {
        !          2028:                                sadb_comb->sadb_comb_encrypt = SADB_X_EALG_AESCTR;
        !          2029:                                sadb_comb->sadb_comb_encrypt_minbits = 128+32;
        !          2030:                                sadb_comb->sadb_comb_encrypt_maxbits = 256+32;
        !          2031:                        } else if (!strncasecmp(ipsec_def_enc, "3des",
        !          2032:                            sizeof("3des"))) {
        !          2033:                                sadb_comb->sadb_comb_encrypt = SADB_EALG_3DESCBC;
        !          2034:                                sadb_comb->sadb_comb_encrypt_minbits = 192;
        !          2035:                                sadb_comb->sadb_comb_encrypt_maxbits = 192;
        !          2036:                        } else if (!strncasecmp(ipsec_def_enc, "des",
        !          2037:                            sizeof("des"))) {
        !          2038:                                sadb_comb->sadb_comb_encrypt = SADB_EALG_DESCBC;
        !          2039:                                sadb_comb->sadb_comb_encrypt_minbits = 64;
        !          2040:                                sadb_comb->sadb_comb_encrypt_maxbits = 64;
        !          2041:                        } else if (!strncasecmp(ipsec_def_enc, "blowfish",
        !          2042:                            sizeof("blowfish"))) {
        !          2043:                                sadb_comb->sadb_comb_encrypt = SADB_X_EALG_BLF;
        !          2044:                                sadb_comb->sadb_comb_encrypt_minbits = 40;
        !          2045:                                sadb_comb->sadb_comb_encrypt_maxbits = BLF_MAXKEYLEN * 8;
        !          2046:                        } else if (!strncasecmp(ipsec_def_enc, "skipjack",
        !          2047:                            sizeof("skipjack"))) {
        !          2048:                                sadb_comb->sadb_comb_encrypt = SADB_X_EALG_SKIPJACK;
        !          2049:                                sadb_comb->sadb_comb_encrypt_minbits = 80;
        !          2050:                                sadb_comb->sadb_comb_encrypt_maxbits = 80;
        !          2051:                        } else if (!strncasecmp(ipsec_def_enc, "cast128",
        !          2052:                            sizeof("cast128"))) {
        !          2053:                                sadb_comb->sadb_comb_encrypt = SADB_X_EALG_CAST;
        !          2054:                                sadb_comb->sadb_comb_encrypt_minbits = 40;
        !          2055:                                sadb_comb->sadb_comb_encrypt_maxbits = 128;
        !          2056:                        }
        !          2057:                } else if (ipo->ipo_sproto == IPPROTO_IPCOMP) {
        !          2058:                        /* Set the compression algorithm */
        !          2059:                        if (!strncasecmp(ipsec_def_comp, "deflate",
        !          2060:                            sizeof("deflate"))) {
        !          2061:                                sadb_comb->sadb_comb_encrypt = SADB_X_CALG_DEFLATE;
        !          2062:                                sadb_comb->sadb_comb_encrypt_minbits = 0;
        !          2063:                                sadb_comb->sadb_comb_encrypt_maxbits = 0;
        !          2064:                        } else if (!strncasecmp(ipsec_def_comp, "lzs",
        !          2065:                            sizeof("lzs"))) {
        !          2066:                                sadb_comb->sadb_comb_encrypt = SADB_X_CALG_LZS;
        !          2067:                                sadb_comb->sadb_comb_encrypt_minbits = 0;
        !          2068:                                sadb_comb->sadb_comb_encrypt_maxbits = 0;
        !          2069:                        }
        !          2070:                }
        !          2071:
        !          2072:                /* Set the authentication algorithm */
        !          2073:                if (!strncasecmp(ipsec_def_auth, "hmac-sha1",
        !          2074:                    sizeof("hmac-sha1"))) {
        !          2075:                        sadb_comb->sadb_comb_auth = SADB_AALG_SHA1HMAC;
        !          2076:                        sadb_comb->sadb_comb_auth_minbits = 160;
        !          2077:                        sadb_comb->sadb_comb_auth_maxbits = 160;
        !          2078:                } else if (!strncasecmp(ipsec_def_auth, "hmac-ripemd160",
        !          2079:                    sizeof("hmac_ripemd160"))) {
        !          2080:                        sadb_comb->sadb_comb_auth = SADB_X_AALG_RIPEMD160HMAC;
        !          2081:                        sadb_comb->sadb_comb_auth_minbits = 160;
        !          2082:                        sadb_comb->sadb_comb_auth_maxbits = 160;
        !          2083:                } else if (!strncasecmp(ipsec_def_auth, "hmac-md5",
        !          2084:                    sizeof("hmac-md5"))) {
        !          2085:                        sadb_comb->sadb_comb_auth = SADB_AALG_MD5HMAC;
        !          2086:                        sadb_comb->sadb_comb_auth_minbits = 128;
        !          2087:                        sadb_comb->sadb_comb_auth_maxbits = 128;
        !          2088:                } else if (!strncasecmp(ipsec_def_auth, "hmac-sha2-256",
        !          2089:                    sizeof("hmac-sha2-256"))) {
        !          2090:                        sadb_comb->sadb_comb_auth = SADB_X_AALG_SHA2_256;
        !          2091:                        sadb_comb->sadb_comb_auth_minbits = 256;
        !          2092:                        sadb_comb->sadb_comb_auth_maxbits = 256;
        !          2093:                } else if (!strncasecmp(ipsec_def_auth, "hmac-sha2-384",
        !          2094:                    sizeof("hmac-sha2-384"))) {
        !          2095:                        sadb_comb->sadb_comb_auth = SADB_X_AALG_SHA2_384;
        !          2096:                        sadb_comb->sadb_comb_auth_minbits = 384;
        !          2097:                        sadb_comb->sadb_comb_auth_maxbits = 384;
        !          2098:                } else if (!strncasecmp(ipsec_def_auth, "hmac-sha2-512",
        !          2099:                    sizeof("hmac-sha2-512"))) {
        !          2100:                        sadb_comb->sadb_comb_auth = SADB_X_AALG_SHA2_512;
        !          2101:                        sadb_comb->sadb_comb_auth_minbits = 512;
        !          2102:                        sadb_comb->sadb_comb_auth_maxbits = 512;
        !          2103:                }
        !          2104:
        !          2105:                sadb_comb->sadb_comb_soft_allocations = ipsec_soft_allocations;
        !          2106:                sadb_comb->sadb_comb_hard_allocations = ipsec_exp_allocations;
        !          2107:
        !          2108:                sadb_comb->sadb_comb_soft_bytes = ipsec_soft_bytes;
        !          2109:                sadb_comb->sadb_comb_hard_bytes = ipsec_exp_bytes;
        !          2110:
        !          2111:                sadb_comb->sadb_comb_soft_addtime = ipsec_soft_timeout;
        !          2112:                sadb_comb->sadb_comb_hard_addtime = ipsec_exp_timeout;
        !          2113:
        !          2114:                sadb_comb->sadb_comb_soft_usetime = ipsec_soft_first_use;
        !          2115:                sadb_comb->sadb_comb_hard_usetime = ipsec_exp_first_use;
        !          2116:                sadb_comb++;
        !          2117:        }
        !          2118:
        !          2119:        /* Send the ACQUIRE message to all compliant registered listeners. */
        !          2120:        if ((rval = pfkeyv2_sendmessage(headers,
        !          2121:            PFKEYV2_SENDMESSAGE_REGISTERED, NULL, smsg->sadb_msg_satype, 0))
        !          2122:            != 0)
        !          2123:                goto ret;
        !          2124:
        !          2125:        rval = 0;
        !          2126: ret:
        !          2127:        if (buffer != NULL) {
        !          2128:                bzero(buffer, i);
        !          2129:                free(buffer, M_PFKEY);
        !          2130:        }
        !          2131:
        !          2132:        return (rval);
        !          2133: }
        !          2134:
        !          2135: /*
        !          2136:  * Notify key management that an expiration went off. The second argument
        !          2137:  * specifies the type of expiration (soft or hard).
        !          2138:  */
        !          2139: int
        !          2140: pfkeyv2_expire(struct tdb *sa, u_int16_t type)
        !          2141: {
        !          2142:        void *p, *headers[SADB_EXT_MAX+1], *buffer = NULL;
        !          2143:        struct sadb_msg *smsg;
        !          2144:        int rval = 0;
        !          2145:        int i;
        !          2146:
        !          2147:        switch (sa->tdb_sproto) {
        !          2148:        case IPPROTO_AH:
        !          2149:        case IPPROTO_ESP:
        !          2150:        case IPPROTO_IPIP:
        !          2151:        case IPPROTO_IPCOMP:
        !          2152: #ifdef TCP_SIGNATURE
        !          2153:        case IPPROTO_TCP:
        !          2154: #endif /* TCP_SIGNATURE */
        !          2155:                break;
        !          2156:
        !          2157:        default:
        !          2158:                rval = EOPNOTSUPP;
        !          2159:                goto ret;
        !          2160:        }
        !          2161:
        !          2162:        i = sizeof(struct sadb_msg) + sizeof(struct sadb_sa) +
        !          2163:            2 * sizeof(struct sadb_lifetime) +
        !          2164:            sizeof(struct sadb_address) + PADUP(SA_LEN(&sa->tdb_src.sa)) +
        !          2165:            sizeof(struct sadb_address) + PADUP(SA_LEN(&sa->tdb_dst.sa));
        !          2166:
        !          2167:        if (!(p = malloc(i, M_PFKEY, M_DONTWAIT))) {
        !          2168:                rval = ENOMEM;
        !          2169:                goto ret;
        !          2170:        }
        !          2171:
        !          2172:        bzero(headers, sizeof(headers));
        !          2173:
        !          2174:        buffer = p;
        !          2175:        bzero(p, i);
        !          2176:
        !          2177:        headers[0] = p;
        !          2178:        p += sizeof(struct sadb_msg);
        !          2179:
        !          2180:        smsg = (struct sadb_msg *) headers[0];
        !          2181:        smsg->sadb_msg_version = PF_KEY_V2;
        !          2182:        smsg->sadb_msg_type = SADB_EXPIRE;
        !          2183:        smsg->sadb_msg_satype = sa->tdb_satype;
        !          2184:        smsg->sadb_msg_len = i / sizeof(uint64_t);
        !          2185:        smsg->sadb_msg_seq = pfkeyv2_seq++;
        !          2186:
        !          2187:        headers[SADB_EXT_SA] = p;
        !          2188:        export_sa(&p, sa);
        !          2189:
        !          2190:        headers[SADB_EXT_LIFETIME_CURRENT] = p;
        !          2191:        export_lifetime(&p, sa, 2);
        !          2192:
        !          2193:        headers[type] = p;
        !          2194:        export_lifetime(&p, sa, type == SADB_EXT_LIFETIME_SOFT ?
        !          2195:            PFKEYV2_LIFETIME_SOFT : PFKEYV2_LIFETIME_HARD);
        !          2196:
        !          2197:        headers[SADB_EXT_ADDRESS_SRC] = p;
        !          2198:        export_address(&p, (struct sockaddr *) &sa->tdb_src);
        !          2199:
        !          2200:        headers[SADB_EXT_ADDRESS_DST] = p;
        !          2201:        export_address(&p, (struct sockaddr *) &sa->tdb_dst);
        !          2202:
        !          2203:        if ((rval = pfkeyv2_sendmessage(headers, PFKEYV2_SENDMESSAGE_BROADCAST,
        !          2204:            NULL, 0, 0)) != 0)
        !          2205:                goto ret;
        !          2206:
        !          2207:        rval = 0;
        !          2208:
        !          2209:  ret:
        !          2210:        if (buffer != NULL) {
        !          2211:                bzero(buffer, i);
        !          2212:                free(buffer, M_PFKEY);
        !          2213:        }
        !          2214:
        !          2215:        return (rval);
        !          2216: }
        !          2217:
        !          2218: struct pfkeyv2_sysctl_walk {
        !          2219:        void            *w_where;
        !          2220:        size_t           w_len;
        !          2221:        int              w_op;
        !          2222:        u_int8_t         w_satype;
        !          2223: };
        !          2224:
        !          2225: int
        !          2226: pfkeyv2_sysctl_walker(struct tdb *sa, void *arg, int last)
        !          2227: {
        !          2228:        struct pfkeyv2_sysctl_walk *w = (struct pfkeyv2_sysctl_walk *)arg;
        !          2229:        void *buffer = NULL;
        !          2230:        int error = 0;
        !          2231:        int buflen, i;
        !          2232:
        !          2233:        if (w->w_satype != SADB_SATYPE_UNSPEC &&
        !          2234:            w->w_satype != sa->tdb_satype)
        !          2235:                return (0);
        !          2236:
        !          2237:        if (w->w_where) {
        !          2238:                void *headers[SADB_EXT_MAX+1];
        !          2239:                struct sadb_msg msg;
        !          2240:
        !          2241:                bzero(headers, sizeof(headers));
        !          2242:                if ((error = pfkeyv2_get(sa, headers, &buffer, &buflen)) != 0)
        !          2243:                        goto done;
        !          2244:                if (w->w_len < sizeof(msg) + buflen) {
        !          2245:                        error = ENOMEM;
        !          2246:                        goto done;
        !          2247:                }
        !          2248:                /* prepend header */
        !          2249:                bzero(&msg, sizeof(msg));
        !          2250:                msg.sadb_msg_version = PF_KEY_V2;
        !          2251:                msg.sadb_msg_satype = sa->tdb_satype;
        !          2252:                msg.sadb_msg_type = SADB_DUMP;
        !          2253:                msg.sadb_msg_len = (sizeof(msg) + buflen) / sizeof(uint64_t);
        !          2254:                if ((error = copyout(&msg, w->w_where, sizeof(msg))) != 0)
        !          2255:                        goto done;
        !          2256:                w->w_where += sizeof(msg);
        !          2257:                w->w_len -= sizeof(msg);
        !          2258:                /* set extension type */
        !          2259:                for (i = 1; i <= SADB_EXT_MAX; i++)
        !          2260:                        if (headers[i])
        !          2261:                                ((struct sadb_ext *)
        !          2262:                                    headers[i])->sadb_ext_type = i;
        !          2263:                if ((error = copyout(buffer, w->w_where, buflen)) != 0)
        !          2264:                        goto done;
        !          2265:                w->w_where += buflen;
        !          2266:                w->w_len -= buflen;
        !          2267:        } else {
        !          2268:                if ((error = pfkeyv2_get(sa, NULL, NULL, &buflen)) != 0)
        !          2269:                        return (error);
        !          2270:                w->w_len += buflen;
        !          2271:                w->w_len += sizeof(struct sadb_msg);
        !          2272:        }
        !          2273:
        !          2274: done:
        !          2275:        if (buffer)
        !          2276:                free(buffer, M_PFKEY);
        !          2277:        return (error);
        !          2278: }
        !          2279:
        !          2280: int
        !          2281: pfkeyv2_dump_policy(struct ipsec_policy *ipo, void **headers, void **buffer,
        !          2282:     int *lenp)
        !          2283: {
        !          2284:        struct sadb_ident *ident;
        !          2285:        int i, rval, perm;
        !          2286:        void *p;
        !          2287:
        !          2288:        /* Find how much space we need. */
        !          2289:        i = 2 * sizeof(struct sadb_protocol);
        !          2290:
        !          2291:        /* We'll need four of them: src, src mask, dst, dst mask. */
        !          2292:        switch (ipo->ipo_addr.sen_type) {
        !          2293: #ifdef INET
        !          2294:        case SENT_IP4:
        !          2295:                i += 4 * PADUP(sizeof(struct sockaddr_in));
        !          2296:                i += 4 * sizeof(struct sadb_address);
        !          2297:                break;
        !          2298: #endif /* INET */
        !          2299: #ifdef INET6
        !          2300:        case SENT_IP6:
        !          2301:                i += 4 * PADUP(sizeof(struct sockaddr_in6));
        !          2302:                i += 4 * sizeof(struct sadb_address);
        !          2303:                break;
        !          2304: #endif /* INET6 */
        !          2305:        default:
        !          2306:                return (EINVAL);
        !          2307:        }
        !          2308:
        !          2309:        /* Local address, might be zeroed. */
        !          2310:        switch (ipo->ipo_src.sa.sa_family) {
        !          2311:        case 0:
        !          2312:                break;
        !          2313: #ifdef INET
        !          2314:        case AF_INET:
        !          2315:                i += PADUP(sizeof(struct sockaddr_in));
        !          2316:                i += sizeof(struct sadb_address);
        !          2317:                break;
        !          2318: #endif /* INET */
        !          2319: #ifdef INET6
        !          2320:        case AF_INET6:
        !          2321:                i += PADUP(sizeof(struct sockaddr_in6));
        !          2322:                i += sizeof(struct sadb_address);
        !          2323:                break;
        !          2324: #endif /* INET6 */
        !          2325:        default:
        !          2326:                return (EINVAL);
        !          2327:        }
        !          2328:
        !          2329:        /* Remote address, might be zeroed. XXX ??? */
        !          2330:        switch (ipo->ipo_dst.sa.sa_family) {
        !          2331:        case 0:
        !          2332:                break;
        !          2333: #ifdef INET
        !          2334:        case AF_INET:
        !          2335:                i += PADUP(sizeof(struct sockaddr_in));
        !          2336:                i += sizeof(struct sadb_address);
        !          2337:                break;
        !          2338: #endif /* INET */
        !          2339: #ifdef INET6
        !          2340:        case AF_INET6:
        !          2341:                i += PADUP(sizeof(struct sockaddr_in6));
        !          2342:                i += sizeof(struct sadb_address);
        !          2343:                break;
        !          2344: #endif /* INET6 */
        !          2345:        default:
        !          2346:                return (EINVAL);
        !          2347:        }
        !          2348:
        !          2349:        if (ipo->ipo_srcid)
        !          2350:                i += sizeof(struct sadb_ident) + PADUP(ipo->ipo_srcid->ref_len);
        !          2351:        if (ipo->ipo_dstid)
        !          2352:                i += sizeof(struct sadb_ident) + PADUP(ipo->ipo_dstid->ref_len);
        !          2353:
        !          2354:        if (lenp)
        !          2355:                *lenp = i;
        !          2356:
        !          2357:        if (buffer == NULL) {
        !          2358:                rval = 0;
        !          2359:                goto ret;
        !          2360:        }
        !          2361:
        !          2362:        if (!(p = malloc(i, M_PFKEY, M_DONTWAIT))) {
        !          2363:                rval = ENOMEM;
        !          2364:                goto ret;
        !          2365:        } else {
        !          2366:                *buffer = p;
        !          2367:                bzero(p, i);
        !          2368:        }
        !          2369:
        !          2370:        /* Local address. */
        !          2371:        if (ipo->ipo_src.sa.sa_family) {
        !          2372:                headers[SADB_EXT_ADDRESS_SRC] = p;
        !          2373:                export_address(&p, (struct sockaddr *)&ipo->ipo_src);
        !          2374:        }
        !          2375:
        !          2376:        /* Remote address. */
        !          2377:        if (ipo->ipo_dst.sa.sa_family) {
        !          2378:                headers[SADB_EXT_ADDRESS_DST] = p;
        !          2379:                export_address(&p, (struct sockaddr *)&ipo->ipo_dst);
        !          2380:        }
        !          2381:
        !          2382:        /* Get actual flow. */
        !          2383:        export_flow(&p, ipo->ipo_type, &ipo->ipo_addr, &ipo->ipo_mask,
        !          2384:            headers);
        !          2385:
        !          2386:        /* Add ids only when we are root. */
        !          2387:        perm = suser(curproc, 0);
        !          2388:        if (perm == 0 && ipo->ipo_srcid) {
        !          2389:                headers[SADB_EXT_IDENTITY_SRC] = p;
        !          2390:                p += sizeof(struct sadb_ident) + PADUP(ipo->ipo_srcid->ref_len);
        !          2391:                ident = (struct sadb_ident *)headers[SADB_EXT_IDENTITY_SRC];
        !          2392:                ident->sadb_ident_len = (sizeof(struct sadb_ident) +
        !          2393:                    PADUP(ipo->ipo_srcid->ref_len)) / sizeof(uint64_t);
        !          2394:                ident->sadb_ident_type = ipo->ipo_srcid->ref_type;
        !          2395:                bcopy(ipo->ipo_srcid + 1, headers[SADB_EXT_IDENTITY_SRC] +
        !          2396:                    sizeof(struct sadb_ident), ipo->ipo_srcid->ref_len);
        !          2397:        }
        !          2398:        if (perm == 0 && ipo->ipo_dstid) {
        !          2399:                headers[SADB_EXT_IDENTITY_DST] = p;
        !          2400:                p += sizeof(struct sadb_ident) + PADUP(ipo->ipo_dstid->ref_len);
        !          2401:                ident = (struct sadb_ident *)headers[SADB_EXT_IDENTITY_DST];
        !          2402:                ident->sadb_ident_len = (sizeof(struct sadb_ident) +
        !          2403:                    PADUP(ipo->ipo_dstid->ref_len)) / sizeof(uint64_t);
        !          2404:                ident->sadb_ident_type = ipo->ipo_dstid->ref_type;
        !          2405:                bcopy(ipo->ipo_dstid + 1, headers[SADB_EXT_IDENTITY_DST] +
        !          2406:                    sizeof(struct sadb_ident), ipo->ipo_dstid->ref_len);
        !          2407:        }
        !          2408:
        !          2409:        rval = 0;
        !          2410: ret:
        !          2411:        return (rval);
        !          2412: }
        !          2413:
        !          2414: /*
        !          2415:  * Caller is responsible for setting at least spltdb().
        !          2416:  */
        !          2417: int
        !          2418: pfkeyv2_ipo_walk(int (*walker)(struct ipsec_policy *, void *), void *arg)
        !          2419: {
        !          2420:        int rval = 0;
        !          2421:        struct ipsec_policy *ipo;
        !          2422:
        !          2423:        TAILQ_FOREACH(ipo, &ipsec_policy_head, ipo_list)
        !          2424:                rval = walker(ipo, (void *)arg);
        !          2425:        return (rval);
        !          2426: }
        !          2427:
        !          2428: int
        !          2429: pfkeyv2_sysctl_policydumper(struct ipsec_policy *ipo, void *arg)
        !          2430: {
        !          2431:        struct pfkeyv2_sysctl_walk *w = (struct pfkeyv2_sysctl_walk *)arg;
        !          2432:        void *buffer = 0;
        !          2433:        int i, buflen, error = 0;
        !          2434:
        !          2435:        /* Do not dump policies attached to a socket. */
        !          2436:        if (ipo->ipo_flags & IPSP_POLICY_SOCKET)
        !          2437:                return (0);
        !          2438:
        !          2439:        if (w->w_where) {
        !          2440:                void *headers[SADB_EXT_MAX + 1];
        !          2441:                struct sadb_msg msg;
        !          2442:
        !          2443:                bzero(headers, sizeof(headers));
        !          2444:                if ((error = pfkeyv2_dump_policy(ipo, headers, &buffer,
        !          2445:                    &buflen)) != 0)
        !          2446:                        goto done;
        !          2447:                if (w->w_len < buflen) {
        !          2448:                        error = ENOMEM;
        !          2449:                        goto done;
        !          2450:                }
        !          2451:                /* prepend header */
        !          2452:                bzero(&msg, sizeof(msg));
        !          2453:                msg.sadb_msg_version = PF_KEY_V2;
        !          2454:                if (ipo->ipo_sproto == IPPROTO_ESP)
        !          2455:                        msg.sadb_msg_satype = SADB_SATYPE_ESP;
        !          2456:                else if (ipo->ipo_sproto == IPPROTO_AH)
        !          2457:                        msg.sadb_msg_satype = SADB_SATYPE_AH;
        !          2458:                else if (ipo->ipo_sproto == IPPROTO_IPCOMP)
        !          2459:                        msg.sadb_msg_satype = SADB_X_SATYPE_IPCOMP;
        !          2460:                else if (ipo->ipo_sproto == IPPROTO_IPIP)
        !          2461:                        msg.sadb_msg_satype = SADB_X_SATYPE_IPIP;
        !          2462:                msg.sadb_msg_type = SADB_X_SPDDUMP;
        !          2463:                msg.sadb_msg_len = (sizeof(msg) + buflen) / sizeof(uint64_t);
        !          2464:                if ((error = copyout(&msg, w->w_where, sizeof(msg))) != 0)
        !          2465:                        goto done;
        !          2466:                w->w_where += sizeof(msg);
        !          2467:                w->w_len -= sizeof(msg);
        !          2468:                /* set extension type */
        !          2469:                for (i = 1; i < SADB_EXT_MAX; i++)
        !          2470:                        if (headers[i])
        !          2471:                                ((struct sadb_ext *)
        !          2472:                                    headers[i])->sadb_ext_type = i;
        !          2473:                if ((error = copyout(buffer, w->w_where, buflen)) != 0)
        !          2474:                        goto done;
        !          2475:                w->w_where += buflen;
        !          2476:                w->w_len -= buflen;
        !          2477:        } else {
        !          2478:                if ((error = pfkeyv2_dump_policy(ipo, NULL, NULL,
        !          2479:                    &buflen)) != 0)
        !          2480:                        goto done;
        !          2481:                w->w_len += buflen;
        !          2482:                w->w_len += sizeof(struct sadb_msg);
        !          2483:        }
        !          2484:
        !          2485: done:
        !          2486:        if (buffer)
        !          2487:                free(buffer, M_PFKEY);
        !          2488:        return (error);
        !          2489: }
        !          2490:
        !          2491: int
        !          2492: pfkeyv2_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp,
        !          2493:     void *new, size_t newlen)
        !          2494: {
        !          2495:        struct pfkeyv2_sysctl_walk w;
        !          2496:        int s, error = EINVAL;
        !          2497:
        !          2498:        if (new)
        !          2499:                return (EPERM);
        !          2500:        if (namelen < 1)
        !          2501:                return (EINVAL);
        !          2502:        w.w_op = name[0];
        !          2503:        w.w_satype = name[1];
        !          2504:        w.w_where = oldp;
        !          2505:        w.w_len = oldp ? *oldlenp : 0;
        !          2506:
        !          2507:        switch(w.w_op) {
        !          2508:        case NET_KEY_SADB_DUMP:
        !          2509:                if ((error = suser(curproc, 0)) != 0)
        !          2510:                        return (error);
        !          2511:                s = spltdb();
        !          2512:                error = tdb_walk(pfkeyv2_sysctl_walker, &w);
        !          2513:                splx(s);
        !          2514:                if (oldp)
        !          2515:                        *oldlenp = w.w_where - oldp;
        !          2516:                else
        !          2517:                        *oldlenp = w.w_len;
        !          2518:                break;
        !          2519:
        !          2520:        case NET_KEY_SPD_DUMP:
        !          2521:                s = spltdb();
        !          2522:                error = pfkeyv2_ipo_walk(pfkeyv2_sysctl_policydumper, &w);
        !          2523:                splx(s);
        !          2524:                if (oldp)
        !          2525:                        *oldlenp = w.w_where - oldp;
        !          2526:                else
        !          2527:                        *oldlenp = w.w_len;
        !          2528:                break;
        !          2529:        }
        !          2530:
        !          2531:        return (error);
        !          2532: }
        !          2533:
        !          2534: int
        !          2535: pfkeyv2_init(void)
        !          2536: {
        !          2537:        int rval;
        !          2538:
        !          2539:        bzero(&pfkeyv2_version, sizeof(struct pfkey_version));
        !          2540:        pfkeyv2_version.protocol = PFKEYV2_PROTOCOL;
        !          2541:        pfkeyv2_version.create = &pfkeyv2_create;
        !          2542:        pfkeyv2_version.release = &pfkeyv2_release;
        !          2543:        pfkeyv2_version.send = &pfkeyv2_send;
        !          2544:        pfkeyv2_version.sysctl = &pfkeyv2_sysctl;
        !          2545:
        !          2546:        rval = pfkey_register(&pfkeyv2_version);
        !          2547:        return (rval);
        !          2548: }
        !          2549:
        !          2550: int
        !          2551: pfkeyv2_cleanup(void)
        !          2552: {
        !          2553:        pfkey_unregister(&pfkeyv2_version);
        !          2554:        return (0);
        !          2555: }

CVSweb