put rules in doubly linked list
authorBart De Schuymer <bdschuym@pandora.be>
Sun, 28 Aug 2005 16:06:22 +0000 (16:06 +0000)
committerBart De Schuymer <bdschuym@pandora.be>
Sun, 28 Aug 2005 16:06:22 +0000 (16:06 +0000)
communication.c
ebtables.c
include/ebtables_u.h
libebtc.c

index 472c7ed..e7711e4 100644 (file)
@@ -73,8 +73,8 @@ static struct ebt_replace *translate_user2kernel(struct ebt_u_replace *u_repl)
                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;
@@ -120,8 +120,8 @@ static struct ebt_replace *translate_user2kernel(struct ebt_u_replace *u_repl)
                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;
@@ -313,8 +313,9 @@ void ebt_deliver_counters(struct ebt_u_replace *u_repl, int exec_style)
        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;
                }
@@ -455,7 +456,7 @@ ebt_translate_watcher(struct ebt_entry_watcher *w,
 
 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 */
@@ -492,7 +493,11 @@ ebt_translate_entry(struct ebt_entry *e, unsigned int *hook, int *n, int *cnt,
                *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;
@@ -527,9 +532,6 @@ ebt_translate_entry(struct ebt_entry *e, unsigned int *hook, int *n, int *cnt,
                        }
                }
 
-               /* I love pointers */
-               **u_e = new;
-               *u_e = &new->next;
                (*cnt)++;
                (*totalcnt)++;
                return 0;
@@ -545,7 +547,7 @@ ebt_translate_entry(struct ebt_entry *e, unsigned int *hook, int *n, int *cnt,
                        if (valid_hooks & (1 << i))
                                break;
                *hook = i;
-               *u_e = &(u_repl->chains[*hook]->entries);
+               *u_e = u_repl->chains[*hook]->entries;
                return 0;
        }
 }
@@ -574,7 +576,10 @@ ebt_translate_chains(struct ebt_entry *e, unsigned int *hook,
                *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);
        }
@@ -708,7 +713,7 @@ int ebt_get_table(struct ebt_u_replace *u_repl, int init)
 {
        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);
index dc04f4e..05c30c4 100644 (file)
@@ -196,7 +196,7 @@ static void list_em(struct ebt_u_entries *entries)
                ebt_printstyle_mac = 2;
        else
                ebt_printstyle_mac = 0;
-       hlp = entries->entries;
+       hlp = entries->entries->next;
        if (replace->flags & LIST_X && entries->policy != EBT_ACCEPT) {
                printf("ebtables -t %s -P %s %s\n", replace->name,
                   entries->name, ebt_standard_targets[-entries->policy - 1]);
@@ -1173,8 +1173,8 @@ check_extension:
                                else
                                        break;
                        }
-                       e = entries->entries;
-                       while (e) {
+                       e = entries->entries->next;
+                       while (e != entries->entries) {
                                /* Userspace extensions use host endian */
                                e->ethproto = ntohs(e->ethproto);
                                ebt_do_final_checks(replace, e, entries);
@@ -1207,7 +1207,7 @@ delete_the_rule:
        if (exec_style == EXEC_STYLE_PRG) {/* Implies ebt_errormsg[0] == '\0' */
                ebt_deliver_table(replace);
 
-               if (replace->cc)
+               if (replace->nentries)
                        ebt_deliver_counters(replace, EXEC_STYLE_PRG);
        }
        return 0;
index 1c87117..e63cc45 100644 (file)
@@ -123,6 +123,7 @@ struct ebt_u_entry
        struct ebt_u_match_list *m_list;
        struct ebt_u_watcher_list *w_list;
        struct ebt_entry_target *t;
+       struct ebt_u_entry *prev;
        struct ebt_u_entry *next;
        struct ebt_counter cnt;
        struct ebt_counter cnt_surplus; /* for increasing/decreasing a counter and for option 'C' */
index 9f93ee1..ee63175 100644 (file)
--- a/libebtc.c
+++ b/libebtc.c
@@ -197,13 +197,14 @@ void ebt_cleanup_replace(struct ebt_u_replace *replace)
        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;
        }
@@ -409,12 +410,25 @@ void ebt_delete_cc(struct ebt_cntchanges *cc)
        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 */
@@ -427,17 +441,8 @@ void ebt_flush_chains(struct ebt_u_replace *replace)
                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;
        }
@@ -455,16 +460,7 @@ void ebt_flush_chains(struct ebt_u_replace *replace)
        }
 
        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 */
@@ -484,12 +480,10 @@ int ebt_check_rule_exists(struct ebt_u_replace *replace,
        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))
@@ -582,7 +576,7 @@ letscontinue:;
 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);
@@ -600,18 +594,24 @@ void ebt_add_rule(struct ebt_u_replace *replace, struct ebt_u_entry *new_entry,
        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;
@@ -694,7 +694,7 @@ void ebt_delete_rule(struct ebt_u_replace *replace,
                     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))
@@ -704,14 +704,14 @@ void ebt_delete_rule(struct ebt_u_replace *replace,
        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);
@@ -744,7 +744,7 @@ void ebt_change_counters(struct ebt_u_replace *replace,
 
        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--) {
@@ -788,8 +788,8 @@ void ebt_zero_counters(struct ebt_u_replace *replace)
                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;
@@ -801,8 +801,8 @@ void ebt_zero_counters(struct ebt_u_replace *replace)
                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;
@@ -838,7 +838,10 @@ void ebt_new_chain(struct ebt_u_replace *replace, const char *name, int policy)
        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;
 }
 
@@ -854,6 +857,7 @@ static void ebt_delete_a_chain(struct ebt_u_replace *replace, int chain, int pri
        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--;
@@ -1010,7 +1014,7 @@ void ebt_check_for_loops(struct ebt_u_replace *replace)
                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;
@@ -1118,12 +1122,10 @@ static int iterate_entries(struct ebt_u_replace *replace, int type)
        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;