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.
29 #include "include/ebtables_u.h"
30 #include "include/ethernetdb.h"
32 /* Checks whether a command has already been specified */
33 #define OPT_COMMANDS (replace->flags & OPT_COMMAND || replace->flags & OPT_ZERO)
35 #define OPT_COMMAND 0x01
36 #define OPT_TABLE 0x02
40 #define OPT_PROTOCOL 0x20
41 #define OPT_SOURCE 0x40
43 #define OPT_ZERO 0x100
44 #define OPT_LOGICALIN 0x200
45 #define OPT_LOGICALOUT 0x400
46 #define OPT_KERNELDATA 0x800 /* This value is also defined in ebtablesd.c */
47 #define OPT_COUNT 0x1000 /* This value is also defined in libebtc.c */
48 #define OPT_CNT_INCR 0x2000 /* This value is also defined in libebtc.c */
49 #define OPT_CNT_DECR 0x4000 /* This value is also defined in libebtc.c */
51 /* Default command line options. Do not mess around with the already
52 * assigned numbers unless you know what you are doing */
53 static struct option ebt_original_options
[] =
55 { "append" , required_argument
, 0, 'A' },
56 { "insert" , required_argument
, 0, 'I' },
57 { "delete" , required_argument
, 0, 'D' },
58 { "list" , optional_argument
, 0, 'L' },
59 { "Lc" , no_argument
, 0, 4 },
60 { "Ln" , no_argument
, 0, 5 },
61 { "Lx" , no_argument
, 0, 6 },
62 { "Lmac2" , no_argument
, 0, 12 },
63 { "zero" , optional_argument
, 0, 'Z' },
64 { "flush" , optional_argument
, 0, 'F' },
65 { "policy" , required_argument
, 0, 'P' },
66 { "in-interface" , required_argument
, 0, 'i' },
67 { "in-if" , required_argument
, 0, 'i' },
68 { "logical-in" , required_argument
, 0, 2 },
69 { "logical-out" , required_argument
, 0, 3 },
70 { "out-interface" , required_argument
, 0, 'o' },
71 { "out-if" , required_argument
, 0, 'o' },
72 { "version" , no_argument
, 0, 'V' },
73 { "help" , no_argument
, 0, 'h' },
74 { "jump" , required_argument
, 0, 'j' },
75 { "set-counters" , required_argument
, 0, 'c' },
76 { "change-counters", required_argument
, 0, 'C' },
77 { "proto" , required_argument
, 0, 'p' },
78 { "protocol" , required_argument
, 0, 'p' },
79 { "db" , required_argument
, 0, 'b' },
80 { "source" , required_argument
, 0, 's' },
81 { "src" , required_argument
, 0, 's' },
82 { "destination" , required_argument
, 0, 'd' },
83 { "dst" , required_argument
, 0, 'd' },
84 { "table" , required_argument
, 0, 't' },
85 { "modprobe" , required_argument
, 0, 'M' },
86 { "new-chain" , required_argument
, 0, 'N' },
87 { "rename-chain" , required_argument
, 0, 'E' },
88 { "delete-chain" , optional_argument
, 0, 'X' },
89 { "atomic-init" , no_argument
, 0, 7 },
90 { "atomic-commit" , no_argument
, 0, 8 },
91 { "atomic-file" , required_argument
, 0, 9 },
92 { "atomic-save" , no_argument
, 0, 10 },
93 { "init-table" , no_argument
, 0, 11 },
97 static struct option
*ebt_options
= ebt_original_options
;
99 /* Holds all the data */
100 static struct ebt_u_replace
*replace
;
102 /* The chosen table */
103 static struct ebt_u_table
*table
;
105 /* The pointers in here are special:
106 * The struct ebt_target pointer is actually a struct ebt_u_target pointer.
107 * I do not feel like using a union.
108 * We need a struct ebt_u_target pointer because we know the address of the data
109 * they point to won't change. We want to allow that the struct ebt_u_target.t
111 * The same holds for the struct ebt_match and struct ebt_watcher pointers */
112 static struct ebt_u_entry
*new_entry
;
115 static int global_option_offset
;
116 #define OPTION_OFFSET 256
117 static struct option
*merge_options(struct option
*oldopts
,
118 const struct option
*newopts
, unsigned int *options_offset
)
120 unsigned int num_old
, num_new
, i
;
121 struct option
*merge
;
123 if (!newopts
|| !oldopts
|| !options_offset
)
124 ebt_print_bug("merge wrong");
125 for (num_old
= 0; oldopts
[num_old
].name
; num_old
++);
126 for (num_new
= 0; newopts
[num_new
].name
; num_new
++);
128 global_option_offset
+= OPTION_OFFSET
;
129 *options_offset
= global_option_offset
;
131 merge
= malloc(sizeof(struct option
) * (num_new
+ num_old
+ 1));
134 memcpy(merge
, oldopts
, num_old
* sizeof(struct option
));
135 for (i
= 0; i
< num_new
; i
++) {
136 merge
[num_old
+ i
] = newopts
[i
];
137 merge
[num_old
+ i
].val
+= *options_offset
;
139 memset(merge
+ num_old
+ num_new
, 0, sizeof(struct option
));
140 /* Only free dynamically allocated stuff */
141 if (oldopts
!= ebt_original_options
)
147 static void merge_match(struct ebt_u_match
*m
)
149 ebt_options
= merge_options
150 (ebt_options
, m
->extra_ops
, &(m
->option_offset
));
153 static void merge_watcher(struct ebt_u_watcher
*w
)
155 ebt_options
= merge_options
156 (ebt_options
, w
->extra_ops
, &(w
->option_offset
));
159 static void merge_target(struct ebt_u_target
*t
)
161 ebt_options
= merge_options
162 (ebt_options
, t
->extra_ops
, &(t
->option_offset
));
165 /* Be backwards compatible, so don't use '+' in kernel */
166 #define IF_WILDCARD 1
167 static void print_iface(const char *iface
)
171 if ((c
= strchr(iface
, IF_WILDCARD
)))
173 printf("%s ", iface
);
178 /* We use replace->flags, so we can't use the following values:
179 * 0x01 == OPT_COMMAND, 0x02 == OPT_TABLE, 0x100 == OPT_ZERO */
183 #define LIST_MAC2 0x20
185 /* Helper function for list_rules() */
186 static void list_em(struct ebt_u_entries
*entries
)
188 int i
, j
, space
= 0, digits
;
189 struct ebt_u_entry
*hlp
;
190 struct ebt_u_match_list
*m_l
;
191 struct ebt_u_watcher_list
*w_l
;
192 struct ebt_u_match
*m
;
193 struct ebt_u_watcher
*w
;
194 struct ebt_u_target
*t
;
196 if (replace
->flags
& LIST_MAC2
)
197 ebt_printstyle_mac
= 2;
199 ebt_printstyle_mac
= 0;
200 hlp
= entries
->entries
->next
;
201 if (replace
->flags
& LIST_X
&& entries
->policy
!= EBT_ACCEPT
) {
202 printf("ebtables -t %s -P %s %s\n", replace
->name
,
203 entries
->name
, ebt_standard_targets
[-entries
->policy
- 1]);
204 } else if (!(replace
->flags
& LIST_X
)) {
205 printf("\nBridge chain: %s, entries: %d, policy: %s\n",
206 entries
->name
, entries
->nentries
,
207 ebt_standard_targets
[-entries
->policy
- 1]);
210 if (replace
->flags
& LIST_N
) {
211 i
= entries
->nentries
;
218 for (i
= 0; i
< entries
->nentries
; i
++) {
219 if (replace
->flags
& LIST_N
) {
221 /* A little work to get nice rule numbers. */
227 for (j
= 0; j
< space
- digits
; j
++)
229 printf("%d. ", i
+ 1);
231 if (replace
->flags
& LIST_X
)
232 printf("ebtables -t %s -A %s ",
233 replace
->name
, entries
->name
);
235 /* The standard target's print() uses this to find out
236 * the name of a udc */
237 hlp
->replace
= replace
;
239 /* Don't print anything about the protocol if no protocol was
240 * specified, obviously this means any protocol will do. */
241 if (!(hlp
->bitmask
& EBT_NOPROTO
)) {
243 if (hlp
->invflags
& EBT_IPROTO
)
245 if (hlp
->bitmask
& EBT_802_3
)
248 struct ethertypeent
*ent
;
250 ent
= getethertypebynumber(ntohs(hlp
->ethproto
));
252 printf("0x%x ", ntohs(hlp
->ethproto
));
254 printf("%s ", ent
->e_name
);
257 if (hlp
->bitmask
& EBT_SOURCEMAC
) {
259 if (hlp
->invflags
& EBT_ISOURCE
)
261 ebt_print_mac_and_mask(hlp
->sourcemac
, hlp
->sourcemsk
);
264 if (hlp
->bitmask
& EBT_DESTMAC
) {
266 if (hlp
->invflags
& EBT_IDEST
)
268 ebt_print_mac_and_mask(hlp
->destmac
, hlp
->destmsk
);
271 if (hlp
->in
[0] != '\0') {
273 if (hlp
->invflags
& EBT_IIN
)
275 print_iface(hlp
->in
);
277 if (hlp
->logical_in
[0] != '\0') {
278 printf("--logical-in ");
279 if (hlp
->invflags
& EBT_ILOGICALIN
)
281 print_iface(hlp
->logical_in
);
283 if (hlp
->logical_out
[0] != '\0') {
284 printf("--logical-out ");
285 if (hlp
->invflags
& EBT_ILOGICALOUT
)
287 print_iface(hlp
->logical_out
);
289 if (hlp
->out
[0] != '\0') {
291 if (hlp
->invflags
& EBT_IOUT
)
293 print_iface(hlp
->out
);
298 m
= ebt_find_match(m_l
->m
->u
.name
);
300 ebt_print_bug("Match not found");
301 m
->print(hlp
, m_l
->m
);
306 w
= ebt_find_watcher(w_l
->w
->u
.name
);
308 ebt_print_bug("Watcher not found");
309 w
->print(hlp
, w_l
->w
);
314 if (strcmp(hlp
->t
->u
.name
, EBT_STANDARD_TARGET
))
315 printf("%s ", hlp
->t
->u
.name
);
316 t
= ebt_find_target(hlp
->t
->u
.name
);
318 ebt_print_bug("Target '%s' not found", hlp
->t
->u
.name
);
319 t
->print(hlp
, hlp
->t
);
320 if (replace
->flags
& LIST_C
) {
321 uint64_t pcnt
= hlp
->cnt
.pcnt
;
322 uint64_t bcnt
= hlp
->cnt
.bcnt
;
324 if (replace
->flags
& LIST_X
)
325 printf("-c %llu %llu", pcnt
, bcnt
);
327 printf(", pcnt = %"PRIu64
" -- bcnt = %"PRIu64
, pcnt
, bcnt
);
334 static void print_help()
336 struct ebt_u_match_list
*m_l
;
337 struct ebt_u_watcher_list
*w_l
;
342 "ebtables -[ADI] chain rule-specification [options]\n"
343 "ebtables -P chain target\n"
344 "ebtables -[LFZ] [chain]\n"
345 "ebtables -[NX] [chain]\n"
346 "ebtables -E old-chain-name new-chain-name\n\n"
348 "--append -A chain : append to chain\n"
349 "--delete -D chain : delete matching rule from chain\n"
350 "--delete -D chain rulenum : delete rule at position rulenum from chain\n"
351 "--change-counters -C chain\n"
352 " [rulenum] pcnt bcnt : change counters of existing rule\n"
353 "--insert -I chain rulenum : insert rule at position rulenum in chain\n"
354 "--list -L [chain] : list the rules in a chain or in all chains\n"
355 "--flush -F [chain] : delete all rules in chain or in all chains\n"
356 "--init-table : replace the kernel table with the initial table\n"
357 "--zero -Z [chain] : put counters on zero in chain or in all chains\n"
358 "--policy -P chain target : change policy on chain to target\n"
359 "--new-chain -N chain : create a user defined chain\n"
360 "--rename-chain -E old new : rename a chain\n"
361 "--delete-chain -X [chain] : delete a user defined chain\n"
362 "--atomic-commit : update the kernel w/t table contained in <FILE>\n"
363 "--atomic-init : put the initial kernel table into <FILE>\n"
364 "--atomic-save : put the current kernel table into <FILE>\n"
365 "--atomic-file file : set <FILE> to file\n\n"
367 "--proto -p [!] proto : protocol hexadecimal, by name or LENGTH\n"
368 "--src -s [!] address[/mask]: source mac address\n"
369 "--dst -d [!] address[/mask]: destination mac address\n"
370 "--in-if -i [!] name[+] : network input interface name\n"
371 "--out-if -o [!] name[+] : network output interface name\n"
372 "--logical-in [!] name[+] : logical bridge input interface name\n"
373 "--logical-out [!] name[+] : logical bridge output interface name\n"
374 "--set-counters -c chain\n"
375 " pcnt bcnt : set the counters of the to be added rule\n"
376 "--modprobe -M program : try to insert modules using this program\n"
377 "--version -V : print package version\n\n"
378 "Environment variable:\n"
379 ATOMIC_ENV_VARIABLE
" : if set <FILE> (see above) will equal its value"
381 m_l
= new_entry
->m_list
;
383 ((struct ebt_u_match
*)m_l
->m
)->help();
387 w_l
= new_entry
->w_list
;
389 ((struct ebt_u_watcher
*)w_l
->w
)->help();
393 ((struct ebt_u_target
*)new_entry
->t
)->help();
396 table
->help(ebt_hooknames
);
399 /* Execute command L */
400 static void list_rules()
404 if (!(replace
->flags
& LIST_X
))
405 printf("Bridge table: %s\n", table
->name
);
406 if (replace
->selected_chain
!= -1)
407 list_em(ebt_to_chain(replace
));
409 /* Create new chains and rename standard chains when necessary */
410 if (replace
->flags
& LIST_X
&& replace
->num_chains
> NF_BR_NUMHOOKS
) {
411 for (i
= NF_BR_NUMHOOKS
; i
< replace
->num_chains
; i
++)
412 printf("ebtables -t %s -N %s\n", replace
->name
, replace
->chains
[i
]->name
);
413 for (i
= 0; i
< NF_BR_NUMHOOKS
; i
++)
414 if (replace
->chains
[i
] && strcmp(replace
->chains
[i
]->name
, ebt_hooknames
[i
]))
415 printf("ebtables -t %s -E %s %s\n", replace
->name
, ebt_hooknames
[i
], replace
->chains
[i
]->name
);
417 for (i
= 0; i
< replace
->num_chains
; i
++)
418 if (replace
->chains
[i
])
419 list_em(replace
->chains
[i
]);
423 static int parse_rule_range(const char *argv
, int *rule_nr
, int *rule_nr_end
)
425 char *colon
= strchr(argv
, ':'), *buffer
;
429 if (*(colon
+ 1) == '\0')
430 *rule_nr_end
= -1; /* Until the last rule */
432 *rule_nr_end
= strtol(colon
+ 1, &buffer
, 10);
433 if (*buffer
!= '\0' || *rule_nr_end
== 0)
438 *rule_nr
= 1; /* Beginning with the first rule */
440 *rule_nr
= strtol(argv
, &buffer
, 10);
441 if (*buffer
!= '\0' || *rule_nr
== 0)
445 *rule_nr_end
= *rule_nr
;
449 /* Incrementing or decrementing rules in daemon mode is not supported as the
450 * involved code overload is not worth it (too annoying to take the increased
451 * counters in the kernel into account). */
452 static int parse_change_counters_rule(int argc
, char **argv
, int *rule_nr
, int *rule_nr_end
, int exec_style
)
457 if (optind
+ 1 >= argc
|| (argv
[optind
][0] == '-' && (argv
[optind
][1] < '0' || argv
[optind
][1] > '9')) ||
458 (argv
[optind
+ 1][0] == '-' && (argv
[optind
+ 1][1] < '0' && argv
[optind
+ 1][1] > '9')))
459 ebt_print_error2("The command -C needs at least 2 arguments");
460 if (optind
+ 2 < argc
&& (argv
[optind
+ 2][0] != '-' || (argv
[optind
+ 2][1] >= '0' && argv
[optind
+ 2][1] <= '9'))) {
461 if (optind
+ 3 != argc
)
462 ebt_print_error2("No extra options allowed with -C start_nr[:end_nr] pcnt bcnt");
463 if (parse_rule_range(argv
[optind
], rule_nr
, rule_nr_end
))
464 ebt_print_error2("Something is wrong with the rule number specification '%s'", argv
[optind
]);
468 if (argv
[optind
][0] == '+') {
469 if (exec_style
== EXEC_STYLE_DAEMON
)
471 ebt_print_error2("Incrementing rule counters (%s) not allowed in daemon mode", argv
[optind
]);
473 new_entry
->cnt_surplus
.pcnt
= strtoull(argv
[optind
] + 1, &buffer
, 10);
474 } else if (argv
[optind
][0] == '-') {
475 if (exec_style
== EXEC_STYLE_DAEMON
)
477 ebt_print_error2("Decrementing rule counters (%s) not allowed in daemon mode", argv
[optind
]);
479 new_entry
->cnt_surplus
.pcnt
= strtoull(argv
[optind
] + 1, &buffer
, 10);
481 new_entry
->cnt_surplus
.pcnt
= strtoull(argv
[optind
], &buffer
, 10);
486 if (argv
[optind
][0] == '+') {
487 if (exec_style
== EXEC_STYLE_DAEMON
)
490 new_entry
->cnt_surplus
.bcnt
= strtoull(argv
[optind
] + 1, &buffer
, 10);
491 } else if (argv
[optind
][0] == '-') {
492 if (exec_style
== EXEC_STYLE_DAEMON
)
495 new_entry
->cnt_surplus
.bcnt
= strtoull(argv
[optind
] + 1, &buffer
, 10);
497 new_entry
->cnt_surplus
.bcnt
= strtoull(argv
[optind
], &buffer
, 10);
504 ebt_print_error2("Packet counter '%s' invalid", argv
[optind
]);
507 static int parse_iface(char *iface
, char *option
)
511 if ((c
= strchr(iface
, '+'))) {
512 if (*(c
+ 1) != '\0') {
513 ebt_print_error("Spurious characters after '+' wildcard for '%s'", option
);
521 void ebt_early_init_once()
523 ebt_iterate_matches(merge_match
);
524 ebt_iterate_watchers(merge_watcher
);
525 ebt_iterate_targets(merge_target
);
528 /* We use exec_style instead of #ifdef's because ebtables.so is a shared object. */
529 int do_command(int argc
, char *argv
[], int exec_style
,
530 struct ebt_u_replace
*replace_
)
534 int zerochain
= -1; /* Needed for the -Z option (we can have -Z <this> -L <that>) */
535 int chcounter
; /* Needed for -C */
539 struct ebt_u_target
*t
;
540 struct ebt_u_match
*m
;
541 struct ebt_u_watcher
*w
;
542 struct ebt_u_match_list
*m_l
;
543 struct ebt_u_watcher_list
*w_l
;
544 struct ebt_u_entries
*entries
;
551 /* The daemon doesn't use the environment variable */
552 if (exec_style
== EXEC_STYLE_PRG
) {
553 buffer
= getenv(ATOMIC_ENV_VARIABLE
);
555 replace
->filename
= malloc(strlen(buffer
) + 1);
556 if (!replace
->filename
)
558 strcpy(replace
->filename
, buffer
);
563 replace
->flags
&= OPT_KERNELDATA
; /* ebtablesd needs OPT_KERNELDATA */
564 replace
->selected_chain
= -1;
565 replace
->command
= 'h';
568 new_entry
= (struct ebt_u_entry
*)malloc(sizeof(struct ebt_u_entry
));
572 /* Put some sane values in our new entry */
573 ebt_initialize_entry(new_entry
);
574 new_entry
->replace
= replace
;
576 /* The scenario induced by this loop makes that:
577 * '-t' ,'-M' and --atomic (if specified) have to come
578 * before '-A' and the like */
580 /* Getopt saves the day */
581 while ((c
= getopt_long(argc
, argv
,
582 "-A:D:C:I:N:E:X::L::Z::F::P:Vhi:o:j:c:p:s:d:t:M:", ebt_options
, NULL
)) != -1) {
585 case 'A': /* Add a rule */
586 case 'D': /* Delete a rule */
587 case 'C': /* Change counters */
588 case 'P': /* Define policy */
589 case 'I': /* Insert a rule */
590 case 'N': /* Make a user defined chain */
591 case 'E': /* Rename chain */
592 case 'X': /* Delete chain */
593 /* We allow -N chainname -P policy */
594 if (replace
->command
== 'N' && c
== 'P') {
595 replace
->command
= c
;
596 optind
--; /* No table specified */
600 ebt_print_error2("Multiple commands are not allowed");
602 replace
->command
= c
;
603 replace
->flags
|= OPT_COMMAND
;
604 if (!(replace
->flags
& OPT_KERNELDATA
))
605 ebt_get_kernel_table(replace
, 0);
606 if (optarg
&& (optarg
[0] == '-' || !strcmp(optarg
, "!")))
607 ebt_print_error2("No chain name specified");
609 if (ebt_get_chainnr(replace
, optarg
) != -1)
610 ebt_print_error2("Chain %s already exists", optarg
);
611 else if (ebt_find_target(optarg
))
612 ebt_print_error2("Target with name %s exists", optarg
);
613 else if (strlen(optarg
) >= EBT_CHAIN_MAXNAMELEN
)
614 ebt_print_error2("Chain name length can't exceed %d",
615 EBT_CHAIN_MAXNAMELEN
- 1);
616 else if (strchr(optarg
, ' ') != NULL
)
617 ebt_print_error2("Use of ' ' not allowed in chain names");
618 ebt_new_chain(replace
, optarg
, EBT_ACCEPT
);
619 /* This is needed to get -N x -P y working */
620 replace
->selected_chain
= ebt_get_chainnr(replace
, optarg
);
622 } else if (c
== 'X') {
623 if (optind
>= argc
) {
624 replace
->selected_chain
= -1;
625 ebt_delete_chain(replace
);
629 if (optind
< argc
- 1)
630 ebt_print_error2("No extra options allowed with -X");
632 if ((replace
->selected_chain
= ebt_get_chainnr(replace
, argv
[optind
])) == -1)
633 ebt_print_error2("Chain '%s' doesn't exist", argv
[optind
]);
634 ebt_delete_chain(replace
);
635 if (ebt_errormsg
[0] != '\0')
641 if ((replace
->selected_chain
= ebt_get_chainnr(replace
, optarg
)) == -1)
642 ebt_print_error2("Chain '%s' doesn't exist", optarg
);
645 ebt_print_error2("No new chain name specified");
646 else if (optind
< argc
- 1)
647 ebt_print_error2("No extra options allowed with -E");
648 else if (strlen(argv
[optind
]) >= EBT_CHAIN_MAXNAMELEN
)
649 ebt_print_error2("Chain name length can't exceed %d characters", EBT_CHAIN_MAXNAMELEN
- 1);
650 else if (ebt_get_chainnr(replace
, argv
[optind
]) != -1)
651 ebt_print_error2("Chain '%s' already exists", argv
[optind
]);
652 else if (ebt_find_target(argv
[optind
]))
653 ebt_print_error2("Target with name '%s' exists", argv
[optind
]);
654 else if (strchr(argv
[optind
], ' ') != NULL
)
655 ebt_print_error2("Use of ' ' not allowed in chain names");
656 ebt_rename_chain(replace
, argv
[optind
]);
659 } else if (c
== 'D' && optind
< argc
&& (argv
[optind
][0] != '-' || (argv
[optind
][1] >= '0' && argv
[optind
][1] <= '9'))) {
660 if (optind
!= argc
- 1)
661 ebt_print_error2("No extra options allowed with -D start_nr[:end_nr]");
662 if (parse_rule_range(argv
[optind
], &rule_nr
, &rule_nr_end
))
663 ebt_print_error2("Problem with the specified rule number(s) '%s'", argv
[optind
]);
665 } else if (c
== 'C') {
666 if ((chcounter
= parse_change_counters_rule(argc
, argv
, &rule_nr
, &rule_nr_end
, exec_style
)) == -1)
668 } else if (c
== 'I') {
669 if (optind
>= argc
|| (argv
[optind
][0] == '-' && (argv
[optind
][1] < '0' || argv
[optind
][1] > '9')))
672 rule_nr
= strtol(argv
[optind
], &buffer
, 10);
674 ebt_print_error2("Problem with the specified rule number '%s'", argv
[optind
]);
677 } else if (c
== 'P') {
680 ebt_print_error2("No policy specified");
681 for (i
= 0; i
< NUM_STANDARD_TARGETS
; i
++)
682 if (!strcmp(argv
[optind
], ebt_standard_targets
[i
])) {
684 if (policy
== EBT_CONTINUE
)
685 ebt_print_error2("Wrong policy '%s'", argv
[optind
]);
688 if (i
== NUM_STANDARD_TARGETS
)
689 ebt_print_error2("Unknown policy '%s'", argv
[optind
]);
694 case 'F': /* Flush */
695 case 'Z': /* Zero counters */
697 if ((replace
->flags
& OPT_ZERO
) || (replace
->flags
& OPT_COMMAND
&& replace
->command
!= 'L'))
699 ebt_print_error2("Command -Z only allowed together with command -L");
700 replace
->flags
|= OPT_ZERO
;
702 if (replace
->flags
& OPT_COMMAND
)
703 ebt_print_error2("Multiple commands are not allowed");
704 replace
->command
= c
;
705 replace
->flags
|= OPT_COMMAND
;
706 if (replace
->flags
& OPT_ZERO
&& c
!= 'L')
711 if (c
== 'L' && exec_style
== EXEC_STYLE_DAEMON
)
712 ebt_print_error2("-L not supported in daemon mode");
715 if (!(replace
->flags
& OPT_KERNELDATA
))
716 ebt_get_kernel_table(replace
, 0);
718 if (optind
< argc
&& argv
[optind
][0] != '-') {
719 if ((i
= ebt_get_chainnr(replace
, argv
[optind
])) == -1)
720 ebt_print_error2("Chain '%s' doesn't exist", argv
[optind
]);
727 replace
->selected_chain
= i
;
730 case 'V': /* Version */
732 ebt_print_error2("Multiple commands are not allowed");
733 replace
->command
= 'V';
734 if (exec_style
== EXEC_STYLE_DAEMON
)
735 ebt_print_error2(PROGNAME
" v"PROGVERSION
" ("PROGDATE
")\n");
738 case 'M': /* Modprobe */
740 ebt_print_error2("Please put the -M option earlier");
742 ebt_modprobe
= optarg
;
746 if (exec_style
== EXEC_STYLE_DAEMON
)
747 ebt_print_error2("-h not supported in daemon mode");
750 ebt_print_error2("Multiple commands are not allowed");
751 replace
->command
= 'h';
753 /* All other arguments should be extension names */
754 while (optind
< argc
) {
755 struct ebt_u_match
*m
;
756 struct ebt_u_watcher
*w
;
758 if (!strcasecmp("list_extensions", argv
[optind
])) {
759 ebt_list_extensions();
762 if ((m
= ebt_find_match(argv
[optind
])))
763 ebt_add_match(new_entry
, m
);
764 else if ((w
= ebt_find_watcher(argv
[optind
])))
765 ebt_add_watcher(new_entry
, w
);
767 if (!(t
= ebt_find_target(argv
[optind
])))
768 ebt_print_error2("Extension '%s' not found", argv
[optind
]);
769 if (replace
->flags
& OPT_JUMP
)
770 ebt_print_error2("Sorry, you can only see help for one target extension at a time");
771 replace
->flags
|= OPT_JUMP
;
772 new_entry
->t
= (struct ebt_entry_target
*)t
;
777 case 't': /* Table */
779 ebt_print_error2("Please put the -t option first");
780 ebt_check_option2(&(replace
->flags
), OPT_TABLE
);
781 if (strlen(optarg
) > EBT_TABLE_MAXNAMELEN
- 1)
782 ebt_print_error2("Table name length cannot exceed %d characters", EBT_TABLE_MAXNAMELEN
- 1);
783 strcpy(replace
->name
, optarg
);
785 case 'i': /* Input interface */
786 case 2 : /* Logical input interface */
787 case 'o': /* Output interface */
788 case 3 : /* Logical output interface */
789 case 'j': /* Target */
790 case 'p': /* Net family protocol */
791 case 's': /* Source mac */
792 case 'd': /* Destination mac */
793 case 'c': /* Set counters */
795 ebt_print_error2("No command specified");
796 if (replace
->command
!= 'A' && replace
->command
!= 'D' && replace
->command
!= 'I' && replace
->command
!= 'C')
797 ebt_print_error2("Command and option do not match");
799 ebt_check_option2(&(replace
->flags
), OPT_IN
);
800 if (replace
->selected_chain
> 2 && replace
->selected_chain
< NF_BR_BROUTING
)
801 ebt_print_error2("Use -i only in INPUT, FORWARD, PREROUTING and BROUTING chains");
802 if (ebt_check_inverse2(optarg
))
803 new_entry
->invflags
|= EBT_IIN
;
805 if (strlen(optarg
) >= IFNAMSIZ
)
807 ebt_print_error2("Interface name length cannot exceed %d characters", IFNAMSIZ
- 1);
808 strcpy(new_entry
->in
, optarg
);
809 if (parse_iface(new_entry
->in
, "-i"))
813 ebt_check_option2(&(replace
->flags
), OPT_LOGICALIN
);
814 if (replace
->selected_chain
> 2 && replace
->selected_chain
< NF_BR_BROUTING
)
815 ebt_print_error2("Use --logical-in only in INPUT, FORWARD, PREROUTING and BROUTING chains");
816 if (ebt_check_inverse2(optarg
))
817 new_entry
->invflags
|= EBT_ILOGICALIN
;
819 if (strlen(optarg
) >= IFNAMSIZ
)
820 goto big_iface_length
;
821 strcpy(new_entry
->logical_in
, optarg
);
822 if (parse_iface(new_entry
->logical_in
, "--logical-in"))
825 } else if (c
== 'o') {
826 ebt_check_option2(&(replace
->flags
), OPT_OUT
);
827 if (replace
->selected_chain
< 2 || replace
->selected_chain
== NF_BR_BROUTING
)
828 ebt_print_error2("Use -o only in OUTPUT, FORWARD and POSTROUTING chains");
829 if (ebt_check_inverse2(optarg
))
830 new_entry
->invflags
|= EBT_IOUT
;
832 if (strlen(optarg
) >= IFNAMSIZ
)
833 goto big_iface_length
;
834 strcpy(new_entry
->out
, optarg
);
835 if (parse_iface(new_entry
->out
, "-o"))
839 ebt_check_option2(&(replace
->flags
), OPT_LOGICALOUT
);
840 if (replace
->selected_chain
< 2 || replace
->selected_chain
== NF_BR_BROUTING
)
841 ebt_print_error2("Use --logical-out only in OUTPUT, FORWARD and POSTROUTING chains");
842 if (ebt_check_inverse2(optarg
))
843 new_entry
->invflags
|= EBT_ILOGICALOUT
;
845 if (strlen(optarg
) >= IFNAMSIZ
)
846 goto big_iface_length
;
847 strcpy(new_entry
->logical_out
, optarg
);
848 if (parse_iface(new_entry
->logical_out
, "--logical-out"))
851 } else if (c
== 'j') {
852 ebt_check_option2(&(replace
->flags
), OPT_JUMP
);
853 for (i
= 0; i
< NUM_STANDARD_TARGETS
; i
++)
854 if (!strcmp(optarg
, ebt_standard_targets
[i
])) {
855 t
= ebt_find_target(EBT_STANDARD_TARGET
);
856 ((struct ebt_standard_target
*) t
->t
)->verdict
= -i
- 1;
859 if (-i
- 1 == EBT_RETURN
&& replace
->selected_chain
< NF_BR_NUMHOOKS
) {
860 ebt_print_error2("Return target only for user defined chains");
861 } else if (i
!= NUM_STANDARD_TARGETS
)
864 if ((i
= ebt_get_chainnr(replace
, optarg
)) != -1) {
865 if (i
< NF_BR_NUMHOOKS
)
866 ebt_print_error2("Don't jump to a standard chain");
867 t
= ebt_find_target(EBT_STANDARD_TARGET
);
868 ((struct ebt_standard_target
*) t
->t
)->verdict
= i
- NF_BR_NUMHOOKS
;
871 /* Must be an extension then */
872 struct ebt_u_target
*t
;
874 t
= ebt_find_target(optarg
);
875 /* -j standard not allowed either */
876 if (!t
|| t
== (struct ebt_u_target
*)new_entry
->t
)
877 ebt_print_error2("Illegal target name '%s'", optarg
);
878 new_entry
->t
= (struct ebt_entry_target
*)t
;
879 ebt_find_target(EBT_STANDARD_TARGET
)->used
= 0;
883 } else if (c
== 's') {
884 ebt_check_option2(&(replace
->flags
), OPT_SOURCE
);
885 if (ebt_check_inverse2(optarg
))
886 new_entry
->invflags
|= EBT_ISOURCE
;
888 if (ebt_get_mac_and_mask(optarg
, new_entry
->sourcemac
, new_entry
->sourcemsk
))
889 ebt_print_error2("Problem with specified source mac '%s'", optarg
);
890 new_entry
->bitmask
|= EBT_SOURCEMAC
;
892 } else if (c
== 'd') {
893 ebt_check_option2(&(replace
->flags
), OPT_DEST
);
894 if (ebt_check_inverse2(optarg
))
895 new_entry
->invflags
|= EBT_IDEST
;
897 if (ebt_get_mac_and_mask(optarg
, new_entry
->destmac
, new_entry
->destmsk
))
898 ebt_print_error2("Problem with specified destination mac '%s'", optarg
);
899 new_entry
->bitmask
|= EBT_DESTMAC
;
901 } else if (c
== 'c') {
902 ebt_check_option2(&(replace
->flags
), OPT_COUNT
);
903 if (ebt_check_inverse2(optarg
))
904 ebt_print_error2("Unexpected '!' after -c");
905 if (optind
>= argc
|| optarg
[0] == '-' || argv
[optind
][0] == '-')
906 ebt_print_error2("Option -c needs 2 arguments");
908 new_entry
->cnt
.pcnt
= strtoull(optarg
, &buffer
, 10);
910 ebt_print_error2("Packet counter '%s' invalid", optarg
);
911 new_entry
->cnt
.bcnt
= strtoull(argv
[optind
], &buffer
, 10);
913 ebt_print_error2("Packet counter '%s' invalid", argv
[optind
]);
917 ebt_check_option2(&(replace
->flags
), OPT_PROTOCOL
);
918 if (ebt_check_inverse2(optarg
))
919 new_entry
->invflags
|= EBT_IPROTO
;
921 new_entry
->bitmask
&= ~((unsigned int)EBT_NOPROTO
);
922 i
= strtol(optarg
, &buffer
, 16);
923 if (*buffer
== '\0' && (i
< 0 || i
> 0xFFFF))
924 ebt_print_error2("Problem with the specified protocol");
925 if (*buffer
!= '\0') {
926 struct ethertypeent
*ent
;
928 if (!strcasecmp(optarg
, "LENGTH")) {
929 new_entry
->bitmask
|= EBT_802_3
;
932 ent
= getethertypebyname(optarg
);
934 ebt_print_error2("Problem with the specified Ethernet protocol '%s', perhaps "_PATH_ETHERTYPES
" is missing", optarg
);
935 new_entry
->ethproto
= ent
->e_ethertype
;
937 new_entry
->ethproto
= i
;
939 if (new_entry
->ethproto
< 0x0600)
940 ebt_print_error2("Sorry, protocols have values above or equal to 0x0600");
944 if (exec_style
== EXEC_STYLE_DAEMON
)
945 ebt_print_error2("--Lc is not supported in daemon mode");
947 ebt_check_option2(&(replace
->flags
), LIST_C
);
948 if (replace
->command
!= 'L')
949 ebt_print_error("Use --Lc with -L");
950 replace
->flags
|= LIST_C
;
954 if (exec_style
== EXEC_STYLE_DAEMON
)
955 ebt_print_error2("--Ln is not supported in daemon mode");
957 ebt_check_option2(&(replace
->flags
), LIST_N
);
958 if (replace
->command
!= 'L')
959 ebt_print_error2("Use --Ln with -L");
960 if (replace
->flags
& LIST_X
)
961 ebt_print_error2("--Lx is not compatible with --Ln");
962 replace
->flags
|= LIST_N
;
966 if (exec_style
== EXEC_STYLE_DAEMON
)
967 ebt_print_error2("--Lx is not supported in daemon mode");
969 ebt_check_option2(&(replace
->flags
), LIST_X
);
970 if (replace
->command
!= 'L')
971 ebt_print_error2("Use --Lx with -L");
972 if (replace
->flags
& LIST_N
)
973 ebt_print_error2("--Lx is not compatible with --Ln");
974 replace
->flags
|= LIST_X
;
976 case 12 : /* Lmac2 */
978 if (exec_style
== EXEC_STYLE_DAEMON
)
979 ebt_print_error("--Lmac2 is not supported in daemon mode");
981 ebt_check_option2(&(replace
->flags
), LIST_MAC2
);
982 if (replace
->command
!= 'L')
983 ebt_print_error2("Use --Lmac2 with -L");
984 replace
->flags
|= LIST_MAC2
;
986 case 8 : /* atomic-commit */
987 if (exec_style
== EXEC_STYLE_DAEMON
)
988 ebt_print_error2("--atomic-commit is not supported in daemon mode");
989 replace
->command
= c
;
991 ebt_print_error2("Multiple commands are not allowed");
992 replace
->flags
|= OPT_COMMAND
;
993 if (!replace
->filename
)
994 ebt_print_error2("No atomic file specified");
995 /* Get the information from the file */
996 ebt_get_table(replace
, 0);
997 /* We don't want the kernel giving us its counters,
998 * they would overwrite the counters extracted from
1000 replace
->num_counters
= 0;
1001 /* Make sure the table will be written to the kernel */
1002 free(replace
->filename
);
1003 replace
->filename
= NULL
;
1005 case 7 : /* atomic-init */
1006 case 10: /* atomic-save */
1007 case 11: /* init-table */
1008 if (exec_style
== EXEC_STYLE_DAEMON
) {
1010 ebt_print_error2("--atomic-init is not supported in daemon mode");
1012 ebt_print_error2("--atomic-save is not supported in daemon mode");
1013 ebt_print_error2("--init-table is not supported in daemon mode");
1015 replace
->command
= c
;
1017 ebt_print_error2("Multiple commands are not allowed");
1018 if (c
!= 11 && !replace
->filename
)
1019 ebt_print_error2("No atomic file specified");
1020 replace
->flags
|= OPT_COMMAND
;
1022 char *tmp
= replace
->filename
;
1024 /* Get the kernel table */
1025 replace
->filename
= NULL
;
1026 ebt_get_kernel_table(replace
, c
== 10 ? 0 : 1);
1027 replace
->filename
= tmp
;
1030 case 9 : /* atomic */
1031 if (exec_style
== EXEC_STYLE_DAEMON
)
1032 ebt_print_error2("--atomic is not supported in daemon mode");
1034 ebt_print_error2("--atomic has to come before the command");
1035 /* A possible memory leak here, but this is not
1036 * executed in daemon mode */
1037 replace
->filename
= (char *)malloc(strlen(optarg
) + 1);
1038 strcpy(replace
->filename
, optarg
);
1041 if (!strcmp(optarg
, "!"))
1042 ebt_check_inverse2(optarg
);
1044 ebt_print_error2("Bad argument : '%s'", optarg
);
1045 /* ebt_check_inverse() did optind++ */
1049 /* Is it a target option? */
1050 t
= (struct ebt_u_target
*)new_entry
->t
;
1051 if ((t
->parse(c
- t
->option_offset
, argv
, argc
, new_entry
, &t
->flags
, &t
->t
))) {
1052 if (ebt_errormsg
[0] != '\0')
1054 goto check_extension
;
1057 /* Is it a match_option? */
1058 for (m
= ebt_matches
; m
; m
= m
->next
)
1059 if (m
->parse(c
- m
->option_offset
, argv
, argc
, new_entry
, &m
->flags
, &m
->m
))
1063 if (ebt_errormsg
[0] != '\0')
1066 ebt_add_match(new_entry
, m
);
1069 goto check_extension
;
1072 /* Is it a watcher option? */
1073 for (w
= ebt_watchers
; w
; w
= w
->next
)
1074 if (w
->parse(c
- w
->option_offset
, argv
, argc
, new_entry
, &w
->flags
, &w
->w
))
1077 if (w
== NULL
&& c
== '?')
1078 ebt_print_error2("Unknown argument: '%s'", argv
[optind
- 1], (char)optopt
, (char)c
);
1079 else if (w
== NULL
) {
1080 if (!strcmp(t
->name
, "standard"))
1081 ebt_print_error2("Unknown argument: don't forget the -t option");
1083 ebt_print_error2("Target-specific option does not correspond with specified target");
1085 if (ebt_errormsg
[0] != '\0')
1088 ebt_add_watcher(new_entry
, w
);
1092 if (replace
->command
!= 'A' && replace
->command
!= 'I' &&
1093 replace
->command
!= 'D' && replace
->command
!= 'C')
1094 ebt_print_error2("Extensions only for -A, -I, -D and -C");
1099 /* Just in case we didn't catch an error */
1100 if (ebt_errormsg
[0] != '\0')
1103 if (!(table
= ebt_find_table(replace
->name
)))
1104 ebt_print_error2("Bad table name");
1106 if (replace
->command
== 'h' && !(replace
->flags
& OPT_ZERO
)) {
1108 if (exec_style
== EXEC_STYLE_PRG
)
1112 /* Do the final checks */
1113 if (replace
->command
== 'A' || replace
->command
== 'I' ||
1114 replace
->command
== 'D' || replace
->command
== 'C') {
1115 /* This will put the hook_mask right for the chains */
1116 ebt_check_for_loops(replace
);
1117 if (ebt_errormsg
[0] != '\0')
1119 entries
= ebt_to_chain(replace
);
1120 m_l
= new_entry
->m_list
;
1121 w_l
= new_entry
->w_list
;
1122 t
= (struct ebt_u_target
*)new_entry
->t
;
1124 m
= (struct ebt_u_match
*)(m_l
->m
);
1125 m
->final_check(new_entry
, m
->m
, replace
->name
,
1126 entries
->hook_mask
, 0);
1127 if (ebt_errormsg
[0] != '\0')
1132 w
= (struct ebt_u_watcher
*)(w_l
->w
);
1133 w
->final_check(new_entry
, w
->w
, replace
->name
,
1134 entries
->hook_mask
, 0);
1135 if (ebt_errormsg
[0] != '\0')
1139 t
->final_check(new_entry
, t
->t
, replace
->name
,
1140 entries
->hook_mask
, 0);
1141 if (ebt_errormsg
[0] != '\0')
1144 /* So, the extensions can work with the host endian.
1145 * The kernel does not have to do this of course */
1146 new_entry
->ethproto
= htons(new_entry
->ethproto
);
1148 if (replace
->command
== 'P') {
1149 if (replace
->selected_chain
< NF_BR_NUMHOOKS
&& policy
== EBT_RETURN
)
1150 ebt_print_error2("Policy RETURN only allowed for user defined chains");
1151 ebt_change_policy(replace
, policy
);
1152 if (ebt_errormsg
[0] != '\0')
1154 } else if (replace
->command
== 'L') {
1156 if (!(replace
->flags
& OPT_ZERO
) && exec_style
== EXEC_STYLE_PRG
)
1159 if (replace
->flags
& OPT_ZERO
) {
1160 replace
->selected_chain
= zerochain
;
1161 ebt_zero_counters(replace
);
1162 } else if (replace
->command
== 'F') {
1163 ebt_flush_chains(replace
);
1164 } else if (replace
->command
== 'A' || replace
->command
== 'I') {
1165 ebt_add_rule(replace
, new_entry
, rule_nr
);
1166 if (ebt_errormsg
[0] != '\0')
1168 /* Makes undoing the add easier (jumps to delete_the_rule) */
1171 rule_nr_end
= rule_nr
;
1173 /* a jump to a udc requires checking for loops */
1174 if (!strcmp(new_entry
->t
->u
.name
, EBT_STANDARD_TARGET
) &&
1175 ((struct ebt_standard_target
*)(new_entry
->t
))->verdict
>= 0) {
1176 /* FIXME: this can be done faster */
1177 ebt_check_for_loops(replace
);
1178 if (ebt_errormsg
[0] != '\0')
1179 goto delete_the_rule
;
1182 /* Do the final_check(), for all entries.
1183 * This is needed when adding a rule that has a chain target */
1185 while (++i
!= replace
->num_chains
) {
1186 struct ebt_u_entry
*e
;
1188 entries
= replace
->chains
[i
];
1190 if (i
< NF_BR_NUMHOOKS
)
1193 ebt_print_bug("whoops\n");
1195 e
= entries
->entries
->next
;
1196 while (e
!= entries
->entries
) {
1197 /* Userspace extensions use host endian */
1198 e
->ethproto
= ntohs(e
->ethproto
);
1199 ebt_do_final_checks(replace
, e
, entries
);
1200 if (ebt_errormsg
[0] != '\0')
1201 goto delete_the_rule
;
1202 e
->ethproto
= htons(e
->ethproto
);
1206 /* Don't reuse the added rule */
1208 } else if (replace
->command
== 'D') {
1210 ebt_delete_rule(replace
, new_entry
, rule_nr
, rule_nr_end
);
1211 if (ebt_errormsg
[0] != '\0')
1213 } else if (replace
->command
== 'C') {
1214 ebt_change_counters(replace
, new_entry
, rule_nr
, rule_nr_end
, &(new_entry
->cnt_surplus
), chcounter
);
1215 if (ebt_errormsg
[0] != '\0')
1218 /* Commands -N, -E, -X, --atomic-commit, --atomic-commit, --atomic-save,
1219 * --init-table fall through */
1221 if (ebt_errormsg
[0] != '\0')
1224 table
->check(replace
);
1226 if (exec_style
== EXEC_STYLE_PRG
) {/* Implies ebt_errormsg[0] == '\0' */
1227 ebt_deliver_table(replace
);
1229 if (replace
->nentries
)
1230 ebt_deliver_counters(replace
);