xref: /freebsd/sbin/setkey/parse.y (revision 0f8f86b71f022b803e99151c19db81b280f245dc)
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 	|	STRING
676 		{
677 			struct protoent *ent;
678 
679 			ent = getprotobyname($1.buf);
680 			if (ent)
681 				$$ = ent->p_proto;
682 			else {
683 				if (strcmp("icmp6", $1.buf) == 0) {
684 					$$ = IPPROTO_ICMPV6;
685 				} else if(strcmp("ip4", $1.buf) == 0) {
686 					$$ = IPPROTO_IPV4;
687 				} else {
688 					yyerror("invalid upper layer protocol");
689 					return -1;
690 				}
691 			}
692 			endprotoent();
693 		}
694 	;
695 
696 upper_misc_spec
697 	:	/*NOTHING*/
698 		{
699 			$$.buf = NULL;
700 			$$.len = 0;
701 		}
702 	|	STRING
703 		{
704 			$$.buf = strdup($1.buf);
705 			if (!$$.buf) {
706 				yyerror("insufficient memory");
707 				return -1;
708 			}
709 			$$.len = strlen($$.buf);
710 		}
711 	;
712 
713 policy_spec
714 	:	F_POLICY policy_requests
715 		{
716 			char *policy;
717 
718 			policy = ipsec_set_policy($2.buf, $2.len);
719 			if (policy == NULL) {
720 				yyerror(ipsec_strerror());
721 				return -1;
722 			}
723 
724 			$$.buf = policy;
725 			$$.len = ipsec_get_policylen(policy);
726 		}
727 	;
728 
729 policy_requests
730 	:	PL_REQUESTS { $$ = $1; }
731 	;
732 
733 %%
734 
735 int
736 setkeymsg0(msg, type, satype, l)
737 	struct sadb_msg *msg;
738 	unsigned int type;
739 	unsigned int satype;
740 	size_t l;
741 {
742 
743 	msg->sadb_msg_version = PF_KEY_V2;
744 	msg->sadb_msg_type = type;
745 	msg->sadb_msg_errno = 0;
746 	msg->sadb_msg_satype = satype;
747 	msg->sadb_msg_reserved = 0;
748 	msg->sadb_msg_seq = 0;
749 	msg->sadb_msg_pid = getpid();
750 	msg->sadb_msg_len = PFKEY_UNIT64(l);
751 	return 0;
752 }
753 
754 /* XXX NO BUFFER OVERRUN CHECK! BAD BAD! */
755 static int
756 setkeymsg_spdaddr(type, upper, policy, srcs, splen, dsts, dplen)
757 	unsigned int type;
758 	unsigned int upper;
759 	vchar_t *policy;
760 	struct addrinfo *srcs;
761 	int splen;
762 	struct addrinfo *dsts;
763 	int dplen;
764 {
765 	struct sadb_msg *msg;
766 	char buf[BUFSIZ];
767 	int l, l0;
768 	struct sadb_address m_addr;
769 	struct addrinfo *s, *d;
770 	int n;
771 	int plen;
772 	struct sockaddr *sa;
773 	int salen;
774 
775 	msg = (struct sadb_msg *)buf;
776 
777 	if (!srcs || !dsts)
778 		return -1;
779 
780 	/* fix up length afterwards */
781 	setkeymsg0(msg, type, SADB_SATYPE_UNSPEC, 0);
782 	l = sizeof(struct sadb_msg);
783 
784 	memcpy(buf + l, policy->buf, policy->len);
785 	l += policy->len;
786 
787 	l0 = l;
788 	n = 0;
789 
790 	/* do it for all src/dst pairs */
791 	for (s = srcs; s; s = s->ai_next) {
792 		for (d = dsts; d; d = d->ai_next) {
793 			/* rewind pointer */
794 			l = l0;
795 
796 			if (s->ai_addr->sa_family != d->ai_addr->sa_family)
797 				continue;
798 			switch (s->ai_addr->sa_family) {
799 			case AF_INET:
800 				plen = sizeof(struct in_addr) << 3;
801 				break;
802 #ifdef INET6
803 			case AF_INET6:
804 				plen = sizeof(struct in6_addr) << 3;
805 				break;
806 #endif
807 			default:
808 				continue;
809 			}
810 
811 			/* set src */
812 			sa = s->ai_addr;
813 			salen = s->ai_addr->sa_len;
814 			m_addr.sadb_address_len = PFKEY_UNIT64(sizeof(m_addr) +
815 			    PFKEY_ALIGN8(salen));
816 			m_addr.sadb_address_exttype = SADB_EXT_ADDRESS_SRC;
817 			m_addr.sadb_address_proto = upper;
818 			m_addr.sadb_address_prefixlen =
819 			    (splen >= 0 ? splen : plen);
820 			m_addr.sadb_address_reserved = 0;
821 
822 			setvarbuf(buf, &l, (struct sadb_ext *)&m_addr,
823 			    sizeof(m_addr), (caddr_t)sa, salen);
824 
825 			/* set dst */
826 			sa = d->ai_addr;
827 			salen = d->ai_addr->sa_len;
828 			m_addr.sadb_address_len = PFKEY_UNIT64(sizeof(m_addr) +
829 			    PFKEY_ALIGN8(salen));
830 			m_addr.sadb_address_exttype = SADB_EXT_ADDRESS_DST;
831 			m_addr.sadb_address_proto = upper;
832 			m_addr.sadb_address_prefixlen =
833 			    (dplen >= 0 ? dplen : plen);
834 			m_addr.sadb_address_reserved = 0;
835 
836 			setvarbuf(buf, &l, (struct sadb_ext *)&m_addr,
837 			    sizeof(m_addr), (caddr_t)sa, salen);
838 
839 			msg->sadb_msg_len = PFKEY_UNIT64(l);
840 
841 			sendkeymsg(buf, l);
842 
843 			n++;
844 		}
845 	}
846 
847 	if (n == 0)
848 		return -1;
849 	else
850 		return 0;
851 }
852 
853 /* XXX NO BUFFER OVERRUN CHECK! BAD BAD! */
854 static int
855 setkeymsg_addr(type, satype, srcs, dsts, no_spi)
856 	unsigned int type;
857 	unsigned int satype;
858 	struct addrinfo *srcs;
859 	struct addrinfo *dsts;
860 	int no_spi;
861 {
862 	struct sadb_msg *msg;
863 	char buf[BUFSIZ];
864 	int l, l0, len;
865 	struct sadb_sa m_sa;
866 	struct sadb_x_sa2 m_sa2;
867 	struct sadb_address m_addr;
868 	struct addrinfo *s, *d;
869 	int n;
870 	int plen;
871 	struct sockaddr *sa;
872 	int salen;
873 
874 	msg = (struct sadb_msg *)buf;
875 
876 	if (!srcs || !dsts)
877 		return -1;
878 
879 	/* fix up length afterwards */
880 	setkeymsg0(msg, type, satype, 0);
881 	l = sizeof(struct sadb_msg);
882 
883 	if (!no_spi) {
884 		len = sizeof(struct sadb_sa);
885 		m_sa.sadb_sa_len = PFKEY_UNIT64(len);
886 		m_sa.sadb_sa_exttype = SADB_EXT_SA;
887 		m_sa.sadb_sa_spi = htonl(p_spi);
888 		m_sa.sadb_sa_replay = p_replay;
889 		m_sa.sadb_sa_state = 0;
890 		m_sa.sadb_sa_auth = p_alg_auth;
891 		m_sa.sadb_sa_encrypt = p_alg_enc;
892 		m_sa.sadb_sa_flags = p_ext;
893 
894 		memcpy(buf + l, &m_sa, len);
895 		l += len;
896 
897 		len = sizeof(struct sadb_x_sa2);
898 		m_sa2.sadb_x_sa2_len = PFKEY_UNIT64(len);
899 		m_sa2.sadb_x_sa2_exttype = SADB_X_EXT_SA2;
900 		m_sa2.sadb_x_sa2_mode = p_mode;
901 		m_sa2.sadb_x_sa2_reqid = p_reqid;
902 
903 		memcpy(buf + l, &m_sa2, len);
904 		l += len;
905 	}
906 
907 	l0 = l;
908 	n = 0;
909 
910 	/* do it for all src/dst pairs */
911 	for (s = srcs; s; s = s->ai_next) {
912 		for (d = dsts; d; d = d->ai_next) {
913 			/* rewind pointer */
914 			l = l0;
915 
916 			if (s->ai_addr->sa_family != d->ai_addr->sa_family)
917 				continue;
918 			switch (s->ai_addr->sa_family) {
919 			case AF_INET:
920 				plen = sizeof(struct in_addr) << 3;
921 				break;
922 #ifdef INET6
923 			case AF_INET6:
924 				plen = sizeof(struct in6_addr) << 3;
925 				break;
926 #endif
927 			default:
928 				continue;
929 			}
930 
931 			/* set src */
932 			sa = s->ai_addr;
933 			salen = s->ai_addr->sa_len;
934 			m_addr.sadb_address_len = PFKEY_UNIT64(sizeof(m_addr) +
935 			    PFKEY_ALIGN8(salen));
936 			m_addr.sadb_address_exttype = SADB_EXT_ADDRESS_SRC;
937 			m_addr.sadb_address_proto = IPSEC_ULPROTO_ANY;
938 			m_addr.sadb_address_prefixlen = plen;
939 			m_addr.sadb_address_reserved = 0;
940 
941 			setvarbuf(buf, &l, (struct sadb_ext *)&m_addr,
942 			    sizeof(m_addr), (caddr_t)sa, salen);
943 
944 			/* set dst */
945 			sa = d->ai_addr;
946 			salen = d->ai_addr->sa_len;
947 			m_addr.sadb_address_len = PFKEY_UNIT64(sizeof(m_addr) +
948 			    PFKEY_ALIGN8(salen));
949 			m_addr.sadb_address_exttype = SADB_EXT_ADDRESS_DST;
950 			m_addr.sadb_address_proto = IPSEC_ULPROTO_ANY;
951 			m_addr.sadb_address_prefixlen = plen;
952 			m_addr.sadb_address_reserved = 0;
953 
954 			setvarbuf(buf, &l, (struct sadb_ext *)&m_addr,
955 			    sizeof(m_addr), (caddr_t)sa, salen);
956 
957 			msg->sadb_msg_len = PFKEY_UNIT64(l);
958 
959 			sendkeymsg(buf, l);
960 
961 			n++;
962 		}
963 	}
964 
965 	if (n == 0)
966 		return -1;
967 	else
968 		return 0;
969 }
970 
971 /* XXX NO BUFFER OVERRUN CHECK! BAD BAD! */
972 static int
973 setkeymsg_add(type, satype, srcs, dsts)
974 	unsigned int type;
975 	unsigned int satype;
976 	struct addrinfo *srcs;
977 	struct addrinfo *dsts;
978 {
979 	struct sadb_msg *msg;
980 	char buf[BUFSIZ];
981 	int l, l0, len;
982 	struct sadb_sa m_sa;
983 	struct sadb_x_sa2 m_sa2;
984 	struct sadb_address m_addr;
985 	struct addrinfo *s, *d;
986 	int n;
987 	int plen;
988 	struct sockaddr *sa;
989 	int salen;
990 
991 	msg = (struct sadb_msg *)buf;
992 
993 	if (!srcs || !dsts)
994 		return -1;
995 
996 	/* fix up length afterwards */
997 	setkeymsg0(msg, type, satype, 0);
998 	l = sizeof(struct sadb_msg);
999 
1000 	/* set encryption algorithm, if present. */
1001 	if (satype != SADB_X_SATYPE_IPCOMP && p_key_enc) {
1002 		struct sadb_key m_key;
1003 
1004 		m_key.sadb_key_len =
1005 			PFKEY_UNIT64(sizeof(m_key)
1006 				   + PFKEY_ALIGN8(p_key_enc_len));
1007 		m_key.sadb_key_exttype = SADB_EXT_KEY_ENCRYPT;
1008 		m_key.sadb_key_bits = p_key_enc_len * 8;
1009 		m_key.sadb_key_reserved = 0;
1010 
1011 		setvarbuf(buf, &l,
1012 			(struct sadb_ext *)&m_key, sizeof(m_key),
1013 			(caddr_t)p_key_enc, p_key_enc_len);
1014 	}
1015 
1016 	/* set authentication algorithm, if present. */
1017 	if (p_key_auth) {
1018 		struct sadb_key m_key;
1019 
1020 		m_key.sadb_key_len =
1021 			PFKEY_UNIT64(sizeof(m_key)
1022 				   + PFKEY_ALIGN8(p_key_auth_len));
1023 		m_key.sadb_key_exttype = SADB_EXT_KEY_AUTH;
1024 		m_key.sadb_key_bits = p_key_auth_len * 8;
1025 		m_key.sadb_key_reserved = 0;
1026 
1027 		setvarbuf(buf, &l,
1028 			(struct sadb_ext *)&m_key, sizeof(m_key),
1029 			(caddr_t)p_key_auth, p_key_auth_len);
1030 	}
1031 
1032 	/* set lifetime for HARD */
1033 	if (p_lt_hard != 0) {
1034 		struct sadb_lifetime m_lt;
1035 		u_int slen = sizeof(struct sadb_lifetime);
1036 
1037 		m_lt.sadb_lifetime_len = PFKEY_UNIT64(slen);
1038 		m_lt.sadb_lifetime_exttype = SADB_EXT_LIFETIME_HARD;
1039 		m_lt.sadb_lifetime_allocations = 0;
1040 		m_lt.sadb_lifetime_bytes = 0;
1041 		m_lt.sadb_lifetime_addtime = p_lt_hard;
1042 		m_lt.sadb_lifetime_usetime = 0;
1043 
1044 		memcpy(buf + l, &m_lt, slen);
1045 		l += len;
1046 	}
1047 
1048 	/* set lifetime for SOFT */
1049 	if (p_lt_soft != 0) {
1050 		struct sadb_lifetime m_lt;
1051 		u_int slen = sizeof(struct sadb_lifetime);
1052 
1053 		m_lt.sadb_lifetime_len = PFKEY_UNIT64(slen);
1054 		m_lt.sadb_lifetime_exttype = SADB_EXT_LIFETIME_SOFT;
1055 		m_lt.sadb_lifetime_allocations = 0;
1056 		m_lt.sadb_lifetime_bytes = 0;
1057 		m_lt.sadb_lifetime_addtime = p_lt_soft;
1058 		m_lt.sadb_lifetime_usetime = 0;
1059 
1060 		memcpy(buf + l, &m_lt, slen);
1061 		l += len;
1062 	}
1063 
1064 	len = sizeof(struct sadb_sa);
1065 	m_sa.sadb_sa_len = PFKEY_UNIT64(len);
1066 	m_sa.sadb_sa_exttype = SADB_EXT_SA;
1067 	m_sa.sadb_sa_spi = htonl(p_spi);
1068 	m_sa.sadb_sa_replay = p_replay;
1069 	m_sa.sadb_sa_state = 0;
1070 	m_sa.sadb_sa_auth = p_alg_auth;
1071 	m_sa.sadb_sa_encrypt = p_alg_enc;
1072 	m_sa.sadb_sa_flags = p_ext;
1073 
1074 	memcpy(buf + l, &m_sa, len);
1075 	l += len;
1076 
1077 	len = sizeof(struct sadb_x_sa2);
1078 	m_sa2.sadb_x_sa2_len = PFKEY_UNIT64(len);
1079 	m_sa2.sadb_x_sa2_exttype = SADB_X_EXT_SA2;
1080 	m_sa2.sadb_x_sa2_mode = p_mode;
1081 	m_sa2.sadb_x_sa2_reqid = p_reqid;
1082 
1083 	memcpy(buf + l, &m_sa2, len);
1084 	l += len;
1085 
1086 	l0 = l;
1087 	n = 0;
1088 
1089 	/* do it for all src/dst pairs */
1090 	for (s = srcs; s; s = s->ai_next) {
1091 		for (d = dsts; d; d = d->ai_next) {
1092 			/* rewind pointer */
1093 			l = l0;
1094 
1095 			if (s->ai_addr->sa_family != d->ai_addr->sa_family)
1096 				continue;
1097 			switch (s->ai_addr->sa_family) {
1098 			case AF_INET:
1099 				plen = sizeof(struct in_addr) << 3;
1100 				break;
1101 #ifdef INET6
1102 			case AF_INET6:
1103 				plen = sizeof(struct in6_addr) << 3;
1104 				break;
1105 #endif
1106 			default:
1107 				continue;
1108 			}
1109 
1110 			/* set src */
1111 			sa = s->ai_addr;
1112 			salen = s->ai_addr->sa_len;
1113 			m_addr.sadb_address_len = PFKEY_UNIT64(sizeof(m_addr) +
1114 			    PFKEY_ALIGN8(salen));
1115 			m_addr.sadb_address_exttype = SADB_EXT_ADDRESS_SRC;
1116 			m_addr.sadb_address_proto = IPSEC_ULPROTO_ANY;
1117 			m_addr.sadb_address_prefixlen = plen;
1118 			m_addr.sadb_address_reserved = 0;
1119 
1120 			setvarbuf(buf, &l, (struct sadb_ext *)&m_addr,
1121 			    sizeof(m_addr), (caddr_t)sa, salen);
1122 
1123 			/* set dst */
1124 			sa = d->ai_addr;
1125 			salen = d->ai_addr->sa_len;
1126 			m_addr.sadb_address_len = PFKEY_UNIT64(sizeof(m_addr) +
1127 			    PFKEY_ALIGN8(salen));
1128 			m_addr.sadb_address_exttype = SADB_EXT_ADDRESS_DST;
1129 			m_addr.sadb_address_proto = IPSEC_ULPROTO_ANY;
1130 			m_addr.sadb_address_prefixlen = plen;
1131 			m_addr.sadb_address_reserved = 0;
1132 
1133 			setvarbuf(buf, &l, (struct sadb_ext *)&m_addr,
1134 			    sizeof(m_addr), (caddr_t)sa, salen);
1135 
1136 			msg->sadb_msg_len = PFKEY_UNIT64(l);
1137 
1138 			sendkeymsg(buf, l);
1139 
1140 			n++;
1141 		}
1142 	}
1143 
1144 	if (n == 0)
1145 		return -1;
1146 	else
1147 		return 0;
1148 }
1149 
1150 static struct addrinfo *
1151 parse_addr(host, port)
1152 	char *host;
1153 	char *port;
1154 {
1155 	struct addrinfo hints, *res = NULL;
1156 	int error;
1157 
1158 	memset(&hints, 0, sizeof(hints));
1159 	hints.ai_family = p_aifamily;
1160 	hints.ai_socktype = SOCK_DGRAM;		/*dummy*/
1161 	hints.ai_protocol = IPPROTO_UDP;	/*dummy*/
1162 	hints.ai_flags = p_aiflags;
1163 	error = getaddrinfo(host, port, &hints, &res);
1164 	if (error != 0) {
1165 		yyerror(gai_strerror(error));
1166 		return NULL;
1167 	}
1168 	return res;
1169 }
1170 
1171 static int
1172 fix_portstr(spec, sport, dport)
1173 	vchar_t *spec, *sport, *dport;
1174 {
1175 	char *p, *p2;
1176 	u_int l;
1177 
1178 	l = 0;
1179 	for (p = spec->buf; *p != ',' && *p != '\0' && l < spec->len; p++, l++)
1180 		;
1181 	if (*p == '\0') {
1182 		p2 = "0";
1183 	} else {
1184 		if (*p == ',') {
1185 			*p = '\0';
1186 			p2 = ++p;
1187 		}
1188 		for (p = p2; *p != '\0' && l < spec->len; p++, l++)
1189 			;
1190 		if (*p != '\0' || *p2 == '\0') {
1191 			yyerror("invalid an upper layer protocol spec");
1192 			return -1;
1193 		}
1194 	}
1195 
1196 	sport->buf = strdup(spec->buf);
1197 	if (!sport->buf) {
1198 		yyerror("insufficient memory");
1199 		return -1;
1200 	}
1201 	sport->len = strlen(sport->buf);
1202 	dport->buf = strdup(p2);
1203 	if (!dport->buf) {
1204 		yyerror("insufficient memory");
1205 		return -1;
1206 	}
1207 	dport->len = strlen(dport->buf);
1208 
1209 	return 0;
1210 }
1211 
1212 static int
1213 setvarbuf(buf, off, ebuf, elen, vbuf, vlen)
1214 	char *buf;
1215 	int *off;
1216 	struct sadb_ext *ebuf;
1217 	int elen;
1218 	caddr_t vbuf;
1219 	int vlen;
1220 {
1221 	memset(buf + *off, 0, PFKEY_UNUNIT64(ebuf->sadb_ext_len));
1222 	memcpy(buf + *off, (caddr_t)ebuf, elen);
1223 	memcpy(buf + *off + elen, vbuf, vlen);
1224 	(*off) += PFKEY_ALIGN8(elen + vlen);
1225 
1226 	return 0;
1227 }
1228 
1229 void
1230 parse_init()
1231 {
1232 	p_spi = 0;
1233 
1234 	p_ext = SADB_X_EXT_CYCSEQ;
1235 	p_alg_enc = SADB_EALG_NONE;
1236 	p_alg_auth = SADB_AALG_NONE;
1237 	p_mode = IPSEC_MODE_ANY;
1238 	p_reqid = 0;
1239 	p_replay = 0;
1240 	p_key_enc_len = p_key_auth_len = 0;
1241 	p_key_enc = p_key_auth = 0;
1242 	p_lt_hard = p_lt_soft = 0;
1243 
1244 	p_aiflags = 0;
1245 	p_aifamily = PF_UNSPEC;
1246 
1247 	return;
1248 }
1249 
1250 void
1251 free_buffer()
1252 {
1253 	/* we got tons of memory leaks in the parser anyways, leave them */
1254 
1255 	return;
1256 }
1257