xref: /freebsd/sbin/setkey/parse.y (revision 77a0943ded95b9e6438f7db70c4a28e4d93946d4)
1 /*	$FreeBSD$	*/
2 /*	$KAME: parse.y,v 1.29 2000/06/10 14:17:44 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 struct sockaddr *p_src, *p_dst;
61 u_int p_prefs, p_prefd, p_upper;
62 u_int p_satype, p_ext, p_alg_enc, p_alg_auth, p_replay, p_mode;
63 u_int32_t p_reqid;
64 u_int p_key_enc_len, p_key_auth_len;
65 caddr_t p_key_enc, p_key_auth;
66 time_t p_lt_hard, p_lt_soft;
67 
68 u_int p_policy_len;
69 char *p_policy;
70 
71 /* temporary buffer */
72 static struct sockaddr *pp_addr;
73 static u_int pp_prefix;
74 static u_int pp_port;
75 static caddr_t pp_key;
76 
77 extern u_char m_buf[BUFSIZ];
78 extern int m_len;
79 extern char cmdarg[8192];
80 extern int f_debug;
81 
82 int setkeymsg __P((void));
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 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
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 	|	flush_command
144 	|	dump_command
145 	|	spdadd_command
146 	|	spddelete_command
147 	|	spddump_command
148 	|	spdflush_command
149 	;
150 	/* commands concerned with management, there is in tail of this file. */
151 
152 	/* add command */
153 add_command
154 	:	ADD { p_type = SADB_ADD; }
155 		sa_selector_spec extension_spec algorithm_spec EOT
156 	;
157 
158 	/* delete */
159 delete_command
160 	:	DELETE { p_type = SADB_DELETE; }
161 		sa_selector_spec extension_spec
162 		{
163 			if (p_mode != IPSEC_MODE_ANY)
164 				yyerror("WARNING: mode is obsoleted.");
165 		}
166 		EOT
167 	;
168 
169 	/* get command */
170 get_command
171 	:	GET { p_type = SADB_GET; }
172 		sa_selector_spec extension_spec
173 		{
174 			if (p_mode != IPSEC_MODE_ANY)
175 				yyerror("WARNING: mode is obsoleted.");
176 		}
177 		EOT
178 	;
179 
180 	/* flush */
181 flush_command
182 	:	FLUSH { p_type = SADB_FLUSH; }
183 		protocol_spec EOT
184 	;
185 
186 	/* dump */
187 dump_command
188 	:	DUMP { p_type = SADB_DUMP; }
189 		protocol_spec EOT
190 	;
191 
192 	/* sa_selector_spec */
193 sa_selector_spec
194 	:	ipaddress { p_src = pp_addr; }
195 		ipaddress { p_dst = pp_addr; }
196 		protocol_spec spi
197 	;
198 
199 protocol_spec
200 	:	/*NOTHING*/ { p_satype = SADB_SATYPE_UNSPEC; }
201 	|	PR_ESP
202 		{
203 			p_satype = SADB_SATYPE_ESP;
204 			if ($1 == 1)
205 				p_ext |= SADB_X_EXT_OLD;
206 			else
207 				p_ext &= ~SADB_X_EXT_OLD;
208 		}
209 	|	PR_AH
210 		{
211 			p_satype = SADB_SATYPE_AH;
212 			if ($1 == 1)
213 				p_ext |= SADB_X_EXT_OLD;
214 			else
215 				p_ext &= ~SADB_X_EXT_OLD;
216 		}
217 	|	PR_IPCOMP
218 		{
219 			p_satype = SADB_X_SATYPE_IPCOMP;
220 		}
221 	;
222 
223 spi
224 	:	DECSTRING { p_spi = $1; }
225 	|	HEXSTRING
226 		{
227 			caddr_t bp;
228 			caddr_t yp = $1.buf;
229 			char buf0[4], buf[4];
230 			int i, j;
231 
232 			/* sanity check */
233 			if ($1.len > 4) {
234 				yyerror("SPI too big.");
235 				free($1.buf);
236 				return -1;
237 			}
238 
239 			bp = buf0;
240 			while (*yp) {
241 				*bp = (ATOX(yp[0]) << 4) | ATOX(yp[1]);
242 				yp += 2, bp++;
243 			}
244 
245 			/* initialize */
246 			for (i = 0; i < 4; i++) buf[i] = 0;
247 
248 			for (j = $1.len - 1, i = 3; j >= 0; j--, i--)
249 				buf[i] = buf0[j];
250 
251 			/* XXX: endian */
252 			p_spi = ntohl(*(u_int32_t *)buf);
253 
254 			free($1.buf);
255 		}
256 	;
257 
258 algorithm_spec
259 	:	esp_spec
260 	|	ah_spec
261 	|	ipcomp_spec
262 	;
263 
264 esp_spec
265 	:	F_ENC enc_alg enc_key F_AUTH auth_alg auth_key
266 	|	F_ENC enc_alg enc_key
267 	;
268 
269 ah_spec
270 	:	F_AUTH auth_alg auth_key
271 	;
272 
273 ipcomp_spec
274 	:	F_COMP ALG_COMP { p_alg_enc = $2; }
275 	|	F_COMP ALG_COMP { p_alg_enc = $2; }
276 		F_RAWCPI { p_ext |= SADB_X_EXT_RAWCPI; }
277 	;
278 
279 enc_alg
280 	:	ALG_ENC { p_alg_enc = $1; }
281 	|	ALG_ENC_DESDERIV
282 		{
283 			p_alg_enc = $1;
284 			if (p_ext & SADB_X_EXT_OLD) {
285 				yyerror("algorithm mismatched.");
286 				return -1;
287 			}
288 			p_ext |= SADB_X_EXT_DERIV;
289 		}
290 	|	ALG_ENC_DES32IV
291 		{
292 			p_alg_enc = $1;
293 			if (!(p_ext & SADB_X_EXT_OLD)) {
294 				yyerror("algorithm mismatched.");
295 				return -1;
296 			}
297 			p_ext |= SADB_X_EXT_IV4B;
298 		}
299 	;
300 
301 enc_key
302 	:	/*NOTHING*/
303 		{
304 			if (p_alg_enc != SADB_EALG_NULL) {
305 				yyerror("no key found.");
306 				return -1;
307 			}
308 		}
309 	|	key_string
310 		{
311 			p_key_enc_len = $1.len;
312 			p_key_enc = pp_key;
313 
314 			if (ipsec_check_keylen(SADB_EXT_SUPPORTED_ENCRYPT,
315 					p_alg_enc,
316 					PFKEY_UNUNIT64(p_key_enc_len)) < 0) {
317 				yyerror(ipsec_strerror());
318 				return -1;
319 			}
320 		}
321 	;
322 
323 auth_alg
324 	:	ALG_AUTH { p_alg_auth = $1; }
325 	;
326 
327 auth_key
328 	:	/*NOTHING*/
329 		{
330 			if (p_alg_auth != SADB_AALG_NULL) {
331 				yyerror("no key found.");
332 				return -1;
333 			}
334 		}
335 	|	key_string
336 		{
337 			p_key_auth_len = $1.len;
338 			p_key_auth = pp_key;
339 
340 			if (ipsec_check_keylen(SADB_EXT_SUPPORTED_AUTH,
341 					p_alg_auth,
342 					PFKEY_UNUNIT64(p_key_auth_len)) < 0) {
343 				yyerror(ipsec_strerror());
344 				return -1;
345 			}
346 		}
347 	;
348 
349 key_string
350 	:	QUOTEDSTRING
351 		{
352 			pp_key = $1.buf;
353 			/* free pp_key later */
354 		}
355 	|	HEXSTRING
356 		{
357 			caddr_t bp;
358 			caddr_t yp = $1.buf;
359 
360 			if ((pp_key = malloc($1.len)) == 0) {
361 				free($1.buf);
362 				yyerror("not enough core");
363 				return -1;
364 			}
365 			memset(pp_key, 0, $1.len);
366 
367 			bp = pp_key;
368 			while (*yp) {
369 				*bp = (ATOX(yp[0]) << 4) | ATOX(yp[1]);
370 				yp += 2, bp++;
371 			}
372 
373 			free($1.buf);
374 		}
375 	;
376 
377 extension_spec
378 	:	/*NOTHING*/
379 	|	extension_spec extension
380 	;
381 
382 extension
383 	:	F_EXT EXTENSION { p_ext |= $2; }
384 	|	F_EXT NOCYCLICSEQ { p_ext &= ~SADB_X_EXT_CYCSEQ; }
385 	|	F_MODE MODE { p_mode = $2; }
386 	|	F_MODE ANY { p_mode = IPSEC_MODE_ANY; }
387 	|	F_REQID DECSTRING { p_reqid = $2; }
388 	|	F_REPLAY DECSTRING
389 		{
390 			if (p_ext & SADB_X_EXT_OLD) {
391 				yyerror("replay prevention "
392 				        "only use on new spec.");
393 				return -1;
394 			}
395 			p_replay = $2;
396 		}
397 	|	F_LIFETIME_HARD DECSTRING { p_lt_hard = $2; }
398 	|	F_LIFETIME_SOFT DECSTRING { p_lt_soft = $2; }
399 	;
400 
401 	/* definition about command for SPD management */
402 	/* spdadd */
403 spdadd_command
404 	:	SPDADD
405 		{
406 			p_type = SADB_X_SPDADD;
407 			p_satype = SADB_SATYPE_UNSPEC;
408 		}
409 		sp_selector_spec policy_spec EOT
410 	;
411 
412 spddelete_command:
413 		SPDDELETE
414 		{
415 			p_type = SADB_X_SPDDELETE;
416 			p_satype = SADB_SATYPE_UNSPEC;
417 		}
418 		sp_selector_spec policy_spec EOT
419 	;
420 
421 spddump_command:
422 		SPDDUMP
423 		{
424 			p_type = SADB_X_SPDDUMP;
425 			p_satype = SADB_SATYPE_UNSPEC;
426 		}
427 		EOT
428 	;
429 
430 spdflush_command:
431 		SPDFLUSH
432 		{
433 			p_type = SADB_X_SPDFLUSH;
434 			p_satype = SADB_SATYPE_UNSPEC;
435 		}
436 		EOT
437 	;
438 
439 	/* sp_selector_spec */
440 sp_selector_spec
441 	:	ipaddress { p_src = pp_addr; }
442 		prefix { p_prefs = pp_prefix; }
443 		port
444 		{
445 			switch (p_src->sa_family) {
446 			case AF_INET:
447 				((struct sockaddr_in *)p_src)->sin_port =
448 				    htons(pp_port);
449 				break;
450 #ifdef INET6
451 			case AF_INET6:
452 				((struct sockaddr_in6 *)p_src)->sin6_port =
453 				    htons(pp_port);
454 				break;
455 #endif
456 			default:
457 				exit(1); /*XXX*/
458 			}
459 		}
460 		ipaddress { p_dst = pp_addr; }
461 		prefix { p_prefd = pp_prefix; }
462 		port
463 		{
464 			switch (p_dst->sa_family) {
465 			case AF_INET:
466 				((struct sockaddr_in *)p_dst)->sin_port =
467 				    htons(pp_port);
468 				break;
469 #ifdef INET6
470 			case AF_INET6:
471 				((struct sockaddr_in6 *)p_dst)->sin6_port =
472 				    htons(pp_port);
473 				break;
474 #endif
475 			default:
476 				exit(1); /*XXX*/
477 			}
478 		}
479 		upper_spec
480 		{
481 			/* XXX is it something userland should check? */
482 #if 0
483 			switch (p_upper) {
484 			case IPPROTO_ICMP:
485 			case IPPROTO_ICMPV6:
486 				if (_INPORTBYSA(p_src) != IPSEC_PORT_ANY
487 				 || _INPORTBYSA(p_dst) != IPSEC_PORT_ANY) {
488 					yyerror("port number must be \"any\".");
489 					return -1;
490 				}
491 				if ((pp_addr->sa_family == AF_INET6
492 				  && p_upper == IPPROTO_ICMP)
493 				 || (pp_addr->sa_family == AF_INET
494 				  && p_upper == IPPROTO_ICMPV6)) {
495 					yyerror("upper layer protocol "
496 						"mismatched.\n");
497 					return -1;
498 				}
499 				break;
500 			default:
501 				break;
502 			}
503 #endif
504 		}
505 	;
506 
507 ipaddress
508 	:	ADDRESS
509 		{
510 			struct addrinfo *res;
511 
512 			res = parse_addr($1.buf, NULL, AI_NUMERICHOST);
513 			if (res == NULL) {
514 				free($1.buf);
515 				return -1;
516 			}
517 			pp_addr = (struct sockaddr *)malloc(res->ai_addrlen);
518 			if (!pp_addr) {
519 				yyerror("not enough core");
520 				goto end;
521 			}
522 
523 			memcpy(pp_addr, res->ai_addr, res->ai_addrlen);
524 		    end:
525 			freeaddrinfo(res);
526 			free($1.buf);
527 		}
528 	;
529 
530 prefix
531 	:	/*NOTHING*/ { pp_prefix = ~0; }
532 	|	PREFIX { pp_prefix = $1; }
533 	;
534 
535 port
536 	:	/*NOTHING*/ { pp_port = IPSEC_PORT_ANY; }
537 	|	PORT { pp_port = $1; }
538 	|	PORTANY { pp_port = IPSEC_PORT_ANY; }
539 	;
540 
541 upper_spec
542 	:	DECSTRING { p_upper = $1; }
543 	|	UP_PROTO { p_upper = $1; }
544 	|	PR_ESP { p_upper = IPPROTO_ESP; };
545 	|	PR_AH { p_upper = IPPROTO_AH; };
546 	|	PR_IPCOMP { p_upper = IPPROTO_IPCOMP; };
547 	|	ANY { p_upper = IPSEC_ULPROTO_ANY; }
548 	;
549 
550 policy_spec
551 	:	F_POLICY policy_requests
552 		{
553 			p_policy = ipsec_set_policy($2.buf, $2.len);
554 			if (p_policy == NULL) {
555 				free($2.buf);
556 				p_policy = NULL;
557 				yyerror(ipsec_strerror());
558 				return -1;
559 			}
560 
561 			p_policy_len = ipsec_get_policylen(p_policy);
562 
563 			free($2.buf);
564 		}
565 	;
566 
567 policy_requests
568 	:	PL_REQUESTS { $$ = $1; }
569 	;
570 
571 %%
572 
573 int
574 setkeymsg()
575 {
576 	struct sadb_msg m_msg;
577 
578 	m_msg.sadb_msg_version = PF_KEY_V2;
579 	m_msg.sadb_msg_type = p_type;
580 	m_msg.sadb_msg_errno = 0;
581 	m_msg.sadb_msg_satype = p_satype;
582 	m_msg.sadb_msg_reserved = 0;
583 	m_msg.sadb_msg_seq = 0;
584 	m_msg.sadb_msg_pid = getpid();
585 
586 	m_len = sizeof(struct sadb_msg);
587 	memcpy(m_buf, &m_msg, m_len);
588 
589 	switch (p_type) {
590 	case SADB_FLUSH:
591 	case SADB_DUMP:
592 		break;
593 
594 	case SADB_ADD:
595 		/* set encryption algorithm, if present. */
596 		if (p_satype != SADB_X_SATYPE_IPCOMP && p_alg_enc != SADB_EALG_NONE) {
597 			struct sadb_key m_key;
598 
599 			m_key.sadb_key_len =
600 				PFKEY_UNIT64(sizeof(m_key)
601 				           + PFKEY_ALIGN8(p_key_enc_len));
602 			m_key.sadb_key_exttype = SADB_EXT_KEY_ENCRYPT;
603 			m_key.sadb_key_bits = p_key_enc_len * 8;
604 			m_key.sadb_key_reserved = 0;
605 
606 			setvarbuf(&m_len,
607 				(struct sadb_ext *)&m_key, sizeof(m_key),
608 				(caddr_t)p_key_enc, p_key_enc_len);
609 		}
610 
611 		/* set authentication algorithm, if present. */
612 		if (p_alg_auth != SADB_AALG_NONE) {
613 			struct sadb_key m_key;
614 
615 			m_key.sadb_key_len =
616 				PFKEY_UNIT64(sizeof(m_key)
617 				           + PFKEY_ALIGN8(p_key_auth_len));
618 			m_key.sadb_key_exttype = SADB_EXT_KEY_AUTH;
619 			m_key.sadb_key_bits = p_key_auth_len * 8;
620 			m_key.sadb_key_reserved = 0;
621 
622 			setvarbuf(&m_len,
623 				(struct sadb_ext *)&m_key, sizeof(m_key),
624 				(caddr_t)p_key_auth, p_key_auth_len);
625 		}
626 
627 		/* set lifetime for HARD */
628 		if (p_lt_hard != 0) {
629 			struct sadb_lifetime m_lt;
630 			u_int len = sizeof(struct sadb_lifetime);
631 
632 			m_lt.sadb_lifetime_len = PFKEY_UNIT64(len);
633 			m_lt.sadb_lifetime_exttype = SADB_EXT_LIFETIME_HARD;
634 			m_lt.sadb_lifetime_allocations = 0;
635 			m_lt.sadb_lifetime_bytes = 0;
636 			m_lt.sadb_lifetime_addtime = p_lt_hard;
637 			m_lt.sadb_lifetime_usetime = 0;
638 
639 			memcpy(m_buf + m_len, &m_lt, len);
640 			m_len += len;
641 		}
642 
643 		/* set lifetime for SOFT */
644 		if (p_lt_soft != 0) {
645 			struct sadb_lifetime m_lt;
646 			u_int len = sizeof(struct sadb_lifetime);
647 
648 			m_lt.sadb_lifetime_len = PFKEY_UNIT64(len);
649 			m_lt.sadb_lifetime_exttype = SADB_EXT_LIFETIME_SOFT;
650 			m_lt.sadb_lifetime_allocations = 0;
651 			m_lt.sadb_lifetime_bytes = 0;
652 			m_lt.sadb_lifetime_addtime = p_lt_soft;
653 			m_lt.sadb_lifetime_usetime = 0;
654 
655 			memcpy(m_buf + m_len, &m_lt, len);
656 			m_len += len;
657 		}
658 		/* FALLTHROUGH */
659 
660 	case SADB_DELETE:
661 	case SADB_GET:
662 	    {
663 		struct sadb_sa m_sa;
664 		struct sadb_x_sa2 m_sa2;
665 		struct sadb_address m_addr;
666 		u_int len;
667 
668 		len = sizeof(struct sadb_sa);
669 		m_sa.sadb_sa_len = PFKEY_UNIT64(len);
670 		m_sa.sadb_sa_exttype = SADB_EXT_SA;
671 		m_sa.sadb_sa_spi = htonl(p_spi);
672 		m_sa.sadb_sa_replay = p_replay;
673 		m_sa.sadb_sa_state = 0;
674 		m_sa.sadb_sa_auth = p_alg_auth;
675 		m_sa.sadb_sa_encrypt = p_alg_enc;
676 		m_sa.sadb_sa_flags = p_ext;
677 
678 		memcpy(m_buf + m_len, &m_sa, len);
679 		m_len += len;
680 
681 		len = sizeof(struct sadb_x_sa2);
682 		m_sa2.sadb_x_sa2_len = PFKEY_UNIT64(len);
683 		m_sa2.sadb_x_sa2_exttype = SADB_X_EXT_SA2;
684 		m_sa2.sadb_x_sa2_mode = p_mode;
685 		m_sa2.sadb_x_sa2_reqid = p_reqid;
686 
687 		memcpy(m_buf + m_len, &m_sa2, len);
688 		m_len += len;
689 
690 		/* set src */
691 		m_addr.sadb_address_len =
692 			PFKEY_UNIT64(sizeof(m_addr)
693 			           + PFKEY_ALIGN8(p_src->sa_len));
694 		m_addr.sadb_address_exttype = SADB_EXT_ADDRESS_SRC;
695 		m_addr.sadb_address_proto = IPSEC_ULPROTO_ANY;
696 		switch (p_src->sa_family) {
697 		case AF_INET:
698 			m_addr.sadb_address_prefixlen =
699 			    sizeof(struct in_addr) << 3;
700 			break;
701 #ifdef INET6
702 		case AF_INET6:
703 			m_addr.sadb_address_prefixlen =
704 			    sizeof(struct in6_addr) << 3;
705 			break;
706 #endif
707 		default:
708 			yyerror("unsupported address family");
709 			exit(1);	/*XXX*/
710 		}
711 		m_addr.sadb_address_reserved = 0;
712 
713 		setvarbuf(&m_len,
714 			(struct sadb_ext *)&m_addr, sizeof(m_addr),
715 			(caddr_t)p_src, p_src->sa_len);
716 
717 		/* set dst */
718 		m_addr.sadb_address_len =
719 			PFKEY_UNIT64(sizeof(m_addr)
720 			           + PFKEY_ALIGN8(p_dst->sa_len));
721 		m_addr.sadb_address_exttype = SADB_EXT_ADDRESS_DST;
722 		m_addr.sadb_address_proto = IPSEC_ULPROTO_ANY;
723 		switch (p_dst->sa_family) {
724 		case AF_INET:
725 			m_addr.sadb_address_prefixlen =
726 			    sizeof(struct in_addr) << 3;
727 			break;
728 #ifdef INET6
729 		case AF_INET6:
730 			m_addr.sadb_address_prefixlen =
731 			    sizeof(struct in6_addr) << 3;
732 			break;
733 #endif
734 		default:
735 			yyerror("unsupported address family");
736 			exit(1);	/*XXX*/
737 		}
738 		m_addr.sadb_address_reserved = 0;
739 
740 		setvarbuf(&m_len,
741 			(struct sadb_ext *)&m_addr, sizeof(m_addr),
742 			(caddr_t)p_dst, p_dst->sa_len);
743 	    }
744 		break;
745 
746 	/* for SPD management */
747 	case SADB_X_SPDFLUSH:
748 	case SADB_X_SPDDUMP:
749 		break;
750 
751 	case SADB_X_SPDADD:
752 	case SADB_X_SPDDELETE:
753 	    {
754 		struct sadb_address m_addr;
755 		u_int8_t plen;
756 
757 		memcpy(m_buf + m_len, p_policy, p_policy_len);
758 		m_len += p_policy_len;
759 		free(p_policy);
760 		p_policy = NULL;
761 
762 		/* set src */
763 		m_addr.sadb_address_len =
764 			PFKEY_UNIT64(sizeof(m_addr)
765 			           + PFKEY_ALIGN8(p_src->sa_len));
766 		m_addr.sadb_address_exttype = SADB_EXT_ADDRESS_SRC;
767 		m_addr.sadb_address_proto = p_upper;
768 		switch (p_src->sa_family) {
769 		case AF_INET:
770 			plen = sizeof(struct in_addr) << 3;
771 			break;
772 #ifdef INET6
773 		case AF_INET6:
774 			plen = sizeof(struct in6_addr) << 3;
775 			break;
776 #endif
777 		default:
778 			yyerror("unsupported address family");
779 			exit(1);	/*XXX*/
780 		}
781 		m_addr.sadb_address_prefixlen =
782 		    (p_prefs != ~0 ? p_prefs : plen);
783 		m_addr.sadb_address_reserved = 0;
784 
785 		setvarbuf(&m_len,
786 			(struct sadb_ext *)&m_addr, sizeof(m_addr),
787 			(caddr_t)p_src, p_src->sa_len);
788 
789 		/* set dst */
790 		m_addr.sadb_address_len =
791 			PFKEY_UNIT64(sizeof(m_addr)
792 			           + PFKEY_ALIGN8(p_dst->sa_len));
793 		m_addr.sadb_address_exttype = SADB_EXT_ADDRESS_DST;
794 		m_addr.sadb_address_proto = p_upper;
795 		switch (p_dst->sa_family) {
796 		case AF_INET:
797 			plen = sizeof(struct in_addr) << 3;
798 			break;
799 #ifdef INET6
800 		case AF_INET6:
801 			plen = sizeof(struct in6_addr) << 3;
802 			break;
803 #endif
804 		default:
805 			yyerror("unsupported address family");
806 			exit(1);	/*XXX*/
807 		}
808 		m_addr.sadb_address_prefixlen =
809 		    (p_prefd != ~0 ? p_prefd : plen);
810 		m_addr.sadb_address_reserved = 0;
811 
812 		setvarbuf(&m_len,
813 			(struct sadb_ext *)&m_addr, sizeof(m_addr),
814 			(caddr_t)p_dst, p_dst->sa_len);
815 	    }
816 		break;
817 	}
818 
819 	((struct sadb_msg *)m_buf)->sadb_msg_len = PFKEY_UNIT64(m_len);
820 
821 	return 0;
822 }
823 
824 static struct addrinfo *
825 parse_addr(host, port, flag)
826 	char *host;
827 	char *port;
828 	int flag;
829 {
830 	struct addrinfo hints, *res = NULL;
831 	int error;
832 
833 	memset(&hints, 0, sizeof(hints));
834 	hints.ai_family = PF_UNSPEC;
835 	hints.ai_socktype = SOCK_DGRAM;
836 	hints.ai_flags = flag;
837 	error = getaddrinfo(host, port, &hints, &res);
838 	if (error != 0) {
839 		yyerror(gai_strerror(error));
840 		return NULL;
841 	}
842 	if (res->ai_next != NULL) {
843 		yyerror(gai_strerror(error));
844 	}
845 	return res;
846 }
847 
848 static int
849 setvarbuf(off, ebuf, elen, vbuf, vlen)
850 	caddr_t vbuf;
851 	struct sadb_ext *ebuf;
852 	int *off, elen, vlen;
853 {
854 	memset(m_buf + *off, 0, PFKEY_UNUNIT64(ebuf->sadb_ext_len));
855 	memcpy(m_buf + *off, (caddr_t)ebuf, elen);
856 	memcpy(m_buf + *off + elen, vbuf, vlen);
857 	(*off) += PFKEY_ALIGN8(elen + vlen);
858 
859 	return 0;
860 }
861 
862 void
863 parse_init()
864 {
865 	p_type = 0;
866 	p_spi = 0;
867 
868 	p_src = 0, p_dst = 0;
869 	pp_prefix = p_prefs = p_prefd = ~0;
870 	pp_port = IPSEC_PORT_ANY;
871 	p_upper = 0;
872 
873 	p_satype = 0;
874 	p_ext = SADB_X_EXT_CYCSEQ;
875 	p_alg_enc = SADB_EALG_NONE;
876 	p_alg_auth = SADB_AALG_NONE;
877 	p_mode = IPSEC_MODE_ANY;
878 	p_reqid = 0;
879 	p_replay = 0;
880 	p_key_enc_len = p_key_auth_len = 0;
881 	p_key_enc = p_key_auth = 0;
882 	p_lt_hard = p_lt_soft = 0;
883 
884 	p_policy_len = 0;
885 	p_policy = NULL;
886 
887 	memset(cmdarg, 0, sizeof(cmdarg));
888 
889 	return;
890 }
891 
892 void
893 free_buffer()
894 {
895 	if (p_src) free(p_src);
896 	if (p_dst) free(p_dst);
897 	if (p_key_enc) free(p_key_enc);
898 	if (p_key_auth) free(p_key_auth);
899 
900 	return;
901 }
902 
903