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