xref: /netbsd-src/crypto/dist/ipsec-tools/src/setkey/parse.y (revision c3ab26950fe8540fb553d1d1dcae454bc98e5a25)
1 /*	$NetBSD: parse.y,v 1.16 2013/10/20 21:17:28 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 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
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 	|	BLCL ANY ELCL
801 		{
802 			$$.buf = strdup("0");
803 			if (!$$.buf) {
804 				yyerror("insufficient memory");
805 				return -1;
806 			}
807 			$$.len = strlen($$.buf);
808 		}
809 	|	BLCL DECSTRING ELCL
810 		{
811 			char buf[20];
812 			snprintf(buf, sizeof(buf), "%lu", $2);
813 			$$.buf = strdup(buf);
814 			if (!$$.buf) {
815 				yyerror("insufficient memory");
816 				return -1;
817 			}
818 			$$.len = strlen($$.buf);
819 		}
820 	|	BLCL STRING ELCL
821 		{
822 			$$ = $2;
823 		}
824 	;
825 
826 upper_spec
827 	:	DECSTRING { $$ = $1; }
828 	|	ANY { $$ = IPSEC_ULPROTO_ANY; }
829 	|	PR_TCP {
830 				$$ = IPPROTO_TCP;
831 			}
832 	|	STRING
833 		{
834 			struct protoent *ent;
835 
836 			ent = getprotobyname($1.buf);
837 			if (ent)
838 				$$ = ent->p_proto;
839 			else {
840 				if (strcmp("icmp6", $1.buf) == 0) {
841 					$$ = IPPROTO_ICMPV6;
842 				} else if(strcmp("ip4", $1.buf) == 0) {
843 					$$ = IPPROTO_IPV4;
844 				} else {
845 					yyerror("invalid upper layer protocol");
846 					return -1;
847 				}
848 			}
849 			endprotoent();
850 		}
851 	;
852 
853 upper_misc_spec
854 	:	/*NOTHING*/
855 		{
856 			$$.buf = NULL;
857 			$$.len = 0;
858 		}
859 	|	STRING
860 		{
861 			$$.buf = strdup($1.buf);
862 			if (!$$.buf) {
863 				yyerror("insufficient memory");
864 				return -1;
865 			}
866 			$$.len = strlen($$.buf);
867 		}
868 	;
869 
870 context_spec
871 	:	/* NOTHING */
872 	|	SECURITY_CTX DECSTRING DECSTRING QUOTEDSTRING {
873 			sec_ctx.doi = $2;
874 			sec_ctx.alg = $3;
875 			sec_ctx.len = $4.len+1;
876 			sec_ctx.buf = $4.buf;
877 		}
878 	;
879 
880 policy_spec
881 	:	F_POLICY policy_requests
882 		{
883 			char *policy;
884 #ifdef HAVE_PFKEY_POLICY_PRIORITY
885 			struct sadb_x_policy *xpl;
886 #endif
887 
888 			policy = ipsec_set_policy($2.buf, $2.len);
889 			if (policy == NULL) {
890 				yyerror(ipsec_strerror());
891 				return -1;
892 			}
893 
894 			$$.buf = policy;
895 			$$.len = ipsec_get_policylen(policy);
896 
897 #ifdef HAVE_PFKEY_POLICY_PRIORITY
898 			xpl = (struct sadb_x_policy *) $$.buf;
899 			last_priority = xpl->sadb_x_policy_priority;
900 #endif
901 		}
902 	;
903 
904 policy_requests
905 	:	PL_REQUESTS { $$ = $1; }
906 	;
907 
908 	/* exit */
909 exit_command
910 	:	EXIT EOT
911 		{
912 			exit_now = 1;
913 			YYACCEPT;
914 		}
915 	;
916 %%
917 
918 int
919 setkeymsg0(msg, type, satype, l)
920 	struct sadb_msg *msg;
921 	unsigned int type;
922 	unsigned int satype;
923 	size_t l;
924 {
925 
926 	msg->sadb_msg_version = PF_KEY_V2;
927 	msg->sadb_msg_type = type;
928 	msg->sadb_msg_errno = 0;
929 	msg->sadb_msg_satype = satype;
930 	msg->sadb_msg_reserved = 0;
931 	msg->sadb_msg_seq = 0;
932 	msg->sadb_msg_pid = getpid();
933 	msg->sadb_msg_len = PFKEY_UNIT64(l);
934 	return 0;
935 }
936 
937 /* XXX NO BUFFER OVERRUN CHECK! BAD BAD! */
938 static int
939 setkeymsg_spdaddr(type, upper, policy, srcs, splen, dsts, dplen)
940 	unsigned int type;
941 	unsigned int upper;
942 	vchar_t *policy;
943 	struct addrinfo *srcs;
944 	int splen;
945 	struct addrinfo *dsts;
946 	int dplen;
947 {
948 	struct sadb_msg *msg;
949 	char buf[BUFSIZ];
950 	int l, l0;
951 	struct sadb_address m_addr;
952 	struct addrinfo *s, *d;
953 	int n;
954 	int plen;
955 	struct sockaddr *sa;
956 	int salen;
957 #ifdef HAVE_POLICY_FWD
958 	struct sadb_x_ipsecrequest *ps = NULL;
959 	int saved_level, saved_id = 0;
960 #endif
961 
962 	msg = (struct sadb_msg *)buf;
963 
964 	if (!srcs || !dsts)
965 		return -1;
966 
967 	/* fix up length afterwards */
968 	setkeymsg0(msg, type, SADB_SATYPE_UNSPEC, 0);
969 	l = sizeof(struct sadb_msg);
970 
971 	memcpy(buf + l, policy->buf, policy->len);
972 	l += policy->len;
973 
974 	l0 = l;
975 	n = 0;
976 
977 	/* do it for all src/dst pairs */
978 	for (s = srcs; s; s = s->ai_next) {
979 		for (d = dsts; d; d = d->ai_next) {
980 			/* rewind pointer */
981 			l = l0;
982 
983 			if (s->ai_addr->sa_family != d->ai_addr->sa_family)
984 				continue;
985 			switch (s->ai_addr->sa_family) {
986 			case AF_INET:
987 				plen = sizeof(struct in_addr) << 3;
988 				break;
989 #ifdef INET6
990 			case AF_INET6:
991 				plen = sizeof(struct in6_addr) << 3;
992 				break;
993 #endif
994 			default:
995 				continue;
996 			}
997 
998 			/* set src */
999 			sa = s->ai_addr;
1000 			salen = sysdep_sa_len(s->ai_addr);
1001 			m_addr.sadb_address_len = PFKEY_UNIT64(sizeof(m_addr) +
1002 			    PFKEY_ALIGN8(salen));
1003 			m_addr.sadb_address_exttype = SADB_EXT_ADDRESS_SRC;
1004 			m_addr.sadb_address_proto = upper;
1005 			m_addr.sadb_address_prefixlen =
1006 			    (splen >= 0 ? splen : plen);
1007 			m_addr.sadb_address_reserved = 0;
1008 
1009 			setvarbuf(buf, &l, (struct sadb_ext *)&m_addr,
1010 			    sizeof(m_addr), (caddr_t)sa, salen);
1011 
1012 			/* set dst */
1013 			sa = d->ai_addr;
1014 			salen = sysdep_sa_len(d->ai_addr);
1015 			m_addr.sadb_address_len = PFKEY_UNIT64(sizeof(m_addr) +
1016 			    PFKEY_ALIGN8(salen));
1017 			m_addr.sadb_address_exttype = SADB_EXT_ADDRESS_DST;
1018 			m_addr.sadb_address_proto = upper;
1019 			m_addr.sadb_address_prefixlen =
1020 			    (dplen >= 0 ? dplen : plen);
1021 			m_addr.sadb_address_reserved = 0;
1022 
1023 			setvarbuf(buf, &l, (struct sadb_ext *)&m_addr,
1024 			    sizeof(m_addr), sa, salen);
1025 #ifdef SADB_X_EXT_SEC_CTX
1026 			/* Add security context label */
1027 			if (sec_ctx.doi) {
1028 				struct sadb_x_sec_ctx m_sec_ctx;
1029 				u_int slen = sizeof(struct sadb_x_sec_ctx);
1030 
1031 				memset(&m_sec_ctx, 0, slen);
1032 
1033 				m_sec_ctx.sadb_x_sec_len =
1034 				PFKEY_UNIT64(slen + PFKEY_ALIGN8(sec_ctx.len));
1035 
1036 				m_sec_ctx.sadb_x_sec_exttype =
1037 					SADB_X_EXT_SEC_CTX;
1038 				m_sec_ctx.sadb_x_ctx_len = sec_ctx.len;/*bytes*/
1039 				m_sec_ctx.sadb_x_ctx_doi = sec_ctx.doi;
1040 				m_sec_ctx.sadb_x_ctx_alg = sec_ctx.alg;
1041 				setvarbuf(buf, &l,
1042 					  (struct sadb_ext *)&m_sec_ctx, slen,
1043 					  (caddr_t)sec_ctx.buf, sec_ctx.len);
1044 			}
1045 #endif
1046 			msg->sadb_msg_len = PFKEY_UNIT64(l);
1047 
1048 			sendkeymsg(buf, l);
1049 
1050 #ifdef HAVE_POLICY_FWD
1051 			/* create extra call for FWD policy */
1052 			if (f_rfcmode && sp->sadb_x_policy_dir == IPSEC_DIR_INBOUND) {
1053 				sp->sadb_x_policy_dir = IPSEC_DIR_FWD;
1054 				ps = (struct sadb_x_ipsecrequest*) (sp+1);
1055 
1056 				/* if request level is unique, change it to
1057 				 * require for fwd policy */
1058 				/* XXX: currently, only first policy is updated
1059 				 * only. Update following too... */
1060 				saved_level = ps->sadb_x_ipsecrequest_level;
1061 				if (saved_level == IPSEC_LEVEL_UNIQUE) {
1062 					saved_id = ps->sadb_x_ipsecrequest_reqid;
1063 					ps->sadb_x_ipsecrequest_reqid=0;
1064 					ps->sadb_x_ipsecrequest_level=IPSEC_LEVEL_REQUIRE;
1065 				}
1066 
1067 				sendkeymsg(buf, l);
1068 				/* restoring for next message */
1069 				sp->sadb_x_policy_dir = IPSEC_DIR_INBOUND;
1070 				if (saved_level == IPSEC_LEVEL_UNIQUE) {
1071 					ps->sadb_x_ipsecrequest_reqid = saved_id;
1072 					ps->sadb_x_ipsecrequest_level = saved_level;
1073 				}
1074 			}
1075 #endif
1076 
1077 			n++;
1078 		}
1079 	}
1080 
1081 	if (n == 0)
1082 		return -1;
1083 	else
1084 		return 0;
1085 }
1086 
1087 static int
1088 setkeymsg_spdaddr_tag(type, tag, policy)
1089 	unsigned int type;
1090 	char *tag;
1091 	vchar_t *policy;
1092 {
1093 	struct sadb_msg *msg;
1094 	char buf[BUFSIZ];
1095 	int l;
1096 #ifdef SADB_X_EXT_TAG
1097 	struct sadb_x_tag m_tag;
1098 #endif
1099 
1100 	msg = (struct sadb_msg *)buf;
1101 
1102 	/* fix up length afterwards */
1103 	setkeymsg0(msg, type, SADB_SATYPE_UNSPEC, 0);
1104 	l = sizeof(struct sadb_msg);
1105 
1106 	memcpy(buf + l, policy->buf, policy->len);
1107 	l += policy->len;
1108 
1109 #ifdef SADB_X_EXT_TAG
1110 	memset(&m_tag, 0, sizeof(m_tag));
1111 	m_tag.sadb_x_tag_len = PFKEY_UNIT64(sizeof(m_tag));
1112 	m_tag.sadb_x_tag_exttype = SADB_X_EXT_TAG;
1113 	if (strlcpy(m_tag.sadb_x_tag_name, tag,
1114 	    sizeof(m_tag.sadb_x_tag_name)) >= sizeof(m_tag.sadb_x_tag_name))
1115 		return -1;
1116 	memcpy(buf + l, &m_tag, sizeof(m_tag));
1117 	l += sizeof(m_tag);
1118 #endif
1119 
1120 	msg->sadb_msg_len = PFKEY_UNIT64(l);
1121 
1122 	sendkeymsg(buf, l);
1123 
1124 	return 0;
1125 }
1126 
1127 /* XXX NO BUFFER OVERRUN CHECK! BAD BAD! */
1128 static int
1129 setkeymsg_addr(type, satype, srcs, dsts, no_spi)
1130 	unsigned int type;
1131 	unsigned int satype;
1132 	struct addrinfo *srcs;
1133 	struct addrinfo *dsts;
1134 	int no_spi;
1135 {
1136 	struct sadb_msg *msg;
1137 	char buf[BUFSIZ];
1138 	int l, l0, len;
1139 	struct sadb_sa m_sa;
1140 	struct sadb_x_sa2 m_sa2;
1141 	struct sadb_address m_addr;
1142 	struct addrinfo *s, *d;
1143 	int n;
1144 	int plen;
1145 	struct sockaddr *sa;
1146 	int salen;
1147 
1148 	msg = (struct sadb_msg *)buf;
1149 
1150 	if (!srcs || !dsts)
1151 		return -1;
1152 
1153 	/* fix up length afterwards */
1154 	setkeymsg0(msg, type, satype, 0);
1155 	l = sizeof(struct sadb_msg);
1156 
1157 	if (!no_spi) {
1158 		len = sizeof(struct sadb_sa);
1159 		m_sa.sadb_sa_len = PFKEY_UNIT64(len);
1160 		m_sa.sadb_sa_exttype = SADB_EXT_SA;
1161 		m_sa.sadb_sa_spi = htonl(p_spi);
1162 		m_sa.sadb_sa_replay = p_replay;
1163 		m_sa.sadb_sa_state = 0;
1164 		m_sa.sadb_sa_auth = p_alg_auth;
1165 		m_sa.sadb_sa_encrypt = p_alg_enc;
1166 		m_sa.sadb_sa_flags = p_ext;
1167 
1168 		memcpy(buf + l, &m_sa, len);
1169 		l += len;
1170 
1171 		len = sizeof(struct sadb_x_sa2);
1172 		m_sa2.sadb_x_sa2_len = PFKEY_UNIT64(len);
1173 		m_sa2.sadb_x_sa2_exttype = SADB_X_EXT_SA2;
1174 		m_sa2.sadb_x_sa2_mode = p_mode;
1175 		m_sa2.sadb_x_sa2_reqid = p_reqid;
1176 
1177 		memcpy(buf + l, &m_sa2, len);
1178 		l += len;
1179 	}
1180 
1181 	l0 = l;
1182 	n = 0;
1183 
1184 	/* do it for all src/dst pairs */
1185 	for (s = srcs; s; s = s->ai_next) {
1186 		for (d = dsts; d; d = d->ai_next) {
1187 			/* rewind pointer */
1188 			l = l0;
1189 
1190 			if (s->ai_addr->sa_family != d->ai_addr->sa_family)
1191 				continue;
1192 			switch (s->ai_addr->sa_family) {
1193 			case AF_INET:
1194 				plen = sizeof(struct in_addr) << 3;
1195 				break;
1196 #ifdef INET6
1197 			case AF_INET6:
1198 				plen = sizeof(struct in6_addr) << 3;
1199 				break;
1200 #endif
1201 			default:
1202 				continue;
1203 			}
1204 
1205 			/* set src */
1206 			sa = s->ai_addr;
1207 			salen = sysdep_sa_len(s->ai_addr);
1208 			m_addr.sadb_address_len = PFKEY_UNIT64(sizeof(m_addr) +
1209 			    PFKEY_ALIGN8(salen));
1210 			m_addr.sadb_address_exttype = SADB_EXT_ADDRESS_SRC;
1211 			m_addr.sadb_address_proto = IPSEC_ULPROTO_ANY;
1212 			m_addr.sadb_address_prefixlen = plen;
1213 			m_addr.sadb_address_reserved = 0;
1214 
1215 			setvarbuf(buf, &l, (struct sadb_ext *)&m_addr,
1216 			    sizeof(m_addr), sa, salen);
1217 
1218 			/* set dst */
1219 			sa = d->ai_addr;
1220 			salen = sysdep_sa_len(d->ai_addr);
1221 			m_addr.sadb_address_len = PFKEY_UNIT64(sizeof(m_addr) +
1222 			    PFKEY_ALIGN8(salen));
1223 			m_addr.sadb_address_exttype = SADB_EXT_ADDRESS_DST;
1224 			m_addr.sadb_address_proto = IPSEC_ULPROTO_ANY;
1225 			m_addr.sadb_address_prefixlen = plen;
1226 			m_addr.sadb_address_reserved = 0;
1227 
1228 			setvarbuf(buf, &l, (struct sadb_ext *)&m_addr,
1229 			    sizeof(m_addr), sa, salen);
1230 
1231 			msg->sadb_msg_len = PFKEY_UNIT64(l);
1232 
1233 			sendkeymsg(buf, l);
1234 
1235 			n++;
1236 		}
1237 	}
1238 
1239 	if (n == 0)
1240 		return -1;
1241 	else
1242 		return 0;
1243 }
1244 
1245 #ifdef SADB_X_EXT_NAT_T_TYPE
1246 static u_int16_t get_port (struct addrinfo *addr)
1247 {
1248 	struct sockaddr *s = addr->ai_addr;
1249 	u_int16_t port = 0;
1250 
1251 	switch (s->sa_family) {
1252 	case AF_INET:
1253 	  {
1254 		struct sockaddr_in *sin4 = (struct sockaddr_in *)s;
1255 		port = ntohs(sin4->sin_port);
1256 		break;
1257 	  }
1258 	case AF_INET6:
1259 	  {
1260 		struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)s;
1261 		port = ntohs(sin6->sin6_port);
1262 		break;
1263 	  }
1264 	}
1265 
1266 	if (port == 0)
1267 		port = DEFAULT_NATT_PORT;
1268 
1269 	return port;
1270 }
1271 #endif
1272 
1273 /* XXX NO BUFFER OVERRUN CHECK! BAD BAD! */
1274 static int
1275 setkeymsg_add(type, satype, srcs, dsts)
1276 	unsigned int type;
1277 	unsigned int satype;
1278 	struct addrinfo *srcs;
1279 	struct addrinfo *dsts;
1280 {
1281 	struct sadb_msg *msg;
1282 	char buf[BUFSIZ];
1283 	int l, l0, len;
1284 	struct sadb_sa m_sa;
1285 	struct sadb_x_sa2 m_sa2;
1286 	struct sadb_address m_addr;
1287 	struct addrinfo *s, *d;
1288 	int n;
1289 	int plen;
1290 	struct sockaddr *sa;
1291 	int salen;
1292 
1293 	msg = (struct sadb_msg *)buf;
1294 
1295 	if (!srcs || !dsts)
1296 		return -1;
1297 
1298 	/* fix up length afterwards */
1299 	setkeymsg0(msg, type, satype, 0);
1300 	l = sizeof(struct sadb_msg);
1301 
1302 	/* set encryption algorithm, if present. */
1303 	if (satype != SADB_X_SATYPE_IPCOMP && p_key_enc) {
1304 		union {
1305 			struct sadb_key key;
1306 			struct sadb_ext ext;
1307 		} m;
1308 
1309 		m.key.sadb_key_len =
1310 			PFKEY_UNIT64(sizeof(m.key)
1311 				   + PFKEY_ALIGN8(p_key_enc_len));
1312 		m.key.sadb_key_exttype = SADB_EXT_KEY_ENCRYPT;
1313 		m.key.sadb_key_bits = p_key_enc_len * 8;
1314 		m.key.sadb_key_reserved = 0;
1315 
1316 		setvarbuf(buf, &l, &m.ext, sizeof(m.key),
1317 			p_key_enc, p_key_enc_len);
1318 	}
1319 
1320 	/* set authentication algorithm, if present. */
1321 	if (p_key_auth) {
1322 		union {
1323 			struct sadb_key key;
1324 			struct sadb_ext ext;
1325 		} m;
1326 
1327 		m.key.sadb_key_len =
1328 			PFKEY_UNIT64(sizeof(m.key)
1329 				   + PFKEY_ALIGN8(p_key_auth_len));
1330 		m.key.sadb_key_exttype = SADB_EXT_KEY_AUTH;
1331 		m.key.sadb_key_bits = p_key_auth_len * 8;
1332 		m.key.sadb_key_reserved = 0;
1333 
1334 		setvarbuf(buf, &l, &m.ext, sizeof(m.key),
1335 			p_key_auth, p_key_auth_len);
1336 	}
1337 
1338 	/* set lifetime for HARD */
1339 	if (p_lt_hard != 0 || p_lb_hard != 0) {
1340 		struct sadb_lifetime m_lt;
1341 		u_int slen = sizeof(struct sadb_lifetime);
1342 
1343 		m_lt.sadb_lifetime_len = PFKEY_UNIT64(slen);
1344 		m_lt.sadb_lifetime_exttype = SADB_EXT_LIFETIME_HARD;
1345 		m_lt.sadb_lifetime_allocations = 0;
1346 		m_lt.sadb_lifetime_bytes = p_lb_hard;
1347 		m_lt.sadb_lifetime_addtime = p_lt_hard;
1348 		m_lt.sadb_lifetime_usetime = 0;
1349 
1350 		memcpy(buf + l, &m_lt, slen);
1351 		l += slen;
1352 	}
1353 
1354 	/* set lifetime for SOFT */
1355 	if (p_lt_soft != 0 || p_lb_soft != 0) {
1356 		struct sadb_lifetime m_lt;
1357 		u_int slen = sizeof(struct sadb_lifetime);
1358 
1359 		m_lt.sadb_lifetime_len = PFKEY_UNIT64(slen);
1360 		m_lt.sadb_lifetime_exttype = SADB_EXT_LIFETIME_SOFT;
1361 		m_lt.sadb_lifetime_allocations = 0;
1362 		m_lt.sadb_lifetime_bytes = p_lb_soft;
1363 		m_lt.sadb_lifetime_addtime = p_lt_soft;
1364 		m_lt.sadb_lifetime_usetime = 0;
1365 
1366 		memcpy(buf + l, &m_lt, slen);
1367 		l += slen;
1368 	}
1369 
1370 #ifdef SADB_X_EXT_SEC_CTX
1371 	/* Add security context label */
1372 	if (sec_ctx.doi) {
1373 		struct sadb_x_sec_ctx m_sec_ctx;
1374 		u_int slen = sizeof(struct sadb_x_sec_ctx);
1375 
1376 		memset(&m_sec_ctx, 0, slen);
1377 
1378 		m_sec_ctx.sadb_x_sec_len = PFKEY_UNIT64(slen +
1379 					PFKEY_ALIGN8(sec_ctx.len));
1380 		m_sec_ctx.sadb_x_sec_exttype = SADB_X_EXT_SEC_CTX;
1381 		m_sec_ctx.sadb_x_ctx_len = sec_ctx.len; /* bytes */
1382 		m_sec_ctx.sadb_x_ctx_doi = sec_ctx.doi;
1383 		m_sec_ctx.sadb_x_ctx_alg = sec_ctx.alg;
1384 		setvarbuf(buf, &l, (struct sadb_ext *)&m_sec_ctx, slen,
1385 			  (caddr_t)sec_ctx.buf, sec_ctx.len);
1386 	}
1387 #endif
1388 
1389 	len = sizeof(struct sadb_sa);
1390 	m_sa.sadb_sa_len = PFKEY_UNIT64(len);
1391 	m_sa.sadb_sa_exttype = SADB_EXT_SA;
1392 	m_sa.sadb_sa_spi = htonl(p_spi);
1393 	m_sa.sadb_sa_replay = p_replay;
1394 	m_sa.sadb_sa_state = 0;
1395 	m_sa.sadb_sa_auth = p_alg_auth;
1396 	m_sa.sadb_sa_encrypt = p_alg_enc;
1397 	m_sa.sadb_sa_flags = p_ext;
1398 
1399 	memcpy(buf + l, &m_sa, len);
1400 	l += len;
1401 
1402 	len = sizeof(struct sadb_x_sa2);
1403 	m_sa2.sadb_x_sa2_len = PFKEY_UNIT64(len);
1404 	m_sa2.sadb_x_sa2_exttype = SADB_X_EXT_SA2;
1405 	m_sa2.sadb_x_sa2_mode = p_mode;
1406 	m_sa2.sadb_x_sa2_reqid = p_reqid;
1407 
1408 	memcpy(buf + l, &m_sa2, len);
1409 	l += len;
1410 
1411 #ifdef SADB_X_EXT_NAT_T_TYPE
1412 	if (p_natt_type) {
1413 		struct sadb_x_nat_t_type natt_type;
1414 
1415 		len = sizeof(struct sadb_x_nat_t_type);
1416 		memset(&natt_type, 0, len);
1417 		natt_type.sadb_x_nat_t_type_len = PFKEY_UNIT64(len);
1418 		natt_type.sadb_x_nat_t_type_exttype = SADB_X_EXT_NAT_T_TYPE;
1419 		natt_type.sadb_x_nat_t_type_type = p_natt_type;
1420 
1421 		memcpy(buf + l, &natt_type, len);
1422 		l += len;
1423 
1424 		if (p_natt_oa) {
1425 			sa = p_natt_oa->ai_addr;
1426 			switch (sa->sa_family) {
1427 			case AF_INET:
1428 				plen = sizeof(struct in_addr) << 3;
1429 				break;
1430 #ifdef INET6
1431 			case AF_INET6:
1432 				plen = sizeof(struct in6_addr) << 3;
1433 				break;
1434 #endif
1435 			default:
1436 				return -1;
1437 			}
1438 			salen = sysdep_sa_len(sa);
1439 			m_addr.sadb_address_len = PFKEY_UNIT64(sizeof(m_addr) +
1440 			    PFKEY_ALIGN8(salen));
1441 			m_addr.sadb_address_exttype = SADB_X_EXT_NAT_T_OA;
1442 			m_addr.sadb_address_proto = IPSEC_ULPROTO_ANY;
1443 			m_addr.sadb_address_prefixlen = plen;
1444 			m_addr.sadb_address_reserved = 0;
1445 
1446 			setvarbuf(buf, &l, (struct sadb_ext *)&m_addr,
1447 			    sizeof(m_addr), sa, salen);
1448 		}
1449 	}
1450 #endif
1451 
1452 	l0 = l;
1453 	n = 0;
1454 
1455 	/* do it for all src/dst pairs */
1456 	for (s = srcs; s; s = s->ai_next) {
1457 		for (d = dsts; d; d = d->ai_next) {
1458 			/* rewind pointer */
1459 			l = l0;
1460 
1461 			if (s->ai_addr->sa_family != d->ai_addr->sa_family)
1462 				continue;
1463 			switch (s->ai_addr->sa_family) {
1464 			case AF_INET:
1465 				plen = sizeof(struct in_addr) << 3;
1466 				break;
1467 #ifdef INET6
1468 			case AF_INET6:
1469 				plen = sizeof(struct in6_addr) << 3;
1470 				break;
1471 #endif
1472 			default:
1473 				continue;
1474 			}
1475 
1476 			/* set src */
1477 			sa = s->ai_addr;
1478 			salen = sysdep_sa_len(s->ai_addr);
1479 			m_addr.sadb_address_len = PFKEY_UNIT64(sizeof(m_addr) +
1480 			    PFKEY_ALIGN8(salen));
1481 			m_addr.sadb_address_exttype = SADB_EXT_ADDRESS_SRC;
1482 			m_addr.sadb_address_proto = IPSEC_ULPROTO_ANY;
1483 			m_addr.sadb_address_prefixlen = plen;
1484 			m_addr.sadb_address_reserved = 0;
1485 
1486 			setvarbuf(buf, &l, (struct sadb_ext *)&m_addr,
1487 			    sizeof(m_addr), sa, salen);
1488 
1489 			/* set dst */
1490 			sa = d->ai_addr;
1491 			salen = sysdep_sa_len(d->ai_addr);
1492 			m_addr.sadb_address_len = PFKEY_UNIT64(sizeof(m_addr) +
1493 			    PFKEY_ALIGN8(salen));
1494 			m_addr.sadb_address_exttype = SADB_EXT_ADDRESS_DST;
1495 			m_addr.sadb_address_proto = IPSEC_ULPROTO_ANY;
1496 			m_addr.sadb_address_prefixlen = plen;
1497 			m_addr.sadb_address_reserved = 0;
1498 
1499 			setvarbuf(buf, &l, (struct sadb_ext *)&m_addr,
1500 			    sizeof(m_addr), sa, salen);
1501 
1502 #ifdef SADB_X_EXT_NAT_T_TYPE
1503 			if (p_natt_type) {
1504 				struct sadb_x_nat_t_port natt_port;
1505 
1506 				/* NATT_SPORT */
1507 				len = sizeof(struct sadb_x_nat_t_port);
1508 				memset(&natt_port, 0, len);
1509 				natt_port.sadb_x_nat_t_port_len = PFKEY_UNIT64(len);
1510 				natt_port.sadb_x_nat_t_port_exttype =
1511 					SADB_X_EXT_NAT_T_SPORT;
1512 				natt_port.sadb_x_nat_t_port_port = htons(get_port(s));
1513 
1514 				memcpy(buf + l, &natt_port, len);
1515 				l += len;
1516 
1517 				/* NATT_DPORT */
1518 				natt_port.sadb_x_nat_t_port_exttype =
1519 					SADB_X_EXT_NAT_T_DPORT;
1520 				natt_port.sadb_x_nat_t_port_port = htons(get_port(d));
1521 
1522 				memcpy(buf + l, &natt_port, len);
1523 				l += len;
1524 #ifdef SADB_X_EXT_NAT_T_FRAG
1525 				if (p_esp_frag) {
1526 					struct sadb_x_nat_t_frag esp_frag;
1527 
1528 					/* NATT_FRAG */
1529 					len = sizeof(struct sadb_x_nat_t_frag);
1530 					memset(&esp_frag, 0, len);
1531 					esp_frag.sadb_x_nat_t_frag_len = PFKEY_UNIT64(len);
1532 					esp_frag.sadb_x_nat_t_frag_exttype =
1533 						SADB_X_EXT_NAT_T_FRAG;
1534 					esp_frag.sadb_x_nat_t_frag_fraglen = p_esp_frag;
1535 
1536 					memcpy(buf + l, &esp_frag, len);
1537 					l += len;
1538 				}
1539 #endif
1540 			}
1541 #endif
1542 			msg->sadb_msg_len = PFKEY_UNIT64(l);
1543 
1544 			sendkeymsg(buf, l);
1545 
1546 			n++;
1547 		}
1548 	}
1549 
1550 	if (n == 0)
1551 		return -1;
1552 	else
1553 		return 0;
1554 }
1555 
1556 static struct addrinfo *
1557 parse_addr(host, port)
1558 	char *host;
1559 	char *port;
1560 {
1561 	struct addrinfo hints, *res = NULL;
1562 	int error;
1563 
1564 	memset(&hints, 0, sizeof(hints));
1565 	hints.ai_family = p_aifamily;
1566 	hints.ai_socktype = SOCK_DGRAM;		/*dummy*/
1567 	hints.ai_protocol = IPPROTO_UDP;	/*dummy*/
1568 	hints.ai_flags = p_aiflags;
1569 	error = getaddrinfo(host, port, &hints, &res);
1570 	if (error != 0) {
1571 		yyerror(gai_strerror(error));
1572 		return NULL;
1573 	}
1574 	return res;
1575 }
1576 
1577 static int
1578 fix_portstr(ulproto, spec, sport, dport)
1579 	int ulproto;
1580 	vchar_t *spec, *sport, *dport;
1581 {
1582 	char sp[16], dp[16];
1583 	int a, b, c, d;
1584 	unsigned long u;
1585 
1586 	if (spec->buf == NULL)
1587 		return 0;
1588 
1589 	switch (ulproto) {
1590 	case IPPROTO_ICMP:
1591 	case IPPROTO_ICMPV6:
1592 	case IPPROTO_MH:
1593 		if (sscanf(spec->buf, "%d,%d", &a, &b) == 2) {
1594 			sprintf(sp, "%d", a);
1595 			sprintf(dp, "%d", b);
1596 		} else if (sscanf(spec->buf, "%d", &a) == 1) {
1597 			sprintf(sp, "%d", a);
1598 		} else {
1599 			yyerror("invalid an upper layer protocol spec");
1600 			return -1;
1601 		}
1602 		break;
1603 	case IPPROTO_GRE:
1604 		if (sscanf(spec->buf, "%d.%d.%d.%d", &a, &b, &c, &d) == 4) {
1605 			sprintf(sp, "%d", (a << 8) + b);
1606 			sprintf(dp, "%d", (c << 8) + d);
1607 		} else if (sscanf(spec->buf, "%lu", &u) == 1) {
1608 			sprintf(sp, "%d", (int) (u >> 16));
1609 			sprintf(dp, "%d", (int) (u & 0xffff));
1610 		} else {
1611 			yyerror("invalid an upper layer protocol spec");
1612 			return -1;
1613 		}
1614 		break;
1615 	}
1616 
1617 	free(sport->buf);
1618 	sport->buf = strdup(sp);
1619 	if (!sport->buf) {
1620 		yyerror("insufficient memory");
1621 		return -1;
1622 	}
1623 	sport->len = strlen(sport->buf);
1624 
1625 	free(dport->buf);
1626 	dport->buf = strdup(dp);
1627 	if (!dport->buf) {
1628 		yyerror("insufficient memory");
1629 		return -1;
1630 	}
1631 	dport->len = strlen(dport->buf);
1632 
1633 	return 0;
1634 }
1635 
1636 static int
1637 setvarbuf(buf, off, ebuf, elen, vbuf, vlen)
1638 	char *buf;
1639 	int *off;
1640 	struct sadb_ext *ebuf;
1641 	int elen;
1642 	const void *vbuf;
1643 	int vlen;
1644 {
1645 	memset(buf + *off, 0, PFKEY_UNUNIT64(ebuf->sadb_ext_len));
1646 	memcpy(buf + *off, (caddr_t)ebuf, elen);
1647 	memcpy(buf + *off + elen, vbuf, vlen);
1648 	(*off) += PFKEY_ALIGN8(elen + vlen);
1649 
1650 	return 0;
1651 }
1652 
1653 void
1654 parse_init()
1655 {
1656 	p_spi = 0;
1657 
1658 	p_ext = SADB_X_EXT_CYCSEQ;
1659 	p_alg_enc = SADB_EALG_NONE;
1660 	p_alg_auth = SADB_AALG_NONE;
1661 	p_mode = IPSEC_MODE_ANY;
1662 	p_reqid = 0;
1663 	p_replay = 0;
1664 	p_key_enc_len = p_key_auth_len = 0;
1665 	p_key_enc = p_key_auth = 0;
1666 	p_lt_hard = p_lt_soft = 0;
1667 	p_lb_hard = p_lb_soft = 0;
1668 
1669 	memset(&sec_ctx, 0, sizeof(struct security_ctx));
1670 
1671 	p_aiflags = 0;
1672 	p_aifamily = PF_UNSPEC;
1673 
1674 	/* Clear out any natt OA information */
1675 	if (p_natt_oa)
1676 		freeaddrinfo (p_natt_oa);
1677 	p_natt_oa = NULL;
1678 	p_natt_type = 0;
1679 	p_esp_frag = 0;
1680 
1681 	return;
1682 }
1683 
1684 void
1685 free_buffer()
1686 {
1687 	/* we got tons of memory leaks in the parser anyways, leave them */
1688 
1689 	return;
1690 }
1691