chain_offsets[i] = entries_size;
entries_size += sizeof(struct ebt_entries);
j = 0;
- e = entries->entries;
- while (e) {
+ e = entries->entries->next;
+ while (e != entries->entries) {
j++;
entries_size += sizeof(struct ebt_entry);
m_l = e->m_list;
hlp->counter_offset = entries->counter_offset;
hlp->distinguisher = 0; /* Make the kernel see the light */
p += sizeof(struct ebt_entries);
- e = entries->entries;
- while (e) {
+ e = entries->entries->next;
+ while (e != entries->entries) {
struct ebt_entry *tmp = (struct ebt_entry *)p;
tmp->bitmask = e->bitmask | EBT_ENTRY_OR_ENTRIES;
old = u_repl->counters;
new = newcounters;
while (cc != u_repl->cc) {
- if (!next) {
- while (chainnr < u_repl->num_chains && (!(entries = u_repl->chains[chainnr++]) || !(next = entries->entries)));
+ if (!next || next == entries->entries) {
+ while (chainnr < u_repl->num_chains && (!(entries = u_repl->chains[chainnr++]) ||
+ (next = entries->entries->next) == entries->entries));
if (chainnr == u_repl->num_chains)
break;
}
static int
ebt_translate_entry(struct ebt_entry *e, unsigned int *hook, int *n, int *cnt,
- int *totalcnt, struct ebt_u_entry ***u_e, struct ebt_u_replace *u_repl,
+ int *totalcnt, struct ebt_u_entry **u_e, struct ebt_u_replace *u_repl,
unsigned int valid_hooks, char *base, struct ebt_cntchanges **cc)
{
/* An entry */
*cc = (*cc)->next;
new->m_list = NULL;
new->w_list = NULL;
- new->next = NULL;
+ new->next = (*u_e)->next;
+ new->next->prev = new;
+ (*u_e)->next = new;
+ new->prev = *u_e;
+ *u_e = new;
m_l = &new->m_list;
EBT_MATCH_ITERATE(e, ebt_translate_match, &m_l);
w_l = &new->w_list;
}
}
- /* I love pointers */
- **u_e = new;
- *u_e = &new->next;
(*cnt)++;
(*totalcnt)++;
return 0;
if (valid_hooks & (1 << i))
break;
*hook = i;
- *u_e = &(u_repl->chains[*hook]->entries);
+ *u_e = u_repl->chains[*hook]->entries;
return 0;
}
}
*hook = i;
new->nentries = entries->nentries;
new->policy = entries->policy;
- new->entries = NULL;
+ new->entries = (struct ebt_u_entry *)malloc(sizeof(struct ebt_u_entry));
+ if (!new->entries)
+ ebt_print_memory();
+ new->entries->next = new->entries->prev = new->entries;
new->counter_offset = entries->counter_offset;
strcpy(new->name, entries->name);
}
{
int i, j, k, hook;
struct ebt_replace repl;
- struct ebt_u_entry **u_e;
+ struct ebt_u_entry *u_e;
struct ebt_cntchanges *new_cc, *cc;
strcpy(repl.name, u_repl->name);
for (i = 0; i < replace->num_chains; i++) {
if (!(entries = replace->chains[i]))
continue;
- u_e1 = entries->entries;
- while (u_e1) {
+ u_e1 = entries->entries->next;
+ while (u_e1 != entries->entries) {
ebt_free_u_entry(u_e1);
u_e2 = u_e1->next;
free(u_e1);
u_e1 = u_e2;
}
+ free(entries->entries);
free(entries);
replace->chains[i] = NULL;
}
cc->type = CNT_DEL;
}
+void ebt_empty_chain(struct ebt_u_entries *entries)
+{
+ struct ebt_u_entry *u_e = entries->entries->next, *tmp;
+ while (u_e != entries->entries) {
+ ebt_delete_cc(u_e->cc);
+ ebt_free_u_entry(u_e);
+ tmp = u_e->next;
+ free(u_e);
+ u_e = tmp;
+ }
+ entries->entries->next = entries->entries->prev = entries->entries;
+ entries->nentries = 0;
+}
+
/* Flush one chain or the complete table
* If selected_chain == -1 then flush the complete table */
void ebt_flush_chains(struct ebt_u_replace *replace)
{
int i, numdel;
- struct ebt_u_entry *u_e, *tmp;
struct ebt_u_entries *entries = ebt_to_chain(replace);
/* Flush whole table */
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;
- entries->entries = NULL;
- while (u_e) {
- ebt_delete_cc(u_e->cc);
- ebt_free_u_entry(u_e);
- tmp = u_e->next;
- free(u_e);
- u_e = tmp;
- }
+ ebt_empty_chain(entries);
}
return;
}
}
entries = ebt_to_chain(replace);
- entries->nentries = 0;
- u_e = entries->entries;
- while (u_e) {
- ebt_delete_cc(u_e->cc);
- ebt_free_u_entry(u_e);
- tmp = u_e->next;
- free(u_e);
- u_e = tmp;
- }
- entries->entries = NULL;
+ ebt_empty_chain(entries);
}
#define OPT_COUNT 0x1000 /* This value is also defined in ebtables.c */
struct ebt_u_entries *entries = ebt_to_chain(replace);
int i, j, k;
- u_e = entries->entries;
+ u_e = entries->entries->next;
/* Check for an existing rule (if there are duplicate rules,
* take the first occurance) */
for (i = 0; i < entries->nentries; i++, u_e = u_e->next) {
- if (!u_e)
- ebt_print_bug("Hmm, trouble");
if (u_e->ethproto != new_entry->ethproto)
continue;
if (strcmp(u_e->in, new_entry->in))
void ebt_add_rule(struct ebt_u_replace *replace, struct ebt_u_entry *new_entry, int rule_nr)
{
int i;
- struct ebt_u_entry **u_e;
+ struct ebt_u_entry *u_e;
struct ebt_u_match_list *m_l;
struct ebt_u_watcher_list *w_l;
struct ebt_u_entries *entries = ebt_to_chain(replace);
replace->nentries++;
entries->nentries++;
/* Go to the right position in the chain */
- u_e = &entries->entries;
- for (i = 0; i < rule_nr; i++)
- u_e = &(*u_e)->next;
+ if (rule_nr == entries->nentries-1)
+ u_e = entries->entries;
+ else {
+ u_e = entries->entries->next;
+ for (i = 0; i < rule_nr; i++)
+ u_e = u_e->next;
+ }
/* Insert the rule */
- new_entry->next = *u_e;
- *u_e = new_entry;
+ new_entry->next = u_e;
+ new_entry->prev = u_e->prev;
+ u_e->prev->next = new_entry;
+ u_e->prev = new_entry;
new_cc = (struct ebt_cntchanges *)malloc(sizeof(struct ebt_cntchanges));
if (!new_cc)
ebt_print_memory();
new_cc->type = CNT_ADD;
new_cc->change = 0;
- if (!new_entry->next) {
+ if (new_entry->next == entries->entries) {
for (i = replace->selected_chain+1; i < replace->num_chains; i++)
if (!replace->chains[i] || replace->chains[i]->nentries == 0)
continue;
struct ebt_u_entry *new_entry, int begin, int end)
{
int i, nr_deletes;
- struct ebt_u_entry **u_e, *u_e2;
+ struct ebt_u_entry *u_e, *u_e2;
struct ebt_u_entries *entries = ebt_to_chain(replace);
if (check_and_change_rule_number(replace, new_entry, &begin, &end))
replace->nentries -= nr_deletes;
entries->nentries -= nr_deletes;
/* Go to the right position in the chain */
- u_e = &entries->entries;
+ u_e = entries->entries->next;
for (i = 0; i < begin; i++)
- u_e = &(*u_e)->next;
+ u_e = u_e->next;
/* Remove the rules */
for (i = 0; i < nr_deletes; i++) {
- u_e2 = *u_e;
+ u_e2 = u_e;
ebt_delete_cc(u_e2->cc);
- *u_e = (*u_e)->next;
+ u_e = u_e->next;
/* Free everything */
ebt_free_u_entry(u_e2);
free(u_e2);
if (check_and_change_rule_number(replace, new_entry, &begin, &end))
return;
- u_e = entries->entries;
+ u_e = entries->entries->next;
for (i = 0; i < begin; i++)
u_e = u_e->next;
for (i = end-begin+1; i > 0; i--) {
for (i = 0; i < replace->num_chains; i++) {
if (!(entries = replace->chains[i]))
continue;
- next = entries->entries;
- while (next) {
+ next = entries->entries->next;
+ while (next != entries->entries) {
if (next->cc->type == CNT_NORM)
next->cc->type = CNT_CHANGE;
next->cnt.bcnt = next->cnt.pcnt = 0;
if (entries->nentries == 0)
return;
- next = entries->entries;
- while (next) {
+ next = entries->entries->next;
+ while (next != entries->entries) {
if (next->cc->type == CNT_NORM)
next->cc->type = CNT_CHANGE;
next->cnt.bcnt = next->cnt.pcnt = 0;
new->counter_offset = replace->nentries;
new->hook_mask = 0;
strcpy(new->name, name);
- new->entries = NULL;
+ new->entries = (struct ebt_u_entry *)malloc(sizeof(struct ebt_u_entry));
+ if (!new->entries)
+ ebt_print_memory();
+ new->entries->next = new->entries->prev = new->entries;
new->kernel_start = NULL;
}
decrease_chain_jumps(replace);
ebt_flush_chains(replace);
replace->selected_chain = tmp;
+ free(replace->chains[chain]->entries);
free(replace->chains[chain]);
memmove(replace->chains+chain, replace->chains+chain+1, (replace->num_chains-chain-1)*sizeof(void *));
replace->num_chains--;
entries->hook_mask = (1 << i) | (1 << NF_BR_NUMHOOKS);
chain_nr = i;
- e = entries->entries;
+ e = entries->entries->next;
for (j = 0; j < entries->nentries; j++) {
if (strcmp(e->t->u.name, EBT_STANDARD_TARGET))
goto letscontinue;
for (i = 0; i < replace->num_chains; i++) {
if (!(entries = replace->chains[i]))
continue;
- e = entries->entries;
- j = 0;
- while (e) {
+ e = entries->entries->next;
+ for (j = 0; j < entries->nentries; j++) {
int chain_jmp;
- j++;
if (strcmp(e->t->u.name, EBT_STANDARD_TARGET)) {
e = e->next;
continue;