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