xref: /freebsd/sbin/setkey/parse.y (revision 3193579b66fd7067f898dbc54bdea81a0e6f9bd0)
1 /*	$FreeBSD$	*/
2 /*	$KAME: parse.y,v 1.81 2003/07/01 04:01:48 itojun Exp $	*/
3 
4 /*
5  * Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project.
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  * 3. Neither the name of the project nor the names of its contributors
17  *    may be used to endorse or promote products derived from this software
18  *    without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23  * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
24  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30  * SUCH DAMAGE.
31  */
32 
33 %{
34 #include <sys/types.h>
35 #include <sys/param.h>
36 #include <sys/socket.h>
37 
38 #include <net/route.h>
39 #include <netinet/in.h>
40 #include <net/pfkeyv2.h>
41 #include <netkey/key_var.h>
42 #include <netinet6/ipsec.h>
43 #include <arpa/inet.h>
44 
45 #include <string.h>
46 #include <unistd.h>
47 #include <stdio.h>
48 #include <netdb.h>
49 #include <ctype.h>
50 #include <errno.h>
51 
52 #include "libpfkey.h"
53 #include "vchar.h"
54 
55 #define ATOX(c) \
56   (isdigit(c) ? (c - '0') : (isupper(c) ? (c - 'A' + 10) : (c - 'a' + 10)))
57 
58 u_int32_t p_spi;
59 u_int p_ext, p_alg_enc, p_alg_auth, p_replay, p_mode;
60 u_int32_t p_reqid;
61 u_int p_key_enc_len, p_key_auth_len;
62 caddr_t p_key_enc, p_key_auth;
63 time_t p_lt_hard, p_lt_soft;
64 
65 static int p_aiflags = 0, p_aifamily = PF_UNSPEC;
66 
67 static struct addrinfo *parse_addr __P((char *, char *));
68 static int fix_portstr __P((vchar_t *, vchar_t *, vchar_t *));
69 static int setvarbuf __P((char *, int *, struct sadb_ext *, int, caddr_t, int));
70 void parse_init __P((void));
71 void free_buffer __P((void));
72 
73 int setkeymsg0 __P((struct sadb_msg *, unsigned int, unsigned int, size_t));
74 static int setkeymsg_spdaddr __P((unsigned int, unsigned int, vchar_t *,
75 	struct addrinfo *, int, struct addrinfo *, int));
76 static int setkeymsg_addr __P((unsigned int, unsigned int,
77 	struct addrinfo *, struct addrinfo *, int));
78 static int setkeymsg_add __P((unsigned int, unsigned int,
79 	struct addrinfo *, struct addrinfo *));
80 extern int setkeymsg __P((char *, size_t *));
81 extern int sendkeymsg __P((char *, size_t));
82 
83 extern int yylex __P((void));
84 extern void yyfatal __P((const char *));
85 extern void yyerror __P((const char *));
86 %}
87 
88 %union {
89 	int num;
90 	unsigned long ulnum;
91 	vchar_t val;
92 	struct addrinfo *res;
93 }
94 
95 %token EOT SLASH BLCL ELCL
96 %token ADD GET DELETE DELETEALL FLUSH DUMP
97 %token PR_ESP PR_AH PR_IPCOMP
98 %token F_PROTOCOL F_AUTH F_ENC F_REPLAY F_COMP F_RAWCPI
99 %token F_MODE MODE F_REQID
100 %token F_EXT EXTENSION NOCYCLICSEQ
101 %token ALG_AUTH ALG_AUTH_NOKEY
102 %token ALG_ENC ALG_ENC_NOKEY ALG_ENC_DESDERIV ALG_ENC_DES32IV ALG_ENC_OLD
103 %token ALG_COMP
104 %token F_LIFETIME_HARD F_LIFETIME_SOFT
105 %token DECSTRING QUOTEDSTRING HEXSTRING STRING ANY
106 	/* SPD management */
107 %token SPDADD SPDDELETE SPDDUMP SPDFLUSH
108 %token F_POLICY PL_REQUESTS
109 %token F_AIFLAGS
110 %token TAGGED
111 
112 %type <num> prefix protocol_spec upper_spec
113 %type <num> ALG_ENC ALG_ENC_DESDERIV ALG_ENC_DES32IV ALG_ENC_OLD ALG_ENC_NOKEY
114 %type <num> ALG_AUTH ALG_AUTH_NOKEY
115 %type <num> ALG_COMP
116 %type <num> PR_ESP PR_AH PR_IPCOMP
117 %type <num> EXTENSION MODE
118 %type <ulnum> DECSTRING
119 %type <val> PL_REQUESTS portstr key_string
120 %type <val> policy_requests
121 %type <val> QUOTEDSTRING HEXSTRING STRING
122 %type <val> F_AIFLAGS
123 %type <val> upper_misc_spec policy_spec
124 %type <res> ipaddr
125 
126 %%
127 commands
128 	:	/*NOTHING*/
129 	|	commands command
130 		{
131 			free_buffer();
132 			parse_init();
133 		}
134 	;
135 
136 command
137 	:	add_command
138 	|	get_command
139 	|	delete_command
140 	|	deleteall_command
141 	|	flush_command
142 	|	dump_command
143 	|	spdadd_command
144 	|	spddelete_command
145 	|	spddump_command
146 	|	spdflush_command
147 	;
148 	/* commands concerned with management, there is in tail of this file. */
149 
150 	/* add command */
151 add_command
152 	:	ADD ipaddropts ipaddr ipaddr protocol_spec spi extension_spec algorithm_spec EOT
153 		{
154 			int status;
155 
156 			status = setkeymsg_add(SADB_ADD, $5, $3, $4);
157 			if (status < 0)
158 				return -1;
159 		}
160 	;
161 
162 	/* delete */
163 delete_command
164 	:	DELETE ipaddropts ipaddr ipaddr protocol_spec spi extension_spec EOT
165 		{
166 			int status;
167 
168 			if ($3->ai_next || $4->ai_next) {
169 				yyerror("multiple address specified");
170 				return -1;
171 			}
172 			if (p_mode != IPSEC_MODE_ANY)
173 				yyerror("WARNING: mode is obsolete");
174 
175 			status = setkeymsg_addr(SADB_DELETE, $5, $3, $4, 0);
176 			if (status < 0)
177 				return -1;
178 		}
179 	;
180 
181 	/* deleteall command */
182 deleteall_command
183 	:	DELETEALL ipaddropts ipaddr ipaddr protocol_spec EOT
184 		{
185 			int status;
186 
187 			status = setkeymsg_addr(SADB_DELETE, $5, $3, $4, 1);
188 			if (status < 0)
189 				return -1;
190 		}
191 	;
192 
193 	/* get command */
194 get_command
195 	:	GET ipaddropts ipaddr ipaddr protocol_spec spi extension_spec EOT
196 		{
197 			int status;
198 
199 			if (p_mode != IPSEC_MODE_ANY)
200 				yyerror("WARNING: mode is obsolete");
201 
202 			status = setkeymsg_addr(SADB_GET, $5, $3, $4, 0);
203 			if (status < 0)
204 				return -1;
205 		}
206 	;
207 
208 	/* flush */
209 flush_command
210 	:	FLUSH protocol_spec EOT
211 		{
212 			struct sadb_msg msg;
213 			setkeymsg0(&msg, SADB_FLUSH, $2, sizeof(msg));
214 			sendkeymsg((char *)&msg, sizeof(msg));
215 		}
216 	;
217 
218 	/* dump */
219 dump_command
220 	:	DUMP protocol_spec EOT
221 		{
222 			struct sadb_msg msg;
223 			setkeymsg0(&msg, SADB_DUMP, $2, sizeof(msg));
224 			sendkeymsg((char *)&msg, sizeof(msg));
225 		}
226 	;
227 
228 protocol_spec
229 	:	/*NOTHING*/
230 		{
231 			$$ = SADB_SATYPE_UNSPEC;
232 		}
233 	|	PR_ESP
234 		{
235 			$$ = SADB_SATYPE_ESP;
236 			if ($1 == 1)
237 				p_ext |= SADB_X_EXT_OLD;
238 			else
239 				p_ext &= ~SADB_X_EXT_OLD;
240 		}
241 	|	PR_AH
242 		{
243 			$$ = SADB_SATYPE_AH;
244 			if ($1 == 1)
245 				p_ext |= SADB_X_EXT_OLD;
246 			else
247 				p_ext &= ~SADB_X_EXT_OLD;
248 		}
249 	|	PR_IPCOMP
250 		{
251 			$$ = SADB_X_SATYPE_IPCOMP;
252 		}
253 	;
254 
255 spi
256 	:	DECSTRING { p_spi = $1; }
257 	|	HEXSTRING
258 		{
259 			char *ep;
260 			unsigned long v;
261 
262 			ep = NULL;
263 			v = strtoul($1.buf, &ep, 16);
264 			if (!ep || *ep) {
265 				yyerror("invalid SPI");
266 				return -1;
267 			}
268 			if (v & ~0xffffffff) {
269 				yyerror("SPI too big.");
270 				return -1;
271 			}
272 
273 			p_spi = v;
274 		}
275 	;
276 
277 algorithm_spec
278 	:	esp_spec
279 	|	ah_spec
280 	|	ipcomp_spec
281 	;
282 
283 esp_spec
284 	:	F_ENC enc_alg F_AUTH auth_alg
285 	|	F_ENC enc_alg
286 	;
287 
288 ah_spec
289 	:	F_AUTH auth_alg
290 	;
291 
292 ipcomp_spec
293 	:	F_COMP ALG_COMP
294 		{
295 			if ($2 < 0) {
296 				yyerror("unsupported algorithm");
297 				return -1;
298 			}
299 			p_alg_enc = $2;
300 		}
301 	|	F_COMP ALG_COMP F_RAWCPI
302 		{
303 			if ($2 < 0) {
304 				yyerror("unsupported algorithm");
305 				return -1;
306 			}
307 			p_alg_enc = $2;
308 			p_ext |= SADB_X_EXT_RAWCPI;
309 		}
310 	;
311 
312 enc_alg
313 	:	ALG_ENC_NOKEY {
314 			if ($1 < 0) {
315 				yyerror("unsupported algorithm");
316 				return -1;
317 			}
318 			p_alg_enc = $1;
319 
320 			p_key_enc_len = 0;
321 			p_key_enc = NULL;
322 		}
323 	|	ALG_ENC key_string {
324 			if ($1 < 0) {
325 				yyerror("unsupported algorithm");
326 				return -1;
327 			}
328 			p_alg_enc = $1;
329 
330 			p_key_enc_len = $2.len;
331 			p_key_enc = $2.buf;
332 			if (ipsec_check_keylen(SADB_EXT_SUPPORTED_ENCRYPT,
333 			    p_alg_enc, PFKEY_UNUNIT64(p_key_enc_len)) < 0) {
334 				yyerror(ipsec_strerror());
335 				return -1;
336 			}
337 		}
338 	|	ALG_ENC_OLD {
339 			if ($1 < 0) {
340 				yyerror("unsupported algorithm");
341 				return -1;
342 			}
343 			yyerror("WARNING: obsolete algorithm");
344 			p_alg_enc = $1;
345 
346 			p_key_enc_len = 0;
347 			p_key_enc = NULL;
348 		}
349 	|	ALG_ENC_DESDERIV key_string
350 		{
351 			if ($1 < 0) {
352 				yyerror("unsupported algorithm");
353 				return -1;
354 			}
355 			p_alg_enc = $1;
356 			if (p_ext & SADB_X_EXT_OLD) {
357 				yyerror("algorithm mismatched");
358 				return -1;
359 			}
360 			p_ext |= SADB_X_EXT_DERIV;
361 
362 			p_key_enc_len = $2.len;
363 			p_key_enc = $2.buf;
364 			if (ipsec_check_keylen(SADB_EXT_SUPPORTED_ENCRYPT,
365 			    p_alg_enc, PFKEY_UNUNIT64(p_key_enc_len)) < 0) {
366 				yyerror(ipsec_strerror());
367 				return -1;
368 			}
369 		}
370 	|	ALG_ENC_DES32IV key_string
371 		{
372 			if ($1 < 0) {
373 				yyerror("unsupported algorithm");
374 				return -1;
375 			}
376 			p_alg_enc = $1;
377 			if (!(p_ext & SADB_X_EXT_OLD)) {
378 				yyerror("algorithm mismatched");
379 				return -1;
380 			}
381 			p_ext |= SADB_X_EXT_IV4B;
382 
383 			p_key_enc_len = $2.len;
384 			p_key_enc = $2.buf;
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 	;
392 
393 auth_alg
394 	:	ALG_AUTH key_string {
395 			if ($1 < 0) {
396 				yyerror("unsupported algorithm");
397 				return -1;
398 			}
399 			p_alg_auth = $1;
400 
401 			p_key_auth_len = $2.len;
402 			p_key_auth = $2.buf;
403 			if (ipsec_check_keylen(SADB_EXT_SUPPORTED_AUTH,
404 			    p_alg_auth, PFKEY_UNUNIT64(p_key_auth_len)) < 0) {
405 				yyerror(ipsec_strerror());
406 				return -1;
407 			}
408 		}
409 	|	ALG_AUTH_NOKEY {
410 			if ($1 < 0) {
411 				yyerror("unsupported algorithm");
412 				return -1;
413 			}
414 			p_alg_auth = $1;
415 
416 			p_key_auth_len = 0;
417 			p_key_auth = NULL;
418 		}
419 	;
420 
421 key_string
422 	:	QUOTEDSTRING
423 		{
424 			$$ = $1;
425 		}
426 	|	HEXSTRING
427 		{
428 			caddr_t pp_key;
429 			caddr_t bp;
430 			caddr_t yp = $1.buf;
431 			int l;
432 
433 			l = strlen(yp) % 2 + strlen(yp) / 2;
434 			if ((pp_key = malloc(l)) == 0) {
435 				yyerror("not enough core");
436 				return -1;
437 			}
438 			memset(pp_key, 0, l);
439 
440 			bp = pp_key;
441 			if (strlen(yp) % 2) {
442 				*bp = ATOX(yp[0]);
443 				yp++, bp++;
444 			}
445 			while (*yp) {
446 				*bp = (ATOX(yp[0]) << 4) | ATOX(yp[1]);
447 				yp += 2, bp++;
448 			}
449 
450 			$$.len = l;
451 			$$.buf = pp_key;
452 		}
453 	;
454 
455 extension_spec
456 	:	/*NOTHING*/
457 	|	extension_spec extension
458 	;
459 
460 extension
461 	:	F_EXT EXTENSION { p_ext |= $2; }
462 	|	F_EXT NOCYCLICSEQ { p_ext &= ~SADB_X_EXT_CYCSEQ; }
463 	|	F_MODE MODE { p_mode = $2; }
464 	|	F_MODE ANY { p_mode = IPSEC_MODE_ANY; }
465 	|	F_REQID DECSTRING { p_reqid = $2; }
466 	|	F_REPLAY DECSTRING
467 		{
468 			if ((p_ext & SADB_X_EXT_OLD) != 0) {
469 				yyerror("replay prevention cannot be used with "
470 				    "ah/esp-old");
471 				return -1;
472 			}
473 			p_replay = $2;
474 		}
475 	|	F_LIFETIME_HARD DECSTRING { p_lt_hard = $2; }
476 	|	F_LIFETIME_SOFT DECSTRING { p_lt_soft = $2; }
477 	;
478 
479 	/* definition about command for SPD management */
480 	/* spdadd */
481 spdadd_command
482 	:	SPDADD ipaddropts STRING prefix portstr STRING prefix portstr upper_spec upper_misc_spec policy_spec EOT
483 		{
484 			int status;
485 			struct addrinfo *src, *dst;
486 
487 			/* fixed port fields if ulp is icmpv6 */
488 			if ($10.buf != NULL) {
489 				if ($9 != IPPROTO_ICMPV6)
490 					return -1;
491 				free($5.buf);
492 				free($8.buf);
493 				if (fix_portstr(&$10, &$5, &$8))
494 					return -1;
495 			}
496 
497 			src = parse_addr($3.buf, $5.buf);
498 			dst = parse_addr($6.buf, $8.buf);
499 			if (!src || !dst) {
500 				/* yyerror is already called */
501 				return -1;
502 			}
503 			if (src->ai_next || dst->ai_next) {
504 				yyerror("multiple address specified");
505 				freeaddrinfo(src);
506 				freeaddrinfo(dst);
507 				return -1;
508 			}
509 
510 			status = setkeymsg_spdaddr(SADB_X_SPDADD, $9, &$11,
511 			    src, $4, dst, $7);
512 			freeaddrinfo(src);
513 			freeaddrinfo(dst);
514 			if (status < 0)
515 				return -1;
516 		}
517 	|	SPDADD TAGGED QUOTEDSTRING policy_spec EOT
518 		{
519 			return -1;
520 		}
521 	;
522 
523 spddelete_command
524 	:	SPDDELETE ipaddropts STRING prefix portstr STRING prefix portstr upper_spec upper_misc_spec policy_spec EOT
525 		{
526 			int status;
527 			struct addrinfo *src, *dst;
528 
529 			/* fixed port fields if ulp is icmpv6 */
530 			if ($10.buf != NULL) {
531 				if ($9 != IPPROTO_ICMPV6)
532 					return -1;
533 				free($5.buf);
534 				free($8.buf);
535 				if (fix_portstr(&$10, &$5, &$8))
536 					return -1;
537 			}
538 
539 			src = parse_addr($3.buf, $5.buf);
540 			dst = parse_addr($6.buf, $8.buf);
541 			if (!src || !dst) {
542 				/* yyerror is already called */
543 				return -1;
544 			}
545 			if (src->ai_next || dst->ai_next) {
546 				yyerror("multiple address specified");
547 				freeaddrinfo(src);
548 				freeaddrinfo(dst);
549 				return -1;
550 			}
551 
552 			status = setkeymsg_spdaddr(SADB_X_SPDDELETE, $9, &$11,
553 			    src, $4, dst, $7);
554 			freeaddrinfo(src);
555 			freeaddrinfo(dst);
556 			if (status < 0)
557 				return -1;
558 		}
559 	;
560 
561 spddump_command:
562 		SPDDUMP EOT
563 		{
564 			struct sadb_msg msg;
565 			setkeymsg0(&msg, SADB_X_SPDDUMP, SADB_SATYPE_UNSPEC,
566 			    sizeof(msg));
567 			sendkeymsg((char *)&msg, sizeof(msg));
568 		}
569 	;
570 
571 spdflush_command:
572 		SPDFLUSH EOT
573 		{
574 			struct sadb_msg msg;
575 			setkeymsg0(&msg, SADB_X_SPDFLUSH, SADB_SATYPE_UNSPEC,
576 			    sizeof(msg));
577 			sendkeymsg((char *)&msg, sizeof(msg));
578 		}
579 	;
580 
581 ipaddropts
582 	:	/* nothing */
583 	|	ipaddropts ipaddropt
584 	;
585 
586 ipaddropt
587 	:	F_AIFLAGS
588 		{
589 			char *p;
590 
591 			for (p = $1.buf + 1; *p; p++)
592 				switch (*p) {
593 				case '4':
594 					p_aifamily = AF_INET;
595 					break;
596 #ifdef INET6
597 				case '6':
598 					p_aifamily = AF_INET6;
599 					break;
600 #endif
601 				case 'n':
602 					p_aiflags = AI_NUMERICHOST;
603 					break;
604 				default:
605 					yyerror("invalid flag");
606 					return -1;
607 				}
608 		}
609 	;
610 
611 ipaddr
612 	:	STRING
613 		{
614 			$$ = parse_addr($1.buf, NULL);
615 			if ($$ == NULL) {
616 				/* yyerror already called by parse_addr */
617 				return -1;
618 			}
619 		}
620 	;
621 
622 prefix
623 	:	/*NOTHING*/ { $$ = -1; }
624 	|	SLASH DECSTRING { $$ = $2; }
625 	;
626 
627 portstr
628 	:	/*NOTHING*/
629 		{
630 			$$.buf = strdup("0");
631 			if (!$$.buf) {
632 				yyerror("insufficient memory");
633 				return -1;
634 			}
635 			$$.len = strlen($$.buf);
636 		}
637 	|	BLCL ANY ELCL
638 		{
639 			$$.buf = strdup("0");
640 			if (!$$.buf) {
641 				yyerror("insufficient memory");
642 				return -1;
643 			}
644 			$$.len = strlen($$.buf);
645 		}
646 	|	BLCL DECSTRING ELCL
647 		{
648 			char buf[20];
649 			snprintf(buf, sizeof(buf), "%lu", $2);
650 			$$.buf = strdup(buf);
651 			if (!$$.buf) {
652 				yyerror("insufficient memory");
653 				return -1;
654 			}
655 			$$.len = strlen($$.buf);
656 		}
657 	|	BLCL STRING ELCL
658 		{
659 			$$ = $2;
660 		}
661 	;
662 
663 upper_spec
664 	:	DECSTRING { $$ = $1; }
665 	|	ANY { $$ = IPSEC_ULPROTO_ANY; }
666 	|	STRING
667 		{
668 			struct protoent *ent;
669 
670 			ent = getprotobyname($1.buf);
671 			if (ent)
672 				$$ = ent->p_proto;
673 			else {
674 				if (strcmp("icmp6", $1.buf) == 0) {
675 					$$ = IPPROTO_ICMPV6;
676 				} else if(strcmp("ip4", $1.buf) == 0) {
677 					$$ = IPPROTO_IPV4;
678 				} else {
679 					yyerror("invalid upper layer protocol");
680 					return -1;
681 				}
682 			}
683 			endprotoent();
684 		}
685 	;
686 
687 upper_misc_spec
688 	:	/*NOTHING*/
689 		{
690 			$$.buf = NULL;
691 			$$.len = 0;
692 		}
693 	|	STRING
694 		{
695 			$$.buf = strdup($1.buf);
696 			if (!$$.buf) {
697 				yyerror("insufficient memory");
698 				return -1;
699 			}
700 			$$.len = strlen($$.buf);
701 		}
702 	;
703 
704 policy_spec
705 	:	F_POLICY policy_requests
706 		{
707 			char *policy;
708 
709 			policy = ipsec_set_policy($2.buf, $2.len);
710 			if (policy == NULL) {
711 				yyerror(ipsec_strerror());
712 				return -1;
713 			}
714 
715 			$$.buf = policy;
716 			$$.len = ipsec_get_policylen(policy);
717 		}
718 	;
719 
720 policy_requests
721 	:	PL_REQUESTS { $$ = $1; }
722 	;
723 
724 %%
725 
726 int
727 setkeymsg0(msg, type, satype, l)
728 	struct sadb_msg *msg;
729 	unsigned int type;
730 	unsigned int satype;
731 	size_t l;
732 {
733 
734 	msg->sadb_msg_version = PF_KEY_V2;
735 	msg->sadb_msg_type = type;
736 	msg->sadb_msg_errno = 0;
737 	msg->sadb_msg_satype = satype;
738 	msg->sadb_msg_reserved = 0;
739 	msg->sadb_msg_seq = 0;
740 	msg->sadb_msg_pid = getpid();
741 	msg->sadb_msg_len = PFKEY_UNIT64(l);
742 	return 0;
743 }
744 
745 /* XXX NO BUFFER OVERRUN CHECK! BAD BAD! */
746 static int
747 setkeymsg_spdaddr(type, upper, policy, srcs, splen, dsts, dplen)
748 	unsigned int type;
749 	unsigned int upper;
750 	vchar_t *policy;
751 	struct addrinfo *srcs;
752 	int splen;
753 	struct addrinfo *dsts;
754 	int dplen;
755 {
756 	struct sadb_msg *msg;
757 	char buf[BUFSIZ];
758 	int l, l0;
759 	struct sadb_address m_addr;
760 	struct addrinfo *s, *d;
761 	int n;
762 	int plen;
763 	struct sockaddr *sa;
764 	int salen;
765 
766 	msg = (struct sadb_msg *)buf;
767 
768 	if (!srcs || !dsts)
769 		return -1;
770 
771 	/* fix up length afterwards */
772 	setkeymsg0(msg, type, SADB_SATYPE_UNSPEC, 0);
773 	l = sizeof(struct sadb_msg);
774 
775 	memcpy(buf + l, policy->buf, policy->len);
776 	l += policy->len;
777 
778 	l0 = l;
779 	n = 0;
780 
781 	/* do it for all src/dst pairs */
782 	for (s = srcs; s; s = s->ai_next) {
783 		for (d = dsts; d; d = d->ai_next) {
784 			/* rewind pointer */
785 			l = l0;
786 
787 			if (s->ai_addr->sa_family != d->ai_addr->sa_family)
788 				continue;
789 			switch (s->ai_addr->sa_family) {
790 			case AF_INET:
791 				plen = sizeof(struct in_addr) << 3;
792 				break;
793 #ifdef INET6
794 			case AF_INET6:
795 				plen = sizeof(struct in6_addr) << 3;
796 				break;
797 #endif
798 			default:
799 				continue;
800 			}
801 
802 			/* set src */
803 			sa = s->ai_addr;
804 			salen = s->ai_addr->sa_len;
805 			m_addr.sadb_address_len = PFKEY_UNIT64(sizeof(m_addr) +
806 			    PFKEY_ALIGN8(salen));
807 			m_addr.sadb_address_exttype = SADB_EXT_ADDRESS_SRC;
808 			m_addr.sadb_address_proto = upper;
809 			m_addr.sadb_address_prefixlen =
810 			    (splen >= 0 ? splen : plen);
811 			m_addr.sadb_address_reserved = 0;
812 
813 			setvarbuf(buf, &l, (struct sadb_ext *)&m_addr,
814 			    sizeof(m_addr), (caddr_t)sa, salen);
815 
816 			/* set dst */
817 			sa = d->ai_addr;
818 			salen = d->ai_addr->sa_len;
819 			m_addr.sadb_address_len = PFKEY_UNIT64(sizeof(m_addr) +
820 			    PFKEY_ALIGN8(salen));
821 			m_addr.sadb_address_exttype = SADB_EXT_ADDRESS_DST;
822 			m_addr.sadb_address_proto = upper;
823 			m_addr.sadb_address_prefixlen =
824 			    (dplen >= 0 ? dplen : plen);
825 			m_addr.sadb_address_reserved = 0;
826 
827 			setvarbuf(buf, &l, (struct sadb_ext *)&m_addr,
828 			    sizeof(m_addr), (caddr_t)sa, salen);
829 
830 			msg->sadb_msg_len = PFKEY_UNIT64(l);
831 
832 			sendkeymsg(buf, l);
833 
834 			n++;
835 		}
836 	}
837 
838 	if (n == 0)
839 		return -1;
840 	else
841 		return 0;
842 }
843 
844 /* XXX NO BUFFER OVERRUN CHECK! BAD BAD! */
845 static int
846 setkeymsg_addr(type, satype, srcs, dsts, no_spi)
847 	unsigned int type;
848 	unsigned int satype;
849 	struct addrinfo *srcs;
850 	struct addrinfo *dsts;
851 	int no_spi;
852 {
853 	struct sadb_msg *msg;
854 	char buf[BUFSIZ];
855 	int l, l0, len;
856 	struct sadb_sa m_sa;
857 	struct sadb_x_sa2 m_sa2;
858 	struct sadb_address m_addr;
859 	struct addrinfo *s, *d;
860 	int n;
861 	int plen;
862 	struct sockaddr *sa;
863 	int salen;
864 
865 	msg = (struct sadb_msg *)buf;
866 
867 	if (!srcs || !dsts)
868 		return -1;
869 
870 	/* fix up length afterwards */
871 	setkeymsg0(msg, type, satype, 0);
872 	l = sizeof(struct sadb_msg);
873 
874 	if (!no_spi) {
875 		len = sizeof(struct sadb_sa);
876 		m_sa.sadb_sa_len = PFKEY_UNIT64(len);
877 		m_sa.sadb_sa_exttype = SADB_EXT_SA;
878 		m_sa.sadb_sa_spi = htonl(p_spi);
879 		m_sa.sadb_sa_replay = p_replay;
880 		m_sa.sadb_sa_state = 0;
881 		m_sa.sadb_sa_auth = p_alg_auth;
882 		m_sa.sadb_sa_encrypt = p_alg_enc;
883 		m_sa.sadb_sa_flags = p_ext;
884 
885 		memcpy(buf + l, &m_sa, len);
886 		l += len;
887 
888 		len = sizeof(struct sadb_x_sa2);
889 		m_sa2.sadb_x_sa2_len = PFKEY_UNIT64(len);
890 		m_sa2.sadb_x_sa2_exttype = SADB_X_EXT_SA2;
891 		m_sa2.sadb_x_sa2_mode = p_mode;
892 		m_sa2.sadb_x_sa2_reqid = p_reqid;
893 
894 		memcpy(buf + l, &m_sa2, len);
895 		l += len;
896 	}
897 
898 	l0 = l;
899 	n = 0;
900 
901 	/* do it for all src/dst pairs */
902 	for (s = srcs; s; s = s->ai_next) {
903 		for (d = dsts; d; d = d->ai_next) {
904 			/* rewind pointer */
905 			l = l0;
906 
907 			if (s->ai_addr->sa_family != d->ai_addr->sa_family)
908 				continue;
909 			switch (s->ai_addr->sa_family) {
910 			case AF_INET:
911 				plen = sizeof(struct in_addr) << 3;
912 				break;
913 #ifdef INET6
914 			case AF_INET6:
915 				plen = sizeof(struct in6_addr) << 3;
916 				break;
917 #endif
918 			default:
919 				continue;
920 			}
921 
922 			/* set src */
923 			sa = s->ai_addr;
924 			salen = s->ai_addr->sa_len;
925 			m_addr.sadb_address_len = PFKEY_UNIT64(sizeof(m_addr) +
926 			    PFKEY_ALIGN8(salen));
927 			m_addr.sadb_address_exttype = SADB_EXT_ADDRESS_SRC;
928 			m_addr.sadb_address_proto = IPSEC_ULPROTO_ANY;
929 			m_addr.sadb_address_prefixlen = plen;
930 			m_addr.sadb_address_reserved = 0;
931 
932 			setvarbuf(buf, &l, (struct sadb_ext *)&m_addr,
933 			    sizeof(m_addr), (caddr_t)sa, salen);
934 
935 			/* set dst */
936 			sa = d->ai_addr;
937 			salen = d->ai_addr->sa_len;
938 			m_addr.sadb_address_len = PFKEY_UNIT64(sizeof(m_addr) +
939 			    PFKEY_ALIGN8(salen));
940 			m_addr.sadb_address_exttype = SADB_EXT_ADDRESS_DST;
941 			m_addr.sadb_address_proto = IPSEC_ULPROTO_ANY;
942 			m_addr.sadb_address_prefixlen = plen;
943 			m_addr.sadb_address_reserved = 0;
944 
945 			setvarbuf(buf, &l, (struct sadb_ext *)&m_addr,
946 			    sizeof(m_addr), (caddr_t)sa, salen);
947 
948 			msg->sadb_msg_len = PFKEY_UNIT64(l);
949 
950 			sendkeymsg(buf, l);
951 
952 			n++;
953 		}
954 	}
955 
956 	if (n == 0)
957 		return -1;
958 	else
959 		return 0;
960 }
961 
962 /* XXX NO BUFFER OVERRUN CHECK! BAD BAD! */
963 static int
964 setkeymsg_add(type, satype, srcs, dsts)
965 	unsigned int type;
966 	unsigned int satype;
967 	struct addrinfo *srcs;
968 	struct addrinfo *dsts;
969 {
970 	struct sadb_msg *msg;
971 	char buf[BUFSIZ];
972 	int l, l0, len;
973 	struct sadb_sa m_sa;
974 	struct sadb_x_sa2 m_sa2;
975 	struct sadb_address m_addr;
976 	struct addrinfo *s, *d;
977 	int n;
978 	int plen;
979 	struct sockaddr *sa;
980 	int salen;
981 
982 	msg = (struct sadb_msg *)buf;
983 
984 	if (!srcs || !dsts)
985 		return -1;
986 
987 	/* fix up length afterwards */
988 	setkeymsg0(msg, type, satype, 0);
989 	l = sizeof(struct sadb_msg);
990 
991 	/* set encryption algorithm, if present. */
992 	if (satype != SADB_X_SATYPE_IPCOMP && p_key_enc) {
993 		struct sadb_key m_key;
994 
995 		m_key.sadb_key_len =
996 			PFKEY_UNIT64(sizeof(m_key)
997 				   + PFKEY_ALIGN8(p_key_enc_len));
998 		m_key.sadb_key_exttype = SADB_EXT_KEY_ENCRYPT;
999 		m_key.sadb_key_bits = p_key_enc_len * 8;
1000 		m_key.sadb_key_reserved = 0;
1001 
1002 		setvarbuf(buf, &l,
1003 			(struct sadb_ext *)&m_key, sizeof(m_key),
1004 			(caddr_t)p_key_enc, p_key_enc_len);
1005 	}
1006 
1007 	/* set authentication algorithm, if present. */
1008 	if (p_key_auth) {
1009 		struct sadb_key m_key;
1010 
1011 		m_key.sadb_key_len =
1012 			PFKEY_UNIT64(sizeof(m_key)
1013 				   + PFKEY_ALIGN8(p_key_auth_len));
1014 		m_key.sadb_key_exttype = SADB_EXT_KEY_AUTH;
1015 		m_key.sadb_key_bits = p_key_auth_len * 8;
1016 		m_key.sadb_key_reserved = 0;
1017 
1018 		setvarbuf(buf, &l,
1019 			(struct sadb_ext *)&m_key, sizeof(m_key),
1020 			(caddr_t)p_key_auth, p_key_auth_len);
1021 	}
1022 
1023 	/* set lifetime for HARD */
1024 	if (p_lt_hard != 0) {
1025 		struct sadb_lifetime m_lt;
1026 		u_int slen = sizeof(struct sadb_lifetime);
1027 
1028 		m_lt.sadb_lifetime_len = PFKEY_UNIT64(slen);
1029 		m_lt.sadb_lifetime_exttype = SADB_EXT_LIFETIME_HARD;
1030 		m_lt.sadb_lifetime_allocations = 0;
1031 		m_lt.sadb_lifetime_bytes = 0;
1032 		m_lt.sadb_lifetime_addtime = p_lt_hard;
1033 		m_lt.sadb_lifetime_usetime = 0;
1034 
1035 		memcpy(buf + l, &m_lt, slen);
1036 		l += len;
1037 	}
1038 
1039 	/* set lifetime for SOFT */
1040 	if (p_lt_soft != 0) {
1041 		struct sadb_lifetime m_lt;
1042 		u_int slen = sizeof(struct sadb_lifetime);
1043 
1044 		m_lt.sadb_lifetime_len = PFKEY_UNIT64(slen);
1045 		m_lt.sadb_lifetime_exttype = SADB_EXT_LIFETIME_SOFT;
1046 		m_lt.sadb_lifetime_allocations = 0;
1047 		m_lt.sadb_lifetime_bytes = 0;
1048 		m_lt.sadb_lifetime_addtime = p_lt_soft;
1049 		m_lt.sadb_lifetime_usetime = 0;
1050 
1051 		memcpy(buf + l, &m_lt, slen);
1052 		l += len;
1053 	}
1054 
1055 	len = sizeof(struct sadb_sa);
1056 	m_sa.sadb_sa_len = PFKEY_UNIT64(len);
1057 	m_sa.sadb_sa_exttype = SADB_EXT_SA;
1058 	m_sa.sadb_sa_spi = htonl(p_spi);
1059 	m_sa.sadb_sa_replay = p_replay;
1060 	m_sa.sadb_sa_state = 0;
1061 	m_sa.sadb_sa_auth = p_alg_auth;
1062 	m_sa.sadb_sa_encrypt = p_alg_enc;
1063 	m_sa.sadb_sa_flags = p_ext;
1064 
1065 	memcpy(buf + l, &m_sa, len);
1066 	l += len;
1067 
1068 	len = sizeof(struct sadb_x_sa2);
1069 	m_sa2.sadb_x_sa2_len = PFKEY_UNIT64(len);
1070 	m_sa2.sadb_x_sa2_exttype = SADB_X_EXT_SA2;
1071 	m_sa2.sadb_x_sa2_mode = p_mode;
1072 	m_sa2.sadb_x_sa2_reqid = p_reqid;
1073 
1074 	memcpy(buf + l, &m_sa2, len);
1075 	l += len;
1076 
1077 	l0 = l;
1078 	n = 0;
1079 
1080 	/* do it for all src/dst pairs */
1081 	for (s = srcs; s; s = s->ai_next) {
1082 		for (d = dsts; d; d = d->ai_next) {
1083 			/* rewind pointer */
1084 			l = l0;
1085 
1086 			if (s->ai_addr->sa_family != d->ai_addr->sa_family)
1087 				continue;
1088 			switch (s->ai_addr->sa_family) {
1089 			case AF_INET:
1090 				plen = sizeof(struct in_addr) << 3;
1091 				break;
1092 #ifdef INET6
1093 			case AF_INET6:
1094 				plen = sizeof(struct in6_addr) << 3;
1095 				break;
1096 #endif
1097 			default:
1098 				continue;
1099 			}
1100 
1101 			/* set src */
1102 			sa = s->ai_addr;
1103 			salen = s->ai_addr->sa_len;
1104 			m_addr.sadb_address_len = PFKEY_UNIT64(sizeof(m_addr) +
1105 			    PFKEY_ALIGN8(salen));
1106 			m_addr.sadb_address_exttype = SADB_EXT_ADDRESS_SRC;
1107 			m_addr.sadb_address_proto = IPSEC_ULPROTO_ANY;
1108 			m_addr.sadb_address_prefixlen = plen;
1109 			m_addr.sadb_address_reserved = 0;
1110 
1111 			setvarbuf(buf, &l, (struct sadb_ext *)&m_addr,
1112 			    sizeof(m_addr), (caddr_t)sa, salen);
1113 
1114 			/* set dst */
1115 			sa = d->ai_addr;
1116 			salen = d->ai_addr->sa_len;
1117 			m_addr.sadb_address_len = PFKEY_UNIT64(sizeof(m_addr) +
1118 			    PFKEY_ALIGN8(salen));
1119 			m_addr.sadb_address_exttype = SADB_EXT_ADDRESS_DST;
1120 			m_addr.sadb_address_proto = IPSEC_ULPROTO_ANY;
1121 			m_addr.sadb_address_prefixlen = plen;
1122 			m_addr.sadb_address_reserved = 0;
1123 
1124 			setvarbuf(buf, &l, (struct sadb_ext *)&m_addr,
1125 			    sizeof(m_addr), (caddr_t)sa, salen);
1126 
1127 			msg->sadb_msg_len = PFKEY_UNIT64(l);
1128 
1129 			sendkeymsg(buf, l);
1130 
1131 			n++;
1132 		}
1133 	}
1134 
1135 	if (n == 0)
1136 		return -1;
1137 	else
1138 		return 0;
1139 }
1140 
1141 static struct addrinfo *
1142 parse_addr(host, port)
1143 	char *host;
1144 	char *port;
1145 {
1146 	struct addrinfo hints, *res = NULL;
1147 	int error;
1148 
1149 	memset(&hints, 0, sizeof(hints));
1150 	hints.ai_family = p_aifamily;
1151 	hints.ai_socktype = SOCK_DGRAM;		/*dummy*/
1152 	hints.ai_protocol = IPPROTO_UDP;	/*dummy*/
1153 	hints.ai_flags = p_aiflags;
1154 	error = getaddrinfo(host, port, &hints, &res);
1155 	if (error != 0) {
1156 		yyerror(gai_strerror(error));
1157 		return NULL;
1158 	}
1159 	return res;
1160 }
1161 
1162 static int
1163 fix_portstr(spec, sport, dport)
1164 	vchar_t *spec, *sport, *dport;
1165 {
1166 	char *p, *p2;
1167 	u_int l;
1168 
1169 	l = 0;
1170 	for (p = spec->buf; *p != ',' && *p != '\0' && l < spec->len; p++, l++)
1171 		;
1172 	if (*p == '\0') {
1173 		p2 = "0";
1174 	} else {
1175 		if (*p == ',') {
1176 			*p = '\0';
1177 			p2 = ++p;
1178 		}
1179 		for (p = p2; *p != '\0' && l < spec->len; p++, l++)
1180 			;
1181 		if (*p != '\0' || *p2 == '\0') {
1182 			yyerror("invalid an upper layer protocol spec");
1183 			return -1;
1184 		}
1185 	}
1186 
1187 	sport->buf = strdup(spec->buf);
1188 	if (!sport->buf) {
1189 		yyerror("insufficient memory");
1190 		return -1;
1191 	}
1192 	sport->len = strlen(sport->buf);
1193 	dport->buf = strdup(p2);
1194 	if (!dport->buf) {
1195 		yyerror("insufficient memory");
1196 		return -1;
1197 	}
1198 	dport->len = strlen(dport->buf);
1199 
1200 	return 0;
1201 }
1202 
1203 static int
1204 setvarbuf(buf, off, ebuf, elen, vbuf, vlen)
1205 	char *buf;
1206 	int *off;
1207 	struct sadb_ext *ebuf;
1208 	int elen;
1209 	caddr_t vbuf;
1210 	int vlen;
1211 {
1212 	memset(buf + *off, 0, PFKEY_UNUNIT64(ebuf->sadb_ext_len));
1213 	memcpy(buf + *off, (caddr_t)ebuf, elen);
1214 	memcpy(buf + *off + elen, vbuf, vlen);
1215 	(*off) += PFKEY_ALIGN8(elen + vlen);
1216 
1217 	return 0;
1218 }
1219 
1220 void
1221 parse_init()
1222 {
1223 	p_spi = 0;
1224 
1225 	p_ext = SADB_X_EXT_CYCSEQ;
1226 	p_alg_enc = SADB_EALG_NONE;
1227 	p_alg_auth = SADB_AALG_NONE;
1228 	p_mode = IPSEC_MODE_ANY;
1229 	p_reqid = 0;
1230 	p_replay = 0;
1231 	p_key_enc_len = p_key_auth_len = 0;
1232 	p_key_enc = p_key_auth = 0;
1233 	p_lt_hard = p_lt_soft = 0;
1234 
1235 	p_aiflags = 0;
1236 	p_aifamily = PF_UNSPEC;
1237 
1238 	return;
1239 }
1240 
1241 void
1242 free_buffer()
1243 {
1244 	/* we got tons of memory leaks in the parser anyways, leave them */
1245 
1246 	return;
1247 }
1248