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