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