1 /* $NetBSD: policy_parse.y,v 1.10 2007/07/18 12:07:50 vanhu Exp $ */
3 /* $KAME: policy_parse.y,v 1.21 2003/12/12 08:01:26 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:
36 * in <priority> <policy>
37 * out <priority> <policy>
39 * <priority> is one of the following:
40 * priority <signed int> where the integer is an offset from the default
41 * priority, where negative numbers indicate lower
42 * priority (towards end of list) and positive numbers
43 * indicate higher priority (towards beginning of list)
45 * priority {low,def,high} {+,-} <unsigned int> where low and high are
46 * constants which are closer
47 * to the end of the list and
48 * beginning of the list,
51 * <policy> is one of following:
52 * "discard", "none", "ipsec <requests>", "entrust", "bypass",
54 * The following requests are accepted as <requests>:
56 * protocol/mode/src-dst/level
57 * protocol/mode/src-dst parsed as protocol/mode/src-dst/default
58 * protocol/mode/src-dst/ parsed as protocol/mode/src-dst/default
59 * protocol/transport parsed as protocol/mode/any-any/default
60 * protocol/transport//level parsed as protocol/mode/any-any/level
62 * You can concatenate these requests with either ' '(single space) or '\n'.
70 #include <sys/types.h>
71 #include <sys/param.h>
72 #include <sys/socket.h>
74 #include <netinet/in.h>
86 #include "ipsec_strerror.h"
90 #define INT32_MAX (0xffffffff)
94 #define INT32_MIN (-INT32_MAX-1)
98 (isdigit
(c
) ?
(c
- '0') : (isupper
(c
) ?
(c
- 'A' + 10) : (c
- 'a' + 10) ))
100 static u_int8_t
*pbuf
= NULL
; /* sadb_x_policy buffer */
101 static int tlen
= 0; /* total length of pbuf */
102 static int offset
= 0; /* offset of pbuf */
103 static int p_dir
, p_type
, p_protocol
, p_mode
, p_level
, p_reqid
;
104 static u_int32_t p_priority
= 0;
105 static long p_priority_offset
= 0;
106 static struct sockaddr
*p_src
= NULL
;
107 static struct sockaddr
*p_dst
= NULL
;
110 extern
void yyerror __P
((char *msg
));
111 static struct sockaddr
*parse_sockaddr __P
((struct _val
*addrbuf
,
112 struct _val
*portbuf
));
113 static int rule_check __P
((void));
114 static int init_x_policy __P
((void));
115 static int set_x_request __P
((struct sockaddr
*, struct sockaddr
*));
116 static int set_sockaddr __P
((struct sockaddr
*));
117 static void policy_parse_request_init __P
((void));
118 static void *policy_parse __P
((const char *, int));
120 extern
void __policy__strbuffer__init__ __P
((const char *));
121 extern
void __policy__strbuffer__free__ __P
((void));
122 extern
int yyparse __P
((void));
123 extern
int yylex __P
((void));
125 extern
char *__libipsectext
; /*XXX*/
140 %token
<num32
> PRIO_BASE
141 %token
<val
> PRIO_OFFSET
142 %token ACTION PROTOCOL MODE LEVEL LEVEL_SPECIFY IPADDRESS PORT
145 %type
<num
> DIR PRIORITY ACTION PROTOCOL MODE LEVEL
146 %type
<val
> IPADDRESS LEVEL_SPECIFY PORT
155 #ifdef HAVE_PFKEY_POLICY_PRIORITY
156 p_priority
= PRIORITY_DEFAULT
;
165 |
DIR PRIORITY PRIO_OFFSET ACTION
169 p_priority_offset
= -atol
($3.buf
);
172 if
(errno
!= 0 || p_priority_offset
< INT32_MIN
)
174 __ipsec_errcode
= EIPSEC_INVAL_PRIORITY_OFFSET
;
178 p_priority
= PRIORITY_DEFAULT
+ (u_int32_t
) p_priority_offset
;
184 |
DIR PRIORITY HYPHEN PRIO_OFFSET ACTION
190 p_priority_offset
= atol
($4.buf
);
192 if
(errno
!= 0 || p_priority_offset
> INT32_MAX
)
194 __ipsec_errcode
= EIPSEC_INVAL_PRIORITY_OFFSET
;
198 /* negative input value means lower priority, therefore higher
199 actual value so that is closer to the end of the list */
200 p_priority
= PRIORITY_DEFAULT
+ (u_int32_t
) p_priority_offset
;
206 |
DIR PRIORITY PRIO_BASE ACTION
217 |
DIR PRIORITY PRIO_BASE PLUS PRIO_OFFSET ACTION
223 p_priority_offset
= atol
($5.buf
);
225 if
(errno
!= 0 || p_priority_offset
> PRIORITY_OFFSET_NEGATIVE_MAX
)
227 __ipsec_errcode
= EIPSEC_INVAL_PRIORITY_BASE_OFFSET
;
231 /* adding value means higher priority, therefore lower
232 actual value so that is closer to the beginning of the list */
233 p_priority
= $3 - (u_int32_t
) p_priority_offset
;
239 |
DIR PRIORITY PRIO_BASE HYPHEN PRIO_OFFSET ACTION
245 p_priority_offset
= atol
($5.buf
);
247 if
(errno
!= 0 || p_priority_offset
> PRIORITY_OFFSET_POSITIVE_MAX
)
249 __ipsec_errcode
= EIPSEC_INVAL_PRIORITY_BASE_OFFSET
;
253 /* subtracting value means lower priority, therefore higher
254 actual value so that is closer to the end of the list */
255 p_priority
= $3 + (u_int32_t
) p_priority_offset
;
264 p_type
= 0; /* ignored it by kernel */
276 if
(rule_check
() < 0)
279 if
(set_x_request
(p_src
, p_dst
) < 0)
282 policy_parse_request_init
();
287 : protocol SLASH mode SLASH addresses SLASH level
288 | protocol SLASH mode SLASH addresses SLASH
289 | protocol SLASH mode SLASH addresses
290 | protocol SLASH mode SLASH
291 | protocol SLASH mode SLASH SLASH level
292 | protocol SLASH mode
294 __ipsec_errcode
= EIPSEC_FEW_ARGUMENTS
;
298 __ipsec_errcode
= EIPSEC_FEW_ARGUMENTS
;
304 : PROTOCOL
{ p_protocol
= $1; }
308 : MODE
{ p_mode
= $1; }
317 p_level
= IPSEC_LEVEL_UNIQUE
;
318 p_reqid
= atol
($1.buf
); /* atol() is good. */
324 p_src
= parse_sockaddr
(&$1, NULL
);
330 p_dst
= parse_sockaddr
(&$4, NULL
);
335 p_src
= parse_sockaddr
(&$1, &$2);
341 p_dst
= parse_sockaddr
(&$5, &$6);
346 if
(p_dir
!= IPSEC_DIR_OUTBOUND
) {
347 __ipsec_errcode
= EIPSEC_INVAL_DIR
;
352 if
(p_dir
!= IPSEC_DIR_INBOUND
) {
353 __ipsec_errcode
= EIPSEC_INVAL_DIR
;
368 fprintf
(stderr
, "libipsec: %s while parsing \"%s\"\n",
369 msg
, __libipsectext
);
374 static struct sockaddr
*
375 parse_sockaddr
(addrbuf
, portbuf
)
376 struct _val
*addrbuf
;
377 struct _val
*portbuf
;
379 struct addrinfo hints
, *res
;
383 struct sockaddr
*newaddr
= NULL
;
385 if
((addr
= malloc
(addrbuf
->len
+ 1)) == NULL
) {
386 yyerror("malloc failed");
387 __ipsec_set_strerror
(strerror
(errno
));
391 if
(portbuf
&& ((serv
= malloc
(portbuf
->len
+ 1)) == NULL
)) {
393 yyerror("malloc failed");
394 __ipsec_set_strerror
(strerror
(errno
));
398 strncpy
(addr
, addrbuf
->buf
, addrbuf
->len
);
399 addr
[addrbuf
->len
] = '\0';
402 strncpy
(serv
, portbuf
->buf
, portbuf
->len
);
403 serv
[portbuf
->len
] = '\0';
406 memset
(&hints
, 0, sizeof
(hints
));
407 hints.ai_family
= PF_UNSPEC
;
408 hints.ai_flags
= AI_NUMERICHOST
;
409 hints.ai_socktype
= SOCK_DGRAM
;
410 error = getaddrinfo
(addr
, serv
, &hints
, &res
);
415 yyerror("invalid IP address");
416 __ipsec_set_strerror
(gai_strerror
(error));
420 if
(res
->ai_addr
== NULL
) {
421 yyerror("invalid IP address");
422 __ipsec_set_strerror
(gai_strerror
(error));
426 newaddr
= malloc
(res
->ai_addrlen
);
427 if
(newaddr
== NULL
) {
428 __ipsec_errcode
= EIPSEC_NO_BUFS
;
432 memcpy
(newaddr
, res
->ai_addr
, res
->ai_addrlen
);
436 __ipsec_errcode
= EIPSEC_NO_ERROR
;
443 if
(p_type
== IPSEC_POLICY_IPSEC
) {
444 if
(p_protocol
== IPPROTO_IP
) {
445 __ipsec_errcode
= EIPSEC_NO_PROTO
;
449 if
(p_mode
!= IPSEC_MODE_TRANSPORT
450 && p_mode
!= IPSEC_MODE_TUNNEL
) {
451 __ipsec_errcode
= EIPSEC_INVAL_MODE
;
455 if
(p_src
== NULL
&& p_dst
== NULL
) {
456 if
(p_mode
!= IPSEC_MODE_TRANSPORT
) {
457 __ipsec_errcode
= EIPSEC_INVAL_ADDRESS
;
461 else if
(p_src
->sa_family
!= p_dst
->sa_family
) {
462 __ipsec_errcode
= EIPSEC_FAMILY_MISMATCH
;
467 __ipsec_errcode
= EIPSEC_NO_ERROR
;
474 struct sadb_x_policy
*p
;
480 pbuf
= malloc
(sizeof
(struct sadb_x_policy
));
482 __ipsec_errcode
= EIPSEC_NO_BUFS
;
485 tlen
= sizeof
(struct sadb_x_policy
);
487 memset
(pbuf
, 0, tlen
);
488 p
= (struct sadb_x_policy
*)pbuf
;
489 p
->sadb_x_policy_len
= 0; /* must update later */
490 p
->sadb_x_policy_exttype
= SADB_X_EXT_POLICY
;
491 p
->sadb_x_policy_type
= p_type
;
492 p
->sadb_x_policy_dir
= p_dir
;
493 p
->sadb_x_policy_id
= 0;
494 #ifdef HAVE_PFKEY_POLICY_PRIORITY
495 p
->sadb_x_policy_priority
= p_priority
;
497 /* fail if given a priority and libipsec was not compiled with
501 __ipsec_errcode
= EIPSEC_PRIORITY_NOT_COMPILED
;
508 __ipsec_errcode
= EIPSEC_NO_ERROR
;
513 set_x_request
(src
, dst
)
514 struct sockaddr
*src
, *dst
;
516 struct sadb_x_ipsecrequest
*p
;
521 + (src ? sysdep_sa_len
(src
) : 0)
522 + (dst ? sysdep_sa_len
(dst
) : 0);
523 tlen
+= reqlen
; /* increment to total length */
525 n
= realloc
(pbuf
, tlen
);
527 __ipsec_errcode
= EIPSEC_NO_BUFS
;
532 p
= (struct sadb_x_ipsecrequest
*)&pbuf
[offset
];
533 p
->sadb_x_ipsecrequest_len
= reqlen
;
534 p
->sadb_x_ipsecrequest_proto
= p_protocol
;
535 p
->sadb_x_ipsecrequest_mode
= p_mode
;
536 p
->sadb_x_ipsecrequest_level
= p_level
;
537 p
->sadb_x_ipsecrequest_reqid
= p_reqid
;
538 offset
+= sizeof
(*p
);
540 if
(set_sockaddr
(src
) || set_sockaddr
(dst
))
543 __ipsec_errcode
= EIPSEC_NO_ERROR
;
549 struct sockaddr
*addr
;
552 __ipsec_errcode
= EIPSEC_NO_ERROR
;
556 /* tlen has already incremented */
558 memcpy
(&pbuf
[offset
], addr
, sysdep_sa_len
(addr
));
560 offset
+= sysdep_sa_len
(addr
);
562 __ipsec_errcode
= EIPSEC_NO_ERROR
;
567 policy_parse_request_init
()
569 p_protocol
= IPPROTO_IP
;
570 p_mode
= IPSEC_MODE_ANY
;
571 p_level
= IPSEC_LEVEL_DEFAULT
;
586 policy_parse
(msg
, msglen
)
596 p_dir
= IPSEC_DIR_INVALID
;
597 p_type
= IPSEC_POLICY_DISCARD
;
598 policy_parse_request_init
();
599 __policy__strbuffer__init__
(msg
);
601 error = yyparse(); /* it must be set errcode. */
602 __policy__strbuffer__free__
();
610 /* update total length */
611 ((struct sadb_x_policy
*)pbuf
)->sadb_x_policy_len
= PFKEY_UNIT64
(tlen
);
613 __ipsec_errcode
= EIPSEC_NO_ERROR
;
619 ipsec_set_policy
(msg
, msglen
)
620 __ipsec_const
char *msg
;
625 policy
= policy_parse
(msg
, msglen
);
626 if
(policy
== NULL
) {
627 if
(__ipsec_errcode
== EIPSEC_NO_ERROR
)
628 __ipsec_errcode
= EIPSEC_INVAL_ARGUMENT
;
632 __ipsec_errcode
= EIPSEC_NO_ERROR
;