summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ebtables.c64
-rw-r--r--extensions/ebt_arp.c8
-rw-r--r--extensions/ebt_ip.c3
-rw-r--r--extensions/ebt_log.c3
-rw-r--r--extensions/ebt_nat.c10
-rw-r--r--extensions/ebt_redirect.c3
-rw-r--r--extensions/ebt_standard.c3
-rw-r--r--extensions/ebt_vlan.c2
-rw-r--r--include/ebtables_u.h6
9 files changed, 79 insertions, 23 deletions
diff --git a/ebtables.c b/ebtables.c
index d4c6a6b..c58c0c6 100644
--- a/ebtables.c
+++ b/ebtables.c
@@ -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,