[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

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