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

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

1.1     ! nbrk        1: /*     $OpenBSD: pfkeyv2_parsemessage.c,v 1.42 2007/07/30 11:43:59 hshoexer 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/param.h>
        !            74: #include <sys/systm.h>
        !            75: #include <sys/socket.h>
        !            76: #include <sys/mbuf.h>
        !            77: #include <sys/proc.h>
        !            78: #include <netinet/ip_ipsp.h>
        !            79: #include <net/pfkeyv2.h>
        !            80:
        !            81: #if NPF > 0
        !            82: #include <net/if.h>
        !            83: #include <net/pfvar.h>
        !            84: #endif
        !            85:
        !            86: extern int encdebug;
        !            87:
        !            88: #ifdef ENCDEBUG
        !            89: #define DPRINTF(x)     if (encdebug) printf x
        !            90: #else
        !            91: #define DPRINTF(x)
        !            92: #endif
        !            93:
        !            94: #define BITMAP_SA                      (1LL << SADB_EXT_SA)
        !            95: #define BITMAP_LIFETIME_CURRENT        (1LL << SADB_EXT_LIFETIME_CURRENT)
        !            96: #define BITMAP_LIFETIME_HARD           (1LL << SADB_EXT_LIFETIME_HARD)
        !            97: #define BITMAP_LIFETIME_SOFT           (1LL << SADB_EXT_LIFETIME_SOFT)
        !            98: #define BITMAP_ADDRESS_SRC             (1LL << SADB_EXT_ADDRESS_SRC)
        !            99: #define BITMAP_ADDRESS_DST             (1LL << SADB_EXT_ADDRESS_DST)
        !           100: #define BITMAP_ADDRESS_PROXY           (1LL << SADB_EXT_ADDRESS_PROXY)
        !           101: #define BITMAP_KEY_AUTH                (1LL << SADB_EXT_KEY_AUTH)
        !           102: #define BITMAP_KEY_ENCRYPT             (1LL << SADB_EXT_KEY_ENCRYPT)
        !           103: #define BITMAP_IDENTITY_SRC            (1LL << SADB_EXT_IDENTITY_SRC)
        !           104: #define BITMAP_IDENTITY_DST            (1LL << SADB_EXT_IDENTITY_DST)
        !           105: #define BITMAP_SENSITIVITY             (1LL << SADB_EXT_SENSITIVITY)
        !           106: #define BITMAP_PROPOSAL                (1LL << SADB_EXT_PROPOSAL)
        !           107: #define BITMAP_SUPPORTED_AUTH          (1LL << SADB_EXT_SUPPORTED_AUTH)
        !           108: #define BITMAP_SUPPORTED_ENCRYPT       (1LL << SADB_EXT_SUPPORTED_ENCRYPT)
        !           109: #define BITMAP_SPIRANGE                (1LL << SADB_EXT_SPIRANGE)
        !           110: #define BITMAP_LIFETIME (BITMAP_LIFETIME_CURRENT | BITMAP_LIFETIME_HARD | BITMAP_LIFETIME_SOFT)
        !           111: #define BITMAP_ADDRESS (BITMAP_ADDRESS_SRC | BITMAP_ADDRESS_DST | BITMAP_ADDRESS_PROXY)
        !           112: #define BITMAP_KEY      (BITMAP_KEY_AUTH | BITMAP_KEY_ENCRYPT)
        !           113: #define BITMAP_IDENTITY (BITMAP_IDENTITY_SRC | BITMAP_IDENTITY_DST)
        !           114: #define BITMAP_MSG                     1
        !           115: #define BITMAP_X_SRC_MASK              (1LL << SADB_X_EXT_SRC_MASK)
        !           116: #define BITMAP_X_DST_MASK              (1LL << SADB_X_EXT_DST_MASK)
        !           117: #define BITMAP_X_PROTOCOL              (1LL << SADB_X_EXT_PROTOCOL)
        !           118: #define BITMAP_X_SRC_FLOW              (1LL << SADB_X_EXT_SRC_FLOW)
        !           119: #define BITMAP_X_DST_FLOW              (1LL << SADB_X_EXT_DST_FLOW)
        !           120: #define BITMAP_X_FLOW_TYPE             (1LL << SADB_X_EXT_FLOW_TYPE)
        !           121: #define BITMAP_X_SA2                   (1LL << SADB_X_EXT_SA2)
        !           122: #define BITMAP_X_DST2                  (1LL << SADB_X_EXT_DST2)
        !           123: #define BITMAP_X_POLICY                (1LL << SADB_X_EXT_POLICY)
        !           124: #define BITMAP_X_LOCAL_CREDENTIALS     (1LL << SADB_X_EXT_LOCAL_CREDENTIALS)
        !           125: #define BITMAP_X_REMOTE_CREDENTIALS    (1LL << SADB_X_EXT_REMOTE_CREDENTIALS)
        !           126: #define BITMAP_X_LOCAL_AUTH            (1LL << SADB_X_EXT_LOCAL_AUTH)
        !           127: #define BITMAP_X_REMOTE_AUTH           (1LL << SADB_X_EXT_REMOTE_AUTH)
        !           128: #define BITMAP_X_CREDENTIALS           (BITMAP_X_LOCAL_CREDENTIALS | BITMAP_X_REMOTE_CREDENTIALS | BITMAP_X_LOCAL_AUTH | BITMAP_X_REMOTE_AUTH)
        !           129: #define BITMAP_X_FLOW                  (BITMAP_X_SRC_MASK | BITMAP_X_DST_MASK | BITMAP_X_PROTOCOL | BITMAP_X_SRC_FLOW | BITMAP_X_DST_FLOW | BITMAP_X_FLOW_TYPE)
        !           130: #define BITMAP_X_SUPPORTED_COMP        (1LL << SADB_X_EXT_SUPPORTED_COMP)
        !           131: #define BITMAP_X_UDPENCAP              (1LL << SADB_X_EXT_UDPENCAP)
        !           132: #define BITMAP_X_LIFETIME_LASTUSE      (1LL << SADB_X_EXT_LIFETIME_LASTUSE)
        !           133: #define BITMAP_X_TAG                   (1LL << SADB_X_EXT_TAG)
        !           134:
        !           135: uint64_t sadb_exts_allowed_in[SADB_MAX+1] =
        !           136: {
        !           137:        /* RESERVED */
        !           138:        ~0,
        !           139:        /* GETSPI */
        !           140:        BITMAP_ADDRESS_SRC | BITMAP_ADDRESS_DST | BITMAP_SPIRANGE,
        !           141:        /* UPDATE */
        !           142:        BITMAP_SA | BITMAP_LIFETIME | BITMAP_ADDRESS | BITMAP_KEY | BITMAP_IDENTITY | BITMAP_X_CREDENTIALS | BITMAP_X_FLOW | BITMAP_X_UDPENCAP | BITMAP_X_TAG,
        !           143:        /* ADD */
        !           144:        BITMAP_SA | BITMAP_LIFETIME | BITMAP_ADDRESS | BITMAP_KEY | BITMAP_IDENTITY | BITMAP_X_CREDENTIALS | BITMAP_X_FLOW | BITMAP_X_UDPENCAP | BITMAP_X_LIFETIME_LASTUSE | BITMAP_X_TAG,
        !           145:        /* DELETE */
        !           146:        BITMAP_SA | BITMAP_ADDRESS_SRC | BITMAP_ADDRESS_DST,
        !           147:        /* GET */
        !           148:        BITMAP_SA | BITMAP_ADDRESS_SRC | BITMAP_ADDRESS_DST,
        !           149:        /* ACQUIRE */
        !           150:        BITMAP_ADDRESS_SRC | BITMAP_ADDRESS_DST | BITMAP_IDENTITY | BITMAP_PROPOSAL | BITMAP_X_CREDENTIALS,
        !           151:        /* REGISTER */
        !           152:        0,
        !           153:        /* EXPIRE */
        !           154:        BITMAP_SA | BITMAP_ADDRESS_SRC | BITMAP_ADDRESS_DST,
        !           155:        /* FLUSH */
        !           156:        0,
        !           157:        /* DUMP */
        !           158:        0,
        !           159:        /* X_PROMISC */
        !           160:        0,
        !           161:        /* X_ADDFLOW */
        !           162:        BITMAP_ADDRESS_SRC | BITMAP_ADDRESS_DST | BITMAP_IDENTITY_SRC | BITMAP_IDENTITY_DST | BITMAP_X_FLOW,
        !           163:        /* X_DELFLOW */
        !           164:        BITMAP_X_FLOW,
        !           165:        /* X_GRPSPIS */
        !           166:        BITMAP_SA | BITMAP_X_SA2 | BITMAP_X_DST2 | BITMAP_ADDRESS_DST | BITMAP_X_PROTOCOL,
        !           167:        /* X_ASKPOLICY */
        !           168:        BITMAP_X_POLICY,
        !           169: };
        !           170:
        !           171: uint64_t sadb_exts_required_in[SADB_MAX+1] =
        !           172: {
        !           173:        /* RESERVED */
        !           174:        0,
        !           175:        /* GETSPI */
        !           176:        BITMAP_ADDRESS_SRC | BITMAP_ADDRESS_DST | BITMAP_SPIRANGE,
        !           177:        /* UPDATE */
        !           178:        BITMAP_SA | BITMAP_ADDRESS_SRC | BITMAP_ADDRESS_DST,
        !           179:        /* ADD */
        !           180:        BITMAP_SA | BITMAP_ADDRESS_DST,
        !           181:        /* DELETE */
        !           182:        BITMAP_SA | BITMAP_ADDRESS_DST,
        !           183:        /* GET */
        !           184:        BITMAP_SA | BITMAP_ADDRESS_DST,
        !           185:        /* ACQUIRE */
        !           186:        0,
        !           187:        /* REGISTER */
        !           188:        0,
        !           189:        /* EXPIRE */
        !           190:        BITMAP_SA | BITMAP_ADDRESS_SRC | BITMAP_ADDRESS_DST,
        !           191:        /* FLUSH */
        !           192:        0,
        !           193:        /* DUMP */
        !           194:        0,
        !           195:        /* X_PROMISC */
        !           196:        0,
        !           197:        /* X_ADDFLOW */
        !           198:        BITMAP_X_SRC_MASK | BITMAP_X_DST_MASK | BITMAP_X_SRC_FLOW | BITMAP_X_DST_FLOW | BITMAP_X_FLOW_TYPE,
        !           199:        /* X_DELFLOW */
        !           200:        BITMAP_X_SRC_MASK | BITMAP_X_DST_MASK | BITMAP_X_SRC_FLOW | BITMAP_X_DST_FLOW | BITMAP_X_FLOW_TYPE,
        !           201:        /* X_GRPSPIS */
        !           202:        BITMAP_SA | BITMAP_X_SA2 | BITMAP_X_DST2 | BITMAP_ADDRESS_DST | BITMAP_X_PROTOCOL,
        !           203:        /* X_ASKPOLICY */
        !           204:        BITMAP_X_POLICY,
        !           205: };
        !           206:
        !           207: uint64_t sadb_exts_allowed_out[SADB_MAX+1] =
        !           208: {
        !           209:        /* RESERVED */
        !           210:        ~0,
        !           211:        /* GETSPI */
        !           212:        BITMAP_SA | BITMAP_ADDRESS_SRC | BITMAP_ADDRESS_DST,
        !           213:        /* UPDATE */
        !           214:        BITMAP_SA | BITMAP_LIFETIME | BITMAP_ADDRESS | BITMAP_IDENTITY | BITMAP_X_CREDENTIALS | BITMAP_X_FLOW | BITMAP_X_UDPENCAP | BITMAP_X_TAG,
        !           215:        /* ADD */
        !           216:        BITMAP_SA | BITMAP_LIFETIME | BITMAP_ADDRESS | BITMAP_IDENTITY | BITMAP_X_CREDENTIALS | BITMAP_X_FLOW | BITMAP_X_UDPENCAP | BITMAP_X_TAG,
        !           217:        /* DELETE */
        !           218:        BITMAP_SA | BITMAP_ADDRESS_SRC | BITMAP_ADDRESS_DST,
        !           219:        /* GET */
        !           220:        BITMAP_SA | BITMAP_LIFETIME | BITMAP_ADDRESS | BITMAP_KEY | BITMAP_IDENTITY | BITMAP_X_CREDENTIALS | BITMAP_X_UDPENCAP | BITMAP_X_LIFETIME_LASTUSE | BITMAP_X_SRC_MASK | BITMAP_X_DST_MASK | BITMAP_X_PROTOCOL | BITMAP_X_FLOW_TYPE | BITMAP_X_SRC_FLOW | BITMAP_X_DST_FLOW | BITMAP_X_TAG,
        !           221:        /* ACQUIRE */
        !           222:        BITMAP_ADDRESS_SRC | BITMAP_ADDRESS_DST | BITMAP_IDENTITY | BITMAP_PROPOSAL | BITMAP_X_CREDENTIALS,
        !           223:        /* REGISTER */
        !           224:        BITMAP_SUPPORTED_AUTH | BITMAP_SUPPORTED_ENCRYPT | BITMAP_X_SUPPORTED_COMP,
        !           225:        /* EXPIRE */
        !           226:        BITMAP_SA | BITMAP_LIFETIME | BITMAP_ADDRESS,
        !           227:        /* FLUSH */
        !           228:        0,
        !           229:        /* DUMP */
        !           230:        BITMAP_SA | BITMAP_LIFETIME | BITMAP_ADDRESS | BITMAP_IDENTITY,
        !           231:        /* X_PROMISC */
        !           232:        0,
        !           233:        /* X_ADDFLOW */
        !           234:        BITMAP_ADDRESS_SRC | BITMAP_ADDRESS_DST | BITMAP_X_SRC_MASK | BITMAP_X_DST_MASK | BITMAP_X_PROTOCOL | BITMAP_X_SRC_FLOW | BITMAP_X_DST_FLOW | BITMAP_X_FLOW_TYPE | BITMAP_IDENTITY_SRC | BITMAP_IDENTITY_DST,
        !           235:        /* X_DELFLOW */
        !           236:        BITMAP_X_SRC_MASK | BITMAP_X_DST_MASK | BITMAP_X_PROTOCOL | BITMAP_X_SRC_FLOW | BITMAP_X_DST_FLOW | BITMAP_X_FLOW_TYPE,
        !           237:        /* X_GRPSPIS */
        !           238:        BITMAP_SA | BITMAP_X_SA2 | BITMAP_X_DST2 | BITMAP_ADDRESS_DST | BITMAP_X_PROTOCOL,
        !           239:        /* X_ASKPOLICY */
        !           240:        BITMAP_X_SRC_FLOW | BITMAP_X_DST_FLOW | BITMAP_X_SRC_MASK | BITMAP_X_DST_MASK | BITMAP_X_FLOW_TYPE | BITMAP_X_POLICY,
        !           241: };
        !           242:
        !           243: uint64_t sadb_exts_required_out[SADB_MAX+1] =
        !           244: {
        !           245:        /* RESERVED */
        !           246:        0,
        !           247:        /* GETSPI */
        !           248:        BITMAP_SA | BITMAP_ADDRESS_DST,
        !           249:        /* UPDATE */
        !           250:        BITMAP_SA | BITMAP_ADDRESS_DST,
        !           251:        /* ADD */
        !           252:        BITMAP_SA | BITMAP_ADDRESS_DST,
        !           253:        /* DELETE */
        !           254:        BITMAP_SA | BITMAP_ADDRESS_DST,
        !           255:        /* GET */
        !           256:        BITMAP_SA | BITMAP_LIFETIME_CURRENT | BITMAP_ADDRESS_DST,
        !           257:        /* ACQUIRE */
        !           258:        0,
        !           259:        /* REGISTER */
        !           260:        BITMAP_SUPPORTED_AUTH | BITMAP_SUPPORTED_ENCRYPT | BITMAP_X_SUPPORTED_COMP,
        !           261:        /* EXPIRE */
        !           262:        BITMAP_SA | BITMAP_ADDRESS_DST,
        !           263:        /* FLUSH */
        !           264:        0,
        !           265:        /* DUMP */
        !           266:        0,
        !           267:        /* X_PROMISC */
        !           268:        0,
        !           269:        /* X_ADDFLOW */
        !           270:        BITMAP_X_SRC_MASK | BITMAP_X_DST_MASK | BITMAP_X_SRC_FLOW | BITMAP_X_DST_FLOW | BITMAP_X_FLOW_TYPE,
        !           271:        /* X_DELFLOW */
        !           272:        BITMAP_X_SRC_MASK | BITMAP_X_DST_MASK | BITMAP_X_SRC_FLOW | BITMAP_X_DST_FLOW | BITMAP_X_FLOW_TYPE,
        !           273:        /* X_GRPSPIS */
        !           274:        BITMAP_SA | BITMAP_X_SA2 | BITMAP_X_DST2 | BITMAP_ADDRESS_DST | BITMAP_X_PROTOCOL,
        !           275:        /* X_REPPOLICY */
        !           276:        BITMAP_X_SRC_FLOW | BITMAP_X_DST_FLOW | BITMAP_X_SRC_MASK | BITMAP_X_DST_MASK | BITMAP_X_FLOW_TYPE,
        !           277: };
        !           278:
        !           279: int pfkeyv2_parsemessage(void *, int, void **);
        !           280:
        !           281: #define RETURN_EINVAL(line) goto einval;
        !           282:
        !           283: int
        !           284: pfkeyv2_parsemessage(void *p, int len, void **headers)
        !           285: {
        !           286:        struct sadb_ext *sadb_ext;
        !           287:        int i, left = len;
        !           288:        uint64_t allow, seen = 1;
        !           289:        struct sadb_msg *sadb_msg = (struct sadb_msg *) p;
        !           290:
        !           291:        bzero(headers, (SADB_EXT_MAX + 1) * sizeof(void *));
        !           292:
        !           293:        if (left < sizeof(struct sadb_msg)) {
        !           294:                DPRINTF(("pfkeyv2_parsemessage: message too short\n"));
        !           295:                return (EINVAL);
        !           296:        }
        !           297:
        !           298:        headers[0] = p;
        !           299:
        !           300:        if (sadb_msg->sadb_msg_len * sizeof(uint64_t) != left) {
        !           301:                DPRINTF(("pfkeyv2_parsemessage: length not a multiple of 64\n"));
        !           302:                return (EINVAL);
        !           303:        }
        !           304:
        !           305:        p += sizeof(struct sadb_msg);
        !           306:        left -= sizeof(struct sadb_msg);
        !           307:
        !           308:        if (sadb_msg->sadb_msg_reserved) {
        !           309:                DPRINTF(("pfkeyv2_parsemessage: message header reserved "
        !           310:                    "field set\n"));
        !           311:                return (EINVAL);
        !           312:        }
        !           313:
        !           314:        if (sadb_msg->sadb_msg_type > SADB_MAX) {
        !           315:                DPRINTF(("pfkeyv2_parsemessage: message type > %d\n",
        !           316:                    SADB_MAX));
        !           317:                return (EINVAL);
        !           318:        }
        !           319:
        !           320:        if (!sadb_msg->sadb_msg_type) {
        !           321:                DPRINTF(("pfkeyv2_parsemessage: message type unset\n"));
        !           322:                return (EINVAL);
        !           323:        }
        !           324:
        !           325:        if (sadb_msg->sadb_msg_pid != curproc->p_pid) {
        !           326:                DPRINTF(("pfkeyv2_parsemessage: bad PID value\n"));
        !           327:                return (EINVAL);
        !           328:        }
        !           329:
        !           330:        if (sadb_msg->sadb_msg_errno) {
        !           331:                if (left) {
        !           332:                        DPRINTF(("pfkeyv2_parsemessage: too-large error message\n"));
        !           333:                        return (EINVAL);
        !           334:                }
        !           335:                return (0);
        !           336:        }
        !           337:
        !           338:        if (sadb_msg->sadb_msg_type == SADB_X_PROMISC) {
        !           339:                DPRINTF(("pfkeyv2_parsemessage: message type promiscuous\n"));
        !           340:                return (0);
        !           341:        }
        !           342:
        !           343:        allow = sadb_exts_allowed_in[sadb_msg->sadb_msg_type];
        !           344:
        !           345:        while (left > 0) {
        !           346:                sadb_ext = (struct sadb_ext *)p;
        !           347:                if (left < sizeof(struct sadb_ext)) {
        !           348:                        DPRINTF(("pfkeyv2_parsemessage: extension header too "
        !           349:                            "short\n"));
        !           350:                        return (EINVAL);
        !           351:                }
        !           352:
        !           353:                i = sadb_ext->sadb_ext_len * sizeof(uint64_t);
        !           354:                if (left < i) {
        !           355:                        DPRINTF(("pfkeyv2_parsemessage: extension header "
        !           356:                            "exceeds message length\n"));
        !           357:                        return (EINVAL);
        !           358:                }
        !           359:
        !           360:                if (sadb_ext->sadb_ext_type > SADB_EXT_MAX) {
        !           361:                        DPRINTF(("pfkeyv2_parsemessage: unknown extension "
        !           362:                            "header %d\n", sadb_ext->sadb_ext_type));
        !           363:                        return (EINVAL);
        !           364:                }
        !           365:
        !           366:                if (!sadb_ext->sadb_ext_type) {
        !           367:                        DPRINTF(("pfkeyv2_parsemessage: unset extension "
        !           368:                            "header\n"));
        !           369:                        return (EINVAL);
        !           370:                }
        !           371:
        !           372:                if (!(allow & (1LL << sadb_ext->sadb_ext_type))) {
        !           373:                        DPRINTF(("pfkeyv2_parsemessage: extension header %d "
        !           374:                            "not permitted on message type %d\n",
        !           375:                            sadb_ext->sadb_ext_type, sadb_msg->sadb_msg_type));
        !           376:                        return (EINVAL);
        !           377:                }
        !           378:
        !           379:                if (headers[sadb_ext->sadb_ext_type]) {
        !           380:                        DPRINTF(("pfkeyv2_parsemessage: duplicate extension "
        !           381:                            "header %d\n", sadb_ext->sadb_ext_type));
        !           382:                        return (EINVAL);
        !           383:                }
        !           384:
        !           385:                seen |= (1LL << sadb_ext->sadb_ext_type);
        !           386:
        !           387:                switch (sadb_ext->sadb_ext_type) {
        !           388:                case SADB_EXT_SA:
        !           389:                case SADB_X_EXT_SA2:
        !           390:                {
        !           391:                        struct sadb_sa *sadb_sa = (struct sadb_sa *)p;
        !           392:
        !           393:                        if (i != sizeof(struct sadb_sa)) {
        !           394:                                DPRINTF(("pfkeyv2_parsemessage: bad header "
        !           395:                                    "length for SA extension header %d\n",
        !           396:                                    sadb_ext->sadb_ext_type));
        !           397:                                return (EINVAL);
        !           398:                        }
        !           399:
        !           400:                        if (sadb_sa->sadb_sa_state > SADB_SASTATE_MAX) {
        !           401:                                DPRINTF(("pfkeyv2_parsemessage: unknown SA "
        !           402:                                    "state %d in SA extension header %d\n",
        !           403:                                    sadb_sa->sadb_sa_state,
        !           404:                                    sadb_ext->sadb_ext_type));
        !           405:                                return (EINVAL);
        !           406:                        }
        !           407:
        !           408:                        if (sadb_sa->sadb_sa_state == SADB_SASTATE_DEAD) {
        !           409:                                DPRINTF(("pfkeyv2_parsemessage: cannot set SA "
        !           410:                                    "state to dead, SA extension header %d\n",
        !           411:                                    sadb_ext->sadb_ext_type));
        !           412:                                return (EINVAL);
        !           413:                        }
        !           414:
        !           415:                        if (sadb_sa->sadb_sa_encrypt > SADB_EALG_MAX) {
        !           416:                                DPRINTF(("pfkeyv2_parsemessage: unknown "
        !           417:                                    "encryption algorithm %d in SA extension "
        !           418:                                    "header %d\n", sadb_sa->sadb_sa_encrypt,
        !           419:                                    sadb_ext->sadb_ext_type));
        !           420:                                return (EINVAL);
        !           421:                        }
        !           422:
        !           423:                        if (sadb_sa->sadb_sa_auth > SADB_AALG_MAX) {
        !           424:                                DPRINTF(("pfkeyv2_parsemessage: unknown "
        !           425:                                    "authentication algorithm %d in SA "
        !           426:                                    "extension header %d\n",
        !           427:                                    sadb_sa->sadb_sa_auth,
        !           428:                                    sadb_ext->sadb_ext_type));
        !           429:                                return (EINVAL);
        !           430:                        }
        !           431:
        !           432:                        if (sadb_sa->sadb_sa_replay > 32) {
        !           433:                                DPRINTF(("pfkeyv2_parsemessage: unsupported "
        !           434:                                    "replay window size %d in SA extension "
        !           435:                                    "header %d\n", sadb_sa->sadb_sa_replay,
        !           436:                                    sadb_ext->sadb_ext_type));
        !           437:                                return (EINVAL);
        !           438:                        }
        !           439:                }
        !           440:                break;
        !           441:                case SADB_X_EXT_PROTOCOL:
        !           442:                case SADB_X_EXT_FLOW_TYPE:
        !           443:                        if (i != sizeof(struct sadb_protocol)) {
        !           444:                                DPRINTF(("pfkeyv2_parsemessage: bad "
        !           445:                                    "PROTOCOL/FLOW header length in extension "
        !           446:                                    "header %d\n", sadb_ext->sadb_ext_type));
        !           447:                                return (EINVAL);
        !           448:                        }
        !           449:                        break;
        !           450:                case SADB_X_EXT_POLICY:
        !           451:                        if (i != sizeof(struct sadb_x_policy)) {
        !           452:                                DPRINTF(("pfkeyv2_parsemessage: bad POLICY "
        !           453:                                    "header length\n"));
        !           454:                                return (EINVAL);
        !           455:                        }
        !           456:                        break;
        !           457:                case SADB_EXT_LIFETIME_CURRENT:
        !           458:                case SADB_EXT_LIFETIME_HARD:
        !           459:                case SADB_EXT_LIFETIME_SOFT:
        !           460:                case SADB_X_EXT_LIFETIME_LASTUSE:
        !           461:                        if (i != sizeof(struct sadb_lifetime)) {
        !           462:                                DPRINTF(("pfkeyv2_parsemessage: bad header "
        !           463:                                    "length for LIFETIME extension header "
        !           464:                                    "%d\n", sadb_ext->sadb_ext_type));
        !           465:                                return (EINVAL);
        !           466:                        }
        !           467:                        break;
        !           468:                case SADB_EXT_ADDRESS_SRC:
        !           469:                case SADB_EXT_ADDRESS_DST:
        !           470:                case SADB_X_EXT_SRC_MASK:
        !           471:                case SADB_X_EXT_DST_MASK:
        !           472:                case SADB_X_EXT_SRC_FLOW:
        !           473:                case SADB_X_EXT_DST_FLOW:
        !           474:                case SADB_X_EXT_DST2:
        !           475:                case SADB_EXT_ADDRESS_PROXY:
        !           476:                {
        !           477:                        struct sadb_address *sadb_address =
        !           478:                            (struct sadb_address *)p;
        !           479:                        struct sockaddr *sa = (struct sockaddr *)(p +
        !           480:                            sizeof(struct sadb_address));
        !           481:
        !           482:                        if (i < sizeof(struct sadb_address) +
        !           483:                            sizeof(struct sockaddr)) {
        !           484:                                DPRINTF(("pfkeyv2_parsemessage: bad ADDRESS "
        !           485:                                    "extension header %d length\n",
        !           486:                                    sadb_ext->sadb_ext_type));
        !           487:                                return (EINVAL);
        !           488:                        }
        !           489:
        !           490:                        if (sadb_address->sadb_address_reserved) {
        !           491:                                DPRINTF(("pfkeyv2_parsemessage: ADDRESS "
        !           492:                                    "extension header %d reserved field set\n",
        !           493:                                    sadb_ext->sadb_ext_type));
        !           494:                                return (EINVAL);
        !           495:                        }
        !           496:                        if (sa->sa_len &&
        !           497:                            (i != sizeof(struct sadb_address) +
        !           498:                            PADUP(sa->sa_len))) {
        !           499:                                DPRINTF(("pfkeyv2_parsemessage: bad sockaddr "
        !           500:                                    "length field in ADDRESS extension "
        !           501:                                    "header %d\n", sadb_ext->sadb_ext_type));
        !           502:                                return (EINVAL);
        !           503:                        }
        !           504:
        !           505:                        switch (sa->sa_family) {
        !           506:                        case AF_INET:
        !           507:                                if (sizeof(struct sadb_address) +
        !           508:                                    PADUP(sizeof(struct sockaddr_in)) != i) {
        !           509:                                        DPRINTF(("pfkeyv2_parsemessage: "
        !           510:                                            "invalid ADDRESS extension header "
        !           511:                                            "%d length\n",
        !           512:                                            sadb_ext->sadb_ext_type));
        !           513:                                        return (EINVAL);
        !           514:                                }
        !           515:
        !           516:                                if (sa->sa_len != sizeof(struct sockaddr_in)) {
        !           517:                                        DPRINTF(("pfkeyv2_parsemessage: bad "
        !           518:                                            "sockaddr_in length in ADDRESS "
        !           519:                                            "extension header %d\n",
        !           520:                                            sadb_ext->sadb_ext_type));
        !           521:                                        return (EINVAL);
        !           522:                                }
        !           523:
        !           524:                                /* Only check the right pieces */
        !           525:                                switch (sadb_ext->sadb_ext_type)
        !           526:                                {
        !           527:                                case SADB_X_EXT_SRC_MASK:
        !           528:                                case SADB_X_EXT_DST_MASK:
        !           529:                                case SADB_X_EXT_SRC_FLOW:
        !           530:                                case SADB_X_EXT_DST_FLOW:
        !           531:                                        break;
        !           532:
        !           533:                                default:
        !           534:                                        if (((struct sockaddr_in *)sa)->sin_port) {
        !           535:                                                DPRINTF(("pfkeyv2_parsemessage"
        !           536:                                                    ": port field set in "
        !           537:                                                    "sockaddr_in of ADDRESS "
        !           538:                                                    "extension header %d\n",
        !           539:                                                    sadb_ext->sadb_ext_type));
        !           540:                                                return (EINVAL);
        !           541:                                        }
        !           542:                                        break;
        !           543:                                }
        !           544:
        !           545:                                {
        !           546:                                        char zero[sizeof(((struct sockaddr_in *)sa)->sin_zero)];
        !           547:                                        bzero(zero, sizeof(zero));
        !           548:
        !           549:                                        if (bcmp(&((struct sockaddr_in *)sa)->sin_zero, zero, sizeof(zero))) {
        !           550:                                                DPRINTF(("pfkeyv2_parsemessage"
        !           551:                                                    ": reserved sockaddr_in "
        !           552:                                                    "field non-zero'ed in "
        !           553:                                                    "ADDRESS extension header "
        !           554:                                                    "%d\n",
        !           555:                                                    sadb_ext->sadb_ext_type));
        !           556:                                                return (EINVAL);
        !           557:                                        }
        !           558:                                }
        !           559:                                break;
        !           560: #if INET6
        !           561:                        case AF_INET6:
        !           562:                                if (i != sizeof(struct sadb_address) +
        !           563:                                    PADUP(sizeof(struct sockaddr_in6))) {
        !           564:                                        DPRINTF(("pfkeyv2_parsemessage: "
        !           565:                                            "invalid sockaddr_in6 length in "
        !           566:                                            "ADDRESS extension header %d\n",
        !           567:                                            sadb_ext->sadb_ext_type));
        !           568:                                        return (EINVAL);
        !           569:                                }
        !           570:
        !           571:                                if (sa->sa_len !=
        !           572:                                    sizeof(struct sockaddr_in6)) {
        !           573:                                        DPRINTF(("pfkeyv2_parsemessage: bad "
        !           574:                                            "sockaddr_in6 length in ADDRESS "
        !           575:                                            "extension header %d\n",
        !           576:                                            sadb_ext->sadb_ext_type));
        !           577:                                        return (EINVAL);
        !           578:                                }
        !           579:
        !           580:                                if (((struct sockaddr_in6 *)sa)->sin6_flowinfo) {
        !           581:                                        DPRINTF(("pfkeyv2_parsemessage: "
        !           582:                                            "flowinfo field set in "
        !           583:                                            "sockaddr_in6 of ADDRESS "
        !           584:                                            "extension header %d\n",
        !           585:                                            sadb_ext->sadb_ext_type));
        !           586:                                        return (EINVAL);
        !           587:                                }
        !           588:
        !           589:                                /* Only check the right pieces */
        !           590:                                switch (sadb_ext->sadb_ext_type)
        !           591:                                {
        !           592:                                case SADB_X_EXT_SRC_MASK:
        !           593:                                case SADB_X_EXT_DST_MASK:
        !           594:                                case SADB_X_EXT_SRC_FLOW:
        !           595:                                case SADB_X_EXT_DST_FLOW:
        !           596:                                        break;
        !           597:
        !           598:                                default:
        !           599:                                        if (((struct sockaddr_in6 *)sa)->sin6_port) {
        !           600:                                                DPRINTF(("pfkeyv2_parsemessage"
        !           601:                                                    ": port field set in "
        !           602:                                                    "sockaddr_in6 of ADDRESS "
        !           603:                                                    "extension header %d\n",
        !           604:                                                    sadb_ext->sadb_ext_type));
        !           605:                                                return (EINVAL);
        !           606:                                        }
        !           607:                                        break;
        !           608:                                }
        !           609:                                break;
        !           610: #endif /* INET6 */
        !           611:                        default:
        !           612:                                if (sadb_msg->sadb_msg_satype ==
        !           613:                                    SADB_X_SATYPE_TCPSIGNATURE &&
        !           614:                                    sa->sa_family == 0)
        !           615:                                        break;
        !           616:                                DPRINTF(("pfkeyv2_parsemessage: unknown "
        !           617:                                    "address family %d in ADDRESS extension "
        !           618:                                    "header %d\n",
        !           619:                                    sa->sa_family, sadb_ext->sadb_ext_type));
        !           620:                                return (EINVAL);
        !           621:                        }
        !           622:                }
        !           623:                break;
        !           624:                case SADB_EXT_KEY_AUTH:
        !           625:                case SADB_EXT_KEY_ENCRYPT:
        !           626:                {
        !           627:                        struct sadb_key *sadb_key = (struct sadb_key *)p;
        !           628:
        !           629:                        if (i < sizeof(struct sadb_key)) {
        !           630:                                DPRINTF(("pfkeyv2_parsemessage: bad header "
        !           631:                                    "length in KEY extension header %d\n",
        !           632:                                    sadb_ext->sadb_ext_type));
        !           633:                                return (EINVAL);
        !           634:                        }
        !           635:
        !           636:                        if (!sadb_key->sadb_key_bits) {
        !           637:                                DPRINTF(("pfkeyv2_parsemessage: key length "
        !           638:                                    "unset in KEY extension header %d\n",
        !           639:                                    sadb_ext->sadb_ext_type));
        !           640:                                return (EINVAL);
        !           641:                        }
        !           642:
        !           643:                        if (((sadb_key->sadb_key_bits + 63) / 64) * sizeof(uint64_t) != i - sizeof(struct sadb_key)) {
        !           644:                                DPRINTF(("pfkeyv2_parsemessage: invalid key "
        !           645:                                    "length in KEY extension header %d\n",
        !           646:                                    sadb_ext->sadb_ext_type));
        !           647:                                return (EINVAL);
        !           648:                        }
        !           649:
        !           650:                        if (sadb_key->sadb_key_reserved) {
        !           651:                                DPRINTF(("pfkeyv2_parsemessage: reserved field"
        !           652:                                    " set in KEY extension header %d\n",
        !           653:                                    sadb_ext->sadb_ext_type));
        !           654:                                return (EINVAL);
        !           655:                        }
        !           656:                }
        !           657:                break;
        !           658:                case SADB_X_EXT_LOCAL_AUTH:
        !           659:                case SADB_X_EXT_REMOTE_AUTH:
        !           660:                {
        !           661:                        struct sadb_x_cred *sadb_cred =
        !           662:                            (struct sadb_x_cred *)p;
        !           663:
        !           664:                        if (i < sizeof(struct sadb_x_cred)) {
        !           665:                                DPRINTF(("pfkeyv2_parsemessage: bad header "
        !           666:                                    "length for AUTH extension header %d\n",
        !           667:                                    sadb_ext->sadb_ext_type));
        !           668:                                return (EINVAL);
        !           669:                        }
        !           670:
        !           671:                        if (sadb_cred->sadb_x_cred_type > SADB_X_AUTHTYPE_MAX) {
        !           672:                                DPRINTF(("pfkeyv2_parsemessage: unknown auth "
        !           673:                                    "type %d in AUTH extension header %d\n",
        !           674:                                    sadb_cred->sadb_x_cred_type,
        !           675:                                    sadb_ext->sadb_ext_type));
        !           676:                                return (EINVAL);
        !           677:                        }
        !           678:
        !           679:                        if (sadb_cred->sadb_x_cred_reserved) {
        !           680:                                DPRINTF(("pfkeyv2_parsemessage: reserved field"
        !           681:                                    " set in AUTH extension header %d\n",
        !           682:                                    sadb_ext->sadb_ext_type));
        !           683:                                return (EINVAL);
        !           684:                        }
        !           685:                }
        !           686:                break;
        !           687:                case SADB_X_EXT_LOCAL_CREDENTIALS:
        !           688:                case SADB_X_EXT_REMOTE_CREDENTIALS:
        !           689:                {
        !           690:                        struct sadb_x_cred *sadb_cred =
        !           691:                            (struct sadb_x_cred *)p;
        !           692:
        !           693:                        if (i < sizeof(struct sadb_x_cred)) {
        !           694:                                DPRINTF(("pfkeyv2_parsemessage: bad header "
        !           695:                                    "length of CREDENTIALS extension header "
        !           696:                                    "%d\n", sadb_ext->sadb_ext_type));
        !           697:                                return (EINVAL);
        !           698:                        }
        !           699:
        !           700:                        if (sadb_cred->sadb_x_cred_type > SADB_X_CREDTYPE_MAX) {
        !           701:                                DPRINTF(("pfkeyv2_parsemessage: unknown "
        !           702:                                    "credential type %d in CREDENTIALS "
        !           703:                                    "extension header %d\n",
        !           704:                                    sadb_cred->sadb_x_cred_type,
        !           705:                                    sadb_ext->sadb_ext_type));
        !           706:                                return (EINVAL);
        !           707:                        }
        !           708:
        !           709:                        if (sadb_cred->sadb_x_cred_reserved) {
        !           710:                                DPRINTF(("pfkeyv2_parsemessage: reserved "
        !           711:                                    "field set in CREDENTIALS extension "
        !           712:                                    "header %d\n", sadb_ext->sadb_ext_type));
        !           713:                                return (EINVAL);
        !           714:                        }
        !           715:                }
        !           716:                break;
        !           717:                case SADB_EXT_IDENTITY_SRC:
        !           718:                case SADB_EXT_IDENTITY_DST:
        !           719:                {
        !           720:                        struct sadb_ident *sadb_ident = (struct sadb_ident *)p;
        !           721:
        !           722:                        if (i < sizeof(struct sadb_ident)) {
        !           723:                                DPRINTF(("pfkeyv2_parsemessage: bad header "
        !           724:                                    "length of IDENTITY extension header %d\n",
        !           725:                                    sadb_ext->sadb_ext_type));
        !           726:                                return (EINVAL);
        !           727:                        }
        !           728:
        !           729:                        if (sadb_ident->sadb_ident_type > SADB_IDENTTYPE_MAX) {
        !           730:                                DPRINTF(("pfkeyv2_parsemessage: unknown "
        !           731:                                    "identity type %d in IDENTITY extension "
        !           732:                                    "header %d\n",
        !           733:                                    sadb_ident->sadb_ident_type,
        !           734:                                    sadb_ext->sadb_ext_type));
        !           735:                                return (EINVAL);
        !           736:                        }
        !           737:
        !           738:                        if (sadb_ident->sadb_ident_reserved) {
        !           739:                                DPRINTF(("pfkeyv2_parsemessage: reserved "
        !           740:                                    "field set in IDENTITY extension header "
        !           741:                                    "%d\n", sadb_ext->sadb_ext_type));
        !           742:                                return (EINVAL);
        !           743:                        }
        !           744:
        !           745:                        if (i > sizeof(struct sadb_ident)) {
        !           746:                                char *c =
        !           747:                                    (char *)(p + sizeof(struct sadb_ident));
        !           748:                                int j;
        !           749:
        !           750:                                if (*(char *)(p + i - 1)) {
        !           751:                                        DPRINTF(("pfkeyv2_parsemessage: non "
        !           752:                                            "NUL-terminated identity in "
        !           753:                                            "IDENTITY extension header %d\n",
        !           754:                                            sadb_ext->sadb_ext_type));
        !           755:                                        return (EINVAL);
        !           756:                                }
        !           757:
        !           758:                                j = PADUP(strlen(c) + 1) +
        !           759:                                    sizeof(struct sadb_ident);
        !           760:
        !           761:                                if (i != j) {
        !           762:                                        DPRINTF(("pfkeyv2_parsemessage: actual"
        !           763:                                            " identity length does not match "
        !           764:                                            "expected length in identity "
        !           765:                                            "extension header %d\n",
        !           766:                                            sadb_ext->sadb_ext_type));
        !           767:                                        return (EINVAL);
        !           768:                                }
        !           769:                        }
        !           770:                }
        !           771:                break;
        !           772:                case SADB_EXT_SENSITIVITY:
        !           773:                {
        !           774:                        struct sadb_sens *sadb_sens = (struct sadb_sens *)p;
        !           775:
        !           776:                        if (i < sizeof(struct sadb_sens)) {
        !           777:                                DPRINTF(("pfkeyv2_parsemessage: bad header "
        !           778:                                    "length for SENSITIVITY extension "
        !           779:                                    "header\n"));
        !           780:                                return (EINVAL);
        !           781:                        }
        !           782:
        !           783:                        if (i != (sadb_sens->sadb_sens_sens_len +
        !           784:                            sadb_sens->sadb_sens_integ_len) *
        !           785:                            sizeof(uint64_t) +
        !           786:                            sizeof(struct sadb_sens)) {
        !           787:                                DPRINTF(("pfkeyv2_parsemessage: bad payload "
        !           788:                                    "length for SENSITIVITY extension "
        !           789:                                    "header\n"));
        !           790:                                return (EINVAL);
        !           791:                        }
        !           792:                }
        !           793:                break;
        !           794:                case SADB_EXT_PROPOSAL:
        !           795:                {
        !           796:                        struct sadb_prop *sadb_prop = (struct sadb_prop *)p;
        !           797:
        !           798:                        if (i < sizeof(struct sadb_prop)) {
        !           799:                                DPRINTF(("pfkeyv2_parsemessage: bad PROPOSAL "
        !           800:                                    "header length\n"));
        !           801:                                return (EINVAL);
        !           802:                        }
        !           803:
        !           804:                        if (sadb_prop->sadb_prop_reserved) {
        !           805:                                DPRINTF(("pfkeyv2_parsemessage: reserved field"
        !           806:                                    "set in PROPOSAL extension header\n"));
        !           807:                                return (EINVAL);
        !           808:                        }
        !           809:
        !           810:                        if ((i - sizeof(struct sadb_prop)) %
        !           811:                            sizeof(struct sadb_comb)) {
        !           812:                                DPRINTF(("pfkeyv2_parsemessage: bad proposal "
        !           813:                                    "length\n"));
        !           814:                                return (EINVAL);
        !           815:                        }
        !           816:
        !           817:                        {
        !           818:                                struct sadb_comb *sadb_comb =
        !           819:                                    (struct sadb_comb *)(p +
        !           820:                                        sizeof(struct sadb_prop));
        !           821:                                int j;
        !           822:
        !           823:                                for (j = 0;
        !           824:                                    j < (i - sizeof(struct sadb_prop))/
        !           825:                                    sizeof(struct sadb_comb);
        !           826:                                    j++) {
        !           827:                                        if (sadb_comb->sadb_comb_auth >
        !           828:                                            SADB_AALG_MAX) {
        !           829:                                                DPRINTF(("pfkeyv2_parsemessage"
        !           830:                                                    ": unknown authentication "
        !           831:                                                    "algorithm %d in "
        !           832:                                                    "PROPOSAL\n",
        !           833:                                                    sadb_comb->sadb_comb_auth));
        !           834:                                                return (EINVAL);
        !           835:                                        }
        !           836:
        !           837:                                        if (sadb_comb->sadb_comb_encrypt >
        !           838:                                            SADB_EALG_MAX) {
        !           839:                                                DPRINTF(("pfkeyv2_parsemessage"
        !           840:                                                    ": unknown encryption "
        !           841:                                                    "algorithm %d in "
        !           842:                                                    "PROPOSAL\n",
        !           843:                                                    sadb_comb->sadb_comb_encrypt));
        !           844:                                                return (EINVAL);
        !           845:                                        }
        !           846:
        !           847:                                        if (sadb_comb->sadb_comb_reserved) {
        !           848:                                                DPRINTF(("pfkeyv2_parsemessage"
        !           849:                                                    ": reserved field set in "
        !           850:                                                    "COMB header\n"));
        !           851:                                                return (EINVAL);
        !           852:                                        }
        !           853:                                }
        !           854:                        }
        !           855:                }
        !           856:                break;
        !           857:                case SADB_EXT_SUPPORTED_AUTH:
        !           858:                case SADB_EXT_SUPPORTED_ENCRYPT:
        !           859:                case SADB_X_EXT_SUPPORTED_COMP:
        !           860:                {
        !           861:                        struct sadb_supported *sadb_supported =
        !           862:                            (struct sadb_supported *)p;
        !           863:                        int j;
        !           864:
        !           865:                        if (i < sizeof(struct sadb_supported)) {
        !           866:                                DPRINTF(("pfkeyv2_parsemessage: bad header "
        !           867:                                    "length for SUPPORTED extension header "
        !           868:                                    "%d\n", sadb_ext->sadb_ext_type));
        !           869:                                return (EINVAL);
        !           870:                        }
        !           871:
        !           872:                        if (sadb_supported->sadb_supported_reserved) {
        !           873:                                DPRINTF(("pfkeyv2_parsemessage: reserved "
        !           874:                                    "field set in SUPPORTED extension "
        !           875:                                    "header %d\n", sadb_ext->sadb_ext_type));
        !           876:                                return (EINVAL);
        !           877:                        }
        !           878:
        !           879:                        {
        !           880:                                struct sadb_alg *sadb_alg =
        !           881:                                    (struct sadb_alg *)(p +
        !           882:                                        sizeof(struct sadb_supported));
        !           883:                                int max_alg;
        !           884:
        !           885:                                max_alg = sadb_ext->sadb_ext_type ==
        !           886:                                    SADB_EXT_SUPPORTED_AUTH ?
        !           887:                                    SADB_AALG_MAX : SADB_EXT_SUPPORTED_ENCRYPT ?
        !           888:                                    SADB_EALG_MAX : SADB_X_CALG_MAX;
        !           889:
        !           890:                                for (j = 0;
        !           891:                                    j < sadb_supported->sadb_supported_len - 1;
        !           892:                                    j++) {
        !           893:                                        if (sadb_alg->sadb_alg_id > max_alg) {
        !           894:                                                DPRINTF(("pfkeyv2_parsemessage"
        !           895:                                                    ": unknown algorithm %d "
        !           896:                                                    "in SUPPORTED extension "
        !           897:                                                    "header %d\n",
        !           898:                                                    sadb_alg->sadb_alg_id,
        !           899:                                                    sadb_ext->sadb_ext_type));
        !           900:                                                return (EINVAL);
        !           901:                                        }
        !           902:
        !           903:                                        if (sadb_alg->sadb_alg_reserved) {
        !           904:                                                DPRINTF(("pfkeyv2_parsemessage"
        !           905:                                                    ": reserved field set in "
        !           906:                                                    "supported algorithms "
        !           907:                                                    "header inside SUPPORTED "
        !           908:                                                    "extension header %d\n",
        !           909:                                                    sadb_ext->sadb_ext_type));
        !           910:                                                return (EINVAL);
        !           911:                                        }
        !           912:
        !           913:                                        sadb_alg++;
        !           914:                                }
        !           915:                        }
        !           916:                }
        !           917:                break;
        !           918:                case SADB_EXT_SPIRANGE:
        !           919:                {
        !           920:                        struct sadb_spirange *sadb_spirange =
        !           921:                            (struct sadb_spirange *)p;
        !           922:
        !           923:                        if (i != sizeof(struct sadb_spirange)) {
        !           924:                                DPRINTF(("pfkeyv2_parsemessage: bad header "
        !           925:                                    "length of SPIRANGE extension header\n"));
        !           926:                                return (EINVAL);
        !           927:                        }
        !           928:
        !           929:                        if (sadb_spirange->sadb_spirange_min >
        !           930:                            sadb_spirange->sadb_spirange_max) {
        !           931:                                DPRINTF(("pfkeyv2_parsemessage: bad SPI "
        !           932:                                    "range\n"));
        !           933:                                return (EINVAL);
        !           934:                        }
        !           935:                }
        !           936:                break;
        !           937:                case SADB_X_EXT_UDPENCAP:
        !           938:                        if (i != sizeof(struct sadb_x_udpencap)) {
        !           939:                                DPRINTF(("pfkeyv2_parsemessage: bad UDPENCAP "
        !           940:                                    "header length\n"));
        !           941:                                return (EINVAL);
        !           942:                        }
        !           943:                        break;
        !           944: #if NPF > 0
        !           945:                case SADB_X_EXT_TAG:
        !           946:                        if (i < sizeof(struct sadb_x_tag)) {
        !           947:                                DPRINTF(("pfkeyv2_parsemessage: "
        !           948:                                    "TAG extension header too small"));
        !           949:                                return (EINVAL);
        !           950:                        }
        !           951:                        if (i > (sizeof(struct sadb_x_tag) +
        !           952:                            PF_TAG_NAME_SIZE)) {
        !           953:                                DPRINTF(("pfkeyv2_parsemessage: "
        !           954:                                    "TAG extension header too long"));
        !           955:                                return (EINVAL);
        !           956:                        }
        !           957:                        break;
        !           958: #endif
        !           959:                default:
        !           960:                        DPRINTF(("pfkeyv2_parsemessage: unknown extension "
        !           961:                            "header type %d\n",
        !           962:                            sadb_ext->sadb_ext_type));
        !           963:                        return (EINVAL);
        !           964:                }
        !           965:
        !           966:                headers[sadb_ext->sadb_ext_type] = p;
        !           967:                p += i;
        !           968:                left -= i;
        !           969:        }
        !           970:
        !           971:        if (left) {
        !           972:                DPRINTF(("pfkeyv2_parsemessage: message too long\n"));
        !           973:                return (EINVAL);
        !           974:        }
        !           975:
        !           976:        {
        !           977:                uint64_t required;
        !           978:
        !           979:                required = sadb_exts_required_in[sadb_msg->sadb_msg_type];
        !           980:
        !           981:                if ((seen & required) != required) {
        !           982:                        DPRINTF(("pfkeyv2_parsemessage: required fields "
        !           983:                            "missing\n"));
        !           984:                        return (EINVAL);
        !           985:                }
        !           986:        }
        !           987:
        !           988:        switch (((struct sadb_msg *)headers[0])->sadb_msg_type) {
        !           989:        case SADB_UPDATE:
        !           990:                if (((struct sadb_sa *)headers[SADB_EXT_SA])->sadb_sa_state !=
        !           991:                    SADB_SASTATE_MATURE) {
        !           992:                        DPRINTF(("pfkeyv2_parsemessage: updating non-mature "
        !           993:                            "SA prohibited\n"));
        !           994:                        return (EINVAL);
        !           995:                }
        !           996:                break;
        !           997:        case SADB_ADD:
        !           998:                if (((struct sadb_sa *)headers[SADB_EXT_SA])->sadb_sa_state !=
        !           999:                    SADB_SASTATE_MATURE) {
        !          1000:                        DPRINTF(("pfkeyv2_parsemessage: adding non-mature "
        !          1001:                            "SA prohibited\n"));
        !          1002:                        return (EINVAL);
        !          1003:                }
        !          1004:                break;
        !          1005:        }
        !          1006:
        !          1007:        return (0);
        !          1008: }

CVSweb