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