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