xref: /freebsd/lib/libipsec/policy_parse.y (revision 50ecbc5142e1c58f2132b351da19c5e4aa5f4e6a)
1bd9f52d5SHajimu UMEMOTO /*	$KAME: policy_parse.y,v 1.14 2003/06/27 03:39:20 itojun Exp $	*/
23c62e87aSJun-ichiro itojun Hagino 
38a16b7a1SPedro F. Giffuni /*-
48a16b7a1SPedro F. Giffuni  * SPDX-License-Identifier: BSD-3-Clause
58a16b7a1SPedro F. Giffuni  *
69a4365d0SYoshinobu Inoue  * Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project.
79a4365d0SYoshinobu Inoue  * All rights reserved.
89a4365d0SYoshinobu Inoue  *
99a4365d0SYoshinobu Inoue  * Redistribution and use in source and binary forms, with or without
109a4365d0SYoshinobu Inoue  * modification, are permitted provided that the following conditions
119a4365d0SYoshinobu Inoue  * are met:
129a4365d0SYoshinobu Inoue  * 1. Redistributions of source code must retain the above copyright
139a4365d0SYoshinobu Inoue  *    notice, this list of conditions and the following disclaimer.
149a4365d0SYoshinobu Inoue  * 2. Redistributions in binary form must reproduce the above copyright
159a4365d0SYoshinobu Inoue  *    notice, this list of conditions and the following disclaimer in the
169a4365d0SYoshinobu Inoue  *    documentation and/or other materials provided with the distribution.
179a4365d0SYoshinobu Inoue  * 3. Neither the name of the project nor the names of its contributors
189a4365d0SYoshinobu Inoue  *    may be used to endorse or promote products derived from this software
199a4365d0SYoshinobu Inoue  *    without specific prior written permission.
209a4365d0SYoshinobu Inoue  *
219a4365d0SYoshinobu Inoue  * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
229a4365d0SYoshinobu Inoue  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
239a4365d0SYoshinobu Inoue  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
249a4365d0SYoshinobu Inoue  * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
259a4365d0SYoshinobu Inoue  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
269a4365d0SYoshinobu Inoue  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
279a4365d0SYoshinobu Inoue  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
289a4365d0SYoshinobu Inoue  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
299a4365d0SYoshinobu Inoue  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
309a4365d0SYoshinobu Inoue  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
319a4365d0SYoshinobu Inoue  * SUCH DAMAGE.
329a4365d0SYoshinobu Inoue  */
339a4365d0SYoshinobu Inoue 
349a4365d0SYoshinobu Inoue /*
359a4365d0SYoshinobu Inoue  * IN/OUT bound policy configuration take place such below:
369a4365d0SYoshinobu Inoue  *	in <policy>
379a4365d0SYoshinobu Inoue  *	out <policy>
389a4365d0SYoshinobu Inoue  *
399a4365d0SYoshinobu Inoue  * <policy> is one of following:
409a4365d0SYoshinobu Inoue  *	"discard", "none", "ipsec <requests>", "entrust", "bypass",
419a4365d0SYoshinobu Inoue  *
429a4365d0SYoshinobu Inoue  * The following requests are accepted as <requests>:
439a4365d0SYoshinobu Inoue  *
449a4365d0SYoshinobu Inoue  *	protocol/mode/src-dst/level
459a4365d0SYoshinobu Inoue  *	protocol/mode/src-dst		parsed as protocol/mode/src-dst/default
469a4365d0SYoshinobu Inoue  *	protocol/mode/src-dst/		parsed as protocol/mode/src-dst/default
479a4365d0SYoshinobu Inoue  *	protocol/transport		parsed as protocol/mode/any-any/default
489a4365d0SYoshinobu Inoue  *	protocol/transport//level	parsed as protocol/mode/any-any/level
499a4365d0SYoshinobu Inoue  *
509a4365d0SYoshinobu Inoue  * You can concatenate these requests with either ' '(single space) or '\n'.
519a4365d0SYoshinobu Inoue  */
529a4365d0SYoshinobu Inoue 
539a4365d0SYoshinobu Inoue %{
54a2f733abSWarner Losh 
559a4365d0SYoshinobu Inoue #include <sys/types.h>
569a4365d0SYoshinobu Inoue #include <sys/param.h>
579a4365d0SYoshinobu Inoue #include <sys/socket.h>
589a4365d0SYoshinobu Inoue 
599a4365d0SYoshinobu Inoue #include <netinet/in.h>
608409aedfSGeorge V. Neville-Neil #include <netipsec/ipsec.h>
619a4365d0SYoshinobu Inoue 
629a4365d0SYoshinobu Inoue #include <stdlib.h>
639a4365d0SYoshinobu Inoue #include <stdio.h>
649a4365d0SYoshinobu Inoue #include <string.h>
659a4365d0SYoshinobu Inoue #include <netdb.h>
669a4365d0SYoshinobu Inoue 
679a4365d0SYoshinobu Inoue #include "ipsec_strerror.h"
689a4365d0SYoshinobu Inoue 
699a4365d0SYoshinobu Inoue #define ATOX(c) \
709a4365d0SYoshinobu Inoue   (isdigit(c) ? (c - '0') : (isupper(c) ? (c - 'A' + 10) : (c - 'a' + 10) ))
719a4365d0SYoshinobu Inoue 
729a4365d0SYoshinobu Inoue static caddr_t pbuf = NULL;		/* sadb_x_policy buffer */
739a4365d0SYoshinobu Inoue static int tlen = 0;			/* total length of pbuf */
749a4365d0SYoshinobu Inoue static int offset = 0;			/* offset of pbuf */
753c62e87aSJun-ichiro itojun Hagino static int p_dir, p_type, p_protocol, p_mode, p_level, p_reqid;
769a4365d0SYoshinobu Inoue static struct sockaddr *p_src = NULL;
779a4365d0SYoshinobu Inoue static struct sockaddr *p_dst = NULL;
789a4365d0SYoshinobu Inoue 
793c62e87aSJun-ichiro itojun Hagino struct _val;
80*50ecbc51SLexi Winter extern void yyerror(const char *msg);
81*50ecbc51SLexi Winter static struct sockaddr *parse_sockaddr(const struct _val *buf);
8269160b1eSDavid E. O'Brien static int rule_check(void);
8369160b1eSDavid E. O'Brien static int init_x_policy(void);
8469160b1eSDavid E. O'Brien static int set_x_request(struct sockaddr *src, struct sockaddr *dst);
85*50ecbc51SLexi Winter static int set_sockaddr(const struct sockaddr *addr);
8669160b1eSDavid E. O'Brien static void policy_parse_request_init(void);
87*50ecbc51SLexi Winter static caddr_t policy_parse(const char *msg, int msglen);
889a4365d0SYoshinobu Inoue 
89*50ecbc51SLexi Winter extern void __policy__strbuffer__init__(const char *msg);
90bd9f52d5SHajimu UMEMOTO extern void __policy__strbuffer__free__(void);
9169160b1eSDavid E. O'Brien extern int yylex(void);
929a4365d0SYoshinobu Inoue 
93bd9f52d5SHajimu UMEMOTO extern char *__libipsecyytext;	/*XXX*/
94bd9f52d5SHajimu UMEMOTO 
959a4365d0SYoshinobu Inoue %}
969a4365d0SYoshinobu Inoue 
979a4365d0SYoshinobu Inoue %union {
989a4365d0SYoshinobu Inoue 	u_int num;
999a4365d0SYoshinobu Inoue 	struct _val {
1009a4365d0SYoshinobu Inoue 		int len;
1019a4365d0SYoshinobu Inoue 		char *buf;
1029a4365d0SYoshinobu Inoue 	} val;
1039a4365d0SYoshinobu Inoue }
1049a4365d0SYoshinobu Inoue 
1053c62e87aSJun-ichiro itojun Hagino %token DIR ACTION PROTOCOL MODE LEVEL LEVEL_SPECIFY
1069a4365d0SYoshinobu Inoue %token IPADDRESS
1079a4365d0SYoshinobu Inoue %token ME ANY
1089a4365d0SYoshinobu Inoue %token SLASH HYPHEN
1099a4365d0SYoshinobu Inoue %type <num> DIR ACTION PROTOCOL MODE LEVEL
1103c62e87aSJun-ichiro itojun Hagino %type <val> IPADDRESS LEVEL_SPECIFY
1119a4365d0SYoshinobu Inoue 
1129a4365d0SYoshinobu Inoue %%
1139a4365d0SYoshinobu Inoue policy_spec
1149a4365d0SYoshinobu Inoue 	:	DIR ACTION
1159a4365d0SYoshinobu Inoue 		{
1169a4365d0SYoshinobu Inoue 			p_dir = $1;
1179a4365d0SYoshinobu Inoue 			p_type = $2;
1189a4365d0SYoshinobu Inoue 
1199a4365d0SYoshinobu Inoue 			if (init_x_policy())
1209a4365d0SYoshinobu Inoue 				return -1;
1219a4365d0SYoshinobu Inoue 		}
1229a4365d0SYoshinobu Inoue 		rules
1233c62e87aSJun-ichiro itojun Hagino 	|	DIR
1243c62e87aSJun-ichiro itojun Hagino 		{
1253c62e87aSJun-ichiro itojun Hagino 			p_dir = $1;
1263c62e87aSJun-ichiro itojun Hagino 			p_type = 0;	/* ignored it by kernel */
1273c62e87aSJun-ichiro itojun Hagino 
1283c62e87aSJun-ichiro itojun Hagino 			if (init_x_policy())
1293c62e87aSJun-ichiro itojun Hagino 				return -1;
1303c62e87aSJun-ichiro itojun Hagino 		}
1319a4365d0SYoshinobu Inoue 	;
1329a4365d0SYoshinobu Inoue 
1339a4365d0SYoshinobu Inoue rules
1349a4365d0SYoshinobu Inoue 	:	/*NOTHING*/
1359a4365d0SYoshinobu Inoue 	|	rules rule {
1369a4365d0SYoshinobu Inoue 			if (rule_check() < 0)
1379a4365d0SYoshinobu Inoue 				return -1;
1389a4365d0SYoshinobu Inoue 
1399a4365d0SYoshinobu Inoue 			if (set_x_request(p_src, p_dst) < 0)
1409a4365d0SYoshinobu Inoue 				return -1;
1419a4365d0SYoshinobu Inoue 
1429a4365d0SYoshinobu Inoue 			policy_parse_request_init();
1439a4365d0SYoshinobu Inoue 		}
1449a4365d0SYoshinobu Inoue 	;
1459a4365d0SYoshinobu Inoue 
1469a4365d0SYoshinobu Inoue rule
1479a4365d0SYoshinobu Inoue 	:	protocol SLASH mode SLASH addresses SLASH level
1489a4365d0SYoshinobu Inoue 	|	protocol SLASH mode SLASH addresses SLASH
1499a4365d0SYoshinobu Inoue 	|	protocol SLASH mode SLASH addresses
1509a4365d0SYoshinobu Inoue 	|	protocol SLASH mode SLASH
1519a4365d0SYoshinobu Inoue 	|	protocol SLASH mode SLASH SLASH level
1529a4365d0SYoshinobu Inoue 	|	protocol SLASH mode
1539a4365d0SYoshinobu Inoue 	|	protocol SLASH {
1543c62e87aSJun-ichiro itojun Hagino 			__ipsec_errcode = EIPSEC_FEW_ARGUMENTS;
1559a4365d0SYoshinobu Inoue 			return -1;
1569a4365d0SYoshinobu Inoue 		}
1579a4365d0SYoshinobu Inoue 	|	protocol {
1583c62e87aSJun-ichiro itojun Hagino 			__ipsec_errcode = EIPSEC_FEW_ARGUMENTS;
1599a4365d0SYoshinobu Inoue 			return -1;
1609a4365d0SYoshinobu Inoue 		}
1619a4365d0SYoshinobu Inoue 	;
1629a4365d0SYoshinobu Inoue 
1639a4365d0SYoshinobu Inoue protocol
1649a4365d0SYoshinobu Inoue 	:	PROTOCOL { p_protocol = $1; }
1659a4365d0SYoshinobu Inoue 	;
1669a4365d0SYoshinobu Inoue 
1679a4365d0SYoshinobu Inoue mode
1689a4365d0SYoshinobu Inoue 	:	MODE { p_mode = $1; }
1699a4365d0SYoshinobu Inoue 	;
1709a4365d0SYoshinobu Inoue 
1719a4365d0SYoshinobu Inoue level
1723c62e87aSJun-ichiro itojun Hagino 	:	LEVEL {
1733c62e87aSJun-ichiro itojun Hagino 			p_level = $1;
1743c62e87aSJun-ichiro itojun Hagino 			p_reqid = 0;
1753c62e87aSJun-ichiro itojun Hagino 		}
1763c62e87aSJun-ichiro itojun Hagino 	|	LEVEL_SPECIFY {
1773c62e87aSJun-ichiro itojun Hagino 			p_level = IPSEC_LEVEL_UNIQUE;
1783c62e87aSJun-ichiro itojun Hagino 			p_reqid = atol($1.buf);	/* atol() is good. */
1793c62e87aSJun-ichiro itojun Hagino 		}
1809a4365d0SYoshinobu Inoue 	;
1819a4365d0SYoshinobu Inoue 
1829a4365d0SYoshinobu Inoue addresses
1839a4365d0SYoshinobu Inoue 	:	IPADDRESS {
1849a4365d0SYoshinobu Inoue 			p_src = parse_sockaddr(&$1);
1859a4365d0SYoshinobu Inoue 			if (p_src == NULL)
1869a4365d0SYoshinobu Inoue 				return -1;
1879a4365d0SYoshinobu Inoue 		}
1889a4365d0SYoshinobu Inoue 		HYPHEN
1899a4365d0SYoshinobu Inoue 		IPADDRESS {
1909a4365d0SYoshinobu Inoue 			p_dst = parse_sockaddr(&$4);
1919a4365d0SYoshinobu Inoue 			if (p_dst == NULL)
1929a4365d0SYoshinobu Inoue 				return -1;
1939a4365d0SYoshinobu Inoue 		}
1949a4365d0SYoshinobu Inoue 	|	ME HYPHEN ANY {
1959a4365d0SYoshinobu Inoue 			if (p_dir != IPSEC_DIR_OUTBOUND) {
1963c62e87aSJun-ichiro itojun Hagino 				__ipsec_errcode = EIPSEC_INVAL_DIR;
1979a4365d0SYoshinobu Inoue 				return -1;
1989a4365d0SYoshinobu Inoue 			}
1999a4365d0SYoshinobu Inoue 		}
2009a4365d0SYoshinobu Inoue 	|	ANY HYPHEN ME {
2019a4365d0SYoshinobu Inoue 			if (p_dir != IPSEC_DIR_INBOUND) {
2023c62e87aSJun-ichiro itojun Hagino 				__ipsec_errcode = EIPSEC_INVAL_DIR;
2039a4365d0SYoshinobu Inoue 				return -1;
2049a4365d0SYoshinobu Inoue 			}
2059a4365d0SYoshinobu Inoue 		}
2069a4365d0SYoshinobu Inoue 		/*
2079a4365d0SYoshinobu Inoue 	|	ME HYPHEN ME
2089a4365d0SYoshinobu Inoue 		*/
2099a4365d0SYoshinobu Inoue 	;
2109a4365d0SYoshinobu Inoue 
2119a4365d0SYoshinobu Inoue %%
2129a4365d0SYoshinobu Inoue 
2139a4365d0SYoshinobu Inoue void
214*50ecbc51SLexi Winter yyerror(const char *msg)
2159a4365d0SYoshinobu Inoue {
2163c62e87aSJun-ichiro itojun Hagino 	fprintf(stderr, "libipsec: %s while parsing \"%s\"\n",
2173c62e87aSJun-ichiro itojun Hagino 		msg, __libipsecyytext);
2189a4365d0SYoshinobu Inoue 
2199a4365d0SYoshinobu Inoue 	return;
2209a4365d0SYoshinobu Inoue }
2219a4365d0SYoshinobu Inoue 
2229a4365d0SYoshinobu Inoue static struct sockaddr *
223*50ecbc51SLexi Winter parse_sockaddr(const struct _val *buf)
2249a4365d0SYoshinobu Inoue {
2259a4365d0SYoshinobu Inoue 	struct addrinfo hints, *res;
2269a4365d0SYoshinobu Inoue 	char *serv = NULL;
2279a4365d0SYoshinobu Inoue 	int error;
2289a4365d0SYoshinobu Inoue 	struct sockaddr *newaddr = NULL;
2299a4365d0SYoshinobu Inoue 
2309a4365d0SYoshinobu Inoue 	memset(&hints, 0, sizeof(hints));
2319a4365d0SYoshinobu Inoue 	hints.ai_family = PF_UNSPEC;
2329a4365d0SYoshinobu Inoue 	hints.ai_flags = AI_NUMERICHOST;
2339a4365d0SYoshinobu Inoue 	error = getaddrinfo(buf->buf, serv, &hints, &res);
2343c62e87aSJun-ichiro itojun Hagino 	if (error != 0) {
2353c62e87aSJun-ichiro itojun Hagino 		yyerror("invalid IP address");
2363c62e87aSJun-ichiro itojun Hagino 		__ipsec_set_strerror(gai_strerror(error));
2379a4365d0SYoshinobu Inoue 		return NULL;
2389a4365d0SYoshinobu Inoue 	}
2399a4365d0SYoshinobu Inoue 
2409a4365d0SYoshinobu Inoue 	if (res->ai_addr == NULL) {
2413c62e87aSJun-ichiro itojun Hagino 		yyerror("invalid IP address");
2423c62e87aSJun-ichiro itojun Hagino 		__ipsec_set_strerror(gai_strerror(error));
2439a4365d0SYoshinobu Inoue 		return NULL;
2449a4365d0SYoshinobu Inoue 	}
2459a4365d0SYoshinobu Inoue 
2469a4365d0SYoshinobu Inoue 	newaddr = malloc(res->ai_addr->sa_len);
2479a4365d0SYoshinobu Inoue 	if (newaddr == NULL) {
2483c62e87aSJun-ichiro itojun Hagino 		__ipsec_errcode = EIPSEC_NO_BUFS;
2499a4365d0SYoshinobu Inoue 		freeaddrinfo(res);
2509a4365d0SYoshinobu Inoue 		return NULL;
2519a4365d0SYoshinobu Inoue 	}
2529a4365d0SYoshinobu Inoue 	memcpy(newaddr, res->ai_addr, res->ai_addr->sa_len);
2539a4365d0SYoshinobu Inoue 
2549a4365d0SYoshinobu Inoue 	freeaddrinfo(res);
2559a4365d0SYoshinobu Inoue 
2563c62e87aSJun-ichiro itojun Hagino 	__ipsec_errcode = EIPSEC_NO_ERROR;
2579a4365d0SYoshinobu Inoue 	return newaddr;
2589a4365d0SYoshinobu Inoue }
2599a4365d0SYoshinobu Inoue 
2609a4365d0SYoshinobu Inoue static int
26158436df3SMateusz Guzik rule_check(void)
2629a4365d0SYoshinobu Inoue {
2639a4365d0SYoshinobu Inoue 	if (p_type == IPSEC_POLICY_IPSEC) {
2649a4365d0SYoshinobu Inoue 		if (p_protocol == IPPROTO_IP) {
2653c62e87aSJun-ichiro itojun Hagino 			__ipsec_errcode = EIPSEC_NO_PROTO;
2669a4365d0SYoshinobu Inoue 			return -1;
2679a4365d0SYoshinobu Inoue 		}
2689a4365d0SYoshinobu Inoue 
2699a4365d0SYoshinobu Inoue 		if (p_mode != IPSEC_MODE_TRANSPORT
2709a4365d0SYoshinobu Inoue 		 && p_mode != IPSEC_MODE_TUNNEL) {
2713c62e87aSJun-ichiro itojun Hagino 			__ipsec_errcode = EIPSEC_INVAL_MODE;
2729a4365d0SYoshinobu Inoue 			return -1;
2739a4365d0SYoshinobu Inoue 		}
2749a4365d0SYoshinobu Inoue 
2759a4365d0SYoshinobu Inoue 		if (p_src == NULL && p_dst == NULL) {
2769a4365d0SYoshinobu Inoue 			 if (p_mode != IPSEC_MODE_TRANSPORT) {
2773c62e87aSJun-ichiro itojun Hagino 				__ipsec_errcode = EIPSEC_INVAL_ADDRESS;
2789a4365d0SYoshinobu Inoue 				return -1;
2799a4365d0SYoshinobu Inoue 			}
2809a4365d0SYoshinobu Inoue 		}
2819a4365d0SYoshinobu Inoue 		else if (p_src->sa_family != p_dst->sa_family) {
2823c62e87aSJun-ichiro itojun Hagino 			__ipsec_errcode = EIPSEC_FAMILY_MISMATCH;
2839a4365d0SYoshinobu Inoue 			return -1;
2849a4365d0SYoshinobu Inoue 		}
2859a4365d0SYoshinobu Inoue 	}
2869a4365d0SYoshinobu Inoue 
2873c62e87aSJun-ichiro itojun Hagino 	__ipsec_errcode = EIPSEC_NO_ERROR;
2889a4365d0SYoshinobu Inoue 	return 0;
2899a4365d0SYoshinobu Inoue }
2909a4365d0SYoshinobu Inoue 
2919a4365d0SYoshinobu Inoue static int
29258436df3SMateusz Guzik init_x_policy(void)
2939a4365d0SYoshinobu Inoue {
2949a4365d0SYoshinobu Inoue 	struct sadb_x_policy *p;
2959a4365d0SYoshinobu Inoue 
2969a4365d0SYoshinobu Inoue 	tlen = sizeof(struct sadb_x_policy);
2979a4365d0SYoshinobu Inoue 
2989a4365d0SYoshinobu Inoue 	pbuf = malloc(tlen);
2999a4365d0SYoshinobu Inoue 	if (pbuf == NULL) {
3003c62e87aSJun-ichiro itojun Hagino 		__ipsec_errcode = EIPSEC_NO_BUFS;
3019a4365d0SYoshinobu Inoue 		return -1;
3029a4365d0SYoshinobu Inoue 	}
303bd9f52d5SHajimu UMEMOTO 	memset(pbuf, 0, tlen);
3049a4365d0SYoshinobu Inoue 	p = (struct sadb_x_policy *)pbuf;
3059a4365d0SYoshinobu Inoue 	p->sadb_x_policy_len = 0;	/* must update later */
3069a4365d0SYoshinobu Inoue 	p->sadb_x_policy_exttype = SADB_X_EXT_POLICY;
3079a4365d0SYoshinobu Inoue 	p->sadb_x_policy_type = p_type;
3089a4365d0SYoshinobu Inoue 	p->sadb_x_policy_dir = p_dir;
309bd9f52d5SHajimu UMEMOTO 	p->sadb_x_policy_id = 0;
310bd9f52d5SHajimu UMEMOTO 
3119a4365d0SYoshinobu Inoue 	offset = tlen;
3129a4365d0SYoshinobu Inoue 
3133c62e87aSJun-ichiro itojun Hagino 	__ipsec_errcode = EIPSEC_NO_ERROR;
3149a4365d0SYoshinobu Inoue 	return 0;
3159a4365d0SYoshinobu Inoue }
3169a4365d0SYoshinobu Inoue 
3179a4365d0SYoshinobu Inoue static int
31858436df3SMateusz Guzik set_x_request(struct sockaddr *src, struct sockaddr *dst)
3199a4365d0SYoshinobu Inoue {
3209a4365d0SYoshinobu Inoue 	struct sadb_x_ipsecrequest *p;
3219a4365d0SYoshinobu Inoue 	int reqlen;
3229a4365d0SYoshinobu Inoue 
3239a4365d0SYoshinobu Inoue 	reqlen = sizeof(*p)
3249a4365d0SYoshinobu Inoue 		+ (src ? src->sa_len : 0)
3259a4365d0SYoshinobu Inoue 		+ (dst ? dst->sa_len : 0);
3269a4365d0SYoshinobu Inoue 	tlen += reqlen;		/* increment to total length */
3279a4365d0SYoshinobu Inoue 
3289a4365d0SYoshinobu Inoue 	pbuf = realloc(pbuf, tlen);
3299a4365d0SYoshinobu Inoue 	if (pbuf == NULL) {
3303c62e87aSJun-ichiro itojun Hagino 		__ipsec_errcode = EIPSEC_NO_BUFS;
3319a4365d0SYoshinobu Inoue 		return -1;
3329a4365d0SYoshinobu Inoue 	}
3339a4365d0SYoshinobu Inoue 	p = (struct sadb_x_ipsecrequest *)&pbuf[offset];
3349a4365d0SYoshinobu Inoue 	p->sadb_x_ipsecrequest_len = reqlen;
3359a4365d0SYoshinobu Inoue 	p->sadb_x_ipsecrequest_proto = p_protocol;
3369a4365d0SYoshinobu Inoue 	p->sadb_x_ipsecrequest_mode = p_mode;
3379a4365d0SYoshinobu Inoue 	p->sadb_x_ipsecrequest_level = p_level;
3383c62e87aSJun-ichiro itojun Hagino 	p->sadb_x_ipsecrequest_reqid = p_reqid;
3399a4365d0SYoshinobu Inoue 	offset += sizeof(*p);
3409a4365d0SYoshinobu Inoue 
3419a4365d0SYoshinobu Inoue 	if (set_sockaddr(src) || set_sockaddr(dst))
3429a4365d0SYoshinobu Inoue 		return -1;
3439a4365d0SYoshinobu Inoue 
3443c62e87aSJun-ichiro itojun Hagino 	__ipsec_errcode = EIPSEC_NO_ERROR;
3459a4365d0SYoshinobu Inoue 	return 0;
3469a4365d0SYoshinobu Inoue }
3479a4365d0SYoshinobu Inoue 
3489a4365d0SYoshinobu Inoue static int
349*50ecbc51SLexi Winter set_sockaddr(const struct sockaddr *addr)
3509a4365d0SYoshinobu Inoue {
3519a4365d0SYoshinobu Inoue 	if (addr == NULL) {
3523c62e87aSJun-ichiro itojun Hagino 		__ipsec_errcode = EIPSEC_NO_ERROR;
3539a4365d0SYoshinobu Inoue 		return 0;
3549a4365d0SYoshinobu Inoue 	}
3559a4365d0SYoshinobu Inoue 
3569a4365d0SYoshinobu Inoue 	/* tlen has already incremented */
3579a4365d0SYoshinobu Inoue 
3589a4365d0SYoshinobu Inoue 	memcpy(&pbuf[offset], addr, addr->sa_len);
3599a4365d0SYoshinobu Inoue 
3609a4365d0SYoshinobu Inoue 	offset += addr->sa_len;
3619a4365d0SYoshinobu Inoue 
3623c62e87aSJun-ichiro itojun Hagino 	__ipsec_errcode = EIPSEC_NO_ERROR;
3639a4365d0SYoshinobu Inoue 	return 0;
3649a4365d0SYoshinobu Inoue }
3659a4365d0SYoshinobu Inoue 
3669a4365d0SYoshinobu Inoue static void
36758436df3SMateusz Guzik policy_parse_request_init(void)
3689a4365d0SYoshinobu Inoue {
3699a4365d0SYoshinobu Inoue 	p_protocol = IPPROTO_IP;
3709a4365d0SYoshinobu Inoue 	p_mode = IPSEC_MODE_ANY;
3719a4365d0SYoshinobu Inoue 	p_level = IPSEC_LEVEL_DEFAULT;
3723c62e87aSJun-ichiro itojun Hagino 	p_reqid = 0;
3739a4365d0SYoshinobu Inoue 	if (p_src != NULL) {
3749a4365d0SYoshinobu Inoue 		free(p_src);
3759a4365d0SYoshinobu Inoue 		p_src = NULL;
3769a4365d0SYoshinobu Inoue 	}
3779a4365d0SYoshinobu Inoue 	if (p_dst != NULL) {
3789a4365d0SYoshinobu Inoue 		free(p_dst);
3799a4365d0SYoshinobu Inoue 		p_dst = NULL;
3809a4365d0SYoshinobu Inoue 	}
3819a4365d0SYoshinobu Inoue 
3829a4365d0SYoshinobu Inoue 	return;
3839a4365d0SYoshinobu Inoue }
3849a4365d0SYoshinobu Inoue 
3859a4365d0SYoshinobu Inoue static caddr_t
386*50ecbc51SLexi Winter policy_parse(const char *msg, int msglen)
3879a4365d0SYoshinobu Inoue {
3889a4365d0SYoshinobu Inoue 	int error;
3899a4365d0SYoshinobu Inoue 	pbuf = NULL;
3909a4365d0SYoshinobu Inoue 	tlen = 0;
3919a4365d0SYoshinobu Inoue 
3929a4365d0SYoshinobu Inoue 	/* initialize */
3939a4365d0SYoshinobu Inoue 	p_dir = IPSEC_DIR_INVALID;
3949a4365d0SYoshinobu Inoue 	p_type = IPSEC_POLICY_DISCARD;
3959a4365d0SYoshinobu Inoue 	policy_parse_request_init();
3969a4365d0SYoshinobu Inoue 	__policy__strbuffer__init__(msg);
3979a4365d0SYoshinobu Inoue 
3989a4365d0SYoshinobu Inoue 	error = yyparse();	/* it must be set errcode. */
399bd9f52d5SHajimu UMEMOTO 	__policy__strbuffer__free__();
400bd9f52d5SHajimu UMEMOTO 
4019a4365d0SYoshinobu Inoue 	if (error) {
4029a4365d0SYoshinobu Inoue 		if (pbuf != NULL)
4039a4365d0SYoshinobu Inoue 			free(pbuf);
4049a4365d0SYoshinobu Inoue 		return NULL;
4059a4365d0SYoshinobu Inoue 	}
4069a4365d0SYoshinobu Inoue 
4079a4365d0SYoshinobu Inoue 	/* update total length */
4089a4365d0SYoshinobu Inoue 	((struct sadb_x_policy *)pbuf)->sadb_x_policy_len = PFKEY_UNIT64(tlen);
4099a4365d0SYoshinobu Inoue 
4103c62e87aSJun-ichiro itojun Hagino 	__ipsec_errcode = EIPSEC_NO_ERROR;
4119a4365d0SYoshinobu Inoue 
4129a4365d0SYoshinobu Inoue 	return pbuf;
4139a4365d0SYoshinobu Inoue }
4149a4365d0SYoshinobu Inoue 
4159a4365d0SYoshinobu Inoue caddr_t
416*50ecbc51SLexi Winter ipsec_set_policy(const char *msg, int msglen)
4179a4365d0SYoshinobu Inoue {
4189a4365d0SYoshinobu Inoue 	caddr_t policy;
4199a4365d0SYoshinobu Inoue 
4209a4365d0SYoshinobu Inoue 	policy = policy_parse(msg, msglen);
4219a4365d0SYoshinobu Inoue 	if (policy == NULL) {
4223c62e87aSJun-ichiro itojun Hagino 		if (__ipsec_errcode == EIPSEC_NO_ERROR)
4233c62e87aSJun-ichiro itojun Hagino 			__ipsec_errcode = EIPSEC_INVAL_ARGUMENT;
4249a4365d0SYoshinobu Inoue 		return NULL;
4259a4365d0SYoshinobu Inoue 	}
4269a4365d0SYoshinobu Inoue 
4273c62e87aSJun-ichiro itojun Hagino 	__ipsec_errcode = EIPSEC_NO_ERROR;
4289a4365d0SYoshinobu Inoue 	return policy;
4299a4365d0SYoshinobu Inoue }
4309a4365d0SYoshinobu Inoue 
431