LCOV - code coverage report
Current view: top level - net - pfkeyv2_parsemessage.c (source / functions) Hit Total Coverage
Test: 6.4 Lines: 0 204 0.0 %
Date: 2018-10-19 03:25:38 Functions: 0 1 0.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.13