]> git.ipfire.org Git - thirdparty/iptables.git/commitdiff
Make "is_same" test basics and entries only: targets are generic.
authorRusty Russell <rusty@rustcorp.com.au>
Thu, 16 Dec 2004 14:22:23 +0000 (14:22 +0000)
committerRusty Russell <rusty@rustcorp.com.au>
Thu, 16 Dec 2004 14:22:23 +0000 (14:22 +0000)
Make target testing aware of different kinds of rules.
Change reverse logic: target_different now target_same.
Set type to MODULE in iptcc_map_target.
Add testcase for this.

libiptc/libip4tc.c
libiptc/libip6tc.c
libiptc/libiptc.c

index 399d591030c250b30d213e3fe169a82626e3d377..f623c78c4a1a6ebfbfc90b0fdc6aa1c6210b9dcd 100644 (file)
@@ -184,11 +184,10 @@ dump_entry(STRUCT_ENTRY *e, const TC_HANDLE_T handle)
        return 0;
 }
 
-static int
+static unsigned char *
 is_same(const STRUCT_ENTRY *a, const STRUCT_ENTRY *b, unsigned char *matchmask)
 {
        unsigned int i;
-       STRUCT_ENTRY_TARGET *ta, *tb;
        unsigned char *mptr;
 
        /* Always compare head structures: ignore mask here. */
@@ -199,43 +198,31 @@ is_same(const STRUCT_ENTRY *a, const STRUCT_ENTRY *b, unsigned char *matchmask)
            || a->ip.proto != b->ip.proto
            || a->ip.flags != b->ip.flags
            || a->ip.invflags != b->ip.invflags)
-               return 0;
+               return NULL;
 
        for (i = 0; i < IFNAMSIZ; i++) {
                if (a->ip.iniface_mask[i] != b->ip.iniface_mask[i])
-                       return 0;
+                       return NULL;
                if ((a->ip.iniface[i] & a->ip.iniface_mask[i])
                    != (b->ip.iniface[i] & b->ip.iniface_mask[i]))
-                       return 0;
+                       return NULL;
                if (a->ip.outiface_mask[i] != b->ip.outiface_mask[i])
-                       return 0;
+                       return NULL;
                if ((a->ip.outiface[i] & a->ip.outiface_mask[i])
                    != (b->ip.outiface[i] & b->ip.outiface_mask[i]))
-                       return 0;
+                       return NULL;
        }
 
        if (a->nfcache != b->nfcache
            || a->target_offset != b->target_offset
            || a->next_offset != b->next_offset)
-               return 0;
+               return NULL;
 
        mptr = matchmask + sizeof(STRUCT_ENTRY);
        if (IPT_MATCH_ITERATE(a, match_different, a->elems, b->elems, &mptr))
-               return 0;
-
-       ta = GET_TARGET((STRUCT_ENTRY *)a);
-       tb = GET_TARGET((STRUCT_ENTRY *)b);
-       if (ta->u.target_size != tb->u.target_size)
-               return 0;
-       if (strcmp(ta->u.user.name, tb->u.user.name) != 0)
-               return 0;
-
-       mptr += sizeof(*ta);
-       if (target_different(ta->data, tb->data,
-                            ta->u.target_size - sizeof(*ta), mptr))
-               return 0;
+               return NULL;
 
-       return 1;
+       return mptr;
 }
 
 #if 0
index c915ccbc06722f27c6e3e6888f381c6140e0b7e6..06b15fbc9cdf2f4effd439c603fab40d7ef31853 100644 (file)
@@ -214,12 +214,11 @@ dump_entry(struct ip6t_entry *e, const ip6tc_handle_t handle)
        return 0;
 }
 
-static int
+static unsigned char *
 is_same(const STRUCT_ENTRY *a, const STRUCT_ENTRY *b,
        unsigned char *matchmask)
 {
        unsigned int i;
-       STRUCT_ENTRY_TARGET *ta, *tb;
        unsigned char *mptr;
 
        /* Always compare head structures: ignore mask here. */
@@ -231,43 +230,31 @@ is_same(const STRUCT_ENTRY *a, const STRUCT_ENTRY *b,
            || a->ipv6.tos != b->ipv6.tos
            || a->ipv6.flags != b->ipv6.flags
            || a->ipv6.invflags != b->ipv6.invflags)
-               return 0;
+               return NULL;
 
        for (i = 0; i < IFNAMSIZ; i++) {
                if (a->ipv6.iniface_mask[i] != b->ipv6.iniface_mask[i])
-                       return 0;
+                       return NULL;
                if ((a->ipv6.iniface[i] & a->ipv6.iniface_mask[i])
                    != (b->ipv6.iniface[i] & b->ipv6.iniface_mask[i]))
-                       return 0;
+                       return NULL;
                if (a->ipv6.outiface_mask[i] != b->ipv6.outiface_mask[i])
-                       return 0;
+                       return NULL;
                if ((a->ipv6.outiface[i] & a->ipv6.outiface_mask[i])
                    != (b->ipv6.outiface[i] & b->ipv6.outiface_mask[i]))
-                       return 0;
+                       return NULL;
        }
 
        if (a->nfcache != b->nfcache
            || a->target_offset != b->target_offset
            || a->next_offset != b->next_offset)
-               return 0;
+               return NULL;
 
        mptr = matchmask + sizeof(STRUCT_ENTRY);
        if (IP6T_MATCH_ITERATE(a, match_different, a->elems, b->elems, &mptr))
-               return 0;
-
-       ta = GET_TARGET((STRUCT_ENTRY *)a);
-       tb = GET_TARGET((STRUCT_ENTRY *)b);
-       if (ta->u.target_size != tb->u.target_size)
-               return 0;
-       if (strcmp(ta->u.user.name, tb->u.user.name) != 0)
-               return 0;
-       mptr += sizeof(*ta);
-
-       if (target_different(ta->data, tb->data,
-                            ta->u.target_size - sizeof(*ta), mptr))
-               return 0;
+               return NULL;
 
-       return 1;
+       return mptr;
 }
 
 /* All zeroes == unconditional rule. */
index fad337c1dda2c253017c6187feadbd9521522cbe..218ff0393345f54f309a1ad40c8603f6a67f4812 100644 (file)
@@ -1238,7 +1238,7 @@ iptcc_map_target(const TC_HANDLE_T handle,
        memset(t->u.user.name + strlen(t->u.user.name),
               0,
               FUNCTION_MAXNAMELEN - strlen(t->u.user.name));
-
+       r->type = IPTCC_R_MODULE;
        set_changed(handle);
        return 1;
 }
@@ -1413,20 +1413,42 @@ match_different(const STRUCT_ENTRY_MATCH *a,
 }
 
 static inline int
-target_different(const unsigned char *a_targdata,
-                const unsigned char *b_targdata,
-                unsigned int tdatasize,
-                const unsigned char *mask)
+target_same(struct rule_head *a, struct rule_head *b,const unsigned char *mask)
 {
        unsigned int i;
-       for (i = 0; i < tdatasize; i++)
-               if (((a_targdata[i] ^ b_targdata[i]) & mask[i]) != 0)
-                       return 1;
+       STRUCT_ENTRY_TARGET *ta, *tb;
 
-       return 0;
+       if (a->type != b->type)
+               return 0;
+
+       ta = GET_TARGET(a->entry);
+       tb = GET_TARGET(b->entry);
+
+       switch (a->type) {
+       case IPTCC_R_FALLTHROUGH:
+               return 1;
+       case IPTCC_R_JUMP:
+               return a->jump == b->jump;
+       case IPTCC_R_STANDARD:
+               return ((STRUCT_STANDARD_TARGET *)ta)->verdict
+                       == ((STRUCT_STANDARD_TARGET *)tb)->verdict;
+       case IPTCC_R_MODULE:
+               if (ta->u.target_size != tb->u.target_size)
+                       return 0;
+               if (strcmp(ta->u.user.name, tb->u.user.name) != 0)
+                       return 0;
+
+               for (i = 0; i < ta->u.target_size - sizeof(*ta); i++)
+                       if (((ta->data[i] ^ ta->data[i]) & mask[i]) != 0)
+                               return 0;
+               return 1;
+       default:
+               fprintf(stderr, "ERROR: bad type %i\n", a->type);
+               abort();
+       }
 }
 
-static int
+static unsigned char *
 is_same(const STRUCT_ENTRY *a,
        const STRUCT_ENTRY *b,
        unsigned char *matchmask);
@@ -1463,24 +1485,30 @@ TC_DELETE_ENTRY(const IPT_CHAINLABEL chain,
        }
 
        list_for_each_entry(i, &c->rules, list) {
-               if (r->type == i->type
-                   && is_same(r->entry, i->entry, matchmask)) {
-                       /* If we are about to delete the rule that is the
-                        * current iterator, move rule iterator back.  next
-                        * pointer will then point to real next node */
-                       if (i == (*handle)->rule_iterator_cur) {
-                               (*handle)->rule_iterator_cur = 
-                                       list_entry((*handle)->rule_iterator_cur->list.prev,
-                                                  struct rule_head, list);
-                       }
+               unsigned char *mask;
+
+               mask = is_same(r->entry, i->entry, matchmask);
+               if (!mask)
+                       continue;
+
+               if (!target_same(r, i, mask))
+                       continue;
+
+               /* If we are about to delete the rule that is the
+                * current iterator, move rule iterator back.  next
+                * pointer will then point to real next node */
+               if (i == (*handle)->rule_iterator_cur) {
+                       (*handle)->rule_iterator_cur = 
+                               list_entry((*handle)->rule_iterator_cur->list.prev,
+                                          struct rule_head, list);
+               }
 
-                       c->num_rules--;
-                       iptcc_delete_rule(i);
+               c->num_rules--;
+               iptcc_delete_rule(i);
 
-                       set_changed(*handle);
-                       free(r);
-                       return 1;
-               }
+               set_changed(*handle);
+               free(r);
+               return 1;
        }
 
        free(r);