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