xref: /netbsd-src/crypto/dist/ipsec-tools/src/setkey/parse.y (revision fa28c6faa16e0b00edee7acdcaf4899797043def)
1 /*	$NetBSD: parse.y,v 1.17 2014/09/10 21:04:08 christos Exp $	*/
2 
3 /*	$KAME: parse.y,v 1.81 2003/07/01 04:01:48 itojun Exp $	*/
4 
5 /*
6  * Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project.
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  * 3. Neither the name of the project nor the names of its contributors
18  *    may be used to endorse or promote products derived from this software
19  *    without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31  * SUCH DAMAGE.
32  */
33 
34 %{
35 #ifdef HAVE_CONFIG_H
36 #include "config.h"
37 #endif
38 
39 #include <sys/types.h>
40 #include <sys/param.h>
41 #include <sys/socket.h>
42 
43 #include <netinet/in.h>
44 #include <net/pfkeyv2.h>
45 #include PATH_IPSEC_H
46 #include <arpa/inet.h>
47 
48 #include <string.h>
49 #include <unistd.h>
50 #include <stdio.h>
51 #include <netdb.h>
52 #include <ctype.h>
53 #include <errno.h>
54 #include <stdlib.h>
55 
56 #include "libpfkey.h"
57 #include "vchar.h"
58 #include "extern.h"
59 
60 #define DEFAULT_NATT_PORT	4500
61 
62 #ifndef UDP_ENCAP_ESPINUDP
63 #define UDP_ENCAP_ESPINUDP	2
64 #endif
65 
66 #define ATOX(c) \
67   (isdigit((int)c) ? (c - '0') : \
68     (isupper((int)c) ? (c - 'A' + 10) : (c - 'a' + 10)))
69 
70 u_int32_t p_spi;
71 u_int p_ext, p_alg_enc, p_alg_auth, p_replay, p_mode;
72 u_int32_t p_reqid;
73 u_int p_key_enc_len, p_key_auth_len;
74 const char *p_key_enc;
75 const char *p_key_auth;
76 time_t p_lt_hard, p_lt_soft;
77 size_t p_lb_hard, p_lb_soft;
78 
79 struct security_ctx {
80 	u_int8_t doi;
81 	u_int8_t alg;
82 	u_int16_t len;
83 	char *buf;
84 };
85 
86 struct security_ctx sec_ctx;
87 
88 static u_int p_natt_type, p_esp_frag;
89 static struct addrinfo * p_natt_oa = NULL;
90 
91 static int p_aiflags = 0, p_aifamily = PF_UNSPEC;
92 
93 static struct addrinfo *parse_addr __P((char *, char *));
94 static int fix_portstr __P((int, vchar_t *, vchar_t *, vchar_t *));
95 static int setvarbuf __P((char *, int *, struct sadb_ext *, int,
96     const void *, int));
97 void parse_init __P((void));
98 void free_buffer __P((void));
99 
100 int setkeymsg0 __P((struct sadb_msg *, unsigned int, unsigned int, size_t));
101 static int setkeymsg_spdaddr __P((unsigned int, unsigned int, vchar_t *,
102 	struct addrinfo *, int, struct addrinfo *, int));
103 static int setkeymsg_spdaddr_tag __P((unsigned int, char *, vchar_t *));
104 static int setkeymsg_addr __P((unsigned int, unsigned int,
105 	struct addrinfo *, struct addrinfo *, int));
106 static int setkeymsg_add __P((unsigned int, unsigned int,
107 	struct addrinfo *, struct addrinfo *));
108 %}
109 
110 %union {
111 	int num;
112 	unsigned long ulnum;
113 	vchar_t val;
114 	struct addrinfo *res;
115 }
116 
117 %token EOT SLASH BLCL ELCL
118 %token ADD GET DELETE DELETEALL FLUSH DUMP EXIT
119 %token PR_ESP PR_AH PR_IPCOMP PR_ESPUDP PR_TCP
120 %token F_PROTOCOL F_AUTH F_ENC F_REPLAY F_COMP F_RAWCPI
121 %token F_MODE MODE F_REQID
122 %token F_EXT EXTENSION NOCYCLICSEQ
123 %token ALG_AUTH ALG_AUTH_NOKEY
124 %token ALG_ENC ALG_ENC_NOKEY ALG_ENC_DESDERIV ALG_ENC_DES32IV ALG_ENC_OLD
125 %token ALG_COMP
126 %token F_LIFETIME_HARD F_LIFETIME_SOFT
127 %token F_LIFEBYTE_HARD F_LIFEBYTE_SOFT
128 %token F_ESPFRAG
129 %token DECSTRING QUOTEDSTRING HEXSTRING STRING ANY
130 	/* SPD management */
131 %token SPDADD SPDUPDATE SPDDELETE SPDDUMP SPDFLUSH
132 %token F_POLICY PL_REQUESTS
133 %token F_AIFLAGS
134 %token TAGGED
135 %token SECURITY_CTX
136 
137 %type <num> prefix protocol_spec upper_spec
138 %type <num> ALG_ENC ALG_ENC_DESDERIV ALG_ENC_DES32IV ALG_ENC_OLD ALG_ENC_NOKEY
139 %type <num> ALG_AUTH ALG_AUTH_NOKEY
140 %type <num> ALG_COMP
141 %type <num> PR_ESP PR_AH PR_IPCOMP PR_ESPUDP PR_TCP
142 %type <num> EXTENSION MODE
143 %type <ulnum> DECSTRING
144 %type <val> PL_REQUESTS portstr portstr_notempty key_string
145 %type <val> policy_requests
146 %type <val> QUOTEDSTRING HEXSTRING STRING
147 %type <val> F_AIFLAGS
148 %type <val> upper_misc_spec policy_spec
149 %type <res> ipaddr ipandport
150 
151 %%
152 commands
153 	:	/*NOTHING*/
154 	|	commands command
155 		{
156 			free_buffer();
157 			parse_init();
158 		}
159 	;
160 
161 command
162 	:	add_command
163 	|	get_command
164 	|	delete_command
165 	|	deleteall_command
166 	|	flush_command
167 	|	dump_command
168 	|	exit_command
169 	|	spdadd_command
170 	|	spdupdate_command
171 	|	spddelete_command
172 	|	spddump_command
173 	|	spdflush_command
174 	;
175 	/* commands concerned with management, there is in tail of this file. */
176 
177 	/* add command */
178 add_command
179 	:	ADD ipaddropts ipandport ipandport protocol_spec spi extension_spec algorithm_spec EOT
180 		{
181 			int status;
182 
183 			status = setkeymsg_add(SADB_ADD, $5, $3, $4);
184 			if (status < 0)
185 				return -1;
186 		}
187 	;
188 
189 	/* delete */
190 delete_command
191 	:	DELETE ipaddropts ipandport ipandport protocol_spec spi extension_spec EOT
192 		{
193 			int status;
194 
195 			if ($3->ai_next || $4->ai_next) {
196 				yyerror("multiple address specified");
197 				return -1;
198 			}
199 			if (p_mode != IPSEC_MODE_ANY)
200 				yyerror("WARNING: mode is obsolete");
201 
202 			status = setkeymsg_addr(SADB_DELETE, $5, $3, $4, 0);
203 			if (status < 0)
204 				return -1;
205 		}
206 	;
207 
208 	/* deleteall command */
209 deleteall_command
210 	:	DELETEALL ipaddropts ipaddr ipaddr protocol_spec EOT
211 		{
212 #ifndef __linux__
213 			if (setkeymsg_addr(SADB_DELETE, $5, $3, $4, 1) < 0)
214 				return -1;
215 #else /* __linux__ */
216 			/* linux strictly adheres to RFC2367, and returns
217 			 * an error if we send an SADB_DELETE request without
218 			 * an SPI. Therefore, we must first retrieve a list
219 			 * of SPIs for all matching SADB entries, and then
220 			 * delete each one separately. */
221 			u_int32_t *spi;
222 			int i, n;
223 
224 			spi = sendkeymsg_spigrep($5, $3, $4, &n);
225 			for (i = 0; i < n; i++) {
226 				p_spi = spi[i];
227 				if (setkeymsg_addr(SADB_DELETE,
228 							$5, $3, $4, 0) < 0)
229 					return -1;
230 			}
231 			free(spi);
232 #endif /* __linux__ */
233 		}
234 	;
235 
236 	/* get command */
237 get_command
238 	:	GET ipaddropts ipandport ipandport protocol_spec spi extension_spec EOT
239 		{
240 			int status;
241 
242 			if (p_mode != IPSEC_MODE_ANY)
243 				yyerror("WARNING: mode is obsolete");
244 
245 			status = setkeymsg_addr(SADB_GET, $5, $3, $4, 0);
246 			if (status < 0)
247 				return -1;
248 		}
249 	;
250 
251 	/* flush */
252 flush_command
253 	:	FLUSH protocol_spec EOT
254 		{
255 			struct sadb_msg msg;
256 			setkeymsg0(&msg, SADB_FLUSH, $2, sizeof(msg));
257 			sendkeymsg((char *)&msg, sizeof(msg));
258 		}
259 	;
260 
261 	/* dump */
262 dump_command
263 	:	DUMP protocol_spec EOT
264 		{
265 			struct sadb_msg msg;
266 			setkeymsg0(&msg, SADB_DUMP, $2, sizeof(msg));
267 			sendkeymsg((char *)&msg, sizeof(msg));
268 		}
269 	;
270 
271 protocol_spec
272 	:	/*NOTHING*/
273 		{
274 			$$ = SADB_SATYPE_UNSPEC;
275 		}
276 	|	PR_ESP
277 		{
278 			$$ = SADB_SATYPE_ESP;
279 			if ($1 == 1)
280 				p_ext |= SADB_X_EXT_OLD;
281 			else
282 				p_ext &= ~SADB_X_EXT_OLD;
283 		}
284 	|	PR_AH
285 		{
286 			$$ = SADB_SATYPE_AH;
287 			if ($1 == 1)
288 				p_ext |= SADB_X_EXT_OLD;
289 			else
290 				p_ext &= ~SADB_X_EXT_OLD;
291 		}
292 	|	PR_IPCOMP
293 		{
294 			$$ = SADB_X_SATYPE_IPCOMP;
295 		}
296 	|	PR_ESPUDP
297 		{
298 			$$ = SADB_SATYPE_ESP;
299 			p_ext &= ~SADB_X_EXT_OLD;
300 			p_natt_oa = 0;
301 			p_natt_type = UDP_ENCAP_ESPINUDP;
302 		}
303 	|	PR_ESPUDP ipaddr
304 		{
305 			$$ = SADB_SATYPE_ESP;
306 			p_ext &= ~SADB_X_EXT_OLD;
307 			p_natt_oa = $2;
308 			p_natt_type = UDP_ENCAP_ESPINUDP;
309 		}
310 	|	PR_TCP
311 		{
312 #ifdef SADB_X_SATYPE_TCPSIGNATURE
313 			$$ = SADB_X_SATYPE_TCPSIGNATURE;
314 #endif
315 		}
316 	;
317 
318 spi
319 	:	DECSTRING { p_spi = $1; }
320 	|	HEXSTRING
321 		{
322 			char *ep;
323 			unsigned long v;
324 
325 			ep = NULL;
326 			v = strtoul($1.buf, &ep, 16);
327 			if (!ep || *ep) {
328 				yyerror("invalid SPI");
329 				return -1;
330 			}
331 			if (v & ~0xffffffff) {
332 				yyerror("SPI too big.");
333 				return -1;
334 			}
335 
336 			p_spi = v;
337 		}
338 	;
339 
340 algorithm_spec
341 	:	esp_spec
342 	|	ah_spec
343 	|	ipcomp_spec
344 	;
345 
346 esp_spec
347 	:	F_ENC enc_alg F_AUTH auth_alg
348 	|	F_ENC enc_alg
349 	;
350 
351 ah_spec
352 	:	F_AUTH auth_alg
353 	;
354 
355 ipcomp_spec
356 	:	F_COMP ALG_COMP
357 		{
358 			if ($2 < 0) {
359 				yyerror("unsupported algorithm");
360 				return -1;
361 			}
362 			p_alg_enc = $2;
363 		}
364 	|	F_COMP ALG_COMP F_RAWCPI
365 		{
366 			if ($2 < 0) {
367 				yyerror("unsupported algorithm");
368 				return -1;
369 			}
370 			p_alg_enc = $2;
371 			p_ext |= SADB_X_EXT_RAWCPI;
372 		}
373 	;
374 
375 enc_alg
376 	:	ALG_ENC_NOKEY {
377 			if ($1 < 0) {
378 				yyerror("unsupported algorithm");
379 				return -1;
380 			}
381 			p_alg_enc = $1;
382 
383 			p_key_enc_len = 0;
384 			p_key_enc = "";
385 			if (ipsec_check_keylen(SADB_EXT_SUPPORTED_ENCRYPT,
386 			    p_alg_enc, PFKEY_UNUNIT64(p_key_enc_len)) < 0) {
387 				yyerror(ipsec_strerror());
388 				return -1;
389 			}
390 		}
391 	|	ALG_ENC key_string {
392 			if ($1 < 0) {
393 				yyerror("unsupported algorithm");
394 				return -1;
395 			}
396 			p_alg_enc = $1;
397 
398 			p_key_enc_len = $2.len;
399 			p_key_enc = $2.buf;
400 			if (ipsec_check_keylen(SADB_EXT_SUPPORTED_ENCRYPT,
401 			    p_alg_enc, PFKEY_UNUNIT64(p_key_enc_len)) < 0) {
402 				yyerror(ipsec_strerror());
403 				return -1;
404 			}
405 		}
406 	|	ALG_ENC_OLD {
407 			if ($1 < 0) {
408 				yyerror("unsupported algorithm");
409 				return -1;
410 			}
411 			yyerror("WARNING: obsolete algorithm");
412 			p_alg_enc = $1;
413 
414 			p_key_enc_len = 0;
415 			p_key_enc = "";
416 			if (ipsec_check_keylen(SADB_EXT_SUPPORTED_ENCRYPT,
417 			    p_alg_enc, PFKEY_UNUNIT64(p_key_enc_len)) < 0) {
418 				yyerror(ipsec_strerror());
419 				return -1;
420 			}
421 		}
422 	|	ALG_ENC_DESDERIV key_string
423 		{
424 			if ($1 < 0) {
425 				yyerror("unsupported algorithm");
426 				return -1;
427 			}
428 			p_alg_enc = $1;
429 			if (p_ext & SADB_X_EXT_OLD) {
430 				yyerror("algorithm mismatched");
431 				return -1;
432 			}
433 			p_ext |= SADB_X_EXT_DERIV;
434 
435 			p_key_enc_len = $2.len;
436 			p_key_enc = $2.buf;
437 			if (ipsec_check_keylen(SADB_EXT_SUPPORTED_ENCRYPT,
438 			    p_alg_enc, PFKEY_UNUNIT64(p_key_enc_len)) < 0) {
439 				yyerror(ipsec_strerror());
440 				return -1;
441 			}
442 		}
443 	|	ALG_ENC_DES32IV key_string
444 		{
445 			if ($1 < 0) {
446 				yyerror("unsupported algorithm");
447 				return -1;
448 			}
449 			p_alg_enc = $1;
450 			if (!(p_ext & SADB_X_EXT_OLD)) {
451 				yyerror("algorithm mismatched");
452 				return -1;
453 			}
454 			p_ext |= SADB_X_EXT_IV4B;
455 
456 			p_key_enc_len = $2.len;
457 			p_key_enc = $2.buf;
458 			if (ipsec_check_keylen(SADB_EXT_SUPPORTED_ENCRYPT,
459 			    p_alg_enc, PFKEY_UNUNIT64(p_key_enc_len)) < 0) {
460 				yyerror(ipsec_strerror());
461 				return -1;
462 			}
463 		}
464 	;
465 
466 auth_alg
467 	:	ALG_AUTH key_string {
468 			if ($1 < 0) {
469 				yyerror("unsupported algorithm");
470 				return -1;
471 			}
472 			p_alg_auth = $1;
473 
474 			p_key_auth_len = $2.len;
475 			p_key_auth = $2.buf;
476 #ifdef SADB_X_AALG_TCP_MD5
477 			if (p_alg_auth == SADB_X_AALG_TCP_MD5) {
478 				if ((p_key_auth_len < 1) ||
479 				    (p_key_auth_len > 80))
480 					return -1;
481 			} else
482 #endif
483 			{
484 				if (ipsec_check_keylen(SADB_EXT_SUPPORTED_AUTH,
485 				    p_alg_auth,
486 				    PFKEY_UNUNIT64(p_key_auth_len)) < 0) {
487 					yyerror(ipsec_strerror());
488 					return -1;
489 				}
490 			}
491 		}
492 	|	ALG_AUTH_NOKEY {
493 			if ($1 < 0) {
494 				yyerror("unsupported algorithm");
495 				return -1;
496 			}
497 			p_alg_auth = $1;
498 
499 			p_key_auth_len = 0;
500 			p_key_auth = NULL;
501 		}
502 	;
503 
504 key_string
505 	:	QUOTEDSTRING
506 		{
507 			$$ = $1;
508 		}
509 	|	HEXSTRING
510 		{
511 			caddr_t pp_key;
512 			caddr_t bp;
513 			caddr_t yp = $1.buf;
514 			int l;
515 
516 			l = strlen(yp) % 2 + strlen(yp) / 2;
517 			if ((pp_key = malloc(l)) == 0) {
518 				yyerror("not enough core");
519 				return -1;
520 			}
521 			memset(pp_key, 0, l);
522 
523 			bp = pp_key;
524 			if (strlen(yp) % 2) {
525 				*bp = ATOX(yp[0]);
526 				yp++, bp++;
527 			}
528 			while (*yp) {
529 				*bp = (ATOX(yp[0]) << 4) | ATOX(yp[1]);
530 				yp += 2, bp++;
531 			}
532 
533 			$$.len = l;
534 			$$.buf = pp_key;
535 		}
536 	;
537 
538 extension_spec
539 	:	/*NOTHING*/
540 	|	extension_spec extension
541 	;
542 
543 extension
544 	:	F_EXT EXTENSION { p_ext |= $2; }
545 	|	F_EXT NOCYCLICSEQ { p_ext &= ~SADB_X_EXT_CYCSEQ; }
546 	|	F_MODE MODE { p_mode = $2; }
547 	|	F_MODE ANY { p_mode = IPSEC_MODE_ANY; }
548 	|	F_REQID DECSTRING { p_reqid = $2; }
549 	|	F_ESPFRAG DECSTRING
550 		{
551 			if (p_natt_type == 0) {
552 				yyerror("esp fragment size only valid for NAT-T");
553 				return -1;
554 			}
555 			p_esp_frag = $2;
556 		}
557 	|	F_REPLAY DECSTRING
558 		{
559 			if ((p_ext & SADB_X_EXT_OLD) != 0) {
560 				yyerror("replay prevention cannot be used with "
561 				    "ah/esp-old");
562 				return -1;
563 			}
564 			p_replay = $2;
565 		}
566 	|	F_LIFETIME_HARD DECSTRING { p_lt_hard = $2; }
567 	|	F_LIFETIME_SOFT DECSTRING { p_lt_soft = $2; }
568 	|	F_LIFEBYTE_HARD DECSTRING { p_lb_hard = $2; }
569 	|	F_LIFEBYTE_SOFT DECSTRING { p_lb_soft = $2; }
570 	|	SECURITY_CTX DECSTRING DECSTRING QUOTEDSTRING {
571 		sec_ctx.doi = $2;
572 		sec_ctx.alg = $3;
573 		sec_ctx.len = $4.len+1;
574 		sec_ctx.buf = $4.buf;
575 	}
576 	;
577 
578 	/* definition about command for SPD management */
579 	/* spdadd */
580 spdadd_command
581 	/* XXX merge with spdupdate ??? */
582 	:	SPDADD ipaddropts STRING prefix portstr STRING prefix portstr upper_spec upper_misc_spec context_spec policy_spec EOT
583 		{
584 			int status;
585 			struct addrinfo *src, *dst;
586 
587 #ifdef HAVE_PFKEY_POLICY_PRIORITY
588 			last_msg_type = SADB_X_SPDADD;
589 #endif
590 
591 			/* fixed port fields if ulp is icmp */
592 			if (fix_portstr($9, &$10, &$5, &$8))
593 				return -1;
594 
595 			src = parse_addr($3.buf, $5.buf);
596 			dst = parse_addr($6.buf, $8.buf);
597 			if (!src || !dst) {
598 				/* yyerror is already called */
599 				return -1;
600 			}
601 			if (src->ai_next || dst->ai_next) {
602 				yyerror("multiple address specified");
603 				freeaddrinfo(src);
604 				freeaddrinfo(dst);
605 				return -1;
606 			}
607 
608 			status = setkeymsg_spdaddr(SADB_X_SPDADD, $9, &$12,
609 			    src, $4, dst, $7);
610 			freeaddrinfo(src);
611 			freeaddrinfo(dst);
612 			if (status < 0)
613 				return -1;
614 		}
615 	|	SPDADD TAGGED QUOTEDSTRING policy_spec EOT
616 		{
617 			int status;
618 
619 			status = setkeymsg_spdaddr_tag(SADB_X_SPDADD,
620 			    $3.buf, &$4);
621 			if (status < 0)
622 				return -1;
623 		}
624 	;
625 
626 spdupdate_command
627 	/* XXX merge with spdadd ??? */
628 	:	SPDUPDATE ipaddropts STRING prefix portstr STRING prefix portstr upper_spec upper_misc_spec context_spec policy_spec EOT
629 		{
630 			int status;
631 			struct addrinfo *src, *dst;
632 
633 #ifdef HAVE_PFKEY_POLICY_PRIORITY
634 			last_msg_type = SADB_X_SPDUPDATE;
635 #endif
636 
637 			/* fixed port fields if ulp is icmp */
638 			if (fix_portstr($9, &$10, &$5, &$8))
639 				return -1;
640 
641 			src = parse_addr($3.buf, $5.buf);
642 			dst = parse_addr($6.buf, $8.buf);
643 			if (!src || !dst) {
644 				/* yyerror is already called */
645 				return -1;
646 			}
647 			if (src->ai_next || dst->ai_next) {
648 				yyerror("multiple address specified");
649 				freeaddrinfo(src);
650 				freeaddrinfo(dst);
651 				return -1;
652 			}
653 
654 			status = setkeymsg_spdaddr(SADB_X_SPDUPDATE, $9, &$12,
655 			    src, $4, dst, $7);
656 			freeaddrinfo(src);
657 			freeaddrinfo(dst);
658 			if (status < 0)
659 				return -1;
660 		}
661 	|	SPDUPDATE TAGGED QUOTEDSTRING policy_spec EOT
662 		{
663 			int status;
664 
665 			status = setkeymsg_spdaddr_tag(SADB_X_SPDUPDATE,
666 			    $3.buf, &$4);
667 			if (status < 0)
668 				return -1;
669 		}
670 	;
671 
672 spddelete_command
673 	:	SPDDELETE ipaddropts STRING prefix portstr STRING prefix portstr upper_spec upper_misc_spec context_spec policy_spec EOT
674 		{
675 			int status;
676 			struct addrinfo *src, *dst;
677 
678 			/* fixed port fields if ulp is icmp */
679 			if (fix_portstr($9, &$10, &$5, &$8))
680 				return -1;
681 
682 			src = parse_addr($3.buf, $5.buf);
683 			dst = parse_addr($6.buf, $8.buf);
684 			if (!src || !dst) {
685 				/* yyerror is already called */
686 				return -1;
687 			}
688 			if (src->ai_next || dst->ai_next) {
689 				yyerror("multiple address specified");
690 				freeaddrinfo(src);
691 				freeaddrinfo(dst);
692 				return -1;
693 			}
694 
695 			status = setkeymsg_spdaddr(SADB_X_SPDDELETE, $9, &$12,
696 			    src, $4, dst, $7);
697 			freeaddrinfo(src);
698 			freeaddrinfo(dst);
699 			if (status < 0)
700 				return -1;
701 		}
702 	;
703 
704 spddump_command:
705 		SPDDUMP EOT
706 		{
707 			struct sadb_msg msg;
708 			setkeymsg0(&msg, SADB_X_SPDDUMP, SADB_SATYPE_UNSPEC,
709 			    sizeof(msg));
710 			sendkeymsg((char *)&msg, sizeof(msg));
711 		}
712 	;
713 
714 spdflush_command
715 	:
716 		SPDFLUSH EOT
717 		{
718 			struct sadb_msg msg;
719 			setkeymsg0(&msg, SADB_X_SPDFLUSH, SADB_SATYPE_UNSPEC,
720 			    sizeof(msg));
721 			sendkeymsg((char *)&msg, sizeof(msg));
722 		}
723 	;
724 
725 ipaddropts
726 	:	/* nothing */
727 	|	ipaddropts ipaddropt
728 	;
729 
730 ipaddropt
731 	:	F_AIFLAGS
732 		{
733 			char *p;
734 
735 			for (p = $1.buf + 1; *p; p++)
736 				switch (*p) {
737 				case '4':
738 					p_aifamily = AF_INET;
739 					break;
740 #ifdef INET6
741 				case '6':
742 					p_aifamily = AF_INET6;
743 					break;
744 #endif
745 				case 'n':
746 					p_aiflags = AI_NUMERICHOST;
747 					break;
748 				default:
749 					yyerror("invalid flag");
750 					return -1;
751 				}
752 		}
753 	;
754 
755 ipaddr
756 	:	STRING
757 		{
758 			$$ = parse_addr($1.buf, NULL);
759 			if ($$ == NULL) {
760 				/* yyerror already called by parse_addr */
761 				return -1;
762 			}
763 		}
764 	;
765 
766 ipandport
767 	:	STRING
768 		{
769 			$$ = parse_addr($1.buf, NULL);
770 			if ($$ == NULL) {
771 				/* yyerror already called by parse_addr */
772 				return -1;
773 			}
774 		}
775 	|	STRING portstr_notempty
776 		{
777 			$$ = parse_addr($1.buf, $2.buf);
778 			if ($$ == NULL) {
779 				/* yyerror already called by parse_addr */
780 				return -1;
781 			}
782 		}
783 	;
784 
785 prefix
786 	:	/*NOTHING*/ { $$ = -1; }
787 	|	SLASH DECSTRING { $$ = $2; }
788 	;
789 
790 portstr
791 	:	/*NOTHING*/
792 		{
793 			$$.buf = strdup("0");
794 			if (!$$.buf) {
795 				yyerror("insufficient memory");
796 				return -1;
797 			}
798 			$$.len = strlen($$.buf);
799 		}
800 	| portstr_notempty
801 	;
802 
803 portstr_notempty
804 	: 	BLCL ANY ELCL
805 		{
806 			$$.buf = strdup("0");
807 			if (!$$.buf) {
808 				yyerror("insufficient memory");
809 				return -1;
810 			}
811 			$$.len = strlen($$.buf);
812 		}
813 	|	BLCL DECSTRING ELCL
814 		{
815 			char buf[20];
816 			snprintf(buf, sizeof(buf), "%lu", $2);
817 			$$.buf = strdup(buf);
818 			if (!$$.buf) {
819 				yyerror("insufficient memory");
820 				return -1;
821 			}
822 			$$.len = strlen($$.buf);
823 		}
824 	|	BLCL STRING ELCL
825 		{
826 			$$ = $2;
827 		}
828 	;
829 
830 upper_spec
831 	:	DECSTRING { $$ = $1; }
832 	|	ANY { $$ = IPSEC_ULPROTO_ANY; }
833 	|	PR_TCP {
834 				$$ = IPPROTO_TCP;
835 			}
836 	|	STRING
837 		{
838 			struct protoent *ent;
839 
840 			ent = getprotobyname($1.buf);
841 			if (ent)
842 				$$ = ent->p_proto;
843 			else {
844 				if (strcmp("icmp6", $1.buf) == 0) {
845 					$$ = IPPROTO_ICMPV6;
846 				} else if(strcmp("ip4", $1.buf) == 0) {
847 					$$ = IPPROTO_IPV4;
848 				} else {
849 					yyerror("invalid upper layer protocol");
850 					return -1;
851 				}
852 			}
853 			endprotoent();
854 		}
855 	;
856 
857 upper_misc_spec
858 	:	/*NOTHING*/
859 		{
860 			$$.buf = NULL;
861 			$$.len = 0;
862 		}
863 	|	STRING
864 		{
865 			$$.buf = strdup($1.buf);
866 			if (!$$.buf) {
867 				yyerror("insufficient memory");
868 				return -1;
869 			}
870 			$$.len = strlen($$.buf);
871 		}
872 	;
873 
874 context_spec
875 	:	/* NOTHING */
876 	|	SECURITY_CTX DECSTRING DECSTRING QUOTEDSTRING {
877 			sec_ctx.doi = $2;
878 			sec_ctx.alg = $3;
879 			sec_ctx.len = $4.len+1;
880 			sec_ctx.buf = $4.buf;
881 		}
882 	;
883 
884 policy_spec
885 	:	F_POLICY policy_requests
886 		{
887 			char *policy;
888 #ifdef HAVE_PFKEY_POLICY_PRIORITY
889 			struct sadb_x_policy *xpl;
890 #endif
891 
892 			policy = ipsec_set_policy($2.buf, $2.len);
893 			if (policy == NULL) {
894 				yyerror(ipsec_strerror());
895 				return -1;
896 			}
897 
898 			$$.buf = policy;
899 			$$.len = ipsec_get_policylen(policy);
900 
901 #ifdef HAVE_PFKEY_POLICY_PRIORITY
902 			xpl = (struct sadb_x_policy *) $$.buf;
903 			last_priority = xpl->sadb_x_policy_priority;
904 #endif
905 		}
906 	;
907 
908 policy_requests
909 	:	PL_REQUESTS { $$ = $1; }
910 	;
911 
912 	/* exit */
913 exit_command
914 	:	EXIT EOT
915 		{
916 			exit_now = 1;
917 			YYACCEPT;
918 		}
919 	;
920 %%
921 
922 int
923 setkeymsg0(msg, type, satype, l)
924 	struct sadb_msg *msg;
925 	unsigned int type;
926 	unsigned int satype;
927 	size_t l;
928 {
929 
930 	msg->sadb_msg_version = PF_KEY_V2;
931 	msg->sadb_msg_type = type;
932 	msg->sadb_msg_errno = 0;
933 	msg->sadb_msg_satype = satype;
934 	msg->sadb_msg_reserved = 0;
935 	msg->sadb_msg_seq = 0;
936 	msg->sadb_msg_pid = getpid();
937 	msg->sadb_msg_len = PFKEY_UNIT64(l);
938 	return 0;
939 }
940 
941 /* XXX NO BUFFER OVERRUN CHECK! BAD BAD! */
942 static int
943 setkeymsg_spdaddr(type, upper, policy, srcs, splen, dsts, dplen)
944 	unsigned int type;
945 	unsigned int upper;
946 	vchar_t *policy;
947 	struct addrinfo *srcs;
948 	int splen;
949 	struct addrinfo *dsts;
950 	int dplen;
951 {
952 	struct sadb_msg *msg;
953 	char buf[BUFSIZ];
954 	int l, l0;
955 	struct sadb_address m_addr;
956 	struct addrinfo *s, *d;
957 	int n;
958 	int plen;
959 	struct sockaddr *sa;
960 	int salen;
961 #ifdef HAVE_POLICY_FWD
962 	struct sadb_x_ipsecrequest *ps = NULL;
963 	int saved_level, saved_id = 0;
964 #endif
965 
966 	msg = (struct sadb_msg *)buf;
967 
968 	if (!srcs || !dsts)
969 		return -1;
970 
971 	/* fix up length afterwards */
972 	setkeymsg0(msg, type, SADB_SATYPE_UNSPEC, 0);
973 	l = sizeof(struct sadb_msg);
974 
975 	memcpy(buf + l, policy->buf, policy->len);
976 	l += policy->len;
977 
978 	l0 = l;
979 	n = 0;
980 
981 	/* do it for all src/dst pairs */
982 	for (s = srcs; s; s = s->ai_next) {
983 		for (d = dsts; d; d = d->ai_next) {
984 			/* rewind pointer */
985 			l = l0;
986 
987 			if (s->ai_addr->sa_family != d->ai_addr->sa_family)
988 				continue;
989 			switch (s->ai_addr->sa_family) {
990 			case AF_INET:
991 				plen = sizeof(struct in_addr) << 3;
992 				break;
993 #ifdef INET6
994 			case AF_INET6:
995 				plen = sizeof(struct in6_addr) << 3;
996 				break;
997 #endif
998 			default:
999 				continue;
1000 			}
1001 
1002 			/* set src */
1003 			sa = s->ai_addr;
1004 			salen = sysdep_sa_len(s->ai_addr);
1005 			m_addr.sadb_address_len = PFKEY_UNIT64(sizeof(m_addr) +
1006 			    PFKEY_ALIGN8(salen));
1007 			m_addr.sadb_address_exttype = SADB_EXT_ADDRESS_SRC;
1008 			m_addr.sadb_address_proto = upper;
1009 			m_addr.sadb_address_prefixlen =
1010 			    (splen >= 0 ? splen : plen);
1011 			m_addr.sadb_address_reserved = 0;
1012 
1013 			setvarbuf(buf, &l, (struct sadb_ext *)&m_addr,
1014 			    sizeof(m_addr), (caddr_t)sa, salen);
1015 
1016 			/* set dst */
1017 			sa = d->ai_addr;
1018 			salen = sysdep_sa_len(d->ai_addr);
1019 			m_addr.sadb_address_len = PFKEY_UNIT64(sizeof(m_addr) +
1020 			    PFKEY_ALIGN8(salen));
1021 			m_addr.sadb_address_exttype = SADB_EXT_ADDRESS_DST;
1022 			m_addr.sadb_address_proto = upper;
1023 			m_addr.sadb_address_prefixlen =
1024 			    (dplen >= 0 ? dplen : plen);
1025 			m_addr.sadb_address_reserved = 0;
1026 
1027 			setvarbuf(buf, &l, (struct sadb_ext *)&m_addr,
1028 			    sizeof(m_addr), sa, salen);
1029 #ifdef SADB_X_EXT_SEC_CTX
1030 			/* Add security context label */
1031 			if (sec_ctx.doi) {
1032 				struct sadb_x_sec_ctx m_sec_ctx;
1033 				u_int slen = sizeof(struct sadb_x_sec_ctx);
1034 
1035 				memset(&m_sec_ctx, 0, slen);
1036 
1037 				m_sec_ctx.sadb_x_sec_len =
1038 				PFKEY_UNIT64(slen + PFKEY_ALIGN8(sec_ctx.len));
1039 
1040 				m_sec_ctx.sadb_x_sec_exttype =
1041 					SADB_X_EXT_SEC_CTX;
1042 				m_sec_ctx.sadb_x_ctx_len = sec_ctx.len;/*bytes*/
1043 				m_sec_ctx.sadb_x_ctx_doi = sec_ctx.doi;
1044 				m_sec_ctx.sadb_x_ctx_alg = sec_ctx.alg;
1045 				setvarbuf(buf, &l,
1046 					  (struct sadb_ext *)&m_sec_ctx, slen,
1047 					  (caddr_t)sec_ctx.buf, sec_ctx.len);
1048 			}
1049 #endif
1050 			msg->sadb_msg_len = PFKEY_UNIT64(l);
1051 
1052 			sendkeymsg(buf, l);
1053 
1054 #ifdef HAVE_POLICY_FWD
1055 			/* create extra call for FWD policy */
1056 			if (f_rfcmode && sp->sadb_x_policy_dir == IPSEC_DIR_INBOUND) {
1057 				sp->sadb_x_policy_dir = IPSEC_DIR_FWD;
1058 				ps = (struct sadb_x_ipsecrequest*) (sp+1);
1059 
1060 				/* if request level is unique, change it to
1061 				 * require for fwd policy */
1062 				/* XXX: currently, only first policy is updated
1063 				 * only. Update following too... */
1064 				saved_level = ps->sadb_x_ipsecrequest_level;
1065 				if (saved_level == IPSEC_LEVEL_UNIQUE) {
1066 					saved_id = ps->sadb_x_ipsecrequest_reqid;
1067 					ps->sadb_x_ipsecrequest_reqid=0;
1068 					ps->sadb_x_ipsecrequest_level=IPSEC_LEVEL_REQUIRE;
1069 				}
1070 
1071 				sendkeymsg(buf, l);
1072 				/* restoring for next message */
1073 				sp->sadb_x_policy_dir = IPSEC_DIR_INBOUND;
1074 				if (saved_level == IPSEC_LEVEL_UNIQUE) {
1075 					ps->sadb_x_ipsecrequest_reqid = saved_id;
1076 					ps->sadb_x_ipsecrequest_level = saved_level;
1077 				}
1078 			}
1079 #endif
1080 
1081 			n++;
1082 		}
1083 	}
1084 
1085 	if (n == 0)
1086 		return -1;
1087 	else
1088 		return 0;
1089 }
1090 
1091 static int
1092 setkeymsg_spdaddr_tag(type, tag, policy)
1093 	unsigned int type;
1094 	char *tag;
1095 	vchar_t *policy;
1096 {
1097 	struct sadb_msg *msg;
1098 	char buf[BUFSIZ];
1099 	int l;
1100 #ifdef SADB_X_EXT_TAG
1101 	struct sadb_x_tag m_tag;
1102 #endif
1103 
1104 	msg = (struct sadb_msg *)buf;
1105 
1106 	/* fix up length afterwards */
1107 	setkeymsg0(msg, type, SADB_SATYPE_UNSPEC, 0);
1108 	l = sizeof(struct sadb_msg);
1109 
1110 	memcpy(buf + l, policy->buf, policy->len);
1111 	l += policy->len;
1112 
1113 #ifdef SADB_X_EXT_TAG
1114 	memset(&m_tag, 0, sizeof(m_tag));
1115 	m_tag.sadb_x_tag_len = PFKEY_UNIT64(sizeof(m_tag));
1116 	m_tag.sadb_x_tag_exttype = SADB_X_EXT_TAG;
1117 	if (strlcpy(m_tag.sadb_x_tag_name, tag,
1118 	    sizeof(m_tag.sadb_x_tag_name)) >= sizeof(m_tag.sadb_x_tag_name))
1119 		return -1;
1120 	memcpy(buf + l, &m_tag, sizeof(m_tag));
1121 	l += sizeof(m_tag);
1122 #endif
1123 
1124 	msg->sadb_msg_len = PFKEY_UNIT64(l);
1125 
1126 	sendkeymsg(buf, l);
1127 
1128 	return 0;
1129 }
1130 
1131 /* XXX NO BUFFER OVERRUN CHECK! BAD BAD! */
1132 static int
1133 setkeymsg_addr(type, satype, srcs, dsts, no_spi)
1134 	unsigned int type;
1135 	unsigned int satype;
1136 	struct addrinfo *srcs;
1137 	struct addrinfo *dsts;
1138 	int no_spi;
1139 {
1140 	struct sadb_msg *msg;
1141 	char buf[BUFSIZ];
1142 	int l, l0, len;
1143 	struct sadb_sa m_sa;
1144 	struct sadb_x_sa2 m_sa2;
1145 	struct sadb_address m_addr;
1146 	struct addrinfo *s, *d;
1147 	int n;
1148 	int plen;
1149 	struct sockaddr *sa;
1150 	int salen;
1151 
1152 	msg = (struct sadb_msg *)buf;
1153 
1154 	if (!srcs || !dsts)
1155 		return -1;
1156 
1157 	/* fix up length afterwards */
1158 	setkeymsg0(msg, type, satype, 0);
1159 	l = sizeof(struct sadb_msg);
1160 
1161 	if (!no_spi) {
1162 		len = sizeof(struct sadb_sa);
1163 		m_sa.sadb_sa_len = PFKEY_UNIT64(len);
1164 		m_sa.sadb_sa_exttype = SADB_EXT_SA;
1165 		m_sa.sadb_sa_spi = htonl(p_spi);
1166 		m_sa.sadb_sa_replay = p_replay;
1167 		m_sa.sadb_sa_state = 0;
1168 		m_sa.sadb_sa_auth = p_alg_auth;
1169 		m_sa.sadb_sa_encrypt = p_alg_enc;
1170 		m_sa.sadb_sa_flags = p_ext;
1171 
1172 		memcpy(buf + l, &m_sa, len);
1173 		l += len;
1174 
1175 		len = sizeof(struct sadb_x_sa2);
1176 		m_sa2.sadb_x_sa2_len = PFKEY_UNIT64(len);
1177 		m_sa2.sadb_x_sa2_exttype = SADB_X_EXT_SA2;
1178 		m_sa2.sadb_x_sa2_mode = p_mode;
1179 		m_sa2.sadb_x_sa2_reqid = p_reqid;
1180 
1181 		memcpy(buf + l, &m_sa2, len);
1182 		l += len;
1183 	}
1184 
1185 	l0 = l;
1186 	n = 0;
1187 
1188 	/* do it for all src/dst pairs */
1189 	for (s = srcs; s; s = s->ai_next) {
1190 		for (d = dsts; d; d = d->ai_next) {
1191 			/* rewind pointer */
1192 			l = l0;
1193 
1194 			if (s->ai_addr->sa_family != d->ai_addr->sa_family)
1195 				continue;
1196 			switch (s->ai_addr->sa_family) {
1197 			case AF_INET:
1198 				plen = sizeof(struct in_addr) << 3;
1199 				break;
1200 #ifdef INET6
1201 			case AF_INET6:
1202 				plen = sizeof(struct in6_addr) << 3;
1203 				break;
1204 #endif
1205 			default:
1206 				continue;
1207 			}
1208 
1209 			/* set src */
1210 			sa = s->ai_addr;
1211 			salen = sysdep_sa_len(s->ai_addr);
1212 			m_addr.sadb_address_len = PFKEY_UNIT64(sizeof(m_addr) +
1213 			    PFKEY_ALIGN8(salen));
1214 			m_addr.sadb_address_exttype = SADB_EXT_ADDRESS_SRC;
1215 			m_addr.sadb_address_proto = IPSEC_ULPROTO_ANY;
1216 			m_addr.sadb_address_prefixlen = plen;
1217 			m_addr.sadb_address_reserved = 0;
1218 
1219 			setvarbuf(buf, &l, (struct sadb_ext *)&m_addr,
1220 			    sizeof(m_addr), sa, salen);
1221 
1222 			/* set dst */
1223 			sa = d->ai_addr;
1224 			salen = sysdep_sa_len(d->ai_addr);
1225 			m_addr.sadb_address_len = PFKEY_UNIT64(sizeof(m_addr) +
1226 			    PFKEY_ALIGN8(salen));
1227 			m_addr.sadb_address_exttype = SADB_EXT_ADDRESS_DST;
1228 			m_addr.sadb_address_proto = IPSEC_ULPROTO_ANY;
1229 			m_addr.sadb_address_prefixlen = plen;
1230 			m_addr.sadb_address_reserved = 0;
1231 
1232 			setvarbuf(buf, &l, (struct sadb_ext *)&m_addr,
1233 			    sizeof(m_addr), sa, salen);
1234 
1235 			msg->sadb_msg_len = PFKEY_UNIT64(l);
1236 
1237 			sendkeymsg(buf, l);
1238 
1239 			n++;
1240 		}
1241 	}
1242 
1243 	if (n == 0)
1244 		return -1;
1245 	else
1246 		return 0;
1247 }
1248 
1249 #ifdef SADB_X_EXT_NAT_T_TYPE
1250 static u_int16_t get_port (struct addrinfo *addr)
1251 {
1252 	struct sockaddr *s = addr->ai_addr;
1253 	u_int16_t port = 0;
1254 
1255 	switch (s->sa_family) {
1256 	case AF_INET:
1257 	  {
1258 		struct sockaddr_in *sin4 = (struct sockaddr_in *)s;
1259 		port = ntohs(sin4->sin_port);
1260 		break;
1261 	  }
1262 	case AF_INET6:
1263 	  {
1264 		struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)s;
1265 		port = ntohs(sin6->sin6_port);
1266 		break;
1267 	  }
1268 	}
1269 
1270 	if (port == 0)
1271 		port = DEFAULT_NATT_PORT;
1272 
1273 	return port;
1274 }
1275 #endif
1276 
1277 /* XXX NO BUFFER OVERRUN CHECK! BAD BAD! */
1278 static int
1279 setkeymsg_add(type, satype, srcs, dsts)
1280 	unsigned int type;
1281 	unsigned int satype;
1282 	struct addrinfo *srcs;
1283 	struct addrinfo *dsts;
1284 {
1285 	struct sadb_msg *msg;
1286 	char buf[BUFSIZ];
1287 	int l, l0, len;
1288 	struct sadb_sa m_sa;
1289 	struct sadb_x_sa2 m_sa2;
1290 	struct sadb_address m_addr;
1291 	struct addrinfo *s, *d;
1292 	int n;
1293 	int plen;
1294 	struct sockaddr *sa;
1295 	int salen;
1296 
1297 	msg = (struct sadb_msg *)buf;
1298 
1299 	if (!srcs || !dsts)
1300 		return -1;
1301 
1302 	/* fix up length afterwards */
1303 	setkeymsg0(msg, type, satype, 0);
1304 	l = sizeof(struct sadb_msg);
1305 
1306 	/* set encryption algorithm, if present. */
1307 	if (satype != SADB_X_SATYPE_IPCOMP && p_key_enc) {
1308 		union {
1309 			struct sadb_key key;
1310 			struct sadb_ext ext;
1311 		} m;
1312 
1313 		m.key.sadb_key_len =
1314 			PFKEY_UNIT64(sizeof(m.key)
1315 				   + PFKEY_ALIGN8(p_key_enc_len));
1316 		m.key.sadb_key_exttype = SADB_EXT_KEY_ENCRYPT;
1317 		m.key.sadb_key_bits = p_key_enc_len * 8;
1318 		m.key.sadb_key_reserved = 0;
1319 
1320 		setvarbuf(buf, &l, &m.ext, sizeof(m.key),
1321 			p_key_enc, p_key_enc_len);
1322 	}
1323 
1324 	/* set authentication algorithm, if present. */
1325 	if (p_key_auth) {
1326 		union {
1327 			struct sadb_key key;
1328 			struct sadb_ext ext;
1329 		} m;
1330 
1331 		m.key.sadb_key_len =
1332 			PFKEY_UNIT64(sizeof(m.key)
1333 				   + PFKEY_ALIGN8(p_key_auth_len));
1334 		m.key.sadb_key_exttype = SADB_EXT_KEY_AUTH;
1335 		m.key.sadb_key_bits = p_key_auth_len * 8;
1336 		m.key.sadb_key_reserved = 0;
1337 
1338 		setvarbuf(buf, &l, &m.ext, sizeof(m.key),
1339 			p_key_auth, p_key_auth_len);
1340 	}
1341 
1342 	/* set lifetime for HARD */
1343 	if (p_lt_hard != 0 || p_lb_hard != 0) {
1344 		struct sadb_lifetime m_lt;
1345 		u_int slen = sizeof(struct sadb_lifetime);
1346 
1347 		m_lt.sadb_lifetime_len = PFKEY_UNIT64(slen);
1348 		m_lt.sadb_lifetime_exttype = SADB_EXT_LIFETIME_HARD;
1349 		m_lt.sadb_lifetime_allocations = 0;
1350 		m_lt.sadb_lifetime_bytes = p_lb_hard;
1351 		m_lt.sadb_lifetime_addtime = p_lt_hard;
1352 		m_lt.sadb_lifetime_usetime = 0;
1353 
1354 		memcpy(buf + l, &m_lt, slen);
1355 		l += slen;
1356 	}
1357 
1358 	/* set lifetime for SOFT */
1359 	if (p_lt_soft != 0 || p_lb_soft != 0) {
1360 		struct sadb_lifetime m_lt;
1361 		u_int slen = sizeof(struct sadb_lifetime);
1362 
1363 		m_lt.sadb_lifetime_len = PFKEY_UNIT64(slen);
1364 		m_lt.sadb_lifetime_exttype = SADB_EXT_LIFETIME_SOFT;
1365 		m_lt.sadb_lifetime_allocations = 0;
1366 		m_lt.sadb_lifetime_bytes = p_lb_soft;
1367 		m_lt.sadb_lifetime_addtime = p_lt_soft;
1368 		m_lt.sadb_lifetime_usetime = 0;
1369 
1370 		memcpy(buf + l, &m_lt, slen);
1371 		l += slen;
1372 	}
1373 
1374 #ifdef SADB_X_EXT_SEC_CTX
1375 	/* Add security context label */
1376 	if (sec_ctx.doi) {
1377 		struct sadb_x_sec_ctx m_sec_ctx;
1378 		u_int slen = sizeof(struct sadb_x_sec_ctx);
1379 
1380 		memset(&m_sec_ctx, 0, slen);
1381 
1382 		m_sec_ctx.sadb_x_sec_len = PFKEY_UNIT64(slen +
1383 					PFKEY_ALIGN8(sec_ctx.len));
1384 		m_sec_ctx.sadb_x_sec_exttype = SADB_X_EXT_SEC_CTX;
1385 		m_sec_ctx.sadb_x_ctx_len = sec_ctx.len; /* bytes */
1386 		m_sec_ctx.sadb_x_ctx_doi = sec_ctx.doi;
1387 		m_sec_ctx.sadb_x_ctx_alg = sec_ctx.alg;
1388 		setvarbuf(buf, &l, (struct sadb_ext *)&m_sec_ctx, slen,
1389 			  (caddr_t)sec_ctx.buf, sec_ctx.len);
1390 	}
1391 #endif
1392 
1393 	len = sizeof(struct sadb_sa);
1394 	m_sa.sadb_sa_len = PFKEY_UNIT64(len);
1395 	m_sa.sadb_sa_exttype = SADB_EXT_SA;
1396 	m_sa.sadb_sa_spi = htonl(p_spi);
1397 	m_sa.sadb_sa_replay = p_replay;
1398 	m_sa.sadb_sa_state = 0;
1399 	m_sa.sadb_sa_auth = p_alg_auth;
1400 	m_sa.sadb_sa_encrypt = p_alg_enc;
1401 	m_sa.sadb_sa_flags = p_ext;
1402 
1403 	memcpy(buf + l, &m_sa, len);
1404 	l += len;
1405 
1406 	len = sizeof(struct sadb_x_sa2);
1407 	m_sa2.sadb_x_sa2_len = PFKEY_UNIT64(len);
1408 	m_sa2.sadb_x_sa2_exttype = SADB_X_EXT_SA2;
1409 	m_sa2.sadb_x_sa2_mode = p_mode;
1410 	m_sa2.sadb_x_sa2_reqid = p_reqid;
1411 
1412 	memcpy(buf + l, &m_sa2, len);
1413 	l += len;
1414 
1415 #ifdef SADB_X_EXT_NAT_T_TYPE
1416 	if (p_natt_type) {
1417 		struct sadb_x_nat_t_type natt_type;
1418 
1419 		len = sizeof(struct sadb_x_nat_t_type);
1420 		memset(&natt_type, 0, len);
1421 		natt_type.sadb_x_nat_t_type_len = PFKEY_UNIT64(len);
1422 		natt_type.sadb_x_nat_t_type_exttype = SADB_X_EXT_NAT_T_TYPE;
1423 		natt_type.sadb_x_nat_t_type_type = p_natt_type;
1424 
1425 		memcpy(buf + l, &natt_type, len);
1426 		l += len;
1427 
1428 		if (p_natt_oa) {
1429 			sa = p_natt_oa->ai_addr;
1430 			switch (sa->sa_family) {
1431 			case AF_INET:
1432 				plen = sizeof(struct in_addr) << 3;
1433 				break;
1434 #ifdef INET6
1435 			case AF_INET6:
1436 				plen = sizeof(struct in6_addr) << 3;
1437 				break;
1438 #endif
1439 			default:
1440 				return -1;
1441 			}
1442 			salen = sysdep_sa_len(sa);
1443 			m_addr.sadb_address_len = PFKEY_UNIT64(sizeof(m_addr) +
1444 			    PFKEY_ALIGN8(salen));
1445 			m_addr.sadb_address_exttype = SADB_X_EXT_NAT_T_OA;
1446 			m_addr.sadb_address_proto = IPSEC_ULPROTO_ANY;
1447 			m_addr.sadb_address_prefixlen = plen;
1448 			m_addr.sadb_address_reserved = 0;
1449 
1450 			setvarbuf(buf, &l, (struct sadb_ext *)&m_addr,
1451 			    sizeof(m_addr), sa, salen);
1452 		}
1453 	}
1454 #endif
1455 
1456 	l0 = l;
1457 	n = 0;
1458 
1459 	/* do it for all src/dst pairs */
1460 	for (s = srcs; s; s = s->ai_next) {
1461 		for (d = dsts; d; d = d->ai_next) {
1462 			/* rewind pointer */
1463 			l = l0;
1464 
1465 			if (s->ai_addr->sa_family != d->ai_addr->sa_family)
1466 				continue;
1467 			switch (s->ai_addr->sa_family) {
1468 			case AF_INET:
1469 				plen = sizeof(struct in_addr) << 3;
1470 				break;
1471 #ifdef INET6
1472 			case AF_INET6:
1473 				plen = sizeof(struct in6_addr) << 3;
1474 				break;
1475 #endif
1476 			default:
1477 				continue;
1478 			}
1479 
1480 			/* set src */
1481 			sa = s->ai_addr;
1482 			salen = sysdep_sa_len(s->ai_addr);
1483 			m_addr.sadb_address_len = PFKEY_UNIT64(sizeof(m_addr) +
1484 			    PFKEY_ALIGN8(salen));
1485 			m_addr.sadb_address_exttype = SADB_EXT_ADDRESS_SRC;
1486 			m_addr.sadb_address_proto = IPSEC_ULPROTO_ANY;
1487 			m_addr.sadb_address_prefixlen = plen;
1488 			m_addr.sadb_address_reserved = 0;
1489 
1490 			setvarbuf(buf, &l, (struct sadb_ext *)&m_addr,
1491 			    sizeof(m_addr), sa, salen);
1492 
1493 			/* set dst */
1494 			sa = d->ai_addr;
1495 			salen = sysdep_sa_len(d->ai_addr);
1496 			m_addr.sadb_address_len = PFKEY_UNIT64(sizeof(m_addr) +
1497 			    PFKEY_ALIGN8(salen));
1498 			m_addr.sadb_address_exttype = SADB_EXT_ADDRESS_DST;
1499 			m_addr.sadb_address_proto = IPSEC_ULPROTO_ANY;
1500 			m_addr.sadb_address_prefixlen = plen;
1501 			m_addr.sadb_address_reserved = 0;
1502 
1503 			setvarbuf(buf, &l, (struct sadb_ext *)&m_addr,
1504 			    sizeof(m_addr), sa, salen);
1505 
1506 #ifdef SADB_X_EXT_NAT_T_TYPE
1507 			if (p_natt_type) {
1508 				struct sadb_x_nat_t_port natt_port;
1509 
1510 				/* NATT_SPORT */
1511 				len = sizeof(struct sadb_x_nat_t_port);
1512 				memset(&natt_port, 0, len);
1513 				natt_port.sadb_x_nat_t_port_len = PFKEY_UNIT64(len);
1514 				natt_port.sadb_x_nat_t_port_exttype =
1515 					SADB_X_EXT_NAT_T_SPORT;
1516 				natt_port.sadb_x_nat_t_port_port = htons(get_port(s));
1517 
1518 				memcpy(buf + l, &natt_port, len);
1519 				l += len;
1520 
1521 				/* NATT_DPORT */
1522 				natt_port.sadb_x_nat_t_port_exttype =
1523 					SADB_X_EXT_NAT_T_DPORT;
1524 				natt_port.sadb_x_nat_t_port_port = htons(get_port(d));
1525 
1526 				memcpy(buf + l, &natt_port, len);
1527 				l += len;
1528 #ifdef SADB_X_EXT_NAT_T_FRAG
1529 				if (p_esp_frag) {
1530 					struct sadb_x_nat_t_frag esp_frag;
1531 
1532 					/* NATT_FRAG */
1533 					len = sizeof(struct sadb_x_nat_t_frag);
1534 					memset(&esp_frag, 0, len);
1535 					esp_frag.sadb_x_nat_t_frag_len = PFKEY_UNIT64(len);
1536 					esp_frag.sadb_x_nat_t_frag_exttype =
1537 						SADB_X_EXT_NAT_T_FRAG;
1538 					esp_frag.sadb_x_nat_t_frag_fraglen = p_esp_frag;
1539 
1540 					memcpy(buf + l, &esp_frag, len);
1541 					l += len;
1542 				}
1543 #endif
1544 			}
1545 #endif
1546 			msg->sadb_msg_len = PFKEY_UNIT64(l);
1547 
1548 			sendkeymsg(buf, l);
1549 
1550 			n++;
1551 		}
1552 	}
1553 
1554 	if (n == 0)
1555 		return -1;
1556 	else
1557 		return 0;
1558 }
1559 
1560 static struct addrinfo *
1561 parse_addr(host, port)
1562 	char *host;
1563 	char *port;
1564 {
1565 	struct addrinfo hints, *res = NULL;
1566 	int error;
1567 
1568 	memset(&hints, 0, sizeof(hints));
1569 	hints.ai_family = p_aifamily;
1570 	hints.ai_socktype = SOCK_DGRAM;		/*dummy*/
1571 	hints.ai_protocol = IPPROTO_UDP;	/*dummy*/
1572 	hints.ai_flags = p_aiflags;
1573 	error = getaddrinfo(host, port, &hints, &res);
1574 	if (error != 0) {
1575 		yyerror(gai_strerror(error));
1576 		return NULL;
1577 	}
1578 	return res;
1579 }
1580 
1581 static int
1582 fix_portstr(ulproto, spec, sport, dport)
1583 	int ulproto;
1584 	vchar_t *spec, *sport, *dport;
1585 {
1586 	char sp[16], dp[16];
1587 	int a, b, c, d;
1588 	unsigned long u;
1589 
1590 	if (spec->buf == NULL)
1591 		return 0;
1592 
1593 	switch (ulproto) {
1594 	case IPPROTO_ICMP:
1595 	case IPPROTO_ICMPV6:
1596 	case IPPROTO_MH:
1597 		if (sscanf(spec->buf, "%d,%d", &a, &b) == 2) {
1598 			sprintf(sp, "%d", a);
1599 			sprintf(dp, "%d", b);
1600 		} else if (sscanf(spec->buf, "%d", &a) == 1) {
1601 			sprintf(sp, "%d", a);
1602 		} else {
1603 			yyerror("invalid an upper layer protocol spec");
1604 			return -1;
1605 		}
1606 		break;
1607 	case IPPROTO_GRE:
1608 		if (sscanf(spec->buf, "%d.%d.%d.%d", &a, &b, &c, &d) == 4) {
1609 			sprintf(sp, "%d", (a << 8) + b);
1610 			sprintf(dp, "%d", (c << 8) + d);
1611 		} else if (sscanf(spec->buf, "%lu", &u) == 1) {
1612 			sprintf(sp, "%d", (int) (u >> 16));
1613 			sprintf(dp, "%d", (int) (u & 0xffff));
1614 		} else {
1615 			yyerror("invalid an upper layer protocol spec");
1616 			return -1;
1617 		}
1618 		break;
1619 	}
1620 
1621 	free(sport->buf);
1622 	sport->buf = strdup(sp);
1623 	if (!sport->buf) {
1624 		yyerror("insufficient memory");
1625 		return -1;
1626 	}
1627 	sport->len = strlen(sport->buf);
1628 
1629 	free(dport->buf);
1630 	dport->buf = strdup(dp);
1631 	if (!dport->buf) {
1632 		yyerror("insufficient memory");
1633 		return -1;
1634 	}
1635 	dport->len = strlen(dport->buf);
1636 
1637 	return 0;
1638 }
1639 
1640 static int
1641 setvarbuf(buf, off, ebuf, elen, vbuf, vlen)
1642 	char *buf;
1643 	int *off;
1644 	struct sadb_ext *ebuf;
1645 	int elen;
1646 	const void *vbuf;
1647 	int vlen;
1648 {
1649 	memset(buf + *off, 0, PFKEY_UNUNIT64(ebuf->sadb_ext_len));
1650 	memcpy(buf + *off, (caddr_t)ebuf, elen);
1651 	memcpy(buf + *off + elen, vbuf, vlen);
1652 	(*off) += PFKEY_ALIGN8(elen + vlen);
1653 
1654 	return 0;
1655 }
1656 
1657 void
1658 parse_init()
1659 {
1660 	p_spi = 0;
1661 
1662 	p_ext = SADB_X_EXT_CYCSEQ;
1663 	p_alg_enc = SADB_EALG_NONE;
1664 	p_alg_auth = SADB_AALG_NONE;
1665 	p_mode = IPSEC_MODE_ANY;
1666 	p_reqid = 0;
1667 	p_replay = 0;
1668 	p_key_enc_len = p_key_auth_len = 0;
1669 	p_key_enc = p_key_auth = 0;
1670 	p_lt_hard = p_lt_soft = 0;
1671 	p_lb_hard = p_lb_soft = 0;
1672 
1673 	memset(&sec_ctx, 0, sizeof(struct security_ctx));
1674 
1675 	p_aiflags = 0;
1676 	p_aifamily = PF_UNSPEC;
1677 
1678 	/* Clear out any natt OA information */
1679 	if (p_natt_oa)
1680 		freeaddrinfo (p_natt_oa);
1681 	p_natt_oa = NULL;
1682 	p_natt_type = 0;
1683 	p_esp_frag = 0;
1684 
1685 	return;
1686 }
1687 
1688 void
1689 free_buffer()
1690 {
1691 	/* we got tons of memory leaks in the parser anyways, leave them */
1692 
1693 	return;
1694 }
1695