162583Sitojun/*	$FreeBSD$	*/
2151293Sume/*	$KAME: parse.y,v 1.83 2004/05/18 08:48:23 sakane Exp $	*/
362583Sitojun
455505Sshin/*
555505Sshin * Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project.
655505Sshin * All rights reserved.
762583Sitojun *
855505Sshin * Redistribution and use in source and binary forms, with or without
955505Sshin * modification, are permitted provided that the following conditions
1055505Sshin * are met:
1155505Sshin * 1. Redistributions of source code must retain the above copyright
1255505Sshin *    notice, this list of conditions and the following disclaimer.
1355505Sshin * 2. Redistributions in binary form must reproduce the above copyright
1455505Sshin *    notice, this list of conditions and the following disclaimer in the
1555505Sshin *    documentation and/or other materials provided with the distribution.
1655505Sshin * 3. Neither the name of the project nor the names of its contributors
1755505Sshin *    may be used to endorse or promote products derived from this software
1855505Sshin *    without specific prior written permission.
1962583Sitojun *
2055505Sshin * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
2155505Sshin * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2255505Sshin * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2355505Sshin * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
2455505Sshin * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2555505Sshin * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2655505Sshin * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2755505Sshin * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2855505Sshin * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2955505Sshin * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3055505Sshin * SUCH DAMAGE.
3155505Sshin */
3255505Sshin
3355505Sshin%{
3455505Sshin#include <sys/types.h>
3555505Sshin#include <sys/param.h>
3655505Sshin#include <sys/socket.h>
3755505Sshin
3855505Sshin#include <net/route.h>
3955505Sshin#include <netinet/in.h>
4055505Sshin#include <net/pfkeyv2.h>
41171135Sgnn#include <netipsec/key_var.h>
42171135Sgnn#include <netipsec/ipsec.h>
4355505Sshin#include <arpa/inet.h>
4455505Sshin
4555505Sshin#include <string.h>
4655505Sshin#include <unistd.h>
4755505Sshin#include <stdio.h>
4862583Sitojun#include <netdb.h>
4955505Sshin#include <ctype.h>
5055505Sshin#include <errno.h>
5155505Sshin
5262583Sitojun#include "libpfkey.h"
5355505Sshin#include "vchar.h"
5455505Sshin
5555505Sshin#define ATOX(c) \
56122108Sume  (isdigit(c) ? (c - '0') : (isupper(c) ? (c - 'A' + 10) : (c - 'a' + 10)))
5755505Sshin
5862583Sitojunu_int32_t p_spi;
59122108Sumeu_int p_ext, p_alg_enc, p_alg_auth, p_replay, p_mode;
6062583Sitojunu_int32_t p_reqid;
6162583Sitojunu_int p_key_enc_len, p_key_auth_len;
6262583Sitojuncaddr_t p_key_enc, p_key_auth;
6362583Sitojuntime_t p_lt_hard, p_lt_soft;
6455505Sshin
65122108Sumestatic int p_aiflags = 0, p_aifamily = PF_UNSPEC;
6655505Sshin
67173412Skevlostatic struct addrinfo *parse_addr(char *, char *);
68173412Skevlostatic int fix_portstr(vchar_t *, vchar_t *, vchar_t *);
69173412Skevlostatic int setvarbuf(char *, int *, struct sadb_ext *, int, caddr_t, int);
70173412Skevlovoid parse_init(void);
71173412Skevlovoid free_buffer(void);
7255505Sshin
73173412Skevloint setkeymsg0(struct sadb_msg *, unsigned int, unsigned int, size_t);
74173412Skevlostatic int setkeymsg_spdaddr(unsigned int, unsigned int, vchar_t *,
75173412Skevlo	struct addrinfo *, int, struct addrinfo *, int);
76173412Skevlostatic int setkeymsg_addr(unsigned int, unsigned int,
77173412Skevlo	struct addrinfo *, struct addrinfo *, int);
78173412Skevlostatic int setkeymsg_add(unsigned int, unsigned int,
79173412Skevlo	struct addrinfo *, struct addrinfo *);
80173412Skevloextern int setkeymsg(char *, size_t *);
81173412Skevloextern int sendkeymsg(char *, size_t);
8255505Sshin
83173412Skevloextern int yylex(void);
84173412Skevloextern void yyfatal(const char *);
85173412Skevloextern void yyerror(const char *);
8655505Sshin%}
8755505Sshin
8855505Sshin%union {
89122108Sume	int num;
90122108Sume	unsigned long ulnum;
9155505Sshin	vchar_t val;
92122108Sume	struct addrinfo *res;
9355505Sshin}
9455505Sshin
95122108Sume%token EOT SLASH BLCL ELCL
96122108Sume%token ADD GET DELETE DELETEALL FLUSH DUMP
97125681Sbms%token PR_ESP PR_AH PR_IPCOMP PR_TCP
9855505Sshin%token F_PROTOCOL F_AUTH F_ENC F_REPLAY F_COMP F_RAWCPI
9962583Sitojun%token F_MODE MODE F_REQID
10062583Sitojun%token F_EXT EXTENSION NOCYCLICSEQ
101122108Sume%token ALG_AUTH ALG_AUTH_NOKEY
102122108Sume%token ALG_ENC ALG_ENC_NOKEY ALG_ENC_DESDERIV ALG_ENC_DES32IV ALG_ENC_OLD
103122108Sume%token ALG_COMP
10455505Sshin%token F_LIFETIME_HARD F_LIFETIME_SOFT
10578064Sume%token DECSTRING QUOTEDSTRING HEXSTRING STRING ANY
10655505Sshin	/* SPD management */
10755505Sshin%token SPDADD SPDDELETE SPDDUMP SPDFLUSH
10855505Sshin%token F_POLICY PL_REQUESTS
109122108Sume%token F_AIFLAGS
110122108Sume%token TAGGED
11155505Sshin
112122108Sume%type <num> prefix protocol_spec upper_spec
113122108Sume%type <num> ALG_ENC ALG_ENC_DESDERIV ALG_ENC_DES32IV ALG_ENC_OLD ALG_ENC_NOKEY
114122108Sume%type <num> ALG_AUTH ALG_AUTH_NOKEY
115122108Sume%type <num> ALG_COMP
116125681Sbms%type <num> PR_ESP PR_AH PR_IPCOMP PR_TCP
117122108Sume%type <num> EXTENSION MODE
118122108Sume%type <ulnum> DECSTRING
119122108Sume%type <val> PL_REQUESTS portstr key_string
120122108Sume%type <val> policy_requests
12178064Sume%type <val> QUOTEDSTRING HEXSTRING STRING
122122108Sume%type <val> F_AIFLAGS
123122108Sume%type <val> upper_misc_spec policy_spec
124122108Sume%type <res> ipaddr
12562583Sitojun
12655505Sshin%%
12755505Sshincommands
12855505Sshin	:	/*NOTHING*/
12955505Sshin	|	commands command
13055505Sshin		{
13155505Sshin			free_buffer();
13255505Sshin			parse_init();
13355505Sshin		}
13455505Sshin	;
13555505Sshin
13655505Sshincommand
13755505Sshin	:	add_command
13855505Sshin	|	get_command
13955505Sshin	|	delete_command
14078064Sume	|	deleteall_command
14155505Sshin	|	flush_command
14255505Sshin	|	dump_command
14355505Sshin	|	spdadd_command
14455505Sshin	|	spddelete_command
14555505Sshin	|	spddump_command
14655505Sshin	|	spdflush_command
14755505Sshin	;
14855505Sshin	/* commands concerned with management, there is in tail of this file. */
14955505Sshin
15055505Sshin	/* add command */
15155505Sshinadd_command
152122108Sume	:	ADD ipaddropts ipaddr ipaddr protocol_spec spi extension_spec algorithm_spec EOT
153122108Sume		{
154122108Sume			int status;
155122108Sume
156122108Sume			status = setkeymsg_add(SADB_ADD, $5, $3, $4);
157122108Sume			if (status < 0)
158122108Sume				return -1;
159122108Sume		}
16055505Sshin	;
16155505Sshin
16255505Sshin	/* delete */
16355505Sshindelete_command
164122108Sume	:	DELETE ipaddropts ipaddr ipaddr protocol_spec spi extension_spec EOT
16562583Sitojun		{
166122108Sume			int status;
167122108Sume
168122108Sume			if ($3->ai_next || $4->ai_next) {
169122108Sume				yyerror("multiple address specified");
170122108Sume				return -1;
171122108Sume			}
17262583Sitojun			if (p_mode != IPSEC_MODE_ANY)
173122108Sume				yyerror("WARNING: mode is obsolete");
174122108Sume
175122108Sume			status = setkeymsg_addr(SADB_DELETE, $5, $3, $4, 0);
176122108Sume			if (status < 0)
177122108Sume				return -1;
17862583Sitojun		}
17955505Sshin	;
18055505Sshin
18178064Sume	/* deleteall command */
18278064Sumedeleteall_command
183122108Sume	:	DELETEALL ipaddropts ipaddr ipaddr protocol_spec EOT
184122108Sume		{
185122108Sume			int status;
186122108Sume
187122108Sume			status = setkeymsg_addr(SADB_DELETE, $5, $3, $4, 1);
188122108Sume			if (status < 0)
189122108Sume				return -1;
190122108Sume		}
19178064Sume	;
19278064Sume
19355505Sshin	/* get command */
19455505Sshinget_command
195122108Sume	:	GET ipaddropts ipaddr ipaddr protocol_spec spi extension_spec EOT
19662583Sitojun		{
197122108Sume			int status;
198122108Sume
19962583Sitojun			if (p_mode != IPSEC_MODE_ANY)
200122108Sume				yyerror("WARNING: mode is obsolete");
201122108Sume
202122108Sume			status = setkeymsg_addr(SADB_GET, $5, $3, $4, 0);
203122108Sume			if (status < 0)
204122108Sume				return -1;
20562583Sitojun		}
20655505Sshin	;
20755505Sshin
20855505Sshin	/* flush */
20955505Sshinflush_command
210122108Sume	:	FLUSH protocol_spec EOT
211122108Sume		{
212122108Sume			struct sadb_msg msg;
213122108Sume			setkeymsg0(&msg, SADB_FLUSH, $2, sizeof(msg));
214122108Sume			sendkeymsg((char *)&msg, sizeof(msg));
215122108Sume		}
21655505Sshin	;
21755505Sshin
21855505Sshin	/* dump */
21955505Sshindump_command
220122108Sume	:	DUMP protocol_spec EOT
221122108Sume		{
222122108Sume			struct sadb_msg msg;
223122108Sume			setkeymsg0(&msg, SADB_DUMP, $2, sizeof(msg));
224122108Sume			sendkeymsg((char *)&msg, sizeof(msg));
225122108Sume		}
22655505Sshin	;
22755505Sshin
22855505Sshinprotocol_spec
229122108Sume	:	/*NOTHING*/
230122108Sume		{
231122108Sume			$$ = SADB_SATYPE_UNSPEC;
232122108Sume		}
23355505Sshin	|	PR_ESP
23455505Sshin		{
235122108Sume			$$ = SADB_SATYPE_ESP;
23662583Sitojun			if ($1 == 1)
23755505Sshin				p_ext |= SADB_X_EXT_OLD;
23855505Sshin			else
23955505Sshin				p_ext &= ~SADB_X_EXT_OLD;
24055505Sshin		}
24155505Sshin	|	PR_AH
24255505Sshin		{
243122108Sume			$$ = SADB_SATYPE_AH;
24462583Sitojun			if ($1 == 1)
24555505Sshin				p_ext |= SADB_X_EXT_OLD;
24655505Sshin			else
24755505Sshin				p_ext &= ~SADB_X_EXT_OLD;
24855505Sshin		}
24955505Sshin	|	PR_IPCOMP
25055505Sshin		{
251122108Sume			$$ = SADB_X_SATYPE_IPCOMP;
25255505Sshin		}
253125681Sbms	|	PR_TCP
254125681Sbms		{
255125681Sbms			$$ = SADB_X_SATYPE_TCPSIGNATURE;
256125681Sbms		}
25755505Sshin	;
258125681Sbms
25955505Sshinspi
26062583Sitojun	:	DECSTRING { p_spi = $1; }
26155505Sshin	|	HEXSTRING
26255505Sshin		{
263122108Sume			char *ep;
264122108Sume			unsigned long v;
26555505Sshin
266122108Sume			ep = NULL;
267122108Sume			v = strtoul($1.buf, &ep, 16);
268122108Sume			if (!ep || *ep) {
269122108Sume				yyerror("invalid SPI");
270122108Sume				return -1;
271122108Sume			}
272122108Sume			if (v & ~0xffffffff) {
27355505Sshin				yyerror("SPI too big.");
27455505Sshin				return -1;
27555505Sshin			}
27655505Sshin
277122108Sume			p_spi = v;
27855505Sshin		}
27955505Sshin	;
28055505Sshin
28155505Sshinalgorithm_spec
28255505Sshin	:	esp_spec
28355505Sshin	|	ah_spec
28455505Sshin	|	ipcomp_spec
28555505Sshin	;
28655505Sshin
28755505Sshinesp_spec
288122108Sume	:	F_ENC enc_alg F_AUTH auth_alg
289122108Sume	|	F_ENC enc_alg
29055505Sshin	;
29155505Sshin
29255505Sshinah_spec
293122108Sume	:	F_AUTH auth_alg
29455505Sshin	;
29555505Sshin
29655505Sshinipcomp_spec
297122108Sume	:	F_COMP ALG_COMP
298122108Sume		{
299122108Sume			if ($2 < 0) {
300122108Sume				yyerror("unsupported algorithm");
301122108Sume				return -1;
302122108Sume			}
303122108Sume			p_alg_enc = $2;
304122108Sume		}
305122108Sume	|	F_COMP ALG_COMP F_RAWCPI
306122108Sume		{
307122108Sume			if ($2 < 0) {
308122108Sume				yyerror("unsupported algorithm");
309122108Sume				return -1;
310122108Sume			}
311122108Sume			p_alg_enc = $2;
312122108Sume			p_ext |= SADB_X_EXT_RAWCPI;
313122108Sume		}
31455505Sshin	;
31555505Sshin
31655505Sshinenc_alg
317122108Sume	:	ALG_ENC_NOKEY {
318122108Sume			if ($1 < 0) {
319122108Sume				yyerror("unsupported algorithm");
320122108Sume				return -1;
321122108Sume			}
322122108Sume			p_alg_enc = $1;
323122108Sume
324122108Sume			p_key_enc_len = 0;
325122108Sume			p_key_enc = NULL;
326129183Sume			if (ipsec_check_keylen(SADB_EXT_SUPPORTED_ENCRYPT,
327129183Sume			    p_alg_enc, PFKEY_UNUNIT64(p_key_enc_len)) < 0) {
328129183Sume				yyerror(ipsec_strerror());
329129183Sume				return -1;
330129183Sume			}
331122108Sume		}
332122108Sume	|	ALG_ENC key_string {
333122108Sume			if ($1 < 0) {
334122108Sume				yyerror("unsupported algorithm");
335122108Sume				return -1;
336122108Sume			}
337122108Sume			p_alg_enc = $1;
338122108Sume
339122108Sume			p_key_enc_len = $2.len;
340122108Sume			p_key_enc = $2.buf;
341122108Sume			if (ipsec_check_keylen(SADB_EXT_SUPPORTED_ENCRYPT,
342122108Sume			    p_alg_enc, PFKEY_UNUNIT64(p_key_enc_len)) < 0) {
343122108Sume				yyerror(ipsec_strerror());
344122108Sume				return -1;
345122108Sume			}
346122108Sume		}
347122108Sume	|	ALG_ENC_OLD {
348122108Sume			if ($1 < 0) {
349122108Sume				yyerror("unsupported algorithm");
350122108Sume				return -1;
351122108Sume			}
352122108Sume			yyerror("WARNING: obsolete algorithm");
353122108Sume			p_alg_enc = $1;
354122108Sume
355122108Sume			p_key_enc_len = 0;
356122108Sume			p_key_enc = NULL;
357129183Sume			if (ipsec_check_keylen(SADB_EXT_SUPPORTED_ENCRYPT,
358129183Sume			    p_alg_enc, PFKEY_UNUNIT64(p_key_enc_len)) < 0) {
359129183Sume				yyerror(ipsec_strerror());
360129183Sume				return -1;
361129183Sume			}
362122108Sume		}
363122108Sume	|	ALG_ENC_DESDERIV key_string
36455505Sshin		{
365122108Sume			if ($1 < 0) {
366122108Sume				yyerror("unsupported algorithm");
367122108Sume				return -1;
368122108Sume			}
36962583Sitojun			p_alg_enc = $1;
37055505Sshin			if (p_ext & SADB_X_EXT_OLD) {
371122108Sume				yyerror("algorithm mismatched");
37255505Sshin				return -1;
37355505Sshin			}
37455505Sshin			p_ext |= SADB_X_EXT_DERIV;
375122108Sume
376122108Sume			p_key_enc_len = $2.len;
377122108Sume			p_key_enc = $2.buf;
378122108Sume			if (ipsec_check_keylen(SADB_EXT_SUPPORTED_ENCRYPT,
379122108Sume			    p_alg_enc, PFKEY_UNUNIT64(p_key_enc_len)) < 0) {
380122108Sume				yyerror(ipsec_strerror());
381122108Sume				return -1;
382122108Sume			}
38355505Sshin		}
384122108Sume	|	ALG_ENC_DES32IV key_string
38555505Sshin		{
386122108Sume			if ($1 < 0) {
387122108Sume				yyerror("unsupported algorithm");
388122108Sume				return -1;
389122108Sume			}
39062583Sitojun			p_alg_enc = $1;
39155505Sshin			if (!(p_ext & SADB_X_EXT_OLD)) {
392122108Sume				yyerror("algorithm mismatched");
39355505Sshin				return -1;
39455505Sshin			}
39555505Sshin			p_ext |= SADB_X_EXT_IV4B;
39655505Sshin
397122108Sume			p_key_enc_len = $2.len;
398122108Sume			p_key_enc = $2.buf;
39955505Sshin			if (ipsec_check_keylen(SADB_EXT_SUPPORTED_ENCRYPT,
400122108Sume			    p_alg_enc, PFKEY_UNUNIT64(p_key_enc_len)) < 0) {
40155505Sshin				yyerror(ipsec_strerror());
40255505Sshin				return -1;
40355505Sshin			}
40455505Sshin		}
40555505Sshin	;
40655505Sshin
40755505Sshinauth_alg
408122108Sume	:	ALG_AUTH key_string {
409122108Sume			if ($1 < 0) {
410122108Sume				yyerror("unsupported algorithm");
41155505Sshin				return -1;
41255505Sshin			}
413122108Sume			p_alg_auth = $1;
41455505Sshin
415122108Sume			p_key_auth_len = $2.len;
416122108Sume			p_key_auth = $2.buf;
417125681Sbms
418125681Sbms			if (p_alg_auth == SADB_X_AALG_TCP_MD5) {
419125681Sbms				if ((p_key_auth_len < 1) || (p_key_auth_len >
420125681Sbms				    80))
421125681Sbms					return -1;
422125681Sbms			} else if (ipsec_check_keylen(SADB_EXT_SUPPORTED_AUTH,
423122108Sume			    p_alg_auth, PFKEY_UNUNIT64(p_key_auth_len)) < 0) {
42455505Sshin				yyerror(ipsec_strerror());
42555505Sshin				return -1;
42655505Sshin			}
42755505Sshin		}
428122108Sume	|	ALG_AUTH_NOKEY {
429122108Sume			if ($1 < 0) {
430122108Sume				yyerror("unsupported algorithm");
431122108Sume				return -1;
432122108Sume			}
433122108Sume			p_alg_auth = $1;
434122108Sume
435122108Sume			p_key_auth_len = 0;
436122108Sume			p_key_auth = NULL;
437122108Sume		}
43855505Sshin	;
43955505Sshin
44055505Sshinkey_string
44155505Sshin	:	QUOTEDSTRING
44255505Sshin		{
443122108Sume			$$ = $1;
44455505Sshin		}
44555505Sshin	|	HEXSTRING
44655505Sshin		{
447122108Sume			caddr_t pp_key;
44855505Sshin			caddr_t bp;
44962583Sitojun			caddr_t yp = $1.buf;
450122108Sume			int l;
45155505Sshin
452122108Sume			l = strlen(yp) % 2 + strlen(yp) / 2;
453122108Sume			if ((pp_key = malloc(l)) == 0) {
45462583Sitojun				yyerror("not enough core");
45555505Sshin				return -1;
45655505Sshin			}
457122108Sume			memset(pp_key, 0, l);
45855505Sshin
45955505Sshin			bp = pp_key;
460122108Sume			if (strlen(yp) % 2) {
461122108Sume				*bp = ATOX(yp[0]);
462122108Sume				yp++, bp++;
463122108Sume			}
46455505Sshin			while (*yp) {
46555505Sshin				*bp = (ATOX(yp[0]) << 4) | ATOX(yp[1]);
46655505Sshin				yp += 2, bp++;
46755505Sshin			}
46855505Sshin
469122108Sume			$$.len = l;
470122108Sume			$$.buf = pp_key;
47155505Sshin		}
47255505Sshin	;
47355505Sshin
47455505Sshinextension_spec
47555505Sshin	:	/*NOTHING*/
47655505Sshin	|	extension_spec extension
47755505Sshin	;
47855505Sshin
47955505Sshinextension
48062583Sitojun	:	F_EXT EXTENSION { p_ext |= $2; }
48162583Sitojun	|	F_EXT NOCYCLICSEQ { p_ext &= ~SADB_X_EXT_CYCSEQ; }
48262583Sitojun	|	F_MODE MODE { p_mode = $2; }
48355505Sshin	|	F_MODE ANY { p_mode = IPSEC_MODE_ANY; }
48462583Sitojun	|	F_REQID DECSTRING { p_reqid = $2; }
48555505Sshin	|	F_REPLAY DECSTRING
48655505Sshin		{
487122108Sume			if ((p_ext & SADB_X_EXT_OLD) != 0) {
488122108Sume				yyerror("replay prevention cannot be used with "
489122108Sume				    "ah/esp-old");
49055505Sshin				return -1;
49155505Sshin			}
49262583Sitojun			p_replay = $2;
49355505Sshin		}
49462583Sitojun	|	F_LIFETIME_HARD DECSTRING { p_lt_hard = $2; }
49562583Sitojun	|	F_LIFETIME_SOFT DECSTRING { p_lt_soft = $2; }
49655505Sshin	;
49755505Sshin
49855505Sshin	/* definition about command for SPD management */
49955505Sshin	/* spdadd */
50055505Sshinspdadd_command
501122108Sume	:	SPDADD ipaddropts STRING prefix portstr STRING prefix portstr upper_spec upper_misc_spec policy_spec EOT
50255505Sshin		{
503122108Sume			int status;
504122108Sume			struct addrinfo *src, *dst;
505122108Sume
506122108Sume			/* fixed port fields if ulp is icmpv6 */
507122108Sume			if ($10.buf != NULL) {
508122108Sume				if ($9 != IPPROTO_ICMPV6)
509122108Sume					return -1;
510122108Sume				free($5.buf);
511122108Sume				free($8.buf);
512122108Sume				if (fix_portstr(&$10, &$5, &$8))
513122108Sume					return -1;
514122108Sume			}
515122108Sume
516122108Sume			src = parse_addr($3.buf, $5.buf);
517122108Sume			dst = parse_addr($6.buf, $8.buf);
518122108Sume			if (!src || !dst) {
519122108Sume				/* yyerror is already called */
520122108Sume				return -1;
521122108Sume			}
522122108Sume			if (src->ai_next || dst->ai_next) {
523122108Sume				yyerror("multiple address specified");
524122108Sume				freeaddrinfo(src);
525122108Sume				freeaddrinfo(dst);
526122108Sume				return -1;
527122108Sume			}
528122108Sume
529122108Sume			status = setkeymsg_spdaddr(SADB_X_SPDADD, $9, &$11,
530122108Sume			    src, $4, dst, $7);
531122108Sume			freeaddrinfo(src);
532122108Sume			freeaddrinfo(dst);
533122108Sume			if (status < 0)
534122108Sume				return -1;
53555505Sshin		}
536122108Sume	|	SPDADD TAGGED QUOTEDSTRING policy_spec EOT
537122108Sume		{
538122108Sume			return -1;
539122108Sume		}
54055505Sshin	;
54155505Sshin
542122108Sumespddelete_command
543122108Sume	:	SPDDELETE ipaddropts STRING prefix portstr STRING prefix portstr upper_spec upper_misc_spec policy_spec EOT
54455505Sshin		{
545122108Sume			int status;
546122108Sume			struct addrinfo *src, *dst;
547122108Sume
548122108Sume			/* fixed port fields if ulp is icmpv6 */
549122108Sume			if ($10.buf != NULL) {
550122108Sume				if ($9 != IPPROTO_ICMPV6)
551122108Sume					return -1;
552122108Sume				free($5.buf);
553122108Sume				free($8.buf);
554122108Sume				if (fix_portstr(&$10, &$5, &$8))
555122108Sume					return -1;
556122108Sume			}
557122108Sume
558122108Sume			src = parse_addr($3.buf, $5.buf);
559122108Sume			dst = parse_addr($6.buf, $8.buf);
560122108Sume			if (!src || !dst) {
561122108Sume				/* yyerror is already called */
562122108Sume				return -1;
563122108Sume			}
564122108Sume			if (src->ai_next || dst->ai_next) {
565122108Sume				yyerror("multiple address specified");
566122108Sume				freeaddrinfo(src);
567122108Sume				freeaddrinfo(dst);
568122108Sume				return -1;
569122108Sume			}
570122108Sume
571122108Sume			status = setkeymsg_spdaddr(SADB_X_SPDDELETE, $9, &$11,
572122108Sume			    src, $4, dst, $7);
573122108Sume			freeaddrinfo(src);
574122108Sume			freeaddrinfo(dst);
575122108Sume			if (status < 0)
576122108Sume				return -1;
57755505Sshin		}
57855505Sshin	;
57955505Sshin
58055505Sshinspddump_command:
581122108Sume		SPDDUMP EOT
58255505Sshin		{
583122108Sume			struct sadb_msg msg;
584122108Sume			setkeymsg0(&msg, SADB_X_SPDDUMP, SADB_SATYPE_UNSPEC,
585122108Sume			    sizeof(msg));
586122108Sume			sendkeymsg((char *)&msg, sizeof(msg));
58755505Sshin		}
58855505Sshin	;
58955505Sshin
59055505Sshinspdflush_command:
591122108Sume		SPDFLUSH EOT
59255505Sshin		{
593122108Sume			struct sadb_msg msg;
594122108Sume			setkeymsg0(&msg, SADB_X_SPDFLUSH, SADB_SATYPE_UNSPEC,
595122108Sume			    sizeof(msg));
596122108Sume			sendkeymsg((char *)&msg, sizeof(msg));
59755505Sshin		}
59855505Sshin	;
59955505Sshin
600122108Sumeipaddropts
601122108Sume	:	/* nothing */
602122108Sume	|	ipaddropts ipaddropt
603122108Sume	;
604122108Sume
605122108Sumeipaddropt
606122108Sume	:	F_AIFLAGS
60762583Sitojun		{
608122108Sume			char *p;
609122108Sume
610122108Sume			for (p = $1.buf + 1; *p; p++)
611122108Sume				switch (*p) {
612122108Sume				case '4':
613122108Sume					p_aifamily = AF_INET;
614122108Sume					break;
61562583Sitojun#ifdef INET6
616122108Sume				case '6':
617122108Sume					p_aifamily = AF_INET6;
618122108Sume					break;
61962583Sitojun#endif
620122108Sume				case 'n':
621122108Sume					p_aiflags = AI_NUMERICHOST;
622122108Sume					break;
623122108Sume				default:
624122108Sume					yyerror("invalid flag");
62562583Sitojun					return -1;
62662583Sitojun				}
62762583Sitojun		}
62855505Sshin	;
62955505Sshin
630122108Sumeipaddr
631122108Sume	:	STRING
63255505Sshin		{
633122108Sume			$$ = parse_addr($1.buf, NULL);
634122108Sume			if ($$ == NULL) {
635122108Sume				/* yyerror already called by parse_addr */
63655505Sshin				return -1;
63755505Sshin			}
63855505Sshin		}
63955505Sshin	;
64055505Sshin
64155505Sshinprefix
642122108Sume	:	/*NOTHING*/ { $$ = -1; }
643122108Sume	|	SLASH DECSTRING { $$ = $2; }
64455505Sshin	;
64555505Sshin
646122108Sumeportstr
647122108Sume	:	/*NOTHING*/
648122108Sume		{
649122108Sume			$$.buf = strdup("0");
650122108Sume			if (!$$.buf) {
651122108Sume				yyerror("insufficient memory");
652122108Sume				return -1;
653122108Sume			}
654122108Sume			$$.len = strlen($$.buf);
655122108Sume		}
656122108Sume	|	BLCL ANY ELCL
657122108Sume		{
658122108Sume			$$.buf = strdup("0");
659122108Sume			if (!$$.buf) {
660122108Sume				yyerror("insufficient memory");
661122108Sume				return -1;
662122108Sume			}
663122108Sume			$$.len = strlen($$.buf);
664122108Sume		}
665122108Sume	|	BLCL DECSTRING ELCL
666122108Sume		{
667122108Sume			char buf[20];
668122108Sume			snprintf(buf, sizeof(buf), "%lu", $2);
669122108Sume			$$.buf = strdup(buf);
670122108Sume			if (!$$.buf) {
671122108Sume				yyerror("insufficient memory");
672122108Sume				return -1;
673122108Sume			}
674122108Sume			$$.len = strlen($$.buf);
675122108Sume		}
676122108Sume	|	BLCL STRING ELCL
677122108Sume		{
678122108Sume			$$ = $2;
679122108Sume		}
68055505Sshin	;
68155505Sshin
68255505Sshinupper_spec
683122108Sume	:	DECSTRING { $$ = $1; }
684122108Sume	|	ANY { $$ = IPSEC_ULPROTO_ANY; }
685127684Sbms	|	PR_TCP { $$ = IPPROTO_TCP; }
686175248Smaxim	|	PR_ESP { $$ = IPPROTO_ESP; }
68778064Sume	|	STRING
68878064Sume		{
68978064Sume			struct protoent *ent;
69078064Sume
69178064Sume			ent = getprotobyname($1.buf);
69278064Sume			if (ent)
693122108Sume				$$ = ent->p_proto;
69478064Sume			else {
69578064Sume				if (strcmp("icmp6", $1.buf) == 0) {
696122108Sume					$$ = IPPROTO_ICMPV6;
69778064Sume				} else if(strcmp("ip4", $1.buf) == 0) {
698122108Sume					$$ = IPPROTO_IPV4;
69978064Sume				} else {
70078064Sume					yyerror("invalid upper layer protocol");
70178064Sume					return -1;
70278064Sume				}
70378064Sume			}
704122108Sume			endprotoent();
70578064Sume		}
70655505Sshin	;
70755505Sshin
708122108Sumeupper_misc_spec
709122108Sume	:	/*NOTHING*/
710122108Sume		{
711122108Sume			$$.buf = NULL;
712122108Sume			$$.len = 0;
713122108Sume		}
714122108Sume	|	STRING
715122108Sume		{
716122108Sume			$$.buf = strdup($1.buf);
717122108Sume			if (!$$.buf) {
718122108Sume				yyerror("insufficient memory");
719122108Sume				return -1;
720122108Sume			}
721122108Sume			$$.len = strlen($$.buf);
722122108Sume		}
723122108Sume	;
724122108Sume
72555505Sshinpolicy_spec
72655505Sshin	:	F_POLICY policy_requests
72755505Sshin		{
728122108Sume			char *policy;
729122108Sume
730122108Sume			policy = ipsec_set_policy($2.buf, $2.len);
731122108Sume			if (policy == NULL) {
73255505Sshin				yyerror(ipsec_strerror());
73355505Sshin				return -1;
73455505Sshin			}
73555505Sshin
736122108Sume			$$.buf = policy;
737122108Sume			$$.len = ipsec_get_policylen(policy);
73855505Sshin		}
73955505Sshin	;
74055505Sshin
74162583Sitojunpolicy_requests
74262583Sitojun	:	PL_REQUESTS { $$ = $1; }
74355505Sshin	;
74455505Sshin
74555505Sshin%%
74655505Sshin
74755505Sshinint
748122108Sumesetkeymsg0(msg, type, satype, l)
749122108Sume	struct sadb_msg *msg;
750122108Sume	unsigned int type;
751122108Sume	unsigned int satype;
752122108Sume	size_t l;
75355505Sshin{
75455505Sshin
755122108Sume	msg->sadb_msg_version = PF_KEY_V2;
756122108Sume	msg->sadb_msg_type = type;
757122108Sume	msg->sadb_msg_errno = 0;
758122108Sume	msg->sadb_msg_satype = satype;
759122108Sume	msg->sadb_msg_reserved = 0;
760122108Sume	msg->sadb_msg_seq = 0;
761122108Sume	msg->sadb_msg_pid = getpid();
762122108Sume	msg->sadb_msg_len = PFKEY_UNIT64(l);
763122108Sume	return 0;
764122108Sume}
76555505Sshin
766122108Sume/* XXX NO BUFFER OVERRUN CHECK! BAD BAD! */
767122108Sumestatic int
768122108Sumesetkeymsg_spdaddr(type, upper, policy, srcs, splen, dsts, dplen)
769122108Sume	unsigned int type;
770122108Sume	unsigned int upper;
771122108Sume	vchar_t *policy;
772122108Sume	struct addrinfo *srcs;
773122108Sume	int splen;
774122108Sume	struct addrinfo *dsts;
775122108Sume	int dplen;
776122108Sume{
777122108Sume	struct sadb_msg *msg;
778122108Sume	char buf[BUFSIZ];
779122108Sume	int l, l0;
780122108Sume	struct sadb_address m_addr;
781122108Sume	struct addrinfo *s, *d;
782122108Sume	int n;
783122108Sume	int plen;
784122108Sume	struct sockaddr *sa;
785122108Sume	int salen;
78655505Sshin
787122108Sume	msg = (struct sadb_msg *)buf;
78855505Sshin
789122108Sume	if (!srcs || !dsts)
790122108Sume		return -1;
79155505Sshin
792122108Sume	/* fix up length afterwards */
793122108Sume	setkeymsg0(msg, type, SADB_SATYPE_UNSPEC, 0);
794122108Sume	l = sizeof(struct sadb_msg);
79555505Sshin
796122108Sume	memcpy(buf + l, policy->buf, policy->len);
797122108Sume	l += policy->len;
79855505Sshin
799122108Sume	l0 = l;
800122108Sume	n = 0;
80155505Sshin
802122108Sume	/* do it for all src/dst pairs */
803122108Sume	for (s = srcs; s; s = s->ai_next) {
804122108Sume		for (d = dsts; d; d = d->ai_next) {
805122108Sume			/* rewind pointer */
806122108Sume			l = l0;
80755505Sshin
808122108Sume			if (s->ai_addr->sa_family != d->ai_addr->sa_family)
809122108Sume				continue;
810122108Sume			switch (s->ai_addr->sa_family) {
811122108Sume			case AF_INET:
812122108Sume				plen = sizeof(struct in_addr) << 3;
813122108Sume				break;
814122108Sume#ifdef INET6
815122108Sume			case AF_INET6:
816122108Sume				plen = sizeof(struct in6_addr) << 3;
817122108Sume				break;
818122108Sume#endif
819122108Sume			default:
820122108Sume				continue;
821122108Sume			}
82255505Sshin
823122108Sume			/* set src */
824122108Sume			sa = s->ai_addr;
825122108Sume			salen = s->ai_addr->sa_len;
826122108Sume			m_addr.sadb_address_len = PFKEY_UNIT64(sizeof(m_addr) +
827122108Sume			    PFKEY_ALIGN8(salen));
828122108Sume			m_addr.sadb_address_exttype = SADB_EXT_ADDRESS_SRC;
829122108Sume			m_addr.sadb_address_proto = upper;
830122108Sume			m_addr.sadb_address_prefixlen =
831122108Sume			    (splen >= 0 ? splen : plen);
832122108Sume			m_addr.sadb_address_reserved = 0;
83355505Sshin
834122108Sume			setvarbuf(buf, &l, (struct sadb_ext *)&m_addr,
835122108Sume			    sizeof(m_addr), (caddr_t)sa, salen);
83655505Sshin
837122108Sume			/* set dst */
838122108Sume			sa = d->ai_addr;
839122108Sume			salen = d->ai_addr->sa_len;
840122108Sume			m_addr.sadb_address_len = PFKEY_UNIT64(sizeof(m_addr) +
841122108Sume			    PFKEY_ALIGN8(salen));
842122108Sume			m_addr.sadb_address_exttype = SADB_EXT_ADDRESS_DST;
843122108Sume			m_addr.sadb_address_proto = upper;
844122108Sume			m_addr.sadb_address_prefixlen =
845122108Sume			    (dplen >= 0 ? dplen : plen);
846122108Sume			m_addr.sadb_address_reserved = 0;
84755505Sshin
848122108Sume			setvarbuf(buf, &l, (struct sadb_ext *)&m_addr,
849122108Sume			    sizeof(m_addr), (caddr_t)sa, salen);
85055505Sshin
851122108Sume			msg->sadb_msg_len = PFKEY_UNIT64(l);
85255505Sshin
853122108Sume			sendkeymsg(buf, l);
854122108Sume
855122108Sume			n++;
85655505Sshin		}
857122108Sume	}
85855505Sshin
859122108Sume	if (n == 0)
860122108Sume		return -1;
861122108Sume	else
862122108Sume		return 0;
863122108Sume}
86455505Sshin
865122108Sume/* XXX NO BUFFER OVERRUN CHECK! BAD BAD! */
866122108Sumestatic int
867122108Sumesetkeymsg_addr(type, satype, srcs, dsts, no_spi)
868122108Sume	unsigned int type;
869122108Sume	unsigned int satype;
870122108Sume	struct addrinfo *srcs;
871122108Sume	struct addrinfo *dsts;
872122108Sume	int no_spi;
873122108Sume{
874122108Sume	struct sadb_msg *msg;
875122108Sume	char buf[BUFSIZ];
876122108Sume	int l, l0, len;
877122108Sume	struct sadb_sa m_sa;
878122108Sume	struct sadb_x_sa2 m_sa2;
879122108Sume	struct sadb_address m_addr;
880122108Sume	struct addrinfo *s, *d;
881122108Sume	int n;
882122108Sume	int plen;
883122108Sume	struct sockaddr *sa;
884122108Sume	int salen;
88555505Sshin
886122108Sume	msg = (struct sadb_msg *)buf;
88755505Sshin
888122108Sume	if (!srcs || !dsts)
889122108Sume		return -1;
89062583Sitojun
891122108Sume	/* fix up length afterwards */
892122108Sume	setkeymsg0(msg, type, satype, 0);
893122108Sume	l = sizeof(struct sadb_msg);
89462583Sitojun
895122108Sume	if (!no_spi) {
896122108Sume		len = sizeof(struct sadb_sa);
897122108Sume		m_sa.sadb_sa_len = PFKEY_UNIT64(len);
898122108Sume		m_sa.sadb_sa_exttype = SADB_EXT_SA;
899122108Sume		m_sa.sadb_sa_spi = htonl(p_spi);
900122108Sume		m_sa.sadb_sa_replay = p_replay;
901122108Sume		m_sa.sadb_sa_state = 0;
902122108Sume		m_sa.sadb_sa_auth = p_alg_auth;
903122108Sume		m_sa.sadb_sa_encrypt = p_alg_enc;
904122108Sume		m_sa.sadb_sa_flags = p_ext;
905122108Sume
906122108Sume		memcpy(buf + l, &m_sa, len);
907122108Sume		l += len;
908122108Sume
909122108Sume		len = sizeof(struct sadb_x_sa2);
910122108Sume		m_sa2.sadb_x_sa2_len = PFKEY_UNIT64(len);
911122108Sume		m_sa2.sadb_x_sa2_exttype = SADB_X_EXT_SA2;
912122108Sume		m_sa2.sadb_x_sa2_mode = p_mode;
913122108Sume		m_sa2.sadb_x_sa2_reqid = p_reqid;
914122108Sume
915122108Sume		memcpy(buf + l, &m_sa2, len);
916122108Sume		l += len;
917122108Sume	}
918122108Sume
919122108Sume	l0 = l;
920122108Sume	n = 0;
921122108Sume
922122108Sume	/* do it for all src/dst pairs */
923122108Sume	for (s = srcs; s; s = s->ai_next) {
924122108Sume		for (d = dsts; d; d = d->ai_next) {
925122108Sume			/* rewind pointer */
926122108Sume			l = l0;
927122108Sume
928122108Sume			if (s->ai_addr->sa_family != d->ai_addr->sa_family)
929122108Sume				continue;
930122108Sume			switch (s->ai_addr->sa_family) {
931122108Sume			case AF_INET:
932122108Sume				plen = sizeof(struct in_addr) << 3;
933122108Sume				break;
93462583Sitojun#ifdef INET6
935122108Sume			case AF_INET6:
936122108Sume				plen = sizeof(struct in6_addr) << 3;
937122108Sume				break;
93862583Sitojun#endif
939122108Sume			default:
940122108Sume				continue;
941122108Sume			}
94255505Sshin
943122108Sume			/* set src */
944122108Sume			sa = s->ai_addr;
945122108Sume			salen = s->ai_addr->sa_len;
946122108Sume			m_addr.sadb_address_len = PFKEY_UNIT64(sizeof(m_addr) +
947122108Sume			    PFKEY_ALIGN8(salen));
948122108Sume			m_addr.sadb_address_exttype = SADB_EXT_ADDRESS_SRC;
949122108Sume			m_addr.sadb_address_proto = IPSEC_ULPROTO_ANY;
950122108Sume			m_addr.sadb_address_prefixlen = plen;
951122108Sume			m_addr.sadb_address_reserved = 0;
95255505Sshin
953122108Sume			setvarbuf(buf, &l, (struct sadb_ext *)&m_addr,
954122108Sume			    sizeof(m_addr), (caddr_t)sa, salen);
955122108Sume
956122108Sume			/* set dst */
957122108Sume			sa = d->ai_addr;
958122108Sume			salen = d->ai_addr->sa_len;
959122108Sume			m_addr.sadb_address_len = PFKEY_UNIT64(sizeof(m_addr) +
960122108Sume			    PFKEY_ALIGN8(salen));
961122108Sume			m_addr.sadb_address_exttype = SADB_EXT_ADDRESS_DST;
962122108Sume			m_addr.sadb_address_proto = IPSEC_ULPROTO_ANY;
963122108Sume			m_addr.sadb_address_prefixlen = plen;
964122108Sume			m_addr.sadb_address_reserved = 0;
965122108Sume
966122108Sume			setvarbuf(buf, &l, (struct sadb_ext *)&m_addr,
967122108Sume			    sizeof(m_addr), (caddr_t)sa, salen);
968122108Sume
969122108Sume			msg->sadb_msg_len = PFKEY_UNIT64(l);
970122108Sume
971122108Sume			sendkeymsg(buf, l);
972122108Sume
973122108Sume			n++;
97462583Sitojun		}
975122108Sume	}
97655505Sshin
977122108Sume	if (n == 0)
978122108Sume		return -1;
979122108Sume	else
980122108Sume		return 0;
981122108Sume}
98255505Sshin
983122108Sume/* XXX NO BUFFER OVERRUN CHECK! BAD BAD! */
984122108Sumestatic int
985122108Sumesetkeymsg_add(type, satype, srcs, dsts)
986122108Sume	unsigned int type;
987122108Sume	unsigned int satype;
988122108Sume	struct addrinfo *srcs;
989122108Sume	struct addrinfo *dsts;
990122108Sume{
991122108Sume	struct sadb_msg *msg;
992122108Sume	char buf[BUFSIZ];
993122108Sume	int l, l0, len;
994122108Sume	struct sadb_sa m_sa;
995122108Sume	struct sadb_x_sa2 m_sa2;
996122108Sume	struct sadb_address m_addr;
997122108Sume	struct addrinfo *s, *d;
998122108Sume	int n;
999122108Sume	int plen;
1000122108Sume	struct sockaddr *sa;
1001122108Sume	int salen;
100255505Sshin
1003122108Sume	msg = (struct sadb_msg *)buf;
100462583Sitojun
1005122108Sume	if (!srcs || !dsts)
1006122108Sume		return -1;
100755505Sshin
1008122108Sume	/* fix up length afterwards */
1009122108Sume	setkeymsg0(msg, type, satype, 0);
1010122108Sume	l = sizeof(struct sadb_msg);
1011122108Sume
1012122108Sume	/* set encryption algorithm, if present. */
1013122108Sume	if (satype != SADB_X_SATYPE_IPCOMP && p_key_enc) {
1014122108Sume		struct sadb_key m_key;
1015122108Sume
1016122108Sume		m_key.sadb_key_len =
1017122108Sume			PFKEY_UNIT64(sizeof(m_key)
1018122108Sume				   + PFKEY_ALIGN8(p_key_enc_len));
1019122108Sume		m_key.sadb_key_exttype = SADB_EXT_KEY_ENCRYPT;
1020122108Sume		m_key.sadb_key_bits = p_key_enc_len * 8;
1021122108Sume		m_key.sadb_key_reserved = 0;
1022122108Sume
1023122108Sume		setvarbuf(buf, &l,
1024122108Sume			(struct sadb_ext *)&m_key, sizeof(m_key),
1025122108Sume			(caddr_t)p_key_enc, p_key_enc_len);
1026122108Sume	}
1027122108Sume
1028122108Sume	/* set authentication algorithm, if present. */
1029122108Sume	if (p_key_auth) {
1030122108Sume		struct sadb_key m_key;
1031122108Sume
1032122108Sume		m_key.sadb_key_len =
1033122108Sume			PFKEY_UNIT64(sizeof(m_key)
1034122108Sume				   + PFKEY_ALIGN8(p_key_auth_len));
1035122108Sume		m_key.sadb_key_exttype = SADB_EXT_KEY_AUTH;
1036122108Sume		m_key.sadb_key_bits = p_key_auth_len * 8;
1037122108Sume		m_key.sadb_key_reserved = 0;
1038122108Sume
1039122108Sume		setvarbuf(buf, &l,
1040122108Sume			(struct sadb_ext *)&m_key, sizeof(m_key),
1041122108Sume			(caddr_t)p_key_auth, p_key_auth_len);
1042122108Sume	}
1043122108Sume
1044122108Sume	/* set lifetime for HARD */
1045122108Sume	if (p_lt_hard != 0) {
1046122108Sume		struct sadb_lifetime m_lt;
1047122108Sume		u_int slen = sizeof(struct sadb_lifetime);
1048122108Sume
1049122108Sume		m_lt.sadb_lifetime_len = PFKEY_UNIT64(slen);
1050122108Sume		m_lt.sadb_lifetime_exttype = SADB_EXT_LIFETIME_HARD;
1051122108Sume		m_lt.sadb_lifetime_allocations = 0;
1052122108Sume		m_lt.sadb_lifetime_bytes = 0;
1053122108Sume		m_lt.sadb_lifetime_addtime = p_lt_hard;
1054122108Sume		m_lt.sadb_lifetime_usetime = 0;
1055122108Sume
1056122108Sume		memcpy(buf + l, &m_lt, slen);
1057151293Sume		l += slen;
1058122108Sume	}
1059122108Sume
1060122108Sume	/* set lifetime for SOFT */
1061122108Sume	if (p_lt_soft != 0) {
1062122108Sume		struct sadb_lifetime m_lt;
1063122108Sume		u_int slen = sizeof(struct sadb_lifetime);
1064122108Sume
1065122108Sume		m_lt.sadb_lifetime_len = PFKEY_UNIT64(slen);
1066122108Sume		m_lt.sadb_lifetime_exttype = SADB_EXT_LIFETIME_SOFT;
1067122108Sume		m_lt.sadb_lifetime_allocations = 0;
1068122108Sume		m_lt.sadb_lifetime_bytes = 0;
1069122108Sume		m_lt.sadb_lifetime_addtime = p_lt_soft;
1070122108Sume		m_lt.sadb_lifetime_usetime = 0;
1071122108Sume
1072122108Sume		memcpy(buf + l, &m_lt, slen);
1073151293Sume		l += slen;
1074122108Sume	}
1075122108Sume
1076122108Sume	len = sizeof(struct sadb_sa);
1077122108Sume	m_sa.sadb_sa_len = PFKEY_UNIT64(len);
1078122108Sume	m_sa.sadb_sa_exttype = SADB_EXT_SA;
1079122108Sume	m_sa.sadb_sa_spi = htonl(p_spi);
1080122108Sume	m_sa.sadb_sa_replay = p_replay;
1081122108Sume	m_sa.sadb_sa_state = 0;
1082122108Sume	m_sa.sadb_sa_auth = p_alg_auth;
1083122108Sume	m_sa.sadb_sa_encrypt = p_alg_enc;
1084122108Sume	m_sa.sadb_sa_flags = p_ext;
1085122108Sume
1086122108Sume	memcpy(buf + l, &m_sa, len);
1087122108Sume	l += len;
1088122108Sume
1089122108Sume	len = sizeof(struct sadb_x_sa2);
1090122108Sume	m_sa2.sadb_x_sa2_len = PFKEY_UNIT64(len);
1091122108Sume	m_sa2.sadb_x_sa2_exttype = SADB_X_EXT_SA2;
1092122108Sume	m_sa2.sadb_x_sa2_mode = p_mode;
1093122108Sume	m_sa2.sadb_x_sa2_reqid = p_reqid;
1094122108Sume
1095122108Sume	memcpy(buf + l, &m_sa2, len);
1096122108Sume	l += len;
1097122108Sume
1098122108Sume	l0 = l;
1099122108Sume	n = 0;
1100122108Sume
1101122108Sume	/* do it for all src/dst pairs */
1102122108Sume	for (s = srcs; s; s = s->ai_next) {
1103122108Sume		for (d = dsts; d; d = d->ai_next) {
1104122108Sume			/* rewind pointer */
1105122108Sume			l = l0;
1106122108Sume
1107122108Sume			if (s->ai_addr->sa_family != d->ai_addr->sa_family)
1108122108Sume				continue;
1109122108Sume			switch (s->ai_addr->sa_family) {
1110122108Sume			case AF_INET:
1111122108Sume				plen = sizeof(struct in_addr) << 3;
1112122108Sume				break;
111362583Sitojun#ifdef INET6
1114122108Sume			case AF_INET6:
1115122108Sume				plen = sizeof(struct in6_addr) << 3;
1116122108Sume				break;
111762583Sitojun#endif
1118122108Sume			default:
1119122108Sume				continue;
1120122108Sume			}
112155505Sshin
1122122108Sume			/* set src */
1123122108Sume			sa = s->ai_addr;
1124122108Sume			salen = s->ai_addr->sa_len;
1125122108Sume			m_addr.sadb_address_len = PFKEY_UNIT64(sizeof(m_addr) +
1126122108Sume			    PFKEY_ALIGN8(salen));
1127122108Sume			m_addr.sadb_address_exttype = SADB_EXT_ADDRESS_SRC;
1128122108Sume			m_addr.sadb_address_proto = IPSEC_ULPROTO_ANY;
1129122108Sume			m_addr.sadb_address_prefixlen = plen;
1130122108Sume			m_addr.sadb_address_reserved = 0;
113155505Sshin
1132122108Sume			setvarbuf(buf, &l, (struct sadb_ext *)&m_addr,
1133122108Sume			    sizeof(m_addr), (caddr_t)sa, salen);
1134122108Sume
1135122108Sume			/* set dst */
1136122108Sume			sa = d->ai_addr;
1137122108Sume			salen = d->ai_addr->sa_len;
1138122108Sume			m_addr.sadb_address_len = PFKEY_UNIT64(sizeof(m_addr) +
1139122108Sume			    PFKEY_ALIGN8(salen));
1140122108Sume			m_addr.sadb_address_exttype = SADB_EXT_ADDRESS_DST;
1141122108Sume			m_addr.sadb_address_proto = IPSEC_ULPROTO_ANY;
1142122108Sume			m_addr.sadb_address_prefixlen = plen;
1143122108Sume			m_addr.sadb_address_reserved = 0;
1144122108Sume
1145122108Sume			setvarbuf(buf, &l, (struct sadb_ext *)&m_addr,
1146122108Sume			    sizeof(m_addr), (caddr_t)sa, salen);
1147122108Sume
1148122108Sume			msg->sadb_msg_len = PFKEY_UNIT64(l);
1149122108Sume
1150122108Sume			sendkeymsg(buf, l);
1151122108Sume
1152122108Sume			n++;
115362583Sitojun		}
115455505Sshin	}
115555505Sshin
1156122108Sume	if (n == 0)
1157122108Sume		return -1;
1158122108Sume	else
1159122108Sume		return 0;
116055505Sshin}
116155505Sshin
116262583Sitojunstatic struct addrinfo *
1163122108Sumeparse_addr(host, port)
116462583Sitojun	char *host;
116562583Sitojun	char *port;
116662583Sitojun{
116762583Sitojun	struct addrinfo hints, *res = NULL;
116862583Sitojun	int error;
116962583Sitojun
117062583Sitojun	memset(&hints, 0, sizeof(hints));
1171122108Sume	hints.ai_family = p_aifamily;
1172122108Sume	hints.ai_socktype = SOCK_DGRAM;		/*dummy*/
1173122108Sume	hints.ai_protocol = IPPROTO_UDP;	/*dummy*/
1174122108Sume	hints.ai_flags = p_aiflags;
117562583Sitojun	error = getaddrinfo(host, port, &hints, &res);
117662583Sitojun	if (error != 0) {
117762583Sitojun		yyerror(gai_strerror(error));
117862583Sitojun		return NULL;
117962583Sitojun	}
118062583Sitojun	return res;
118162583Sitojun}
118262583Sitojun
118355505Sshinstatic int
1184122108Sumefix_portstr(spec, sport, dport)
1185122108Sume	vchar_t *spec, *sport, *dport;
1186122108Sume{
1187122108Sume	char *p, *p2;
1188122108Sume	u_int l;
1189122108Sume
1190122108Sume	l = 0;
1191122108Sume	for (p = spec->buf; *p != ',' && *p != '\0' && l < spec->len; p++, l++)
1192122108Sume		;
1193122108Sume	if (*p == '\0') {
1194122108Sume		p2 = "0";
1195122108Sume	} else {
1196122108Sume		if (*p == ',') {
1197122108Sume			*p = '\0';
1198122108Sume			p2 = ++p;
1199122108Sume		}
1200122108Sume		for (p = p2; *p != '\0' && l < spec->len; p++, l++)
1201122108Sume			;
1202122108Sume		if (*p != '\0' || *p2 == '\0') {
1203122108Sume			yyerror("invalid an upper layer protocol spec");
1204122108Sume			return -1;
1205122108Sume		}
1206122108Sume	}
1207122108Sume
1208122108Sume	sport->buf = strdup(spec->buf);
1209122108Sume	if (!sport->buf) {
1210122108Sume		yyerror("insufficient memory");
1211122108Sume		return -1;
1212122108Sume	}
1213122108Sume	sport->len = strlen(sport->buf);
1214122108Sume	dport->buf = strdup(p2);
1215122108Sume	if (!dport->buf) {
1216122108Sume		yyerror("insufficient memory");
1217122108Sume		return -1;
1218122108Sume	}
1219122108Sume	dport->len = strlen(dport->buf);
1220122108Sume
1221122108Sume	return 0;
1222122108Sume}
1223122108Sume
1224122108Sumestatic int
1225122108Sumesetvarbuf(buf, off, ebuf, elen, vbuf, vlen)
1226122108Sume	char *buf;
1227122108Sume	int *off;
1228122108Sume	struct sadb_ext *ebuf;
1229122108Sume	int elen;
123055505Sshin	caddr_t vbuf;
1231122108Sume	int vlen;
123255505Sshin{
1233122108Sume	memset(buf + *off, 0, PFKEY_UNUNIT64(ebuf->sadb_ext_len));
1234122108Sume	memcpy(buf + *off, (caddr_t)ebuf, elen);
1235122108Sume	memcpy(buf + *off + elen, vbuf, vlen);
123655505Sshin	(*off) += PFKEY_ALIGN8(elen + vlen);
123755505Sshin
123855505Sshin	return 0;
123955505Sshin}
124055505Sshin
124155505Sshinvoid
124255505Sshinparse_init()
124355505Sshin{
124455505Sshin	p_spi = 0;
124555505Sshin
124662583Sitojun	p_ext = SADB_X_EXT_CYCSEQ;
124755505Sshin	p_alg_enc = SADB_EALG_NONE;
124855505Sshin	p_alg_auth = SADB_AALG_NONE;
124955505Sshin	p_mode = IPSEC_MODE_ANY;
125062583Sitojun	p_reqid = 0;
125162583Sitojun	p_replay = 0;
125255505Sshin	p_key_enc_len = p_key_auth_len = 0;
125355505Sshin	p_key_enc = p_key_auth = 0;
125455505Sshin	p_lt_hard = p_lt_soft = 0;
125555505Sshin
1256122108Sume	p_aiflags = 0;
1257122108Sume	p_aifamily = PF_UNSPEC;
125855505Sshin
125955505Sshin	return;
126055505Sshin}
126155505Sshin
126255505Sshinvoid
126355505Sshinfree_buffer()
126455505Sshin{
1265122108Sume	/* we got tons of memory leaks in the parser anyways, leave them */
126655505Sshin
126755505Sshin	return;
126855505Sshin}
1269