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