1 /* 2 * firewall3 - 3rd OpenWrt UCI firewall implementation 3 * 4 * Copyright (C) 2013 Jo-Philipp Wich <jo@mein.io> 5 * 6 * Permission to use, copy, modify, and/or distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19 #define _GNU_SOURCE 20 21 #include <net/if.h> 22 #include <sys/ioctl.h> 23 24 #include "utils.h" 25 #include "options.h" 26 27 #include "zones.h" 28 #include "ipsets.h" 29 30 31 static int fw3_lock_fd = -1; 32 static pid_t pipe_pid = -1; 33 static FILE *pipe_fd = NULL; 34 35 bool fw3_pr_debug = false; 36 37 38 static void 39 warn_elem_section_name(struct uci_section *s, bool find_name) 40 { 41 int i = 0; 42 struct uci_option *o; 43 struct uci_element *tmp; 44 45 if (s->anonymous) 46 { 47 uci_foreach_element(&s->package->sections, tmp) 48 { 49 if (strcmp(uci_to_section(tmp)->type, s->type)) 50 continue; 51 52 if (&s->e == tmp) 53 break; 54 55 i++; 56 } 57 58 fprintf(stderr, "@%s[%d]", s->type, i); 59 60 if (find_name) 61 { 62 uci_foreach_element(&s->options, tmp) 63 { 64 o = uci_to_option(tmp); 65 66 if (!strcmp(tmp->name, "name") && (o->type == UCI_TYPE_STRING)) 67 { 68 fprintf(stderr, " (%s)", o->v.string); 69 break; 70 } 71 } 72 } 73 } 74 else 75 { 76 fprintf(stderr, "'%s'", s->e.name); 77 } 78 79 if (find_name) 80 fprintf(stderr, " "); 81 } 82 83 void 84 warn_elem(struct uci_element *e, const char *format, ...) 85 { 86 if (e->type == UCI_TYPE_SECTION) 87 { 88 fprintf(stderr, "Warning: Section "); 89 warn_elem_section_name(uci_to_section(e), true); 90 } 91 else if (e->type == UCI_TYPE_OPTION) 92 { 93 fprintf(stderr, "Warning: Option "); 94 warn_elem_section_name(uci_to_option(e)->section, false); 95 fprintf(stderr, ".%s ", e->name); 96 } 97 98 va_list argptr; 99 va_start(argptr, format); 100 vfprintf(stderr, format, argptr); 101 va_end(argptr); 102 103 fprintf(stderr, "\n"); 104 } 105 106 void 107 warn(const char* format, ...) 108 { 109 fprintf(stderr, "Warning: "); 110 va_list argptr; 111 va_start(argptr, format); 112 vfprintf(stderr, format, argptr); 113 va_end(argptr); 114 fprintf(stderr, "\n"); 115 } 116 117 void 118 error(const char* format, ...) 119 { 120 fprintf(stderr, "Error: "); 121 va_list argptr; 122 va_start(argptr, format); 123 vfprintf(stderr, format, argptr); 124 va_end(argptr); 125 fprintf(stderr, "\n"); 126 127 exit(1); 128 } 129 130 void 131 info(const char* format, ...) 132 { 133 va_list argptr; 134 va_start(argptr, format); 135 vfprintf(stderr, format, argptr); 136 va_end(argptr); 137 fprintf(stderr, "\n"); 138 } 139 140 void * 141 fw3_alloc(size_t size) 142 { 143 void *mem; 144 145 mem = calloc(1, size); 146 147 if (!mem) 148 error("Out of memory while allocating %zd bytes", size); 149 150 return mem; 151 } 152 153 char * 154 fw3_strdup(const char *s) 155 { 156 char *ns; 157 158 ns = strdup(s); 159 160 if (!ns) 161 error("Out of memory while duplicating string '%s'", s); 162 163 return ns; 164 } 165 166 const char * 167 fw3_find_command(const char *cmd) 168 { 169 struct stat s; 170 int plen = 0, clen = strlen(cmd) + 1; 171 char *search, *p; 172 static char path[PATH_MAX]; 173 174 if (!stat(cmd, &s) && S_ISREG(s.st_mode)) 175 return cmd; 176 177 search = getenv("PATH"); 178 179 if (!search) 180 search = "/bin:/usr/bin:/sbin:/usr/sbin"; 181 182 p = search; 183 184 do 185 { 186 if (*p != ':' && *p != '\0') 187 continue; 188 189 plen = p - search; 190 191 if ((plen + clen) >= sizeof(path)) 192 continue; 193 194 snprintf(path, sizeof(path), "%.*s/%s", plen, search, cmd); 195 196 if (!stat(path, &s) && S_ISREG(s.st_mode)) 197 return path; 198 199 search = p + 1; 200 } 201 while (*p++); 202 203 return NULL; 204 } 205 206 bool 207 fw3_stdout_pipe(void) 208 { 209 pipe_fd = stdout; 210 return true; 211 } 212 213 bool 214 __fw3_command_pipe(bool silent, const char *command, ...) 215 { 216 pid_t pid; 217 va_list argp; 218 int pfds[2]; 219 int argn; 220 char *arg, **args, **tmp; 221 222 command = fw3_find_command(command); 223 224 if (!command) 225 return false; 226 227 if (pipe(pfds)) 228 return false; 229 230 argn = 2; 231 args = calloc(argn, sizeof(arg)); 232 233 if (!args) 234 return false; 235 236 args[0] = (char *)command; 237 args[1] = NULL; 238 239 va_start(argp, command); 240 241 while ((arg = va_arg(argp, char *)) != NULL) 242 { 243 tmp = realloc(args, ++argn * sizeof(arg)); 244 245 if (!tmp) 246 break; 247 248 args = tmp; 249 args[argn-2] = arg; 250 args[argn-1] = NULL; 251 } 252 253 va_end(argp); 254 255 switch ((pid = fork())) 256 { 257 case -1: 258 free(args); 259 return false; 260 261 case 0: 262 dup2(pfds[0], 0); 263 264 close(pfds[0]); 265 close(pfds[1]); 266 267 close(1); 268 269 if (silent) 270 close(2); 271 272 execv(command, args); 273 274 default: 275 signal(SIGPIPE, SIG_IGN); 276 pipe_pid = pid; 277 close(pfds[0]); 278 fcntl(pfds[1], F_SETFD, fcntl(pfds[1], F_GETFD) | FD_CLOEXEC); 279 } 280 281 pipe_fd = fdopen(pfds[1], "w"); 282 free(args); 283 return true; 284 } 285 286 void 287 fw3_pr(const char *fmt, ...) 288 { 289 va_list args; 290 291 if (fw3_pr_debug && pipe_fd != stdout) 292 { 293 va_start(args, fmt); 294 vfprintf(stderr, fmt, args); 295 va_end(args); 296 } 297 298 va_start(args, fmt); 299 vfprintf(pipe_fd, fmt, args); 300 va_end(args); 301 } 302 303 void 304 fw3_command_close(void) 305 { 306 if (pipe_fd && pipe_fd != stdout) 307 fclose(pipe_fd); 308 309 if (pipe_pid > -1) 310 waitpid(pipe_pid, NULL, 0); 311 312 signal(SIGPIPE, SIG_DFL); 313 314 pipe_fd = NULL; 315 pipe_pid = -1; 316 } 317 318 static bool 319 file_contains(const char *path, const char *str) 320 { 321 FILE *f; 322 char line[12]; 323 bool seen = false; 324 325 if (!(f = fopen(path, "r"))) 326 return false; 327 328 while (fgets(line, sizeof(line), f)) 329 { 330 if (!strncmp(line, str, strlen(str))) 331 { 332 seen = true; 333 break; 334 } 335 } 336 337 fclose(f); 338 339 return seen; 340 } 341 342 bool 343 fw3_has_target(const bool ipv6, const char *target) 344 { 345 const char *path = ipv6 346 ? "/proc/net/ip6_tables_targets" : "/proc/net/ip_tables_targets"; 347 348 return file_contains(path, target); 349 } 350 351 bool 352 fw3_lock_path(int *fd, const char *path) 353 { 354 int lock_fd = open(path, O_CREAT|O_WRONLY, S_IRUSR|S_IWUSR); 355 356 if (lock_fd < 0) 357 { 358 warn("Cannot create lock file %s: %s", path, strerror(errno)); 359 return false; 360 } 361 362 if (flock(lock_fd, LOCK_EX)) 363 { 364 warn("Cannot acquire exclusive lock: %s", strerror(errno)); 365 close(lock_fd); 366 return false; 367 } 368 369 *fd = lock_fd; 370 371 return true; 372 } 373 374 bool 375 fw3_lock() 376 { 377 return fw3_lock_path(&fw3_lock_fd, FW3_LOCKFILE); 378 } 379 380 381 void 382 fw3_unlock_path(int *fd, const char *lockpath) 383 { 384 if (*fd < 0) 385 return; 386 387 if (flock(*fd, LOCK_UN)) 388 warn("Cannot release exclusive lock: %s", strerror(errno)); 389 390 close(*fd); 391 392 *fd = -1; 393 } 394 395 396 void 397 fw3_unlock(void) 398 { 399 fw3_unlock_path(&fw3_lock_fd, FW3_LOCKFILE); 400 } 401 402 403 static void 404 write_defaults_uci(struct uci_context *ctx, struct fw3_defaults *d, 405 struct uci_package *dest) 406 { 407 char buf[sizeof("0xffffffff")]; 408 struct uci_ptr ptr = { .p = dest }; 409 410 uci_add_section(ctx, dest, "defaults", &ptr.s); 411 412 ptr.o = NULL; 413 ptr.option = "input"; 414 ptr.value = fw3_flag_names[d->policy_input]; 415 uci_set(ctx, &ptr); 416 417 ptr.o = NULL; 418 ptr.option = "output"; 419 ptr.value = fw3_flag_names[d->policy_output]; 420 uci_set(ctx, &ptr); 421 422 ptr.o = NULL; 423 ptr.option = "forward"; 424 ptr.value = fw3_flag_names[d->policy_forward]; 425 uci_set(ctx, &ptr); 426 427 snprintf(buf, sizeof(buf), "0x%x", d->flags[0]); 428 ptr.o = NULL; 429 ptr.option = "__flags_v4"; 430 ptr.value = buf; 431 uci_set(ctx, &ptr); 432 433 snprintf(buf, sizeof(buf), "0x%x", d->flags[1]); 434 ptr.o = NULL; 435 ptr.option = "__flags_v6"; 436 ptr.value = buf; 437 uci_set(ctx, &ptr); 438 } 439 440 static void 441 write_zone_uci(struct uci_context *ctx, struct fw3_zone *z, 442 struct uci_package *dest, struct ifaddrs *ifaddr) 443 { 444 struct fw3_device *dev; 445 struct fw3_address *sub; 446 struct ifaddrs *ifa; 447 enum fw3_family fam = FW3_FAMILY_ANY; 448 449 char *p, buf[INET6_ADDRSTRLEN]; 450 451 struct uci_ptr ptr = { .p = dest }; 452 453 if (!z->enabled) 454 return; 455 456 if (fw3_no_table(z->flags[0]) && !fw3_no_table(z->flags[1])) 457 fam = FW3_FAMILY_V6; 458 else if (!fw3_no_table(z->flags[0]) && fw3_no_table(z->flags[1])) 459 fam = FW3_FAMILY_V4; 460 else if (fw3_no_table(z->flags[0]) && fw3_no_table(z->flags[1])) 461 return; 462 463 uci_add_section(ctx, dest, "zone", &ptr.s); 464 465 ptr.o = NULL; 466 ptr.option = "name"; 467 ptr.value = z->name; 468 uci_set(ctx, &ptr); 469 470 ptr.o = NULL; 471 ptr.option = "input"; 472 ptr.value = fw3_flag_names[z->policy_input]; 473 uci_set(ctx, &ptr); 474 475 ptr.o = NULL; 476 ptr.option = "output"; 477 ptr.value = fw3_flag_names[z->policy_output]; 478 uci_set(ctx, &ptr); 479 480 ptr.o = NULL; 481 ptr.option = "forward"; 482 ptr.value = fw3_flag_names[z->policy_forward]; 483 uci_set(ctx, &ptr); 484 485 ptr.o = NULL; 486 ptr.option = "masq"; 487 ptr.value = z->masq ? "1" : ""; 488 uci_set(ctx, &ptr); 489 490 ptr.o = NULL; 491 ptr.option = "mtu_fix"; 492 ptr.value = z->mtu_fix ? "1" : ""; 493 uci_set(ctx, &ptr); 494 495 ptr.o = NULL; 496 ptr.option = "custom_chains"; 497 ptr.value = z->custom_chains ? "1" : ""; 498 uci_set(ctx, &ptr); 499 500 if (fam != FW3_FAMILY_ANY) 501 { 502 ptr.o = NULL; 503 ptr.option = "family"; 504 ptr.value = fw3_flag_names[fam]; 505 uci_set(ctx, &ptr); 506 } 507 508 ptr.o = NULL; 509 ptr.option = "device"; 510 511 fw3_foreach(dev, &z->devices) 512 { 513 char *ep; 514 515 if (!dev) 516 continue; 517 518 p = buf; 519 ep = buf + sizeof(buf); 520 521 if (dev->invert) 522 p += snprintf(p, ep - p, "!"); 523 524 if (*dev->network) 525 p += snprintf(p, ep - p, "%s@%s", dev->name, dev->network); 526 else 527 p += snprintf(p, ep - p, "%s", dev->name); 528 529 ptr.value = buf; 530 uci_add_list(ctx, &ptr); 531 } 532 533 ptr.o = NULL; 534 ptr.option = "subnet"; 535 536 fw3_foreach(sub, &z->subnets) 537 { 538 if (!sub) 539 continue; 540 541 ptr.value = fw3_address_to_string(sub, true, false); 542 uci_add_list(ctx, &ptr); 543 } 544 545 ptr.o = NULL; 546 ptr.option = "__addrs"; 547 548 fw3_foreach(dev, &z->devices) 549 { 550 if (!dev) 551 continue; 552 553 for (ifa = ifaddr; ifa; ifa = ifa->ifa_next) 554 { 555 if (!ifa->ifa_addr || strcmp(dev->name, ifa->ifa_name)) 556 continue; 557 558 if (ifa->ifa_addr->sa_family == AF_INET) 559 inet_ntop(AF_INET, 560 &((struct sockaddr_in *)ifa->ifa_addr)->sin_addr, 561 buf, sizeof(buf)); 562 else if (ifa->ifa_addr->sa_family == AF_INET6) 563 inet_ntop(AF_INET6, 564 &((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr, 565 buf, sizeof(buf)); 566 else 567 continue; 568 569 ptr.value = buf; 570 uci_add_list(ctx, &ptr); 571 } 572 } 573 574 if (z->extra_src) 575 { 576 ptr.o = NULL; 577 ptr.option = "extra_src"; 578 ptr.value = z->extra_src; 579 uci_set(ctx, &ptr); 580 } 581 582 if (z->extra_dest) 583 { 584 ptr.o = NULL; 585 ptr.option = "extra_dest"; 586 ptr.value = z->extra_dest; 587 uci_set(ctx, &ptr); 588 } 589 590 snprintf(buf, sizeof(buf), "0x%x", z->flags[0]); 591 ptr.o = NULL; 592 ptr.option = "__flags_v4"; 593 ptr.value = buf; 594 uci_set(ctx, &ptr); 595 596 snprintf(buf, sizeof(buf), "0x%x", z->flags[1]); 597 ptr.o = NULL; 598 ptr.option = "__flags_v6"; 599 ptr.value = buf; 600 uci_set(ctx, &ptr); 601 } 602 603 static void 604 write_ipset_uci(struct uci_context *ctx, struct fw3_ipset *s, 605 struct uci_package *dest) 606 { 607 struct fw3_ipset_datatype *type; 608 609 char buf[sizeof("65535-65535")]; 610 611 struct uci_ptr ptr = { .p = dest }; 612 613 if (!s->enabled || s->external) 614 return; 615 616 uci_add_section(ctx, dest, "ipset", &ptr.s); 617 618 ptr.o = NULL; 619 ptr.option = "name"; 620 ptr.value = s->name; 621 uci_set(ctx, &ptr); 622 623 ptr.o = NULL; 624 ptr.option = "family"; 625 if (s->family == FW3_FAMILY_V4) 626 ptr.value = "ipv4"; 627 else 628 ptr.value = "ipv6"; 629 uci_set(ctx, &ptr); 630 631 ptr.o = NULL; 632 ptr.option = "storage"; 633 ptr.value = fw3_ipset_method_names[s->method]; 634 uci_set(ctx, &ptr); 635 636 list_for_each_entry(type, &s->datatypes, list) 637 { 638 snprintf(buf, sizeof(buf), "%s_%s", type->dir, fw3_ipset_type_names[type->type]); 639 ptr.o = NULL; 640 ptr.option = "match"; 641 ptr.value = buf; 642 uci_add_list(ctx, &ptr); 643 } 644 645 if (s->iprange.set) 646 { 647 ptr.o = NULL; 648 ptr.option = "iprange"; 649 ptr.value = fw3_address_to_string(&s->iprange, false, false); 650 uci_set(ctx, &ptr); 651 } 652 653 if (s->portrange.set) 654 { 655 snprintf(buf, sizeof(buf), "%u-%u", s->portrange.port_min, s->portrange.port_max); 656 ptr.o = NULL; 657 ptr.option = "portrange"; 658 ptr.value = buf; 659 uci_set(ctx, &ptr); 660 } 661 } 662 663 void 664 fw3_write_statefile(void *state) 665 { 666 FILE *sf; 667 struct fw3_state *s = state; 668 struct fw3_zone *z; 669 struct fw3_ipset *i; 670 struct ifaddrs *ifaddr; 671 672 struct uci_package *p; 673 674 if (fw3_no_family(s->defaults.flags[0]) && 675 fw3_no_family(s->defaults.flags[1])) 676 { 677 unlink(FW3_STATEFILE); 678 } 679 else 680 { 681 sf = fopen(FW3_STATEFILE, "w+"); 682 683 if (!sf) 684 { 685 warn("Cannot create state %s: %s", FW3_STATEFILE, strerror(errno)); 686 return; 687 } 688 689 if (getifaddrs(&ifaddr)) 690 { 691 warn("Cannot get interface addresses: %s", strerror(errno)); 692 ifaddr = NULL; 693 } 694 695 if ((p = uci_lookup_package(s->uci, "fw3_state")) != NULL) 696 uci_unload(s->uci, p); 697 698 uci_import(s->uci, sf, "fw3_state", NULL, true); 699 700 if ((p = uci_lookup_package(s->uci, "fw3_state")) != NULL) 701 { 702 write_defaults_uci(s->uci, &s->defaults, p); 703 704 list_for_each_entry(z, &s->zones, list) 705 write_zone_uci(s->uci, z, p, ifaddr); 706 707 list_for_each_entry(i, &s->ipsets, list) 708 write_ipset_uci(s->uci, i, p); 709 710 uci_export(s->uci, sf, p, true); 711 uci_unload(s->uci, p); 712 } 713 714 fsync(fileno(sf)); 715 fclose(sf); 716 717 if (ifaddr) 718 freeifaddrs(ifaddr); 719 } 720 } 721 722 723 void 724 fw3_free_object(void *obj, const void *opts) 725 { 726 const struct fw3_option *ol; 727 struct list_head *list, *cur, *tmp; 728 729 for (ol = opts; ol->name; ol++) 730 { 731 if (!ol->elem_size) 732 continue; 733 734 list = (struct list_head *)((char *)obj + ol->offset); 735 list_for_each_safe(cur, tmp, list) 736 { 737 list_del(cur); 738 free(cur); 739 } 740 } 741 742 free(obj); 743 } 744 745 void 746 fw3_free_list(struct list_head *head) 747 { 748 struct list_head *entry, *tmp; 749 750 if (!head) 751 return; 752 753 list_for_each_safe(entry, tmp, head) 754 { 755 list_del(entry); 756 free(entry); 757 } 758 759 free(head); 760 } 761 762 bool 763 fw3_hotplug(bool add, void *zone, void *device) 764 { 765 struct fw3_zone *z = zone; 766 struct fw3_device *d = device; 767 768 if (!*d->network) 769 return false; 770 771 switch (fork()) 772 { 773 case -1: 774 warn("Unable to fork(): %s\n", strerror(errno)); 775 return false; 776 777 case 0: 778 break; 779 780 default: 781 return true; 782 } 783 784 close(0); 785 close(1); 786 close(2); 787 if (chdir("/")) {}; 788 789 clearenv(); 790 setenv("ACTION", add ? "add" : "remove", 1); 791 setenv("ZONE", z->name, 1); 792 setenv("INTERFACE", d->network, 1); 793 setenv("DEVICE", d->name, 1); 794 795 execl(FW3_HOTPLUG, FW3_HOTPLUG, "firewall", NULL); 796 797 /* unreached */ 798 return false; 799 } 800 801 int 802 fw3_netmask2bitlen(int family, void *mask) 803 { 804 int bits; 805 struct in_addr *v4; 806 struct in6_addr *v6; 807 808 if (family == FW3_FAMILY_V6) 809 for (bits = 0, v6 = mask; 810 bits < 128 && (v6->s6_addr[bits / 8] << (bits % 8)) & 128; 811 bits++); 812 else 813 for (bits = 0, v4 = mask; 814 bits < 32 && (ntohl(v4->s_addr) << bits) & 0x80000000; 815 bits++); 816 817 return bits; 818 } 819 820 bool 821 fw3_bitlen2netmask(int family, int bits, void *mask) 822 { 823 int i; 824 uint8_t rem, b; 825 struct in_addr *v4; 826 struct in6_addr *v6; 827 828 if (family == FW3_FAMILY_V6) 829 { 830 if (bits < -128 || bits > 128) 831 return false; 832 833 v6 = mask; 834 rem = abs(bits); 835 836 for (i = 0; i < sizeof(v6->s6_addr); i++) 837 { 838 b = (rem > 8) ? 8 : rem; 839 v6->s6_addr[i] = (uint8_t)(0xFF << (8 - b)); 840 rem -= b; 841 } 842 843 if (bits < 0) 844 for (i = 0; i < sizeof(v6->s6_addr); i++) 845 v6->s6_addr[i] = ~v6->s6_addr[i]; 846 } 847 else 848 { 849 if (bits < -32 || bits > 32) 850 return false; 851 852 v4 = mask; 853 v4->s_addr = bits ? htonl(~((1 << (32 - abs(bits))) - 1)) : 0; 854 855 if (bits < 0) 856 v4->s_addr = ~v4->s_addr; 857 } 858 859 return true; 860 } 861 862 void 863 fw3_flush_conntrack(void *state) 864 { 865 bool found; 866 struct fw3_state *s = state; 867 struct fw3_address *addr; 868 struct fw3_device *dev; 869 struct fw3_zone *zone; 870 struct ifaddrs *ifaddr, *ifa; 871 struct sockaddr_in *sin; 872 struct sockaddr_in6 *sin6; 873 char buf[INET6_ADDRSTRLEN]; 874 FILE *ct; 875 876 if (!state) 877 { 878 if ((ct = fopen("/proc/net/nf_conntrack", "w")) != NULL) 879 { 880 info(" * Flushing conntrack table ..."); 881 882 fwrite("f\n", 1, 2, ct); 883 fclose(ct); 884 } 885 886 return; 887 } 888 889 if (getifaddrs(&ifaddr)) 890 { 891 warn("Cannot get interface addresses: %s", strerror(errno)); 892 return; 893 } 894 895 if ((ct = fopen("/proc/net/nf_conntrack", "w")) != NULL) 896 { 897 list_for_each_entry(zone, &s->zones, list) 898 list_for_each_entry(addr, &zone->old_addrs, list) 899 { 900 found = false; 901 902 list_for_each_entry(dev, &zone->devices, list) 903 { 904 for (ifa = ifaddr; ifa && !found; ifa = ifa->ifa_next) 905 { 906 if (!ifa->ifa_addr || strcmp(dev->name, ifa->ifa_name)) 907 continue; 908 909 sin = (struct sockaddr_in *)ifa->ifa_addr; 910 sin6 = (struct sockaddr_in6 *)ifa->ifa_addr; 911 912 if (addr->family == FW3_FAMILY_V4 && 913 sin->sin_family == AF_INET) 914 { 915 found = !memcmp(&addr->address.v4, &sin->sin_addr, 916 sizeof(sin->sin_addr)); 917 } 918 else if (addr->family == FW3_FAMILY_V6 && 919 sin6->sin6_family == AF_INET6) 920 { 921 found = !memcmp(&addr->address.v6, &sin6->sin6_addr, 922 sizeof(sin6->sin6_addr)); 923 } 924 } 925 926 if (found) 927 break; 928 } 929 930 if (!found) 931 { 932 inet_ntop(addr->family == FW3_FAMILY_V4 ? AF_INET : AF_INET6, 933 &addr->address.v4, buf, sizeof(buf)); 934 935 info(" * Flushing conntrack: %s", buf); 936 fprintf(ct, "%s\n", buf); 937 } 938 } 939 940 fclose(ct); 941 } 942 943 freeifaddrs(ifaddr); 944 } 945 946 bool fw3_attr_parse_name_type(struct blob_attr *entry, const char **name, const char **type) 947 { 948 struct blob_attr *opt; 949 unsigned orem; 950 951 if (!type || !name) 952 return false; 953 954 *type = NULL; 955 956 blobmsg_for_each_attr(opt, entry, orem) 957 if (!strcmp(blobmsg_name(opt), "type")) 958 *type = blobmsg_get_string(opt); 959 else if (!strcmp(blobmsg_name(opt), "name")) 960 *name = blobmsg_get_string(opt); 961 962 return *type != NULL ? true : false; 963 } 964 965 const char * 966 fw3_protoname(void *proto) 967 { 968 static char buf[sizeof("4294967295")]; 969 struct fw3_protocol *p = proto; 970 struct protoent *pe; 971 972 if (!p) 973 return "?"; 974 975 pe = getprotobynumber(p->protocol); 976 977 if (!pe) 978 { 979 snprintf(buf, sizeof(buf), "%u", p->protocol); 980 return buf; 981 } 982 983 return pe->p_name; 984 } 985 986 bool 987 fw3_check_loopback_dev(const char *name) 988 { 989 struct ifreq ifr; 990 int s; 991 bool rv = false; 992 993 s = socket(AF_LOCAL, SOCK_DGRAM, 0); 994 995 if (s < 0) 996 return false; 997 998 memset(&ifr, 0, sizeof(ifr)); 999 snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "%s", name); 1000 1001 if (ioctl(s, SIOCGIFFLAGS, &ifr) >= 0) { 1002 if (ifr.ifr_flags & IFF_LOOPBACK) 1003 rv = true; 1004 } 1005 1006 close(s); 1007 1008 return rv; 1009 } 1010 1011 bool 1012 fw3_check_loopback_addr(struct fw3_address *addr) 1013 { 1014 if (addr->family == FW3_FAMILY_V4 && 1015 (ntohl(addr->address.v4.s_addr) >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET) 1016 return true; 1017 1018 if (addr->family == FW3_FAMILY_V6 && !addr->range && 1019 fw3_netmask2bitlen(FW3_FAMILY_V6, &addr->mask.v6) == 128 && 1020 IN6_IS_ADDR_LOOPBACK(&addr->address.v6)) 1021 return true; 1022 1023 return false; 1024 } 1025
This page was automatically generated by LXR 0.3.1. • OpenWrt