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