From 733e54b8250576d6a1e0ab5621ef5b144abdf018 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Thu, 16 Dec 2004 14:22:23 +0000 Subject: Make "is_same" test basics and entries only: targets are generic. 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 | 31 ++++++--------------- libiptc/libip6tc.c | 31 ++++++--------------- libiptc/libiptc.c | 80 ++++++++++++++++++++++++++++++++++++------------------ 3 files changed, 72 insertions(+), 70 deletions(-) diff --git a/libiptc/libip4tc.c b/libiptc/libip4tc.c index 399d5910..f623c78c 100644 --- a/libiptc/libip4tc.c +++ b/libiptc/libip4tc.c @@ -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 diff --git a/libiptc/libip6tc.c b/libiptc/libip6tc.c index c915ccbc..06b15fbc 100644 --- a/libiptc/libip6tc.c +++ b/libiptc/libip6tc.c @@ -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. */ diff --git a/libiptc/libiptc.c b/libiptc/libiptc.c index fad337c1..218ff039 100644 --- a/libiptc/libiptc.c +++ b/libiptc/libiptc.c @@ -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); -- cgit v1.2.3