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