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.3 2003/11/12 20:21:30 eirikn 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
;
214 extern
char *__libipsecyytext
; /*XXX*/
216 fprintf
(stderr
, "libipsec: %s while parsing \"%s\"\n",
217 msg
, __libipsecyytext
);
222 static struct sockaddr
*
226 struct addrinfo hints
, *res
;
229 struct sockaddr
*newaddr
= NULL
;
231 memset
(&hints
, 0, sizeof
(hints
));
232 hints.ai_family
= PF_UNSPEC
;
233 hints.ai_flags
= AI_NUMERICHOST
;
234 error = getaddrinfo
(buf
->buf
, serv
, &hints
, &res
);
236 yyerror("invalid IP address");
237 __ipsec_set_strerror
(gai_strerror
(error));
241 if
(res
->ai_addr
== NULL
) {
242 yyerror("invalid IP address");
243 __ipsec_set_strerror
(gai_strerror
(error));
247 newaddr
= malloc
(res
->ai_addr
->sa_len
);
248 if
(newaddr
== NULL
) {
249 __ipsec_errcode
= EIPSEC_NO_BUFS
;
253 memcpy
(newaddr
, res
->ai_addr
, res
->ai_addr
->sa_len
);
257 __ipsec_errcode
= EIPSEC_NO_ERROR
;
264 if
(p_type
== IPSEC_POLICY_IPSEC
) {
265 if
(p_protocol
== IPPROTO_IP
) {
266 __ipsec_errcode
= EIPSEC_NO_PROTO
;
270 if
(p_mode
!= IPSEC_MODE_TRANSPORT
271 && p_mode
!= IPSEC_MODE_TUNNEL
) {
272 __ipsec_errcode
= EIPSEC_INVAL_MODE
;
276 if
(p_src
== NULL
&& p_dst
== NULL
) {
277 if
(p_mode
!= IPSEC_MODE_TRANSPORT
) {
278 __ipsec_errcode
= EIPSEC_INVAL_ADDRESS
;
282 else if
(p_src
->sa_family
!= p_dst
->sa_family
) {
283 __ipsec_errcode
= EIPSEC_FAMILY_MISMATCH
;
288 __ipsec_errcode
= EIPSEC_NO_ERROR
;
295 struct sadb_x_policy
*p
;
297 tlen
= sizeof
(struct sadb_x_policy
);
301 __ipsec_errcode
= EIPSEC_NO_BUFS
;
304 p
= (struct sadb_x_policy
*)pbuf
;
305 p
->sadb_x_policy_len
= 0; /* must update later */
306 p
->sadb_x_policy_exttype
= SADB_X_EXT_POLICY
;
307 p
->sadb_x_policy_type
= p_type
;
308 p
->sadb_x_policy_dir
= p_dir
;
309 p
->sadb_x_policy_reserved
= 0;
312 __ipsec_errcode
= EIPSEC_NO_ERROR
;
317 set_x_request
(src
, dst
)
318 struct sockaddr
*src
, *dst
;
320 struct sadb_x_ipsecrequest
*p
;
324 + (src ? src
->sa_len
: 0)
325 + (dst ? dst
->sa_len
: 0);
326 tlen
+= reqlen
; /* increment to total length */
328 pbuf
= realloc
(pbuf
, tlen
);
330 __ipsec_errcode
= EIPSEC_NO_BUFS
;
333 p
= (struct sadb_x_ipsecrequest
*)&pbuf
[offset
];
334 p
->sadb_x_ipsecrequest_len
= reqlen
;
335 p
->sadb_x_ipsecrequest_proto
= p_protocol
;
336 p
->sadb_x_ipsecrequest_mode
= p_mode
;
337 p
->sadb_x_ipsecrequest_level
= p_level
;
338 p
->sadb_x_ipsecrequest_reqid
= p_reqid
;
339 offset
+= sizeof
(*p
);
341 if
(set_sockaddr
(src
) || set_sockaddr
(dst
))
344 __ipsec_errcode
= EIPSEC_NO_ERROR
;
350 struct sockaddr
*addr
;
353 __ipsec_errcode
= EIPSEC_NO_ERROR
;
357 /* tlen has already incremented */
359 memcpy
(&pbuf
[offset
], addr
, addr
->sa_len
);
361 offset
+= addr
->sa_len
;
363 __ipsec_errcode
= EIPSEC_NO_ERROR
;
368 policy_parse_request_init
()
370 p_protocol
= IPPROTO_IP
;
371 p_mode
= IPSEC_MODE_ANY
;
372 p_level
= IPSEC_LEVEL_DEFAULT
;
387 policy_parse
(msg
, msglen
)
396 p_dir
= IPSEC_DIR_INVALID
;
397 p_type
= IPSEC_POLICY_DISCARD
;
398 policy_parse_request_init
();
399 __policy__strbuffer__init__
(msg
);
401 error = yyparse(); /* it must be set errcode. */
408 /* update total length */
409 ((struct sadb_x_policy
*)pbuf
)->sadb_x_policy_len
= PFKEY_UNIT64
(tlen
);
411 __ipsec_errcode
= EIPSEC_NO_ERROR
;
417 ipsec_set_policy
(msg
, msglen
)
423 policy
= policy_parse
(msg
, msglen
);
424 if
(policy
== NULL
) {
425 if
(__ipsec_errcode
== EIPSEC_NO_ERROR
)
426 __ipsec_errcode
= EIPSEC_INVAL_ARGUMENT
;
430 __ipsec_errcode
= EIPSEC_NO_ERROR
;