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