1 /* $FreeBSD: src/lib/libipsec/policy_parse.y,v 1.1.2.1 2000/07/15 07:24:04 kris Exp $ */
2 /* $DragonFly: src/lib/libipsec/policy_parse.y,v 1.4 2008/09/30 16:57:05 swildner Exp $ */
3 /* $KAME: policy_parse.y,v 1.10 2000/05/07 05:25:03 itojun Exp $ */
6 * Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project.
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. Neither the name of the project nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 * IN/OUT bound policy configuration take place such below:
39 * <policy> is one of following:
40 * "discard", "none", "ipsec <requests>", "entrust", "bypass",
42 * The following requests are accepted as <requests>:
44 * protocol/mode/src-dst/level
45 * protocol/mode/src-dst parsed as protocol/mode/src-dst/default
46 * protocol/mode/src-dst/ parsed as protocol/mode/src-dst/default
47 * protocol/transport parsed as protocol/mode/any-any/default
48 * protocol/transport//level parsed as protocol/mode/any-any/level
50 * You can concatenate these requests with either ' '(single space) or '\n'.
54 #include <sys/types.h>
55 #include <sys/param.h>
56 #include <sys/socket.h>
58 #include <netinet/in.h>
59 #include <netinet6/ipsec.h>
66 #include "ipsec_strerror.h"
69 (isdigit
(c
) ?
(c
- '0') : (isupper
(c
) ?
(c
- 'A' + 10) : (c
- 'a' + 10) ))
71 static caddr_t pbuf
= NULL
; /* sadb_x_policy buffer */
72 static int tlen
= 0; /* total length of pbuf */
73 static int offset
= 0; /* offset of pbuf */
74 static int p_dir
, p_type
, p_protocol
, p_mode
, p_level
, p_reqid
;
75 static struct sockaddr
*p_src
= NULL
;
76 static struct sockaddr
*p_dst
= NULL
;
79 extern
void yyerror (char *msg
);
80 static struct sockaddr
*parse_sockaddr
(struct _val
*buf
);
81 static int rule_check
(void);
82 static int init_x_policy
(void);
83 static int set_x_request
(struct sockaddr
*src
, struct sockaddr
*dst
);
84 static int set_sockaddr
(struct sockaddr
*addr
);
85 static void policy_parse_request_init
(void);
86 static caddr_t policy_parse
(char *msg
, int msglen
);
88 extern
void __policy__strbuffer__init__
(char *msg
);
89 extern
int yyparse (void);
90 extern
int yylex (void);
102 %token
DIR ACTION PROTOCOL MODE LEVEL LEVEL_SPECIFY
106 %type
<num
> DIR ACTION PROTOCOL MODE LEVEL
107 %type
<val
> IPADDRESS LEVEL_SPECIFY
123 p_type
= 0; /* ignored it by kernel */
133 if
(rule_check
() < 0)
136 if
(set_x_request
(p_src
, p_dst
) < 0)
139 policy_parse_request_init
();
144 : protocol SLASH mode SLASH addresses SLASH level
145 | protocol SLASH mode SLASH addresses SLASH
146 | protocol SLASH mode SLASH addresses
147 | protocol SLASH mode SLASH
148 | protocol SLASH mode SLASH SLASH level
149 | protocol SLASH mode
151 __ipsec_errcode
= EIPSEC_FEW_ARGUMENTS
;
155 __ipsec_errcode
= EIPSEC_FEW_ARGUMENTS
;
161 : PROTOCOL
{ p_protocol
= $1; }
165 : MODE
{ p_mode
= $1; }
174 p_level
= IPSEC_LEVEL_UNIQUE
;
175 p_reqid
= atol
($1.buf
); /* atol() is good. */
181 p_src
= parse_sockaddr
(&$1);
187 p_dst
= parse_sockaddr
(&$4);
192 if
(p_dir
!= IPSEC_DIR_OUTBOUND
) {
193 __ipsec_errcode
= EIPSEC_INVAL_DIR
;
198 if
(p_dir
!= IPSEC_DIR_INBOUND
) {
199 __ipsec_errcode
= EIPSEC_INVAL_DIR
;
213 extern
char *__libipsecyytext
; /*XXX*/
215 fprintf
(stderr
, "libipsec: %s while parsing \"%s\"\n",
216 msg
, __libipsecyytext
);
221 static struct sockaddr
*
222 parse_sockaddr
(struct _val
*buf
)
224 struct addrinfo hints
, *res
;
227 struct sockaddr
*newaddr
= NULL
;
229 memset
(&hints
, 0, sizeof
(hints
));
230 hints.ai_family
= PF_UNSPEC
;
231 hints.ai_flags
= AI_NUMERICHOST
;
232 error = getaddrinfo
(buf
->buf
, serv
, &hints
, &res
);
234 yyerror("invalid IP address");
235 __ipsec_set_strerror
(gai_strerror
(error));
239 if
(res
->ai_addr
== NULL
) {
240 yyerror("invalid IP address");
241 __ipsec_set_strerror
(gai_strerror
(error));
245 newaddr
= malloc
(res
->ai_addr
->sa_len
);
246 if
(newaddr
== NULL
) {
247 __ipsec_errcode
= EIPSEC_NO_BUFS
;
251 memcpy
(newaddr
, res
->ai_addr
, res
->ai_addr
->sa_len
);
255 __ipsec_errcode
= EIPSEC_NO_ERROR
;
262 if
(p_type
== IPSEC_POLICY_IPSEC
) {
263 if
(p_protocol
== IPPROTO_IP
) {
264 __ipsec_errcode
= EIPSEC_NO_PROTO
;
268 if
(p_mode
!= IPSEC_MODE_TRANSPORT
269 && p_mode
!= IPSEC_MODE_TUNNEL
) {
270 __ipsec_errcode
= EIPSEC_INVAL_MODE
;
274 if
(p_src
== NULL
&& p_dst
== NULL
) {
275 if
(p_mode
!= IPSEC_MODE_TRANSPORT
) {
276 __ipsec_errcode
= EIPSEC_INVAL_ADDRESS
;
280 else if
(p_src
->sa_family
!= p_dst
->sa_family
) {
281 __ipsec_errcode
= EIPSEC_FAMILY_MISMATCH
;
286 __ipsec_errcode
= EIPSEC_NO_ERROR
;
293 struct sadb_x_policy
*p
;
295 tlen
= sizeof
(struct sadb_x_policy
);
299 __ipsec_errcode
= EIPSEC_NO_BUFS
;
302 p
= (struct sadb_x_policy
*)pbuf
;
303 p
->sadb_x_policy_len
= 0; /* must update later */
304 p
->sadb_x_policy_exttype
= SADB_X_EXT_POLICY
;
305 p
->sadb_x_policy_type
= p_type
;
306 p
->sadb_x_policy_dir
= p_dir
;
307 p
->sadb_x_policy_reserved
= 0;
310 __ipsec_errcode
= EIPSEC_NO_ERROR
;
315 set_x_request
(struct sockaddr
*src
, struct sockaddr
*dst
)
317 struct sadb_x_ipsecrequest
*p
;
321 + (src ? src
->sa_len
: 0)
322 + (dst ? dst
->sa_len
: 0);
323 tlen
+= reqlen
; /* increment to total length */
325 pbuf
= realloc
(pbuf
, tlen
);
327 __ipsec_errcode
= EIPSEC_NO_BUFS
;
330 p
= (struct sadb_x_ipsecrequest
*)&pbuf
[offset
];
331 p
->sadb_x_ipsecrequest_len
= reqlen
;
332 p
->sadb_x_ipsecrequest_proto
= p_protocol
;
333 p
->sadb_x_ipsecrequest_mode
= p_mode
;
334 p
->sadb_x_ipsecrequest_level
= p_level
;
335 p
->sadb_x_ipsecrequest_reqid
= p_reqid
;
336 offset
+= sizeof
(*p
);
338 if
(set_sockaddr
(src
) || set_sockaddr
(dst
))
341 __ipsec_errcode
= EIPSEC_NO_ERROR
;
346 set_sockaddr
(struct sockaddr
*addr
)
349 __ipsec_errcode
= EIPSEC_NO_ERROR
;
353 /* tlen has already incremented */
355 memcpy
(&pbuf
[offset
], addr
, addr
->sa_len
);
357 offset
+= addr
->sa_len
;
359 __ipsec_errcode
= EIPSEC_NO_ERROR
;
364 policy_parse_request_init
(void)
366 p_protocol
= IPPROTO_IP
;
367 p_mode
= IPSEC_MODE_ANY
;
368 p_level
= IPSEC_LEVEL_DEFAULT
;
383 policy_parse
(char *msg
, int msglen
)
390 p_dir
= IPSEC_DIR_INVALID
;
391 p_type
= IPSEC_POLICY_DISCARD
;
392 policy_parse_request_init
();
393 __policy__strbuffer__init__
(msg
);
395 error = yyparse(); /* it must be set errcode. */
402 /* update total length */
403 ((struct sadb_x_policy
*)pbuf
)->sadb_x_policy_len
= PFKEY_UNIT64
(tlen
);
405 __ipsec_errcode
= EIPSEC_NO_ERROR
;
411 ipsec_set_policy
(char *msg
, int msglen
)
415 policy
= policy_parse
(msg
, msglen
);
416 if
(policy
== NULL
) {
417 if
(__ipsec_errcode
== EIPSEC_NO_ERROR
)
418 __ipsec_errcode
= EIPSEC_INVAL_ARGUMENT
;
422 __ipsec_errcode
= EIPSEC_NO_ERROR
;