• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
ebt_get_mac_and_mask(const char * from,unsigned char * to,unsigned char * mask)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 
ebt_check_inverse2(const char option[],int argc,char ** argv)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  */
parse_rule_number(const char * rule)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 *
parse_target(const char * targetname)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
append_entry(struct nft_handle * h,const char * chain,const char * table,struct ebtables_command_state * cs,int rule_nr,bool verbose,bool append)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
delete_entry(struct nft_handle * h,const char * chain,const char * table,struct ebtables_command_state * cs,int rule_nr,int rule_nr_end,bool verbose)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 
get_current_chain(const char * chain)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)))
ebt_print_error(enum xtables_exittype status,const char * format,...)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 */
ebt_list_extensions(const struct xtables_target * t,const struct xtables_rule_match * m)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
merge_options(struct option * oldopts,const struct option * newopts,unsigned int * options_offset)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  */
command_jump(struct ebtables_command_state * cs,const char * jumpto)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 
print_help(const struct xtables_target * t,const struct xtables_rule_match * m,const char * table)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 */
list_rules(struct nft_handle * h,const char * chain,const char * table,int rule_nr,int verbose,int numeric,int expanded,int linenumbers,int counters)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 
parse_rule_range(const char * argv,int * rule_nr,int * rule_nr_end)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). */
parse_change_counters_rule(int argc,char ** argv,int * rule_nr,int * rule_nr_end,int exec_style,struct ebtables_command_state * cs)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 
parse_iface(char * iface,char * option)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() */
ebt_load_match(const char * name)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 
ebt_load_watcher(const char * name)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 
ebt_load_match_extensions(void)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 
ebt_add_match(struct xtables_match * m,struct ebtables_command_state * cs)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 
ebt_add_watcher(struct xtables_target * watcher,struct ebtables_command_state * cs)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. */
do_commandeb(struct nft_handle * h,int argc,char * argv[],char ** table)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