]>
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" | |
87 | ||
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; | |
108 | static struct sockaddr *p_src = NULL; | |
109 | static struct sockaddr *p_dst = NULL; | |
110 | ||
111 | struct _val; | |
112 | extern void yyerror __P((char *msg)); | |
113 | static struct sockaddr *parse_sockaddr __P((struct _val *addrbuf, | |
114 | struct _val *portbuf)); | |
115 | static int rule_check __P((void)); | |
116 | static int init_x_policy __P((void)); | |
117 | static int set_x_request __P((struct sockaddr *, struct sockaddr *)); | |
118 | static int set_sockaddr __P((struct sockaddr *)); | |
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 | ||
393 | static struct sockaddr * | |
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; | |
402 | struct sockaddr *newaddr = NULL; | |
403 | ||
404 | if ((addr = malloc(addrbuf->len + 1)) == NULL) { | |
405 | yyerror("malloc failed"); | |
406 | __ipsec_set_strerror(strerror(errno)); | |
407 | return NULL; | |
408 | } | |
409 | ||
410 | if (portbuf && ((serv = malloc(portbuf->len + 1)) == NULL)) { | |
411 | free(addr); | |
412 | yyerror("malloc failed"); | |
413 | __ipsec_set_strerror(strerror(errno)); | |
414 | return NULL; | |
415 | } | |
416 | ||
417 | strncpy(addr, addrbuf->buf, addrbuf->len); | |
418 | addr[addrbuf->len] = '\0'; | |
419 | ||
420 | if (portbuf) { | |
421 | strncpy(serv, portbuf->buf, portbuf->len); | |
422 | serv[portbuf->len] = '\0'; | |
423 | } | |
424 | ||
425 | memset(&hints, 0, sizeof(hints)); | |
426 | hints.ai_family = PF_UNSPEC; | |
427 | hints.ai_flags = AI_NUMERICHOST; | |
428 | hints.ai_socktype = SOCK_DGRAM; | |
429 | error = getaddrinfo(addr, serv, &hints, &res); | |
430 | free(addr); | |
431 | if (serv != NULL) | |
432 | free(serv); | |
433 | if (error != 0) { | |
434 | yyerror("invalid IP address"); | |
435 | __ipsec_set_strerror(gai_strerror(error)); | |
436 | return NULL; | |
437 | } | |
438 | ||
439 | if (res->ai_addr == NULL) { | |
440 | yyerror("invalid IP address"); | |
441 | __ipsec_set_strerror(gai_strerror(error)); | |
442 | return NULL; | |
443 | } | |
444 | ||
445 | newaddr = malloc(res->ai_addrlen); | |
446 | if (newaddr == NULL) { | |
447 | __ipsec_errcode = EIPSEC_NO_BUFS; | |
448 | freeaddrinfo(res); | |
449 | return NULL; | |
450 | } | |
451 | memcpy(newaddr, res->ai_addr, res->ai_addrlen); | |
452 | ||
453 | freeaddrinfo(res); | |
454 | ||
455 | __ipsec_errcode = EIPSEC_NO_ERROR; | |
456 | return newaddr; | |
457 | } | |
458 | ||
459 | static int | |
460 | rule_check() | |
461 | { | |
462 | if (p_type == IPSEC_POLICY_IPSEC) { | |
463 | if (p_protocol == IPPROTO_IP) { | |
464 | __ipsec_errcode = EIPSEC_NO_PROTO; | |
465 | return -1; | |
466 | } | |
467 | ||
468 | if (p_mode != IPSEC_MODE_TRANSPORT | |
469 | && p_mode != IPSEC_MODE_TUNNEL) { | |
470 | __ipsec_errcode = EIPSEC_INVAL_MODE; | |
471 | return -1; | |
472 | } | |
473 | ||
474 | if (p_src == NULL && p_dst == NULL) { | |
475 | if (p_mode != IPSEC_MODE_TRANSPORT) { | |
476 | __ipsec_errcode = EIPSEC_INVAL_ADDRESS; | |
477 | return -1; | |
478 | } | |
479 | } | |
480 | else if (p_src->sa_family != p_dst->sa_family) { | |
481 | __ipsec_errcode = EIPSEC_FAMILY_MISMATCH; | |
482 | return -1; | |
483 | } | |
484 | } | |
485 | ||
486 | __ipsec_errcode = EIPSEC_NO_ERROR; | |
487 | return 0; | |
488 | } | |
489 | ||
490 | static int | |
491 | init_x_policy() | |
492 | { | |
493 | struct sadb_x_policy *p; | |
494 | ||
495 | if (pbuf) { | |
496 | free(pbuf); | |
497 | tlen = 0; | |
498 | } | |
499 | pbuf = malloc(sizeof(struct sadb_x_policy)); | |
500 | if (pbuf == NULL) { | |
501 | __ipsec_errcode = EIPSEC_NO_BUFS; | |
502 | return -1; | |
503 | } | |
504 | tlen = sizeof(struct sadb_x_policy); | |
505 | ||
506 | memset(pbuf, 0, tlen); | |
507 | p = (struct sadb_x_policy *)pbuf; | |
508 | p->sadb_x_policy_len = 0; /* must update later */ | |
509 | p->sadb_x_policy_exttype = SADB_X_EXT_POLICY; | |
510 | p->sadb_x_policy_type = p_type; | |
511 | p->sadb_x_policy_dir = p_dir; | |
512 | p->sadb_x_policy_id = 0; | |
513 | #ifdef HAVE_PFKEY_POLICY_PRIORITY | |
514 | p->sadb_x_policy_priority = p_priority; | |
515 | #else | |
516 | /* fail if given a priority and libipsec was not compiled with | |
517 | priority support */ | |
518 | if (p_priority != 0) | |
519 | { | |
520 | __ipsec_errcode = EIPSEC_PRIORITY_NOT_COMPILED; | |
521 | return -1; | |
522 | } | |
523 | #endif | |
524 | ||
525 | offset = tlen; | |
526 | ||
527 | __ipsec_errcode = EIPSEC_NO_ERROR; | |
528 | return 0; | |
529 | } | |
530 | ||
531 | static int | |
532 | set_x_request(src, dst) | |
533 | struct sockaddr *src, *dst; | |
534 | { | |
535 | struct sadb_x_ipsecrequest *p; | |
536 | int reqlen; | |
537 | u_int8_t *n; | |
538 | ||
539 | reqlen = sizeof(*p) | |
540 | + (src ? sysdep_sa_len(src) : 0) | |
541 | + (dst ? sysdep_sa_len(dst) : 0); | |
542 | tlen += reqlen; /* increment to total length */ | |
543 | ||
544 | n = realloc(pbuf, tlen); | |
545 | if (n == NULL) { | |
546 | __ipsec_errcode = EIPSEC_NO_BUFS; | |
547 | return -1; | |
548 | } | |
549 | pbuf = n; | |
550 | ||
551 | p = (struct sadb_x_ipsecrequest *)&pbuf[offset]; | |
552 | p->sadb_x_ipsecrequest_len = reqlen; | |
553 | p->sadb_x_ipsecrequest_proto = p_protocol; | |
554 | p->sadb_x_ipsecrequest_mode = p_mode; | |
555 | p->sadb_x_ipsecrequest_level = p_level; | |
556 | p->sadb_x_ipsecrequest_reqid = p_reqid; | |
557 | offset += sizeof(*p); | |
558 | ||
559 | if (set_sockaddr(src) || set_sockaddr(dst)) | |
560 | return -1; | |
561 | ||
562 | __ipsec_errcode = EIPSEC_NO_ERROR; | |
563 | return 0; | |
564 | } | |
565 | ||
566 | static int | |
567 | set_sockaddr(addr) | |
568 | struct sockaddr *addr; | |
569 | { | |
570 | if (addr == NULL) { | |
571 | __ipsec_errcode = EIPSEC_NO_ERROR; | |
572 | return 0; | |
573 | } | |
574 | ||
575 | /* tlen has already incremented */ | |
576 | ||
577 | memcpy(&pbuf[offset], addr, sysdep_sa_len(addr)); | |
578 | ||
579 | offset += sysdep_sa_len(addr); | |
580 | ||
581 | __ipsec_errcode = EIPSEC_NO_ERROR; | |
582 | return 0; | |
583 | } | |
584 | ||
585 | static void | |
586 | policy_parse_request_init() | |
587 | { | |
588 | p_protocol = IPPROTO_IP; | |
589 | p_mode = IPSEC_MODE_ANY; | |
590 | p_level = IPSEC_LEVEL_DEFAULT; | |
591 | p_reqid = 0; | |
592 | if (p_src != NULL) { | |
593 | free(p_src); | |
594 | p_src = NULL; | |
595 | } | |
596 | if (p_dst != NULL) { | |
597 | free(p_dst); | |
598 | p_dst = NULL; | |
599 | } | |
600 | ||
601 | return; | |
602 | } | |
603 | ||
604 | static void * | |
605 | policy_parse(msg, msglen) | |
606 | const char *msg; | |
607 | int msglen; | |
608 | { | |
609 | int error; | |
610 | ||
611 | pbuf = NULL; | |
612 | tlen = 0; | |
613 | ||
614 | /* initialize */ | |
615 | p_dir = IPSEC_DIR_INVALID; | |
616 | p_type = IPSEC_POLICY_DISCARD; | |
617 | policy_parse_request_init(); | |
618 | __policy__strbuffer__init__(msg); | |
619 | ||
620 | error = yyparse(); /* it must be set errcode. */ | |
621 | __policy__strbuffer__free__(); | |
622 | ||
623 | if (error) { | |
624 | if (pbuf != NULL) | |
625 | free(pbuf); | |
626 | return NULL; | |
627 | } | |
628 | ||
629 | /* update total length */ | |
630 | ((struct sadb_x_policy *)pbuf)->sadb_x_policy_len = PFKEY_UNIT64(tlen); | |
631 | ||
632 | __ipsec_errcode = EIPSEC_NO_ERROR; | |
633 | ||
634 | return pbuf; | |
635 | } | |
636 | ||
637 | ipsec_policy_t | |
638 | ipsec_set_policy(msg, msglen) | |
639 | __ipsec_const char *msg; | |
640 | int msglen; | |
641 | { | |
642 | caddr_t policy; | |
643 | ||
644 | policy = policy_parse(msg, msglen); | |
645 | if (policy == NULL) { | |
646 | if (__ipsec_errcode == EIPSEC_NO_ERROR) | |
647 | __ipsec_errcode = EIPSEC_INVAL_ARGUMENT; | |
648 | return NULL; | |
649 | } | |
650 | ||
651 | __ipsec_errcode = EIPSEC_NO_ERROR; | |
652 | return policy; | |
653 | } |