1 /* 2 * (C) 2000-2006 by the netfilter coreteam <coreteam (at) netfilter.org>: 3 * 4 * This program is free software; you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation; either version 2 of the License, or 7 * (at your option) any later version. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program; if not, write to the Free Software 16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 */ 18 #include "config.h" 19 #include <ctype.h> 20 #include <errno.h> 21 #include <fcntl.h> 22 #include <inttypes.h> 23 #include <netdb.h> 24 #include <stdarg.h> 25 #include <stdbool.h> 26 #include <stdio.h> 27 #include <stdlib.h> 28 #include <string.h> 29 #include <unistd.h> 30 #include <sys/socket.h> 31 #include <sys/stat.h> 32 #include <sys/statfs.h> 33 #include <sys/types.h> 34 #include <sys/utsname.h> 35 #include <sys/wait.h> 36 #include <arpa/inet.h> 37 #if defined(HAVE_LINUX_MAGIC_H) 38 # include <linux/magic.h> /* for PROC_SUPER_MAGIC */ 39 #elif defined(HAVE_LINUX_PROC_FS_H) 40 # include <linux/proc_fs.h> /* Linux 2.4 */ 41 #else 42 # define PROC_SUPER_MAGIC 0x9fa0 43 #endif 44 45 #include <xtables.h> 46 #include <limits.h> /* INT_MAX in ip_tables.h/ip6_tables.h */ 47 #include <linux/netfilter_ipv4/ip_tables.h> 48 #include <linux/netfilter_ipv6/ip6_tables.h> 49 #include <libiptc/libxtc.h> 50 51 #ifndef NO_SHARED_LIBS 52 #include <dlfcn.h> 53 #endif 54 #ifndef IPT_SO_GET_REVISION_MATCH /* Old kernel source. */ 55 # define IPT_SO_GET_REVISION_MATCH (IPT_BASE_CTL + 2) 56 # define IPT_SO_GET_REVISION_TARGET (IPT_BASE_CTL + 3) 57 #endif 58 #ifndef IP6T_SO_GET_REVISION_MATCH /* Old kernel source. */ 59 # define IP6T_SO_GET_REVISION_MATCH 68 60 # define IP6T_SO_GET_REVISION_TARGET 69 61 #endif 62 #include <getopt.h> 63 #include "iptables/internal.h" 64 #include "xshared.h" 65 66 #define NPROTO 255 67 68 #ifndef PROC_SYS_MODPROBE 69 #define PROC_SYS_MODPROBE "/proc/sys/kernel/modprobe" 70 #endif 71 72 /* we need this for ip6?tables-restore. ip6?tables-restore.c sets line to the 73 * current line of the input file, in order to give a more precise error 74 * message. ip6?tables itself doesn't need this, so it is initialized to the 75 * magic number of -1 */ 76 int line = -1; 77 78 void basic_exit_err(enum xtables_exittype status, const char *msg, ...) __attribute__((noreturn, format(printf,2,3))); 79 80 struct xtables_globals *xt_params = NULL; 81 82 void basic_exit_err(enum xtables_exittype status, const char *msg, ...) 83 { 84 va_list args; 85 86 va_start(args, msg); 87 fprintf(stderr, "%s v%s: ", xt_params->program_name, xt_params->program_version); 88 vfprintf(stderr, msg, args); 89 va_end(args); 90 fprintf(stderr, "\n"); 91 exit(status); 92 } 93 94 void xtables_free_opts(int unused) 95 { 96 if (xt_params->opts != xt_params->orig_opts) { 97 free(xt_params->opts); 98 xt_params->opts = NULL; 99 } 100 } 101 102 struct option *xtables_merge_options(struct option *orig_opts, 103 struct option *oldopts, 104 const struct option *newopts, 105 unsigned int *option_offset) 106 { 107 unsigned int num_oold = 0, num_old = 0, num_new = 0, i; 108 struct option *merge, *mp; 109 110 if (newopts == NULL) 111 return oldopts; 112 113 for (num_oold = 0; orig_opts[num_oold].name; num_oold++) ; 114 if (oldopts != NULL) 115 for (num_old = 0; oldopts[num_old].name; num_old++) ; 116 for (num_new = 0; newopts[num_new].name; num_new++) ; 117 118 /* 119 * Since @oldopts also has @orig_opts already (and does so at the 120 * start), skip these entries. 121 */ 122 oldopts += num_oold; 123 num_old -= num_oold; 124 125 merge = malloc(sizeof(*mp) * (num_oold + num_old + num_new + 1)); 126 if (merge == NULL) 127 return NULL; 128 129 /* Let the base options -[ADI...] have precedence over everything */ 130 memcpy(merge, orig_opts, sizeof(*mp) * num_oold); 131 mp = merge + num_oold; 132 133 /* Second, the new options */ 134 xt_params->option_offset += XT_OPTION_OFFSET_SCALE; 135 *option_offset = xt_params->option_offset; 136 memcpy(mp, newopts, sizeof(*mp) * num_new); 137 138 for (i = 0; i < num_new; ++i, ++mp) 139 mp->val += *option_offset; 140 141 /* Third, the old options */ 142 memcpy(mp, oldopts, sizeof(*mp) * num_old); 143 mp += num_old; 144 xtables_free_opts(0); 145 146 /* Clear trailing entry */ 147 memset(mp, 0, sizeof(*mp)); 148 return merge; 149 } 150 151 static const struct xtables_afinfo afinfo_ipv4 = { 152 .kmod = "ip_tables", 153 .proc_exists = "/proc/net/ip_tables_names", 154 .libprefix = "libipt_", 155 .family = NFPROTO_IPV4, 156 .ipproto = IPPROTO_IP, 157 .so_rev_match = IPT_SO_GET_REVISION_MATCH, 158 .so_rev_target = IPT_SO_GET_REVISION_TARGET, 159 }; 160 161 static const struct xtables_afinfo afinfo_ipv6 = { 162 .kmod = "ip6_tables", 163 .proc_exists = "/proc/net/ip6_tables_names", 164 .libprefix = "libip6t_", 165 .family = NFPROTO_IPV6, 166 .ipproto = IPPROTO_IPV6, 167 .so_rev_match = IP6T_SO_GET_REVISION_MATCH, 168 .so_rev_target = IP6T_SO_GET_REVISION_TARGET, 169 }; 170 171 /* Dummy families for arptables-compat and ebtables-compat. Leave structure 172 * fields that we don't use unset. 173 */ 174 static const struct xtables_afinfo afinfo_bridge = { 175 .libprefix = "libebt_", 176 .family = NFPROTO_BRIDGE, 177 }; 178 179 static const struct xtables_afinfo afinfo_arp = { 180 .libprefix = "libarpt_", 181 .family = NFPROTO_ARP, 182 }; 183 184 const struct xtables_afinfo *afinfo; 185 186 /* Search path for Xtables .so files */ 187 static const char *xtables_libdir; 188 189 /* the path to command to load kernel module */ 190 const char *xtables_modprobe_program; 191 192 /* Keep track of matches/targets pending full registration: linked lists. */ 193 struct xtables_match *xtables_pending_matches; 194 struct xtables_target *xtables_pending_targets; 195 196 /* Keep track of fully registered external matches/targets: linked lists. */ 197 struct xtables_match *xtables_matches; 198 struct xtables_target *xtables_targets; 199 200 /* Fully register a match/target which was previously partially registered. */ 201 static void xtables_fully_register_pending_match(struct xtables_match *me); 202 static void xtables_fully_register_pending_target(struct xtables_target *me); 203 204 void xtables_init(void) 205 { 206 xtables_libdir = getenv("XTABLES_LIBDIR"); 207 if (xtables_libdir != NULL) 208 return; 209 xtables_libdir = getenv("IPTABLES_LIB_DIR"); 210 if (xtables_libdir != NULL) { 211 fprintf(stderr, "IPTABLES_LIB_DIR is deprecated, " 212 "use XTABLES_LIBDIR.\n"); 213 return; 214 } 215 /* 216 * Well yes, IP6TABLES_LIB_DIR is of lower priority over 217 * IPTABLES_LIB_DIR since this moved to libxtables; I think that is ok 218 * for these env vars are deprecated anyhow, and in light of the 219 * (shared) libxt_*.so files, makes less sense to have 220 * IPTABLES_LIB_DIR != IP6TABLES_LIB_DIR. 221 */ 222 xtables_libdir = getenv("IP6TABLES_LIB_DIR"); 223 if (xtables_libdir != NULL) { 224 fprintf(stderr, "IP6TABLES_LIB_DIR is deprecated, " 225 "use XTABLES_LIBDIR.\n"); 226 return; 227 } 228 xtables_libdir = XTABLES_LIBDIR; 229 } 230 231 void xtables_set_nfproto(uint8_t nfproto) 232 { 233 switch (nfproto) { 234 case NFPROTO_IPV4: 235 afinfo = &afinfo_ipv4; 236 break; 237 case NFPROTO_IPV6: 238 afinfo = &afinfo_ipv6; 239 break; 240 case NFPROTO_BRIDGE: 241 afinfo = &afinfo_bridge; 242 break; 243 case NFPROTO_ARP: 244 afinfo = &afinfo_arp; 245 break; 246 default: 247 fprintf(stderr, "libxtables: unhandled NFPROTO in %s\n", 248 __func__); 249 } 250 } 251 252 /** 253 * xtables_set_params - set the global parameters used by xtables 254 * @xtp: input xtables_globals structure 255 * 256 * The app is expected to pass a valid xtables_globals data-filled 257 * with proper values 258 * @xtp cannot be NULL 259 * 260 * Returns -1 on failure to set and 0 on success 261 */ 262 int xtables_set_params(struct xtables_globals *xtp) 263 { 264 if (!xtp) { 265 fprintf(stderr, "%s: Illegal global params\n",__func__); 266 return -1; 267 } 268 269 xt_params = xtp; 270 271 if (!xt_params->exit_err) 272 xt_params->exit_err = basic_exit_err; 273 274 return 0; 275 } 276 277 int xtables_init_all(struct xtables_globals *xtp, uint8_t nfproto) 278 { 279 xtables_init(); 280 xtables_set_nfproto(nfproto); 281 return xtables_set_params(xtp); 282 } 283 284 /** 285 * xtables_*alloc - wrappers that exit on failure 286 */ 287 void *xtables_calloc(size_t count, size_t size) 288 { 289 void *p; 290 291 if ((p = calloc(count, size)) == NULL) { 292 perror("ip[6]tables: calloc failed"); 293 exit(1); 294 } 295 296 return p; 297 } 298 299 void *xtables_malloc(size_t size) 300 { 301 void *p; 302 303 if ((p = malloc(size)) == NULL) { 304 perror("ip[6]tables: malloc failed"); 305 exit(1); 306 } 307 308 return p; 309 } 310 311 void *xtables_realloc(void *ptr, size_t size) 312 { 313 void *p; 314 315 if ((p = realloc(ptr, size)) == NULL) { 316 perror("ip[6]tables: realloc failed"); 317 exit(1); 318 } 319 320 return p; 321 } 322 323 static char *get_modprobe(void) 324 { 325 int procfile; 326 char *ret; 327 int count; 328 329 procfile = open(PROC_SYS_MODPROBE, O_RDONLY); 330 if (procfile < 0) 331 return NULL; 332 if (fcntl(procfile, F_SETFD, FD_CLOEXEC) == -1) { 333 fprintf(stderr, "Could not set close on exec: %s\n", 334 strerror(errno)); 335 exit(1); 336 } 337 338 ret = malloc(PATH_MAX); 339 if (ret) { 340 count = read(procfile, ret, PATH_MAX); 341 if (count > 0 && count < PATH_MAX) 342 { 343 if (ret[count - 1] == '\n') 344 ret[count - 1] = '\0'; 345 else 346 ret[count] = '\0'; 347 close(procfile); 348 return ret; 349 } 350 } 351 free(ret); 352 close(procfile); 353 return NULL; 354 } 355 356 int xtables_insmod(const char *modname, const char *modprobe, bool quiet) 357 { 358 char *buf = NULL; 359 char *argv[4]; 360 int status; 361 362 /* If they don't explicitly set it, read out of kernel */ 363 if (!modprobe) { 364 buf = get_modprobe(); 365 if (!buf) 366 return -1; 367 modprobe = buf; 368 } 369 370 argv[0] = (char *)modprobe; 371 argv[1] = (char *)modname; 372 argv[2] = quiet ? "-q" : NULL; 373 argv[3] = NULL; 374 375 /* 376 * Need to flush the buffer, or the child may output it again 377 * when switching the program thru execv. 378 */ 379 fflush(stdout); 380 381 switch (vfork()) { 382 case 0: 383 execv(argv[0], argv); 384 385 /* not usually reached */ 386 _exit(1); 387 case -1: 388 free(buf); 389 return -1; 390 391 default: /* parent */ 392 wait(&status); 393 } 394 395 free(buf); 396 if (WIFEXITED(status) && WEXITSTATUS(status) == 0) 397 return 0; 398 return -1; 399 } 400 401 /* return true if a given file exists within procfs */ 402 static bool proc_file_exists(const char *filename) 403 { 404 struct stat s; 405 struct statfs f; 406 407 if (lstat(filename, &s)) 408 return false; 409 if (!S_ISREG(s.st_mode)) 410 return false; 411 if (statfs(filename, &f)) 412 return false; 413 if (f.f_type != PROC_SUPER_MAGIC) 414 return false; 415 return true; 416 } 417 418 int xtables_load_ko(const char *modprobe, bool quiet) 419 { 420 static bool loaded = false; 421 int ret; 422 423 if (loaded) 424 return 0; 425 426 if (proc_file_exists(afinfo->proc_exists)) { 427 loaded = true; 428 return 0; 429 }; 430 431 ret = xtables_insmod(afinfo->kmod, modprobe, quiet); 432 if (ret == 0) 433 loaded = true; 434 435 return ret; 436 } 437 438 /** 439 * xtables_strtou{i,l} - string to number conversion 440 * @s: input string 441 * @end: like strtoul's "end" pointer 442 * @value: pointer for result 443 * @min: minimum accepted value 444 * @max: maximum accepted value 445 * 446 * If @end is NULL, we assume the caller wants a "strict strtoul", and hence 447 * "15a" is rejected. 448 * In either case, the value obtained is compared for min-max compliance. 449 * Base is always 0, i.e. autodetect depending on @s. 450 * 451 * Returns true/false whether number was accepted. On failure, *value has 452 * undefined contents. 453 */ 454 bool xtables_strtoul(const char *s, char **end, uintmax_t *value, 455 uintmax_t min, uintmax_t max) 456 { 457 uintmax_t v; 458 const char *p; 459 char *my_end; 460 461 errno = 0; 462 /* Since strtoul allows leading minus, we have to check for ourself. */ 463 for (p = s; isspace(*p); ++p) 464 ; 465 if (*p == '-') 466 return false; 467 v = strtoumax(s, &my_end, 0); 468 if (my_end == s) 469 return false; 470 if (end != NULL) 471 *end = my_end; 472 473 if (errno != ERANGE && min <= v && (max == 0 || v <= max)) { 474 if (value != NULL) 475 *value = v; 476 if (end == NULL) 477 return *my_end == '\0'; 478 return true; 479 } 480 481 return false; 482 } 483 484 bool xtables_strtoui(const char *s, char **end, unsigned int *value, 485 unsigned int min, unsigned int max) 486 { 487 uintmax_t v; 488 bool ret; 489 490 ret = xtables_strtoul(s, end, &v, min, max); 491 if (value != NULL) 492 *value = v; 493 return ret; 494 } 495 496 int xtables_service_to_port(const char *name, const char *proto) 497 { 498 struct servent *service; 499 500 if ((service = getservbyname(name, proto)) != NULL) 501 return ntohs((unsigned short) service->s_port); 502 503 return -1; 504 } 505 506 uint16_t xtables_parse_port(const char *port, const char *proto) 507 { 508 unsigned int portnum; 509 510 if (xtables_strtoui(port, NULL, &portnum, 0, UINT16_MAX) || 511 (portnum = xtables_service_to_port(port, proto)) != (unsigned)-1) 512 return portnum; 513 514 xt_params->exit_err(PARAMETER_PROBLEM, 515 "invalid port/service `%s' specified", port); 516 } 517 518 void xtables_parse_interface(const char *arg, char *vianame, 519 unsigned char *mask) 520 { 521 unsigned int vialen = strlen(arg); 522 unsigned int i; 523 524 memset(mask, 0, IFNAMSIZ); 525 memset(vianame, 0, IFNAMSIZ); 526 527 if (vialen + 1 > IFNAMSIZ) 528 xt_params->exit_err(PARAMETER_PROBLEM, 529 "interface name `%s' must be shorter than IFNAMSIZ" 530 " (%i)", arg, IFNAMSIZ-1); 531 532 strcpy(vianame, arg); 533 if (vialen == 0) 534 return; 535 else if (vianame[vialen - 1] == '+') { 536 memset(mask, 0xFF, vialen - 1); 537 /* Don't remove `+' here! -HW */ 538 } else { 539 /* Include nul-terminator in match */ 540 memset(mask, 0xFF, vialen + 1); 541 for (i = 0; vianame[i]; i++) { 542 if (vianame[i] == '/' || 543 vianame[i] == ' ') { 544 fprintf(stderr, 545 "Warning: weird character in interface" 546 " `%s' ('/' and ' ' are not allowed by the kernel).\n", 547 vianame); 548 break; 549 } 550 } 551 } 552 } 553 554 #ifndef NO_SHARED_LIBS 555 static void *load_extension(const char *search_path, const char *af_prefix, 556 const char *name, bool is_target) 557 { 558 const char *all_prefixes[] = {af_prefix, "libxt_", NULL}; 559 const char **prefix; 560 const char *dir = search_path, *next; 561 void *ptr = NULL; 562 struct stat sb; 563 char path[256]; 564 565 do { 566 next = strchr(dir, ':'); 567 if (next == NULL) 568 next = dir + strlen(dir); 569 570 for (prefix = all_prefixes; *prefix != NULL; ++prefix) { 571 snprintf(path, sizeof(path), "%.*s/%s%s.so", 572 (unsigned int)(next - dir), dir, 573 *prefix, name); 574 575 if (stat(path, &sb) != 0) { 576 if (errno == ENOENT) 577 continue; 578 fprintf(stderr, "%s: %s\n", path, 579 strerror(errno)); 580 return NULL; 581 } 582 if (dlopen(path, RTLD_NOW) == NULL) { 583 fprintf(stderr, "%s: %s\n", path, dlerror()); 584 break; 585 } 586 587 if (is_target) 588 ptr = xtables_find_target(name, XTF_DONT_LOAD); 589 else 590 ptr = xtables_find_match(name, 591 XTF_DONT_LOAD, NULL); 592 593 if (ptr != NULL) 594 return ptr; 595 596 errno = ENOENT; 597 return NULL; 598 } 599 dir = next + 1; 600 } while (*next != '\0'); 601 602 return NULL; 603 } 604 #endif 605 606 static bool extension_cmp(const char *name1, const char *name2, uint32_t family) 607 { 608 if (strcmp(name1, name2) == 0 && 609 (family == afinfo->family || 610 family == NFPROTO_UNSPEC)) 611 return true; 612 613 return false; 614 } 615 616 struct xtables_match * 617 xtables_find_match(const char *name, enum xtables_tryload tryload, 618 struct xtables_rule_match **matches) 619 { 620 struct xtables_match **dptr; 621 struct xtables_match *ptr; 622 const char *icmp6 = "icmp6"; 623 624 if (strlen(name) >= XT_EXTENSION_MAXNAMELEN) 625 xtables_error(PARAMETER_PROBLEM, 626 "Invalid match name \"%s\" (%u chars max)", 627 name, XT_EXTENSION_MAXNAMELEN - 1); 628 629 /* This is ugly as hell. Nonetheless, there is no way of changing 630 * this without hurting backwards compatibility */ 631 if ( (strcmp(name,"icmpv6") == 0) || 632 (strcmp(name,"ipv6-icmp") == 0) || 633 (strcmp(name,"icmp6") == 0) ) 634 name = icmp6; 635 636 /* Trigger delayed initialization */ 637 for (dptr = &xtables_pending_matches; *dptr; ) { 638 if (extension_cmp(name, (*dptr)->name, (*dptr)->family)) { 639 ptr = *dptr; 640 *dptr = (*dptr)->next; 641 ptr->next = NULL; 642 xtables_fully_register_pending_match(ptr); 643 } else { 644 dptr = &((*dptr)->next); 645 } 646 } 647 648 for (ptr = xtables_matches; ptr; ptr = ptr->next) { 649 if (extension_cmp(name, ptr->name, ptr->family)) { 650 struct xtables_match *clone; 651 652 /* First match of this type: */ 653 if (ptr->m == NULL) 654 break; 655 656 /* Second and subsequent clones */ 657 clone = xtables_malloc(sizeof(struct xtables_match)); 658 memcpy(clone, ptr, sizeof(struct xtables_match)); 659 clone->udata = NULL; 660 clone->mflags = 0; 661 /* This is a clone: */ 662 clone->next = clone; 663 664 ptr = clone; 665 break; 666 } 667 } 668 669 #ifndef NO_SHARED_LIBS 670 if (!ptr && tryload != XTF_DONT_LOAD && tryload != XTF_DURING_LOAD) { 671 ptr = load_extension(xtables_libdir, afinfo->libprefix, 672 name, false); 673 674 if (ptr == NULL && tryload == XTF_LOAD_MUST_SUCCEED) 675 xt_params->exit_err(PARAMETER_PROBLEM, 676 "Couldn't load match `%s':%s\n", 677 name, strerror(errno)); 678 } 679 #else 680 if (ptr && !ptr->loaded) { 681 if (tryload != XTF_DONT_LOAD) 682 ptr->loaded = 1; 683 else 684 ptr = NULL; 685 } 686 if(!ptr && (tryload == XTF_LOAD_MUST_SUCCEED)) { 687 xt_params->exit_err(PARAMETER_PROBLEM, 688 "Couldn't find match `%s'\n", name); 689 } 690 #endif 691 692 if (ptr && matches) { 693 struct xtables_rule_match **i; 694 struct xtables_rule_match *newentry; 695 696 newentry = xtables_malloc(sizeof(struct xtables_rule_match)); 697 698 for (i = matches; *i; i = &(*i)->next) { 699 if (extension_cmp(name, (*i)->match->name, 700 (*i)->match->family)) 701 (*i)->completed = true; 702 } 703 newentry->match = ptr; 704 newentry->completed = false; 705 newentry->next = NULL; 706 *i = newentry; 707 } 708 709 return ptr; 710 } 711 712 struct xtables_target * 713 xtables_find_target(const char *name, enum xtables_tryload tryload) 714 { 715 struct xtables_target **dptr; 716 struct xtables_target *ptr; 717 718 /* Standard target? */ 719 if (strcmp(name, "") == 0 720 || strcmp(name, XTC_LABEL_ACCEPT) == 0 721 || strcmp(name, XTC_LABEL_DROP) == 0 722 || strcmp(name, XTC_LABEL_QUEUE) == 0 723 || strcmp(name, XTC_LABEL_RETURN) == 0) 724 name = "standard"; 725 726 /* Trigger delayed initialization */ 727 for (dptr = &xtables_pending_targets; *dptr; ) { 728 if (extension_cmp(name, (*dptr)->name, (*dptr)->family)) { 729 ptr = *dptr; 730 *dptr = (*dptr)->next; 731 ptr->next = NULL; 732 xtables_fully_register_pending_target(ptr); 733 } else { 734 dptr = &((*dptr)->next); 735 } 736 } 737 738 for (ptr = xtables_targets; ptr; ptr = ptr->next) { 739 if (extension_cmp(name, ptr->name, ptr->family)) 740 break; 741 } 742 743 #ifndef NO_SHARED_LIBS 744 if (!ptr && tryload != XTF_DONT_LOAD && tryload != XTF_DURING_LOAD) { 745 ptr = load_extension(xtables_libdir, afinfo->libprefix, 746 name, true); 747 748 if (ptr == NULL && tryload == XTF_LOAD_MUST_SUCCEED) 749 xt_params->exit_err(PARAMETER_PROBLEM, 750 "Couldn't load target `%s':%s\n", 751 name, strerror(errno)); 752 } 753 #else 754 if (ptr && !ptr->loaded) { 755 if (tryload != XTF_DONT_LOAD) 756 ptr->loaded = 1; 757 else 758 ptr = NULL; 759 } 760 if (ptr == NULL && tryload == XTF_LOAD_MUST_SUCCEED) { 761 xt_params->exit_err(PARAMETER_PROBLEM, 762 "Couldn't find target `%s'\n", name); 763 } 764 #endif 765 766 if (ptr) 767 ptr->used = 1; 768 769 return ptr; 770 } 771 772 int xtables_compatible_revision(const char *name, uint8_t revision, int opt) 773 { 774 struct xt_get_revision rev; 775 socklen_t s = sizeof(rev); 776 int max_rev, sockfd; 777 778 sockfd = socket(afinfo->family, SOCK_RAW, IPPROTO_RAW); 779 if (sockfd < 0) { 780 if (errno == EPERM) { 781 /* revision 0 is always supported. */ 782 if (revision != 0) 783 fprintf(stderr, "%s: Could not determine whether " 784 "revision %u is supported, " 785 "assuming it is.\n", 786 name, revision); 787 return 1; 788 } 789 fprintf(stderr, "Could not open socket to kernel: %s\n", 790 strerror(errno)); 791 exit(1); 792 } 793 794 if (fcntl(sockfd, F_SETFD, FD_CLOEXEC) == -1) { 795 fprintf(stderr, "Could not set close on exec: %s\n", 796 strerror(errno)); 797 exit(1); 798 } 799 800 xtables_load_ko(xtables_modprobe_program, true); 801 802 strcpy(rev.name, name); 803 rev.revision = revision; 804 805 max_rev = getsockopt(sockfd, afinfo->ipproto, opt, &rev, &s); 806 if (max_rev < 0) { 807 /* Definitely don't support this? */ 808 if (errno == ENOENT || errno == EPROTONOSUPPORT) { 809 close(sockfd); 810 return 0; 811 } else if (errno == ENOPROTOOPT) { 812 close(sockfd); 813 /* Assume only revision 0 support (old kernel) */ 814 return (revision == 0); 815 } else { 816 fprintf(stderr, "getsockopt failed strangely: %s\n", 817 strerror(errno)); 818 exit(1); 819 } 820 } 821 close(sockfd); 822 return 1; 823 } 824 825 826 static int compatible_match_revision(const char *name, uint8_t revision) 827 { 828 return xt_params->compat_rev(name, revision, afinfo->so_rev_match); 829 } 830 831 static int compatible_target_revision(const char *name, uint8_t revision) 832 { 833 return xt_params->compat_rev(name, revision, afinfo->so_rev_target); 834 } 835 836 static void xtables_check_options(const char *name, const struct option *opt) 837 { 838 for (; opt->name != NULL; ++opt) 839 if (opt->val < 0 || opt->val >= XT_OPTION_OFFSET_SCALE) { 840 fprintf(stderr, "%s: Extension %s uses invalid " 841 "option value %d\n",xt_params->program_name, 842 name, opt->val); 843 exit(1); 844 } 845 } 846 847 void xtables_register_match(struct xtables_match *me) 848 { 849 if (me->version == NULL) { 850 fprintf(stderr, "%s: match %s<%u> is missing a version\n", 851 xt_params->program_name, me->name, me->revision); 852 exit(1); 853 } 854 if (strcmp(me->version, XTABLES_VERSION) != 0) { 855 fprintf(stderr, "%s: match \"%s\" has version \"%s\", " 856 "but \"%s\" is required.\n", 857 xt_params->program_name, me->name, 858 me->version, XTABLES_VERSION); 859 exit(1); 860 } 861 862 if (strlen(me->name) >= XT_EXTENSION_MAXNAMELEN) { 863 fprintf(stderr, "%s: match `%s' has invalid name\n", 864 xt_params->program_name, me->name); 865 exit(1); 866 } 867 868 if (me->family >= NPROTO) { 869 fprintf(stderr, 870 "%s: BUG: match %s has invalid protocol family\n", 871 xt_params->program_name, me->name); 872 exit(1); 873 } 874 875 if (me->x6_options != NULL) 876 xtables_option_metavalidate(me->name, me->x6_options); 877 if (me->extra_opts != NULL) 878 xtables_check_options(me->name, me->extra_opts); 879 880 /* ignore not interested match */ 881 if (me->family != afinfo->family && me->family != AF_UNSPEC) 882 return; 883 884 /* place on linked list of matches pending full registration */ 885 me->next = xtables_pending_matches; 886 xtables_pending_matches = me; 887 } 888 889 /** 890 * Compare two actions for their preference 891 * @a: one action 892 * @b: another 893 * 894 * Like strcmp, returns a negative number if @a is less preferred than @b, 895 * positive number if @a is more preferred than @b, or zero if equally 896 * preferred. 897 */ 898 static int 899 xtables_mt_prefer(bool a_alias, unsigned int a_rev, unsigned int a_fam, 900 bool b_alias, unsigned int b_rev, unsigned int b_fam) 901 { 902 /* 903 * Alias ranks higher than no alias. 904 * (We want the new action to be used whenever possible.) 905 */ 906 if (!a_alias && b_alias) 907 return -1; 908 if (a_alias && !b_alias) 909 return 1; 910 911 /* Higher revision ranks higher. */ 912 if (a_rev < b_rev) 913 return -1; 914 if (a_rev > b_rev) 915 return 1; 916 917 /* NFPROTO_<specific> ranks higher than NFPROTO_UNSPEC. */ 918 if (a_fam == NFPROTO_UNSPEC && b_fam != NFPROTO_UNSPEC) 919 return -1; 920 if (a_fam != NFPROTO_UNSPEC && b_fam == NFPROTO_UNSPEC) 921 return 1; 922 923 /* Must be the same thing. */ 924 return 0; 925 } 926 927 static int xtables_match_prefer(const struct xtables_match *a, 928 const struct xtables_match *b) 929 { 930 return xtables_mt_prefer(a->real_name != NULL, 931 a->revision, a->family, 932 b->real_name != NULL, 933 b->revision, b->family); 934 } 935 936 static int xtables_target_prefer(const struct xtables_target *a, 937 const struct xtables_target *b) 938 { 939 /* 940 * Note that if x->real_name==NULL, it will be set to x->name in 941 * xtables_register_*; the direct pointer comparison here is therefore 942 * legitimate to detect an alias. 943 */ 944 return xtables_mt_prefer(a->real_name != NULL, 945 a->revision, a->family, 946 b->real_name != NULL, 947 b->revision, b->family); 948 } 949 950 static void xtables_fully_register_pending_match(struct xtables_match *me) 951 { 952 struct xtables_match **i, *old; 953 const char *rn; 954 int compare; 955 956 old = xtables_find_match(me->name, XTF_DURING_LOAD, NULL); 957 if (old) { 958 compare = xtables_match_prefer(old, me); 959 if (compare == 0) { 960 fprintf(stderr, 961 "%s: match `%s' already registered.\n", 962 xt_params->program_name, me->name); 963 exit(1); 964 } 965 966 /* Now we have two (or more) options, check compatibility. */ 967 rn = (old->real_name != NULL) ? old->real_name : old->name; 968 if (compare > 0 && 969 compatible_match_revision(rn, old->revision)) 970 return; 971 972 /* See if new match can be used. */ 973 rn = (me->real_name != NULL) ? me->real_name : me->name; 974 if (!compatible_match_revision(rn, me->revision)) 975 return; 976 977 /* Delete old one. */ 978 for (i = &xtables_matches; *i!=old; i = &(*i)->next); 979 *i = old->next; 980 } 981 982 if (me->size != XT_ALIGN(me->size)) { 983 fprintf(stderr, "%s: match `%s' has invalid size %u.\n", 984 xt_params->program_name, me->name, 985 (unsigned int)me->size); 986 exit(1); 987 } 988 989 /* Append to list. */ 990 for (i = &xtables_matches; *i; i = &(*i)->next); 991 me->next = NULL; 992 *i = me; 993 994 me->m = NULL; 995 me->mflags = 0; 996 } 997 998 void xtables_register_matches(struct xtables_match *match, unsigned int n) 999 { 1000 do { 1001 xtables_register_match(&match[--n]); 1002 } while (n > 0); 1003 } 1004 1005 void xtables_register_target(struct xtables_target *me) 1006 { 1007 if (me->version == NULL) { 1008 fprintf(stderr, "%s: target %s<%u> is missing a version\n", 1009 xt_params->program_name, me->name, me->revision); 1010 exit(1); 1011 } 1012 if (strcmp(me->version, XTABLES_VERSION) != 0) { 1013 fprintf(stderr, "%s: target \"%s\" has version \"%s\", " 1014 "but \"%s\" is required.\n", 1015 xt_params->program_name, me->name, 1016 me->version, XTABLES_VERSION); 1017 exit(1); 1018 } 1019 1020 if (strlen(me->name) >= XT_EXTENSION_MAXNAMELEN) { 1021 fprintf(stderr, "%s: target `%s' has invalid name\n", 1022 xt_params->program_name, me->name); 1023 exit(1); 1024 } 1025 1026 if (me->family >= NPROTO) { 1027 fprintf(stderr, 1028 "%s: BUG: target %s has invalid protocol family\n", 1029 xt_params->program_name, me->name); 1030 exit(1); 1031 } 1032 1033 if (me->x6_options != NULL) 1034 xtables_option_metavalidate(me->name, me->x6_options); 1035 if (me->extra_opts != NULL) 1036 xtables_check_options(me->name, me->extra_opts); 1037 1038 /* ignore not interested target */ 1039 if (me->family != afinfo->family && me->family != AF_UNSPEC) 1040 return; 1041 1042 /* place on linked list of targets pending full registration */ 1043 me->next = xtables_pending_targets; 1044 xtables_pending_targets = me; 1045 } 1046 1047 static void xtables_fully_register_pending_target(struct xtables_target *me) 1048 { 1049 struct xtables_target *old; 1050 const char *rn; 1051 int compare; 1052 1053 old = xtables_find_target(me->name, XTF_DURING_LOAD); 1054 if (old) { 1055 struct xtables_target **i; 1056 1057 compare = xtables_target_prefer(old, me); 1058 if (compare == 0) { 1059 fprintf(stderr, 1060 "%s: target `%s' already registered.\n", 1061 xt_params->program_name, me->name); 1062 exit(1); 1063 } 1064 1065 /* Now we have two (or more) options, check compatibility. */ 1066 rn = (old->real_name != NULL) ? old->real_name : old->name; 1067 if (compare > 0 && 1068 compatible_target_revision(rn, old->revision)) 1069 return; 1070 1071 /* See if new target can be used. */ 1072 rn = (me->real_name != NULL) ? me->real_name : me->name; 1073 if (!compatible_target_revision(rn, me->revision)) 1074 return; 1075 1076 /* Delete old one. */ 1077 for (i = &xtables_targets; *i!=old; i = &(*i)->next); 1078 *i = old->next; 1079 } 1080 1081 if (me->size != XT_ALIGN(me->size)) { 1082 fprintf(stderr, "%s: target `%s' has invalid size %u.\n", 1083 xt_params->program_name, me->name, 1084 (unsigned int)me->size); 1085 exit(1); 1086 } 1087 1088 /* Prepend to list. */ 1089 me->next = xtables_targets; 1090 xtables_targets = me; 1091 me->t = NULL; 1092 me->tflags = 0; 1093 } 1094 1095 void xtables_register_targets(struct xtables_target *target, unsigned int n) 1096 { 1097 do { 1098 xtables_register_target(&target[--n]); 1099 } while (n > 0); 1100 } 1101 1102 /* receives a list of xtables_rule_match, release them */ 1103 void xtables_rule_matches_free(struct xtables_rule_match **matches) 1104 { 1105 struct xtables_rule_match *matchp, *tmp; 1106 1107 for (matchp = *matches; matchp;) { 1108 tmp = matchp->next; 1109 if (matchp->match->m) { 1110 free(matchp->match->m); 1111 matchp->match->m = NULL; 1112 } 1113 if (matchp->match == matchp->match->next) { 1114 free(matchp->match); 1115 matchp->match = NULL; 1116 } 1117 free(matchp); 1118 matchp = tmp; 1119 } 1120 1121 *matches = NULL; 1122 } 1123 1124 /** 1125 * xtables_param_act - act on condition 1126 * @status: a constant from enum xtables_exittype 1127 * 1128 * %XTF_ONLY_ONCE: print error message that option may only be used once. 1129 * @p1: module name (e.g. "mark") 1130 * @p2(...): option in conflict (e.g. "--mark") 1131 * @p3(...): condition to match on (see extensions/ for examples) 1132 * 1133 * %XTF_NO_INVERT: option does not support inversion 1134 * @p1: module name 1135 * @p2: option in conflict 1136 * @p3: condition to match on 1137 * 1138 * %XTF_BAD_VALUE: bad value for option 1139 * @p1: module name 1140 * @p2: option with which the problem occurred (e.g. "--mark") 1141 * @p3: string the user passed in (e.g. "99999999999999") 1142 * 1143 * %XTF_ONE_ACTION: two mutually exclusive actions have been specified 1144 * @p1: module name 1145 * 1146 * Displays an error message and exits the program. 1147 */ 1148 void xtables_param_act(unsigned int status, const char *p1, ...) 1149 { 1150 const char *p2, *p3; 1151 va_list args; 1152 bool b; 1153 1154 va_start(args, p1); 1155 1156 switch (status) { 1157 case XTF_ONLY_ONCE: 1158 p2 = va_arg(args, const char *); 1159 b = va_arg(args, unsigned int); 1160 if (!b) { 1161 va_end(args); 1162 return; 1163 } 1164 xt_params->exit_err(PARAMETER_PROBLEM, 1165 "%s: \"%s\" option may only be specified once", 1166 p1, p2); 1167 break; 1168 case XTF_NO_INVERT: 1169 p2 = va_arg(args, const char *); 1170 b = va_arg(args, unsigned int); 1171 if (!b) { 1172 va_end(args); 1173 return; 1174 } 1175 xt_params->exit_err(PARAMETER_PROBLEM, 1176 "%s: \"%s\" option cannot be inverted", p1, p2); 1177 break; 1178 case XTF_BAD_VALUE: 1179 p2 = va_arg(args, const char *); 1180 p3 = va_arg(args, const char *); 1181 xt_params->exit_err(PARAMETER_PROBLEM, 1182 "%s: Bad value for \"%s\" option: \"%s\"", 1183 p1, p2, p3); 1184 break; 1185 case XTF_ONE_ACTION: 1186 b = va_arg(args, unsigned int); 1187 if (!b) { 1188 va_end(args); 1189 return; 1190 } 1191 xt_params->exit_err(PARAMETER_PROBLEM, 1192 "%s: At most one action is possible", p1); 1193 break; 1194 default: 1195 xt_params->exit_err(status, p1, args); 1196 break; 1197 } 1198 1199 va_end(args); 1200 } 1201 1202 const char *xtables_ipaddr_to_numeric(const struct in_addr *addrp) 1203 { 1204 static char buf[20]; 1205 const unsigned char *bytep = (const void *)&addrp->s_addr; 1206 1207 sprintf(buf, "%u.%u.%u.%u", bytep[0], bytep[1], bytep[2], bytep[3]); 1208 return buf; 1209 } 1210 1211 static const char *ipaddr_to_host(const struct in_addr *addr) 1212 { 1213 static char hostname[NI_MAXHOST]; 1214 struct sockaddr_in saddr = { 1215 .sin_family = AF_INET, 1216 .sin_addr = *addr, 1217 }; 1218 int err; 1219 1220 1221 err = getnameinfo((const void *)&saddr, sizeof(struct sockaddr_in), 1222 hostname, sizeof(hostname) - 1, NULL, 0, 0); 1223 if (err != 0) 1224 return NULL; 1225 1226 return hostname; 1227 } 1228 1229 static const char *ipaddr_to_network(const struct in_addr *addr) 1230 { 1231 struct netent *net; 1232 1233 if ((net = getnetbyaddr(ntohl(addr->s_addr), AF_INET)) != NULL) 1234 return net->n_name; 1235 1236 return NULL; 1237 } 1238 1239 const char *xtables_ipaddr_to_anyname(const struct in_addr *addr) 1240 { 1241 const char *name; 1242 1243 if ((name = ipaddr_to_host(addr)) != NULL || 1244 (name = ipaddr_to_network(addr)) != NULL) 1245 return name; 1246 1247 return xtables_ipaddr_to_numeric(addr); 1248 } 1249 1250 int xtables_ipmask_to_cidr(const struct in_addr *mask) 1251 { 1252 uint32_t maskaddr, bits; 1253 int i; 1254 1255 maskaddr = ntohl(mask->s_addr); 1256 /* shortcut for /32 networks */ 1257 if (maskaddr == 0xFFFFFFFFL) 1258 return 32; 1259 1260 i = 32; 1261 bits = 0xFFFFFFFEL; 1262 while (--i >= 0 && maskaddr != bits) 1263 bits <<= 1; 1264 if (i >= 0) 1265 return i; 1266 1267 /* this mask cannot be converted to CIDR notation */ 1268 return -1; 1269 } 1270 1271 const char *xtables_ipmask_to_numeric(const struct in_addr *mask) 1272 { 1273 static char buf[20]; 1274 uint32_t cidr; 1275 1276 cidr = xtables_ipmask_to_cidr(mask); 1277 if (cidr == (unsigned int)-1) { 1278 /* mask was not a decent combination of 1's and 0's */ 1279 sprintf(buf, "/%s", xtables_ipaddr_to_numeric(mask)); 1280 return buf; 1281 } else if (cidr == 32) { 1282 /* we don't want to see "/32" */ 1283 return ""; 1284 } 1285 1286 sprintf(buf, "/%d", cidr); 1287 return buf; 1288 } 1289 1290 static struct in_addr *__numeric_to_ipaddr(const char *dotted, bool is_mask) 1291 { 1292 static struct in_addr addr; 1293 unsigned char *addrp; 1294 unsigned int onebyte; 1295 char buf[20], *p, *q; 1296 int i; 1297 1298 /* copy dotted string, because we need to modify it */ 1299 strncpy(buf, dotted, sizeof(buf) - 1); 1300 buf[sizeof(buf) - 1] = '\0'; 1301 addrp = (void *)&addr.s_addr; 1302 1303 p = buf; 1304 for (i = 0; i < 3; ++i) { 1305 if ((q = strchr(p, '.')) == NULL) { 1306 if (is_mask) 1307 return NULL; 1308 1309 /* autocomplete, this is a network address */ 1310 if (!xtables_strtoui(p, NULL, &onebyte, 0, UINT8_MAX)) 1311 return NULL; 1312 1313 addrp[i] = onebyte; 1314 while (i < 3) 1315 addrp[++i] = 0; 1316 1317 return &addr; 1318 } 1319 1320 *q = '\0'; 1321 if (!xtables_strtoui(p, NULL, &onebyte, 0, UINT8_MAX)) 1322 return NULL; 1323 1324 addrp[i] = onebyte; 1325 p = q + 1; 1326 } 1327 1328 /* we have checked 3 bytes, now we check the last one */ 1329 if (!xtables_strtoui(p, NULL, &onebyte, 0, UINT8_MAX)) 1330 return NULL; 1331 1332 addrp[3] = onebyte; 1333 return &addr; 1334 } 1335 1336 struct in_addr *xtables_numeric_to_ipaddr(const char *dotted) 1337 { 1338 return __numeric_to_ipaddr(dotted, false); 1339 } 1340 1341 struct in_addr *xtables_numeric_to_ipmask(const char *dotted) 1342 { 1343 return __numeric_to_ipaddr(dotted, true); 1344 } 1345 1346 static struct in_addr *network_to_ipaddr(const char *name) 1347 { 1348 static struct in_addr addr; 1349 struct netent *net; 1350 1351 if ((net = getnetbyname(name)) != NULL) { 1352 if (net->n_addrtype != AF_INET) 1353 return NULL; 1354 addr.s_addr = htonl(net->n_net); 1355 return &addr; 1356 } 1357 1358 return NULL; 1359 } 1360 1361 static struct in_addr *host_to_ipaddr(const char *name, unsigned int *naddr) 1362 { 1363 struct in_addr *addr; 1364 struct addrinfo hints; 1365 struct addrinfo *res, *p; 1366 int err; 1367 unsigned int i; 1368 1369 memset(&hints, 0, sizeof(hints)); 1370 hints.ai_flags = AI_CANONNAME; 1371 hints.ai_family = AF_INET; 1372 hints.ai_socktype = SOCK_RAW; 1373 1374 *naddr = 0; 1375 if ((err = getaddrinfo(name, NULL, &hints, &res)) != 0) { 1376 return NULL; 1377 } else { 1378 for (p = res; p != NULL; p = p->ai_next) 1379 ++*naddr; 1380 addr = xtables_calloc(*naddr, sizeof(struct in_addr)); 1381 for (i = 0, p = res; p != NULL; p = p->ai_next) 1382 memcpy(&addr[i++], 1383 &((const struct sockaddr_in *)p->ai_addr)->sin_addr, 1384 sizeof(struct in_addr)); 1385 freeaddrinfo(res); 1386 return addr; 1387 } 1388 1389 return NULL; 1390 } 1391 1392 static struct in_addr * 1393 ipparse_hostnetwork(const char *name, unsigned int *naddrs) 1394 { 1395 struct in_addr *addrptmp, *addrp; 1396 1397 if ((addrptmp = xtables_numeric_to_ipaddr(name)) != NULL || 1398 (addrptmp = network_to_ipaddr(name)) != NULL) { 1399 addrp = xtables_malloc(sizeof(struct in_addr)); 1400 memcpy(addrp, addrptmp, sizeof(*addrp)); 1401 *naddrs = 1; 1402 return addrp; 1403 } 1404 if ((addrptmp = host_to_ipaddr(name, naddrs)) != NULL) 1405 return addrptmp; 1406 1407 xt_params->exit_err(PARAMETER_PROBLEM, "host/network `%s' not found", name); 1408 } 1409 1410 static struct in_addr *parse_ipmask(const char *mask) 1411 { 1412 static struct in_addr maskaddr; 1413 struct in_addr *addrp; 1414 unsigned int bits; 1415 1416 if (mask == NULL) { 1417 /* no mask at all defaults to 32 bits */ 1418 maskaddr.s_addr = 0xFFFFFFFF; 1419 return &maskaddr; 1420 } 1421 if ((addrp = xtables_numeric_to_ipmask(mask)) != NULL) 1422 /* dotted_to_addr already returns a network byte order addr */ 1423 return addrp; 1424 if (!xtables_strtoui(mask, NULL, &bits, 0, 32)) 1425 xt_params->exit_err(PARAMETER_PROBLEM, 1426 "invalid mask `%s' specified", mask); 1427 if (bits != 0) { 1428 maskaddr.s_addr = htonl(0xFFFFFFFF << (32 - bits)); 1429 return &maskaddr; 1430 } 1431 1432 maskaddr.s_addr = 0U; 1433 return &maskaddr; 1434 } 1435 1436 void xtables_ipparse_multiple(const char *name, struct in_addr **addrpp, 1437 struct in_addr **maskpp, unsigned int *naddrs) 1438 { 1439 struct in_addr *addrp; 1440 char buf[256], *p, *next; 1441 unsigned int len, i, j, n, count = 1; 1442 const char *loop = name; 1443 1444 while ((loop = strchr(loop, ',')) != NULL) { 1445 ++count; 1446 ++loop; /* skip ',' */ 1447 } 1448 1449 *addrpp = xtables_malloc(sizeof(struct in_addr) * count); 1450 *maskpp = xtables_malloc(sizeof(struct in_addr) * count); 1451 1452 loop = name; 1453 1454 for (i = 0; i < count; ++i) { 1455 while (isspace(*loop)) 1456 ++loop; 1457 next = strchr(loop, ','); 1458 if (next != NULL) 1459 len = next - loop; 1460 else 1461 len = strlen(loop); 1462 if (len > sizeof(buf) - 1) 1463 xt_params->exit_err(PARAMETER_PROBLEM, 1464 "Hostname too long"); 1465 1466 strncpy(buf, loop, len); 1467 buf[len] = '\0'; 1468 if ((p = strrchr(buf, '/')) != NULL) { 1469 *p = '\0'; 1470 addrp = parse_ipmask(p + 1); 1471 } else { 1472 addrp = parse_ipmask(NULL); 1473 } 1474 memcpy(*maskpp + i, addrp, sizeof(*addrp)); 1475 1476 /* if a null mask is given, the name is ignored, like in "any/0" */ 1477 if ((*maskpp + i)->s_addr == 0) 1478 /* 1479 * A bit pointless to process multiple addresses 1480 * in this case... 1481 */ 1482 strcpy(buf, "0.0.0.0"); 1483 1484 addrp = ipparse_hostnetwork(buf, &n); 1485 if (n > 1) { 1486 count += n - 1; 1487 *addrpp = xtables_realloc(*addrpp, 1488 sizeof(struct in_addr) * count); 1489 *maskpp = xtables_realloc(*maskpp, 1490 sizeof(struct in_addr) * count); 1491 for (j = 0; j < n; ++j) 1492 /* for each new addr */ 1493 memcpy(*addrpp + i + j, addrp + j, 1494 sizeof(*addrp)); 1495 for (j = 1; j < n; ++j) 1496 /* for each new mask */ 1497 memcpy(*maskpp + i + j, *maskpp + i, 1498 sizeof(*addrp)); 1499 i += n - 1; 1500 } else { 1501 memcpy(*addrpp + i, addrp, sizeof(*addrp)); 1502 } 1503 /* free what ipparse_hostnetwork had allocated: */ 1504 free(addrp); 1505 if (next == NULL) 1506 break; 1507 loop = next + 1; 1508 } 1509 *naddrs = count; 1510 for (i = 0; i < count; ++i) 1511 (*addrpp+i)->s_addr &= (*maskpp+i)->s_addr; 1512 } 1513 1514 1515 /** 1516 * xtables_ipparse_any - transform arbitrary name to in_addr 1517 * 1518 * Possible inputs (pseudo regex): 1519 * m{^($hostname|$networkname|$ipaddr)(/$mask)?} 1520 * "1.2.3.4/5", "1.2.3.4", "hostname", "networkname" 1521 */ 1522 void xtables_ipparse_any(const char *name, struct in_addr **addrpp, 1523 struct in_addr *maskp, unsigned int *naddrs) 1524 { 1525 unsigned int i, j, k, n; 1526 struct in_addr *addrp; 1527 char buf[256], *p; 1528 1529 strncpy(buf, name, sizeof(buf) - 1); 1530 buf[sizeof(buf) - 1] = '\0'; 1531 if ((p = strrchr(buf, '/')) != NULL) { 1532 *p = '\0'; 1533 addrp = parse_ipmask(p + 1); 1534 } else { 1535 addrp = parse_ipmask(NULL); 1536 } 1537 memcpy(maskp, addrp, sizeof(*maskp)); 1538 1539 /* if a null mask is given, the name is ignored, like in "any/0" */ 1540 if (maskp->s_addr == 0U) 1541 strcpy(buf, "0.0.0.0"); 1542 1543 addrp = *addrpp = ipparse_hostnetwork(buf, naddrs); 1544 n = *naddrs; 1545 for (i = 0, j = 0; i < n; ++i) { 1546 addrp[j++].s_addr &= maskp->s_addr; 1547 for (k = 0; k < j - 1; ++k) 1548 if (addrp[k].s_addr == addrp[j-1].s_addr) { 1549 /* 1550 * Nuke the dup by copying an address from the 1551 * tail here, and check the current position 1552 * again (--j). 1553 */ 1554 memcpy(&addrp[--j], &addrp[--*naddrs], 1555 sizeof(struct in_addr)); 1556 break; 1557 } 1558 } 1559 } 1560 1561 const char *xtables_ip6addr_to_numeric(const struct in6_addr *addrp) 1562 { 1563 /* 0000:0000:0000:0000:0000:0000:000.000.000.000 1564 * 0000:0000:0000:0000:0000:0000:0000:0000 */ 1565 static char buf[50+1]; 1566 return inet_ntop(AF_INET6, addrp, buf, sizeof(buf)); 1567 } 1568 1569 static const char *ip6addr_to_host(const struct in6_addr *addr) 1570 { 1571 static char hostname[NI_MAXHOST]; 1572 struct sockaddr_in6 saddr; 1573 int err; 1574 1575 memset(&saddr, 0, sizeof(struct sockaddr_in6)); 1576 memcpy(&saddr.sin6_addr, addr, sizeof(*addr)); 1577 saddr.sin6_family = AF_INET6; 1578 1579 err = getnameinfo((const void *)&saddr, sizeof(struct sockaddr_in6), 1580 hostname, sizeof(hostname) - 1, NULL, 0, 0); 1581 if (err != 0) 1582 return NULL; 1583 1584 return hostname; 1585 } 1586 1587 const char *xtables_ip6addr_to_anyname(const struct in6_addr *addr) 1588 { 1589 const char *name; 1590 1591 if ((name = ip6addr_to_host(addr)) != NULL) 1592 return name; 1593 1594 return xtables_ip6addr_to_numeric(addr); 1595 } 1596 1597 int xtables_ip6mask_to_cidr(const struct in6_addr *k) 1598 { 1599 unsigned int bits = 0; 1600 uint32_t a, b, c, d; 1601 1602 a = ntohl(k->s6_addr32[0]); 1603 b = ntohl(k->s6_addr32[1]); 1604 c = ntohl(k->s6_addr32[2]); 1605 d = ntohl(k->s6_addr32[3]); 1606 while (a & 0x80000000U) { 1607 ++bits; 1608 a <<= 1; 1609 a |= (b >> 31) & 1; 1610 b <<= 1; 1611 b |= (c >> 31) & 1; 1612 c <<= 1; 1613 c |= (d >> 31) & 1; 1614 d <<= 1; 1615 } 1616 if (a != 0 || b != 0 || c != 0 || d != 0) 1617 return -1; 1618 return bits; 1619 } 1620 1621 const char *xtables_ip6mask_to_numeric(const struct in6_addr *addrp) 1622 { 1623 static char buf[50+2]; 1624 int l = xtables_ip6mask_to_cidr(addrp); 1625 1626 if (l == -1) { 1627 strcpy(buf, "/"); 1628 strcat(buf, xtables_ip6addr_to_numeric(addrp)); 1629 return buf; 1630 } 1631 /* we don't want to see "/128" */ 1632 if (l == 128) 1633 return ""; 1634 else 1635 sprintf(buf, "/%d", l); 1636 return buf; 1637 } 1638 1639 struct in6_addr *xtables_numeric_to_ip6addr(const char *num) 1640 { 1641 static struct in6_addr ap; 1642 int err; 1643 1644 if ((err = inet_pton(AF_INET6, num, &ap)) == 1) 1645 return ≈ 1646 1647 return NULL; 1648 } 1649 1650 static struct in6_addr * 1651 host_to_ip6addr(const char *name, unsigned int *naddr) 1652 { 1653 struct in6_addr *addr; 1654 struct addrinfo hints; 1655 struct addrinfo *res, *p; 1656 int err; 1657 unsigned int i; 1658 1659 memset(&hints, 0, sizeof(hints)); 1660 hints.ai_flags = AI_CANONNAME; 1661 hints.ai_family = AF_INET6; 1662 hints.ai_socktype = SOCK_RAW; 1663 1664 *naddr = 0; 1665 if ((err = getaddrinfo(name, NULL, &hints, &res)) != 0) { 1666 return NULL; 1667 } else { 1668 /* Find length of address chain */ 1669 for (p = res; p != NULL; p = p->ai_next) 1670 ++*naddr; 1671 /* Copy each element of the address chain */ 1672 addr = xtables_calloc(*naddr, sizeof(struct in6_addr)); 1673 for (i = 0, p = res; p != NULL; p = p->ai_next) 1674 memcpy(&addr[i++], 1675 &((const struct sockaddr_in6 *)p->ai_addr)->sin6_addr, 1676 sizeof(struct in6_addr)); 1677 freeaddrinfo(res); 1678 return addr; 1679 } 1680 1681 return NULL; 1682 } 1683 1684 static struct in6_addr *network_to_ip6addr(const char *name) 1685 { 1686 /* abort();*/ 1687 /* TODO: not implemented yet, but the exception breaks the 1688 * name resolvation */ 1689 return NULL; 1690 } 1691 1692 static struct in6_addr * 1693 ip6parse_hostnetwork(const char *name, unsigned int *naddrs) 1694 { 1695 struct in6_addr *addrp, *addrptmp; 1696 1697 if ((addrptmp = xtables_numeric_to_ip6addr(name)) != NULL || 1698 (addrptmp = network_to_ip6addr(name)) != NULL) { 1699 addrp = xtables_malloc(sizeof(struct in6_addr)); 1700 memcpy(addrp, addrptmp, sizeof(*addrp)); 1701 *naddrs = 1; 1702 return addrp; 1703 } 1704 if ((addrp = host_to_ip6addr(name, naddrs)) != NULL) 1705 return addrp; 1706 1707 xt_params->exit_err(PARAMETER_PROBLEM, "host/network `%s' not found", name); 1708 } 1709 1710 static struct in6_addr *parse_ip6mask(char *mask) 1711 { 1712 static struct in6_addr maskaddr; 1713 struct in6_addr *addrp; 1714 unsigned int bits; 1715 1716 if (mask == NULL) { 1717 /* no mask at all defaults to 128 bits */ 1718 memset(&maskaddr, 0xff, sizeof maskaddr); 1719 return &maskaddr; 1720 } 1721 if ((addrp = xtables_numeric_to_ip6addr(mask)) != NULL) 1722 return addrp; 1723 if (!xtables_strtoui(mask, NULL, &bits, 0, 128)) 1724 xt_params->exit_err(PARAMETER_PROBLEM, 1725 "invalid mask `%s' specified", mask); 1726 if (bits != 0) { 1727 char *p = (void *)&maskaddr; 1728 memset(p, 0xff, bits / 8); 1729 memset(p + ((bits + 7) / 8), 0, (128 - bits) / 8); 1730 if (bits < 128) 1731 p[bits/8] = 0xff << (8 - (bits & 7)); 1732 return &maskaddr; 1733 } 1734 1735 memset(&maskaddr, 0, sizeof(maskaddr)); 1736 return &maskaddr; 1737 } 1738 1739 void 1740 xtables_ip6parse_multiple(const char *name, struct in6_addr **addrpp, 1741 struct in6_addr **maskpp, unsigned int *naddrs) 1742 { 1743 static const struct in6_addr zero_addr; 1744 struct in6_addr *addrp; 1745 char buf[256], *p, *next; 1746 unsigned int len, i, j, n, count = 1; 1747 const char *loop = name; 1748 1749 while ((loop = strchr(loop, ',')) != NULL) { 1750 ++count; 1751 ++loop; /* skip ',' */ 1752 } 1753 1754 *addrpp = xtables_malloc(sizeof(struct in6_addr) * count); 1755 *maskpp = xtables_malloc(sizeof(struct in6_addr) * count); 1756 1757 loop = name; 1758 1759 for (i = 0; i < count /*NB: count can grow*/; ++i) { 1760 while (isspace(*loop)) 1761 ++loop; 1762 next = strchr(loop, ','); 1763 if (next != NULL) 1764 len = next - loop; 1765 else 1766 len = strlen(loop); 1767 if (len > sizeof(buf) - 1) 1768 xt_params->exit_err(PARAMETER_PROBLEM, 1769 "Hostname too long"); 1770 1771 strncpy(buf, loop, len); 1772 buf[len] = '\0'; 1773 if ((p = strrchr(buf, '/')) != NULL) { 1774 *p = '\0'; 1775 addrp = parse_ip6mask(p + 1); 1776 } else { 1777 addrp = parse_ip6mask(NULL); 1778 } 1779 memcpy(*maskpp + i, addrp, sizeof(*addrp)); 1780 1781 /* if a null mask is given, the name is ignored, like in "any/0" */ 1782 if (memcmp(*maskpp + i, &zero_addr, sizeof(zero_addr)) == 0) 1783 strcpy(buf, "::"); 1784 1785 addrp = ip6parse_hostnetwork(buf, &n); 1786 if (n > 1) { 1787 count += n - 1; 1788 *addrpp = xtables_realloc(*addrpp, 1789 sizeof(struct in6_addr) * count); 1790 *maskpp = xtables_realloc(*maskpp, 1791 sizeof(struct in6_addr) * count); 1792 for (j = 0; j < n; ++j) 1793 /* for each new addr */ 1794 memcpy(*addrpp + i + j, addrp + j, 1795 sizeof(*addrp)); 1796 for (j = 1; j < n; ++j) 1797 /* for each new mask */ 1798 memcpy(*maskpp + i + j, *maskpp + i, 1799 sizeof(*addrp)); 1800 i += n - 1; 1801 } else { 1802 memcpy(*addrpp + i, addrp, sizeof(*addrp)); 1803 } 1804 /* free what ip6parse_hostnetwork had allocated: */ 1805 free(addrp); 1806 if (next == NULL) 1807 break; 1808 loop = next + 1; 1809 } 1810 *naddrs = count; 1811 for (i = 0; i < count; ++i) 1812 for (j = 0; j < 4; ++j) 1813 (*addrpp+i)->s6_addr32[j] &= (*maskpp+i)->s6_addr32[j]; 1814 } 1815 1816 void xtables_ip6parse_any(const char *name, struct in6_addr **addrpp, 1817 struct in6_addr *maskp, unsigned int *naddrs) 1818 { 1819 static const struct in6_addr zero_addr; 1820 struct in6_addr *addrp; 1821 unsigned int i, j, k, n; 1822 char buf[256], *p; 1823 1824 strncpy(buf, name, sizeof(buf) - 1); 1825 buf[sizeof(buf)-1] = '\0'; 1826 if ((p = strrchr(buf, '/')) != NULL) { 1827 *p = '\0'; 1828 addrp = parse_ip6mask(p + 1); 1829 } else { 1830 addrp = parse_ip6mask(NULL); 1831 } 1832 memcpy(maskp, addrp, sizeof(*maskp)); 1833 1834 /* if a null mask is given, the name is ignored, like in "any/0" */ 1835 if (memcmp(maskp, &zero_addr, sizeof(zero_addr)) == 0) 1836 strcpy(buf, "::"); 1837 1838 addrp = *addrpp = ip6parse_hostnetwork(buf, naddrs); 1839 n = *naddrs; 1840 for (i = 0, j = 0; i < n; ++i) { 1841 for (k = 0; k < 4; ++k) 1842 addrp[j].s6_addr32[k] &= maskp->s6_addr32[k]; 1843 ++j; 1844 for (k = 0; k < j - 1; ++k) 1845 if (IN6_ARE_ADDR_EQUAL(&addrp[k], &addrp[j - 1])) { 1846 /* 1847 * Nuke the dup by copying an address from the 1848 * tail here, and check the current position 1849 * again (--j). 1850 */ 1851 memcpy(&addrp[--j], &addrp[--*naddrs], 1852 sizeof(struct in_addr)); 1853 break; 1854 } 1855 } 1856 } 1857 1858 void xtables_save_string(const char *value) 1859 { 1860 static const char no_quote_chars[] = "_-0123456789" 1861 "abcdefghijklmnopqrstuvwxyz" 1862 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; 1863 static const char escape_chars[] = "\"\\'"; 1864 size_t length; 1865 const char *p; 1866 1867 length = strspn(value, no_quote_chars); 1868 if (length > 0 && value[length] == 0) { 1869 /* no quoting required */ 1870 putchar(' '); 1871 fputs(value, stdout); 1872 } else { 1873 /* there is at least one dangerous character in the 1874 value, which we have to quote. Write double quotes 1875 around the value and escape special characters with 1876 a backslash */ 1877 printf(" \""); 1878 1879 for (p = strpbrk(value, escape_chars); p != NULL; 1880 p = strpbrk(value, escape_chars)) { 1881 if (p > value) 1882 fwrite(value, 1, p - value, stdout); 1883 putchar('\\'); 1884 putchar(*p); 1885 value = p + 1; 1886 } 1887 1888 /* print the rest and finish the double quoted 1889 string */ 1890 fputs(value, stdout); 1891 putchar('\"'); 1892 } 1893 } 1894 1895 const struct xtables_pprot xtables_chain_protos[] = { 1896 {"tcp", IPPROTO_TCP}, 1897 {"sctp", IPPROTO_SCTP}, 1898 {"udp", IPPROTO_UDP}, 1899 {"udplite", IPPROTO_UDPLITE}, 1900 {"icmp", IPPROTO_ICMP}, 1901 {"icmpv6", IPPROTO_ICMPV6}, 1902 {"ipv6-icmp", IPPROTO_ICMPV6}, 1903 {"esp", IPPROTO_ESP}, 1904 {"ah", IPPROTO_AH}, 1905 {"ipv6-mh", IPPROTO_MH}, 1906 {"mh", IPPROTO_MH}, 1907 {"all", 0}, 1908 {NULL}, 1909 }; 1910 1911 uint16_t 1912 xtables_parse_protocol(const char *s) 1913 { 1914 const struct protoent *pent; 1915 unsigned int proto, i; 1916 1917 if (xtables_strtoui(s, NULL, &proto, 0, UINT8_MAX)) 1918 return proto; 1919 1920 /* first deal with the special case of 'all' to prevent 1921 * people from being able to redefine 'all' in nsswitch 1922 * and/or provoke expensive [not working] ldap/nis/... 1923 * lookups */ 1924 if (strcmp(s, "all") == 0) 1925 return 0; 1926 1927 pent = getprotobyname(s); 1928 if (pent != NULL) 1929 return pent->p_proto; 1930 1931 for (i = 0; i < ARRAY_SIZE(xtables_chain_protos); ++i) { 1932 if (xtables_chain_protos[i].name == NULL) 1933 continue; 1934 if (strcmp(s, xtables_chain_protos[i].name) == 0) 1935 return xtables_chain_protos[i].num; 1936 } 1937 xt_params->exit_err(PARAMETER_PROBLEM, 1938 "unknown protocol \"%s\" specified", s); 1939 return -1; 1940 } 1941 1942 void xtables_print_num(uint64_t number, unsigned int format) 1943 { 1944 if (!(format & FMT_KILOMEGAGIGA)) { 1945 printf(FMT("%8llu ","%llu "), (unsigned long long)number); 1946 return; 1947 } 1948 if (number <= 99999) { 1949 printf(FMT("%5llu ","%llu "), (unsigned long long)number); 1950 return; 1951 } 1952 number = (number + 500) / 1000; 1953 if (number <= 9999) { 1954 printf(FMT("%4lluK ","%lluK "), (unsigned long long)number); 1955 return; 1956 } 1957 number = (number + 500) / 1000; 1958 if (number <= 9999) { 1959 printf(FMT("%4lluM ","%lluM "), (unsigned long long)number); 1960 return; 1961 } 1962 number = (number + 500) / 1000; 1963 if (number <= 9999) { 1964 printf(FMT("%4lluG ","%lluG "), (unsigned long long)number); 1965 return; 1966 } 1967 number = (number + 500) / 1000; 1968 printf(FMT("%4lluT ","%lluT "), (unsigned long long)number); 1969 } 1970 1971 int kernel_version; 1972 1973 void get_kernel_version(void) 1974 { 1975 static struct utsname uts; 1976 int x = 0, y = 0, z = 0; 1977 1978 if (uname(&uts) == -1) { 1979 fprintf(stderr, "Unable to retrieve kernel version.\n"); 1980 xtables_free_opts(1); 1981 exit(1); 1982 } 1983 1984 sscanf(uts.release, "%d.%d.%d", &x, &y, &z); 1985 kernel_version = LINUX_VERSION(x, y, z); 1986 } 1987 1988 #include <linux/netfilter/nf_tables.h> 1989 1990 struct xt_xlate { 1991 struct { 1992 char *data; 1993 int size; 1994 int rem; 1995 int off; 1996 } buf; 1997 char comment[NFT_USERDATA_MAXLEN]; 1998 }; 1999 2000 struct xt_xlate *xt_xlate_alloc(int size) 2001 { 2002 struct xt_xlate *xl; 2003 2004 xl = malloc(sizeof(struct xt_xlate)); 2005 if (xl == NULL) 2006 xtables_error(RESOURCE_PROBLEM, "OOM"); 2007 2008 xl->buf.data = malloc(size); 2009 if (xl->buf.data == NULL) 2010 xtables_error(RESOURCE_PROBLEM, "OOM"); 2011 2012 xl->buf.size = size; 2013 xl->buf.rem = size; 2014 xl->buf.off = 0; 2015 xl->comment[0] = '\0'; 2016 2017 return xl; 2018 } 2019 2020 void xt_xlate_free(struct xt_xlate *xl) 2021 { 2022 free(xl->buf.data); 2023 free(xl); 2024 } 2025 2026 void xt_xlate_add(struct xt_xlate *xl, const char *fmt, ...) 2027 { 2028 va_list ap; 2029 int len; 2030 2031 va_start(ap, fmt); 2032 len = vsnprintf(xl->buf.data + xl->buf.off, xl->buf.rem, fmt, ap); 2033 if (len < 0 || len >= xl->buf.rem) 2034 xtables_error(RESOURCE_PROBLEM, "OOM"); 2035 2036 va_end(ap); 2037 xl->buf.rem -= len; 2038 xl->buf.off += len; 2039 } 2040 2041 void xt_xlate_add_comment(struct xt_xlate *xl, const char *comment) 2042 { 2043 strncpy(xl->comment, comment, NFT_USERDATA_MAXLEN - 1); 2044 xl->comment[NFT_USERDATA_MAXLEN - 1] = '\0'; 2045 } 2046 2047 const char *xt_xlate_get_comment(struct xt_xlate *xl) 2048 { 2049 return xl->comment[0] ? xl->comment : NULL; 2050 } 2051 2052 const char *xt_xlate_get(struct xt_xlate *xl) 2053 { 2054 return xl->buf.data; 2055 } 2056