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