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 <getopt.h>
25#include <string.h>
26#include <stdio.h>
27#include <stdlib.h>
28#include <inttypes.h>
29#include "include/ebtables_u.h"
30#include "include/ethernetdb.h"
31
32/* Checks whether a command has already been specified */
33#define OPT_COMMANDS (replace->flags & OPT_COMMAND || replace->flags & OPT_ZERO)
34
35#define OPT_COMMAND	0x01
36#define OPT_TABLE	0x02
37#define OPT_IN		0x04
38#define OPT_OUT		0x08
39#define OPT_JUMP	0x10
40#define OPT_PROTOCOL	0x20
41#define OPT_SOURCE	0x40
42#define OPT_DEST	0x80
43#define OPT_ZERO	0x100
44#define OPT_LOGICALIN	0x200
45#define OPT_LOGICALOUT	0x400
46#define OPT_KERNELDATA	0x800 /* This value is also defined in ebtablesd.c */
47#define OPT_COUNT	0x1000 /* This value is also defined in libebtc.c */
48#define OPT_CNT_INCR	0x2000 /* This value is also defined in libebtc.c */
49#define OPT_CNT_DECR	0x4000 /* This value is also defined in libebtc.c */
50
51/* Default command line options. Do not mess around with the already
52 * assigned numbers unless you know what you are doing */
53static struct option ebt_original_options[] =
54{
55	{ "append"         , required_argument, 0, 'A' },
56	{ "insert"         , required_argument, 0, 'I' },
57	{ "delete"         , required_argument, 0, 'D' },
58	{ "list"           , optional_argument, 0, 'L' },
59	{ "Lc"             , no_argument      , 0, 4   },
60	{ "Ln"             , no_argument      , 0, 5   },
61	{ "Lx"             , no_argument      , 0, 6   },
62	{ "Lmac2"          , no_argument      , 0, 12  },
63	{ "zero"           , optional_argument, 0, 'Z' },
64	{ "flush"          , optional_argument, 0, 'F' },
65	{ "policy"         , required_argument, 0, 'P' },
66	{ "in-interface"   , required_argument, 0, 'i' },
67	{ "in-if"          , required_argument, 0, 'i' },
68	{ "logical-in"     , required_argument, 0, 2   },
69	{ "logical-out"    , required_argument, 0, 3   },
70	{ "out-interface"  , required_argument, 0, 'o' },
71	{ "out-if"         , required_argument, 0, 'o' },
72	{ "version"        , no_argument      , 0, 'V' },
73	{ "help"           , no_argument      , 0, 'h' },
74	{ "jump"           , required_argument, 0, 'j' },
75	{ "set-counters"   , required_argument, 0, 'c' },
76	{ "change-counters", required_argument, 0, 'C' },
77	{ "proto"          , required_argument, 0, 'p' },
78	{ "protocol"       , required_argument, 0, 'p' },
79	{ "db"             , required_argument, 0, 'b' },
80	{ "source"         , required_argument, 0, 's' },
81	{ "src"            , required_argument, 0, 's' },
82	{ "destination"    , required_argument, 0, 'd' },
83	{ "dst"            , required_argument, 0, 'd' },
84	{ "table"          , required_argument, 0, 't' },
85	{ "modprobe"       , required_argument, 0, 'M' },
86	{ "new-chain"      , required_argument, 0, 'N' },
87	{ "rename-chain"   , required_argument, 0, 'E' },
88	{ "delete-chain"   , optional_argument, 0, 'X' },
89	{ "atomic-init"    , no_argument      , 0, 7   },
90	{ "atomic-commit"  , no_argument      , 0, 8   },
91	{ "atomic-file"    , required_argument, 0, 9   },
92	{ "atomic-save"    , no_argument      , 0, 10  },
93	{ "init-table"     , no_argument      , 0, 11  },
94	{ 0 }
95};
96
97static struct option *ebt_options = ebt_original_options;
98
99/* Holds all the data */
100static struct ebt_u_replace *replace;
101
102/* The chosen table */
103static struct ebt_u_table *table;
104
105/* The pointers in here are special:
106 * The struct ebt_target pointer is actually a struct ebt_u_target pointer.
107 * I do not feel like using a union.
108 * We need a struct ebt_u_target pointer because we know the address of the data
109 * they point to won't change. We want to allow that the struct ebt_u_target.t
110 * member can change.
111 * The same holds for the struct ebt_match and struct ebt_watcher pointers */
112static struct ebt_u_entry *new_entry;
113
114
115static int global_option_offset;
116#define OPTION_OFFSET 256
117static struct option *merge_options(struct option *oldopts,
118   const struct option *newopts, unsigned int *options_offset)
119{
120	unsigned int num_old, num_new, i;
121	struct option *merge;
122
123	if (!newopts || !oldopts || !options_offset)
124		ebt_print_bug("merge wrong");
125	for (num_old = 0; oldopts[num_old].name; num_old++);
126	for (num_new = 0; newopts[num_new].name; num_new++);
127
128	global_option_offset += OPTION_OFFSET;
129	*options_offset = global_option_offset;
130
131	merge = malloc(sizeof(struct option) * (num_new + num_old + 1));
132	if (!merge)
133		ebt_print_memory();
134	memcpy(merge, oldopts, num_old * sizeof(struct option));
135	for (i = 0; i < num_new; i++) {
136		merge[num_old + i] = newopts[i];
137		merge[num_old + i].val += *options_offset;
138	}
139	memset(merge + num_old + num_new, 0, sizeof(struct option));
140	/* Only free dynamically allocated stuff */
141	if (oldopts != ebt_original_options)
142		free(oldopts);
143
144	return merge;
145}
146
147static void merge_match(struct ebt_u_match *m)
148{
149	ebt_options = merge_options
150	   (ebt_options, m->extra_ops, &(m->option_offset));
151}
152
153static void merge_watcher(struct ebt_u_watcher *w)
154{
155	ebt_options = merge_options
156	   (ebt_options, w->extra_ops, &(w->option_offset));
157}
158
159static void merge_target(struct ebt_u_target *t)
160{
161	ebt_options = merge_options
162	   (ebt_options, t->extra_ops, &(t->option_offset));
163}
164
165/* Be backwards compatible, so don't use '+' in kernel */
166#define IF_WILDCARD 1
167static void print_iface(const char *iface)
168{
169	char *c;
170
171	if ((c = strchr(iface, IF_WILDCARD)))
172		*c = '+';
173	printf("%s ", iface);
174	if (c)
175		*c = IF_WILDCARD;
176}
177
178/* We use replace->flags, so we can't use the following values:
179 * 0x01 == OPT_COMMAND, 0x02 == OPT_TABLE, 0x100 == OPT_ZERO */
180#define LIST_N    0x04
181#define LIST_C    0x08
182#define LIST_X    0x10
183#define LIST_MAC2 0x20
184
185/* Helper function for list_rules() */
186static void list_em(struct ebt_u_entries *entries)
187{
188	int i, j, space = 0, digits;
189	struct ebt_u_entry *hlp;
190	struct ebt_u_match_list *m_l;
191	struct ebt_u_watcher_list *w_l;
192	struct ebt_u_match *m;
193	struct ebt_u_watcher *w;
194	struct ebt_u_target *t;
195
196	if (replace->flags & LIST_MAC2)
197		ebt_printstyle_mac = 2;
198	else
199		ebt_printstyle_mac = 0;
200	hlp = entries->entries->next;
201	if (replace->flags & LIST_X && entries->policy != EBT_ACCEPT) {
202		printf("ebtables -t %s -P %s %s\n", replace->name,
203		   entries->name, ebt_standard_targets[-entries->policy - 1]);
204	} else if (!(replace->flags & LIST_X)) {
205		printf("\nBridge chain: %s, entries: %d, policy: %s\n",
206		   entries->name, entries->nentries,
207		   ebt_standard_targets[-entries->policy - 1]);
208	}
209
210	if (replace->flags & LIST_N) {
211		i = entries->nentries;
212		while (i > 9) {
213			space++;
214			i /= 10;
215		}
216	}
217
218	for (i = 0; i < entries->nentries; i++) {
219		if (replace->flags & LIST_N) {
220			digits = 0;
221			/* A little work to get nice rule numbers. */
222			j = i + 1;
223			while (j > 9) {
224				digits++;
225				j /= 10;
226			}
227			for (j = 0; j < space - digits; j++)
228				printf(" ");
229			printf("%d. ", i + 1);
230		}
231		if (replace->flags & LIST_X)
232			printf("ebtables -t %s -A %s ",
233			   replace->name, entries->name);
234
235		/* The standard target's print() uses this to find out
236		 * the name of a udc */
237		hlp->replace = replace;
238
239		/* Don't print anything about the protocol if no protocol was
240		 * specified, obviously this means any protocol will do. */
241		if (!(hlp->bitmask & EBT_NOPROTO)) {
242			printf("-p ");
243			if (hlp->invflags & EBT_IPROTO)
244				printf("! ");
245			if (hlp->bitmask & EBT_802_3)
246				printf("Length ");
247			else {
248				struct ethertypeent *ent;
249
250				ent = getethertypebynumber(ntohs(hlp->ethproto));
251				if (!ent)
252					printf("0x%x ", ntohs(hlp->ethproto));
253				else
254					printf("%s ", ent->e_name);
255			}
256		}
257		if (hlp->bitmask & EBT_SOURCEMAC) {
258			printf("-s ");
259			if (hlp->invflags & EBT_ISOURCE)
260				printf("! ");
261			ebt_print_mac_and_mask(hlp->sourcemac, hlp->sourcemsk);
262			printf(" ");
263		}
264		if (hlp->bitmask & EBT_DESTMAC) {
265			printf("-d ");
266			if (hlp->invflags & EBT_IDEST)
267				printf("! ");
268			ebt_print_mac_and_mask(hlp->destmac, hlp->destmsk);
269			printf(" ");
270		}
271		if (hlp->in[0] != '\0') {
272			printf("-i ");
273			if (hlp->invflags & EBT_IIN)
274				printf("! ");
275			print_iface(hlp->in);
276		}
277		if (hlp->logical_in[0] != '\0') {
278			printf("--logical-in ");
279			if (hlp->invflags & EBT_ILOGICALIN)
280				printf("! ");
281			print_iface(hlp->logical_in);
282		}
283		if (hlp->logical_out[0] != '\0') {
284			printf("--logical-out ");
285			if (hlp->invflags & EBT_ILOGICALOUT)
286				printf("! ");
287			print_iface(hlp->logical_out);
288		}
289		if (hlp->out[0] != '\0') {
290			printf("-o ");
291			if (hlp->invflags & EBT_IOUT)
292				printf("! ");
293			print_iface(hlp->out);
294		}
295
296		m_l = hlp->m_list;
297		while (m_l) {
298			m = ebt_find_match(m_l->m->u.name);
299			if (!m)
300				ebt_print_bug("Match not found");
301			m->print(hlp, m_l->m);
302			m_l = m_l->next;
303		}
304		w_l = hlp->w_list;
305		while (w_l) {
306			w = ebt_find_watcher(w_l->w->u.name);
307			if (!w)
308				ebt_print_bug("Watcher not found");
309			w->print(hlp, w_l->w);
310			w_l = w_l->next;
311		}
312
313		printf("-j ");
314		if (strcmp(hlp->t->u.name, EBT_STANDARD_TARGET))
315			printf("%s ", hlp->t->u.name);
316		t = ebt_find_target(hlp->t->u.name);
317		if (!t)
318			ebt_print_bug("Target '%s' not found", hlp->t->u.name);
319		t->print(hlp, hlp->t);
320		if (replace->flags & LIST_C) {
321			uint64_t pcnt = hlp->cnt.pcnt;
322			uint64_t bcnt = hlp->cnt.bcnt;
323
324			if (replace->flags & LIST_X)
325				printf("-c %llu %llu", pcnt, bcnt);
326			else
327				printf(", pcnt = %"PRIu64" -- bcnt = %"PRIu64, pcnt, bcnt);
328		}
329		printf("\n");
330		hlp = hlp->next;
331	}
332}
333
334static void print_help()
335{
336	struct ebt_u_match_list *m_l;
337	struct ebt_u_watcher_list *w_l;
338
339	PRINT_VERSION;
340	printf(
341"Usage:\n"
342"ebtables -[ADI] chain rule-specification [options]\n"
343"ebtables -P chain target\n"
344"ebtables -[LFZ] [chain]\n"
345"ebtables -[NX] [chain]\n"
346"ebtables -E old-chain-name new-chain-name\n\n"
347"Commands:\n"
348"--append -A chain             : append to chain\n"
349"--delete -D chain             : delete matching rule from chain\n"
350"--delete -D chain rulenum     : delete rule at position rulenum from chain\n"
351"--change-counters -C chain\n"
352"          [rulenum] pcnt bcnt : change counters of existing rule\n"
353"--insert -I chain rulenum     : insert rule at position rulenum in chain\n"
354"--list   -L [chain]           : list the rules in a chain or in all chains\n"
355"--flush  -F [chain]           : delete all rules in chain or in all chains\n"
356"--init-table                  : replace the kernel table with the initial table\n"
357"--zero   -Z [chain]           : put counters on zero in chain or in all chains\n"
358"--policy -P chain target      : change policy on chain to target\n"
359"--new-chain -N chain          : create a user defined chain\n"
360"--rename-chain -E old new     : rename a chain\n"
361"--delete-chain -X [chain]     : delete a user defined chain\n"
362"--atomic-commit               : update the kernel w/t table contained in <FILE>\n"
363"--atomic-init                 : put the initial kernel table into <FILE>\n"
364"--atomic-save                 : put the current kernel table into <FILE>\n"
365"--atomic-file file            : set <FILE> to file\n\n"
366"Options:\n"
367"--proto  -p [!] proto         : protocol hexadecimal, by name or LENGTH\n"
368"--src    -s [!] address[/mask]: source mac address\n"
369"--dst    -d [!] address[/mask]: destination mac address\n"
370"--in-if  -i [!] name[+]       : network input interface name\n"
371"--out-if -o [!] name[+]       : network output interface name\n"
372"--logical-in  [!] name[+]     : logical bridge input interface name\n"
373"--logical-out [!] name[+]     : logical bridge output interface name\n"
374"--set-counters -c chain\n"
375"          pcnt bcnt           : set the counters of the to be added rule\n"
376"--modprobe -M program         : try to insert modules using this program\n"
377"--version -V                  : print package version\n\n"
378"Environment variable:\n"
379ATOMIC_ENV_VARIABLE "          : if set <FILE> (see above) will equal its value"
380"\n\n");
381	m_l = new_entry->m_list;
382	while (m_l) {
383		((struct ebt_u_match *)m_l->m)->help();
384		printf("\n");
385		m_l = m_l->next;
386	}
387	w_l = new_entry->w_list;
388	while (w_l) {
389		((struct ebt_u_watcher *)w_l->w)->help();
390		printf("\n");
391		w_l = w_l->next;
392	}
393	((struct ebt_u_target *)new_entry->t)->help();
394	printf("\n");
395	if (table->help)
396		table->help(ebt_hooknames);
397}
398
399/* Execute command L */
400static void list_rules()
401{
402	int i;
403
404	if (!(replace->flags & LIST_X))
405		printf("Bridge table: %s\n", table->name);
406	if (replace->selected_chain != -1)
407		list_em(ebt_to_chain(replace));
408	else {
409		/* Create new chains and rename standard chains when necessary */
410		if (replace->flags & LIST_X && replace->num_chains > NF_BR_NUMHOOKS) {
411			for (i = NF_BR_NUMHOOKS; i < replace->num_chains; i++)
412				printf("ebtables -t %s -N %s\n", replace->name, replace->chains[i]->name);
413			for (i = 0; i < NF_BR_NUMHOOKS; i++)
414				if (replace->chains[i] && strcmp(replace->chains[i]->name, ebt_hooknames[i]))
415					printf("ebtables -t %s -E %s %s\n", replace->name, ebt_hooknames[i], replace->chains[i]->name);
416		}
417		for (i = 0; i < replace->num_chains; i++)
418			if (replace->chains[i])
419				list_em(replace->chains[i]);
420	}
421}
422
423static int parse_rule_range(const char *argv, int *rule_nr, int *rule_nr_end)
424{
425	char *colon = strchr(argv, ':'), *buffer;
426
427	if (colon) {
428		*colon = '\0';
429		if (*(colon + 1) == '\0')
430			*rule_nr_end = -1; /* Until the last rule */
431		else {
432			*rule_nr_end = strtol(colon + 1, &buffer, 10);
433			if (*buffer != '\0' || *rule_nr_end == 0)
434				return -1;
435		}
436	}
437	if (colon == argv)
438		*rule_nr = 1; /* Beginning with the first rule */
439	else {
440		*rule_nr = strtol(argv, &buffer, 10);
441		if (*buffer != '\0' || *rule_nr == 0)
442			return -1;
443	}
444	if (!colon)
445		*rule_nr_end = *rule_nr;
446	return 0;
447}
448
449/* Incrementing or decrementing rules in daemon mode is not supported as the
450 * involved code overload is not worth it (too annoying to take the increased
451 * counters in the kernel into account). */
452static int parse_change_counters_rule(int argc, char **argv, int *rule_nr, int *rule_nr_end, int exec_style)
453{
454	char *buffer;
455	int ret = 0;
456
457	if (optind + 1 >= argc || (argv[optind][0] == '-' && (argv[optind][1] < '0' || argv[optind][1] > '9')) ||
458	    (argv[optind + 1][0] == '-' && (argv[optind + 1][1] < '0'  && argv[optind + 1][1] > '9')))
459		ebt_print_error2("The command -C needs at least 2 arguments");
460	if (optind + 2 < argc && (argv[optind + 2][0] != '-' || (argv[optind + 2][1] >= '0' && argv[optind + 2][1] <= '9'))) {
461		if (optind + 3 != argc)
462			ebt_print_error2("No extra options allowed with -C start_nr[:end_nr] pcnt bcnt");
463		if (parse_rule_range(argv[optind], rule_nr, rule_nr_end))
464			ebt_print_error2("Something is wrong with the rule number specification '%s'", argv[optind]);
465		optind++;
466	}
467
468	if (argv[optind][0] == '+') {
469		if (exec_style == EXEC_STYLE_DAEMON)
470daemon_incr:
471			ebt_print_error2("Incrementing rule counters (%s) not allowed in daemon mode", argv[optind]);
472		ret += 1;
473		new_entry->cnt_surplus.pcnt = strtoull(argv[optind] + 1, &buffer, 10);
474	} else if (argv[optind][0] == '-') {
475		if (exec_style == EXEC_STYLE_DAEMON)
476daemon_decr:
477			ebt_print_error2("Decrementing rule counters (%s) not allowed in daemon mode", argv[optind]);
478		ret += 2;
479		new_entry->cnt_surplus.pcnt = strtoull(argv[optind] + 1, &buffer, 10);
480	} else
481		new_entry->cnt_surplus.pcnt = strtoull(argv[optind], &buffer, 10);
482
483	if (*buffer != '\0')
484		goto invalid;
485	optind++;
486	if (argv[optind][0] == '+') {
487		if (exec_style == EXEC_STYLE_DAEMON)
488			goto daemon_incr;
489		ret += 3;
490		new_entry->cnt_surplus.bcnt = strtoull(argv[optind] + 1, &buffer, 10);
491	} else if (argv[optind][0] == '-') {
492		if (exec_style == EXEC_STYLE_DAEMON)
493			goto daemon_decr;
494		ret += 6;
495		new_entry->cnt_surplus.bcnt = strtoull(argv[optind] + 1, &buffer, 10);
496	} else
497		new_entry->cnt_surplus.bcnt = strtoull(argv[optind], &buffer, 10);
498
499	if (*buffer != '\0')
500		goto invalid;
501	optind++;
502	return ret;
503invalid:
504	ebt_print_error2("Packet counter '%s' invalid", argv[optind]);
505}
506
507static int parse_iface(char *iface, char *option)
508{
509	char *c;
510
511	if ((c = strchr(iface, '+'))) {
512		if (*(c + 1) != '\0') {
513			ebt_print_error("Spurious characters after '+' wildcard for '%s'", option);
514			return -1;
515		} else
516			*c = IF_WILDCARD;
517	}
518	return 0;
519}
520
521void ebt_early_init_once()
522{
523	ebt_iterate_matches(merge_match);
524	ebt_iterate_watchers(merge_watcher);
525	ebt_iterate_targets(merge_target);
526}
527
528/* We use exec_style instead of #ifdef's because ebtables.so is a shared object. */
529int do_command(int argc, char *argv[], int exec_style,
530               struct ebt_u_replace *replace_)
531{
532	char *buffer;
533	int c, i;
534	int zerochain = -1; /* Needed for the -Z option (we can have -Z <this> -L <that>) */
535	int chcounter; /* Needed for -C */
536	int policy = 0;
537	int rule_nr = 0;
538	int rule_nr_end = 0;
539	struct ebt_u_target *t;
540	struct ebt_u_match *m;
541	struct ebt_u_watcher *w;
542	struct ebt_u_match_list *m_l;
543	struct ebt_u_watcher_list *w_l;
544	struct ebt_u_entries *entries;
545
546	opterr = 0;
547	ebt_modprobe = NULL;
548
549	replace = replace_;
550
551	/* The daemon doesn't use the environment variable */
552	if (exec_style == EXEC_STYLE_PRG) {
553		buffer = getenv(ATOMIC_ENV_VARIABLE);
554		if (buffer) {
555			replace->filename = malloc(strlen(buffer) + 1);
556			if (!replace->filename)
557				ebt_print_memory();
558			strcpy(replace->filename, buffer);
559			buffer = NULL;
560		}
561	}
562
563	replace->flags &= OPT_KERNELDATA; /* ebtablesd needs OPT_KERNELDATA */
564	replace->selected_chain = -1;
565	replace->command = 'h';
566
567	if (!new_entry) {
568		new_entry = (struct ebt_u_entry *)malloc(sizeof(struct ebt_u_entry));
569		if (!new_entry)
570			ebt_print_memory();
571	}
572	/* Put some sane values in our new entry */
573	ebt_initialize_entry(new_entry);
574	new_entry->replace = replace;
575
576	/* The scenario induced by this loop makes that:
577	 * '-t'  ,'-M' and --atomic (if specified) have to come
578	 * before '-A' and the like */
579
580	/* Getopt saves the day */
581	while ((c = getopt_long(argc, argv,
582	   "-A:D:C:I:N:E:X::L::Z::F::P:Vhi:o:j:c:p:s:d:t:M:", ebt_options, NULL)) != -1) {
583		switch (c) {
584
585		case 'A': /* Add a rule */
586		case 'D': /* Delete a rule */
587		case 'C': /* Change counters */
588		case 'P': /* Define policy */
589		case 'I': /* Insert a rule */
590		case 'N': /* Make a user defined chain */
591		case 'E': /* Rename chain */
592		case 'X': /* Delete chain */
593			/* We allow -N chainname -P policy */
594			if (replace->command == 'N' && c == 'P') {
595				replace->command = c;
596				optind--; /* No table specified */
597				goto handle_P;
598			}
599			if (OPT_COMMANDS)
600				ebt_print_error2("Multiple commands are not allowed");
601
602			replace->command = c;
603			replace->flags |= OPT_COMMAND;
604			if (!(replace->flags & OPT_KERNELDATA))
605				ebt_get_kernel_table(replace, 0);
606			if (optarg && (optarg[0] == '-' || !strcmp(optarg, "!")))
607				ebt_print_error2("No chain name specified");
608			if (c == 'N') {
609				if (ebt_get_chainnr(replace, optarg) != -1)
610					ebt_print_error2("Chain %s already exists", optarg);
611				else if (ebt_find_target(optarg))
612					ebt_print_error2("Target with name %s exists", optarg);
613				else if (strlen(optarg) >= EBT_CHAIN_MAXNAMELEN)
614					ebt_print_error2("Chain name length can't exceed %d",
615							EBT_CHAIN_MAXNAMELEN - 1);
616				else if (strchr(optarg, ' ') != NULL)
617					ebt_print_error2("Use of ' ' not allowed in chain names");
618				ebt_new_chain(replace, optarg, EBT_ACCEPT);
619				/* This is needed to get -N x -P y working */
620				replace->selected_chain = ebt_get_chainnr(replace, optarg);
621				break;
622			} else if (c == 'X') {
623				if (optind >= argc) {
624					replace->selected_chain = -1;
625					ebt_delete_chain(replace);
626					break;
627				}
628
629				if (optind < argc - 1)
630					ebt_print_error2("No extra options allowed with -X");
631
632				if ((replace->selected_chain = ebt_get_chainnr(replace, argv[optind])) == -1)
633					ebt_print_error2("Chain '%s' doesn't exist", argv[optind]);
634				ebt_delete_chain(replace);
635				if (ebt_errormsg[0] != '\0')
636					return -1;
637				optind++;
638				break;
639			}
640
641			if ((replace->selected_chain = ebt_get_chainnr(replace, optarg)) == -1)
642				ebt_print_error2("Chain '%s' doesn't exist", optarg);
643			if (c == 'E') {
644				if (optind >= argc)
645					ebt_print_error2("No new chain name specified");
646				else if (optind < argc - 1)
647					ebt_print_error2("No extra options allowed with -E");
648				else if (strlen(argv[optind]) >= EBT_CHAIN_MAXNAMELEN)
649					ebt_print_error2("Chain name length can't exceed %d characters", EBT_CHAIN_MAXNAMELEN - 1);
650				else if (ebt_get_chainnr(replace, argv[optind]) != -1)
651					ebt_print_error2("Chain '%s' already exists", argv[optind]);
652				else if (ebt_find_target(argv[optind]))
653					ebt_print_error2("Target with name '%s' exists", argv[optind]);
654				else if (strchr(argv[optind], ' ') != NULL)
655					ebt_print_error2("Use of ' ' not allowed in chain names");
656				ebt_rename_chain(replace, argv[optind]);
657				optind++;
658				break;
659			} else if (c == 'D' && optind < argc && (argv[optind][0] != '-' || (argv[optind][1] >= '0' && argv[optind][1] <= '9'))) {
660				if (optind != argc - 1)
661					ebt_print_error2("No extra options allowed with -D start_nr[:end_nr]");
662				if (parse_rule_range(argv[optind], &rule_nr, &rule_nr_end))
663					ebt_print_error2("Problem with the specified rule number(s) '%s'", argv[optind]);
664				optind++;
665			} else if (c == 'C') {
666				if ((chcounter = parse_change_counters_rule(argc, argv, &rule_nr, &rule_nr_end, exec_style)) == -1)
667					return -1;
668			} else if (c == 'I') {
669				if (optind >= argc || (argv[optind][0] == '-' && (argv[optind][1] < '0' || argv[optind][1] > '9')))
670					rule_nr = 1;
671				else {
672					rule_nr = strtol(argv[optind], &buffer, 10);
673					if (*buffer != '\0')
674						ebt_print_error2("Problem with the specified rule number '%s'", argv[optind]);
675					optind++;
676				}
677			} else if (c == 'P') {
678handle_P:
679				if (optind >= argc)
680					ebt_print_error2("No policy specified");
681				for (i = 0; i < NUM_STANDARD_TARGETS; i++)
682					if (!strcmp(argv[optind], ebt_standard_targets[i])) {
683						policy = -i -1;
684						if (policy == EBT_CONTINUE)
685							ebt_print_error2("Wrong policy '%s'", argv[optind]);
686						break;
687					}
688				if (i == NUM_STANDARD_TARGETS)
689					ebt_print_error2("Unknown policy '%s'", argv[optind]);
690				optind++;
691			}
692			break;
693		case 'L': /* List */
694		case 'F': /* Flush */
695		case 'Z': /* Zero counters */
696			if (c == 'Z') {
697				if ((replace->flags & OPT_ZERO) || (replace->flags & OPT_COMMAND && replace->command != 'L'))
698print_zero:
699					ebt_print_error2("Command -Z only allowed together with command -L");
700				replace->flags |= OPT_ZERO;
701			} else {
702				if (replace->flags & OPT_COMMAND)
703					ebt_print_error2("Multiple commands are not allowed");
704				replace->command = c;
705				replace->flags |= OPT_COMMAND;
706				if (replace->flags & OPT_ZERO && c != 'L')
707					goto print_zero;
708			}
709
710#ifdef SILENT_DAEMON
711			if (c== 'L' && exec_style == EXEC_STYLE_DAEMON)
712				ebt_print_error2("-L not supported in daemon mode");
713#endif
714
715			if (!(replace->flags & OPT_KERNELDATA))
716				ebt_get_kernel_table(replace, 0);
717			i = -1;
718			if (optind < argc && argv[optind][0] != '-') {
719				if ((i = ebt_get_chainnr(replace, argv[optind])) == -1)
720					ebt_print_error2("Chain '%s' doesn't exist", argv[optind]);
721				optind++;
722			}
723			if (i != -1) {
724				if (c == 'Z')
725					zerochain = i;
726				else
727					replace->selected_chain = i;
728			}
729			break;
730		case 'V': /* Version */
731			if (OPT_COMMANDS)
732				ebt_print_error2("Multiple commands are not allowed");
733			replace->command = 'V';
734			if (exec_style == EXEC_STYLE_DAEMON)
735				ebt_print_error2(PROGNAME" v"PROGVERSION" ("PROGDATE")\n");
736			PRINT_VERSION;
737			exit(0);
738		case 'M': /* Modprobe */
739			if (OPT_COMMANDS)
740				ebt_print_error2("Please put the -M option earlier");
741			free(ebt_modprobe);
742			ebt_modprobe = optarg;
743			break;
744		case 'h': /* Help */
745#ifdef SILENT_DAEMON
746			if (exec_style == EXEC_STYLE_DAEMON)
747				ebt_print_error2("-h not supported in daemon mode");
748#endif
749			if (OPT_COMMANDS)
750				ebt_print_error2("Multiple commands are not allowed");
751			replace->command = 'h';
752
753			/* All other arguments should be extension names */
754			while (optind < argc) {
755				struct ebt_u_match *m;
756				struct ebt_u_watcher *w;
757
758				if (!strcasecmp("list_extensions", argv[optind])) {
759					ebt_list_extensions();
760					exit(0);
761				}
762				if ((m = ebt_find_match(argv[optind])))
763					ebt_add_match(new_entry, m);
764				else if ((w = ebt_find_watcher(argv[optind])))
765					ebt_add_watcher(new_entry, w);
766				else {
767					if (!(t = ebt_find_target(argv[optind])))
768						ebt_print_error2("Extension '%s' not found", argv[optind]);
769					if (replace->flags & OPT_JUMP)
770						ebt_print_error2("Sorry, you can only see help for one target extension at a time");
771					replace->flags |= OPT_JUMP;
772					new_entry->t = (struct ebt_entry_target *)t;
773				}
774				optind++;
775			}
776			break;
777		case 't': /* Table */
778			if (OPT_COMMANDS)
779				ebt_print_error2("Please put the -t option first");
780			ebt_check_option2(&(replace->flags), OPT_TABLE);
781			if (strlen(optarg) > EBT_TABLE_MAXNAMELEN - 1)
782				ebt_print_error2("Table name length cannot exceed %d characters", EBT_TABLE_MAXNAMELEN - 1);
783			strcpy(replace->name, optarg);
784			break;
785		case 'i': /* Input interface */
786		case 2  : /* Logical input interface */
787		case 'o': /* Output interface */
788		case 3  : /* Logical output interface */
789		case 'j': /* Target */
790		case 'p': /* Net family protocol */
791		case 's': /* Source mac */
792		case 'd': /* Destination mac */
793		case 'c': /* Set counters */
794			if (!OPT_COMMANDS)
795				ebt_print_error2("No command specified");
796			if (replace->command != 'A' && replace->command != 'D' && replace->command != 'I' && replace->command != 'C')
797				ebt_print_error2("Command and option do not match");
798			if (c == 'i') {
799				ebt_check_option2(&(replace->flags), OPT_IN);
800				if (replace->selected_chain > 2 && replace->selected_chain < NF_BR_BROUTING)
801					ebt_print_error2("Use -i only in INPUT, FORWARD, PREROUTING and BROUTING chains");
802				if (ebt_check_inverse2(optarg))
803					new_entry->invflags |= EBT_IIN;
804
805				if (strlen(optarg) >= IFNAMSIZ)
806big_iface_length:
807					ebt_print_error2("Interface name length cannot exceed %d characters", IFNAMSIZ - 1);
808				strcpy(new_entry->in, optarg);
809				if (parse_iface(new_entry->in, "-i"))
810					return -1;
811				break;
812			} else if (c == 2) {
813				ebt_check_option2(&(replace->flags), OPT_LOGICALIN);
814				if (replace->selected_chain > 2 && replace->selected_chain < NF_BR_BROUTING)
815					ebt_print_error2("Use --logical-in only in INPUT, FORWARD, PREROUTING and BROUTING chains");
816				if (ebt_check_inverse2(optarg))
817					new_entry->invflags |= EBT_ILOGICALIN;
818
819				if (strlen(optarg) >= IFNAMSIZ)
820					goto big_iface_length;
821				strcpy(new_entry->logical_in, optarg);
822				if (parse_iface(new_entry->logical_in, "--logical-in"))
823					return -1;
824				break;
825			} else if (c == 'o') {
826				ebt_check_option2(&(replace->flags), OPT_OUT);
827				if (replace->selected_chain < 2 || replace->selected_chain == NF_BR_BROUTING)
828					ebt_print_error2("Use -o only in OUTPUT, FORWARD and POSTROUTING chains");
829				if (ebt_check_inverse2(optarg))
830					new_entry->invflags |= EBT_IOUT;
831
832				if (strlen(optarg) >= IFNAMSIZ)
833					goto big_iface_length;
834				strcpy(new_entry->out, optarg);
835				if (parse_iface(new_entry->out, "-o"))
836					return -1;
837				break;
838			} else if (c == 3) {
839				ebt_check_option2(&(replace->flags), OPT_LOGICALOUT);
840				if (replace->selected_chain < 2 || replace->selected_chain == NF_BR_BROUTING)
841					ebt_print_error2("Use --logical-out only in OUTPUT, FORWARD and POSTROUTING chains");
842				if (ebt_check_inverse2(optarg))
843					new_entry->invflags |= EBT_ILOGICALOUT;
844
845				if (strlen(optarg) >= IFNAMSIZ)
846					goto big_iface_length;
847				strcpy(new_entry->logical_out, optarg);
848				if (parse_iface(new_entry->logical_out, "--logical-out"))
849					return -1;
850				break;
851			} else if (c == 'j') {
852				ebt_check_option2(&(replace->flags), OPT_JUMP);
853				for (i = 0; i < NUM_STANDARD_TARGETS; i++)
854					if (!strcmp(optarg, ebt_standard_targets[i])) {
855						t = ebt_find_target(EBT_STANDARD_TARGET);
856						((struct ebt_standard_target *) t->t)->verdict = -i - 1;
857						break;
858					}
859				if (-i - 1 == EBT_RETURN && replace->selected_chain < NF_BR_NUMHOOKS) {
860					ebt_print_error2("Return target only for user defined chains");
861				} else if (i != NUM_STANDARD_TARGETS)
862					break;
863
864				if ((i = ebt_get_chainnr(replace, optarg)) != -1) {
865					if (i < NF_BR_NUMHOOKS)
866						ebt_print_error2("Don't jump to a standard chain");
867					t = ebt_find_target(EBT_STANDARD_TARGET);
868					((struct ebt_standard_target *) t->t)->verdict = i - NF_BR_NUMHOOKS;
869					break;
870				} else {
871					/* Must be an extension then */
872					struct ebt_u_target *t;
873
874					t = ebt_find_target(optarg);
875					/* -j standard not allowed either */
876					if (!t || t == (struct ebt_u_target *)new_entry->t)
877						ebt_print_error2("Illegal target name '%s'", optarg);
878					new_entry->t = (struct ebt_entry_target *)t;
879					ebt_find_target(EBT_STANDARD_TARGET)->used = 0;
880					t->used = 1;
881				}
882				break;
883			} else if (c == 's') {
884				ebt_check_option2(&(replace->flags), OPT_SOURCE);
885				if (ebt_check_inverse2(optarg))
886					new_entry->invflags |= EBT_ISOURCE;
887
888				if (ebt_get_mac_and_mask(optarg, new_entry->sourcemac, new_entry->sourcemsk))
889					ebt_print_error2("Problem with specified source mac '%s'", optarg);
890				new_entry->bitmask |= EBT_SOURCEMAC;
891				break;
892			} else if (c == 'd') {
893				ebt_check_option2(&(replace->flags), OPT_DEST);
894				if (ebt_check_inverse2(optarg))
895					new_entry->invflags |= EBT_IDEST;
896
897				if (ebt_get_mac_and_mask(optarg, new_entry->destmac, new_entry->destmsk))
898					ebt_print_error2("Problem with specified destination mac '%s'", optarg);
899				new_entry->bitmask |= EBT_DESTMAC;
900				break;
901			} else if (c == 'c') {
902				ebt_check_option2(&(replace->flags), OPT_COUNT);
903				if (ebt_check_inverse2(optarg))
904					ebt_print_error2("Unexpected '!' after -c");
905				if (optind >= argc || optarg[0] == '-' || argv[optind][0] == '-')
906					ebt_print_error2("Option -c needs 2 arguments");
907
908				new_entry->cnt.pcnt = strtoull(optarg, &buffer, 10);
909				if (*buffer != '\0')
910					ebt_print_error2("Packet counter '%s' invalid", optarg);
911				new_entry->cnt.bcnt = strtoull(argv[optind], &buffer, 10);
912				if (*buffer != '\0')
913					ebt_print_error2("Packet counter '%s' invalid", argv[optind]);
914				optind++;
915				break;
916			}
917			ebt_check_option2(&(replace->flags), OPT_PROTOCOL);
918			if (ebt_check_inverse2(optarg))
919				new_entry->invflags |= EBT_IPROTO;
920
921			new_entry->bitmask &= ~((unsigned int)EBT_NOPROTO);
922			i = strtol(optarg, &buffer, 16);
923			if (*buffer == '\0' && (i < 0 || i > 0xFFFF))
924				ebt_print_error2("Problem with the specified protocol");
925			if (*buffer != '\0') {
926				struct ethertypeent *ent;
927
928				if (!strcasecmp(optarg, "LENGTH")) {
929					new_entry->bitmask |= EBT_802_3;
930					break;
931				}
932				ent = getethertypebyname(optarg);
933				if (!ent)
934					ebt_print_error2("Problem with the specified Ethernet protocol '%s', perhaps "_PATH_ETHERTYPES " is missing", optarg);
935				new_entry->ethproto = ent->e_ethertype;
936			} else
937				new_entry->ethproto = i;
938
939			if (new_entry->ethproto < 0x0600)
940				ebt_print_error2("Sorry, protocols have values above or equal to 0x0600");
941			break;
942		case 4  : /* Lc */
943#ifdef SILENT_DAEMON
944			if (exec_style == EXEC_STYLE_DAEMON)
945				ebt_print_error2("--Lc is not supported in daemon mode");
946#endif
947			ebt_check_option2(&(replace->flags), LIST_C);
948			if (replace->command != 'L')
949				ebt_print_error("Use --Lc with -L");
950			replace->flags |= LIST_C;
951			break;
952		case 5  : /* Ln */
953#ifdef SILENT_DAEMON
954			if (exec_style == EXEC_STYLE_DAEMON)
955				ebt_print_error2("--Ln is not supported in daemon mode");
956#endif
957			ebt_check_option2(&(replace->flags), LIST_N);
958			if (replace->command != 'L')
959				ebt_print_error2("Use --Ln with -L");
960			if (replace->flags & LIST_X)
961				ebt_print_error2("--Lx is not compatible with --Ln");
962			replace->flags |= LIST_N;
963			break;
964		case 6  : /* Lx */
965#ifdef SILENT_DAEMON
966			if (exec_style == EXEC_STYLE_DAEMON)
967				ebt_print_error2("--Lx is not supported in daemon mode");
968#endif
969			ebt_check_option2(&(replace->flags), LIST_X);
970			if (replace->command != 'L')
971				ebt_print_error2("Use --Lx with -L");
972			if (replace->flags & LIST_N)
973				ebt_print_error2("--Lx is not compatible with --Ln");
974			replace->flags |= LIST_X;
975			break;
976		case 12 : /* Lmac2 */
977#ifdef SILENT_DAEMON
978			if (exec_style == EXEC_STYLE_DAEMON)
979				ebt_print_error("--Lmac2 is not supported in daemon mode");
980#endif
981			ebt_check_option2(&(replace->flags), LIST_MAC2);
982			if (replace->command != 'L')
983				ebt_print_error2("Use --Lmac2 with -L");
984			replace->flags |= LIST_MAC2;
985			break;
986		case 8 : /* atomic-commit */
987			if (exec_style == EXEC_STYLE_DAEMON)
988				ebt_print_error2("--atomic-commit is not supported in daemon mode");
989			replace->command = c;
990			if (OPT_COMMANDS)
991				ebt_print_error2("Multiple commands are not allowed");
992			replace->flags |= OPT_COMMAND;
993			if (!replace->filename)
994				ebt_print_error2("No atomic file specified");
995			/* Get the information from the file */
996			ebt_get_table(replace, 0);
997			/* We don't want the kernel giving us its counters,
998			 * they would overwrite the counters extracted from
999			 * the file */
1000			replace->num_counters = 0;
1001			/* Make sure the table will be written to the kernel */
1002			free(replace->filename);
1003			replace->filename = NULL;
1004			break;
1005		case 7 : /* atomic-init */
1006		case 10: /* atomic-save */
1007		case 11: /* init-table */
1008			if (exec_style == EXEC_STYLE_DAEMON) {
1009				if (c == 7) {
1010					ebt_print_error2("--atomic-init is not supported in daemon mode");
1011				} else if (c == 10)
1012					ebt_print_error2("--atomic-save is not supported in daemon mode");
1013				ebt_print_error2("--init-table is not supported in daemon mode");
1014			}
1015			replace->command = c;
1016			if (OPT_COMMANDS)
1017				ebt_print_error2("Multiple commands are not allowed");
1018			if (c != 11 && !replace->filename)
1019				ebt_print_error2("No atomic file specified");
1020			replace->flags |= OPT_COMMAND;
1021			{
1022				char *tmp = replace->filename;
1023
1024				/* Get the kernel table */
1025				replace->filename = NULL;
1026				ebt_get_kernel_table(replace, c == 10 ? 0 : 1);
1027				replace->filename = tmp;
1028			}
1029			break;
1030		case 9 : /* atomic */
1031			if (exec_style == EXEC_STYLE_DAEMON)
1032				ebt_print_error2("--atomic is not supported in daemon mode");
1033			if (OPT_COMMANDS)
1034				ebt_print_error2("--atomic has to come before the command");
1035			/* A possible memory leak here, but this is not
1036			 * executed in daemon mode */
1037			replace->filename = (char *)malloc(strlen(optarg) + 1);
1038			strcpy(replace->filename, optarg);
1039			break;
1040		case 1 :
1041			if (!strcmp(optarg, "!"))
1042				ebt_check_inverse2(optarg);
1043			else
1044				ebt_print_error2("Bad argument : '%s'", optarg);
1045			/* ebt_check_inverse() did optind++ */
1046			optind--;
1047			continue;
1048		default:
1049			/* Is it a target option? */
1050			t = (struct ebt_u_target *)new_entry->t;
1051			if ((t->parse(c - t->option_offset, argv, argc, new_entry, &t->flags, &t->t))) {
1052				if (ebt_errormsg[0] != '\0')
1053					return -1;
1054				goto check_extension;
1055			}
1056
1057			/* Is it a match_option? */
1058			for (m = ebt_matches; m; m = m->next)
1059				if (m->parse(c - m->option_offset, argv, argc, new_entry, &m->flags, &m->m))
1060					break;
1061
1062			if (m != NULL) {
1063				if (ebt_errormsg[0] != '\0')
1064					return -1;
1065				if (m->used == 0) {
1066					ebt_add_match(new_entry, m);
1067					m->used = 1;
1068				}
1069				goto check_extension;
1070			}
1071
1072			/* Is it a watcher option? */
1073			for (w = ebt_watchers; w; w = w->next)
1074				if (w->parse(c - w->option_offset, argv, argc, new_entry, &w->flags, &w->w))
1075					break;
1076
1077			if (w == NULL && c == '?')
1078				ebt_print_error2("Unknown argument: '%s'", argv[optind - 1], (char)optopt, (char)c);
1079			else if (w == NULL) {
1080				if (!strcmp(t->name, "standard"))
1081					ebt_print_error2("Unknown argument: don't forget the -t option");
1082				else
1083					ebt_print_error2("Target-specific option does not correspond with specified target");
1084			}
1085			if (ebt_errormsg[0] != '\0')
1086				return -1;
1087			if (w->used == 0) {
1088				ebt_add_watcher(new_entry, w);
1089				w->used = 1;
1090			}
1091check_extension:
1092			if (replace->command != 'A' && replace->command != 'I' &&
1093			    replace->command != 'D' && replace->command != 'C')
1094				ebt_print_error2("Extensions only for -A, -I, -D and -C");
1095		}
1096		ebt_invert = 0;
1097	}
1098
1099	/* Just in case we didn't catch an error */
1100	if (ebt_errormsg[0] != '\0')
1101		return -1;
1102
1103	if (!(table = ebt_find_table(replace->name)))
1104		ebt_print_error2("Bad table name");
1105
1106	if (replace->command == 'h' && !(replace->flags & OPT_ZERO)) {
1107		print_help();
1108		if (exec_style == EXEC_STYLE_PRG)
1109			exit(0);
1110	}
1111
1112	/* Do the final checks */
1113	if (replace->command == 'A' || replace->command == 'I' ||
1114	   replace->command == 'D' || replace->command == 'C') {
1115		/* This will put the hook_mask right for the chains */
1116		ebt_check_for_loops(replace);
1117		if (ebt_errormsg[0] != '\0')
1118			return -1;
1119		entries = ebt_to_chain(replace);
1120		m_l = new_entry->m_list;
1121		w_l = new_entry->w_list;
1122		t = (struct ebt_u_target *)new_entry->t;
1123		while (m_l) {
1124			m = (struct ebt_u_match *)(m_l->m);
1125			m->final_check(new_entry, m->m, replace->name,
1126			   entries->hook_mask, 0);
1127			if (ebt_errormsg[0] != '\0')
1128				return -1;
1129			m_l = m_l->next;
1130		}
1131		while (w_l) {
1132			w = (struct ebt_u_watcher *)(w_l->w);
1133			w->final_check(new_entry, w->w, replace->name,
1134			   entries->hook_mask, 0);
1135			if (ebt_errormsg[0] != '\0')
1136				return -1;
1137			w_l = w_l->next;
1138		}
1139		t->final_check(new_entry, t->t, replace->name,
1140		   entries->hook_mask, 0);
1141		if (ebt_errormsg[0] != '\0')
1142			return -1;
1143	}
1144	/* So, the extensions can work with the host endian.
1145	 * The kernel does not have to do this of course */
1146	new_entry->ethproto = htons(new_entry->ethproto);
1147
1148	if (replace->command == 'P') {
1149		if (replace->selected_chain < NF_BR_NUMHOOKS && policy == EBT_RETURN)
1150			ebt_print_error2("Policy RETURN only allowed for user defined chains");
1151		ebt_change_policy(replace, policy);
1152		if (ebt_errormsg[0] != '\0')
1153			return -1;
1154	} else if (replace->command == 'L') {
1155		list_rules();
1156		if (!(replace->flags & OPT_ZERO) && exec_style == EXEC_STYLE_PRG)
1157			exit(0);
1158	}
1159	if (replace->flags & OPT_ZERO) {
1160		replace->selected_chain = zerochain;
1161		ebt_zero_counters(replace);
1162	} else if (replace->command == 'F') {
1163		ebt_flush_chains(replace);
1164	} else if (replace->command == 'A' || replace->command == 'I') {
1165		ebt_add_rule(replace, new_entry, rule_nr);
1166		if (ebt_errormsg[0] != '\0')
1167			return -1;
1168		/* Makes undoing the add easier (jumps to delete_the_rule) */
1169		if (rule_nr <= 0)
1170			rule_nr--;
1171		rule_nr_end = rule_nr;
1172
1173		/* a jump to a udc requires checking for loops */
1174		if (!strcmp(new_entry->t->u.name, EBT_STANDARD_TARGET) &&
1175		((struct ebt_standard_target *)(new_entry->t))->verdict >= 0) {
1176			/* FIXME: this can be done faster */
1177			ebt_check_for_loops(replace);
1178			if (ebt_errormsg[0] != '\0')
1179				goto delete_the_rule;
1180		}
1181
1182		/* Do the final_check(), for all entries.
1183		 * This is needed when adding a rule that has a chain target */
1184		i = -1;
1185		while (++i != replace->num_chains) {
1186			struct ebt_u_entry *e;
1187
1188			entries = replace->chains[i];
1189			if (!entries) {
1190				if (i < NF_BR_NUMHOOKS)
1191					continue;
1192				else
1193					ebt_print_bug("whoops\n");
1194			}
1195			e = entries->entries->next;
1196			while (e != entries->entries) {
1197				/* Userspace extensions use host endian */
1198				e->ethproto = ntohs(e->ethproto);
1199				ebt_do_final_checks(replace, e, entries);
1200				if (ebt_errormsg[0] != '\0')
1201					goto delete_the_rule;
1202				e->ethproto = htons(e->ethproto);
1203				e = e->next;
1204			}
1205		}
1206		/* Don't reuse the added rule */
1207		new_entry = NULL;
1208	} else if (replace->command == 'D') {
1209delete_the_rule:
1210		ebt_delete_rule(replace, new_entry, rule_nr, rule_nr_end);
1211		if (ebt_errormsg[0] != '\0')
1212			return -1;
1213	} else if (replace->command == 'C') {
1214		ebt_change_counters(replace, new_entry, rule_nr, rule_nr_end, &(new_entry->cnt_surplus), chcounter);
1215		if (ebt_errormsg[0] != '\0')
1216			return -1;
1217	}
1218	/* Commands -N, -E, -X, --atomic-commit, --atomic-commit, --atomic-save,
1219	 * --init-table fall through */
1220
1221	if (ebt_errormsg[0] != '\0')
1222		return -1;
1223	if (table->check)
1224		table->check(replace);
1225
1226	if (exec_style == EXEC_STYLE_PRG) {/* Implies ebt_errormsg[0] == '\0' */
1227		ebt_deliver_table(replace);
1228
1229		if (replace->nentries)
1230			ebt_deliver_counters(replace);
1231	}
1232	return 0;
1233}
1234