Home | History | Annotate | Download | only in iptables
      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