1 /* $OpenBSD: parse.y,v 1.9 2005/07/10 09:33:10 hshoexer Exp $ */
2
3 /*
4 * Copyright (c) 2002, 2003, 2004 Henning Brauer <henning@openbsd.org>
5 * Copyright (c) 2001 Markus Friedl. All rights reserved.
6 * Copyright (c) 2001 Daniel Hartmeier. All rights reserved.
7 * Copyright (c) 2001 Theo de Raadt. All rights reserved.
8 * Copyright (c) 2004, 2005 Hans-Joerg Hoexer <hshoexer@openbsd.org>
9 *
10 * Permission to use, copy, modify, and distribute this software for any
11 * purpose with or without fee is hereby granted, provided that the above
12 * copyright notice and this permission notice appear in all copies.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
15 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
16 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
17 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
18 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
19 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
20 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
21 */
22
23 %{
24 #include <sys/types.h>
25 #include <sys/queue.h>
26 #include <sys/socket.h>
27 #include <sys/stat.h>
28 #include <netinet/in.h>
29 #include <netinet/ip_ipsp.h>
30 #include <arpa/inet.h>
31
32 #include <ctype.h>
33 #include <err.h>
34 #include <errno.h>
35 #include <fcntl.h>
36 #include <limits.h>
37 #include <stdarg.h>
38 #include <stdio.h>
39 #include <string.h>
40 #include <syslog.h>
41 #include <unistd.h>
42
43 #include "ipsecctl.h"
44
45 #define KEYSIZE_LIMIT 1024
46
47 static struct ipsecctl *ipsec = NULL;
48 static FILE *fin = NULL;
49 static int lineno = 1;
50 static int errors = 0;
51 static int debug = 0;
52
53 int yyerror(const char *, ...);
54 int yyparse(void);
55 int kw_cmp(const void *, const void *);
56 int lookup(char *);
57 int lgetc(FILE *);
58 int lungetc(int);
59 int findeol(void);
60 int yylex(void);
61
62 TAILQ_HEAD(symhead, sym) symhead = TAILQ_HEAD_INITIALIZER(symhead);
63 struct sym {
64 TAILQ_ENTRY(sym) entries;
65 int used;
66 int persist;
67 char *nam;
68 char *val;
69 };
70
71 int symset(const char *, const char *, int);
72 int cmdline_symset(char *);
73 char *symget(const char *);
74 int atoul(char *, u_long *);
75 u_int8_t x2i(unsigned char *);
76 struct ipsec_key *parsekey(unsigned char *, size_t);
77 struct ipsec_addr *host(const char *);
78 struct ipsec_addr *copyhost(const struct ipsec_addr *);
79 struct ipsec_rule *create_sa(struct ipsec_addr *, struct ipsec_addr *,
80 u_int32_t, struct ipsec_key *);
81 struct ipsec_rule *create_flow(u_int8_t, struct ipsec_addr *, struct
82 ipsec_addr *, struct ipsec_addr *, u_int8_t,
83 char *, char *, u_int16_t);
84 struct ipsec_rule *reverse_rule(struct ipsec_rule *);
85
86 typedef struct {
87 union {
88 u_int32_t number;
89 u_int8_t dir;
90 char *string;
91 int log;
92 u_int8_t protocol;
93 struct {
94 struct ipsec_addr *src;
95 struct ipsec_addr *dst;
96 } hosts;
97 struct ipsec_addr *peer;
98 struct ipsec_addr *host;
99 struct {
100 char *srcid;
101 char *dstid;
102 } ids;
103 char *id;
104 u_int16_t authtype;
105 u_int32_t spi;
106 struct ipsec_key *key;
107 } v;
108 int lineno;
109 } YYSTYPE;
110
111 %}
112
113 %token FLOW FROM ESP AH IN PEER ON OUT TO SRCID DSTID RSA PSK TCPMD5 SPI KEY
114 %token KEYFILE ERROR
115 %token <v.string> STRING
116 %type <v.dir> dir
117 %type <v.protocol> protocol
118 %type <v.number> number
119 %type <v.hosts> hosts
120 %type <v.peer> peer
121 %type <v.host> host
122 %type <v.ids> ids
123 %type <v.id> id
124 %type <v.authtype> authtype
125 %type <v.spi> spi
126 %type <v.key> keyspec
127 %%
128
129 grammar : /* empty */
130 | grammar '\n'
131 | grammar flowrule '\n'
132 | grammar tcpmd5rule '\n'
133 | grammar error '\n' { errors++; }
134 ;
135
136 number : STRING {
137 unsigned long ulval;
138
139 if (atoul($1, &ulval) == -1) {
140 yyerror("%s is not a number", $1);
141 free($1);
142 YYERROR;
143 }
144 if (ulval > UINT_MAX) {
145 yyerror("0x%lx out of range", ulval);
146 free($1);
147 YYERROR;
148 }
149 $$ = (u_int32_t)ulval;
150 free($1);
151 }
152
153 flowrule : FLOW ipsecrule { }
154 ;
155
156 tcpmd5rule : TCPMD5 hosts spi keyspec {
157 struct ipsec_rule *r;
158
159 r = create_sa($2.src, $2.dst, $3, $4);
160 if (r == NULL)
161 YYERROR;
162 r->nr = ipsec->rule_nr++;
163
164 if (ipsecctl_add_rule(ipsec, r))
165 errx(1, "tcpmd5rule: ipsecctl_add_rule");
166 }
167 ;
168
169 ipsecrule : protocol dir hosts peer ids authtype {
170 struct ipsec_rule *r;
171
172 r = create_flow($2, $3.src, $3.dst, $4, $1, $5.srcid,
173 $5.dstid, $6);
174 if (r == NULL)
175 YYERROR;
176 r->nr = ipsec->rule_nr++;
177
178 if (ipsecctl_add_rule(ipsec, r))
179 errx(1, "esprule: ipsecctl_add_rule");
180
181 /* Create and add reverse rule. */
182 if ($2 == IPSEC_INOUT) {
183 r = reverse_rule(r);
184 r->nr = ipsec->rule_nr++;
185
186 if (ipsecctl_add_rule(ipsec, r))
187 errx(1, "esprule: ipsecctl_add_rule");
188 }
189 }
190 ;
191
192 protocol : /* empty */ { $$ = IPSEC_ESP; }
193 | ESP { $$ = IPSEC_ESP; }
194 | AH { $$ = IPSEC_AH; }
195 ;
196
197 dir : /* empty */ { $$ = IPSEC_INOUT; }
198 | IN { $$ = IPSEC_IN; }
199 | OUT { $$ = IPSEC_OUT; }
200 ;
201
202 hosts : FROM host TO host {
203 $$.src = $2;
204 $$.dst = $4;
205 }
206 ;
207
208 peer : /* empty */ { $$ = NULL; }
209 | PEER STRING {
210 if (($$ = host($2)) == NULL) {
211 free($2);
212 yyerror("could not parse host specification");
213 YYERROR;
214 }
215 free($2);
216 }
217 ;
218
219 host : STRING {
220 if (($$ = host($1)) == NULL) {
221 free($1);
222 yyerror("could not parse host specification");
223 YYERROR;
224 }
225 free($1);
226 }
227 | STRING '/' number {
228 char *buf;
229
230 if (asprintf(&buf, "%s/%u", $1, $3) == -1)
231 err(1, "host: asprintf");
232 free($1);
233 if (($$ = host(buf)) == NULL) {
234 free(buf);
235 yyerror("could not parse host specification");
236 YYERROR;
237 }
238 free(buf);
239 }
240 ;
241
242 ids : /* empty */ {
243 $$.srcid = NULL;
244 $$.dstid = NULL;
245 }
246 | SRCID id DSTID id {
247 $$.srcid = $2;
248 $$.dstid = $4;
249 }
250 | SRCID id {
251 $$.srcid = $2;
252 $$.dstid = NULL;
253 }
254 | DSTID id {
255 $$.srcid = NULL;
256 $$.dstid = $2;
257 }
258 ;
259
260 id : STRING { $$ = $1; }
261 ;
262
263 authtype : /* empty */ { $$ = 0; }
264 | RSA { $$ = AUTH_RSA; }
265 | PSK { $$ = AUTH_PSK; }
266 ;
267
268 spi : SPI number {
269 if ($2 >= SPI_RESERVED_MIN && $2 <= SPI_RESERVED_MAX) {
270 yyerror("invalid spi 0x%lx", $2);
271 YYERROR;
272 }
273 $$ = $2;
274 }
275 ;
276
277 keyspec : /* empty */ { $$ = NULL; }
278 | KEY STRING {
279 unsigned char *hex;
280
281 hex = $2;
282 if (!strncmp(hex, "0x", 2))
283 hex += 2;
284 $$ = parsekey(hex, strlen(hex));
285
286 free($2);
287 }
288 | KEYFILE STRING {
289 struct stat sb;
290 int fd;
291 unsigned char *hex;
292
293 if (stat($2, &sb) < 0)
294 err(1, "stat");
295 if ((sb.st_size > KEYSIZE_LIMIT) || (sb.st_size == 0))
296 errx(1, "key too %s", sb.st_size ? "large" :
297 "small");
298 if ((hex = calloc(sb.st_size, sizeof(unsigned char)))
299 == NULL)
300 err(1, "calloc");
301 if ((fd = open($2, O_RDONLY)) < 0)
302 err(1, "open");
303 if (read(fd, hex, sb.st_size) < sb.st_size)
304 err(1, "read");
305 close(fd);
306 $$ = parsekey(hex, sb.st_size);
307
308 free($2);
309 }
310 ;
311 %%
312
313 struct keywords {
314 const char *k_name;
315 int k_val;
316 };
317
318 int
yyerror(const char * fmt,...)319 yyerror(const char *fmt, ...)
320 {
321 va_list ap;
322 extern char *infile;
323
324 errors = 1;
325 va_start(ap, fmt);
326 fprintf(stderr, "%s: %d: ", infile, yyval.lineno);
327 vfprintf(stderr, fmt, ap);
328 fprintf(stderr, "\n");
329 va_end(ap);
330 return (0);
331 }
332
333 int
kw_cmp(const void * k,const void * e)334 kw_cmp(const void *k, const void *e)
335 {
336 return (strcmp(k, ((const struct keywords *)e)->k_name));
337 }
338
339 int
lookup(char * s)340 lookup(char *s)
341 {
342 /* this has to be sorted always */
343 static const struct keywords keywords[] = {
344 { "ah", AH},
345 { "dstid", DSTID},
346 { "esp", ESP},
347 { "flow", FLOW},
348 { "from", FROM},
349 { "in", IN},
350 { "key", KEY},
351 { "keyfile", KEYFILE},
352 { "out", OUT},
353 { "peer", PEER},
354 { "psk", PSK},
355 { "rsa", RSA},
356 { "spi", SPI},
357 { "srcid", SRCID},
358 { "tcpmd5", TCPMD5},
359 { "to", TO},
360 };
361 const struct keywords *p;
362
363 p = bsearch(s, keywords, sizeof(keywords)/sizeof(keywords[0]),
364 sizeof(keywords[0]), kw_cmp);
365
366 if (p) {
367 if (debug > 1)
368 fprintf(stderr, "%s: %d\n", s, p->k_val);
369 return (p->k_val);
370 } else {
371 if (debug > 1)
372 fprintf(stderr, "string: %s\n", s);
373 return (STRING);
374 }
375 }
376
377 #define MAXPUSHBACK 128
378
379 char *parsebuf;
380 int parseindex;
381 char pushback_buffer[MAXPUSHBACK];
382 int pushback_index = 0;
383
384 int
lgetc(FILE * f)385 lgetc(FILE *f)
386 {
387 int c, next;
388
389 if (parsebuf) {
390 /* Read character from the parsebuffer instead of input. */
391 if (parseindex >= 0) {
392 c = parsebuf[parseindex++];
393 if (c != '\0')
394 return (c);
395 parsebuf = NULL;
396 } else
397 parseindex++;
398 }
399
400 if (pushback_index)
401 return (pushback_buffer[--pushback_index]);
402
403 while ((c = getc(f)) == '\\') {
404 next = getc(f);
405 if (next != '\n') {
406 if (isspace(next))
407 yyerror("whitespace after \\");
408 ungetc(next, f);
409 break;
410 }
411 yylval.lineno = lineno;
412 lineno++;
413 }
414 if (c == '\t' || c == ' ') {
415 /* Compress blanks to a single space. */
416 do {
417 c = getc(f);
418 } while (c == '\t' || c == ' ');
419 ungetc(c, f);
420 c = ' ';
421 }
422
423 return (c);
424 }
425
426 int
lungetc(int c)427 lungetc(int c)
428 {
429 if (c == EOF)
430 return (EOF);
431 if (parsebuf) {
432 parseindex--;
433 if (parseindex >= 0)
434 return (c);
435 }
436 if (pushback_index < MAXPUSHBACK-1)
437 return (pushback_buffer[pushback_index++] = c);
438 else
439 return (EOF);
440 }
441
442 int
findeol(void)443 findeol(void)
444 {
445 int c;
446
447 parsebuf = NULL;
448 pushback_index = 0;
449
450 /* skip to either EOF or the first real EOL */
451 while (1) {
452 c = lgetc(fin);
453 if (c == '\n') {
454 lineno++;
455 break;
456 }
457 if (c == EOF)
458 break;
459 }
460 return (ERROR);
461 }
462
463 int
yylex(void)464 yylex(void)
465 {
466 char buf[8096];
467 char *p, *val;
468 int endc, c;
469 int token;
470
471 top:
472 p = buf;
473 while ((c = lgetc(fin)) == ' ')
474 ; /* nothing */
475
476 yylval.lineno = lineno;
477 if (c == '#')
478 while ((c = lgetc(fin)) != '\n' && c != EOF)
479 ; /* nothing */
480 if (c == '$' && parsebuf == NULL) {
481 while (1) {
482 if ((c = lgetc(fin)) == EOF)
483 return (0);
484
485 if (p + 1 >= buf + sizeof(buf) - 1) {
486 yyerror("string too long");
487 return (findeol());
488 }
489 if (isalnum(c) || c == '_') {
490 *p++ = (char)c;
491 continue;
492 }
493 *p = '\0';
494 lungetc(c);
495 break;
496 }
497 val = symget(buf);
498 if (val == NULL) {
499 yyerror("macro \"%s\" not defined", buf);
500 return (findeol());
501 }
502 parsebuf = val;
503 parseindex = 0;
504 goto top;
505 }
506
507 switch (c) {
508 case '\'':
509 case '"':
510 endc = c;
511 while (1) {
512 if ((c = lgetc(fin)) == EOF)
513 return (0);
514 if (c == endc) {
515 *p = '\0';
516 break;
517 }
518 if (c == '\n') {
519 lineno++;
520 continue;
521 }
522 if (p + 1 >= buf + sizeof(buf) - 1) {
523 yyerror("string too long");
524 return (findeol());
525 }
526 *p++ = (char)c;
527 }
528 yylval.v.string = strdup(buf);
529 if (yylval.v.string == NULL)
530 err(1, "yylex: strdup");
531 return (STRING);
532 }
533
534 #define allowed_in_string(x) \
535 (isalnum(x) || (ispunct(x) && x != '(' && x != ')' && \
536 x != '{' && x != '}' && x != '<' && x != '>' && \
537 x != '!' && x != '=' && x != '/' && x != '#' && \
538 x != ','))
539
540 if (isalnum(c) || c == ':' || c == '_' || c == '*') {
541 do {
542 *p++ = c;
543 if ((unsigned)(p-buf) >= sizeof(buf)) {
544 yyerror("string too long");
545 return (findeol());
546 }
547 } while ((c = lgetc(fin)) != EOF && (allowed_in_string(c)));
548 lungetc(c);
549 *p = '\0';
550 if ((token = lookup(buf)) == STRING)
551 if ((yylval.v.string = strdup(buf)) == NULL)
552 err(1, "yylex: strdup");
553 return (token);
554 }
555 if (c == '\n') {
556 yylval.lineno = lineno;
557 lineno++;
558 }
559 if (c == EOF)
560 return (0);
561 return (c);
562 }
563
564 int
parse_rules(FILE * input,struct ipsecctl * ipsecx)565 parse_rules(FILE *input, struct ipsecctl *ipsecx)
566 {
567 struct sym *sym, *next;
568
569 ipsec = ipsecx;
570 fin = input;
571 lineno = 1;
572 errors = 0;
573
574 yyparse();
575
576 /* Free macros and check which have not been used. */
577 for (sym = TAILQ_FIRST(&symhead); sym != NULL; sym = next) {
578 next = TAILQ_NEXT(sym, entries);
579 free(sym->nam);
580 free(sym->val);
581 TAILQ_REMOVE(&symhead, sym, entries);
582 free(sym);
583 }
584
585 return (errors ? -1 : 0);
586 }
587
588 int
symset(const char * nam,const char * val,int persist)589 symset(const char *nam, const char *val, int persist)
590 {
591 struct sym *sym;
592
593 for (sym = TAILQ_FIRST(&symhead); sym && strcmp(nam, sym->nam);
594 sym = TAILQ_NEXT(sym, entries))
595 ; /* nothing */
596
597 if (sym != NULL) {
598 if (sym->persist == 1)
599 return (0);
600 else {
601 free(sym->nam);
602 free(sym->val);
603 TAILQ_REMOVE(&symhead, sym, entries);
604 free(sym);
605 }
606 }
607 if ((sym = calloc(1, sizeof(*sym))) == NULL)
608 return (-1);
609
610 sym->nam = strdup(nam);
611 if (sym->nam == NULL) {
612 free(sym);
613 return (-1);
614 }
615 sym->val = strdup(val);
616 if (sym->val == NULL) {
617 free(sym->nam);
618 free(sym);
619 return (-1);
620 }
621 sym->used = 0;
622 sym->persist = persist;
623 TAILQ_INSERT_TAIL(&symhead, sym, entries);
624 return (0);
625 }
626
627 int
cmdline_symset(char * s)628 cmdline_symset(char *s)
629 {
630 char *sym, *val;
631 int ret;
632 size_t len;
633
634 if ((val = strrchr(s, '=')) == NULL)
635 return (-1);
636
637 len = strlen(s) - strlen(val) + 1;
638 if ((sym = malloc(len)) == NULL)
639 err(1, "cmdline_symset: malloc");
640
641 strlcpy(sym, s, len);
642
643 ret = symset(sym, val + 1, 1);
644 free(sym);
645
646 return (ret);
647 }
648
649 char *
symget(const char * nam)650 symget(const char *nam)
651 {
652 struct sym *sym;
653
654 TAILQ_FOREACH(sym, &symhead, entries)
655 if (strcmp(nam, sym->nam) == 0) {
656 sym->used = 1;
657 return (sym->val);
658 }
659 return (NULL);
660 }
661
662 int
atoul(char * s,u_long * ulvalp)663 atoul(char *s, u_long *ulvalp)
664 {
665 u_long ulval;
666 char *ep;
667
668 errno = 0;
669 ulval = strtoul(s, &ep, 0);
670 if (s[0] == '\0' || *ep != '\0')
671 return (-1);
672 if (errno == ERANGE && ulval == ULONG_MAX)
673 return (-1);
674 *ulvalp = ulval;
675 return (0);
676 }
677
678 u_int8_t
x2i(unsigned char * s)679 x2i(unsigned char *s)
680 {
681 char ss[3];
682
683 ss[0] = s[0];
684 ss[1] = s[1];
685 ss[2] = 0;
686
687 if (!isxdigit(s[0]) || !isxdigit(s[1])) {
688 yyerror("keys need to be specified in hex digits");
689 return -1;
690 }
691 return ((u_int8_t)strtoul(ss, NULL, 16));
692 }
693
694 struct ipsec_key *
parsekey(unsigned char * hexkey,size_t len)695 parsekey(unsigned char *hexkey, size_t len)
696 {
697 struct ipsec_key *key;
698 int i;
699
700 key = calloc(1, sizeof(struct ipsec_key));
701 if (key == NULL)
702 err(1, "calloc");
703
704 key->len = len / 2;
705 key->data = calloc(key->len, sizeof(u_int8_t));
706 if (key->data == NULL)
707 err(1, "calloc");
708
709 for (i = 0; i < (int)key->len; i++)
710 key->data[i] = x2i(hexkey + 2 * i);
711
712 return (key);
713 }
714
715 struct ipsec_addr *
host(const char * s)716 host(const char *s)
717 {
718 struct ipsec_addr *ipa;
719 int i, bits = 32;
720
721 /* XXX for now only AF_INET. */
722
723 ipa = calloc(1, sizeof(struct ipsec_addr));
724 if (ipa == NULL)
725 err(1, "calloc");
726
727 if (strrchr(s, '/') != NULL) {
728 bits = inet_net_pton(AF_INET, s, &ipa->v4, sizeof(ipa->v4));
729 if (bits == -1 || bits > 32) {
730 free(ipa);
731 return(NULL);
732 }
733 } else {
734 if (inet_pton(AF_INET, s, &ipa->v4) != 1) {
735 free(ipa);
736 return NULL;
737 }
738 }
739
740 bzero(&ipa->v4mask, sizeof(ipa->v4mask));
741 if (bits == 32) {
742 ipa->v4mask.mask32 = 0xffffffff;
743 ipa->netaddress = 0;
744 } else {
745 for (i = 31; i > 31 - bits; i--)
746 ipa->v4mask.mask32 |= (1 << i);
747 ipa->v4mask.mask32 = htonl(ipa->v4mask.mask32);
748 ipa->netaddress = 1;
749 }
750
751 ipa->af = AF_INET;
752
753 return ipa;
754 }
755
756 struct ipsec_addr *
copyhost(const struct ipsec_addr * src)757 copyhost(const struct ipsec_addr *src)
758 {
759 struct ipsec_addr *dst;
760
761 dst = calloc(1, sizeof(struct ipsec_addr));
762 if (dst == NULL)
763 err(1, "calloc");
764
765 memcpy(dst, src, sizeof(struct ipsec_addr));
766 return dst;
767 }
768
769 struct ipsec_rule *
create_sa(struct ipsec_addr * src,struct ipsec_addr * dst,u_int32_t spi,struct ipsec_key * key)770 create_sa(struct ipsec_addr *src, struct ipsec_addr *dst, u_int32_t spi,
771 struct ipsec_key *key)
772 {
773 struct ipsec_rule *r;
774
775 r = calloc(1, sizeof(struct ipsec_rule));
776 if (r == NULL)
777 err(1, "calloc");
778
779 r->type = RULE_SA;
780
781 r->src = src;
782 r->dst = dst;
783 r->spi = spi;
784 r->key = key;
785
786 return r;
787 }
788
789 struct ipsec_rule *
create_flow(u_int8_t dir,struct ipsec_addr * src,struct ipsec_addr * dst,struct ipsec_addr * peer,u_int8_t proto,char * srcid,char * dstid,u_int16_t authtype)790 create_flow(u_int8_t dir, struct ipsec_addr *src, struct ipsec_addr *dst,
791 struct ipsec_addr *peer, u_int8_t proto, char *srcid, char *dstid,
792 u_int16_t authtype)
793 {
794 struct ipsec_rule *r;
795
796 r = calloc(1, sizeof(struct ipsec_rule));
797 if (r == NULL)
798 err(1, "calloc");
799
800 r->type = RULE_FLOW;
801
802 if (dir == IPSEC_INOUT)
803 r->direction = IPSEC_OUT;
804 else
805 r->direction = dir;
806
807 if (r->direction == IPSEC_IN)
808 r->flowtype = TYPE_USE;
809 else
810 r->flowtype = TYPE_REQUIRE;
811
812 r->src = src;
813 r->dst = dst;
814
815 if (peer == NULL) {
816 /* Set peer to remote host. Must be a host address. */
817 if (r->direction == IPSEC_IN) {
818 if (r->src->netaddress) {
819 yyerror("no peer specified");
820 goto errout;
821 }
822 r->peer = copyhost(r->src);
823 } else {
824 if (r->dst->netaddress) {
825 yyerror("no peer specified");
826 goto errout;
827 }
828 r->peer = copyhost(r->dst);
829 }
830 } else
831 r->peer = peer;
832
833 r->proto = proto;
834 r->auth.srcid = srcid;
835 r->auth.dstid = dstid;
836 r->auth.idtype = ID_FQDN; /* XXX For now only FQDN. */
837 #ifdef notyet
838 r->auth.type = authtype;
839 #endif
840
841 return r;
842
843 errout:
844 free(r);
845 if (srcid)
846 free(srcid);
847 if (dstid)
848 free(dstid);
849 free(src);
850 free(dst);
851
852 return NULL;
853 }
854
855 struct ipsec_rule *
reverse_rule(struct ipsec_rule * rule)856 reverse_rule(struct ipsec_rule *rule)
857 {
858 struct ipsec_rule *reverse;
859
860 reverse = calloc(1, sizeof(struct ipsec_rule));
861 if (reverse == NULL)
862 err(1, "calloc");
863
864 reverse->type = RULE_FLOW;
865
866 if (rule->direction == (u_int8_t)IPSEC_OUT) {
867 reverse->direction = (u_int8_t)IPSEC_IN;
868 reverse->flowtype = TYPE_USE;
869 } else {
870 reverse->direction = (u_int8_t)IPSEC_OUT;
871 reverse->flowtype = TYPE_REQUIRE;
872 }
873
874 reverse->src = copyhost(rule->dst);
875 reverse->dst = copyhost(rule->src);
876 reverse->peer = copyhost(rule->peer);
877 reverse->proto = (u_int8_t)rule->proto;
878
879 if (rule->auth.dstid && (reverse->auth.dstid =
880 strdup(rule->auth.dstid)) == NULL)
881 err(1, "strdup");
882 if (rule->auth.srcid && (reverse->auth.srcid =
883 strdup(rule->auth.srcid)) == NULL)
884 err(1, "strdup");
885 reverse->auth.idtype = rule->auth.idtype;
886 reverse->auth.type = rule->auth.type;
887
888 return reverse;
889 }
890