parse.y revision 62583
162583Sitojun/*	$FreeBSD: head/sbin/setkey/parse.y 62583 2000-07-04 16:22:05Z itojun $	*/
262583Sitojun/*	$KAME: parse.y,v 1.29 2000/06/10 14:17:44 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>
4155505Sshin#include <netkey/key_var.h>
4255505Sshin#include <netinet6/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) \
5655505Sshin  (isdigit(c) ? (c - '0') : (isupper(c) ? (c - 'A' + 10) : (c - 'a' + 10) ))
5755505Sshin
5862583Sitojunu_int p_type;
5962583Sitojunu_int32_t p_spi;
6062583Sitojunstruct sockaddr *p_src, *p_dst;
6162583Sitojunu_int p_prefs, p_prefd, p_upper;
6262583Sitojunu_int p_satype, p_ext, p_alg_enc, p_alg_auth, p_replay, p_mode;
6362583Sitojunu_int32_t p_reqid;
6462583Sitojunu_int p_key_enc_len, p_key_auth_len;
6562583Sitojuncaddr_t p_key_enc, p_key_auth;
6662583Sitojuntime_t p_lt_hard, p_lt_soft;
6755505Sshin
6862583Sitojunu_int p_policy_len;
6962583Sitojunchar *p_policy;
7055505Sshin
7155505Sshin/* temporary buffer */
7262583Sitojunstatic struct sockaddr *pp_addr;
7362583Sitojunstatic u_int pp_prefix;
7462583Sitojunstatic u_int pp_port;
7562583Sitojunstatic caddr_t pp_key;
7655505Sshin
7762583Sitojunextern u_char m_buf[BUFSIZ];
7862583Sitojunextern int m_len;
7962583Sitojunextern char cmdarg[8192];
8062583Sitojunextern int f_debug;
8155505Sshin
8262583Sitojunint setkeymsg __P((void));
8362583Sitojunstatic struct addrinfo *parse_addr __P((char *, char *, int));
8462583Sitojunstatic int setvarbuf __P((int *, struct sadb_ext *, int, caddr_t, int));
8562583Sitojunvoid parse_init __P((void));
8662583Sitojunvoid free_buffer __P((void));
8755505Sshin
8862583Sitojunextern int setkeymsg __P((void));
8962583Sitojunextern int sendkeymsg __P((void));
9055505Sshin
9162583Sitojunextern int yylex __P((void));
9262583Sitojunextern void yyfatal __P((const char *));
9362583Sitojunextern void yyerror __P((const char *));
9455505Sshin%}
9555505Sshin
9655505Sshin%union {
9755505Sshin	unsigned long num;
9855505Sshin	vchar_t val;
9955505Sshin}
10055505Sshin
10155505Sshin%token EOT
10255505Sshin%token ADD GET DELETE FLUSH DUMP
10362583Sitojun%token ADDRESS PREFIX PORT PORTANY
10455505Sshin%token UP_PROTO PR_ESP PR_AH PR_IPCOMP
10555505Sshin%token F_PROTOCOL F_AUTH F_ENC F_REPLAY F_COMP F_RAWCPI
10662583Sitojun%token F_MODE MODE F_REQID
10762583Sitojun%token F_EXT EXTENSION NOCYCLICSEQ
10855505Sshin%token ALG_AUTH ALG_ENC ALG_ENC_DESDERIV ALG_ENC_DES32IV ALG_COMP
10955505Sshin%token F_LIFETIME_HARD F_LIFETIME_SOFT
11055505Sshin%token DECSTRING QUOTEDSTRING HEXSTRING ANY
11155505Sshin	/* SPD management */
11255505Sshin%token SPDADD SPDDELETE SPDDUMP SPDFLUSH
11355505Sshin%token F_POLICY PL_REQUESTS
11455505Sshin
11562583Sitojun%type <num> PORT PREFIX EXTENSION MODE
11662583Sitojun%type <num> UP_PROTO PR_ESP PR_AH PR_IPCOMP
11762583Sitojun%type <num> ALG_AUTH ALG_ENC ALG_ENC_DESDERIV ALG_ENC_DES32IV ALG_COMP
11862583Sitojun%type <num> DECSTRING
11962583Sitojun%type <val> ADDRESS PL_REQUESTS
12062583Sitojun%type <val> key_string policy_requests
12162583Sitojun%type <val> QUOTEDSTRING HEXSTRING
12262583Sitojun
12355505Sshin%%
12455505Sshincommands
12555505Sshin	:	/*NOTHING*/
12655505Sshin	|	commands command
12755505Sshin		{
12855505Sshin			if (f_debug) {
12955505Sshin				printf("cmdarg:\n%s\n", cmdarg);
13055505Sshin			} else {
13155505Sshin				setkeymsg();
13255505Sshin				sendkeymsg();
13355505Sshin			}
13455505Sshin			free_buffer();
13555505Sshin			parse_init();
13655505Sshin		}
13755505Sshin	;
13855505Sshin
13955505Sshincommand
14055505Sshin	:	add_command
14155505Sshin	|	get_command
14255505Sshin	|	delete_command
14355505Sshin	|	flush_command
14455505Sshin	|	dump_command
14555505Sshin	|	spdadd_command
14655505Sshin	|	spddelete_command
14755505Sshin	|	spddump_command
14855505Sshin	|	spdflush_command
14955505Sshin	;
15055505Sshin	/* commands concerned with management, there is in tail of this file. */
15155505Sshin
15255505Sshin	/* add command */
15355505Sshinadd_command
15455505Sshin	:	ADD { p_type = SADB_ADD; }
15555505Sshin		sa_selector_spec extension_spec algorithm_spec EOT
15655505Sshin	;
15755505Sshin
15855505Sshin	/* delete */
15955505Sshindelete_command
16055505Sshin	:	DELETE { p_type = SADB_DELETE; }
16162583Sitojun		sa_selector_spec extension_spec
16262583Sitojun		{
16362583Sitojun			if (p_mode != IPSEC_MODE_ANY)
16462583Sitojun				yyerror("WARNING: mode is obsoleted.");
16562583Sitojun		}
16662583Sitojun		EOT
16755505Sshin	;
16855505Sshin
16955505Sshin	/* get command */
17055505Sshinget_command
17155505Sshin	:	GET { p_type = SADB_GET; }
17262583Sitojun		sa_selector_spec extension_spec
17362583Sitojun		{
17462583Sitojun			if (p_mode != IPSEC_MODE_ANY)
17562583Sitojun				yyerror("WARNING: mode is obsoleted.");
17662583Sitojun		}
17762583Sitojun		EOT
17855505Sshin	;
17955505Sshin
18055505Sshin	/* flush */
18155505Sshinflush_command
18255505Sshin	:	FLUSH { p_type = SADB_FLUSH; }
18355505Sshin		protocol_spec EOT
18455505Sshin	;
18555505Sshin
18655505Sshin	/* dump */
18755505Sshindump_command
18855505Sshin	:	DUMP { p_type = SADB_DUMP; }
18955505Sshin		protocol_spec EOT
19055505Sshin	;
19155505Sshin
19255505Sshin	/* sa_selector_spec */
19355505Sshinsa_selector_spec
19455505Sshin	:	ipaddress { p_src = pp_addr; }
19555505Sshin		ipaddress { p_dst = pp_addr; }
19655505Sshin		protocol_spec spi
19755505Sshin	;
19855505Sshin
19955505Sshinprotocol_spec
20055505Sshin	:	/*NOTHING*/ { p_satype = SADB_SATYPE_UNSPEC; }
20155505Sshin	|	PR_ESP
20255505Sshin		{
20355505Sshin			p_satype = SADB_SATYPE_ESP;
20462583Sitojun			if ($1 == 1)
20555505Sshin				p_ext |= SADB_X_EXT_OLD;
20655505Sshin			else
20755505Sshin				p_ext &= ~SADB_X_EXT_OLD;
20855505Sshin		}
20955505Sshin	|	PR_AH
21055505Sshin		{
21155505Sshin			p_satype = SADB_SATYPE_AH;
21262583Sitojun			if ($1 == 1)
21355505Sshin				p_ext |= SADB_X_EXT_OLD;
21455505Sshin			else
21555505Sshin				p_ext &= ~SADB_X_EXT_OLD;
21655505Sshin		}
21755505Sshin	|	PR_IPCOMP
21855505Sshin		{
21955505Sshin			p_satype = SADB_X_SATYPE_IPCOMP;
22055505Sshin		}
22155505Sshin	;
22255505Sshin
22355505Sshinspi
22462583Sitojun	:	DECSTRING { p_spi = $1; }
22555505Sshin	|	HEXSTRING
22655505Sshin		{
22755505Sshin			caddr_t bp;
22862583Sitojun			caddr_t yp = $1.buf;
22955505Sshin			char buf0[4], buf[4];
23055505Sshin			int i, j;
23155505Sshin
23255505Sshin			/* sanity check */
23362583Sitojun			if ($1.len > 4) {
23455505Sshin				yyerror("SPI too big.");
23562583Sitojun				free($1.buf);
23655505Sshin				return -1;
23755505Sshin			}
23855505Sshin
23955505Sshin			bp = buf0;
24055505Sshin			while (*yp) {
24155505Sshin				*bp = (ATOX(yp[0]) << 4) | ATOX(yp[1]);
24255505Sshin				yp += 2, bp++;
24355505Sshin			}
24455505Sshin
24555505Sshin			/* initialize */
24655505Sshin			for (i = 0; i < 4; i++) buf[i] = 0;
24755505Sshin
24862583Sitojun			for (j = $1.len - 1, i = 3; j >= 0; j--, i--)
24955505Sshin				buf[i] = buf0[j];
25055505Sshin
25155505Sshin			/* XXX: endian */
25255505Sshin			p_spi = ntohl(*(u_int32_t *)buf);
25355505Sshin
25462583Sitojun			free($1.buf);
25555505Sshin		}
25655505Sshin	;
25755505Sshin
25855505Sshinalgorithm_spec
25955505Sshin	:	esp_spec
26055505Sshin	|	ah_spec
26155505Sshin	|	ipcomp_spec
26255505Sshin	;
26355505Sshin
26455505Sshinesp_spec
26555505Sshin	:	F_ENC enc_alg enc_key F_AUTH auth_alg auth_key
26655505Sshin	|	F_ENC enc_alg enc_key
26755505Sshin	;
26855505Sshin
26955505Sshinah_spec
27055505Sshin	:	F_AUTH auth_alg auth_key
27155505Sshin	;
27255505Sshin
27355505Sshinipcomp_spec
27462583Sitojun	:	F_COMP ALG_COMP { p_alg_enc = $2; }
27562583Sitojun	|	F_COMP ALG_COMP { p_alg_enc = $2; }
27655505Sshin		F_RAWCPI { p_ext |= SADB_X_EXT_RAWCPI; }
27755505Sshin	;
27855505Sshin
27955505Sshinenc_alg
28062583Sitojun	:	ALG_ENC { p_alg_enc = $1; }
28155505Sshin	|	ALG_ENC_DESDERIV
28255505Sshin		{
28362583Sitojun			p_alg_enc = $1;
28455505Sshin			if (p_ext & SADB_X_EXT_OLD) {
28555505Sshin				yyerror("algorithm mismatched.");
28655505Sshin				return -1;
28755505Sshin			}
28855505Sshin			p_ext |= SADB_X_EXT_DERIV;
28955505Sshin		}
29055505Sshin	|	ALG_ENC_DES32IV
29155505Sshin		{
29262583Sitojun			p_alg_enc = $1;
29355505Sshin			if (!(p_ext & SADB_X_EXT_OLD)) {
29455505Sshin				yyerror("algorithm mismatched.");
29555505Sshin				return -1;
29655505Sshin			}
29755505Sshin			p_ext |= SADB_X_EXT_IV4B;
29855505Sshin		}
29955505Sshin	;
30055505Sshin
30155505Sshinenc_key
30255505Sshin	:	/*NOTHING*/
30355505Sshin		{
30455505Sshin			if (p_alg_enc != SADB_EALG_NULL) {
30555505Sshin				yyerror("no key found.");
30655505Sshin				return -1;
30755505Sshin			}
30855505Sshin		}
30955505Sshin	|	key_string
31055505Sshin		{
31162583Sitojun			p_key_enc_len = $1.len;
31255505Sshin			p_key_enc = pp_key;
31355505Sshin
31455505Sshin			if (ipsec_check_keylen(SADB_EXT_SUPPORTED_ENCRYPT,
31555505Sshin					p_alg_enc,
31655505Sshin					PFKEY_UNUNIT64(p_key_enc_len)) < 0) {
31755505Sshin				yyerror(ipsec_strerror());
31855505Sshin				return -1;
31955505Sshin			}
32055505Sshin		}
32155505Sshin	;
32255505Sshin
32355505Sshinauth_alg
32462583Sitojun	:	ALG_AUTH { p_alg_auth = $1; }
32555505Sshin	;
32655505Sshin
32755505Sshinauth_key
32855505Sshin	:	/*NOTHING*/
32955505Sshin		{
33055505Sshin			if (p_alg_auth != SADB_AALG_NULL) {
33155505Sshin				yyerror("no key found.");
33255505Sshin				return -1;
33355505Sshin			}
33455505Sshin		}
33555505Sshin	|	key_string
33655505Sshin		{
33762583Sitojun			p_key_auth_len = $1.len;
33855505Sshin			p_key_auth = pp_key;
33955505Sshin
34055505Sshin			if (ipsec_check_keylen(SADB_EXT_SUPPORTED_AUTH,
34155505Sshin					p_alg_auth,
34255505Sshin					PFKEY_UNUNIT64(p_key_auth_len)) < 0) {
34355505Sshin				yyerror(ipsec_strerror());
34455505Sshin				return -1;
34555505Sshin			}
34655505Sshin		}
34755505Sshin	;
34855505Sshin
34955505Sshinkey_string
35055505Sshin	:	QUOTEDSTRING
35155505Sshin		{
35262583Sitojun			pp_key = $1.buf;
35355505Sshin			/* free pp_key later */
35455505Sshin		}
35555505Sshin	|	HEXSTRING
35655505Sshin		{
35755505Sshin			caddr_t bp;
35862583Sitojun			caddr_t yp = $1.buf;
35955505Sshin
36062583Sitojun			if ((pp_key = malloc($1.len)) == 0) {
36162583Sitojun				free($1.buf);
36262583Sitojun				yyerror("not enough core");
36355505Sshin				return -1;
36455505Sshin			}
36562583Sitojun			memset(pp_key, 0, $1.len);
36655505Sshin
36755505Sshin			bp = pp_key;
36855505Sshin			while (*yp) {
36955505Sshin				*bp = (ATOX(yp[0]) << 4) | ATOX(yp[1]);
37055505Sshin				yp += 2, bp++;
37155505Sshin			}
37255505Sshin
37362583Sitojun			free($1.buf);
37455505Sshin		}
37555505Sshin	;
37655505Sshin
37755505Sshinextension_spec
37855505Sshin	:	/*NOTHING*/
37955505Sshin	|	extension_spec extension
38055505Sshin	;
38155505Sshin
38255505Sshinextension
38362583Sitojun	:	F_EXT EXTENSION { p_ext |= $2; }
38462583Sitojun	|	F_EXT NOCYCLICSEQ { p_ext &= ~SADB_X_EXT_CYCSEQ; }
38562583Sitojun	|	F_MODE MODE { p_mode = $2; }
38655505Sshin	|	F_MODE ANY { p_mode = IPSEC_MODE_ANY; }
38762583Sitojun	|	F_REQID DECSTRING { p_reqid = $2; }
38855505Sshin	|	F_REPLAY DECSTRING
38955505Sshin		{
39055505Sshin			if (p_ext & SADB_X_EXT_OLD) {
39155505Sshin				yyerror("replay prevention "
39255505Sshin				        "only use on new spec.");
39355505Sshin				return -1;
39455505Sshin			}
39562583Sitojun			p_replay = $2;
39655505Sshin		}
39762583Sitojun	|	F_LIFETIME_HARD DECSTRING { p_lt_hard = $2; }
39862583Sitojun	|	F_LIFETIME_SOFT DECSTRING { p_lt_soft = $2; }
39955505Sshin	;
40055505Sshin
40155505Sshin	/* definition about command for SPD management */
40255505Sshin	/* spdadd */
40355505Sshinspdadd_command
40455505Sshin	:	SPDADD
40555505Sshin		{
40655505Sshin			p_type = SADB_X_SPDADD;
40755505Sshin			p_satype = SADB_SATYPE_UNSPEC;
40855505Sshin		}
40955505Sshin		sp_selector_spec policy_spec EOT
41055505Sshin	;
41155505Sshin
41255505Sshinspddelete_command:
41355505Sshin		SPDDELETE
41455505Sshin		{
41555505Sshin			p_type = SADB_X_SPDDELETE;
41655505Sshin			p_satype = SADB_SATYPE_UNSPEC;
41755505Sshin		}
41862583Sitojun		sp_selector_spec policy_spec EOT
41955505Sshin	;
42055505Sshin
42155505Sshinspddump_command:
42255505Sshin		SPDDUMP
42355505Sshin		{
42455505Sshin			p_type = SADB_X_SPDDUMP;
42555505Sshin			p_satype = SADB_SATYPE_UNSPEC;
42655505Sshin		}
42755505Sshin		EOT
42855505Sshin	;
42955505Sshin
43055505Sshinspdflush_command:
43155505Sshin		SPDFLUSH
43255505Sshin		{
43355505Sshin			p_type = SADB_X_SPDFLUSH;
43455505Sshin			p_satype = SADB_SATYPE_UNSPEC;
43555505Sshin		}
43655505Sshin		EOT
43755505Sshin	;
43855505Sshin
43955505Sshin	/* sp_selector_spec */
44055505Sshinsp_selector_spec
44155505Sshin	:	ipaddress { p_src = pp_addr; }
44255505Sshin		prefix { p_prefs = pp_prefix; }
44362583Sitojun		port
44462583Sitojun		{
44562583Sitojun			switch (p_src->sa_family) {
44662583Sitojun			case AF_INET:
44762583Sitojun				((struct sockaddr_in *)p_src)->sin_port =
44862583Sitojun				    htons(pp_port);
44962583Sitojun				break;
45062583Sitojun#ifdef INET6
45162583Sitojun			case AF_INET6:
45262583Sitojun				((struct sockaddr_in6 *)p_src)->sin6_port =
45362583Sitojun				    htons(pp_port);
45462583Sitojun				break;
45562583Sitojun#endif
45662583Sitojun			default:
45762583Sitojun				exit(1); /*XXX*/
45862583Sitojun			}
45962583Sitojun		}
46055505Sshin		ipaddress { p_dst = pp_addr; }
46155505Sshin		prefix { p_prefd = pp_prefix; }
46262583Sitojun		port
46362583Sitojun		{
46462583Sitojun			switch (p_dst->sa_family) {
46562583Sitojun			case AF_INET:
46662583Sitojun				((struct sockaddr_in *)p_dst)->sin_port =
46762583Sitojun				    htons(pp_port);
46862583Sitojun				break;
46962583Sitojun#ifdef INET6
47062583Sitojun			case AF_INET6:
47162583Sitojun				((struct sockaddr_in6 *)p_dst)->sin6_port =
47262583Sitojun				    htons(pp_port);
47362583Sitojun				break;
47462583Sitojun#endif
47562583Sitojun			default:
47662583Sitojun				exit(1); /*XXX*/
47762583Sitojun			}
47862583Sitojun		}
47955505Sshin		upper_spec
48062583Sitojun		{
48162583Sitojun			/* XXX is it something userland should check? */
48262583Sitojun#if 0
48362583Sitojun			switch (p_upper) {
48462583Sitojun			case IPPROTO_ICMP:
48562583Sitojun			case IPPROTO_ICMPV6:
48662583Sitojun				if (_INPORTBYSA(p_src) != IPSEC_PORT_ANY
48762583Sitojun				 || _INPORTBYSA(p_dst) != IPSEC_PORT_ANY) {
48862583Sitojun					yyerror("port number must be \"any\".");
48962583Sitojun					return -1;
49062583Sitojun				}
49162583Sitojun				if ((pp_addr->sa_family == AF_INET6
49262583Sitojun				  && p_upper == IPPROTO_ICMP)
49362583Sitojun				 || (pp_addr->sa_family == AF_INET
49462583Sitojun				  && p_upper == IPPROTO_ICMPV6)) {
49562583Sitojun					yyerror("upper layer protocol "
49662583Sitojun						"mismatched.\n");
49762583Sitojun					return -1;
49862583Sitojun				}
49962583Sitojun				break;
50062583Sitojun			default:
50162583Sitojun				break;
50262583Sitojun			}
50362583Sitojun#endif
50462583Sitojun		}
50555505Sshin	;
50655505Sshin
50755505Sshinipaddress
50862583Sitojun	:	ADDRESS
50955505Sshin		{
51062583Sitojun			struct addrinfo *res;
51155505Sshin
51262583Sitojun			res = parse_addr($1.buf, NULL, AI_NUMERICHOST);
51362583Sitojun			if (res == NULL) {
51462583Sitojun				free($1.buf);
51555505Sshin				return -1;
51655505Sshin			}
51762583Sitojun			pp_addr = (struct sockaddr *)malloc(res->ai_addrlen);
51862583Sitojun			if (!pp_addr) {
51962583Sitojun				yyerror("not enough core");
52062583Sitojun				goto end;
52155505Sshin			}
52255505Sshin
52362583Sitojun			memcpy(pp_addr, res->ai_addr, res->ai_addrlen);
52462583Sitojun		    end:
52555505Sshin			freeaddrinfo(res);
52662583Sitojun			free($1.buf);
52755505Sshin		}
52855505Sshin	;
52955505Sshin
53055505Sshinprefix
53155505Sshin	:	/*NOTHING*/ { pp_prefix = ~0; }
53262583Sitojun	|	PREFIX { pp_prefix = $1; }
53355505Sshin	;
53455505Sshin
53555505Sshinport
53655505Sshin	:	/*NOTHING*/ { pp_port = IPSEC_PORT_ANY; }
53762583Sitojun	|	PORT { pp_port = $1; }
53855505Sshin	|	PORTANY { pp_port = IPSEC_PORT_ANY; }
53955505Sshin	;
54055505Sshin
54155505Sshinupper_spec
54262583Sitojun	:	DECSTRING { p_upper = $1; }
54362583Sitojun	|	UP_PROTO { p_upper = $1; }
54455505Sshin	|	PR_ESP { p_upper = IPPROTO_ESP; };
54555505Sshin	|	PR_AH { p_upper = IPPROTO_AH; };
54655505Sshin	|	PR_IPCOMP { p_upper = IPPROTO_IPCOMP; };
54755505Sshin	|	ANY { p_upper = IPSEC_ULPROTO_ANY; }
54855505Sshin	;
54955505Sshin
55055505Sshinpolicy_spec
55155505Sshin	:	F_POLICY policy_requests
55255505Sshin		{
55362583Sitojun			p_policy = ipsec_set_policy($2.buf, $2.len);
55455505Sshin			if (p_policy == NULL) {
55562583Sitojun				free($2.buf);
55655505Sshin				p_policy = NULL;
55755505Sshin				yyerror(ipsec_strerror());
55855505Sshin				return -1;
55955505Sshin			}
56055505Sshin
56155505Sshin			p_policy_len = ipsec_get_policylen(p_policy);
56255505Sshin
56362583Sitojun			free($2.buf);
56455505Sshin		}
56555505Sshin	;
56655505Sshin
56762583Sitojunpolicy_requests
56862583Sitojun	:	PL_REQUESTS { $$ = $1; }
56955505Sshin	;
57055505Sshin
57155505Sshin%%
57255505Sshin
57355505Sshinint
57455505Sshinsetkeymsg()
57555505Sshin{
57655505Sshin	struct sadb_msg m_msg;
57755505Sshin
57855505Sshin	m_msg.sadb_msg_version = PF_KEY_V2;
57955505Sshin	m_msg.sadb_msg_type = p_type;
58055505Sshin	m_msg.sadb_msg_errno = 0;
58155505Sshin	m_msg.sadb_msg_satype = p_satype;
58255505Sshin	m_msg.sadb_msg_reserved = 0;
58355505Sshin	m_msg.sadb_msg_seq = 0;
58455505Sshin	m_msg.sadb_msg_pid = getpid();
58555505Sshin
58655505Sshin	m_len = sizeof(struct sadb_msg);
58755505Sshin	memcpy(m_buf, &m_msg, m_len);
58855505Sshin
58955505Sshin	switch (p_type) {
59055505Sshin	case SADB_FLUSH:
59155505Sshin	case SADB_DUMP:
59255505Sshin		break;
59355505Sshin
59455505Sshin	case SADB_ADD:
59555505Sshin		/* set encryption algorithm, if present. */
59655505Sshin		if (p_satype != SADB_X_SATYPE_IPCOMP && p_alg_enc != SADB_EALG_NONE) {
59755505Sshin			struct sadb_key m_key;
59855505Sshin
59955505Sshin			m_key.sadb_key_len =
60055505Sshin				PFKEY_UNIT64(sizeof(m_key)
60155505Sshin				           + PFKEY_ALIGN8(p_key_enc_len));
60255505Sshin			m_key.sadb_key_exttype = SADB_EXT_KEY_ENCRYPT;
60355505Sshin			m_key.sadb_key_bits = p_key_enc_len * 8;
60455505Sshin			m_key.sadb_key_reserved = 0;
60555505Sshin
60655505Sshin			setvarbuf(&m_len,
60755505Sshin				(struct sadb_ext *)&m_key, sizeof(m_key),
60855505Sshin				(caddr_t)p_key_enc, p_key_enc_len);
60955505Sshin		}
61055505Sshin
61155505Sshin		/* set authentication algorithm, if present. */
61255505Sshin		if (p_alg_auth != SADB_AALG_NONE) {
61355505Sshin			struct sadb_key m_key;
61455505Sshin
61555505Sshin			m_key.sadb_key_len =
61655505Sshin				PFKEY_UNIT64(sizeof(m_key)
61755505Sshin				           + PFKEY_ALIGN8(p_key_auth_len));
61855505Sshin			m_key.sadb_key_exttype = SADB_EXT_KEY_AUTH;
61955505Sshin			m_key.sadb_key_bits = p_key_auth_len * 8;
62055505Sshin			m_key.sadb_key_reserved = 0;
62155505Sshin
62255505Sshin			setvarbuf(&m_len,
62355505Sshin				(struct sadb_ext *)&m_key, sizeof(m_key),
62455505Sshin				(caddr_t)p_key_auth, p_key_auth_len);
62555505Sshin		}
62655505Sshin
62755505Sshin		/* set lifetime for HARD */
62855505Sshin		if (p_lt_hard != 0) {
62955505Sshin			struct sadb_lifetime m_lt;
63055505Sshin			u_int len = sizeof(struct sadb_lifetime);
63155505Sshin
63255505Sshin			m_lt.sadb_lifetime_len = PFKEY_UNIT64(len);
63355505Sshin			m_lt.sadb_lifetime_exttype = SADB_EXT_LIFETIME_HARD;
63455505Sshin			m_lt.sadb_lifetime_allocations = 0;
63555505Sshin			m_lt.sadb_lifetime_bytes = 0;
63655505Sshin			m_lt.sadb_lifetime_addtime = p_lt_hard;
63755505Sshin			m_lt.sadb_lifetime_usetime = 0;
63855505Sshin
63955505Sshin			memcpy(m_buf + m_len, &m_lt, len);
64055505Sshin			m_len += len;
64155505Sshin		}
64255505Sshin
64355505Sshin		/* set lifetime for SOFT */
64455505Sshin		if (p_lt_soft != 0) {
64555505Sshin			struct sadb_lifetime m_lt;
64655505Sshin			u_int len = sizeof(struct sadb_lifetime);
64755505Sshin
64855505Sshin			m_lt.sadb_lifetime_len = PFKEY_UNIT64(len);
64955505Sshin			m_lt.sadb_lifetime_exttype = SADB_EXT_LIFETIME_SOFT;
65055505Sshin			m_lt.sadb_lifetime_allocations = 0;
65155505Sshin			m_lt.sadb_lifetime_bytes = 0;
65255505Sshin			m_lt.sadb_lifetime_addtime = p_lt_soft;
65355505Sshin			m_lt.sadb_lifetime_usetime = 0;
65455505Sshin
65555505Sshin			memcpy(m_buf + m_len, &m_lt, len);
65655505Sshin			m_len += len;
65755505Sshin		}
65855505Sshin		/* FALLTHROUGH */
65955505Sshin
66055505Sshin	case SADB_DELETE:
66155505Sshin	case SADB_GET:
66255505Sshin	    {
66355505Sshin		struct sadb_sa m_sa;
66462583Sitojun		struct sadb_x_sa2 m_sa2;
66555505Sshin		struct sadb_address m_addr;
66655505Sshin		u_int len;
66755505Sshin
66855505Sshin		len = sizeof(struct sadb_sa);
66955505Sshin		m_sa.sadb_sa_len = PFKEY_UNIT64(len);
67055505Sshin		m_sa.sadb_sa_exttype = SADB_EXT_SA;
67155505Sshin		m_sa.sadb_sa_spi = htonl(p_spi);
67255505Sshin		m_sa.sadb_sa_replay = p_replay;
67355505Sshin		m_sa.sadb_sa_state = 0;
67455505Sshin		m_sa.sadb_sa_auth = p_alg_auth;
67555505Sshin		m_sa.sadb_sa_encrypt = p_alg_enc;
67655505Sshin		m_sa.sadb_sa_flags = p_ext;
67755505Sshin
67855505Sshin		memcpy(m_buf + m_len, &m_sa, len);
67955505Sshin		m_len += len;
68055505Sshin
68162583Sitojun		len = sizeof(struct sadb_x_sa2);
68262583Sitojun		m_sa2.sadb_x_sa2_len = PFKEY_UNIT64(len);
68362583Sitojun		m_sa2.sadb_x_sa2_exttype = SADB_X_EXT_SA2;
68462583Sitojun		m_sa2.sadb_x_sa2_mode = p_mode;
68562583Sitojun		m_sa2.sadb_x_sa2_reqid = p_reqid;
68662583Sitojun
68762583Sitojun		memcpy(m_buf + m_len, &m_sa2, len);
68862583Sitojun		m_len += len;
68962583Sitojun
69055505Sshin		/* set src */
69155505Sshin		m_addr.sadb_address_len =
69255505Sshin			PFKEY_UNIT64(sizeof(m_addr)
69355505Sshin			           + PFKEY_ALIGN8(p_src->sa_len));
69455505Sshin		m_addr.sadb_address_exttype = SADB_EXT_ADDRESS_SRC;
69555505Sshin		m_addr.sadb_address_proto = IPSEC_ULPROTO_ANY;
69662583Sitojun		switch (p_src->sa_family) {
69762583Sitojun		case AF_INET:
69862583Sitojun			m_addr.sadb_address_prefixlen =
69962583Sitojun			    sizeof(struct in_addr) << 3;
70062583Sitojun			break;
70162583Sitojun#ifdef INET6
70262583Sitojun		case AF_INET6:
70362583Sitojun			m_addr.sadb_address_prefixlen =
70462583Sitojun			    sizeof(struct in6_addr) << 3;
70562583Sitojun			break;
70662583Sitojun#endif
70762583Sitojun		default:
70862583Sitojun			yyerror("unsupported address family");
70962583Sitojun			exit(1);	/*XXX*/
71062583Sitojun		}
71155505Sshin		m_addr.sadb_address_reserved = 0;
71255505Sshin
71355505Sshin		setvarbuf(&m_len,
71455505Sshin			(struct sadb_ext *)&m_addr, sizeof(m_addr),
71555505Sshin			(caddr_t)p_src, p_src->sa_len);
71655505Sshin
71755505Sshin		/* set dst */
71855505Sshin		m_addr.sadb_address_len =
71955505Sshin			PFKEY_UNIT64(sizeof(m_addr)
72055505Sshin			           + PFKEY_ALIGN8(p_dst->sa_len));
72155505Sshin		m_addr.sadb_address_exttype = SADB_EXT_ADDRESS_DST;
72255505Sshin		m_addr.sadb_address_proto = IPSEC_ULPROTO_ANY;
72362583Sitojun		switch (p_dst->sa_family) {
72462583Sitojun		case AF_INET:
72562583Sitojun			m_addr.sadb_address_prefixlen =
72662583Sitojun			    sizeof(struct in_addr) << 3;
72762583Sitojun			break;
72862583Sitojun#ifdef INET6
72962583Sitojun		case AF_INET6:
73062583Sitojun			m_addr.sadb_address_prefixlen =
73162583Sitojun			    sizeof(struct in6_addr) << 3;
73262583Sitojun			break;
73362583Sitojun#endif
73462583Sitojun		default:
73562583Sitojun			yyerror("unsupported address family");
73662583Sitojun			exit(1);	/*XXX*/
73762583Sitojun		}
73855505Sshin		m_addr.sadb_address_reserved = 0;
73955505Sshin
74055505Sshin		setvarbuf(&m_len,
74155505Sshin			(struct sadb_ext *)&m_addr, sizeof(m_addr),
74255505Sshin			(caddr_t)p_dst, p_dst->sa_len);
74355505Sshin	    }
74455505Sshin		break;
74555505Sshin
74655505Sshin	/* for SPD management */
74755505Sshin	case SADB_X_SPDFLUSH:
74855505Sshin	case SADB_X_SPDDUMP:
74955505Sshin		break;
75055505Sshin
75155505Sshin	case SADB_X_SPDADD:
75262583Sitojun	case SADB_X_SPDDELETE:
75355505Sshin	    {
75462583Sitojun		struct sadb_address m_addr;
75562583Sitojun		u_int8_t plen;
75662583Sitojun
75755505Sshin		memcpy(m_buf + m_len, p_policy, p_policy_len);
75855505Sshin		m_len += p_policy_len;
75955505Sshin		free(p_policy);
76055505Sshin		p_policy = NULL;
76155505Sshin
76255505Sshin		/* set src */
76355505Sshin		m_addr.sadb_address_len =
76455505Sshin			PFKEY_UNIT64(sizeof(m_addr)
76555505Sshin			           + PFKEY_ALIGN8(p_src->sa_len));
76655505Sshin		m_addr.sadb_address_exttype = SADB_EXT_ADDRESS_SRC;
76755505Sshin		m_addr.sadb_address_proto = p_upper;
76862583Sitojun		switch (p_src->sa_family) {
76962583Sitojun		case AF_INET:
77062583Sitojun			plen = sizeof(struct in_addr) << 3;
77162583Sitojun			break;
77262583Sitojun#ifdef INET6
77362583Sitojun		case AF_INET6:
77462583Sitojun			plen = sizeof(struct in6_addr) << 3;
77562583Sitojun			break;
77662583Sitojun#endif
77762583Sitojun		default:
77862583Sitojun			yyerror("unsupported address family");
77962583Sitojun			exit(1);	/*XXX*/
78062583Sitojun		}
78155505Sshin		m_addr.sadb_address_prefixlen =
78262583Sitojun		    (p_prefs != ~0 ? p_prefs : plen);
78355505Sshin		m_addr.sadb_address_reserved = 0;
78455505Sshin
78555505Sshin		setvarbuf(&m_len,
78655505Sshin			(struct sadb_ext *)&m_addr, sizeof(m_addr),
78755505Sshin			(caddr_t)p_src, p_src->sa_len);
78855505Sshin
78955505Sshin		/* set dst */
79055505Sshin		m_addr.sadb_address_len =
79155505Sshin			PFKEY_UNIT64(sizeof(m_addr)
79255505Sshin			           + PFKEY_ALIGN8(p_dst->sa_len));
79355505Sshin		m_addr.sadb_address_exttype = SADB_EXT_ADDRESS_DST;
79455505Sshin		m_addr.sadb_address_proto = p_upper;
79562583Sitojun		switch (p_dst->sa_family) {
79662583Sitojun		case AF_INET:
79762583Sitojun			plen = sizeof(struct in_addr) << 3;
79862583Sitojun			break;
79962583Sitojun#ifdef INET6
80062583Sitojun		case AF_INET6:
80162583Sitojun			plen = sizeof(struct in6_addr) << 3;
80262583Sitojun			break;
80362583Sitojun#endif
80462583Sitojun		default:
80562583Sitojun			yyerror("unsupported address family");
80662583Sitojun			exit(1);	/*XXX*/
80762583Sitojun		}
80855505Sshin		m_addr.sadb_address_prefixlen =
80962583Sitojun		    (p_prefd != ~0 ? p_prefd : plen);
81055505Sshin		m_addr.sadb_address_reserved = 0;
81155505Sshin
81255505Sshin		setvarbuf(&m_len,
81355505Sshin			(struct sadb_ext *)&m_addr, sizeof(m_addr),
81455505Sshin			(caddr_t)p_dst, p_dst->sa_len);
81555505Sshin	    }
81655505Sshin		break;
81755505Sshin	}
81855505Sshin
81955505Sshin	((struct sadb_msg *)m_buf)->sadb_msg_len = PFKEY_UNIT64(m_len);
82055505Sshin
82155505Sshin	return 0;
82255505Sshin}
82355505Sshin
82462583Sitojunstatic struct addrinfo *
82562583Sitojunparse_addr(host, port, flag)
82662583Sitojun	char *host;
82762583Sitojun	char *port;
82862583Sitojun	int flag;
82962583Sitojun{
83062583Sitojun	struct addrinfo hints, *res = NULL;
83162583Sitojun	int error;
83262583Sitojun
83362583Sitojun	memset(&hints, 0, sizeof(hints));
83462583Sitojun	hints.ai_family = PF_UNSPEC;
83562583Sitojun	hints.ai_socktype = SOCK_DGRAM;
83662583Sitojun	hints.ai_flags = flag;
83762583Sitojun	error = getaddrinfo(host, port, &hints, &res);
83862583Sitojun	if (error != 0) {
83962583Sitojun		yyerror(gai_strerror(error));
84062583Sitojun		return NULL;
84162583Sitojun	}
84262583Sitojun	if (res->ai_next != NULL) {
84362583Sitojun		yyerror(gai_strerror(error));
84462583Sitojun	}
84562583Sitojun	return res;
84662583Sitojun}
84762583Sitojun
84855505Sshinstatic int
84955505Sshinsetvarbuf(off, ebuf, elen, vbuf, vlen)
85055505Sshin	caddr_t vbuf;
85155505Sshin	struct sadb_ext *ebuf;
85255505Sshin	int *off, elen, vlen;
85355505Sshin{
85455505Sshin	memset(m_buf + *off, 0, PFKEY_UNUNIT64(ebuf->sadb_ext_len));
85555505Sshin	memcpy(m_buf + *off, (caddr_t)ebuf, elen);
85655505Sshin	memcpy(m_buf + *off + elen, vbuf, vlen);
85755505Sshin	(*off) += PFKEY_ALIGN8(elen + vlen);
85855505Sshin
85955505Sshin	return 0;
86055505Sshin}
86155505Sshin
86255505Sshinvoid
86355505Sshinparse_init()
86455505Sshin{
86555505Sshin	p_type = 0;
86655505Sshin	p_spi = 0;
86755505Sshin
86855505Sshin	p_src = 0, p_dst = 0;
86955505Sshin	pp_prefix = p_prefs = p_prefd = ~0;
87055505Sshin	pp_port = IPSEC_PORT_ANY;
87155505Sshin	p_upper = 0;
87255505Sshin
87355505Sshin	p_satype = 0;
87462583Sitojun	p_ext = SADB_X_EXT_CYCSEQ;
87555505Sshin	p_alg_enc = SADB_EALG_NONE;
87655505Sshin	p_alg_auth = SADB_AALG_NONE;
87755505Sshin	p_mode = IPSEC_MODE_ANY;
87862583Sitojun	p_reqid = 0;
87962583Sitojun	p_replay = 0;
88055505Sshin	p_key_enc_len = p_key_auth_len = 0;
88155505Sshin	p_key_enc = p_key_auth = 0;
88255505Sshin	p_lt_hard = p_lt_soft = 0;
88355505Sshin
88455505Sshin	p_policy_len = 0;
88555505Sshin	p_policy = NULL;
88655505Sshin
88755505Sshin	memset(cmdarg, 0, sizeof(cmdarg));
88855505Sshin
88955505Sshin	return;
89055505Sshin}
89155505Sshin
89255505Sshinvoid
89355505Sshinfree_buffer()
89455505Sshin{
89555505Sshin	if (p_src) free(p_src);
89655505Sshin	if (p_dst) free(p_dst);
89755505Sshin	if (p_key_enc) free(p_key_enc);
89855505Sshin	if (p_key_auth) free(p_key_auth);
89955505Sshin
90055505Sshin	return;
90155505Sshin}
90255505Sshin
903