1 /* 2 * ebtables.c, v2.0 July 2002 3 * 4 * Author: Bart De Schuymer 5 * 6 * This code was stongly inspired on the iptables code which is 7 * Copyright (C) 1999 Paul `Rusty' Russell & Michael J. Neuling 8 * 9 * This program is free software; you can redistribute it and/or 10 * modify it under the terms of the GNU General Public License as 11 * published by the Free Software Foundation; either version 2 of the 12 * License, or (at your option) any later version. 13 * 14 * This program is distributed in the hope that it will be useful, but 15 * WITHOUT ANY WARRANTY; without even the implied warranty of 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17 * General Public License for more details. 18 * 19 * You should have received a copy of the GNU General Public License 20 * along with this program; if not, write to the Free Software 21 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 22 */ 23 24 #include <ctype.h> 25 #include <errno.h> 26 #include <getopt.h> 27 #include <string.h> 28 #include <stdio.h> 29 #include <stdlib.h> 30 #include <stdarg.h> 31 #include <inttypes.h> 32 #include <signal.h> 33 #include <net/if.h> 34 #include <netinet/ether.h> 35 #include <iptables.h> 36 #include <xtables.h> 37 38 #include <linux/netfilter_bridge.h> 39 #include <linux/netfilter/nf_tables.h> 40 #include <ebtables/ethernetdb.h> 41 #include <libiptc/libxtc.h> 42 #include "xshared.h" 43 #include "nft.h" 44 #include "nft-bridge.h" 45 46 /* 47 * From include/ebtables_u.h 48 */ 49 #define EXEC_STYLE_PRG 0 50 #define EXEC_STYLE_DAEMON 1 51 52 #define ebt_check_option2(flags, mask) EBT_CHECK_OPTION(flags, mask) 53 54 /* 55 * From useful_functions.c 56 */ 57 58 /* 0: default 59 * 1: the inverse '!' of the option has already been specified */ 60 int ebt_invert = 0; 61 62 unsigned char eb_mac_type_unicast[ETH_ALEN] = {0,0,0,0,0,0}; 63 unsigned char eb_msk_type_unicast[ETH_ALEN] = {1,0,0,0,0,0}; 64 unsigned char eb_mac_type_multicast[ETH_ALEN] = {1,0,0,0,0,0}; 65 unsigned char eb_msk_type_multicast[ETH_ALEN] = {1,0,0,0,0,0}; 66 unsigned char eb_mac_type_broadcast[ETH_ALEN] = {255,255,255,255,255,255}; 67 unsigned char eb_msk_type_broadcast[ETH_ALEN] = {255,255,255,255,255,255}; 68 unsigned char eb_mac_type_bridge_group[ETH_ALEN] = {0x01,0x80,0xc2,0,0,0}; 69 unsigned char eb_msk_type_bridge_group[ETH_ALEN] = {255,255,255,255,255,255}; 70 71 int ebt_get_mac_and_mask(const char *from, unsigned char *to, 72 unsigned char *mask) 73 { 74 char *p; 75 int i; 76 struct ether_addr *addr = NULL; 77 78 if (strcasecmp(from, "Unicast") == 0) { 79 memcpy(to, eb_mac_type_unicast, ETH_ALEN); 80 memcpy(mask, eb_msk_type_unicast, ETH_ALEN); 81 return 0; 82 } 83 if (strcasecmp(from, "Multicast") == 0) { 84 memcpy(to, eb_mac_type_multicast, ETH_ALEN); 85 memcpy(mask, eb_msk_type_multicast, ETH_ALEN); 86 return 0; 87 } 88 if (strcasecmp(from, "Broadcast") == 0) { 89 memcpy(to, eb_mac_type_broadcast, ETH_ALEN); 90 memcpy(mask, eb_msk_type_broadcast, ETH_ALEN); 91 return 0; 92 } 93 if (strcasecmp(from, "BGA") == 0) { 94 memcpy(to, eb_mac_type_bridge_group, ETH_ALEN); 95 memcpy(mask, eb_msk_type_bridge_group, ETH_ALEN); 96 return 0; 97 } 98 if ( (p = strrchr(from, '/')) != NULL) { 99 *p = '\0'; 100 if (!(addr = ether_aton(p + 1))) 101 return -1; 102 memcpy(mask, addr, ETH_ALEN); 103 } else 104 memset(mask, 0xff, ETH_ALEN); 105 if (!(addr = ether_aton(from))) 106 return -1; 107 memcpy(to, addr, ETH_ALEN); 108 for (i = 0; i < ETH_ALEN; i++) 109 to[i] &= mask[i]; 110 return 0; 111 } 112 113 static int ebt_check_inverse2(const char option[], int argc, char **argv) 114 { 115 if (!option) 116 return ebt_invert; 117 if (strcmp(option, "!") == 0) { 118 if (ebt_invert == 1) 119 xtables_error(PARAMETER_PROBLEM, 120 "Double use of '!' not allowed"); 121 if (optind >= argc) 122 optarg = NULL; 123 else 124 optarg = argv[optind]; 125 optind++; 126 ebt_invert = 1; 127 return 1; 128 } 129 return ebt_invert; 130 } 131 132 /* 133 * Glue code to use libxtables 134 */ 135 static int parse_rule_number(const char *rule) 136 { 137 unsigned int rule_nr; 138 139 if (!xtables_strtoui(rule, NULL, &rule_nr, 1, INT_MAX)) 140 xtables_error(PARAMETER_PROBLEM, 141 "Invalid rule number `%s'", rule); 142 143 return rule_nr; 144 } 145 146 static const char * 147 parse_target(const char *targetname) 148 { 149 const char *ptr; 150 151 if (strlen(targetname) < 1) 152 xtables_error(PARAMETER_PROBLEM, 153 "Invalid target name (too short)"); 154 155 if (strlen(targetname)+1 > EBT_CHAIN_MAXNAMELEN) 156 xtables_error(PARAMETER_PROBLEM, 157 "Invalid target '%s' (%d chars max)", 158 targetname, EBT_CHAIN_MAXNAMELEN); 159 160 for (ptr = targetname; *ptr; ptr++) 161 if (isspace(*ptr)) 162 xtables_error(PARAMETER_PROBLEM, 163 "Invalid target name `%s'", targetname); 164 return targetname; 165 } 166 167 static int 168 append_entry(struct nft_handle *h, 169 const char *chain, 170 const char *table, 171 struct ebtables_command_state *cs, 172 int rule_nr, 173 bool verbose, bool append) 174 { 175 int ret = 1; 176 177 if (append) 178 ret = nft_rule_append(h, chain, table, cs, 0, verbose); 179 else 180 ret = nft_rule_insert(h, chain, table, cs, rule_nr, verbose); 181 182 return ret; 183 } 184 185 static int 186 delete_entry(struct nft_handle *h, 187 const char *chain, 188 const char *table, 189 struct ebtables_command_state *cs, 190 int rule_nr, 191 int rule_nr_end, 192 bool verbose) 193 { 194 int ret = 1; 195 196 if (rule_nr == -1) 197 ret = nft_rule_delete(h, chain, table, cs, verbose); 198 else { 199 do { 200 ret = nft_rule_delete_num(h, chain, table, 201 rule_nr, verbose); 202 rule_nr++; 203 } while (rule_nr < rule_nr_end); 204 } 205 206 return ret; 207 } 208 209 static int get_current_chain(const char *chain) 210 { 211 if (strcmp(chain, "PREROUTING") == 0) 212 return NF_BR_PRE_ROUTING; 213 else if (strcmp(chain, "INPUT") == 0) 214 return NF_BR_LOCAL_IN; 215 else if (strcmp(chain, "FORWARD") == 0) 216 return NF_BR_FORWARD; 217 else if (strcmp(chain, "OUTPUT") == 0) 218 return NF_BR_LOCAL_OUT; 219 else if (strcmp(chain, "POSTROUTING") == 0) 220 return NF_BR_POST_ROUTING; 221 222 return -1; 223 } 224 225 /* 226 * The original ebtables parser 227 */ 228 229 /* Checks whether a command has already been specified */ 230 #define OPT_COMMANDS (flags & OPT_COMMAND || flags & OPT_ZERO) 231 232 #define OPT_COMMAND 0x01 233 #define OPT_TABLE 0x02 234 #define OPT_IN 0x04 235 #define OPT_OUT 0x08 236 #define OPT_JUMP 0x10 237 #define OPT_PROTOCOL 0x20 238 #define OPT_SOURCE 0x40 239 #define OPT_DEST 0x80 240 #define OPT_ZERO 0x100 241 #define OPT_LOGICALIN 0x200 242 #define OPT_LOGICALOUT 0x400 243 #define OPT_KERNELDATA 0x800 /* This value is also defined in ebtablesd.c */ 244 #define OPT_COUNT 0x1000 /* This value is also defined in libebtc.c */ 245 #define OPT_CNT_INCR 0x2000 /* This value is also defined in libebtc.c */ 246 #define OPT_CNT_DECR 0x4000 /* This value is also defined in libebtc.c */ 247 248 /* Default command line options. Do not mess around with the already 249 * assigned numbers unless you know what you are doing */ 250 static struct option ebt_original_options[] = 251 { 252 { "append" , required_argument, 0, 'A' }, 253 { "insert" , required_argument, 0, 'I' }, 254 { "delete" , required_argument, 0, 'D' }, 255 { "list" , optional_argument, 0, 'L' }, 256 { "Lc" , no_argument , 0, 4 }, 257 { "Ln" , no_argument , 0, 5 }, 258 { "Lx" , no_argument , 0, 6 }, 259 { "Lmac2" , no_argument , 0, 12 }, 260 { "zero" , optional_argument, 0, 'Z' }, 261 { "flush" , optional_argument, 0, 'F' }, 262 { "policy" , required_argument, 0, 'P' }, 263 { "in-interface" , required_argument, 0, 'i' }, 264 { "in-if" , required_argument, 0, 'i' }, 265 { "logical-in" , required_argument, 0, 2 }, 266 { "logical-out" , required_argument, 0, 3 }, 267 { "out-interface" , required_argument, 0, 'o' }, 268 { "out-if" , required_argument, 0, 'o' }, 269 { "version" , no_argument , 0, 'V' }, 270 { "help" , no_argument , 0, 'h' }, 271 { "jump" , required_argument, 0, 'j' }, 272 { "set-counters" , required_argument, 0, 'c' }, 273 { "change-counters", required_argument, 0, 'C' }, 274 { "proto" , required_argument, 0, 'p' }, 275 { "protocol" , required_argument, 0, 'p' }, 276 { "db" , required_argument, 0, 'b' }, 277 { "source" , required_argument, 0, 's' }, 278 { "src" , required_argument, 0, 's' }, 279 { "destination" , required_argument, 0, 'd' }, 280 { "dst" , required_argument, 0, 'd' }, 281 { "table" , required_argument, 0, 't' }, 282 { "modprobe" , required_argument, 0, 'M' }, 283 { "new-chain" , required_argument, 0, 'N' }, 284 { "rename-chain" , required_argument, 0, 'E' }, 285 { "delete-chain" , optional_argument, 0, 'X' }, 286 { "atomic-init" , no_argument , 0, 7 }, 287 { "atomic-commit" , no_argument , 0, 8 }, 288 { "atomic-file" , required_argument, 0, 9 }, 289 { "atomic-save" , no_argument , 0, 10 }, 290 { "init-table" , no_argument , 0, 11 }, 291 { "concurrent" , no_argument , 0, 13 }, 292 { 0 } 293 }; 294 295 static void __attribute__((__noreturn__,format(printf,2,3))) 296 ebt_print_error(enum xtables_exittype status, const char *format, ...) 297 { 298 va_list l; 299 300 va_start(l, format); 301 vfprintf(stderr, format, l); 302 fprintf(stderr, ".\n"); 303 va_end(l); 304 exit(-1); 305 } 306 307 struct xtables_globals ebtables_globals = { 308 .option_offset = 0, 309 .program_version = IPTABLES_VERSION, 310 .orig_opts = ebt_original_options, 311 .exit_err = ebt_print_error, 312 .compat_rev = nft_compatible_revision, 313 }; 314 315 #define opts ebtables_globals.opts 316 #define prog_name ebtables_globals.program_name 317 #define prog_vers ebtables_globals.program_version 318 319 /* 320 * From libebtc.c 321 */ 322 323 /* Prints all registered extensions */ 324 static void ebt_list_extensions(const struct xtables_target *t, 325 const struct xtables_rule_match *m) 326 { 327 printf("%s v%s\n", prog_name, prog_vers); 328 printf("Loaded userspace extensions:\n"); 329 /*printf("\nLoaded tables:\n"); 330 while (tbl) { 331 printf("%s\n", tbl->name); 332 tbl = tbl->next; 333 }*/ 334 printf("\nLoaded targets:\n"); 335 for (t = xtables_targets; t; t = t->next) { 336 printf("%s\n", t->name); 337 } 338 printf("\nLoaded matches:\n"); 339 for (; m != NULL; m = m->next) 340 printf("%s\n", m->match->name); 341 /*printf("\nLoaded watchers:\n"); 342 while (w) { 343 printf("%s\n", w->name); 344 w = w->next; 345 }*/ 346 } 347 348 #define OPTION_OFFSET 256 349 static struct option *merge_options(struct option *oldopts, 350 const struct option *newopts, 351 unsigned int *options_offset) 352 { 353 unsigned int num_old, num_new, i; 354 struct option *merge; 355 356 if (!newopts || !oldopts || !options_offset) 357 return oldopts; 358 for (num_old = 0; oldopts[num_old].name; num_old++); 359 for (num_new = 0; newopts[num_new].name; num_new++); 360 361 ebtables_globals.option_offset += OPTION_OFFSET; 362 *options_offset = ebtables_globals.option_offset; 363 364 merge = malloc(sizeof(struct option) * (num_new + num_old + 1)); 365 if (!merge) 366 return NULL; 367 memcpy(merge, oldopts, num_old * sizeof(struct option)); 368 for (i = 0; i < num_new; i++) { 369 merge[num_old + i] = newopts[i]; 370 merge[num_old + i].val += *options_offset; 371 } 372 memset(merge + num_old + num_new, 0, sizeof(struct option)); 373 /* Only free dynamically allocated stuff */ 374 if (oldopts != ebt_original_options) 375 free(oldopts); 376 377 return merge; 378 } 379 380 /* 381 * More glue code. 382 */ 383 static struct xtables_target *command_jump(struct ebtables_command_state *cs, 384 const char *jumpto) 385 { 386 struct xtables_target *target; 387 size_t size; 388 389 /* XTF_TRY_LOAD (may be chain name) */ 390 target = xtables_find_target(jumpto, XTF_TRY_LOAD); 391 392 if (!target) 393 return NULL; 394 395 size = XT_ALIGN(sizeof(struct xt_entry_target)) 396 + target->size; 397 398 target->t = xtables_calloc(1, size); 399 target->t->u.target_size = size; 400 strncpy(target->t->u.user.name, jumpto, sizeof(target->t->u.user.name)); 401 target->t->u.user.name[sizeof(target->t->u.user.name)-1] = '\0'; 402 target->t->u.user.revision = target->revision; 403 404 xs_init_target(target); 405 406 opts = merge_options(opts, target->extra_opts, &target->option_offset); 407 if (opts == NULL) 408 xtables_error(OTHER_PROBLEM, "Can't alloc memory"); 409 410 return target; 411 } 412 413 static void print_help(const struct xtables_target *t, 414 const struct xtables_rule_match *m, const char *table) 415 { 416 printf("%s %s\n", prog_name, prog_vers); 417 printf( 418 "Usage:\n" 419 "ebtables -[ADI] chain rule-specification [options]\n" 420 "ebtables -P chain target\n" 421 "ebtables -[LFZ] [chain]\n" 422 "ebtables -[NX] [chain]\n" 423 "ebtables -E old-chain-name new-chain-name\n\n" 424 "Commands:\n" 425 "--append -A chain : append to chain\n" 426 "--delete -D chain : delete matching rule from chain\n" 427 "--delete -D chain rulenum : delete rule at position rulenum from chain\n" 428 "--change-counters -C chain\n" 429 " [rulenum] pcnt bcnt : change counters of existing rule\n" 430 "--insert -I chain rulenum : insert rule at position rulenum in chain\n" 431 "--list -L [chain] : list the rules in a chain or in all chains\n" 432 "--flush -F [chain] : delete all rules in chain or in all chains\n" 433 "--init-table : replace the kernel table with the initial table\n" 434 "--zero -Z [chain] : put counters on zero in chain or in all chains\n" 435 "--policy -P chain target : change policy on chain to target\n" 436 "--new-chain -N chain : create a user defined chain\n" 437 "--rename-chain -E old new : rename a chain\n" 438 "--delete-chain -X [chain] : delete a user defined chain\n" 439 "--atomic-commit : update the kernel w/t table contained in <FILE>\n" 440 "--atomic-init : put the initial kernel table into <FILE>\n" 441 "--atomic-save : put the current kernel table into <FILE>\n" 442 "--atomic-file file : set <FILE> to file\n\n" 443 "Options:\n" 444 "--proto -p [!] proto : protocol hexadecimal, by name or LENGTH\n" 445 "--src -s [!] address[/mask]: source mac address\n" 446 "--dst -d [!] address[/mask]: destination mac address\n" 447 "--in-if -i [!] name[+] : network input interface name\n" 448 "--out-if -o [!] name[+] : network output interface name\n" 449 "--logical-in [!] name[+] : logical bridge input interface name\n" 450 "--logical-out [!] name[+] : logical bridge output interface name\n" 451 "--set-counters -c chain\n" 452 " pcnt bcnt : set the counters of the to be added rule\n" 453 "--modprobe -M program : try to insert modules using this program\n" 454 "--concurrent : use a file lock to support concurrent scripts\n" 455 "--version -V : print package version\n\n" 456 "Environment variable:\n" 457 /*ATOMIC_ENV_VARIABLE " : if set <FILE> (see above) will equal its value"*/ 458 "\n\n"); 459 for (; m != NULL; m = m->next) { 460 printf("\n"); 461 m->match->help(); 462 } 463 if (t != NULL) { 464 printf("\n"); 465 t->help(); 466 } 467 468 // if (table->help) 469 // table->help(ebt_hooknames); 470 } 471 472 /* Execute command L */ 473 static int list_rules(struct nft_handle *h, const char *chain, const char *table, 474 int rule_nr, int verbose, int numeric, int expanded, 475 int linenumbers, int counters) 476 { 477 unsigned int format; 478 479 format = FMT_OPTIONS; 480 if (verbose) 481 format |= FMT_VIA; 482 483 if (numeric) 484 format |= FMT_NUMERIC; 485 486 if (!expanded) 487 format |= FMT_KILOMEGAGIGA; 488 489 if (linenumbers) 490 format |= FMT_LINENUMBERS; 491 492 if (!counters) 493 format |= FMT_NOCOUNTS; 494 495 return nft_rule_list(h, chain, table, rule_nr, format); 496 } 497 498 static int parse_rule_range(const char *argv, int *rule_nr, int *rule_nr_end) 499 { 500 char *colon = strchr(argv, ':'), *buffer; 501 502 if (colon) { 503 *colon = '\0'; 504 if (*(colon + 1) == '\0') 505 *rule_nr_end = -1; /* Until the last rule */ 506 else { 507 *rule_nr_end = strtol(colon + 1, &buffer, 10); 508 if (*buffer != '\0' || *rule_nr_end == 0) 509 return -1; 510 } 511 } 512 if (colon == argv) 513 *rule_nr = 1; /* Beginning with the first rule */ 514 else { 515 *rule_nr = strtol(argv, &buffer, 10); 516 if (*buffer != '\0' || *rule_nr == 0) 517 return -1; 518 } 519 if (!colon) 520 *rule_nr_end = *rule_nr; 521 return 0; 522 } 523 524 /* Incrementing or decrementing rules in daemon mode is not supported as the 525 * involved code overload is not worth it (too annoying to take the increased 526 * counters in the kernel into account). */ 527 static int parse_change_counters_rule(int argc, char **argv, int *rule_nr, int *rule_nr_end, int exec_style, struct ebtables_command_state *cs) 528 { 529 char *buffer; 530 int ret = 0; 531 532 if (optind + 1 >= argc || (argv[optind][0] == '-' && (argv[optind][1] < '0' || argv[optind][1] > '9')) || 533 (argv[optind + 1][0] == '-' && (argv[optind + 1][1] < '0' && argv[optind + 1][1] > '9'))) 534 xtables_error(PARAMETER_PROBLEM, 535 "The command -C needs at least 2 arguments"); 536 if (optind + 2 < argc && (argv[optind + 2][0] != '-' || (argv[optind + 2][1] >= '0' && argv[optind + 2][1] <= '9'))) { 537 if (optind + 3 != argc) 538 xtables_error(PARAMETER_PROBLEM, 539 "No extra options allowed with -C start_nr[:end_nr] pcnt bcnt"); 540 if (parse_rule_range(argv[optind], rule_nr, rule_nr_end)) 541 xtables_error(PARAMETER_PROBLEM, 542 "Something is wrong with the rule number specification '%s'", argv[optind]); 543 optind++; 544 } 545 546 if (argv[optind][0] == '+') { 547 if (exec_style == EXEC_STYLE_DAEMON) 548 daemon_incr: 549 xtables_error(PARAMETER_PROBLEM, 550 "Incrementing rule counters (%s) not allowed in daemon mode", argv[optind]); 551 ret += 1; 552 cs->counters.pcnt = strtoull(argv[optind] + 1, &buffer, 10); 553 } else if (argv[optind][0] == '-') { 554 if (exec_style == EXEC_STYLE_DAEMON) 555 daemon_decr: 556 xtables_error(PARAMETER_PROBLEM, 557 "Decrementing rule counters (%s) not allowed in daemon mode", argv[optind]); 558 ret += 2; 559 cs->counters.pcnt = strtoull(argv[optind] + 1, &buffer, 10); 560 } else 561 cs->counters.pcnt = strtoull(argv[optind], &buffer, 10); 562 563 if (*buffer != '\0') 564 goto invalid; 565 optind++; 566 if (argv[optind][0] == '+') { 567 if (exec_style == EXEC_STYLE_DAEMON) 568 goto daemon_incr; 569 ret += 3; 570 cs->counters.bcnt = strtoull(argv[optind] + 1, &buffer, 10); 571 } else if (argv[optind][0] == '-') { 572 if (exec_style == EXEC_STYLE_DAEMON) 573 goto daemon_decr; 574 ret += 6; 575 cs->counters.bcnt = strtoull(argv[optind] + 1, &buffer, 10); 576 } else 577 cs->counters.bcnt = strtoull(argv[optind], &buffer, 10); 578 579 if (*buffer != '\0') 580 goto invalid; 581 optind++; 582 return ret; 583 invalid: 584 xtables_error(PARAMETER_PROBLEM,"Packet counter '%s' invalid", argv[optind]); 585 } 586 587 static int parse_iface(char *iface, char *option) 588 { 589 char *c; 590 591 if ((c = strchr(iface, '+'))) { 592 if (*(c + 1) != '\0') { 593 xtables_error(PARAMETER_PROBLEM, 594 "Spurious characters after '+' wildcard for '%s'", option); 595 return -1; 596 } else 597 *c = IF_WILDCARD; 598 } 599 return 0; 600 } 601 602 /* This code is very similar to iptables/xtables.c:command_match() */ 603 static void ebt_load_match(const char *name) 604 { 605 struct xtables_match *m; 606 size_t size; 607 608 m = xtables_find_match(name, XTF_LOAD_MUST_SUCCEED, NULL); 609 if (m == NULL) 610 xtables_error(OTHER_PROBLEM, "Unable to load %s match", name); 611 612 size = XT_ALIGN(sizeof(struct xt_entry_match)) + m->size; 613 m->m = xtables_calloc(1, size); 614 m->m->u.match_size = size; 615 strcpy(m->m->u.user.name, m->name); 616 m->m->u.user.revision = m->revision; 617 xs_init_match(m); 618 619 opts = merge_options(opts, m->extra_opts, &m->option_offset); 620 if (opts == NULL) 621 xtables_error(OTHER_PROBLEM, "Can't alloc memory"); 622 } 623 624 static void ebt_load_watcher(const char *name) 625 { 626 struct xtables_target *watcher; 627 size_t size; 628 629 watcher = xtables_find_target(name, XTF_LOAD_MUST_SUCCEED); 630 if (!watcher) 631 xtables_error(OTHER_PROBLEM, 632 "Unable to load %s watcher", name); 633 634 size = XT_ALIGN(sizeof(struct xt_entry_target)) + watcher->size; 635 636 watcher->t = xtables_calloc(1, size); 637 watcher->t->u.target_size = size; 638 strncpy(watcher->t->u.user.name, name, 639 sizeof(watcher->t->u.user.name)); 640 watcher->t->u.user.name[sizeof(watcher->t->u.user.name)-1] = '\0'; 641 watcher->t->u.user.revision = watcher->revision; 642 643 xs_init_target(watcher); 644 645 opts = merge_options(opts, watcher->extra_opts, 646 &watcher->option_offset); 647 if (opts == NULL) 648 xtables_error(OTHER_PROBLEM, "Can't alloc memory"); 649 } 650 651 static void ebt_load_match_extensions(void) 652 { 653 opts = ebt_original_options; 654 ebt_load_match("802_3"); 655 ebt_load_match("ip"); 656 ebt_load_match("mark_m"); 657 ebt_load_match("limit"); 658 659 ebt_load_watcher("log"); 660 ebt_load_watcher("nflog"); 661 } 662 663 static void ebt_add_match(struct xtables_match *m, 664 struct ebtables_command_state *cs) 665 { 666 struct xtables_rule_match *i, **rule_matches = &cs->matches; 667 struct xtables_match *newm; 668 struct ebt_match *newnode; 669 670 /* match already in rule_matches, skip inclusion */ 671 for (i = *rule_matches; i; i = i->next) { 672 if (strcmp(m->name, i->match->name) == 0) { 673 i->match->mflags |= m->mflags; 674 return; 675 } 676 } 677 678 newm = xtables_find_match(m->name, XTF_LOAD_MUST_SUCCEED, rule_matches); 679 if (newm == NULL) 680 xtables_error(OTHER_PROBLEM, 681 "Unable to add match %s", m->name); 682 683 newm->mflags = m->mflags; 684 685 /* glue code for watchers */ 686 newnode = calloc(1, sizeof(struct ebt_match)); 687 if (newnode == NULL) 688 xtables_error(OTHER_PROBLEM, "Unable to alloc memory"); 689 690 newnode->ismatch = true; 691 newnode->u.match = newm; 692 693 if (cs->match_list == NULL) 694 cs->match_list = newnode; 695 else 696 cs->match_list->next = newnode; 697 } 698 699 static void ebt_add_watcher(struct xtables_target *watcher, 700 struct ebtables_command_state *cs) 701 { 702 struct ebt_match *i, *newnode; 703 704 for (i = cs->match_list; i; i = i->next) { 705 if (i->ismatch) 706 continue; 707 if (strcmp(i->u.watcher->name, watcher->name) == 0) { 708 i->u.watcher->tflags |= watcher->tflags; 709 return; 710 } 711 } 712 713 newnode = calloc(1, sizeof(struct ebt_match)); 714 if (newnode == NULL) 715 xtables_error(OTHER_PROBLEM, "Unable to alloc memory"); 716 717 newnode->u.watcher = watcher; 718 719 if (cs->match_list == NULL) 720 cs->match_list = newnode; 721 else 722 cs->match_list->next = newnode; 723 } 724 725 /* We use exec_style instead of #ifdef's because ebtables.so is a shared object. */ 726 int do_commandeb(struct nft_handle *h, int argc, char *argv[], char **table) 727 { 728 char *buffer; 729 int c, i; 730 int zerochain = -1; /* Needed for the -Z option (we can have -Z <this> -L <that>) */ 731 int chcounter = 0; /* Needed for -C */ 732 int rule_nr = 0; 733 int rule_nr_end = 0; 734 int ret = 0; 735 unsigned int flags = 0; 736 struct xtables_target *t, *w; 737 struct xtables_match *m; 738 struct ebtables_command_state cs; 739 char command = 'h'; 740 const char *chain = NULL; 741 const char *policy = NULL; 742 int exec_style = EXEC_STYLE_PRG; 743 int selected_chain = -1; 744 struct xtables_rule_match *xtrm_i; 745 struct ebt_match *match; 746 747 memset(&cs, 0, sizeof(cs)); 748 cs.argv = argv; 749 750 if (nft_init(h, xtables_bridge) < 0) 751 xtables_error(OTHER_PROBLEM, 752 "Could not initialize nftables layer."); 753 754 h->ops = nft_family_ops_lookup(h->family); 755 if (h->ops == NULL) 756 xtables_error(PARAMETER_PROBLEM, "Unknown family"); 757 758 /* manually registering ebt matches, given the original ebtables parser 759 * don't use '-m matchname' and the match can't loaded dinamically when 760 * the user calls it. 761 */ 762 ebt_load_match_extensions(); 763 764 /* clear mflags in case do_commandeb gets called a second time 765 * (we clear the global list of all matches for security)*/ 766 for (m = xtables_matches; m; m = m->next) 767 m->mflags = 0; 768 769 for (t = xtables_targets; t; t = t->next) { 770 t->tflags = 0; 771 t->used = 0; 772 } 773 774 /* prevent getopt to spoil our error reporting */ 775 opterr = false; 776 777 /* Getopt saves the day */ 778 while ((c = getopt_long(argc, argv, 779 "-A:D:C:I:N:E:X::L::Z::F::P:Vhi:o:j:c:p:s:d:t:M:", opts, NULL)) != -1) { 780 cs.c = c; 781 cs.invert = ebt_invert; 782 switch (c) { 783 784 case 'A': /* Add a rule */ 785 case 'D': /* Delete a rule */ 786 case 'C': /* Change counters */ 787 case 'P': /* Define policy */ 788 case 'I': /* Insert a rule */ 789 case 'N': /* Make a user defined chain */ 790 case 'E': /* Rename chain */ 791 case 'X': /* Delete chain */ 792 /* We allow -N chainname -P policy */ 793 /* XXX: Not in ebtables-compat */ 794 if (command == 'N' && c == 'P') { 795 command = c; 796 optind--; /* No table specified */ 797 goto handle_P; 798 } 799 if (OPT_COMMANDS) 800 xtables_error(PARAMETER_PROBLEM, 801 "Multiple commands are not allowed"); 802 803 command = c; 804 chain = optarg; 805 selected_chain = get_current_chain(chain); 806 flags |= OPT_COMMAND; 807 /*if (!(replace->flags & OPT_KERNELDATA)) 808 ebt_get_kernel_table(replace, 0);*/ 809 /*if (optarg && (optarg[0] == '-' || !strcmp(optarg, "!"))) 810 ebt_print_error2("No chain name specified");*/ 811 if (c == 'N') { 812 ret = nft_chain_user_add(h, chain, *table); 813 break; 814 } else if (c == 'X') { 815 ret = nft_chain_user_del(h, chain, *table); 816 break; 817 } 818 819 if (c == 'E') { 820 if (optind >= argc) 821 xtables_error(PARAMETER_PROBLEM, "No new chain name specified"); 822 else if (optind < argc - 1) 823 xtables_error(PARAMETER_PROBLEM, "No extra options allowed with -E"); 824 else if (strlen(argv[optind]) >= NFT_CHAIN_MAXNAMELEN) 825 xtables_error(PARAMETER_PROBLEM, "Chain name length can't exceed %d"" characters", NFT_CHAIN_MAXNAMELEN - 1); 826 else if (strchr(argv[optind], ' ') != NULL) 827 xtables_error(PARAMETER_PROBLEM, "Use of ' ' not allowed in chain names"); 828 829 ret = nft_chain_user_rename(h, chain, *table, 830 argv[optind]); 831 if (ret != 0 && errno == ENOENT) 832 xtables_error(PARAMETER_PROBLEM, "Chain '%s' doesn't exists", chain); 833 834 optind++; 835 break; 836 } else if (c == 'D' && optind < argc && (argv[optind][0] != '-' || (argv[optind][1] >= '0' && argv[optind][1] <= '9'))) { 837 if (optind != argc - 1) 838 xtables_error(PARAMETER_PROBLEM, 839 "No extra options allowed with -D start_nr[:end_nr]"); 840 if (parse_rule_range(argv[optind], &rule_nr, &rule_nr_end)) 841 xtables_error(PARAMETER_PROBLEM, 842 "Problem with the specified rule number(s) '%s'", argv[optind]); 843 optind++; 844 } else if (c == 'C') { 845 if ((chcounter = parse_change_counters_rule(argc, argv, &rule_nr, &rule_nr_end, exec_style, &cs)) == -1) 846 return -1; 847 } else if (c == 'I') { 848 if (optind >= argc || (argv[optind][0] == '-' && (argv[optind][1] < '0' || argv[optind][1] > '9'))) 849 rule_nr = 1; 850 else { 851 rule_nr = parse_rule_number(argv[optind]); 852 optind++; 853 } 854 } else if (c == 'P') { 855 handle_P: 856 if (optind >= argc) 857 xtables_error(PARAMETER_PROBLEM, 858 "No policy specified"); 859 for (i = 0; i < NUM_STANDARD_TARGETS; i++) 860 if (!strcmp(argv[optind], nft_ebt_standard_target(i))) { 861 policy = argv[optind]; 862 if (-i-1 == EBT_CONTINUE) 863 xtables_error(PARAMETER_PROBLEM, 864 "Wrong policy '%s'", 865 argv[optind]); 866 break; 867 } 868 if (i == NUM_STANDARD_TARGETS) 869 xtables_error(PARAMETER_PROBLEM, 870 "Unknown policy '%s'", argv[optind]); 871 optind++; 872 } 873 break; 874 case 'L': /* List */ 875 case 'F': /* Flush */ 876 case 'Z': /* Zero counters */ 877 if (c == 'Z') { 878 if ((flags & OPT_ZERO) || (flags & OPT_COMMAND && command != 'L')) 879 print_zero: 880 xtables_error(PARAMETER_PROBLEM, 881 "Command -Z only allowed together with command -L"); 882 flags |= OPT_ZERO; 883 } else { 884 if (flags & OPT_COMMAND) 885 xtables_error(PARAMETER_PROBLEM, 886 "Multiple commands are not allowed"); 887 command = c; 888 flags |= OPT_COMMAND; 889 if (flags & OPT_ZERO && c != 'L') 890 goto print_zero; 891 } 892 893 #ifdef SILENT_DAEMON 894 if (c== 'L' && exec_style == EXEC_STYLE_DAEMON) 895 xtables_error(PARAMETER_PROBLEM, 896 "-L not supported in daemon mode"); 897 #endif 898 899 /*if (!(replace->flags & OPT_KERNELDATA)) 900 ebt_get_kernel_table(replace, 0); 901 i = -1; 902 if (optind < argc && argv[optind][0] != '-') { 903 if ((i = ebt_get_chainnr(replace, argv[optind])) == -1) 904 ebt_print_error2("Chain '%s' doesn't exist", argv[optind]); 905 optind++; 906 } 907 if (i != -1) { 908 if (c == 'Z') 909 zerochain = i; 910 else 911 replace->selected_chain = i; 912 }*/ 913 break; 914 case 'V': /* Version */ 915 if (OPT_COMMANDS) 916 xtables_error(PARAMETER_PROBLEM, 917 "Multiple commands are not allowed"); 918 command = 'V'; 919 if (exec_style == EXEC_STYLE_DAEMON) 920 xtables_error(PARAMETER_PROBLEM, 921 "%s %s\n", prog_name, prog_vers); 922 printf("%s %s\n", prog_name, prog_vers); 923 exit(0); 924 case 'h': /* Help */ 925 #ifdef SILENT_DAEMON 926 if (exec_style == EXEC_STYLE_DAEMON) 927 xtables_error(PARAMETER_PROBLEM, 928 "-h not supported in daemon mode"); 929 #endif 930 if (OPT_COMMANDS) 931 xtables_error(PARAMETER_PROBLEM, 932 "Multiple commands are not allowed"); 933 command = 'h'; 934 935 /* All other arguments should be extension names */ 936 while (optind < argc) { 937 /*struct ebt_u_match *m; 938 struct ebt_u_watcher *w;*/ 939 940 if (!strcasecmp("list_extensions", argv[optind])) { 941 ebt_list_extensions(xtables_targets, cs.matches); 942 exit(0); 943 } 944 /*if ((m = ebt_find_match(argv[optind]))) 945 ebt_add_match(new_entry, m); 946 else if ((w = ebt_find_watcher(argv[optind]))) 947 ebt_add_watcher(new_entry, w); 948 else {*/ 949 if (!(t = xtables_find_target(argv[optind], XTF_TRY_LOAD))) 950 xtables_error(PARAMETER_PROBLEM,"Extension '%s' not found", argv[optind]); 951 if (flags & OPT_JUMP) 952 xtables_error(PARAMETER_PROBLEM,"Sorry, you can only see help for one target extension at a time"); 953 flags |= OPT_JUMP; 954 cs.target = t; 955 //} 956 optind++; 957 } 958 break; 959 case 't': /* Table */ 960 if (OPT_COMMANDS) 961 xtables_error(PARAMETER_PROBLEM, 962 "Please put the -t option first"); 963 ebt_check_option2(&flags, OPT_TABLE); 964 if (strlen(optarg) > EBT_TABLE_MAXNAMELEN - 1) 965 xtables_error(PARAMETER_PROBLEM, 966 "Table name length cannot exceed %d characters", 967 EBT_TABLE_MAXNAMELEN - 1); 968 *table = optarg; 969 break; 970 case 'i': /* Input interface */ 971 case 2 : /* Logical input interface */ 972 case 'o': /* Output interface */ 973 case 3 : /* Logical output interface */ 974 case 'j': /* Target */ 975 case 'p': /* Net family protocol */ 976 case 's': /* Source mac */ 977 case 'd': /* Destination mac */ 978 case 'c': /* Set counters */ 979 if (!OPT_COMMANDS) 980 xtables_error(PARAMETER_PROBLEM, 981 "No command specified"); 982 if (command != 'A' && command != 'D' && command != 'I' && command != 'C') 983 xtables_error(PARAMETER_PROBLEM, 984 "Command and option do not match"); 985 if (c == 'i') { 986 ebt_check_option2(&flags, OPT_IN); 987 if (selected_chain > 2 && selected_chain < NF_BR_BROUTING) 988 xtables_error(PARAMETER_PROBLEM, 989 "Use -i only in INPUT, FORWARD, PREROUTING and BROUTING chains"); 990 if (ebt_check_inverse2(optarg, argc, argv)) 991 cs.fw.invflags |= EBT_IIN; 992 993 if (strlen(optarg) >= IFNAMSIZ) 994 big_iface_length: 995 xtables_error(PARAMETER_PROBLEM, 996 "Interface name length cannot exceed %d characters", 997 IFNAMSIZ - 1); 998 xtables_parse_interface(optarg, cs.fw.in, cs.fw.in_mask); 999 break; 1000 } else if (c == 2) { 1001 ebt_check_option2(&flags, OPT_LOGICALIN); 1002 if (selected_chain > 2 && selected_chain < NF_BR_BROUTING) 1003 xtables_error(PARAMETER_PROBLEM, 1004 "Use --logical-in only in INPUT, FORWARD, PREROUTING and BROUTING chains"); 1005 if (ebt_check_inverse2(optarg, argc, argv)) 1006 cs.fw.invflags |= EBT_ILOGICALIN; 1007 1008 if (strlen(optarg) >= IFNAMSIZ) 1009 goto big_iface_length; 1010 strcpy(cs.fw.logical_in, optarg); 1011 if (parse_iface(cs.fw.logical_in, "--logical-in")) 1012 return -1; 1013 break; 1014 } else if (c == 'o') { 1015 ebt_check_option2(&flags, OPT_OUT); 1016 if (selected_chain < 2 || selected_chain == NF_BR_BROUTING) 1017 xtables_error(PARAMETER_PROBLEM, 1018 "Use -o only in OUTPUT, FORWARD and POSTROUTING chains"); 1019 if (ebt_check_inverse2(optarg, argc, argv)) 1020 cs.fw.invflags |= EBT_IOUT; 1021 1022 if (strlen(optarg) >= IFNAMSIZ) 1023 goto big_iface_length; 1024 1025 xtables_parse_interface(optarg, cs.fw.out, cs.fw.out_mask); 1026 break; 1027 } else if (c == 3) { 1028 ebt_check_option2(&flags, OPT_LOGICALOUT); 1029 if (selected_chain < 2 || selected_chain == NF_BR_BROUTING) 1030 xtables_error(PARAMETER_PROBLEM, 1031 "Use --logical-out only in OUTPUT, FORWARD and POSTROUTING chains"); 1032 if (ebt_check_inverse2(optarg, argc, argv)) 1033 cs.fw.invflags |= EBT_ILOGICALOUT; 1034 1035 if (strlen(optarg) >= IFNAMSIZ) 1036 goto big_iface_length; 1037 strcpy(cs.fw.logical_out, optarg); 1038 if (parse_iface(cs.fw.logical_out, "--logical-out")) 1039 return -1; 1040 break; 1041 } else if (c == 'j') { 1042 ebt_check_option2(&flags, OPT_JUMP); 1043 cs.jumpto = parse_target(optarg); 1044 cs.target = command_jump(&cs, cs.jumpto); 1045 break; 1046 } else if (c == 's') { 1047 ebt_check_option2(&flags, OPT_SOURCE); 1048 if (ebt_check_inverse2(optarg, argc, argv)) 1049 cs.fw.invflags |= EBT_ISOURCE; 1050 1051 if (ebt_get_mac_and_mask(optarg, cs.fw.sourcemac, cs.fw.sourcemsk)) 1052 xtables_error(PARAMETER_PROBLEM, "Problem with specified source mac '%s'", optarg); 1053 cs.fw.bitmask |= EBT_SOURCEMAC; 1054 break; 1055 } else if (c == 'd') { 1056 ebt_check_option2(&flags, OPT_DEST); 1057 if (ebt_check_inverse2(optarg, argc, argv)) 1058 cs.fw.invflags |= EBT_IDEST; 1059 1060 if (ebt_get_mac_and_mask(optarg, cs.fw.destmac, cs.fw.destmsk)) 1061 xtables_error(PARAMETER_PROBLEM, "Problem with specified destination mac '%s'", optarg); 1062 cs.fw.bitmask |= EBT_DESTMAC; 1063 break; 1064 } else if (c == 'c') { 1065 ebt_check_option2(&flags, OPT_COUNT); 1066 if (ebt_check_inverse2(optarg, argc, argv)) 1067 xtables_error(PARAMETER_PROBLEM, 1068 "Unexpected '!' after -c"); 1069 if (optind >= argc || optarg[0] == '-' || argv[optind][0] == '-') 1070 xtables_error(PARAMETER_PROBLEM, 1071 "Option -c needs 2 arguments"); 1072 1073 cs.counters.pcnt = strtoull(optarg, &buffer, 10); 1074 if (*buffer != '\0') 1075 xtables_error(PARAMETER_PROBLEM, 1076 "Packet counter '%s' invalid", 1077 optarg); 1078 cs.counters.bcnt = strtoull(argv[optind], &buffer, 10); 1079 if (*buffer != '\0') 1080 xtables_error(PARAMETER_PROBLEM, 1081 "Packet counter '%s' invalid", 1082 argv[optind]); 1083 optind++; 1084 break; 1085 } 1086 ebt_check_option2(&flags, OPT_PROTOCOL); 1087 if (ebt_check_inverse2(optarg, argc, argv)) 1088 cs.fw.invflags |= EBT_IPROTO; 1089 1090 cs.fw.bitmask &= ~((unsigned int)EBT_NOPROTO); 1091 i = strtol(optarg, &buffer, 16); 1092 if (*buffer == '\0' && (i < 0 || i > 0xFFFF)) 1093 xtables_error(PARAMETER_PROBLEM, 1094 "Problem with the specified protocol"); 1095 if (*buffer != '\0') { 1096 struct ethertypeent *ent; 1097 1098 if (!strcasecmp(optarg, "LENGTH")) { 1099 cs.fw.bitmask |= EBT_802_3; 1100 break; 1101 } 1102 ent = getethertypebyname(optarg); 1103 if (!ent) 1104 xtables_error(PARAMETER_PROBLEM, 1105 "Problem with the specified Ethernet protocol '%s', perhaps "_PATH_ETHERTYPES " is missing", optarg); 1106 cs.fw.ethproto = ent->e_ethertype; 1107 } else 1108 cs.fw.ethproto = i; 1109 1110 if (cs.fw.ethproto < 0x0600) 1111 xtables_error(PARAMETER_PROBLEM, 1112 "Sorry, protocols have values above or equal to 0x0600"); 1113 break; 1114 case 4 : /* Lc */ 1115 #ifdef SILENT_DAEMON 1116 if (exec_style == EXEC_STYLE_DAEMON) 1117 xtables_error(PARAMETER_PROBLEM, 1118 "--Lc is not supported in daemon mode"); 1119 #endif 1120 ebt_check_option2(&flags, LIST_C); 1121 if (command != 'L') 1122 xtables_error(PARAMETER_PROBLEM, 1123 "Use --Lc with -L"); 1124 flags |= LIST_C; 1125 break; 1126 case 5 : /* Ln */ 1127 #ifdef SILENT_DAEMON 1128 if (exec_style == EXEC_STYLE_DAEMON) 1129 xtables_error(PARAMETER_PROBLEM, 1130 "--Ln is not supported in daemon mode"); 1131 #endif 1132 ebt_check_option2(&flags, LIST_N); 1133 if (command != 'L') 1134 xtables_error(PARAMETER_PROBLEM, 1135 "Use --Ln with -L"); 1136 if (flags & LIST_X) 1137 xtables_error(PARAMETER_PROBLEM, 1138 "--Lx is not compatible with --Ln"); 1139 flags |= LIST_N; 1140 break; 1141 case 6 : /* Lx */ 1142 #ifdef SILENT_DAEMON 1143 if (exec_style == EXEC_STYLE_DAEMON) 1144 xtables_error(PARAMETER_PROBLEM, 1145 "--Lx is not supported in daemon mode"); 1146 #endif 1147 ebt_check_option2(&flags, LIST_X); 1148 if (command != 'L') 1149 xtables_error(PARAMETER_PROBLEM, 1150 "Use --Lx with -L"); 1151 if (flags & LIST_N) 1152 xtables_error(PARAMETER_PROBLEM, 1153 "--Lx is not compatible with --Ln"); 1154 flags |= LIST_X; 1155 break; 1156 case 12 : /* Lmac2 */ 1157 #ifdef SILENT_DAEMON 1158 if (exec_style == EXEC_STYLE_DAEMON) 1159 xtables_error(PARAMETER_PROBLEM, 1160 "--Lmac2 is not supported in daemon mode"); 1161 #endif 1162 ebt_check_option2(&flags, LIST_MAC2); 1163 if (command != 'L') 1164 xtables_error(PARAMETER_PROBLEM, 1165 "Use --Lmac2 with -L"); 1166 flags |= LIST_MAC2; 1167 break; 1168 case 8 : /* atomic-commit */ 1169 /* if (exec_style == EXEC_STYLE_DAEMON) 1170 ebt_print_error2("--atomic-commit is not supported in daemon mode"); 1171 replace->command = c; 1172 if (OPT_COMMANDS) 1173 ebt_print_error2("Multiple commands are not allowed"); 1174 replace->flags |= OPT_COMMAND; 1175 if (!replace->filename) 1176 ebt_print_error2("No atomic file specified");*/ 1177 /* Get the information from the file */ 1178 /*ebt_get_table(replace, 0);*/ 1179 /* We don't want the kernel giving us its counters, 1180 * they would overwrite the counters extracted from 1181 * the file */ 1182 /*replace->num_counters = 0;*/ 1183 /* Make sure the table will be written to the kernel */ 1184 /*free(replace->filename); 1185 replace->filename = NULL; 1186 break;*/ 1187 /*case 7 :*/ /* atomic-init */ 1188 /*case 10:*/ /* atomic-save */ 1189 /*case 11:*/ /* init-table */ 1190 /* if (exec_style == EXEC_STYLE_DAEMON) { 1191 if (c == 7) { 1192 ebt_print_error2("--atomic-init is not supported in daemon mode"); 1193 } else if (c == 10) 1194 ebt_print_error2("--atomic-save is not supported in daemon mode"); 1195 ebt_print_error2("--init-table is not supported in daemon mode"); 1196 } 1197 replace->command = c; 1198 if (OPT_COMMANDS) 1199 ebt_print_error2("Multiple commands are not allowed"); 1200 if (c != 11 && !replace->filename) 1201 ebt_print_error2("No atomic file specified"); 1202 replace->flags |= OPT_COMMAND; 1203 { 1204 char *tmp = replace->filename;*/ 1205 1206 /* Get the kernel table */ 1207 /*replace->filename = NULL; 1208 ebt_get_kernel_table(replace, c == 10 ? 0 : 1); 1209 replace->filename = tmp; 1210 } 1211 break; 1212 case 9 :*/ /* atomic */ 1213 /*if (exec_style == EXEC_STYLE_DAEMON) 1214 ebt_print_error2("--atomic is not supported in daemon mode"); 1215 if (OPT_COMMANDS) 1216 ebt_print_error2("--atomic has to come before the command");*/ 1217 /* A possible memory leak here, but this is not 1218 * executed in daemon mode */ 1219 /*replace->filename = (char *)malloc(strlen(optarg) + 1); 1220 strcpy(replace->filename, optarg); 1221 break; 1222 case 13 : *//* concurrent */ 1223 /*signal(SIGINT, sighandler); 1224 signal(SIGTERM, sighandler); 1225 use_lockfd = 1; 1226 break;*/ 1227 case 1 : 1228 if (!strcmp(optarg, "!")) 1229 ebt_check_inverse2(optarg, argc, argv); 1230 else 1231 xtables_error(PARAMETER_PROBLEM, 1232 "Bad argument : '%s'", optarg); 1233 /* ebt_ebt_check_inverse2() did optind++ */ 1234 optind--; 1235 continue; 1236 default: 1237 /* Is it a target option? */ 1238 if (cs.target != NULL && cs.target->parse != NULL) { 1239 int opt_offset = cs.target->option_offset; 1240 if (cs.target->parse(c - opt_offset, 1241 argv, ebt_invert, 1242 &cs.target->tflags, 1243 NULL, &cs.target->t)) 1244 goto check_extension; 1245 } 1246 1247 /* Is it a match_option? */ 1248 for (m = xtables_matches; m; m = m->next) { 1249 if (m->parse(c - m->option_offset, argv, ebt_invert, &m->mflags, NULL, &m->m)) { 1250 ebt_add_match(m, &cs); 1251 goto check_extension; 1252 } 1253 } 1254 1255 /* Is it a watcher option? */ 1256 for (w = xtables_targets; w; w = w->next) { 1257 if (w->parse(c - w->option_offset, argv, 1258 ebt_invert, &w->tflags, 1259 NULL, &w->t)) { 1260 ebt_add_watcher(w, &cs); 1261 goto check_extension; 1262 } 1263 } 1264 /* 1265 if (w == NULL && c == '?') 1266 ebt_print_error2("Unknown argument: '%s'", argv[optind - 1], (char)optopt, (char)c); 1267 else if (w == NULL) { 1268 if (!strcmp(t->name, "standard")) 1269 ebt_print_error2("Unknown argument: don't forget the -t option"); 1270 else 1271 ebt_print_error2("Target-specific option does not correspond with specified target"); 1272 } 1273 if (ebt_errormsg[0] != '\0') 1274 return -1; 1275 if (w->used == 0) { 1276 ebt_add_watcher(new_entry, w); 1277 w->used = 1; 1278 }*/ 1279 check_extension: 1280 if (command != 'A' && command != 'I' && 1281 command != 'D' && command != 'C') 1282 xtables_error(PARAMETER_PROBLEM, 1283 "Extensions only for -A, -I, -D and -C"); 1284 } 1285 ebt_invert = 0; 1286 } 1287 1288 /* Just in case we didn't catch an error */ 1289 /*if (ebt_errormsg[0] != '\0') 1290 return -1; 1291 1292 if (!(table = ebt_find_table(replace->name))) 1293 ebt_print_error2("Bad table name");*/ 1294 1295 if (command == 'h' && !(flags & OPT_ZERO)) { 1296 print_help(cs.target, cs.matches, *table); 1297 if (exec_style == EXEC_STYLE_PRG) 1298 exit(0); 1299 } 1300 1301 /* Do the final checks */ 1302 if (command == 'A' || command == 'I' || 1303 command == 'D' || command == 'C') { 1304 for (xtrm_i = cs.matches; xtrm_i; xtrm_i = xtrm_i->next) 1305 xtables_option_mfcall(xtrm_i->match); 1306 1307 for (match = cs.match_list; match; match = match->next) { 1308 if (match->ismatch) 1309 continue; 1310 1311 xtables_option_tfcall(match->u.watcher); 1312 } 1313 1314 if (cs.target != NULL) 1315 xtables_option_tfcall(cs.target); 1316 } 1317 /* So, the extensions can work with the host endian. 1318 * The kernel does not have to do this of course */ 1319 cs.fw.ethproto = htons(cs.fw.ethproto); 1320 1321 if (command == 'P') { 1322 if (selected_chain < 0) { 1323 xtables_error(PARAMETER_PROBLEM, 1324 "Policy %s not allowed for user defined chains", 1325 policy); 1326 } 1327 if (strcmp(policy, "RETURN") == 0) { 1328 xtables_error(PARAMETER_PROBLEM, 1329 "Policy RETURN only allowed for user defined chains"); 1330 } 1331 ret = nft_chain_set(h, *table, chain, policy, NULL); 1332 if (ret < 0) 1333 xtables_error(PARAMETER_PROBLEM, "Wrong policy"); 1334 } else if (command == 'L') { 1335 ret = list_rules(h, chain, *table, rule_nr, 1336 flags&OPT_VERBOSE, 1337 flags&OPT_NUMERIC, 1338 /*flags&OPT_EXPANDED*/0, 1339 flags&LIST_N, 1340 flags&LIST_C); 1341 if (!(flags & OPT_ZERO) && exec_style == EXEC_STYLE_PRG) 1342 exit(0); 1343 } 1344 if (flags & OPT_ZERO) { 1345 selected_chain = zerochain; 1346 ret = nft_chain_zero_counters(h, chain, *table); 1347 } else if (command == 'F') { 1348 ret = nft_rule_flush(h, chain, *table); 1349 } else if (command == 'A') { 1350 ret = append_entry(h, chain, *table, &cs, 0, 1351 flags&OPT_VERBOSE, true); 1352 } else if (command == 'I') { 1353 ret = append_entry(h, chain, *table, &cs, rule_nr - 1, 1354 flags&OPT_VERBOSE, false); 1355 } else if (command == 'D') { 1356 ret = delete_entry(h, chain, *table, &cs, rule_nr - 1, 1357 rule_nr_end, flags&OPT_VERBOSE); 1358 } /*else if (replace->command == 'C') { 1359 ebt_change_counters(replace, new_entry, rule_nr, rule_nr_end, &(new_entry->cnt_surplus), chcounter); 1360 if (ebt_errormsg[0] != '\0') 1361 return -1; 1362 }*/ 1363 /* Commands -N, -E, -X, --atomic-commit, --atomic-commit, --atomic-save, 1364 * --init-table fall through */ 1365 1366 /*if (ebt_errormsg[0] != '\0') 1367 return -1; 1368 if (table->check) 1369 table->check(replace); 1370 1371 if (exec_style == EXEC_STYLE_PRG) {*//* Implies ebt_errormsg[0] == '\0' */ 1372 /*ebt_deliver_table(replace); 1373 1374 if (replace->nentries) 1375 ebt_deliver_counters(replace);*/ 1376 1377 ebt_cs_clean(&cs); 1378 return ret; 1379 } 1380