]>
Commit | Line | Data |
---|---|---|
52b7d2ce A |
1 | /* $KAME: policy_parse.y,v 1.21 2003/12/12 08:01:26 itojun Exp $ */ |
2 | ||
3 | /* | |
4 | * Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project. | |
5 | * All rights reserved. | |
6 | * | |
7 | * Redistribution and use in source and binary forms, with or without | |
8 | * modification, are permitted provided that the following conditions | |
9 | * are met: | |
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. | |
18 | * | |
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 | |
29 | * SUCH DAMAGE. | |
30 | */ | |
31 | ||
32 | /* | |
33 | * IN/OUT bound policy configuration take place such below: | |
34 | * in <priority> <policy> | |
35 | * out <priority> <policy> | |
36 | * | |
37 | * <priority> is one of the following: | |
38 | * priority <signed int> where the integer is an offset from the default | |
39 | * priority, where negative numbers indicate lower | |
40 | * priority (towards end of list) and positive numbers | |
41 | * indicate higher priority (towards beginning of list) | |
42 | * | |
43 | * priority {low,def,high} {+,-} <unsigned int> where low and high are | |
44 | * constants which are closer | |
45 | * to the end of the list and | |
46 | * beginning of the list, | |
47 | * respectively | |
48 | * | |
49 | * <policy> is one of following: | |
50 | * "discard", "none", "ipsec <requests>", "entrust", "bypass", | |
51 | * | |
52 | * The following requests are accepted as <requests>: | |
53 | * | |
54 | * protocol/mode/src-dst/level | |
55 | * protocol/mode/src-dst parsed as protocol/mode/src-dst/default | |
56 | * protocol/mode/src-dst/ parsed as protocol/mode/src-dst/default | |
57 | * protocol/transport parsed as protocol/mode/any-any/default | |
58 | * protocol/transport//level parsed as protocol/mode/any-any/level | |
59 | * | |
60 | * You can concatenate these requests with either ' '(single space) or '\n'. | |
61 | */ | |
62 | ||
63 | %{ | |
64 | #ifdef HAVE_CONFIG_H | |
65 | #include "config.h" | |
66 | #endif | |
67 | ||
68 | #include <sys/types.h> | |
69 | #include <sys/param.h> | |
70 | #include <sys/socket.h> | |
71 | ||
72 | #include <netinet/in.h> | |
73 | #ifdef HAVE_NETINET6_IPSEC | |
74 | # include <netinet6/ipsec.h> | |
75 | #else | |
76 | # include <netinet/ipsec.h> | |
77 | #endif | |
78 | ||
79 | #include <stdlib.h> | |
80 | #include <stdio.h> | |
81 | #include <string.h> | |
82 | #include <netdb.h> | |
83 | ||
84 | #include <errno.h> | |
85 | ||
86 | #include "config.h" | |
85f41bec | 87 | #include "var.h" |
52b7d2ce A |
88 | #include "ipsec_strerror.h" |
89 | #include "libpfkey.h" | |
90 | ||
91 | #ifndef INT32_MAX | |
92 | #define INT32_MAX (0xffffffff) | |
93 | #endif | |
94 | ||
95 | #ifndef INT32_MIN | |
96 | #define INT32_MIN (-INT32_MAX-1) | |
97 | #endif | |
98 | ||
99 | #define ATOX(c) \ | |
100 | (isdigit(c) ? (c - '0') : (isupper(c) ? (c - 'A' + 10) : (c - 'a' + 10) )) | |
101 | ||
102 | static u_int8_t *pbuf = NULL; /* sadb_x_policy buffer */ | |
103 | static int tlen = 0; /* total length of pbuf */ | |
104 | static int offset = 0; /* offset of pbuf */ | |
105 | static int p_dir, p_type, p_protocol, p_mode, p_level, p_reqid; | |
106 | static u_int32_t p_priority = 0; | |
107 | static long p_priority_offset = 0; | |
85f41bec A |
108 | static struct sockaddr_storage *p_src = NULL; |
109 | static struct sockaddr_storage *p_dst = NULL; | |
52b7d2ce A |
110 | |
111 | struct _val; | |
112 | extern void yyerror __P((char *msg)); | |
85f41bec | 113 | static struct sockaddr_storage *parse_sockaddr __P((struct _val *addrbuf, |
52b7d2ce A |
114 | struct _val *portbuf)); |
115 | static int rule_check __P((void)); | |
116 | static int init_x_policy __P((void)); | |
85f41bec A |
117 | static int set_x_request __P((struct sockaddr_storage *, struct sockaddr_storage *)); |
118 | static int set_sockaddr __P((struct sockaddr_storage *)); | |
52b7d2ce A |
119 | static void policy_parse_request_init __P((void)); |
120 | static void *policy_parse __P((const char *, int)); | |
121 | ||
122 | extern void __policy__strbuffer__init__ __P((const char *)); | |
123 | extern void __policy__strbuffer__free__ __P((void)); | |
124 | extern int yyparse __P((void)); | |
125 | extern int yylex __P((void)); | |
126 | ||
127 | extern char *__libipsectext; /*XXX*/ | |
128 | ||
129 | %} | |
130 | ||
131 | %union { | |
132 | u_int num; | |
133 | u_int32_t num32; | |
134 | struct _val { | |
135 | int len; | |
136 | char *buf; | |
137 | } val; | |
138 | } | |
139 | ||
140 | %token DIR | |
141 | %token PRIORITY PLUS | |
142 | %token <num32> PRIO_BASE | |
143 | %token <val> PRIO_OFFSET | |
144 | %token ACTION PROTOCOL MODE LEVEL LEVEL_SPECIFY IPADDRESS PORT | |
145 | %token ME ANY | |
146 | %token SLASH HYPHEN | |
147 | %type <num> DIR PRIORITY ACTION PROTOCOL MODE LEVEL | |
148 | %type <val> IPADDRESS LEVEL_SPECIFY PORT | |
149 | ||
150 | %% | |
151 | policy_spec | |
152 | : DIR ACTION | |
153 | { | |
154 | p_dir = $1; | |
155 | p_type = $2; | |
156 | ||
157 | #ifdef HAVE_PFKEY_POLICY_PRIORITY | |
158 | p_priority = PRIORITY_DEFAULT; | |
159 | #else | |
160 | p_priority = 0; | |
161 | #endif | |
162 | ||
163 | if (init_x_policy()) | |
164 | return -1; | |
165 | } | |
166 | rules | |
167 | | DIR PRIORITY PRIO_OFFSET ACTION | |
168 | { | |
169 | char *offset_buf; | |
170 | ||
171 | p_dir = $1; | |
172 | p_type = $4; | |
173 | ||
174 | /* buffer big enough to hold a prepended negative sign */ | |
175 | offset_buf = malloc($3.len + 2); | |
176 | if (offset_buf == NULL) | |
177 | { | |
178 | __ipsec_errcode = EIPSEC_NO_BUFS; | |
179 | return -1; | |
180 | } | |
181 | ||
182 | /* positive input value means higher priority, therefore lower | |
183 | actual value so that is closer to the beginning of the list */ | |
184 | snprintf (offset_buf, $3.len + 2, "-%s", $3.buf); | |
185 | ||
186 | errno = 0; | |
187 | p_priority_offset = atol(offset_buf); | |
188 | ||
189 | free(offset_buf); | |
190 | ||
191 | if (errno != 0 || p_priority_offset < INT32_MIN) | |
192 | { | |
193 | __ipsec_errcode = EIPSEC_INVAL_PRIORITY_OFFSET; | |
194 | return -1; | |
195 | } | |
196 | ||
197 | p_priority = PRIORITY_DEFAULT + (u_int32_t) p_priority_offset; | |
198 | ||
199 | if (init_x_policy()) | |
200 | return -1; | |
201 | } | |
202 | rules | |
203 | | DIR PRIORITY HYPHEN PRIO_OFFSET ACTION | |
204 | { | |
205 | p_dir = $1; | |
206 | p_type = $5; | |
207 | ||
208 | errno = 0; | |
209 | p_priority_offset = atol($4.buf); | |
210 | ||
211 | if (errno != 0 || p_priority_offset > INT32_MAX) | |
212 | { | |
213 | __ipsec_errcode = EIPSEC_INVAL_PRIORITY_OFFSET; | |
214 | return -1; | |
215 | } | |
216 | ||
217 | /* negative input value means lower priority, therefore higher | |
218 | actual value so that is closer to the end of the list */ | |
219 | p_priority = PRIORITY_DEFAULT + (u_int32_t) p_priority_offset; | |
220 | ||
221 | if (init_x_policy()) | |
222 | return -1; | |
223 | } | |
224 | rules | |
225 | | DIR PRIORITY PRIO_BASE ACTION | |
226 | { | |
227 | p_dir = $1; | |
228 | p_type = $4; | |
229 | ||
230 | p_priority = $3; | |
231 | ||
232 | if (init_x_policy()) | |
233 | return -1; | |
234 | } | |
235 | rules | |
236 | | DIR PRIORITY PRIO_BASE PLUS PRIO_OFFSET ACTION | |
237 | { | |
238 | p_dir = $1; | |
239 | p_type = $6; | |
240 | ||
241 | errno = 0; | |
242 | p_priority_offset = atol($5.buf); | |
243 | ||
244 | if (errno != 0 || p_priority_offset > PRIORITY_OFFSET_NEGATIVE_MAX) | |
245 | { | |
246 | __ipsec_errcode = EIPSEC_INVAL_PRIORITY_BASE_OFFSET; | |
247 | return -1; | |
248 | } | |
249 | ||
250 | /* adding value means higher priority, therefore lower | |
251 | actual value so that is closer to the beginning of the list */ | |
252 | p_priority = $3 - (u_int32_t) p_priority_offset; | |
253 | ||
254 | if (init_x_policy()) | |
255 | return -1; | |
256 | } | |
257 | rules | |
258 | | DIR PRIORITY PRIO_BASE HYPHEN PRIO_OFFSET ACTION | |
259 | { | |
260 | p_dir = $1; | |
261 | p_type = $6; | |
262 | ||
263 | errno = 0; | |
264 | p_priority_offset = atol($5.buf); | |
265 | ||
266 | if (errno != 0 || p_priority_offset > PRIORITY_OFFSET_POSITIVE_MAX) | |
267 | { | |
268 | __ipsec_errcode = EIPSEC_INVAL_PRIORITY_BASE_OFFSET; | |
269 | return -1; | |
270 | } | |
271 | ||
272 | /* subtracting value means lower priority, therefore higher | |
273 | actual value so that is closer to the end of the list */ | |
274 | p_priority = $3 + (u_int32_t) p_priority_offset; | |
275 | ||
276 | if (init_x_policy()) | |
277 | return -1; | |
278 | } | |
279 | rules | |
280 | | DIR | |
281 | { | |
282 | p_dir = $1; | |
283 | p_type = 0; /* ignored it by kernel */ | |
284 | ||
285 | p_priority = 0; | |
286 | ||
287 | if (init_x_policy()) | |
288 | return -1; | |
289 | } | |
290 | ; | |
291 | ||
292 | rules | |
293 | : /*NOTHING*/ | |
294 | | rules rule { | |
295 | if (rule_check() < 0) | |
296 | return -1; | |
297 | ||
298 | if (set_x_request(p_src, p_dst) < 0) | |
299 | return -1; | |
300 | ||
301 | policy_parse_request_init(); | |
302 | } | |
303 | ; | |
304 | ||
305 | rule | |
306 | : protocol SLASH mode SLASH addresses SLASH level | |
307 | | protocol SLASH mode SLASH addresses SLASH | |
308 | | protocol SLASH mode SLASH addresses | |
309 | | protocol SLASH mode SLASH | |
310 | | protocol SLASH mode SLASH SLASH level | |
311 | | protocol SLASH mode | |
312 | | protocol SLASH { | |
313 | __ipsec_errcode = EIPSEC_FEW_ARGUMENTS; | |
314 | return -1; | |
315 | } | |
316 | | protocol { | |
317 | __ipsec_errcode = EIPSEC_FEW_ARGUMENTS; | |
318 | return -1; | |
319 | } | |
320 | ; | |
321 | ||
322 | protocol | |
323 | : PROTOCOL { p_protocol = $1; } | |
324 | ; | |
325 | ||
326 | mode | |
327 | : MODE { p_mode = $1; } | |
328 | ; | |
329 | ||
330 | level | |
331 | : LEVEL { | |
332 | p_level = $1; | |
333 | p_reqid = 0; | |
334 | } | |
335 | | LEVEL_SPECIFY { | |
336 | p_level = IPSEC_LEVEL_UNIQUE; | |
337 | p_reqid = atol($1.buf); /* atol() is good. */ | |
338 | } | |
339 | ; | |
340 | ||
341 | addresses | |
342 | : IPADDRESS { | |
343 | p_src = parse_sockaddr(&$1, NULL); | |
344 | if (p_src == NULL) | |
345 | return -1; | |
346 | } | |
347 | HYPHEN | |
348 | IPADDRESS { | |
349 | p_dst = parse_sockaddr(&$4, NULL); | |
350 | if (p_dst == NULL) | |
351 | return -1; | |
352 | } | |
353 | | IPADDRESS PORT { | |
354 | p_src = parse_sockaddr(&$1, &$2); | |
355 | if (p_src == NULL) | |
356 | return -1; | |
357 | } | |
358 | HYPHEN | |
359 | IPADDRESS PORT { | |
360 | p_dst = parse_sockaddr(&$5, &$6); | |
361 | if (p_dst == NULL) | |
362 | return -1; | |
363 | } | |
364 | | ME HYPHEN ANY { | |
365 | if (p_dir != IPSEC_DIR_OUTBOUND) { | |
366 | __ipsec_errcode = EIPSEC_INVAL_DIR; | |
367 | return -1; | |
368 | } | |
369 | } | |
370 | | ANY HYPHEN ME { | |
371 | if (p_dir != IPSEC_DIR_INBOUND) { | |
372 | __ipsec_errcode = EIPSEC_INVAL_DIR; | |
373 | return -1; | |
374 | } | |
375 | } | |
376 | /* | |
377 | | ME HYPHEN ME | |
378 | */ | |
379 | ; | |
380 | ||
381 | %% | |
382 | ||
383 | void | |
384 | yyerror(msg) | |
385 | char *msg; | |
386 | { | |
387 | fprintf(stderr, "libipsec: %s while parsing \"%s\"\n", | |
388 | msg, __libipsectext); | |
389 | ||
390 | return; | |
391 | } | |
392 | ||
85f41bec | 393 | static struct sockaddr_storage * |
52b7d2ce A |
394 | parse_sockaddr(addrbuf, portbuf) |
395 | struct _val *addrbuf; | |
396 | struct _val *portbuf; | |
397 | { | |
398 | struct addrinfo hints, *res; | |
399 | char *addr; | |
400 | char *serv = NULL; | |
401 | int error; | |
85f41bec | 402 | struct sockaddr_storage *newaddr = NULL; |
d1e348cf A |
403 | int addr_len; |
404 | int serv_len; | |
52b7d2ce | 405 | |
d1e348cf A |
406 | addr_len = addrbuf->len + 1; |
407 | if ((addr = malloc(addr_len)) == NULL) { | |
52b7d2ce A |
408 | yyerror("malloc failed"); |
409 | __ipsec_set_strerror(strerror(errno)); | |
410 | return NULL; | |
411 | } | |
d1e348cf A |
412 | |
413 | if (portbuf) { | |
414 | serv_len = portbuf->len + 1; | |
415 | if ((serv = malloc(serv_len)) == NULL) { | |
416 | free(addr); | |
417 | yyerror("malloc failed"); | |
418 | __ipsec_set_strerror(strerror(errno)); | |
419 | return NULL; | |
420 | } | |
52b7d2ce A |
421 | } |
422 | ||
d1e348cf | 423 | strlcpy(addr, addrbuf->buf, addr_len); |
52b7d2ce A |
424 | |
425 | if (portbuf) { | |
d1e348cf | 426 | strlcpy(serv, portbuf->buf, serv_len); |
52b7d2ce A |
427 | } |
428 | ||
429 | memset(&hints, 0, sizeof(hints)); | |
430 | hints.ai_family = PF_UNSPEC; | |
431 | hints.ai_flags = AI_NUMERICHOST; | |
432 | hints.ai_socktype = SOCK_DGRAM; | |
433 | error = getaddrinfo(addr, serv, &hints, &res); | |
434 | free(addr); | |
435 | if (serv != NULL) | |
436 | free(serv); | |
437 | if (error != 0) { | |
438 | yyerror("invalid IP address"); | |
439 | __ipsec_set_strerror(gai_strerror(error)); | |
440 | return NULL; | |
441 | } | |
442 | ||
443 | if (res->ai_addr == NULL) { | |
444 | yyerror("invalid IP address"); | |
445 | __ipsec_set_strerror(gai_strerror(error)); | |
446 | return NULL; | |
447 | } | |
448 | ||
449 | newaddr = malloc(res->ai_addrlen); | |
450 | if (newaddr == NULL) { | |
451 | __ipsec_errcode = EIPSEC_NO_BUFS; | |
452 | freeaddrinfo(res); | |
453 | return NULL; | |
454 | } | |
455 | memcpy(newaddr, res->ai_addr, res->ai_addrlen); | |
456 | ||
457 | freeaddrinfo(res); | |
458 | ||
459 | __ipsec_errcode = EIPSEC_NO_ERROR; | |
460 | return newaddr; | |
461 | } | |
462 | ||
463 | static int | |
464 | rule_check() | |
465 | { | |
466 | if (p_type == IPSEC_POLICY_IPSEC) { | |
467 | if (p_protocol == IPPROTO_IP) { | |
468 | __ipsec_errcode = EIPSEC_NO_PROTO; | |
469 | return -1; | |
470 | } | |
471 | ||
472 | if (p_mode != IPSEC_MODE_TRANSPORT | |
473 | && p_mode != IPSEC_MODE_TUNNEL) { | |
474 | __ipsec_errcode = EIPSEC_INVAL_MODE; | |
475 | return -1; | |
476 | } | |
477 | ||
478 | if (p_src == NULL && p_dst == NULL) { | |
479 | if (p_mode != IPSEC_MODE_TRANSPORT) { | |
480 | __ipsec_errcode = EIPSEC_INVAL_ADDRESS; | |
481 | return -1; | |
482 | } | |
483 | } | |
85f41bec | 484 | else if (p_src->ss_family != p_dst->ss_family) { |
52b7d2ce A |
485 | __ipsec_errcode = EIPSEC_FAMILY_MISMATCH; |
486 | return -1; | |
487 | } | |
488 | } | |
489 | ||
490 | __ipsec_errcode = EIPSEC_NO_ERROR; | |
491 | return 0; | |
492 | } | |
493 | ||
494 | static int | |
495 | init_x_policy() | |
496 | { | |
497 | struct sadb_x_policy *p; | |
498 | ||
499 | if (pbuf) { | |
500 | free(pbuf); | |
501 | tlen = 0; | |
502 | } | |
503 | pbuf = malloc(sizeof(struct sadb_x_policy)); | |
504 | if (pbuf == NULL) { | |
505 | __ipsec_errcode = EIPSEC_NO_BUFS; | |
506 | return -1; | |
507 | } | |
508 | tlen = sizeof(struct sadb_x_policy); | |
509 | ||
510 | memset(pbuf, 0, tlen); | |
85f41bec | 511 | p = ALIGNED_CAST(struct sadb_x_policy *)pbuf; |
52b7d2ce A |
512 | p->sadb_x_policy_len = 0; /* must update later */ |
513 | p->sadb_x_policy_exttype = SADB_X_EXT_POLICY; | |
514 | p->sadb_x_policy_type = p_type; | |
515 | p->sadb_x_policy_dir = p_dir; | |
516 | p->sadb_x_policy_id = 0; | |
517 | #ifdef HAVE_PFKEY_POLICY_PRIORITY | |
518 | p->sadb_x_policy_priority = p_priority; | |
519 | #else | |
520 | /* fail if given a priority and libipsec was not compiled with | |
521 | priority support */ | |
522 | if (p_priority != 0) | |
523 | { | |
524 | __ipsec_errcode = EIPSEC_PRIORITY_NOT_COMPILED; | |
525 | return -1; | |
526 | } | |
527 | #endif | |
528 | ||
529 | offset = tlen; | |
530 | ||
531 | __ipsec_errcode = EIPSEC_NO_ERROR; | |
532 | return 0; | |
533 | } | |
534 | ||
535 | static int | |
536 | set_x_request(src, dst) | |
85f41bec | 537 | struct sockaddr_storage *src, *dst; |
52b7d2ce A |
538 | { |
539 | struct sadb_x_ipsecrequest *p; | |
540 | int reqlen; | |
541 | u_int8_t *n; | |
542 | ||
543 | reqlen = sizeof(*p) | |
85f41bec A |
544 | + (src ? sysdep_sa_len((struct sockaddr *)src) : 0) |
545 | + (dst ? sysdep_sa_len((struct sockaddr *)dst) : 0); | |
52b7d2ce A |
546 | tlen += reqlen; /* increment to total length */ |
547 | ||
548 | n = realloc(pbuf, tlen); | |
549 | if (n == NULL) { | |
550 | __ipsec_errcode = EIPSEC_NO_BUFS; | |
551 | return -1; | |
552 | } | |
553 | pbuf = n; | |
554 | ||
85f41bec | 555 | p = ALIGNED_CAST(struct sadb_x_ipsecrequest *)&pbuf[offset]; // Wcast-align fix - malloc'd buffer/offset 64 bit multiple |
52b7d2ce A |
556 | p->sadb_x_ipsecrequest_len = reqlen; |
557 | p->sadb_x_ipsecrequest_proto = p_protocol; | |
558 | p->sadb_x_ipsecrequest_mode = p_mode; | |
559 | p->sadb_x_ipsecrequest_level = p_level; | |
560 | p->sadb_x_ipsecrequest_reqid = p_reqid; | |
561 | offset += sizeof(*p); | |
562 | ||
563 | if (set_sockaddr(src) || set_sockaddr(dst)) | |
564 | return -1; | |
565 | ||
566 | __ipsec_errcode = EIPSEC_NO_ERROR; | |
567 | return 0; | |
568 | } | |
569 | ||
570 | static int | |
571 | set_sockaddr(addr) | |
85f41bec | 572 | struct sockaddr_storage *addr; |
52b7d2ce A |
573 | { |
574 | if (addr == NULL) { | |
575 | __ipsec_errcode = EIPSEC_NO_ERROR; | |
576 | return 0; | |
577 | } | |
578 | ||
579 | /* tlen has already incremented */ | |
580 | ||
85f41bec | 581 | memcpy(&pbuf[offset], addr, sysdep_sa_len((struct sockaddr *)addr)); |
52b7d2ce | 582 | |
85f41bec | 583 | offset += sysdep_sa_len((struct sockaddr *)addr); |
52b7d2ce A |
584 | |
585 | __ipsec_errcode = EIPSEC_NO_ERROR; | |
586 | return 0; | |
587 | } | |
588 | ||
589 | static void | |
590 | policy_parse_request_init() | |
591 | { | |
592 | p_protocol = IPPROTO_IP; | |
593 | p_mode = IPSEC_MODE_ANY; | |
594 | p_level = IPSEC_LEVEL_DEFAULT; | |
595 | p_reqid = 0; | |
596 | if (p_src != NULL) { | |
597 | free(p_src); | |
598 | p_src = NULL; | |
599 | } | |
600 | if (p_dst != NULL) { | |
601 | free(p_dst); | |
602 | p_dst = NULL; | |
603 | } | |
604 | ||
605 | return; | |
606 | } | |
607 | ||
608 | static void * | |
609 | policy_parse(msg, msglen) | |
610 | const char *msg; | |
611 | int msglen; | |
612 | { | |
613 | int error; | |
614 | ||
615 | pbuf = NULL; | |
616 | tlen = 0; | |
617 | ||
618 | /* initialize */ | |
619 | p_dir = IPSEC_DIR_INVALID; | |
620 | p_type = IPSEC_POLICY_DISCARD; | |
621 | policy_parse_request_init(); | |
622 | __policy__strbuffer__init__(msg); | |
623 | ||
624 | error = yyparse(); /* it must be set errcode. */ | |
625 | __policy__strbuffer__free__(); | |
626 | ||
627 | if (error) { | |
628 | if (pbuf != NULL) | |
629 | free(pbuf); | |
630 | return NULL; | |
631 | } | |
632 | ||
633 | /* update total length */ | |
85f41bec | 634 | (ALIGNED_CAST(struct sadb_x_policy *)pbuf)->sadb_x_policy_len = PFKEY_UNIT64(tlen); |
52b7d2ce A |
635 | |
636 | __ipsec_errcode = EIPSEC_NO_ERROR; | |
637 | ||
638 | return pbuf; | |
639 | } | |
640 | ||
641 | ipsec_policy_t | |
642 | ipsec_set_policy(msg, msglen) | |
643 | __ipsec_const char *msg; | |
644 | int msglen; | |
645 | { | |
646 | caddr_t policy; | |
647 | ||
648 | policy = policy_parse(msg, msglen); | |
649 | if (policy == NULL) { | |
650 | if (__ipsec_errcode == EIPSEC_NO_ERROR) | |
651 | __ipsec_errcode = EIPSEC_INVAL_ARGUMENT; | |
652 | return NULL; | |
653 | } | |
654 | ||
655 | __ipsec_errcode = EIPSEC_NO_ERROR; | |
656 | return policy; | |
657 | } |