root/net/pfkeyv2_parsemessage.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. pfkeyv2_parsemessage

    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 }

/* [<][>][^][v][top][bottom][index][help] */