xref: /freebsd/sbin/setkey/parse.y (revision d2387d42b8da231a5b95cbc313825fb2aadf26f6)
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 PR_TCP
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 PR_TCP
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 	|	PR_TCP
254 		{
255 			$$ = SADB_X_SATYPE_TCPSIGNATURE;
256 		}
257 	;
258 
259 spi
260 	:	DECSTRING { p_spi = $1; }
261 	|	HEXSTRING
262 		{
263 			char *ep;
264 			unsigned long v;
265 
266 			ep = NULL;
267 			v = strtoul($1.buf, &ep, 16);
268 			if (!ep || *ep) {
269 				yyerror("invalid SPI");
270 				return -1;
271 			}
272 			if (v & ~0xffffffff) {
273 				yyerror("SPI too big.");
274 				return -1;
275 			}
276 
277 			p_spi = v;
278 		}
279 	;
280 
281 algorithm_spec
282 	:	esp_spec
283 	|	ah_spec
284 	|	ipcomp_spec
285 	;
286 
287 esp_spec
288 	:	F_ENC enc_alg F_AUTH auth_alg
289 	|	F_ENC enc_alg
290 	;
291 
292 ah_spec
293 	:	F_AUTH auth_alg
294 	;
295 
296 ipcomp_spec
297 	:	F_COMP ALG_COMP
298 		{
299 			if ($2 < 0) {
300 				yyerror("unsupported algorithm");
301 				return -1;
302 			}
303 			p_alg_enc = $2;
304 		}
305 	|	F_COMP ALG_COMP F_RAWCPI
306 		{
307 			if ($2 < 0) {
308 				yyerror("unsupported algorithm");
309 				return -1;
310 			}
311 			p_alg_enc = $2;
312 			p_ext |= SADB_X_EXT_RAWCPI;
313 		}
314 	;
315 
316 enc_alg
317 	:	ALG_ENC_NOKEY {
318 			if ($1 < 0) {
319 				yyerror("unsupported algorithm");
320 				return -1;
321 			}
322 			p_alg_enc = $1;
323 
324 			p_key_enc_len = 0;
325 			p_key_enc = NULL;
326 		}
327 	|	ALG_ENC key_string {
328 			if ($1 < 0) {
329 				yyerror("unsupported algorithm");
330 				return -1;
331 			}
332 			p_alg_enc = $1;
333 
334 			p_key_enc_len = $2.len;
335 			p_key_enc = $2.buf;
336 			if (ipsec_check_keylen(SADB_EXT_SUPPORTED_ENCRYPT,
337 			    p_alg_enc, PFKEY_UNUNIT64(p_key_enc_len)) < 0) {
338 				yyerror(ipsec_strerror());
339 				return -1;
340 			}
341 		}
342 	|	ALG_ENC_OLD {
343 			if ($1 < 0) {
344 				yyerror("unsupported algorithm");
345 				return -1;
346 			}
347 			yyerror("WARNING: obsolete algorithm");
348 			p_alg_enc = $1;
349 
350 			p_key_enc_len = 0;
351 			p_key_enc = NULL;
352 		}
353 	|	ALG_ENC_DESDERIV key_string
354 		{
355 			if ($1 < 0) {
356 				yyerror("unsupported algorithm");
357 				return -1;
358 			}
359 			p_alg_enc = $1;
360 			if (p_ext & SADB_X_EXT_OLD) {
361 				yyerror("algorithm mismatched");
362 				return -1;
363 			}
364 			p_ext |= SADB_X_EXT_DERIV;
365 
366 			p_key_enc_len = $2.len;
367 			p_key_enc = $2.buf;
368 			if (ipsec_check_keylen(SADB_EXT_SUPPORTED_ENCRYPT,
369 			    p_alg_enc, PFKEY_UNUNIT64(p_key_enc_len)) < 0) {
370 				yyerror(ipsec_strerror());
371 				return -1;
372 			}
373 		}
374 	|	ALG_ENC_DES32IV key_string
375 		{
376 			if ($1 < 0) {
377 				yyerror("unsupported algorithm");
378 				return -1;
379 			}
380 			p_alg_enc = $1;
381 			if (!(p_ext & SADB_X_EXT_OLD)) {
382 				yyerror("algorithm mismatched");
383 				return -1;
384 			}
385 			p_ext |= SADB_X_EXT_IV4B;
386 
387 			p_key_enc_len = $2.len;
388 			p_key_enc = $2.buf;
389 			if (ipsec_check_keylen(SADB_EXT_SUPPORTED_ENCRYPT,
390 			    p_alg_enc, PFKEY_UNUNIT64(p_key_enc_len)) < 0) {
391 				yyerror(ipsec_strerror());
392 				return -1;
393 			}
394 		}
395 	;
396 
397 auth_alg
398 	:	ALG_AUTH key_string {
399 			if ($1 < 0) {
400 				yyerror("unsupported algorithm");
401 				return -1;
402 			}
403 			p_alg_auth = $1;
404 
405 			p_key_auth_len = $2.len;
406 			p_key_auth = $2.buf;
407 
408 			if (p_alg_auth == SADB_X_AALG_TCP_MD5) {
409 				if ((p_key_auth_len < 1) || (p_key_auth_len >
410 				    80))
411 					return -1;
412 			} else if (ipsec_check_keylen(SADB_EXT_SUPPORTED_AUTH,
413 			    p_alg_auth, PFKEY_UNUNIT64(p_key_auth_len)) < 0) {
414 				yyerror(ipsec_strerror());
415 				return -1;
416 			}
417 		}
418 	|	ALG_AUTH_NOKEY {
419 			if ($1 < 0) {
420 				yyerror("unsupported algorithm");
421 				return -1;
422 			}
423 			p_alg_auth = $1;
424 
425 			p_key_auth_len = 0;
426 			p_key_auth = NULL;
427 		}
428 	;
429 
430 key_string
431 	:	QUOTEDSTRING
432 		{
433 			$$ = $1;
434 		}
435 	|	HEXSTRING
436 		{
437 			caddr_t pp_key;
438 			caddr_t bp;
439 			caddr_t yp = $1.buf;
440 			int l;
441 
442 			l = strlen(yp) % 2 + strlen(yp) / 2;
443 			if ((pp_key = malloc(l)) == 0) {
444 				yyerror("not enough core");
445 				return -1;
446 			}
447 			memset(pp_key, 0, l);
448 
449 			bp = pp_key;
450 			if (strlen(yp) % 2) {
451 				*bp = ATOX(yp[0]);
452 				yp++, bp++;
453 			}
454 			while (*yp) {
455 				*bp = (ATOX(yp[0]) << 4) | ATOX(yp[1]);
456 				yp += 2, bp++;
457 			}
458 
459 			$$.len = l;
460 			$$.buf = pp_key;
461 		}
462 	;
463 
464 extension_spec
465 	:	/*NOTHING*/
466 	|	extension_spec extension
467 	;
468 
469 extension
470 	:	F_EXT EXTENSION { p_ext |= $2; }
471 	|	F_EXT NOCYCLICSEQ { p_ext &= ~SADB_X_EXT_CYCSEQ; }
472 	|	F_MODE MODE { p_mode = $2; }
473 	|	F_MODE ANY { p_mode = IPSEC_MODE_ANY; }
474 	|	F_REQID DECSTRING { p_reqid = $2; }
475 	|	F_REPLAY DECSTRING
476 		{
477 			if ((p_ext & SADB_X_EXT_OLD) != 0) {
478 				yyerror("replay prevention cannot be used with "
479 				    "ah/esp-old");
480 				return -1;
481 			}
482 			p_replay = $2;
483 		}
484 	|	F_LIFETIME_HARD DECSTRING { p_lt_hard = $2; }
485 	|	F_LIFETIME_SOFT DECSTRING { p_lt_soft = $2; }
486 	;
487 
488 	/* definition about command for SPD management */
489 	/* spdadd */
490 spdadd_command
491 	:	SPDADD ipaddropts STRING prefix portstr STRING prefix portstr upper_spec upper_misc_spec policy_spec EOT
492 		{
493 			int status;
494 			struct addrinfo *src, *dst;
495 
496 			/* fixed port fields if ulp is icmpv6 */
497 			if ($10.buf != NULL) {
498 				if ($9 != IPPROTO_ICMPV6)
499 					return -1;
500 				free($5.buf);
501 				free($8.buf);
502 				if (fix_portstr(&$10, &$5, &$8))
503 					return -1;
504 			}
505 
506 			src = parse_addr($3.buf, $5.buf);
507 			dst = parse_addr($6.buf, $8.buf);
508 			if (!src || !dst) {
509 				/* yyerror is already called */
510 				return -1;
511 			}
512 			if (src->ai_next || dst->ai_next) {
513 				yyerror("multiple address specified");
514 				freeaddrinfo(src);
515 				freeaddrinfo(dst);
516 				return -1;
517 			}
518 
519 			status = setkeymsg_spdaddr(SADB_X_SPDADD, $9, &$11,
520 			    src, $4, dst, $7);
521 			freeaddrinfo(src);
522 			freeaddrinfo(dst);
523 			if (status < 0)
524 				return -1;
525 		}
526 	|	SPDADD TAGGED QUOTEDSTRING policy_spec EOT
527 		{
528 			return -1;
529 		}
530 	;
531 
532 spddelete_command
533 	:	SPDDELETE ipaddropts STRING prefix portstr STRING prefix portstr upper_spec upper_misc_spec policy_spec EOT
534 		{
535 			int status;
536 			struct addrinfo *src, *dst;
537 
538 			/* fixed port fields if ulp is icmpv6 */
539 			if ($10.buf != NULL) {
540 				if ($9 != IPPROTO_ICMPV6)
541 					return -1;
542 				free($5.buf);
543 				free($8.buf);
544 				if (fix_portstr(&$10, &$5, &$8))
545 					return -1;
546 			}
547 
548 			src = parse_addr($3.buf, $5.buf);
549 			dst = parse_addr($6.buf, $8.buf);
550 			if (!src || !dst) {
551 				/* yyerror is already called */
552 				return -1;
553 			}
554 			if (src->ai_next || dst->ai_next) {
555 				yyerror("multiple address specified");
556 				freeaddrinfo(src);
557 				freeaddrinfo(dst);
558 				return -1;
559 			}
560 
561 			status = setkeymsg_spdaddr(SADB_X_SPDDELETE, $9, &$11,
562 			    src, $4, dst, $7);
563 			freeaddrinfo(src);
564 			freeaddrinfo(dst);
565 			if (status < 0)
566 				return -1;
567 		}
568 	;
569 
570 spddump_command:
571 		SPDDUMP EOT
572 		{
573 			struct sadb_msg msg;
574 			setkeymsg0(&msg, SADB_X_SPDDUMP, SADB_SATYPE_UNSPEC,
575 			    sizeof(msg));
576 			sendkeymsg((char *)&msg, sizeof(msg));
577 		}
578 	;
579 
580 spdflush_command:
581 		SPDFLUSH EOT
582 		{
583 			struct sadb_msg msg;
584 			setkeymsg0(&msg, SADB_X_SPDFLUSH, SADB_SATYPE_UNSPEC,
585 			    sizeof(msg));
586 			sendkeymsg((char *)&msg, sizeof(msg));
587 		}
588 	;
589 
590 ipaddropts
591 	:	/* nothing */
592 	|	ipaddropts ipaddropt
593 	;
594 
595 ipaddropt
596 	:	F_AIFLAGS
597 		{
598 			char *p;
599 
600 			for (p = $1.buf + 1; *p; p++)
601 				switch (*p) {
602 				case '4':
603 					p_aifamily = AF_INET;
604 					break;
605 #ifdef INET6
606 				case '6':
607 					p_aifamily = AF_INET6;
608 					break;
609 #endif
610 				case 'n':
611 					p_aiflags = AI_NUMERICHOST;
612 					break;
613 				default:
614 					yyerror("invalid flag");
615 					return -1;
616 				}
617 		}
618 	;
619 
620 ipaddr
621 	:	STRING
622 		{
623 			$$ = parse_addr($1.buf, NULL);
624 			if ($$ == NULL) {
625 				/* yyerror already called by parse_addr */
626 				return -1;
627 			}
628 		}
629 	;
630 
631 prefix
632 	:	/*NOTHING*/ { $$ = -1; }
633 	|	SLASH DECSTRING { $$ = $2; }
634 	;
635 
636 portstr
637 	:	/*NOTHING*/
638 		{
639 			$$.buf = strdup("0");
640 			if (!$$.buf) {
641 				yyerror("insufficient memory");
642 				return -1;
643 			}
644 			$$.len = strlen($$.buf);
645 		}
646 	|	BLCL ANY ELCL
647 		{
648 			$$.buf = strdup("0");
649 			if (!$$.buf) {
650 				yyerror("insufficient memory");
651 				return -1;
652 			}
653 			$$.len = strlen($$.buf);
654 		}
655 	|	BLCL DECSTRING ELCL
656 		{
657 			char buf[20];
658 			snprintf(buf, sizeof(buf), "%lu", $2);
659 			$$.buf = strdup(buf);
660 			if (!$$.buf) {
661 				yyerror("insufficient memory");
662 				return -1;
663 			}
664 			$$.len = strlen($$.buf);
665 		}
666 	|	BLCL STRING ELCL
667 		{
668 			$$ = $2;
669 		}
670 	;
671 
672 upper_spec
673 	:	DECSTRING { $$ = $1; }
674 	|	ANY { $$ = IPSEC_ULPROTO_ANY; }
675 	|	PR_TCP { $$ = IPPROTO_TCP; }
676 	|	STRING
677 		{
678 			struct protoent *ent;
679 
680 			ent = getprotobyname($1.buf);
681 			if (ent)
682 				$$ = ent->p_proto;
683 			else {
684 				if (strcmp("icmp6", $1.buf) == 0) {
685 					$$ = IPPROTO_ICMPV6;
686 				} else if(strcmp("ip4", $1.buf) == 0) {
687 					$$ = IPPROTO_IPV4;
688 				} else {
689 					yyerror("invalid upper layer protocol");
690 					return -1;
691 				}
692 			}
693 			endprotoent();
694 		}
695 	;
696 
697 upper_misc_spec
698 	:	/*NOTHING*/
699 		{
700 			$$.buf = NULL;
701 			$$.len = 0;
702 		}
703 	|	STRING
704 		{
705 			$$.buf = strdup($1.buf);
706 			if (!$$.buf) {
707 				yyerror("insufficient memory");
708 				return -1;
709 			}
710 			$$.len = strlen($$.buf);
711 		}
712 	;
713 
714 policy_spec
715 	:	F_POLICY policy_requests
716 		{
717 			char *policy;
718 
719 			policy = ipsec_set_policy($2.buf, $2.len);
720 			if (policy == NULL) {
721 				yyerror(ipsec_strerror());
722 				return -1;
723 			}
724 
725 			$$.buf = policy;
726 			$$.len = ipsec_get_policylen(policy);
727 		}
728 	;
729 
730 policy_requests
731 	:	PL_REQUESTS { $$ = $1; }
732 	;
733 
734 %%
735 
736 int
737 setkeymsg0(msg, type, satype, l)
738 	struct sadb_msg *msg;
739 	unsigned int type;
740 	unsigned int satype;
741 	size_t l;
742 {
743 
744 	msg->sadb_msg_version = PF_KEY_V2;
745 	msg->sadb_msg_type = type;
746 	msg->sadb_msg_errno = 0;
747 	msg->sadb_msg_satype = satype;
748 	msg->sadb_msg_reserved = 0;
749 	msg->sadb_msg_seq = 0;
750 	msg->sadb_msg_pid = getpid();
751 	msg->sadb_msg_len = PFKEY_UNIT64(l);
752 	return 0;
753 }
754 
755 /* XXX NO BUFFER OVERRUN CHECK! BAD BAD! */
756 static int
757 setkeymsg_spdaddr(type, upper, policy, srcs, splen, dsts, dplen)
758 	unsigned int type;
759 	unsigned int upper;
760 	vchar_t *policy;
761 	struct addrinfo *srcs;
762 	int splen;
763 	struct addrinfo *dsts;
764 	int dplen;
765 {
766 	struct sadb_msg *msg;
767 	char buf[BUFSIZ];
768 	int l, l0;
769 	struct sadb_address m_addr;
770 	struct addrinfo *s, *d;
771 	int n;
772 	int plen;
773 	struct sockaddr *sa;
774 	int salen;
775 
776 	msg = (struct sadb_msg *)buf;
777 
778 	if (!srcs || !dsts)
779 		return -1;
780 
781 	/* fix up length afterwards */
782 	setkeymsg0(msg, type, SADB_SATYPE_UNSPEC, 0);
783 	l = sizeof(struct sadb_msg);
784 
785 	memcpy(buf + l, policy->buf, policy->len);
786 	l += policy->len;
787 
788 	l0 = l;
789 	n = 0;
790 
791 	/* do it for all src/dst pairs */
792 	for (s = srcs; s; s = s->ai_next) {
793 		for (d = dsts; d; d = d->ai_next) {
794 			/* rewind pointer */
795 			l = l0;
796 
797 			if (s->ai_addr->sa_family != d->ai_addr->sa_family)
798 				continue;
799 			switch (s->ai_addr->sa_family) {
800 			case AF_INET:
801 				plen = sizeof(struct in_addr) << 3;
802 				break;
803 #ifdef INET6
804 			case AF_INET6:
805 				plen = sizeof(struct in6_addr) << 3;
806 				break;
807 #endif
808 			default:
809 				continue;
810 			}
811 
812 			/* set src */
813 			sa = s->ai_addr;
814 			salen = s->ai_addr->sa_len;
815 			m_addr.sadb_address_len = PFKEY_UNIT64(sizeof(m_addr) +
816 			    PFKEY_ALIGN8(salen));
817 			m_addr.sadb_address_exttype = SADB_EXT_ADDRESS_SRC;
818 			m_addr.sadb_address_proto = upper;
819 			m_addr.sadb_address_prefixlen =
820 			    (splen >= 0 ? splen : plen);
821 			m_addr.sadb_address_reserved = 0;
822 
823 			setvarbuf(buf, &l, (struct sadb_ext *)&m_addr,
824 			    sizeof(m_addr), (caddr_t)sa, salen);
825 
826 			/* set dst */
827 			sa = d->ai_addr;
828 			salen = d->ai_addr->sa_len;
829 			m_addr.sadb_address_len = PFKEY_UNIT64(sizeof(m_addr) +
830 			    PFKEY_ALIGN8(salen));
831 			m_addr.sadb_address_exttype = SADB_EXT_ADDRESS_DST;
832 			m_addr.sadb_address_proto = upper;
833 			m_addr.sadb_address_prefixlen =
834 			    (dplen >= 0 ? dplen : plen);
835 			m_addr.sadb_address_reserved = 0;
836 
837 			setvarbuf(buf, &l, (struct sadb_ext *)&m_addr,
838 			    sizeof(m_addr), (caddr_t)sa, salen);
839 
840 			msg->sadb_msg_len = PFKEY_UNIT64(l);
841 
842 			sendkeymsg(buf, l);
843 
844 			n++;
845 		}
846 	}
847 
848 	if (n == 0)
849 		return -1;
850 	else
851 		return 0;
852 }
853 
854 /* XXX NO BUFFER OVERRUN CHECK! BAD BAD! */
855 static int
856 setkeymsg_addr(type, satype, srcs, dsts, no_spi)
857 	unsigned int type;
858 	unsigned int satype;
859 	struct addrinfo *srcs;
860 	struct addrinfo *dsts;
861 	int no_spi;
862 {
863 	struct sadb_msg *msg;
864 	char buf[BUFSIZ];
865 	int l, l0, len;
866 	struct sadb_sa m_sa;
867 	struct sadb_x_sa2 m_sa2;
868 	struct sadb_address m_addr;
869 	struct addrinfo *s, *d;
870 	int n;
871 	int plen;
872 	struct sockaddr *sa;
873 	int salen;
874 
875 	msg = (struct sadb_msg *)buf;
876 
877 	if (!srcs || !dsts)
878 		return -1;
879 
880 	/* fix up length afterwards */
881 	setkeymsg0(msg, type, satype, 0);
882 	l = sizeof(struct sadb_msg);
883 
884 	if (!no_spi) {
885 		len = sizeof(struct sadb_sa);
886 		m_sa.sadb_sa_len = PFKEY_UNIT64(len);
887 		m_sa.sadb_sa_exttype = SADB_EXT_SA;
888 		m_sa.sadb_sa_spi = htonl(p_spi);
889 		m_sa.sadb_sa_replay = p_replay;
890 		m_sa.sadb_sa_state = 0;
891 		m_sa.sadb_sa_auth = p_alg_auth;
892 		m_sa.sadb_sa_encrypt = p_alg_enc;
893 		m_sa.sadb_sa_flags = p_ext;
894 
895 		memcpy(buf + l, &m_sa, len);
896 		l += len;
897 
898 		len = sizeof(struct sadb_x_sa2);
899 		m_sa2.sadb_x_sa2_len = PFKEY_UNIT64(len);
900 		m_sa2.sadb_x_sa2_exttype = SADB_X_EXT_SA2;
901 		m_sa2.sadb_x_sa2_mode = p_mode;
902 		m_sa2.sadb_x_sa2_reqid = p_reqid;
903 
904 		memcpy(buf + l, &m_sa2, len);
905 		l += len;
906 	}
907 
908 	l0 = l;
909 	n = 0;
910 
911 	/* do it for all src/dst pairs */
912 	for (s = srcs; s; s = s->ai_next) {
913 		for (d = dsts; d; d = d->ai_next) {
914 			/* rewind pointer */
915 			l = l0;
916 
917 			if (s->ai_addr->sa_family != d->ai_addr->sa_family)
918 				continue;
919 			switch (s->ai_addr->sa_family) {
920 			case AF_INET:
921 				plen = sizeof(struct in_addr) << 3;
922 				break;
923 #ifdef INET6
924 			case AF_INET6:
925 				plen = sizeof(struct in6_addr) << 3;
926 				break;
927 #endif
928 			default:
929 				continue;
930 			}
931 
932 			/* set src */
933 			sa = s->ai_addr;
934 			salen = s->ai_addr->sa_len;
935 			m_addr.sadb_address_len = PFKEY_UNIT64(sizeof(m_addr) +
936 			    PFKEY_ALIGN8(salen));
937 			m_addr.sadb_address_exttype = SADB_EXT_ADDRESS_SRC;
938 			m_addr.sadb_address_proto = IPSEC_ULPROTO_ANY;
939 			m_addr.sadb_address_prefixlen = plen;
940 			m_addr.sadb_address_reserved = 0;
941 
942 			setvarbuf(buf, &l, (struct sadb_ext *)&m_addr,
943 			    sizeof(m_addr), (caddr_t)sa, salen);
944 
945 			/* set dst */
946 			sa = d->ai_addr;
947 			salen = d->ai_addr->sa_len;
948 			m_addr.sadb_address_len = PFKEY_UNIT64(sizeof(m_addr) +
949 			    PFKEY_ALIGN8(salen));
950 			m_addr.sadb_address_exttype = SADB_EXT_ADDRESS_DST;
951 			m_addr.sadb_address_proto = IPSEC_ULPROTO_ANY;
952 			m_addr.sadb_address_prefixlen = plen;
953 			m_addr.sadb_address_reserved = 0;
954 
955 			setvarbuf(buf, &l, (struct sadb_ext *)&m_addr,
956 			    sizeof(m_addr), (caddr_t)sa, salen);
957 
958 			msg->sadb_msg_len = PFKEY_UNIT64(l);
959 
960 			sendkeymsg(buf, l);
961 
962 			n++;
963 		}
964 	}
965 
966 	if (n == 0)
967 		return -1;
968 	else
969 		return 0;
970 }
971 
972 /* XXX NO BUFFER OVERRUN CHECK! BAD BAD! */
973 static int
974 setkeymsg_add(type, satype, srcs, dsts)
975 	unsigned int type;
976 	unsigned int satype;
977 	struct addrinfo *srcs;
978 	struct addrinfo *dsts;
979 {
980 	struct sadb_msg *msg;
981 	char buf[BUFSIZ];
982 	int l, l0, len;
983 	struct sadb_sa m_sa;
984 	struct sadb_x_sa2 m_sa2;
985 	struct sadb_address m_addr;
986 	struct addrinfo *s, *d;
987 	int n;
988 	int plen;
989 	struct sockaddr *sa;
990 	int salen;
991 
992 	msg = (struct sadb_msg *)buf;
993 
994 	if (!srcs || !dsts)
995 		return -1;
996 
997 	/* fix up length afterwards */
998 	setkeymsg0(msg, type, satype, 0);
999 	l = sizeof(struct sadb_msg);
1000 
1001 	/* set encryption algorithm, if present. */
1002 	if (satype != SADB_X_SATYPE_IPCOMP && p_key_enc) {
1003 		struct sadb_key m_key;
1004 
1005 		m_key.sadb_key_len =
1006 			PFKEY_UNIT64(sizeof(m_key)
1007 				   + PFKEY_ALIGN8(p_key_enc_len));
1008 		m_key.sadb_key_exttype = SADB_EXT_KEY_ENCRYPT;
1009 		m_key.sadb_key_bits = p_key_enc_len * 8;
1010 		m_key.sadb_key_reserved = 0;
1011 
1012 		setvarbuf(buf, &l,
1013 			(struct sadb_ext *)&m_key, sizeof(m_key),
1014 			(caddr_t)p_key_enc, p_key_enc_len);
1015 	}
1016 
1017 	/* set authentication algorithm, if present. */
1018 	if (p_key_auth) {
1019 		struct sadb_key m_key;
1020 
1021 		m_key.sadb_key_len =
1022 			PFKEY_UNIT64(sizeof(m_key)
1023 				   + PFKEY_ALIGN8(p_key_auth_len));
1024 		m_key.sadb_key_exttype = SADB_EXT_KEY_AUTH;
1025 		m_key.sadb_key_bits = p_key_auth_len * 8;
1026 		m_key.sadb_key_reserved = 0;
1027 
1028 		setvarbuf(buf, &l,
1029 			(struct sadb_ext *)&m_key, sizeof(m_key),
1030 			(caddr_t)p_key_auth, p_key_auth_len);
1031 	}
1032 
1033 	/* set lifetime for HARD */
1034 	if (p_lt_hard != 0) {
1035 		struct sadb_lifetime m_lt;
1036 		u_int slen = sizeof(struct sadb_lifetime);
1037 
1038 		m_lt.sadb_lifetime_len = PFKEY_UNIT64(slen);
1039 		m_lt.sadb_lifetime_exttype = SADB_EXT_LIFETIME_HARD;
1040 		m_lt.sadb_lifetime_allocations = 0;
1041 		m_lt.sadb_lifetime_bytes = 0;
1042 		m_lt.sadb_lifetime_addtime = p_lt_hard;
1043 		m_lt.sadb_lifetime_usetime = 0;
1044 
1045 		memcpy(buf + l, &m_lt, slen);
1046 		l += len;
1047 	}
1048 
1049 	/* set lifetime for SOFT */
1050 	if (p_lt_soft != 0) {
1051 		struct sadb_lifetime m_lt;
1052 		u_int slen = sizeof(struct sadb_lifetime);
1053 
1054 		m_lt.sadb_lifetime_len = PFKEY_UNIT64(slen);
1055 		m_lt.sadb_lifetime_exttype = SADB_EXT_LIFETIME_SOFT;
1056 		m_lt.sadb_lifetime_allocations = 0;
1057 		m_lt.sadb_lifetime_bytes = 0;
1058 		m_lt.sadb_lifetime_addtime = p_lt_soft;
1059 		m_lt.sadb_lifetime_usetime = 0;
1060 
1061 		memcpy(buf + l, &m_lt, slen);
1062 		l += len;
1063 	}
1064 
1065 	len = sizeof(struct sadb_sa);
1066 	m_sa.sadb_sa_len = PFKEY_UNIT64(len);
1067 	m_sa.sadb_sa_exttype = SADB_EXT_SA;
1068 	m_sa.sadb_sa_spi = htonl(p_spi);
1069 	m_sa.sadb_sa_replay = p_replay;
1070 	m_sa.sadb_sa_state = 0;
1071 	m_sa.sadb_sa_auth = p_alg_auth;
1072 	m_sa.sadb_sa_encrypt = p_alg_enc;
1073 	m_sa.sadb_sa_flags = p_ext;
1074 
1075 	memcpy(buf + l, &m_sa, len);
1076 	l += len;
1077 
1078 	len = sizeof(struct sadb_x_sa2);
1079 	m_sa2.sadb_x_sa2_len = PFKEY_UNIT64(len);
1080 	m_sa2.sadb_x_sa2_exttype = SADB_X_EXT_SA2;
1081 	m_sa2.sadb_x_sa2_mode = p_mode;
1082 	m_sa2.sadb_x_sa2_reqid = p_reqid;
1083 
1084 	memcpy(buf + l, &m_sa2, len);
1085 	l += len;
1086 
1087 	l0 = l;
1088 	n = 0;
1089 
1090 	/* do it for all src/dst pairs */
1091 	for (s = srcs; s; s = s->ai_next) {
1092 		for (d = dsts; d; d = d->ai_next) {
1093 			/* rewind pointer */
1094 			l = l0;
1095 
1096 			if (s->ai_addr->sa_family != d->ai_addr->sa_family)
1097 				continue;
1098 			switch (s->ai_addr->sa_family) {
1099 			case AF_INET:
1100 				plen = sizeof(struct in_addr) << 3;
1101 				break;
1102 #ifdef INET6
1103 			case AF_INET6:
1104 				plen = sizeof(struct in6_addr) << 3;
1105 				break;
1106 #endif
1107 			default:
1108 				continue;
1109 			}
1110 
1111 			/* set src */
1112 			sa = s->ai_addr;
1113 			salen = s->ai_addr->sa_len;
1114 			m_addr.sadb_address_len = PFKEY_UNIT64(sizeof(m_addr) +
1115 			    PFKEY_ALIGN8(salen));
1116 			m_addr.sadb_address_exttype = SADB_EXT_ADDRESS_SRC;
1117 			m_addr.sadb_address_proto = IPSEC_ULPROTO_ANY;
1118 			m_addr.sadb_address_prefixlen = plen;
1119 			m_addr.sadb_address_reserved = 0;
1120 
1121 			setvarbuf(buf, &l, (struct sadb_ext *)&m_addr,
1122 			    sizeof(m_addr), (caddr_t)sa, salen);
1123 
1124 			/* set dst */
1125 			sa = d->ai_addr;
1126 			salen = d->ai_addr->sa_len;
1127 			m_addr.sadb_address_len = PFKEY_UNIT64(sizeof(m_addr) +
1128 			    PFKEY_ALIGN8(salen));
1129 			m_addr.sadb_address_exttype = SADB_EXT_ADDRESS_DST;
1130 			m_addr.sadb_address_proto = IPSEC_ULPROTO_ANY;
1131 			m_addr.sadb_address_prefixlen = plen;
1132 			m_addr.sadb_address_reserved = 0;
1133 
1134 			setvarbuf(buf, &l, (struct sadb_ext *)&m_addr,
1135 			    sizeof(m_addr), (caddr_t)sa, salen);
1136 
1137 			msg->sadb_msg_len = PFKEY_UNIT64(l);
1138 
1139 			sendkeymsg(buf, l);
1140 
1141 			n++;
1142 		}
1143 	}
1144 
1145 	if (n == 0)
1146 		return -1;
1147 	else
1148 		return 0;
1149 }
1150 
1151 static struct addrinfo *
1152 parse_addr(host, port)
1153 	char *host;
1154 	char *port;
1155 {
1156 	struct addrinfo hints, *res = NULL;
1157 	int error;
1158 
1159 	memset(&hints, 0, sizeof(hints));
1160 	hints.ai_family = p_aifamily;
1161 	hints.ai_socktype = SOCK_DGRAM;		/*dummy*/
1162 	hints.ai_protocol = IPPROTO_UDP;	/*dummy*/
1163 	hints.ai_flags = p_aiflags;
1164 	error = getaddrinfo(host, port, &hints, &res);
1165 	if (error != 0) {
1166 		yyerror(gai_strerror(error));
1167 		return NULL;
1168 	}
1169 	return res;
1170 }
1171 
1172 static int
1173 fix_portstr(spec, sport, dport)
1174 	vchar_t *spec, *sport, *dport;
1175 {
1176 	char *p, *p2;
1177 	u_int l;
1178 
1179 	l = 0;
1180 	for (p = spec->buf; *p != ',' && *p != '\0' && l < spec->len; p++, l++)
1181 		;
1182 	if (*p == '\0') {
1183 		p2 = "0";
1184 	} else {
1185 		if (*p == ',') {
1186 			*p = '\0';
1187 			p2 = ++p;
1188 		}
1189 		for (p = p2; *p != '\0' && l < spec->len; p++, l++)
1190 			;
1191 		if (*p != '\0' || *p2 == '\0') {
1192 			yyerror("invalid an upper layer protocol spec");
1193 			return -1;
1194 		}
1195 	}
1196 
1197 	sport->buf = strdup(spec->buf);
1198 	if (!sport->buf) {
1199 		yyerror("insufficient memory");
1200 		return -1;
1201 	}
1202 	sport->len = strlen(sport->buf);
1203 	dport->buf = strdup(p2);
1204 	if (!dport->buf) {
1205 		yyerror("insufficient memory");
1206 		return -1;
1207 	}
1208 	dport->len = strlen(dport->buf);
1209 
1210 	return 0;
1211 }
1212 
1213 static int
1214 setvarbuf(buf, off, ebuf, elen, vbuf, vlen)
1215 	char *buf;
1216 	int *off;
1217 	struct sadb_ext *ebuf;
1218 	int elen;
1219 	caddr_t vbuf;
1220 	int vlen;
1221 {
1222 	memset(buf + *off, 0, PFKEY_UNUNIT64(ebuf->sadb_ext_len));
1223 	memcpy(buf + *off, (caddr_t)ebuf, elen);
1224 	memcpy(buf + *off + elen, vbuf, vlen);
1225 	(*off) += PFKEY_ALIGN8(elen + vlen);
1226 
1227 	return 0;
1228 }
1229 
1230 void
1231 parse_init()
1232 {
1233 	p_spi = 0;
1234 
1235 	p_ext = SADB_X_EXT_CYCSEQ;
1236 	p_alg_enc = SADB_EALG_NONE;
1237 	p_alg_auth = SADB_AALG_NONE;
1238 	p_mode = IPSEC_MODE_ANY;
1239 	p_reqid = 0;
1240 	p_replay = 0;
1241 	p_key_enc_len = p_key_auth_len = 0;
1242 	p_key_enc = p_key_auth = 0;
1243 	p_lt_hard = p_lt_soft = 0;
1244 
1245 	p_aiflags = 0;
1246 	p_aifamily = PF_UNSPEC;
1247 
1248 	return;
1249 }
1250 
1251 void
1252 free_buffer()
1253 {
1254 	/* we got tons of memory leaks in the parser anyways, leave them */
1255 
1256 	return;
1257 }
1258