summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--libiptc/libip4tc.c31
-rw-r--r--libiptc/libip6tc.c31
-rw-r--r--libiptc/libiptc.c80
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);