1 /* $KAME: policy_parse.y,v 1.14 2003/06/27 03:39:20 itojun Exp $ */
4 * Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the project nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * IN/OUT bound policy configuration take place such below:
37 * <policy> is one of following:
38 * "discard", "none", "ipsec <requests>", "entrust", "bypass",
40 * The following requests are accepted as <requests>:
42 * protocol/mode/src-dst/level
43 * protocol/mode/src-dst parsed as protocol/mode/src-dst/default
44 * protocol/mode/src-dst/ parsed as protocol/mode/src-dst/default
45 * protocol/transport parsed as protocol/mode/any-any/default
46 * protocol/transport//level parsed as protocol/mode/any-any/level
48 * You can concatenate these requests with either ' '(single space) or '\n'.
52 #include <sys/cdefs.h>
53 __FBSDID
("$FreeBSD$");
55 #include <sys/types.h>
56 #include <sys/param.h>
57 #include <sys/socket.h>
59 #include <netinet/in.h>
60 #include <netipsec/ipsec.h>
67 #include "ipsec_strerror.h"
70 (isdigit
(c
) ?
(c
- '0') : (isupper
(c
) ?
(c
- 'A' + 10) : (c
- 'a' + 10) ))
72 static caddr_t pbuf
= NULL
; /* sadb_x_policy buffer */
73 static int tlen
= 0; /* total length of pbuf */
74 static int offset
= 0; /* offset of pbuf */
75 static int p_dir
, p_type
, p_protocol
, p_mode
, p_level
, p_reqid
;
76 static struct sockaddr
*p_src
= NULL
;
77 static struct sockaddr
*p_dst
= NULL
;
80 extern
void yyerror(char *msg
);
81 static struct sockaddr
*parse_sockaddr
(struct _val
*buf
);
82 static int rule_check
(void);
83 static int init_x_policy
(void);
84 static int set_x_request
(struct sockaddr
*src
, struct sockaddr
*dst
);
85 static int set_sockaddr
(struct sockaddr
*addr
);
86 static void policy_parse_request_init
(void);
87 static caddr_t policy_parse
(char *msg
, int msglen
);
89 extern
void __policy__strbuffer__init__
(char *msg
);
90 extern
void __policy__strbuffer__free__
(void);
91 extern
int yylex(void);
93 extern
char *__libipsecyytext
; /*XXX*/
105 %token
DIR ACTION PROTOCOL MODE LEVEL LEVEL_SPECIFY
109 %type
<num
> DIR ACTION PROTOCOL MODE LEVEL
110 %type
<val
> IPADDRESS LEVEL_SPECIFY
126 p_type
= 0; /* ignored it by kernel */
136 if
(rule_check
() < 0)
139 if
(set_x_request
(p_src
, p_dst
) < 0)
142 policy_parse_request_init
();
147 : protocol SLASH mode SLASH addresses SLASH level
148 | protocol SLASH mode SLASH addresses SLASH
149 | protocol SLASH mode SLASH addresses
150 | protocol SLASH mode SLASH
151 | protocol SLASH mode SLASH SLASH level
152 | protocol SLASH mode
154 __ipsec_errcode
= EIPSEC_FEW_ARGUMENTS
;
158 __ipsec_errcode
= EIPSEC_FEW_ARGUMENTS
;
164 : PROTOCOL
{ p_protocol
= $1; }
168 : MODE
{ p_mode
= $1; }
177 p_level
= IPSEC_LEVEL_UNIQUE
;
178 p_reqid
= atol
($1.buf
); /* atol() is good. */
184 p_src
= parse_sockaddr
(&$1);
190 p_dst
= parse_sockaddr
(&$4);
195 if
(p_dir
!= IPSEC_DIR_OUTBOUND
) {
196 __ipsec_errcode
= EIPSEC_INVAL_DIR
;
201 if
(p_dir
!= IPSEC_DIR_INBOUND
) {
202 __ipsec_errcode
= EIPSEC_INVAL_DIR
;
217 fprintf
(stderr
, "libipsec: %s while parsing \"%s\"\n",
218 msg
, __libipsecyytext
);
223 static struct sockaddr
*
227 struct addrinfo hints
, *res
;
230 struct sockaddr
*newaddr
= NULL
;
232 memset
(&hints
, 0, sizeof
(hints
));
233 hints.ai_family
= PF_UNSPEC
;
234 hints.ai_flags
= AI_NUMERICHOST
;
235 error = getaddrinfo
(buf
->buf
, serv
, &hints
, &res
);
237 yyerror("invalid IP address");
238 __ipsec_set_strerror
(gai_strerror
(error));
242 if
(res
->ai_addr
== NULL
) {
243 yyerror("invalid IP address");
244 __ipsec_set_strerror
(gai_strerror
(error));
248 newaddr
= malloc
(res
->ai_addr
->sa_len
);
249 if
(newaddr
== NULL
) {
250 __ipsec_errcode
= EIPSEC_NO_BUFS
;
254 memcpy
(newaddr
, res
->ai_addr
, res
->ai_addr
->sa_len
);
258 __ipsec_errcode
= EIPSEC_NO_ERROR
;
265 if
(p_type
== IPSEC_POLICY_IPSEC
) {
266 if
(p_protocol
== IPPROTO_IP
) {
267 __ipsec_errcode
= EIPSEC_NO_PROTO
;
271 if
(p_mode
!= IPSEC_MODE_TRANSPORT
272 && p_mode
!= IPSEC_MODE_TUNNEL
) {
273 __ipsec_errcode
= EIPSEC_INVAL_MODE
;
277 if
(p_src
== NULL
&& p_dst
== NULL
) {
278 if
(p_mode
!= IPSEC_MODE_TRANSPORT
) {
279 __ipsec_errcode
= EIPSEC_INVAL_ADDRESS
;
283 else if
(p_src
->sa_family
!= p_dst
->sa_family
) {
284 __ipsec_errcode
= EIPSEC_FAMILY_MISMATCH
;
289 __ipsec_errcode
= EIPSEC_NO_ERROR
;
296 struct sadb_x_policy
*p
;
298 tlen
= sizeof
(struct sadb_x_policy
);
302 __ipsec_errcode
= EIPSEC_NO_BUFS
;
305 memset
(pbuf
, 0, tlen
);
306 p
= (struct sadb_x_policy
*)pbuf
;
307 p
->sadb_x_policy_len
= 0; /* must update later */
308 p
->sadb_x_policy_exttype
= SADB_X_EXT_POLICY
;
309 p
->sadb_x_policy_type
= p_type
;
310 p
->sadb_x_policy_dir
= p_dir
;
311 p
->sadb_x_policy_id
= 0;
315 __ipsec_errcode
= EIPSEC_NO_ERROR
;
320 set_x_request
(src
, dst
)
321 struct sockaddr
*src
, *dst
;
323 struct sadb_x_ipsecrequest
*p
;
327 + (src ? src
->sa_len
: 0)
328 + (dst ? dst
->sa_len
: 0);
329 tlen
+= reqlen
; /* increment to total length */
331 pbuf
= realloc
(pbuf
, tlen
);
333 __ipsec_errcode
= EIPSEC_NO_BUFS
;
336 p
= (struct sadb_x_ipsecrequest
*)&pbuf
[offset
];
337 p
->sadb_x_ipsecrequest_len
= reqlen
;
338 p
->sadb_x_ipsecrequest_proto
= p_protocol
;
339 p
->sadb_x_ipsecrequest_mode
= p_mode
;
340 p
->sadb_x_ipsecrequest_level
= p_level
;
341 p
->sadb_x_ipsecrequest_reqid
= p_reqid
;
342 offset
+= sizeof
(*p
);
344 if
(set_sockaddr
(src
) || set_sockaddr
(dst
))
347 __ipsec_errcode
= EIPSEC_NO_ERROR
;
353 struct sockaddr
*addr
;
356 __ipsec_errcode
= EIPSEC_NO_ERROR
;
360 /* tlen has already incremented */
362 memcpy
(&pbuf
[offset
], addr
, addr
->sa_len
);
364 offset
+= addr
->sa_len
;
366 __ipsec_errcode
= EIPSEC_NO_ERROR
;
371 policy_parse_request_init
()
373 p_protocol
= IPPROTO_IP
;
374 p_mode
= IPSEC_MODE_ANY
;
375 p_level
= IPSEC_LEVEL_DEFAULT
;
390 policy_parse
(msg
, msglen
)
399 p_dir
= IPSEC_DIR_INVALID
;
400 p_type
= IPSEC_POLICY_DISCARD
;
401 policy_parse_request_init
();
402 __policy__strbuffer__init__
(msg
);
404 error = yyparse(); /* it must be set errcode. */
405 __policy__strbuffer__free__
();
413 /* update total length */
414 ((struct sadb_x_policy
*)pbuf
)->sadb_x_policy_len
= PFKEY_UNIT64
(tlen
);
416 __ipsec_errcode
= EIPSEC_NO_ERROR
;
422 ipsec_set_policy
(msg
, msglen
)
428 policy
= policy_parse
(msg
, msglen
);
429 if
(policy
== NULL
) {
430 if
(__ipsec_errcode
== EIPSEC_NO_ERROR
)
431 __ipsec_errcode
= EIPSEC_INVAL_ARGUMENT
;
435 __ipsec_errcode
= EIPSEC_NO_ERROR
;