xref: /freebsd/sbin/setkey/parse.y (revision 41466b50c1d5bfd1cf6adaae547a579a75d7c04e)
1 /*	$FreeBSD$	*/
2 /*	$KAME: kame/kame/kame/setkey/parse.y,v 1.36 2001/06/07 15:53:12 sakane Exp $	*/
3 
4 /*
5  * Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project.
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  * 3. Neither the name of the project nor the names of its contributors
17  *    may be used to endorse or promote products derived from this software
18  *    without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23  * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
24  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30  * SUCH DAMAGE.
31  */
32 
33 %{
34 #include <sys/types.h>
35 #include <sys/param.h>
36 #include <sys/socket.h>
37 
38 #include <net/route.h>
39 #include <netinet/in.h>
40 #include <net/pfkeyv2.h>
41 #include <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_int p_type;
59 u_int32_t p_spi;
60 int p_no_spi;
61 struct sockaddr *p_src, *p_dst;
62 u_int p_prefs, p_prefd, p_upper;
63 u_int p_satype, 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 
69 u_int p_policy_len;
70 char *p_policy;
71 
72 /* temporary buffer */
73 static struct sockaddr *pp_addr;
74 static u_int pp_prefix;
75 static u_int pp_port;
76 static caddr_t pp_key;
77 
78 extern u_char m_buf[BUFSIZ];
79 extern int m_len;
80 extern char cmdarg[8192];
81 extern int f_debug;
82 
83 static struct addrinfo *parse_addr __P((char *, char *, int));
84 static int setvarbuf __P((int *, struct sadb_ext *, int, caddr_t, int));
85 void parse_init __P((void));
86 void free_buffer __P((void));
87 
88 extern int setkeymsg __P((void));
89 extern int sendkeymsg __P((void));
90 
91 extern int yylex __P((void));
92 extern void yyfatal __P((const char *));
93 extern void yyerror __P((const char *));
94 %}
95 
96 %union {
97 	unsigned long num;
98 	vchar_t val;
99 }
100 
101 %token EOT
102 %token ADD GET DELETE FLUSH DUMP
103 %token ADDRESS PREFIX PORT PORTANY
104 %token UP_PROTO PR_ESP PR_AH PR_IPCOMP
105 %token F_PROTOCOL F_AUTH F_ENC F_REPLAY F_COMP F_RAWCPI
106 %token F_MODE MODE F_REQID
107 %token F_EXT EXTENSION NOCYCLICSEQ
108 %token ALG_AUTH ALG_ENC ALG_ENC_DESDERIV ALG_ENC_DES32IV ALG_COMP
109 %token F_LIFETIME_HARD F_LIFETIME_SOFT
110 %token DECSTRING QUOTEDSTRING HEXSTRING STRING ANY
111 	/* SPD management */
112 %token SPDADD SPDDELETE SPDDUMP SPDFLUSH
113 %token F_POLICY PL_REQUESTS
114 
115 %type <num> PORT PREFIX EXTENSION MODE
116 %type <num> UP_PROTO PR_ESP PR_AH PR_IPCOMP
117 %type <num> ALG_AUTH ALG_ENC ALG_ENC_DESDERIV ALG_ENC_DES32IV ALG_COMP
118 %type <num> DECSTRING
119 %type <val> ADDRESS PL_REQUESTS
120 %type <val> key_string policy_requests
121 %type <val> QUOTEDSTRING HEXSTRING STRING
122 
123 %%
124 commands
125 	:	/*NOTHING*/
126 	|	commands command
127 		{
128 			if (f_debug) {
129 				printf("cmdarg:\n%s\n", cmdarg);
130 			} else {
131 				setkeymsg();
132 				sendkeymsg();
133 			}
134 			free_buffer();
135 			parse_init();
136 		}
137 	;
138 
139 command
140 	:	add_command
141 	|	get_command
142 	|	delete_command
143 	|	deleteall_command
144 	|	flush_command
145 	|	dump_command
146 	|	spdadd_command
147 	|	spddelete_command
148 	|	spddump_command
149 	|	spdflush_command
150 	;
151 	/* commands concerned with management, there is in tail of this file. */
152 
153 	/* add command */
154 add_command
155 	:	ADD { p_type = SADB_ADD; }
156 		sa_selector_spec extension_spec algorithm_spec EOT
157 	;
158 
159 	/* delete */
160 delete_command
161 	:	DELETE { p_type = SADB_DELETE; }
162 		sa_selector_spec extension_spec
163 		{
164 			if (p_mode != IPSEC_MODE_ANY)
165 				yyerror("WARNING: mode is obsoleted.");
166 		}
167 		EOT
168 	;
169 
170 	/* deleteall command */
171 deleteall_command
172 	:	DELETEALL { p_type = SADB_DELETE; }
173 		ipaddress { p_src = pp_addr; }
174 		ipaddress { p_dst = pp_addr; }
175 		protocol_spec
176 		{ p_no_spi = 1; }
177 		EOT
178 	;
179 
180 	/* get command */
181 get_command
182 	:	GET { p_type = SADB_GET; }
183 		sa_selector_spec extension_spec
184 		{
185 			if (p_mode != IPSEC_MODE_ANY)
186 				yyerror("WARNING: mode is obsoleted.");
187 		}
188 		EOT
189 	;
190 
191 	/* flush */
192 flush_command
193 	:	FLUSH { p_type = SADB_FLUSH; }
194 		protocol_spec EOT
195 	;
196 
197 	/* dump */
198 dump_command
199 	:	DUMP { p_type = SADB_DUMP; }
200 		protocol_spec EOT
201 	;
202 
203 	/* sa_selector_spec */
204 sa_selector_spec
205 	:	ipaddress { p_src = pp_addr; }
206 		ipaddress { p_dst = pp_addr; }
207 		protocol_spec spi
208 	;
209 
210 protocol_spec
211 	:	/*NOTHING*/ { p_satype = SADB_SATYPE_UNSPEC; }
212 	|	PR_ESP
213 		{
214 			p_satype = SADB_SATYPE_ESP;
215 			if ($1 == 1)
216 				p_ext |= SADB_X_EXT_OLD;
217 			else
218 				p_ext &= ~SADB_X_EXT_OLD;
219 		}
220 	|	PR_AH
221 		{
222 			p_satype = SADB_SATYPE_AH;
223 			if ($1 == 1)
224 				p_ext |= SADB_X_EXT_OLD;
225 			else
226 				p_ext &= ~SADB_X_EXT_OLD;
227 		}
228 	|	PR_IPCOMP
229 		{
230 			p_satype = SADB_X_SATYPE_IPCOMP;
231 		}
232 	;
233 
234 spi
235 	:	DECSTRING { p_spi = $1; }
236 	|	HEXSTRING
237 		{
238 			caddr_t bp;
239 			caddr_t yp = $1.buf;
240 			char buf0[4], buf[4];
241 			int i, j;
242 
243 			/* sanity check */
244 			if ($1.len > 4) {
245 				yyerror("SPI too big.");
246 				free($1.buf);
247 				return -1;
248 			}
249 
250 			bp = buf0;
251 			while (*yp) {
252 				*bp = (ATOX(yp[0]) << 4) | ATOX(yp[1]);
253 				yp += 2, bp++;
254 			}
255 
256 			/* initialize */
257 			for (i = 0; i < 4; i++) buf[i] = 0;
258 
259 			for (j = $1.len - 1, i = 3; j >= 0; j--, i--)
260 				buf[i] = buf0[j];
261 
262 			/* XXX: endian */
263 			p_spi = ntohl(*(u_int32_t *)buf);
264 
265 			free($1.buf);
266 		}
267 	;
268 
269 algorithm_spec
270 	:	esp_spec
271 	|	ah_spec
272 	|	ipcomp_spec
273 	;
274 
275 esp_spec
276 	:	F_ENC enc_alg enc_key F_AUTH auth_alg auth_key
277 	|	F_ENC enc_alg enc_key
278 	;
279 
280 ah_spec
281 	:	F_AUTH auth_alg auth_key
282 	;
283 
284 ipcomp_spec
285 	:	F_COMP ALG_COMP { p_alg_enc = $2; }
286 	|	F_COMP ALG_COMP { p_alg_enc = $2; }
287 		F_RAWCPI { p_ext |= SADB_X_EXT_RAWCPI; }
288 	;
289 
290 enc_alg
291 	:	ALG_ENC { p_alg_enc = $1; }
292 	|	ALG_ENC_DESDERIV
293 		{
294 			p_alg_enc = $1;
295 			if (p_ext & SADB_X_EXT_OLD) {
296 				yyerror("algorithm mismatched.");
297 				return -1;
298 			}
299 			p_ext |= SADB_X_EXT_DERIV;
300 		}
301 	|	ALG_ENC_DES32IV
302 		{
303 			p_alg_enc = $1;
304 			if (!(p_ext & SADB_X_EXT_OLD)) {
305 				yyerror("algorithm mismatched.");
306 				return -1;
307 			}
308 			p_ext |= SADB_X_EXT_IV4B;
309 		}
310 	;
311 
312 enc_key
313 	:	/*NOTHING*/
314 		{
315 			if (p_alg_enc != SADB_EALG_NULL) {
316 				yyerror("no key found.");
317 				return -1;
318 			}
319 		}
320 	|	key_string
321 		{
322 			p_key_enc_len = $1.len;
323 			p_key_enc = pp_key;
324 
325 			if (ipsec_check_keylen(SADB_EXT_SUPPORTED_ENCRYPT,
326 					p_alg_enc,
327 					PFKEY_UNUNIT64(p_key_enc_len)) < 0) {
328 				yyerror(ipsec_strerror());
329 				return -1;
330 			}
331 		}
332 	;
333 
334 auth_alg
335 	:	ALG_AUTH { p_alg_auth = $1; }
336 	;
337 
338 auth_key
339 	:	/*NOTHING*/
340 		{
341 			if (p_alg_auth != SADB_X_AALG_NULL) {
342 				yyerror("no key found.");
343 				return -1;
344 			}
345 		}
346 	|	key_string
347 		{
348 			p_key_auth_len = $1.len;
349 			p_key_auth = pp_key;
350 
351 			if (ipsec_check_keylen(SADB_EXT_SUPPORTED_AUTH,
352 					p_alg_auth,
353 					PFKEY_UNUNIT64(p_key_auth_len)) < 0) {
354 				yyerror(ipsec_strerror());
355 				return -1;
356 			}
357 		}
358 	;
359 
360 key_string
361 	:	QUOTEDSTRING
362 		{
363 			pp_key = $1.buf;
364 			/* free pp_key later */
365 		}
366 	|	HEXSTRING
367 		{
368 			caddr_t bp;
369 			caddr_t yp = $1.buf;
370 
371 			if ((pp_key = malloc($1.len)) == 0) {
372 				free($1.buf);
373 				yyerror("not enough core");
374 				return -1;
375 			}
376 			memset(pp_key, 0, $1.len);
377 
378 			bp = pp_key;
379 			while (*yp) {
380 				*bp = (ATOX(yp[0]) << 4) | ATOX(yp[1]);
381 				yp += 2, bp++;
382 			}
383 
384 			free($1.buf);
385 		}
386 	;
387 
388 extension_spec
389 	:	/*NOTHING*/
390 	|	extension_spec extension
391 	;
392 
393 extension
394 	:	F_EXT EXTENSION { p_ext |= $2; }
395 	|	F_EXT NOCYCLICSEQ { p_ext &= ~SADB_X_EXT_CYCSEQ; }
396 	|	F_MODE MODE { p_mode = $2; }
397 	|	F_MODE ANY { p_mode = IPSEC_MODE_ANY; }
398 	|	F_REQID DECSTRING { p_reqid = $2; }
399 	|	F_REPLAY DECSTRING
400 		{
401 			if (p_ext & SADB_X_EXT_OLD) {
402 				yyerror("replay prevention "
403 				        "only use on new spec.");
404 				return -1;
405 			}
406 			p_replay = $2;
407 		}
408 	|	F_LIFETIME_HARD DECSTRING { p_lt_hard = $2; }
409 	|	F_LIFETIME_SOFT DECSTRING { p_lt_soft = $2; }
410 	;
411 
412 	/* definition about command for SPD management */
413 	/* spdadd */
414 spdadd_command
415 	:	SPDADD
416 		{
417 			p_type = SADB_X_SPDADD;
418 			p_satype = SADB_SATYPE_UNSPEC;
419 		}
420 		sp_selector_spec policy_spec EOT
421 	;
422 
423 spddelete_command:
424 		SPDDELETE
425 		{
426 			p_type = SADB_X_SPDDELETE;
427 			p_satype = SADB_SATYPE_UNSPEC;
428 		}
429 		sp_selector_spec policy_spec EOT
430 	;
431 
432 spddump_command:
433 		SPDDUMP
434 		{
435 			p_type = SADB_X_SPDDUMP;
436 			p_satype = SADB_SATYPE_UNSPEC;
437 		}
438 		EOT
439 	;
440 
441 spdflush_command:
442 		SPDFLUSH
443 		{
444 			p_type = SADB_X_SPDFLUSH;
445 			p_satype = SADB_SATYPE_UNSPEC;
446 		}
447 		EOT
448 	;
449 
450 	/* sp_selector_spec */
451 sp_selector_spec
452 	:	ipaddress { p_src = pp_addr; }
453 		prefix { p_prefs = pp_prefix; }
454 		port
455 		{
456 			switch (p_src->sa_family) {
457 			case AF_INET:
458 				((struct sockaddr_in *)p_src)->sin_port =
459 				    htons(pp_port);
460 				break;
461 #ifdef INET6
462 			case AF_INET6:
463 				((struct sockaddr_in6 *)p_src)->sin6_port =
464 				    htons(pp_port);
465 				break;
466 #endif
467 			default:
468 				exit(1); /*XXX*/
469 			}
470 		}
471 		ipaddress { p_dst = pp_addr; }
472 		prefix { p_prefd = pp_prefix; }
473 		port
474 		{
475 			switch (p_dst->sa_family) {
476 			case AF_INET:
477 				((struct sockaddr_in *)p_dst)->sin_port =
478 				    htons(pp_port);
479 				break;
480 #ifdef INET6
481 			case AF_INET6:
482 				((struct sockaddr_in6 *)p_dst)->sin6_port =
483 				    htons(pp_port);
484 				break;
485 #endif
486 			default:
487 				exit(1); /*XXX*/
488 			}
489 		}
490 		upper_spec
491 		{
492 			/* XXX is it something userland should check? */
493 #if 0
494 			switch (p_upper) {
495 			case IPPROTO_ICMP:
496 			case IPPROTO_ICMPV6:
497 				if (_INPORTBYSA(p_src) != IPSEC_PORT_ANY
498 				 || _INPORTBYSA(p_dst) != IPSEC_PORT_ANY) {
499 					yyerror("port number must be \"any\".");
500 					return -1;
501 				}
502 				if ((pp_addr->sa_family == AF_INET6
503 				  && p_upper == IPPROTO_ICMP)
504 				 || (pp_addr->sa_family == AF_INET
505 				  && p_upper == IPPROTO_ICMPV6)) {
506 					yyerror("upper layer protocol "
507 						"mismatched.\n");
508 					return -1;
509 				}
510 				break;
511 			default:
512 				break;
513 			}
514 #endif
515 		}
516 	;
517 
518 ipaddress
519 	:	ADDRESS
520 		{
521 			struct addrinfo *res;
522 
523 			res = parse_addr($1.buf, NULL, AI_NUMERICHOST);
524 			if (res == NULL) {
525 				free($1.buf);
526 				return -1;
527 			}
528 			pp_addr = (struct sockaddr *)malloc(res->ai_addrlen);
529 			if (!pp_addr) {
530 				yyerror("not enough core");
531 				goto end;
532 			}
533 
534 			memcpy(pp_addr, res->ai_addr, res->ai_addrlen);
535 		    end:
536 			freeaddrinfo(res);
537 			free($1.buf);
538 		}
539 	;
540 
541 prefix
542 	:	/*NOTHING*/ { pp_prefix = ~0; }
543 	|	PREFIX { pp_prefix = $1; }
544 	;
545 
546 port
547 	:	/*NOTHING*/ { pp_port = IPSEC_PORT_ANY; }
548 	|	PORT { pp_port = $1; }
549 	|	PORTANY { pp_port = IPSEC_PORT_ANY; }
550 	;
551 
552 upper_spec
553 	:	DECSTRING { p_upper = $1; }
554 	|	UP_PROTO { p_upper = $1; }
555 	|	ANY { p_upper = IPSEC_ULPROTO_ANY; }
556 	|	STRING
557 		{
558 			struct protoent *ent;
559 
560 			ent = getprotobyname($1.buf);
561 			if (ent)
562 				p_upper = ent->p_proto;
563 			else {
564 				if (strcmp("icmp6", $1.buf) == 0) {
565 					p_upper = IPPROTO_ICMPV6;
566 				} else if(strcmp("ip4", $1.buf) == 0) {
567 					p_upper = IPPROTO_IPV4;
568 				} else {
569 					yyerror("invalid upper layer protocol");
570 					free($1.buf);
571 					return -1;
572 				}
573 			}
574 			free($1.buf);
575 		}
576 	;
577 
578 policy_spec
579 	:	F_POLICY policy_requests
580 		{
581 			p_policy = ipsec_set_policy($2.buf, $2.len);
582 			if (p_policy == NULL) {
583 				free($2.buf);
584 				p_policy = NULL;
585 				yyerror(ipsec_strerror());
586 				return -1;
587 			}
588 
589 			p_policy_len = ipsec_get_policylen(p_policy);
590 
591 			free($2.buf);
592 		}
593 	;
594 
595 policy_requests
596 	:	PL_REQUESTS { $$ = $1; }
597 	;
598 
599 %%
600 
601 int
602 setkeymsg()
603 {
604 	struct sadb_msg m_msg;
605 
606 	m_msg.sadb_msg_version = PF_KEY_V2;
607 	m_msg.sadb_msg_type = p_type;
608 	m_msg.sadb_msg_errno = 0;
609 	m_msg.sadb_msg_satype = p_satype;
610 	m_msg.sadb_msg_reserved = 0;
611 	m_msg.sadb_msg_seq = 0;
612 	m_msg.sadb_msg_pid = getpid();
613 
614 	m_len = sizeof(struct sadb_msg);
615 	memcpy(m_buf, &m_msg, m_len);
616 
617 	switch (p_type) {
618 	case SADB_FLUSH:
619 	case SADB_DUMP:
620 		break;
621 
622 	case SADB_ADD:
623 		/* set encryption algorithm, if present. */
624 		if (p_satype != SADB_X_SATYPE_IPCOMP && p_alg_enc != SADB_EALG_NONE) {
625 			struct sadb_key m_key;
626 
627 			m_key.sadb_key_len =
628 				PFKEY_UNIT64(sizeof(m_key)
629 				           + PFKEY_ALIGN8(p_key_enc_len));
630 			m_key.sadb_key_exttype = SADB_EXT_KEY_ENCRYPT;
631 			m_key.sadb_key_bits = p_key_enc_len * 8;
632 			m_key.sadb_key_reserved = 0;
633 
634 			setvarbuf(&m_len,
635 				(struct sadb_ext *)&m_key, sizeof(m_key),
636 				(caddr_t)p_key_enc, p_key_enc_len);
637 		}
638 
639 		/* set authentication algorithm, if present. */
640 		if (p_alg_auth != SADB_AALG_NONE) {
641 			struct sadb_key m_key;
642 
643 			m_key.sadb_key_len =
644 				PFKEY_UNIT64(sizeof(m_key)
645 				           + PFKEY_ALIGN8(p_key_auth_len));
646 			m_key.sadb_key_exttype = SADB_EXT_KEY_AUTH;
647 			m_key.sadb_key_bits = p_key_auth_len * 8;
648 			m_key.sadb_key_reserved = 0;
649 
650 			setvarbuf(&m_len,
651 				(struct sadb_ext *)&m_key, sizeof(m_key),
652 				(caddr_t)p_key_auth, p_key_auth_len);
653 		}
654 
655 		/* set lifetime for HARD */
656 		if (p_lt_hard != 0) {
657 			struct sadb_lifetime m_lt;
658 			u_int len = sizeof(struct sadb_lifetime);
659 
660 			m_lt.sadb_lifetime_len = PFKEY_UNIT64(len);
661 			m_lt.sadb_lifetime_exttype = SADB_EXT_LIFETIME_HARD;
662 			m_lt.sadb_lifetime_allocations = 0;
663 			m_lt.sadb_lifetime_bytes = 0;
664 			m_lt.sadb_lifetime_addtime = p_lt_hard;
665 			m_lt.sadb_lifetime_usetime = 0;
666 
667 			memcpy(m_buf + m_len, &m_lt, len);
668 			m_len += len;
669 		}
670 
671 		/* set lifetime for SOFT */
672 		if (p_lt_soft != 0) {
673 			struct sadb_lifetime m_lt;
674 			u_int len = sizeof(struct sadb_lifetime);
675 
676 			m_lt.sadb_lifetime_len = PFKEY_UNIT64(len);
677 			m_lt.sadb_lifetime_exttype = SADB_EXT_LIFETIME_SOFT;
678 			m_lt.sadb_lifetime_allocations = 0;
679 			m_lt.sadb_lifetime_bytes = 0;
680 			m_lt.sadb_lifetime_addtime = p_lt_soft;
681 			m_lt.sadb_lifetime_usetime = 0;
682 
683 			memcpy(m_buf + m_len, &m_lt, len);
684 			m_len += len;
685 		}
686 		/* FALLTHROUGH */
687 
688 	case SADB_DELETE:
689 	case SADB_GET:
690 	    {
691 		struct sadb_sa m_sa;
692 		struct sadb_x_sa2 m_sa2;
693 		struct sadb_address m_addr;
694 		u_int len;
695 
696 		if (p_no_spi == 0) {
697 			len = sizeof(struct sadb_sa);
698 			m_sa.sadb_sa_len = PFKEY_UNIT64(len);
699 			m_sa.sadb_sa_exttype = SADB_EXT_SA;
700 			m_sa.sadb_sa_spi = htonl(p_spi);
701 			m_sa.sadb_sa_replay = p_replay;
702 			m_sa.sadb_sa_state = 0;
703 			m_sa.sadb_sa_auth = p_alg_auth;
704 			m_sa.sadb_sa_encrypt = p_alg_enc;
705 			m_sa.sadb_sa_flags = p_ext;
706 
707 			memcpy(m_buf + m_len, &m_sa, len);
708 			m_len += len;
709 
710 			len = sizeof(struct sadb_x_sa2);
711 			m_sa2.sadb_x_sa2_len = PFKEY_UNIT64(len);
712 			m_sa2.sadb_x_sa2_exttype = SADB_X_EXT_SA2;
713 			m_sa2.sadb_x_sa2_mode = p_mode;
714 			m_sa2.sadb_x_sa2_reqid = p_reqid;
715 
716 			memcpy(m_buf + m_len, &m_sa2, len);
717 			m_len += len;
718 		}
719 
720 		/* set src */
721 		m_addr.sadb_address_len =
722 			PFKEY_UNIT64(sizeof(m_addr)
723 			           + PFKEY_ALIGN8(p_src->sa_len));
724 		m_addr.sadb_address_exttype = SADB_EXT_ADDRESS_SRC;
725 		m_addr.sadb_address_proto = IPSEC_ULPROTO_ANY;
726 		switch (p_src->sa_family) {
727 		case AF_INET:
728 			m_addr.sadb_address_prefixlen =
729 			    sizeof(struct in_addr) << 3;
730 			break;
731 #ifdef INET6
732 		case AF_INET6:
733 			m_addr.sadb_address_prefixlen =
734 			    sizeof(struct in6_addr) << 3;
735 			break;
736 #endif
737 		default:
738 			yyerror("unsupported address family");
739 			exit(1);	/*XXX*/
740 		}
741 		m_addr.sadb_address_reserved = 0;
742 
743 		setvarbuf(&m_len,
744 			(struct sadb_ext *)&m_addr, sizeof(m_addr),
745 			(caddr_t)p_src, p_src->sa_len);
746 
747 		/* set dst */
748 		m_addr.sadb_address_len =
749 			PFKEY_UNIT64(sizeof(m_addr)
750 			           + PFKEY_ALIGN8(p_dst->sa_len));
751 		m_addr.sadb_address_exttype = SADB_EXT_ADDRESS_DST;
752 		m_addr.sadb_address_proto = IPSEC_ULPROTO_ANY;
753 		switch (p_dst->sa_family) {
754 		case AF_INET:
755 			m_addr.sadb_address_prefixlen =
756 			    sizeof(struct in_addr) << 3;
757 			break;
758 #ifdef INET6
759 		case AF_INET6:
760 			m_addr.sadb_address_prefixlen =
761 			    sizeof(struct in6_addr) << 3;
762 			break;
763 #endif
764 		default:
765 			yyerror("unsupported address family");
766 			exit(1);	/*XXX*/
767 		}
768 		m_addr.sadb_address_reserved = 0;
769 
770 		setvarbuf(&m_len,
771 			(struct sadb_ext *)&m_addr, sizeof(m_addr),
772 			(caddr_t)p_dst, p_dst->sa_len);
773 	    }
774 		break;
775 
776 	/* for SPD management */
777 	case SADB_X_SPDFLUSH:
778 	case SADB_X_SPDDUMP:
779 		break;
780 
781 	case SADB_X_SPDADD:
782 	case SADB_X_SPDDELETE:
783 	    {
784 		struct sadb_address m_addr;
785 		u_int8_t plen;
786 
787 		memcpy(m_buf + m_len, p_policy, p_policy_len);
788 		m_len += p_policy_len;
789 		free(p_policy);
790 		p_policy = NULL;
791 
792 		/* set src */
793 		m_addr.sadb_address_len =
794 			PFKEY_UNIT64(sizeof(m_addr)
795 			           + PFKEY_ALIGN8(p_src->sa_len));
796 		m_addr.sadb_address_exttype = SADB_EXT_ADDRESS_SRC;
797 		m_addr.sadb_address_proto = p_upper;
798 		switch (p_src->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 			yyerror("unsupported address family");
809 			exit(1);	/*XXX*/
810 		}
811 		m_addr.sadb_address_prefixlen =
812 		    (p_prefs != ~0 ? p_prefs : plen);
813 		m_addr.sadb_address_reserved = 0;
814 
815 		setvarbuf(&m_len,
816 			(struct sadb_ext *)&m_addr, sizeof(m_addr),
817 			(caddr_t)p_src, p_src->sa_len);
818 
819 		/* set dst */
820 		m_addr.sadb_address_len =
821 			PFKEY_UNIT64(sizeof(m_addr)
822 			           + PFKEY_ALIGN8(p_dst->sa_len));
823 		m_addr.sadb_address_exttype = SADB_EXT_ADDRESS_DST;
824 		m_addr.sadb_address_proto = p_upper;
825 		switch (p_dst->sa_family) {
826 		case AF_INET:
827 			plen = sizeof(struct in_addr) << 3;
828 			break;
829 #ifdef INET6
830 		case AF_INET6:
831 			plen = sizeof(struct in6_addr) << 3;
832 			break;
833 #endif
834 		default:
835 			yyerror("unsupported address family");
836 			exit(1);	/*XXX*/
837 		}
838 		m_addr.sadb_address_prefixlen =
839 		    (p_prefd != ~0 ? p_prefd : plen);
840 		m_addr.sadb_address_reserved = 0;
841 
842 		setvarbuf(&m_len,
843 			(struct sadb_ext *)&m_addr, sizeof(m_addr),
844 			(caddr_t)p_dst, p_dst->sa_len);
845 	    }
846 		break;
847 	}
848 
849 	((struct sadb_msg *)m_buf)->sadb_msg_len = PFKEY_UNIT64(m_len);
850 
851 	return 0;
852 }
853 
854 static struct addrinfo *
855 parse_addr(host, port, flag)
856 	char *host;
857 	char *port;
858 	int flag;
859 {
860 	struct addrinfo hints, *res = NULL;
861 	int error;
862 
863 	memset(&hints, 0, sizeof(hints));
864 	hints.ai_family = PF_UNSPEC;
865 	hints.ai_socktype = SOCK_DGRAM;
866 	hints.ai_flags = flag;
867 	error = getaddrinfo(host, port, &hints, &res);
868 	if (error != 0) {
869 		yyerror(gai_strerror(error));
870 		return NULL;
871 	}
872 	if (res->ai_next != NULL) {
873 		yyerror(gai_strerror(error));
874 	}
875 	return res;
876 }
877 
878 static int
879 setvarbuf(off, ebuf, elen, vbuf, vlen)
880 	caddr_t vbuf;
881 	struct sadb_ext *ebuf;
882 	int *off, elen, vlen;
883 {
884 	memset(m_buf + *off, 0, PFKEY_UNUNIT64(ebuf->sadb_ext_len));
885 	memcpy(m_buf + *off, (caddr_t)ebuf, elen);
886 	memcpy(m_buf + *off + elen, vbuf, vlen);
887 	(*off) += PFKEY_ALIGN8(elen + vlen);
888 
889 	return 0;
890 }
891 
892 void
893 parse_init()
894 {
895 	p_type = 0;
896 	p_spi = 0;
897 	p_no_spi = 0;
898 
899 	p_src = 0, p_dst = 0;
900 	pp_prefix = p_prefs = p_prefd = ~0;
901 	pp_port = IPSEC_PORT_ANY;
902 	p_upper = 0;
903 
904 	p_satype = 0;
905 	p_ext = SADB_X_EXT_CYCSEQ;
906 	p_alg_enc = SADB_EALG_NONE;
907 	p_alg_auth = SADB_AALG_NONE;
908 	p_mode = IPSEC_MODE_ANY;
909 	p_reqid = 0;
910 	p_replay = 0;
911 	p_key_enc_len = p_key_auth_len = 0;
912 	p_key_enc = p_key_auth = 0;
913 	p_lt_hard = p_lt_soft = 0;
914 
915 	p_policy_len = 0;
916 	p_policy = NULL;
917 
918 	memset(cmdarg, 0, sizeof(cmdarg));
919 
920 	return;
921 }
922 
923 void
924 free_buffer()
925 {
926 	if (p_src) free(p_src);
927 	if (p_dst) free(p_dst);
928 	if (p_key_enc) free(p_key_enc);
929 	if (p_key_auth) free(p_key_auth);
930 
931 	return;
932 }
933 
934