diff options
-rw-r--r-- | ebtables.c | 64 | ||||
-rw-r--r-- | extensions/ebt_arp.c | 8 | ||||
-rw-r--r-- | extensions/ebt_ip.c | 3 | ||||
-rw-r--r-- | extensions/ebt_log.c | 3 | ||||
-rw-r--r-- | extensions/ebt_nat.c | 10 | ||||
-rw-r--r-- | extensions/ebt_redirect.c | 3 | ||||
-rw-r--r-- | extensions/ebt_standard.c | 3 | ||||
-rw-r--r-- | extensions/ebt_vlan.c | 2 | ||||
-rw-r--r-- | include/ebtables_u.h | 6 |
9 files changed, 79 insertions, 23 deletions
@@ -1451,6 +1451,33 @@ int getmac_and_mask(char *from, char *to, char *mask) return 0; } +void do_final_checks(struct ebt_u_entry *e, struct ebt_u_entries *entries) +{ + struct ebt_u_match_list *m_l; + struct ebt_u_watcher_list *w_l; + struct ebt_u_target *t; + struct ebt_u_match *m; + struct ebt_u_watcher *w; + + m_l = e->m_list; + w_l = e->w_list; + while (m_l) { + m = find_match(m_l->m->u.name); + m->final_check(e, m_l->m, replace.name, + entries->hook_mask, 1); + m_l = m_l->next; + } + while (w_l) { + w = find_watcher(w_l->w->u.name); + w->final_check(e, w_l->w, replace.name, + entries->hook_mask, 1); + w_l = w_l->next; + } + t = find_target(e->t->u.name); + t->final_check(e, e->t, replace.name, + entries->hook_mask, 1); +} + int check_inverse(const char option[]) { if (strcmp(option, "!") == 0) { @@ -1490,9 +1517,9 @@ int main(int argc, char *argv[]) struct ebt_u_target *t; struct ebt_u_match *m; struct ebt_u_watcher *w; - struct ebt_u_match_list *m_l; + struct ebt_u_match_list *m_l; struct ebt_u_watcher_list *w_l; - struct ebt_u_entries *entries; + struct ebt_u_entries *entries; const char *modprobe = NULL; // initialize the table name, OPT_ flags, selected hook and command @@ -1850,6 +1877,8 @@ int main(int argc, char *argv[]) print_error("Return target" " only for user defined chains"); } + if (i != NUM_STANDARD_TARGETS) + break; if ((i = get_hooknr(optarg)) != -1) { if (i < NF_BR_NUMHOOKS) print_error("don't jump" @@ -2003,19 +2032,18 @@ int main(int argc, char *argv[]) while (m_l) { m = (struct ebt_u_match *)(m_l->m); m->final_check(new_entry, m->m, replace.name, - entries->hook_mask); + entries->hook_mask, 0); m_l = m_l->next; } while (w_l) { w = (struct ebt_u_watcher *)(w_l->w); w->final_check(new_entry, w->w, replace.name, - entries->hook_mask); + entries->hook_mask, 0); w_l = w_l->next; } t->final_check(new_entry, t->t, replace.name, - entries->hook_mask); + entries->hook_mask, 0); } - // so, the extensions can work with the host endian // the kernel does not have to do this ofcourse new_entry->ethproto = htons(new_entry->ethproto); @@ -2037,6 +2065,29 @@ int main(int argc, char *argv[]) } else if (replace.command == 'A' || replace.command == 'I') { add_rule(rule_nr); check_for_loops(); + // do the final_check(), for all entries + // needed when adding a rule that has a chain target + i = -1; + while (1) { + struct ebt_u_entry *e; + + i++; + entries = nr_to_chain(i); + if (!entries) { + if (i < NF_BR_NUMHOOKS) + continue; + else + break; + } + e = entries->entries; + while (e) { + // userspace extensions use host endian + e->ethproto = ntohs(e->ethproto); + do_final_checks(e, entries); + e->ethproto = htons(e->ethproto); + e = e->next; + } + } } else if (replace.command == 'D') delete_rule(rule_nr); // commands -N, -E, -X fall through @@ -2048,6 +2099,5 @@ int main(int argc, char *argv[]) if (counterchanges) deliver_counters(&replace, counterchanges); -// list_rules(); return 0; } diff --git a/extensions/ebt_arp.c b/extensions/ebt_arp.c index d094b68..d088563 100644 --- a/extensions/ebt_arp.c +++ b/extensions/ebt_arp.c @@ -75,9 +75,8 @@ void parse_ip_address(char *address, __u32 *addr, __u32 *msk); #define OPT_PTYPE 0x04 #define OPT_IP_S 0x08 #define OPT_IP_D 0x10 -static int parse(int c, char **argv, int argc, - const struct ebt_u_entry *entry, unsigned int *flags, - struct ebt_entry_match **match) +static int parse(int c, char **argv, int argc, const struct ebt_u_entry *entry, + unsigned int *flags, struct ebt_entry_match **match) { struct ebt_arp_info *arpinfo = (struct ebt_arp_info *)(*match)->data; int i; @@ -177,7 +176,8 @@ static int parse(int c, char **argv, int argc, } static void final_check(const struct ebt_u_entry *entry, -const struct ebt_entry_match *match, const char *name, unsigned int hook_mask) + const struct ebt_entry_match *match, const char *name, + unsigned int hook_mask, unsigned int time) { if (entry->bitmask & EBT_NOPROTO || entry->bitmask & EBT_802_3 || (entry->ethproto != ETH_P_ARP && entry->ethproto != ETH_P_RARP)) diff --git a/extensions/ebt_ip.c b/extensions/ebt_ip.c index cb425f9..71d7f30 100644 --- a/extensions/ebt_ip.c +++ b/extensions/ebt_ip.c @@ -218,7 +218,8 @@ static int parse(int c, char **argv, int argc, const struct ebt_u_entry *entry, } static void final_check(const struct ebt_u_entry *entry, - const struct ebt_entry_match *match, const char *name, unsigned int hook_mask) + const struct ebt_entry_match *match, const char *name, + unsigned int hook_mask, unsigned int time) { if (entry->bitmask & EBT_NOPROTO || entry->bitmask & EBT_802_3 || entry->ethproto != ETH_P_IP) diff --git a/extensions/ebt_log.c b/extensions/ebt_log.c index 1dca3ad..b6e62eb 100644 --- a/extensions/ebt_log.c +++ b/extensions/ebt_log.c @@ -142,7 +142,8 @@ static int parse(int c, char **argv, int argc, const struct ebt_u_entry *entry, } static void final_check(const struct ebt_u_entry *entry, - const struct ebt_entry_watcher *watcher, const char *name, unsigned int hook_mask) + const struct ebt_entry_watcher *watcher, const char *name, + unsigned int hook_mask, unsigned int time) { return; } diff --git a/extensions/ebt_nat.c b/extensions/ebt_nat.c index fe7cd1a..d94763a 100644 --- a/extensions/ebt_nat.c +++ b/extensions/ebt_nat.c @@ -136,22 +136,24 @@ static int parse_d(int c, char **argv, int argc, } static void final_check_s(const struct ebt_u_entry *entry, - const struct ebt_entry_target *target, const char *name, unsigned int hook_mask) + const struct ebt_entry_target *target, const char *name, + unsigned int hook_mask, unsigned int time) { if (!(hook_mask & (1 << NF_BR_POST_ROUTING)) || strcmp(name, "nat")) print_error("Wrong chain for snat"); - if (to_source_supplied == 0) + if (time == 0 && to_source_supplied == 0) print_error("No snat address supplied"); } static void final_check_d(const struct ebt_u_entry *entry, - const struct ebt_entry_target *target, const char *name, unsigned int hook_mask) + const struct ebt_entry_target *target, const char *name, + unsigned int hook_mask, unsigned int time) { if (((hook_mask & ~((1 << NF_BR_PRE_ROUTING) | (1 << NF_BR_LOCAL_OUT))) || strcmp(name, "nat")) && ((hook_mask & ~(1 << NF_BR_BROUTING)) || strcmp(name, "broute"))) print_error("Wrong chain for dnat"); - if (to_dest_supplied == 0) + if (time == 0 && to_dest_supplied == 0) print_error("No dnat address supplied"); } diff --git a/extensions/ebt_redirect.c b/extensions/ebt_redirect.c index 5d329e7..ea0a504 100644 --- a/extensions/ebt_redirect.c +++ b/extensions/ebt_redirect.c @@ -59,7 +59,8 @@ static int parse(int c, char **argv, int argc, } static void final_check(const struct ebt_u_entry *entry, - const struct ebt_entry_target *target, const char *name, unsigned int hook_mask) + const struct ebt_entry_target *target, const char *name, + unsigned int hook_mask, unsigned int time) { if ( ((hook_mask & ~(1 << NF_BR_PRE_ROUTING)) || strcmp(name, "nat")) && ((hook_mask & ~(1 << NF_BR_BROUTING)) || strcmp(name, "broute")) ) diff --git a/extensions/ebt_standard.c b/extensions/ebt_standard.c index 726a1ab..95e00a5 100644 --- a/extensions/ebt_standard.c +++ b/extensions/ebt_standard.c @@ -26,7 +26,8 @@ static int parse(int c, char **argv, int argc, const struct ebt_u_entry *entry, } static void final_check(const struct ebt_u_entry *entry, - const struct ebt_entry_target *target, const char *name, unsigned int hook_mask) + const struct ebt_entry_target *target, const char *name, + unsigned int hook_mask, unsigned int time) { } diff --git a/extensions/ebt_vlan.c b/extensions/ebt_vlan.c index 05ee992..f74b26f 100644 --- a/extensions/ebt_vlan.c +++ b/extensions/ebt_vlan.c @@ -193,7 +193,7 @@ parse (int c, char **argv, int argc, static void final_check (const struct ebt_u_entry *entry, const struct ebt_entry_match *match, - const char *name, unsigned int hook_mask) + const char *name, unsigned int hook_mask, unsigned int time) { /* * Is any proto supplied there? Or specified proto isn't 802.1Q? diff --git a/include/ebtables_u.h b/include/ebtables_u.h index 4c4168b..d86a7c7 100644 --- a/include/ebtables_u.h +++ b/include/ebtables_u.h @@ -119,7 +119,7 @@ struct ebt_u_match struct ebt_entry_match **match); void (*final_check)(const struct ebt_u_entry *entry, const struct ebt_entry_match *match, - const char *name, unsigned int hook_mask); + const char *name, unsigned int hook_mask, unsigned int time); void (*print)(const struct ebt_u_entry *entry, const struct ebt_entry_match *match); int (*compare)(const struct ebt_entry_match *m1, @@ -146,7 +146,7 @@ struct ebt_u_watcher struct ebt_entry_watcher **watcher); void (*final_check)(const struct ebt_u_entry *entry, const struct ebt_entry_watcher *watch, const char *name, - unsigned int hook_mask); + unsigned int hook_mask, unsigned int time); void (*print)(const struct ebt_u_entry *entry, const struct ebt_entry_watcher *watcher); int (*compare)(const struct ebt_entry_watcher *w1, @@ -170,7 +170,7 @@ struct ebt_u_target struct ebt_entry_target **target); void (*final_check)(const struct ebt_u_entry *entry, const struct ebt_entry_target *target, const char *name, - unsigned int hook_mask); + unsigned int hook_mask, unsigned int time); void (*print)(const struct ebt_u_entry *entry, const struct ebt_entry_target *target); int (*compare)(const struct ebt_entry_target *t1, |