summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--communication.c126
-rw-r--r--ebtables.c71
-rw-r--r--extensions/ebt_standard.c3
-rw-r--r--include/ebtables_u.h21
-rw-r--r--libebtc.c351
5 files changed, 156 insertions, 416 deletions
diff --git a/communication.c b/communication.c
index bfe9110..01b69c9 100644
--- a/communication.c
+++ b/communication.c
@@ -46,13 +46,12 @@ static int get_sockfd()
return ret;
}
-static struct ebt_replace * translate_user2kernel(struct ebt_u_replace *u_repl)
+static struct ebt_replace *translate_user2kernel(struct ebt_u_replace *u_repl)
{
struct ebt_replace *new;
struct ebt_u_entry *e;
struct ebt_u_match_list *m_l;
struct ebt_u_watcher_list *w_l;
- struct ebt_u_chain_list *cl;
struct ebt_u_entries *entries;
char *p, *base;
int i, j;
@@ -66,30 +65,11 @@ static struct ebt_replace * translate_user2kernel(struct ebt_u_replace *u_repl)
new->nentries = u_repl->nentries;
new->num_counters = u_repl->num_counters;
new->counters = sparc_cast u_repl->counters;
- /* Determine nr of udc */
- i = 0;
- cl = u_repl->udc;
- while (cl) {
- i++;
- cl = cl->next;
- }
- i += NF_BR_NUMHOOKS;
- chain_offsets = (unsigned int *)malloc(i * sizeof(unsigned int));
+ chain_offsets = (unsigned int *)malloc(u_repl->num_chains * sizeof(unsigned int));
/* Determine size */
- i = 0;
- cl = u_repl->udc;
- while (1) {
- if (i < NF_BR_NUMHOOKS) {
- if (!(new->valid_hooks & (1 << i))) {
- i++;
- continue;
- }
- entries = u_repl->hook_entry[i];
- } else {
- if (!cl)
- break;
- entries = cl->udc;
- }
+ for (i = 0; i < u_repl->num_chains; i++) {
+ if (!(entries = u_repl->chains[i]))
+ continue;
chain_offsets[i] = entries_size;
entries_size += sizeof(struct ebt_entries);
j = 0;
@@ -117,9 +97,6 @@ static struct ebt_replace * translate_user2kernel(struct ebt_u_replace *u_repl)
if (j != entries->nentries)
ebt_print_bug("Wrong nentries: %d != %d, hook = %s", j,
entries->nentries, entries->name);
- if (i >= NF_BR_NUMHOOKS)
- cl = cl->next;
- i++;
}
new->entries_size = entries_size;
@@ -129,24 +106,14 @@ static struct ebt_replace * translate_user2kernel(struct ebt_u_replace *u_repl)
/* Put everything in one block */
new->entries = sparc_cast p;
- i = 0;
- cl = u_repl->udc;
- while (1) {
+ for (i = 0; i < u_repl->num_chains; i++) {
struct ebt_entries *hlp;
hlp = (struct ebt_entries *)p;
- if (i < NF_BR_NUMHOOKS) {
- if (!(new->valid_hooks & (1 << i))) {
- i++;
- continue;
- }
- entries = u_repl->hook_entry[i];
+ if (!(entries = u_repl->chains[i]))
+ continue;
+ if (i < NF_BR_NUMHOOKS)
new->hook_entry[i] = sparc_cast hlp;
- } else {
- if (!cl)
- break;
- entries = cl->udc;
- }
hlp->nentries = entries->nentries;
hlp->policy = entries->policy;
strcpy(hlp->name, entries->name);
@@ -206,9 +173,6 @@ static struct ebt_replace * translate_user2kernel(struct ebt_u_replace *u_repl)
tmp->next_offset = p - base;
e = e->next;
}
- if (i >= NF_BR_NUMHOOKS)
- cl = cl->next;
- i++;
}
/* Sanity check */
@@ -350,7 +314,7 @@ void ebt_deliver_counters(struct ebt_u_replace *u_repl, int exec_style)
new = newcounters;
while (cc) {
if (!next) {
- while (!(entries = ebt_nr_to_chain(u_repl, chainnr++)))
+ while (!(entries = u_repl->chains[chainnr++]))
if (chainnr > NF_BR_NUMHOOKS)
goto letscontinue;/* Prevent infinite loop for -D x:-1 */
if (!(next = entries->entries))
@@ -551,19 +515,14 @@ ebt_translate_entry(struct ebt_entry *e, unsigned int *hook, int *n, int *cnt,
char *tmp = base;
int verdict = ((struct ebt_standard_target *)t)->verdict;
int i;
- struct ebt_u_chain_list *cl;
if (verdict >= 0) {
tmp += verdict;
- cl = u_repl->udc;
- i = 0;
- while (cl && cl->kernel_start != tmp) {
- i++;
- cl = cl->next;
- }
- if (!cl)
- ebt_print_bug("Can't find udc for "
- "jump");
+ for (i = NF_BR_NUMHOOKS; i < u_repl->num_chains; i++)
+ if (u_repl->chains[i]->kernel_start == tmp)
+ break;
+ if (i == u_repl->num_chains)
+ ebt_print_bug("Can't find udc for jump");
((struct ebt_standard_target *)new->t)->verdict = i;
}
}
@@ -577,7 +536,6 @@ ebt_translate_entry(struct ebt_entry *e, unsigned int *hook, int *n, int *cnt,
} else { /* A new chain */
int i;
struct ebt_entries *entries = (struct ebt_entries *)e;
- struct ebt_u_chain_list *cl;
if (*n != *cnt)
ebt_print_bug("Nr of entries in the chain is wrong");
@@ -587,15 +545,7 @@ ebt_translate_entry(struct ebt_entry *e, unsigned int *hook, int *n, int *cnt,
if (valid_hooks & (1 << i))
break;
*hook = i;
- /* Makes use of fact that standard chains come before udc */
- if (i >= NF_BR_NUMHOOKS) { /* Udc */
- i -= NF_BR_NUMHOOKS;
- cl = u_repl->udc;
- while (i-- > 0)
- cl = cl->next;
- *u_e = &(cl->udc->entries);
- } else
- *u_e = &(u_repl->hook_entry[*hook]->entries);
+ *u_e = &(u_repl->chains[*hook]->entries);
return 0;
}
}
@@ -608,39 +558,20 @@ ebt_translate_chains(struct ebt_entry *e, unsigned int *hook,
int i;
struct ebt_entries *entries = (struct ebt_entries *)e;
struct ebt_u_entries *new;
- struct ebt_u_chain_list **chain_list;
if (!(e->bitmask & EBT_ENTRY_OR_ENTRIES)) {
for (i = *hook + 1; i < NF_BR_NUMHOOKS; i++)
if (valid_hooks & (1 << i))
break;
- /* Makes use of fact that standard chains come before udc */
- if (i >= NF_BR_NUMHOOKS) { /* Udc */
- chain_list = &u_repl->udc;
- /* Add in the back */
- while (*chain_list)
- chain_list = &((*chain_list)->next);
- *chain_list = (struct ebt_u_chain_list *)
- malloc(sizeof(struct ebt_u_chain_list));
- if (!(*chain_list))
- ebt_print_memory();
- (*chain_list)->next = NULL;
- (*chain_list)->udc = (struct ebt_u_entries *)
- malloc(sizeof(struct ebt_u_entries));
- if (!((*chain_list)->udc))
- ebt_print_memory();
- new = (*chain_list)->udc;
- /* ebt_translate_entry depends on this for knowing
- * to which chain is being jumped */
- (*chain_list)->kernel_start = (char *)e;
- } else {
- *hook = i;
- new = (struct ebt_u_entries *)
- malloc(sizeof(struct ebt_u_entries));
- if (!new)
- ebt_print_memory();
- u_repl->hook_entry[*hook] = new;
- }
+ new = (struct ebt_u_entries *)malloc(sizeof(struct ebt_u_entries));
+ if (!new)
+ ebt_print_memory();
+ if (i == u_repl->max_chains)
+ ebt_double_chains(u_repl);
+ u_repl->chains[i] = new;
+ if (i >= NF_BR_NUMHOOKS)
+ new->kernel_start = (char *)e;
+ *hook = i;
new->nentries = entries->nentries;
new->policy = entries->policy;
new->entries = NULL;
@@ -797,7 +728,6 @@ int ebt_get_table(struct ebt_u_replace *u_repl, int init)
u_repl->nentries = repl.nentries;
u_repl->num_counters = repl.num_counters;
u_repl->counters = repl.counters;
- u_repl->udc = NULL;
u_repl->counterchanges = NULL;
for (i = 0; i < repl.nentries; i++) {
new_cc = (struct ebt_cntchanges *)
@@ -810,10 +740,16 @@ int ebt_get_table(struct ebt_u_replace *u_repl, int init)
*prev_cc = new_cc;
prev_cc = &(new_cc->next);
}
+ u_repl->chains = (struct ebt_u_entries **)calloc(EBT_ORI_MAX_CHAINS, sizeof(void *));
+ u_repl->max_chains = EBT_ORI_MAX_CHAINS;
hook = -1;
/* FIXME: Clean up when an error is encountered */
EBT_ENTRY_ITERATE(repl.entries, repl.entries_size, ebt_translate_chains,
&hook, u_repl, u_repl->valid_hooks);
+ if (hook >= NF_BR_NUMHOOKS)
+ u_repl->num_chains = hook + 1;
+ else
+ u_repl->num_chains = NF_BR_NUMHOOKS;
i = 0; /* Holds the expected nr. of entries for the chain */
j = 0; /* Holds the up to now counted entries for the chain */
k = 0; /* Holds the total nr. of entries, should equal u_repl->nentries afterwards */
diff --git a/ebtables.c b/ebtables.c
index 08a9e57..717c66b 100644
--- a/ebtables.c
+++ b/ebtables.c
@@ -406,73 +406,24 @@ ATOMIC_ENV_VARIABLE " : if set <FILE> (see above) will equal its value"
static void list_rules()
{
int i;
-#ifdef EBT_DEBUG
- int j;
-#endif
struct ebt_cntchanges *cc = replace->counterchanges;
if (!(replace->flags & LIST_X))
printf("Bridge table: %s\n", table->name);
- if (replace->selected_chain != -1) {
-#ifdef EBT_DEBUG
-
- for (i = 0; i < replace->selected_chain; i++) {
- if (i < NF_BR_NUMHOOKS && !(replace->hook_entry[i]))
- continue;
- j = ebt_nr_to_chain(replace, i)->nentries;
- while (j) {
- if (cc->type != CNT_DEL)
- j--;
- cc = cc->next;
- }
- }
-#endif
+ if (replace->selected_chain != -1)
list_em(ebt_to_chain(replace), cc);
- } else {
- struct ebt_u_chain_list *cl = replace->udc;
-
+ else {
/* Create new chains and rename standard chains when necessary */
- if (replace->flags & LIST_X) {
- while (cl) {
- printf("ebtables -t %s -N %s\n", replace->name,
- cl->udc->name);
- cl = cl->next;
- }
- cl = replace->udc;
+ if (replace->flags & LIST_X && replace->num_chains > NF_BR_NUMHOOKS) {
+ for (i = NF_BR_NUMHOOKS; i < replace->num_chains; i++)
+ printf("ebtables -t %s -N %s\n", replace->name, replace->chains[i]->name);
for (i = 0; i < NF_BR_NUMHOOKS; i++)
- if (replace->hook_entry[i] &&
- strcmp(replace->hook_entry[i]->name, ebt_hooknames[i]))
- printf("ebtables -t %s -E %s %s\n",
- replace->name, ebt_hooknames[i],
- replace->hook_entry[i]->name);
- }
- i = 0;
- while (1) {
- if (i < NF_BR_NUMHOOKS) {
- if (replace->hook_entry[i]) {
- list_em(replace->hook_entry[i], cc);
-#ifdef EBT_DEBUG
- j = replace->hook_entry[i]->nentries;
-#endif
- }
- } else {
- if (!cl)
- break;
- list_em(cl->udc, cc);
-#ifdef EBT_DEBUG
- j = cl->udc->nentries;
-#endif
- cl = cl->next;
- }
-#ifdef EBT_DEBUG
- while (j) {
- if (cc->type != CNT_DEL)
- j--;
- cc = cc->next;
- }
-#endif
- i++;
+ if (replace->chains[i] && strcmp(replace->chains[i]->name, ebt_hooknames[i]))
+ printf("ebtables -t %s -E %s %s\n", replace->name, ebt_hooknames[i], replace->chains[i]->name);
}
+ for (i = 0; i < replace->num_chains; i++)
+ if (replace->chains[i])
+ list_em(replace->chains[i], cc);
}
}
@@ -1223,7 +1174,7 @@ check_extension:
struct ebt_u_entry *e;
i++;
- entries = ebt_nr_to_chain(replace, i);
+ entries = replace->chains[i];
if (!entries) {
if (i < NF_BR_NUMHOOKS)
continue;
diff --git a/extensions/ebt_standard.c b/extensions/ebt_standard.c
index 1420d1d..8059f66 100644
--- a/extensions/ebt_standard.c
+++ b/extensions/ebt_standard.c
@@ -47,8 +47,7 @@ static void print(const struct ebt_u_entry *entry,
if (verdict >= 0) {
struct ebt_u_entries *entries;
- entries = ebt_nr_to_chain(entry->replace,
- verdict + NF_BR_NUMHOOKS);
+ entries = entry->replace->chains[verdict + NF_BR_NUMHOOKS];
printf("%s", entries->name);
return;
}
diff --git a/include/ebtables_u.h b/include/ebtables_u.h
index 3f1a8cf..c74118b 100644
--- a/include/ebtables_u.h
+++ b/include/ebtables_u.h
@@ -43,19 +43,11 @@ struct ebt_u_entries
unsigned int counter_offset;
/* used for udc */
unsigned int hook_mask;
+ char *kernel_start;
char name[EBT_CHAIN_MAXNAMELEN];
struct ebt_u_entry *entries;
};
-struct ebt_u_chain_list
-{
- struct ebt_u_entries *udc;
- struct ebt_u_chain_list *next;
- /* this is only used internally, in communication.c */
- char *kernel_start;
-};
-
-struct ebt_cntchanges;
struct ebt_cntchanges
{
unsigned short type;
@@ -63,15 +55,16 @@ struct ebt_cntchanges
struct ebt_cntchanges *next;
};
+#define EBT_ORI_MAX_CHAINS 10
struct ebt_u_replace
{
char name[EBT_TABLE_MAXNAMELEN];
unsigned int valid_hooks;
/* nr of rules in the table */
unsigned int nentries;
- struct ebt_u_entries *hook_entry[NF_BR_NUMHOOKS];
- /* user defined chains (udc) list */
- struct ebt_u_chain_list *udc;
+ unsigned int num_chains;
+ unsigned int max_chains;
+ struct ebt_u_entries **chains;
/* nr of counters userspace expects back */
unsigned int num_counters;
/* where the kernel will put the old counters */
@@ -239,11 +232,10 @@ void ebt_list_extensions();
void ebt_initialize_entry(struct ebt_u_entry *e);
void ebt_cleanup_replace(struct ebt_u_replace *replace);
void ebt_reinit_extensions();
+void ebt_double_chains(struct ebt_u_replace *replace);
void ebt_free_u_entry(struct ebt_u_entry *e);
struct ebt_u_entries *ebt_name_to_chain(const struct ebt_u_replace *replace,
const char* arg);
-struct ebt_u_entries *ebt_nr_to_chain(const struct ebt_u_replace *replace,
- int nr);
struct ebt_u_entries *ebt_to_chain(const struct ebt_u_replace *replace);
struct ebt_u_entries *ebt_name_to_chain(const struct ebt_u_replace *replace,
const char* arg);
@@ -302,6 +294,7 @@ int do_command(int argc, char *argv[], int exec_style,
struct ethertypeent *parseethertypebynumber(int type);
+#define ebt_to_chain(repl) repl->chains[repl->selected_chain]
#define ebt_print_bug(format, args...) \
__ebt_print_bug(__FILE__, __LINE__, format, ##args)
#define ebt_print_error(format,args...) __ebt_print_error(format, ##args);
diff --git a/libebtc.c b/libebtc.c
index 7774889..451e9c2 100644
--- a/libebtc.c
+++ b/libebtc.c
@@ -34,7 +34,6 @@
#include <sys/wait.h>
static void decrease_chain_jumps(struct ebt_u_replace *replace);
-static void remove_udc(struct ebt_u_replace *replace);
static int iterate_entries(struct ebt_u_replace *replace, int type);
/* The standard names */
@@ -180,7 +179,6 @@ void ebt_cleanup_replace(struct ebt_u_replace *replace)
{
int i;
struct ebt_u_entries *entries;
- struct ebt_u_chain_list *udc1, *udc2;
struct ebt_cntchanges *cc1, *cc2;
struct ebt_u_entry *u_e1, *u_e2;
@@ -196,16 +194,9 @@ void ebt_cleanup_replace(struct ebt_u_replace *replace)
free(replace->counters);
replace->counters = NULL;
- i = -1;
- while (1) {
- i++;
- entries = ebt_nr_to_chain(replace, i);
- if (!entries) {
- if (i < NF_BR_NUMHOOKS)
- continue;
- else
- break;
- }
+ for (i = 0; i < replace->num_chains; i++) {
+ if (!(entries = replace->chains[i]))
+ continue;
u_e1 = entries->entries;
while (u_e1) {
ebt_free_u_entry(u_e1);
@@ -213,19 +204,9 @@ void ebt_cleanup_replace(struct ebt_u_replace *replace)
free(u_e1);
u_e1 = u_e2;
}
+ free(entries);
+ replace->chains[i] = NULL;
}
- for (i = 0; i < NF_BR_NUMHOOKS; i++) {
- free(replace->hook_entry[i]);
- replace->hook_entry[i] = NULL;
- }
- udc1 = replace->udc;
- while (udc1) {
- free(udc1->udc);
- udc2 = udc1->next;
- free(udc1);
- udc1 = udc2;
- }
- replace->udc = NULL;
cc1 = replace->counterchanges;
while (cc1) {
cc2 = cc1->next;
@@ -368,55 +349,18 @@ int ebtables_insmod(const char *modname)
return 0;
}
-/* Gives back a pointer to the chain base, based on nr.
- * If nr >= NF_BR_NUMHOOKS you'll get back a user-defined chain.
- * Returns NULL on failure. */
-struct ebt_u_entries *ebt_nr_to_chain(const struct ebt_u_replace *replace, int nr)
-{
- if (nr == -1)
- return NULL;
- if (nr < NF_BR_NUMHOOKS)
- return replace->hook_entry[nr];
- else {
- int i;
- struct ebt_u_chain_list *cl = replace->udc;
-
- i = nr - NF_BR_NUMHOOKS;
- while (i > 0 && cl) {
- cl = cl->next;
- i--;
- }
- if (cl)
- return cl->udc;
- else
- return NULL;
- }
-}
-
-/* Gives back a pointer to the chain base of selected_chain */
-struct ebt_u_entries *ebt_to_chain(const struct ebt_u_replace *replace)
-{
- return ebt_nr_to_chain(replace, replace->selected_chain);
-}
-
/* Parse the chain name and return a pointer to the chain base.
* Returns NULL on failure. */
-struct ebt_u_entries *ebt_name_to_chain(const struct ebt_u_replace *replace,
- const char* arg)
+struct ebt_u_entries *ebt_name_to_chain(const struct ebt_u_replace *replace, const char* arg)
{
int i;
- struct ebt_u_chain_list *cl = replace->udc;
+ struct ebt_u_entries *chain;
- for (i = 0; i < NF_BR_NUMHOOKS; i++) {
- if (!replace->hook_entry[i])
+ for (i = 0; i < replace->num_chains; i++) {
+ if (!(chain = replace->chains[i]))
continue;
- if (!strcmp(arg, replace->hook_entry[i]->name))
- return replace->hook_entry[i];
- }
- while(cl) {
- if (!strcmp(arg, cl->udc->name))
- return cl->udc;
- cl = cl->next;
+ if (!strcmp(arg, chain->name))
+ return chain;
}
return NULL;
}
@@ -426,20 +370,13 @@ struct ebt_u_entries *ebt_name_to_chain(const struct ebt_u_replace *replace,
int ebt_get_chainnr(const struct ebt_u_replace *replace, const char* arg)
{
int i;
- struct ebt_u_chain_list *cl = replace->udc;
- for (i = 0; i < NF_BR_NUMHOOKS; i++) {
- if (!replace->hook_entry[i])
+ for (i = 0; i < replace->num_chains; i++) {
+ if (!replace->chains[i])
continue;
- if (!strcmp(arg, replace->hook_entry[i]->name))
+ if (!strcmp(arg, replace->chains[i]->name))
return i;
}
- while(cl) {
- if (!strcmp(arg, cl->udc->name))
- return i;
- i++;
- cl = cl->next;
- }
return -1;
}
@@ -479,16 +416,9 @@ void ebt_flush_chains(struct ebt_u_replace *replace)
replace->nentries = 0;
/* Free everything and zero (n)entries */
- i = -1;
- while (1) {
- i++;
- entries = ebt_nr_to_chain(replace, i);
- if (!entries) {
- if (i < NF_BR_NUMHOOKS)
- continue;
- else
- break;
- }
+ for (i = 0; i < replace->num_chains; i++) {
+ if (!(entries = replace->chains[i]))
+ continue;
entries->nentries = 0;
entries->counter_offset = 0;
u_e = entries->entries;
@@ -522,16 +452,9 @@ void ebt_flush_chains(struct ebt_u_replace *replace)
/* Delete the counters belonging to the specified chain,
* update counter_offset */
- i = -1;
- while (1) {
- i++;
- entries = ebt_nr_to_chain(replace, i);
- if (!entries) {
- if (i < NF_BR_NUMHOOKS)
- continue;
- else
- break;
- }
+ for (i = 0; i < replace->num_chains; i++) {
+ if (!(entries = replace->chains[i]))
+ continue;
if (i > replace->selected_chain) {
entries->counter_offset -= numdel;
continue;
@@ -682,8 +605,7 @@ letscontinue:;
* pointers so that they point to ebt_{match,watcher,target}, before adding
* the rule to the chain. Don't free() the ebt_{match,watcher,target} and
* don't reuse the new_entry after a successful call to ebt_add_rule() */
-void ebt_add_rule(struct ebt_u_replace *replace, struct ebt_u_entry *new_entry,
- int rule_nr)
+void ebt_add_rule(struct ebt_u_replace *replace, struct ebt_u_entry *new_entry, int rule_nr)
{
int i, j;
struct ebt_u_entry **u_e;
@@ -707,9 +629,9 @@ void ebt_add_rule(struct ebt_u_replace *replace, struct ebt_u_entry *new_entry,
/* Handle counter stuff */
for (i = 0; i < replace->selected_chain; i++) {
- if (i < NF_BR_NUMHOOKS && !(replace->hook_entry[i]))
+ if (!(replace->chains[i]))
continue;
- j = ebt_nr_to_chain(replace, i)->nentries;
+ j = replace->chains[i]->nentries;
while (j) {
if (cc->type != CNT_DEL)
j--;
@@ -756,17 +678,11 @@ void ebt_add_rule(struct ebt_u_replace *replace, struct ebt_u_entry *new_entry,
}
new_entry->t = ((struct ebt_u_target *)new_entry->t)->t;
/* Update the counter_offset of chains behind this one */
- i = replace->selected_chain;
- while (1) {
- i++;
- entries = ebt_nr_to_chain(replace, i);
- if (!entries) {
- if (i < NF_BR_NUMHOOKS)
- continue;
- else
- break;
- } else
- entries->counter_offset++;
+ for (i = replace->selected_chain+1; i < replace->num_chains; i++) {
+ entries = replace->chains[i];
+ if (!(entries = replace->chains[i]))
+ continue;
+ entries->counter_offset++;
}
}
@@ -830,9 +746,9 @@ void ebt_delete_rule(struct ebt_u_replace *replace,
/* Handle counter stuff */
for (i = 0; i < replace->selected_chain; i++) {
- if (i < NF_BR_NUMHOOKS && !(replace->hook_entry[i]))
+ if (!(replace->chains[i]))
continue;
- j = ebt_nr_to_chain(replace, i)->nentries;
+ j = replace->chains[i]->nentries;
while (j) {
if (cc->type != CNT_DEL)
j--;
@@ -879,16 +795,10 @@ void ebt_delete_rule(struct ebt_u_replace *replace,
/* Update the counter_offset of chains behind this one */
j = replace->selected_chain;
- while (1) {
- j++;
- entries = ebt_nr_to_chain(replace, j);
- if (!entries) {
- if (j < NF_BR_NUMHOOKS)
- continue;
- else
- break;
- } else
- entries->counter_offset -= nr_deletes;
+ for (j = replace->selected_chain+1; j < replace->num_chains; j++) {
+ if (!(entries = replace->chains[j]))
+ continue;
+ entries->counter_offset -= nr_deletes;
}
}
@@ -915,9 +825,9 @@ void ebt_change_counters(struct ebt_u_replace *replace,
return;
for (i = 0; i < replace->selected_chain; i++) {
- if (i < NF_BR_NUMHOOKS && !(replace->hook_entry[i]))
+ if (!(replace->chains[i]))
continue;
- j = ebt_nr_to_chain(replace, i)->nentries;
+ j = replace->chains[i]->nentries;
while (j) {
if (cc->type != CNT_DEL)
j--;
@@ -982,19 +892,9 @@ void ebt_zero_counters(struct ebt_u_replace *replace)
cc->type = CNT_ZERO;
cc = cc->next;
}
- i = -1;
- while (1) {
- i++;
- if (i < NF_BR_NUMHOOKS && !(replace->hook_entry[i]))
+ for (i = 0; i < replace->num_chains; i++) {
+ if (!(entries = replace->chains[i]))
continue;
- entries = ebt_nr_to_chain(replace, i);
- if (!entries) {
-#ifdef EBT_DEBUG
- if (i < NF_BR_NUMHOOKS)
- ebt_print_bug("i < NF_BR_NUMHOOKS");
-#endif
- break;
- }
next = entries->entries;
while (next) {
next->cnt.bcnt = next->cnt.pcnt = 0;
@@ -1006,9 +906,9 @@ void ebt_zero_counters(struct ebt_u_replace *replace)
return;
for (i = 0; i < replace->selected_chain; i++) {
- if (i < NF_BR_NUMHOOKS && !(replace->hook_entry[i]))
+ if (!(replace->chains[i]))
continue;
- j = ebt_nr_to_chain(replace, i)->nentries;
+ j = replace->chains[i]->nentries;
while (j) {
if (cc->type != CNT_DEL)
j--;
@@ -1035,7 +935,7 @@ void ebt_zero_counters(struct ebt_u_replace *replace)
/* Add a new chain and specify its policy */
void ebt_new_chain(struct ebt_u_replace *replace, const char *name, int policy)
{
- struct ebt_u_chain_list *cl, **cl2;
+ struct ebt_u_entries *new;
if (ebt_get_chainnr(replace, name) != -1) {
ebt_print_error("Chain %s already exists", optarg);
@@ -1048,60 +948,51 @@ void ebt_new_chain(struct ebt_u_replace *replace, const char *name, int policy)
EBT_CHAIN_MAXNAMELEN - 1);
return;
}
- cl = (struct ebt_u_chain_list *)
- malloc(sizeof(struct ebt_u_chain_list));
- if (!cl)
- ebt_print_memory();
- cl->next = NULL;
- cl->udc = (struct ebt_u_entries *)malloc(sizeof(struct ebt_u_entries));
- if (!cl->udc)
+ if (replace->num_chains == replace->max_chains)
+ ebt_double_chains(replace);
+ new = (struct ebt_u_entries *)malloc(sizeof(struct ebt_u_entries));
+ if (!new)
ebt_print_memory();
- cl->udc->nentries = 0;
- cl->udc->policy = policy;
- cl->udc->counter_offset = replace->nentries;
- cl->udc->hook_mask = 0;
- strcpy(cl->udc->name, name);
- cl->udc->entries = NULL;
- cl->kernel_start = NULL;
- /* Put the new chain at the end */
- cl2 = &(replace->udc);
- while (*cl2)
- cl2 = &((*cl2)->next);
- *cl2 = cl;
+ replace->chains[replace->num_chains++] = new;
+ new->nentries = 0;
+ new->policy = policy;
+ new->counter_offset = replace->nentries;
+ new->hook_mask = 0;
+ strcpy(new->name, name);
+ new->entries = NULL;
+ new->kernel_start = NULL;
+}
+
+static void ebt_delete_a_chain(struct ebt_u_replace *replace, int chain, int print_err)
+{
+ int tmp = replace->selected_chain;
+ /* If the chain is referenced, don't delete it,
+ * also decrement jumps to a chain behind the
+ * one we're deleting */
+ replace->selected_chain = chain;
+ if (ebt_check_for_references(replace, print_err))
+ return;
+ decrease_chain_jumps(replace);
+ ebt_flush_chains(replace);
+ replace->selected_chain = tmp;
+ free(replace->chains[chain]);
+ memmove(replace->chains+chain, replace->chains+chain+1, (replace->num_chains-chain-1)*sizeof(void *));
+ replace->num_chains--;
}
/* Selected_chain == -1: delete all non-referenced udc
* selected_chain < NF_BR_NUMHOOKS is illegal */
void ebt_delete_chain(struct ebt_u_replace *replace)
{
- int chain_nr = replace->selected_chain, print_error = 1;
+ int i;
- if (chain_nr != -1 && chain_nr < NF_BR_NUMHOOKS)
+ if (replace->selected_chain != -1 && replace->selected_chain < NF_BR_NUMHOOKS)
ebt_print_bug("You can't remove a standard chain");
- if (chain_nr == -1) {
- print_error = 0;
- replace->selected_chain = NF_BR_NUMHOOKS;
- }
- do {
- if (ebt_to_chain(replace) == NULL) {
- if (chain_nr == -1)
- break;
- ebt_print_bug("udc nr %d doesn't exist", chain_nr);
- }
- /* If the chain is referenced, don't delete it,
- * also decrement jumps to a chain behind the
- * one we're deleting */
- if (ebt_check_for_references(replace, print_error)) {
- if (chain_nr != -1)
- break;
- replace->selected_chain++;
- continue;
- }
- decrease_chain_jumps(replace);
- ebt_flush_chains(replace);
- remove_udc(replace);
- } while (chain_nr == -1);
- replace->selected_chain = chain_nr; /* Put back to -1 */
+ if (replace->selected_chain == -1)
+ for (i = NF_BR_NUMHOOKS; i < replace->num_chains; i++)
+ ebt_delete_a_chain(replace, i, 0);
+ else
+ ebt_delete_a_chain(replace, replace->selected_chain, 1);
}
/* Rename an existing chain. */
@@ -1124,6 +1015,19 @@ void ebt_rename_chain(struct ebt_u_replace *replace, const char *name)
*/
+void ebt_double_chains(struct ebt_u_replace *replace)
+{
+ struct ebt_u_entries **new;
+
+ replace->max_chains *= 2;
+ new = (struct ebt_u_entries **)malloc(replace->max_chains*sizeof(void *));
+ if (!new)
+ ebt_print_memory();
+ memcpy(new, replace->chains, replace->max_chains/2*sizeof(void *));
+ free(replace->chains);
+ replace->chains = new;
+}
+
/* Executes the final_check() function for all extensions used by the rule
* ebt_check_for_loops should have been executed earlier, to make sure the
* hook_mask is correct. The time argument to final_check() is set to 1,
@@ -1206,28 +1110,22 @@ void ebt_check_for_loops(struct ebt_u_replace *replace)
struct ebt_u_stack *stack = NULL;
struct ebt_u_entry *e;
- i = -1;
/* Initialize hook_mask to 0 */
- while (1) {
- i++;
- if (i < NF_BR_NUMHOOKS && !(replace->hook_entry[i]))
+ for (i = 0; i < replace->num_chains; i++) {
+ if (!(entries = replace->chains[i]))
continue;
- entries = ebt_nr_to_chain(replace, i);
- if (!entries)
- break;
entries->hook_mask = 0;
}
- if (i > NF_BR_NUMHOOKS) {
- stack = (struct ebt_u_stack *)malloc((i - NF_BR_NUMHOOKS) * sizeof(struct ebt_u_stack));
- if (!stack)
- ebt_print_memory();
- }
+ if (replace->num_chains == NF_BR_NUMHOOKS)
+ return;
+ stack = (struct ebt_u_stack *)malloc((replace->num_chains - NF_BR_NUMHOOKS) * sizeof(struct ebt_u_stack));
+ if (!stack)
+ ebt_print_memory();
/* Check for loops, starting from every base chain */
for (i = 0; i < NF_BR_NUMHOOKS; i++) {
- if (!(replace->hook_entry[i]))
+ if (!(entries = replace->chains[i]))
continue;
- entries = ebt_nr_to_chain(replace, i);
/* (1 << NF_BR_NUMHOOKS) implies it's a standard chain
* (usefull in the final_check() funtions) */
entries->hook_mask = (1 << i) | (1 << NF_BR_NUMHOOKS);
@@ -1240,14 +1138,14 @@ void ebt_check_for_loops(struct ebt_u_replace *replace)
verdict = ((struct ebt_standard_target *)(e->t))->verdict;
if (verdict < 0)
goto letscontinue;
- entries2 = ebt_nr_to_chain(replace, verdict + NF_BR_NUMHOOKS);
+ entries2 = replace->chains[verdict + NF_BR_NUMHOOKS];
entries2->hook_mask |= entries->hook_mask;
/* Now see if we've been here before */
for (k = 0; k < sp; k++)
if (stack[k].chain_nr == verdict + NF_BR_NUMHOOKS) {
ebt_print_error("Loop from chain '%s' to chain '%s'",
- ebt_nr_to_chain(replace, chain_nr)->name,
- ebt_nr_to_chain(replace, stack[k].chain_nr)->name);
+ replace->chains[chain_nr]->name,
+ replace->chains[stack[k].chain_nr]->name);
goto free_stack;
}
/* Jump to the chain, make sure we know how to get back */
@@ -1332,21 +1230,15 @@ void ebt_add_watcher(struct ebt_u_entry *new_entry, struct ebt_u_watcher *w)
* returns 0 otherwise */
static int iterate_entries(struct ebt_u_replace *replace, int type)
{
- int i = -1, j, chain_nr = replace->selected_chain - NF_BR_NUMHOOKS;
+ int i, j, chain_nr = replace->selected_chain - NF_BR_NUMHOOKS;
struct ebt_u_entries *entries;
struct ebt_u_entry *e;
if (chain_nr < 0)
ebt_print_bug("iterate_entries: udc = %d < 0", chain_nr);
- while (1) {
- i++;
- entries = ebt_nr_to_chain(replace, i);
- if (!entries) {
- if (i < NF_BR_NUMHOOKS)
- continue;
- else
- break;
- }
+ for (i = 0; i < replace->num_chains; i++) {
+ if (!(entries = replace->chains[i]))
+ continue;
e = entries->entries;
j = 0;
while (e) {
@@ -1366,7 +1258,7 @@ static int iterate_entries(struct ebt_u_replace *replace, int type)
if (type == 2)
return 1;
ebt_print_error("Can't delete the chain '%s', it's referenced in chain '%s', rule %d",
- ebt_nr_to_chain(replace, chain_nr + NF_BR_NUMHOOKS)->name, entries->name, j);
+ replace->chains[chain_nr + NF_BR_NUMHOOKS]->name, entries->name, j);
return 1;
}
break;
@@ -1387,37 +1279,6 @@ static void decrease_chain_jumps(struct ebt_u_replace *replace)
iterate_entries(replace, 0);
}
-/* Selected_chain >= NF_BR_NUMHOOKS */
-static void remove_udc(struct ebt_u_replace *replace)
-{
- struct ebt_u_chain_list *cl, **cl2;
- struct ebt_u_entries *entries;
- struct ebt_u_entry *u_e, *tmp;
- int chain_nr = replace->selected_chain;
-
- if (chain_nr < NF_BR_NUMHOOKS)
- ebt_print_bug("remove_udc: chain_nr = %d < %d", chain_nr,
- NF_BR_NUMHOOKS);
- /* First free the rules */
- entries = ebt_nr_to_chain(replace, chain_nr);
- u_e = entries->entries;
- while (u_e) {
- ebt_free_u_entry(u_e);
- tmp = u_e->next;
- free(u_e);
- u_e = tmp;
- }
-
- /* next, remove the chain */
- cl2 = &(replace->udc);
- while ((*cl2)->udc != entries)
- cl2 = &((*cl2)->next);
- cl = (*cl2);
- (*cl2) = (*cl2)->next;
- free(cl->udc);
- free(cl);
-}
-
/* Used in initialization code of modules */
void ebt_register_match(struct ebt_u_match *m)
{