2 * ebtables.c, v2.0 July 2002
4 * Author: Bart De Schuymer
6 * This code was stongly inspired on the iptables code which is
7 * Copyright (C) 1999 Paul `Rusty' Russell & Michael J. Neuling
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.
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.
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.
30 #include "include/ebtables_u.h"
31 #include "include/ethernetdb.h"
33 /* Checks whether a command has already been specified */
34 #define OPT_COMMANDS (replace->flags & OPT_COMMAND || replace->flags & OPT_ZERO)
36 #define OPT_COMMAND 0x01
37 #define OPT_TABLE 0x02
41 #define OPT_PROTOCOL 0x20
42 #define OPT_SOURCE 0x40
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 */
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
[] =
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 },
99 static struct option
*ebt_options
= ebt_original_options
;
101 /* Holds all the data */
102 static struct ebt_u_replace
*replace
;
104 /* The chosen table */
105 static struct ebt_u_table
*table
;
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
113 * The same holds for the struct ebt_match and struct ebt_watcher pointers */
114 static struct ebt_u_entry
*new_entry
;
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
)
122 unsigned int num_old
, num_new
, i
;
123 struct option
*merge
;
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
++);
130 global_option_offset
+= OPTION_OFFSET
;
131 *options_offset
= global_option_offset
;
133 merge
= malloc(sizeof(struct option
) * (num_new
+ num_old
+ 1));
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
;
141 memset(merge
+ num_old
+ num_new
, 0, sizeof(struct option
));
142 /* Only free dynamically allocated stuff */
143 if (oldopts
!= ebt_original_options
)
149 static void merge_match(struct ebt_u_match
*m
)
151 ebt_options
= merge_options
152 (ebt_options
, m
->extra_ops
, &(m
->option_offset
));
155 static void merge_watcher(struct ebt_u_watcher
*w
)
157 ebt_options
= merge_options
158 (ebt_options
, w
->extra_ops
, &(w
->option_offset
));
161 static void merge_target(struct ebt_u_target
*t
)
163 ebt_options
= merge_options
164 (ebt_options
, t
->extra_ops
, &(t
->option_offset
));
167 /* Be backwards compatible, so don't use '+' in kernel */
168 #define IF_WILDCARD 1
169 static void print_iface(const char *iface
)
173 if ((c
= strchr(iface
, IF_WILDCARD
)))
175 printf("%s ", iface
);
180 /* We use replace->flags, so we can't use the following values:
181 * 0x01 == OPT_COMMAND, 0x02 == OPT_TABLE, 0x100 == OPT_ZERO */
185 #define LIST_MAC2 0x20
187 /* Helper function for list_rules() */
188 static void list_em(struct ebt_u_entries
*entries
)
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
;
198 if (replace
->flags
& LIST_MAC2
)
199 ebt_printstyle_mac
= 2;
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]);
212 if (replace
->flags
& LIST_N
) {
213 i
= entries
->nentries
;
220 for (i
= 0; i
< entries
->nentries
; i
++) {
221 if (replace
->flags
& LIST_N
) {
223 /* A little work to get nice rule numbers. */
229 for (j
= 0; j
< space
- digits
; j
++)
231 printf("%d. ", i
+ 1);
233 if (replace
->flags
& LIST_X
)
234 printf("ebtables -t %s -A %s ",
235 replace
->name
, entries
->name
);
237 /* The standard target's print() uses this to find out
238 * the name of a udc */
239 hlp
->replace
= replace
;
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
)) {
245 if (hlp
->invflags
& EBT_IPROTO
)
247 if (hlp
->bitmask
& EBT_802_3
)
250 struct ethertypeent
*ent
;
252 ent
= getethertypebynumber(ntohs(hlp
->ethproto
));
254 printf("0x%x ", ntohs(hlp
->ethproto
));
256 printf("%s ", ent
->e_name
);
259 if (hlp
->bitmask
& EBT_SOURCEMAC
) {
261 if (hlp
->invflags
& EBT_ISOURCE
)
263 ebt_print_mac_and_mask(hlp
->sourcemac
, hlp
->sourcemsk
);
266 if (hlp
->bitmask
& EBT_DESTMAC
) {
268 if (hlp
->invflags
& EBT_IDEST
)
270 ebt_print_mac_and_mask(hlp
->destmac
, hlp
->destmsk
);
273 if (hlp
->in
[0] != '\0') {
275 if (hlp
->invflags
& EBT_IIN
)
277 print_iface(hlp
->in
);
279 if (hlp
->logical_in
[0] != '\0') {
280 printf("--logical-in ");
281 if (hlp
->invflags
& EBT_ILOGICALIN
)
283 print_iface(hlp
->logical_in
);
285 if (hlp
->logical_out
[0] != '\0') {
286 printf("--logical-out ");
287 if (hlp
->invflags
& EBT_ILOGICALOUT
)
289 print_iface(hlp
->logical_out
);
291 if (hlp
->out
[0] != '\0') {
293 if (hlp
->invflags
& EBT_IOUT
)
295 print_iface(hlp
->out
);
300 m
= ebt_find_match(m_l
->m
->u
.name
);
302 ebt_print_bug("Match not found");
303 m
->print(hlp
, m_l
->m
);
308 w
= ebt_find_watcher(w_l
->w
->u
.name
);
310 ebt_print_bug("Watcher not found");
311 w
->print(hlp
, w_l
->w
);
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
);
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
;
326 if (replace
->flags
& LIST_X
)
327 printf("-c %"PRIu64
" %"PRIu64
, pcnt
, bcnt
);
329 printf(", pcnt = %"PRIu64
" -- bcnt = %"PRIu64
, pcnt
, bcnt
);
336 static void print_help()
338 struct ebt_u_match_list
*m_l
;
339 struct ebt_u_watcher_list
*w_l
;
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"
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"
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"
384 m_l
= new_entry
->m_list
;
386 ((struct ebt_u_match
*)m_l
->m
)->help();
390 w_l
= new_entry
->w_list
;
392 ((struct ebt_u_watcher
*)w_l
->w
)->help();
396 ((struct ebt_u_target
*)new_entry
->t
)->help();
399 table
->help(ebt_hooknames
);
402 /* Execute command L */
403 static void list_rules()
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
));
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
);
420 for (i
= 0; i
< replace
->num_chains
; i
++)
421 if (replace
->chains
[i
])
422 list_em(replace
->chains
[i
]);
426 static int parse_rule_range(const char *argv
, int *rule_nr
, int *rule_nr_end
)
428 char *colon
= strchr(argv
, ':'), *buffer
;
432 if (*(colon
+ 1) == '\0')
433 *rule_nr_end
= -1; /* Until the last rule */
435 *rule_nr_end
= strtol(colon
+ 1, &buffer
, 10);
436 if (*buffer
!= '\0' || *rule_nr_end
== 0)
441 *rule_nr
= 1; /* Beginning with the first rule */
443 *rule_nr
= strtol(argv
, &buffer
, 10);
444 if (*buffer
!= '\0' || *rule_nr
== 0)
448 *rule_nr_end
= *rule_nr
;
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
)
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
]);
471 if (argv
[optind
][0] == '+') {
472 if (exec_style
== EXEC_STYLE_DAEMON
)
474 ebt_print_error2("Incrementing rule counters (%s) not allowed in daemon mode", argv
[optind
]);
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
)
480 ebt_print_error2("Decrementing rule counters (%s) not allowed in daemon mode", argv
[optind
]);
482 new_entry
->cnt_surplus
.pcnt
= strtoull(argv
[optind
] + 1, &buffer
, 10);
484 new_entry
->cnt_surplus
.pcnt
= strtoull(argv
[optind
], &buffer
, 10);
489 if (argv
[optind
][0] == '+') {
490 if (exec_style
== EXEC_STYLE_DAEMON
)
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
)
498 new_entry
->cnt_surplus
.bcnt
= strtoull(argv
[optind
] + 1, &buffer
, 10);
500 new_entry
->cnt_surplus
.bcnt
= strtoull(argv
[optind
], &buffer
, 10);
507 ebt_print_error2("Packet counter '%s' invalid", argv
[optind
]);
510 static int parse_iface(char *iface
, char *option
)
514 if ((c
= strchr(iface
, '+'))) {
515 if (*(c
+ 1) != '\0') {
516 ebt_print_error("Spurious characters after '+' wildcard for '%s'", option
);
524 void ebt_early_init_once()
526 ebt_iterate_matches(merge_match
);
527 ebt_iterate_watchers(merge_watcher
);
528 ebt_iterate_targets(merge_target
);
531 /* signal handler, installed when the option --concurrent is specified. */
532 static void sighandler(int signum
)
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_
)
543 int zerochain
= -1; /* Needed for the -Z option (we can have -Z <this> -L <that>) */
544 int chcounter
= 0; /* Needed for -C */
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
;
560 /* The daemon doesn't use the environment variable */
561 if (exec_style
== EXEC_STYLE_PRG
) {
562 buffer
= getenv(ATOMIC_ENV_VARIABLE
);
564 replace
->filename
= malloc(strlen(buffer
) + 1);
565 if (!replace
->filename
)
567 strcpy(replace
->filename
, buffer
);
572 replace
->flags
&= OPT_KERNELDATA
; /* ebtablesd needs OPT_KERNELDATA */
573 replace
->selected_chain
= -1;
574 replace
->command
= 'h';
577 new_entry
= (struct ebt_u_entry
*)malloc(sizeof(struct ebt_u_entry
));
581 /* Put some sane values in our new entry */
582 ebt_initialize_entry(new_entry
);
583 new_entry
->replace
= replace
;
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 */
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) {
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 */
609 ebt_print_error2("Multiple commands are not allowed");
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");
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
);
631 } else if (c
== 'X') {
632 if (optind
>= argc
) {
633 replace
->selected_chain
= -1;
634 ebt_delete_chain(replace
);
638 if (optind
< argc
- 1)
639 ebt_print_error2("No extra options allowed with -X");
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')
650 if ((replace
->selected_chain
= ebt_get_chainnr(replace
, optarg
)) == -1)
651 ebt_print_error2("Chain '%s' doesn't exist", optarg
);
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
]);
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
]);
674 } else if (c
== 'C') {
675 if ((chcounter
= parse_change_counters_rule(argc
, argv
, &rule_nr
, &rule_nr_end
, exec_style
)) == -1)
677 } else if (c
== 'I') {
678 if (optind
>= argc
|| (argv
[optind
][0] == '-' && (argv
[optind
][1] < '0' || argv
[optind
][1] > '9')))
681 rule_nr
= strtol(argv
[optind
], &buffer
, 10);
683 ebt_print_error2("Problem with the specified rule number '%s'", argv
[optind
]);
686 } else if (c
== 'P') {
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
])) {
693 if (policy
== EBT_CONTINUE
)
694 ebt_print_error2("Wrong policy '%s'", argv
[optind
]);
697 if (i
== NUM_STANDARD_TARGETS
)
698 ebt_print_error2("Unknown policy '%s'", argv
[optind
]);
703 case 'F': /* Flush */
704 case 'Z': /* Zero counters */
706 if ((replace
->flags
& OPT_ZERO
) || (replace
->flags
& OPT_COMMAND
&& replace
->command
!= 'L'))
708 ebt_print_error2("Command -Z only allowed together with command -L");
709 replace
->flags
|= OPT_ZERO
;
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')
720 if (c
== 'L' && exec_style
== EXEC_STYLE_DAEMON
)
721 ebt_print_error2("-L not supported in daemon mode");
724 if (!(replace
->flags
& OPT_KERNELDATA
))
725 ebt_get_kernel_table(replace
, 0);
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
]);
736 replace
->selected_chain
= i
;
739 case 'V': /* Version */
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");
747 case 'M': /* Modprobe */
749 ebt_print_error2("Please put the -M option earlier");
751 ebt_modprobe
= optarg
;
755 if (exec_style
== EXEC_STYLE_DAEMON
)
756 ebt_print_error2("-h not supported in daemon mode");
759 ebt_print_error2("Multiple commands are not allowed");
760 replace
->command
= 'h';
762 /* All other arguments should be extension names */
763 while (optind
< argc
) {
764 struct ebt_u_match
*m
;
765 struct ebt_u_watcher
*w
;
767 if (!strcasecmp("list_extensions", argv
[optind
])) {
768 ebt_list_extensions();
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
);
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
;
786 case 't': /* Table */
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
);
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 */
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");
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
;
814 if (strlen(optarg
) >= IFNAMSIZ
)
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"))
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
;
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"))
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
;
841 if (strlen(optarg
) >= IFNAMSIZ
)
842 goto big_iface_length
;
843 strcpy(new_entry
->out
, optarg
);
844 if (parse_iface(new_entry
->out
, "-o"))
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
;
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"))
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;
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
)
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
;
880 /* Must be an extension then */
881 struct ebt_u_target
*t
;
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;
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
;
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
;
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
;
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
;
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");
917 new_entry
->cnt
.pcnt
= strtoull(optarg
, &buffer
, 10);
919 ebt_print_error2("Packet counter '%s' invalid", optarg
);
920 new_entry
->cnt
.bcnt
= strtoull(argv
[optind
], &buffer
, 10);
922 ebt_print_error2("Packet counter '%s' invalid", argv
[optind
]);
926 ebt_check_option2(&(replace
->flags
), OPT_PROTOCOL
);
927 if (ebt_check_inverse2(optarg
))
928 new_entry
->invflags
|= EBT_IPROTO
;
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
;
937 if (!strcasecmp(optarg
, "LENGTH")) {
938 new_entry
->bitmask
|= EBT_802_3
;
941 ent
= getethertypebyname(optarg
);
943 ebt_print_error2("Problem with the specified Ethernet protocol '%s', perhaps "_PATH_ETHERTYPES
" is missing", optarg
);
944 new_entry
->ethproto
= ent
->e_ethertype
;
946 new_entry
->ethproto
= i
;
948 if (new_entry
->ethproto
< 0x0600)
949 ebt_print_error2("Sorry, protocols have values above or equal to 0x0600");
953 if (exec_style
== EXEC_STYLE_DAEMON
)
954 ebt_print_error2("--Lc is not supported in daemon mode");
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
;
963 if (exec_style
== EXEC_STYLE_DAEMON
)
964 ebt_print_error2("--Ln is not supported in daemon mode");
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
;
975 if (exec_style
== EXEC_STYLE_DAEMON
)
976 ebt_print_error2("--Lx is not supported in daemon mode");
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
;
985 case 12 : /* Lmac2 */
987 if (exec_style
== EXEC_STYLE_DAEMON
)
988 ebt_print_error("--Lmac2 is not supported in daemon mode");
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
;
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
;
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
1009 replace
->num_counters
= 0;
1010 /* Make sure the table will be written to the kernel */
1011 free(replace
->filename
);
1012 replace
->filename
= NULL
;
1014 case 7 : /* atomic-init */
1015 case 10: /* atomic-save */
1016 case 11: /* init-table */
1017 if (exec_style
== EXEC_STYLE_DAEMON
) {
1019 ebt_print_error2("--atomic-init is not supported in daemon mode");
1021 ebt_print_error2("--atomic-save is not supported in daemon mode");
1022 ebt_print_error2("--init-table is not supported in daemon mode");
1024 replace
->command
= c
;
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
;
1031 char *tmp
= replace
->filename
;
1033 /* Get the kernel table */
1034 replace
->filename
= NULL
;
1035 ebt_get_kernel_table(replace
, c
== 10 ? 0 : 1);
1036 replace
->filename
= tmp
;
1039 case 9 : /* atomic */
1040 if (exec_style
== EXEC_STYLE_DAEMON
)
1041 ebt_print_error2("--atomic is not supported in daemon mode");
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
);
1049 case 13 : /* concurrent */
1050 signal(SIGINT
, sighandler
);
1051 signal(SIGTERM
, sighandler
);
1055 if (!strcmp(optarg
, "!"))
1056 ebt_check_inverse2(optarg
);
1058 ebt_print_error2("Bad argument : '%s'", optarg
);
1059 /* ebt_check_inverse() did optind++ */
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')
1068 goto check_extension
;
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
))
1077 if (ebt_errormsg
[0] != '\0')
1080 ebt_add_match(new_entry
, m
);
1083 goto check_extension
;
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
))
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");
1097 ebt_print_error2("Target-specific option does not correspond with specified target");
1099 if (ebt_errormsg
[0] != '\0')
1102 ebt_add_watcher(new_entry
, w
);
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");
1113 /* Just in case we didn't catch an error */
1114 if (ebt_errormsg
[0] != '\0')
1117 if (!(table
= ebt_find_table(replace
->name
)))
1118 ebt_print_error2("Bad table name");
1120 if (replace
->command
== 'h' && !(replace
->flags
& OPT_ZERO
)) {
1122 if (exec_style
== EXEC_STYLE_PRG
)
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')
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
;
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')
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')
1153 t
->final_check(new_entry
, t
->t
, replace
->name
,
1154 entries
->hook_mask
, 0);
1155 if (ebt_errormsg
[0] != '\0')
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
);
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')
1168 } else if (replace
->command
== 'L') {
1170 if (!(replace
->flags
& OPT_ZERO
) && exec_style
== EXEC_STYLE_PRG
)
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')
1182 /* Makes undoing the add easier (jumps to delete_the_rule) */
1185 rule_nr_end
= rule_nr
;
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
;
1196 /* Do the final_check(), for all entries.
1197 * This is needed when adding a rule that has a chain target */
1199 while (++i
!= replace
->num_chains
) {
1200 struct ebt_u_entry
*e
;
1202 entries
= replace
->chains
[i
];
1204 if (i
< NF_BR_NUMHOOKS
)
1207 ebt_print_bug("whoops\n");
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
);
1220 /* Don't reuse the added rule */
1222 } else if (replace
->command
== 'D') {
1224 ebt_delete_rule(replace
, new_entry
, rule_nr
, rule_nr_end
);
1225 if (ebt_errormsg
[0] != '\0')
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')
1232 /* Commands -N, -E, -X, --atomic-commit, --atomic-commit, --atomic-save,
1233 * --init-table fall through */
1235 if (ebt_errormsg
[0] != '\0')
1238 table
->check(replace
);
1240 if (exec_style
== EXEC_STYLE_PRG
) {/* Implies ebt_errormsg[0] == '\0' */
1241 ebt_deliver_table(replace
);
1243 if (replace
->nentries
)
1244 ebt_deliver_counters(replace
);