1/*	$FreeBSD: src/usr.sbin/setkey/parse.y,v 1.3 2001/06/11 12:39:28 ume Exp $	*/
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 <netinet/in.h>
39#include <net/pfkeyv2.h>
40#include <netinet/ipsec.h>
41#include <arpa/inet.h>
42
43#include <string.h>
44#include <stdlib.h>
45#include <unistd.h>
46#include <stdio.h>
47#include <netdb.h>
48#include <ctype.h>
49#include <errno.h>
50#include <malloc.h>
51
52#include "libpfkey.h"
53#include "libipsec.h"
54#include "vchar.h"
55
56#define ATOX(c) \
57  (isdigit(c) ? (c - '0') : (isupper(c) ? (c - 'A' + 10) : (c - 'a' + 10) ))
58
59u_int p_type;
60u_int32_t p_spi;
61int p_no_spi;
62struct sockaddr *p_src, *p_dst;
63u_int p_prefs, p_prefd, p_upper;
64u_int p_satype, p_ext, p_alg_enc, p_alg_auth, p_replay, p_mode;
65u_int32_t p_reqid;
66u_int p_key_enc_len, p_key_auth_len;
67caddr_t p_key_enc, p_key_auth;
68time_t p_lt_hard, p_lt_soft;
69
70u_int p_policy_len;
71char *p_policy;
72
73/* temporary buffer */
74static struct sockaddr *pp_addr;
75static u_int pp_prefix;
76static u_int pp_port;
77static caddr_t pp_key;
78
79extern u_char m_buf[BUFSIZ];
80extern int m_len;
81extern char cmdarg[8192];
82extern int f_debug;
83
84static struct addrinfo *parse_addr __P((char *, char *, int));
85static int setvarbuf __P((int *, struct sadb_ext *, int, caddr_t, int));
86void parse_init __P((void));
87void free_buffer __P((void));
88
89extern int setkeymsg __P((void));
90extern int sendkeymsg __P((void));
91
92extern int yylex __P((void));
93extern void yyfatal __P((const char *));
94extern void yyerror __P((const char *));
95%}
96
97%union {
98	unsigned long num;
99	vchar_t val;
100}
101
102%token EOT
103%token ADD GET DELETE FLUSH DUMP
104%token ADDRESS PREFIX PORT PORTANY
105%token UP_PROTO PR_ESP PR_AH PR_IPCOMP
106%token F_PROTOCOL F_AUTH F_ENC F_REPLAY F_COMP F_RAWCPI
107%token F_MODE MODE F_REQID
108%token F_EXT EXTENSION NOCYCLICSEQ
109%token ALG_AUTH ALG_ENC ALG_ENC_DESDERIV ALG_ENC_DES32IV ALG_COMP
110%token F_LIFETIME_HARD F_LIFETIME_SOFT
111%token DECSTRING QUOTEDSTRING HEXSTRING STRING ANY
112	/* SPD management */
113%token SPDADD SPDDELETE SPDDUMP SPDFLUSH
114%token F_POLICY PL_REQUESTS DELETEALL
115
116%type <num> PORT PREFIX EXTENSION MODE
117%type <num> UP_PROTO PR_ESP PR_AH PR_IPCOMP
118%type <num> ALG_AUTH ALG_ENC ALG_ENC_DESDERIV ALG_ENC_DES32IV ALG_COMP
119%type <num> DECSTRING
120%type <val> ADDRESS PL_REQUESTS
121%type <val> key_string policy_requests
122%type <val> QUOTEDSTRING HEXSTRING STRING
123
124%%
125commands
126	:	/*NOTHING*/
127	|	commands command
128		{
129			if (f_debug) {
130				printf("cmdarg:\n%s\n", cmdarg);
131			} else {
132				setkeymsg();
133				sendkeymsg();
134			}
135			free_buffer();
136			parse_init();
137		}
138	;
139
140command
141	:	add_command
142	|	get_command
143	|	delete_command
144	|	deleteall_command
145	|	flush_command
146	|	dump_command
147	|	spdadd_command
148	|	spddelete_command
149	|	spddump_command
150	|	spdflush_command
151	;
152	/* commands concerned with management, there is in tail of this file. */
153
154	/* add command */
155add_command
156	:	ADD { p_type = SADB_ADD; }
157		sa_selector_spec extension_spec algorithm_spec EOT
158	;
159
160	/* delete */
161delete_command
162	:	DELETE { p_type = SADB_DELETE; }
163		sa_selector_spec extension_spec
164		{
165			if (p_mode != IPSEC_MODE_ANY)
166				yyerror("WARNING: mode is obsoleted.");
167		}
168		EOT
169	;
170
171	/* deleteall command */
172deleteall_command
173	:	DELETEALL { p_type = SADB_DELETE; }
174		ipaddress { p_src = pp_addr; }
175		ipaddress { p_dst = pp_addr; }
176		protocol_spec
177		{ p_no_spi = 1; }
178		EOT
179	;
180
181	/* get command */
182get_command
183	:	GET { p_type = SADB_GET; }
184		sa_selector_spec extension_spec
185		{
186			if (p_mode != IPSEC_MODE_ANY)
187				yyerror("WARNING: mode is obsoleted.");
188		}
189		EOT
190	;
191
192	/* flush */
193flush_command
194	:	FLUSH { p_type = SADB_FLUSH; }
195		protocol_spec EOT
196	;
197
198	/* dump */
199dump_command
200	:	DUMP { p_type = SADB_DUMP; }
201		protocol_spec EOT
202	;
203
204	/* sa_selector_spec */
205sa_selector_spec
206	:	ipaddress { p_src = pp_addr; }
207		ipaddress { p_dst = pp_addr; }
208		protocol_spec spi
209	;
210
211protocol_spec
212	:	/*NOTHING*/ { p_satype = SADB_SATYPE_UNSPEC; }
213	|	PR_ESP
214		{
215			p_satype = SADB_SATYPE_ESP;
216			if ($1 == 1)
217				p_ext |= SADB_X_EXT_OLD;
218			else
219				p_ext &= ~SADB_X_EXT_OLD;
220		}
221	|	PR_AH
222		{
223			p_satype = SADB_SATYPE_AH;
224			if ($1 == 1)
225				p_ext |= SADB_X_EXT_OLD;
226			else
227				p_ext &= ~SADB_X_EXT_OLD;
228		}
229	|	PR_IPCOMP
230		{
231			p_satype = SADB_X_SATYPE_IPCOMP;
232		}
233	;
234
235spi
236	:	DECSTRING { p_spi = $1; }
237	|	HEXSTRING
238		{
239			caddr_t bp;
240			caddr_t yp = $1.buf;
241			char buf0[4], buf[4];
242			int i, j;
243
244			/* sanity check */
245			if ($1.len > 4) {
246				yyerror("SPI too big.");
247				free($1.buf);
248				return -1;
249			}
250
251			bp = buf0;
252			while (*yp) {
253				*bp = (ATOX(yp[0]) << 4) | ATOX(yp[1]);
254				yp += 2, bp++;
255			}
256
257			/* initialize */
258			for (i = 0; i < 4; i++) buf[i] = 0;
259
260			for (j = $1.len - 1, i = 3; j >= 0; j--, i--)
261				buf[i] = buf0[j];
262
263			/* XXX: endian */
264			p_spi = ntohl(*(u_int32_t *)buf);
265
266			free($1.buf);
267		}
268	;
269
270algorithm_spec
271	:	esp_spec
272	|	ah_spec
273	|	ipcomp_spec
274	;
275
276esp_spec
277	:	F_ENC enc_alg enc_key F_AUTH auth_alg auth_key
278	|	F_ENC enc_alg enc_key
279	;
280
281ah_spec
282	:	F_AUTH auth_alg auth_key
283	;
284
285ipcomp_spec
286	:	F_COMP ALG_COMP { p_alg_enc = $2; }
287	|	F_COMP ALG_COMP { p_alg_enc = $2; }
288		F_RAWCPI { p_ext |= SADB_X_EXT_RAWCPI; }
289	;
290
291enc_alg
292	:	ALG_ENC { p_alg_enc = $1; }
293	|	ALG_ENC_DESDERIV
294		{
295			p_alg_enc = $1;
296			if (p_ext & SADB_X_EXT_OLD) {
297				yyerror("algorithm mismatched.");
298				return -1;
299			}
300			p_ext |= SADB_X_EXT_DERIV;
301		}
302	|	ALG_ENC_DES32IV
303		{
304			p_alg_enc = $1;
305			if (!(p_ext & SADB_X_EXT_OLD)) {
306				yyerror("algorithm mismatched.");
307				return -1;
308			}
309			p_ext |= SADB_X_EXT_IV4B;
310		}
311	;
312
313enc_key
314	:	/*NOTHING*/
315		{
316			if (p_alg_enc != SADB_EALG_NULL) {
317				yyerror("no key found.");
318				return -1;
319			}
320		}
321	|	key_string
322		{
323			p_key_enc_len = $1.len;
324			p_key_enc = pp_key;
325
326			if (ipsec_check_keylen(SADB_EXT_SUPPORTED_ENCRYPT,
327					p_alg_enc,
328					PFKEY_UNUNIT64(p_key_enc_len)) < 0) {
329				yyerror(ipsec_strerror());
330				return -1;
331			}
332		}
333	;
334
335auth_alg
336	:	ALG_AUTH { p_alg_auth = $1; }
337	;
338
339auth_key
340	:	/*NOTHING*/
341		{
342			if (p_alg_auth != SADB_X_AALG_NULL) {
343				yyerror("no key found.");
344				return -1;
345			}
346		}
347	|	key_string
348		{
349			p_key_auth_len = $1.len;
350			p_key_auth = pp_key;
351
352			if (ipsec_check_keylen(SADB_EXT_SUPPORTED_AUTH,
353					p_alg_auth,
354					PFKEY_UNUNIT64(p_key_auth_len)) < 0) {
355				yyerror(ipsec_strerror());
356				return -1;
357			}
358		}
359	;
360
361key_string
362	:	QUOTEDSTRING
363		{
364			pp_key = $1.buf;
365			/* free pp_key later */
366		}
367	|	HEXSTRING
368		{
369			caddr_t bp;
370			caddr_t yp = $1.buf;
371
372			if ((pp_key = malloc($1.len)) == 0) {
373				free($1.buf);
374				yyerror("not enough core");
375				return -1;
376			}
377			memset(pp_key, 0, $1.len);
378
379			bp = pp_key;
380			while (*yp) {
381				*bp = (ATOX(yp[0]) << 4) | ATOX(yp[1]);
382				yp += 2, bp++;
383			}
384
385			free($1.buf);
386		}
387	;
388
389extension_spec
390	:	/*NOTHING*/
391	|	extension_spec extension
392	;
393
394extension
395	:	F_EXT EXTENSION { p_ext |= $2; }
396	|	F_EXT NOCYCLICSEQ { p_ext &= ~SADB_X_EXT_CYCSEQ; }
397	|	F_MODE MODE { p_mode = $2; }
398	|	F_MODE ANY { p_mode = IPSEC_MODE_ANY; }
399	|	F_REQID DECSTRING { p_reqid = $2; }
400	|	F_REPLAY DECSTRING
401		{
402			if (p_ext & SADB_X_EXT_OLD) {
403				yyerror("replay prevention "
404				        "only use on new spec.");
405				return -1;
406			}
407			p_replay = $2;
408		}
409	|	F_LIFETIME_HARD DECSTRING { p_lt_hard = $2; }
410	|	F_LIFETIME_SOFT DECSTRING { p_lt_soft = $2; }
411	;
412
413	/* definition about command for SPD management */
414	/* spdadd */
415spdadd_command
416	:	SPDADD
417		{
418			p_type = SADB_X_SPDADD;
419			p_satype = SADB_SATYPE_UNSPEC;
420		}
421		sp_selector_spec policy_spec EOT
422	;
423
424spddelete_command:
425		SPDDELETE
426		{
427			p_type = SADB_X_SPDDELETE;
428			p_satype = SADB_SATYPE_UNSPEC;
429		}
430		sp_selector_spec policy_spec EOT
431	;
432
433spddump_command:
434		SPDDUMP
435		{
436			p_type = SADB_X_SPDDUMP;
437			p_satype = SADB_SATYPE_UNSPEC;
438		}
439		EOT
440	;
441
442spdflush_command:
443		SPDFLUSH
444		{
445			p_type = SADB_X_SPDFLUSH;
446			p_satype = SADB_SATYPE_UNSPEC;
447		}
448		EOT
449	;
450
451	/* sp_selector_spec */
452sp_selector_spec
453	:	ipaddress { p_src = pp_addr; }
454		prefix { p_prefs = pp_prefix; }
455		port
456		{
457			switch (p_src->sa_family) {
458			case AF_INET:
459				((struct sockaddr_in *)p_src)->sin_port =
460				    htons(pp_port);
461				break;
462#ifdef INET6
463			case AF_INET6:
464				((struct sockaddr_in6 *)p_src)->sin6_port =
465				    htons(pp_port);
466				break;
467#endif
468			default:
469				exit(1); /*XXX*/
470			}
471		}
472		ipaddress { p_dst = pp_addr; }
473		prefix { p_prefd = pp_prefix; }
474		port
475		{
476			switch (p_dst->sa_family) {
477			case AF_INET:
478				((struct sockaddr_in *)p_dst)->sin_port =
479				    htons(pp_port);
480				break;
481#ifdef INET6
482			case AF_INET6:
483				((struct sockaddr_in6 *)p_dst)->sin6_port =
484				    htons(pp_port);
485				break;
486#endif
487			default:
488				exit(1); /*XXX*/
489			}
490		}
491		upper_spec
492		{
493			/* XXX is it something userland should check? */
494#if 0
495			switch (p_upper) {
496			case IPPROTO_ICMP:
497			case IPPROTO_ICMPV6:
498				if (_INPORTBYSA(p_src) != IPSEC_PORT_ANY
499				 || _INPORTBYSA(p_dst) != IPSEC_PORT_ANY) {
500					yyerror("port number must be \"any\".");
501					return -1;
502				}
503				if ((pp_addr->sa_family == AF_INET6
504				  && p_upper == IPPROTO_ICMP)
505				 || (pp_addr->sa_family == AF_INET
506				  && p_upper == IPPROTO_ICMPV6)) {
507					yyerror("upper layer protocol "
508						"mismatched.\n");
509					return -1;
510				}
511				break;
512			default:
513				break;
514			}
515#endif
516		}
517	;
518
519ipaddress
520	:	ADDRESS
521		{
522			struct addrinfo *res;
523
524			res = parse_addr($1.buf, NULL, AI_NUMERICHOST);
525			if (res == NULL) {
526				free($1.buf);
527				return -1;
528			}
529			pp_addr = (struct sockaddr *)malloc(res->ai_addrlen);
530			if (!pp_addr) {
531				yyerror("not enough core");
532				goto end;
533			}
534
535			memcpy(pp_addr, res->ai_addr, res->ai_addrlen);
536		    end:
537			freeaddrinfo(res);
538			free($1.buf);
539		}
540	;
541
542prefix
543	:	/*NOTHING*/ { pp_prefix = ~0; }
544	|	PREFIX { pp_prefix = $1; }
545	;
546
547port
548	:	/*NOTHING*/ { pp_port = IPSEC_PORT_ANY; }
549	|	PORT { pp_port = $1; }
550	|	PORTANY { pp_port = IPSEC_PORT_ANY; }
551	;
552
553upper_spec
554	:	DECSTRING { p_upper = $1; }
555	|	UP_PROTO { p_upper = $1; }
556	|	ANY { p_upper = IPSEC_ULPROTO_ANY; }
557	|	STRING
558		{
559			struct protoent *ent;
560
561			ent = getprotobyname($1.buf);
562			if (ent)
563				p_upper = ent->p_proto;
564			else {
565				if (strcmp("icmp6", $1.buf) == 0) {
566					p_upper = IPPROTO_ICMPV6;
567				} else if(strcmp("ip4", $1.buf) == 0) {
568					p_upper = IPPROTO_IPV4;
569				} else {
570					yyerror("invalid upper layer protocol");
571					free($1.buf);
572					return -1;
573				}
574			}
575			free($1.buf);
576		}
577	;
578
579policy_spec
580	:	F_POLICY policy_requests
581		{
582			p_policy = ipsec_set_policy($2.buf, $2.len);
583			if (p_policy == NULL) {
584				free($2.buf);
585				p_policy = NULL;
586				yyerror(ipsec_strerror());
587				return -1;
588			}
589
590			p_policy_len = ipsec_get_policylen(p_policy);
591
592			free($2.buf);
593		}
594	;
595
596policy_requests
597	:	PL_REQUESTS { $$ = $1; }
598;
599%%
600
601int
602setkeymsg()
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(sysdep_sa_len(p_src)));
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, sysdep_sa_len(p_src));
746
747		/* set dst */
748		m_addr.sadb_address_len =
749			PFKEY_UNIT64(sizeof(m_addr)
750			           + PFKEY_ALIGN8(sysdep_sa_len(p_dst)));
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, sysdep_sa_len(p_dst));
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(sysdep_sa_len(p_src)));
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, sysdep_sa_len(p_src));
818
819		/* set dst */
820		m_addr.sadb_address_len =
821			PFKEY_UNIT64(sizeof(m_addr)
822			           + PFKEY_ALIGN8(sysdep_sa_len(p_dst)));
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, sysdep_sa_len(p_dst));
845	    }
846		break;
847	}
848
849	((struct sadb_msg *)m_buf)->sadb_msg_len = PFKEY_UNIT64(m_len);
850
851	return 0;
852}
853
854static struct addrinfo *
855parse_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
878static int
879setvarbuf(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
892void
893parse_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
923void
924free_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