summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--libxtables/xtables.c95
1 files changed, 71 insertions, 24 deletions
diff --git a/libxtables/xtables.c b/libxtables/xtables.c
index 857da8a6..ebdcc512 100644
--- a/libxtables/xtables.c
+++ b/libxtables/xtables.c
@@ -963,7 +963,7 @@ static int xtables_target_prefer(const struct xtables_target *a,
static bool xtables_fully_register_pending_match(struct xtables_match *me)
{
- struct xtables_match **i, *old;
+ struct xtables_match **i, *old, *pos = NULL;
const char *rn;
int compare;
@@ -973,7 +973,7 @@ static bool xtables_fully_register_pending_match(struct xtables_match *me)
return false;
old = xtables_find_match(me->name, XTF_DURING_LOAD, NULL);
- if (old) {
+ while (old) {
compare = xtables_match_prefer(old, me);
if (compare == 0) {
fprintf(stderr,
@@ -984,18 +984,41 @@ static bool xtables_fully_register_pending_match(struct xtables_match *me)
/* Now we have two (or more) options, check compatibility. */
rn = (old->real_name != NULL) ? old->real_name : old->name;
- if (compare > 0 &&
- compatible_match_revision(rn, old->revision))
- return true;
+ if (compare > 0) {
+ /* Kernel tells old isn't compatible anymore??? */
+ if (!compatible_match_revision(rn, old->revision)) {
+ /* Delete old one. */
+ for (i = &xtables_matches; *i != old;)
+ i = &(*i)->next;
+ *i = old->next;
+ }
+ pos = old;
+ old = old->next;
+ if (!old)
+ break;
+ if (!extension_cmp(me->name, old->name, old->family))
+ break;
+ continue;
+ }
- /* Delete old one. */
- for (i = &xtables_matches; *i!=old; i = &(*i)->next);
- *i = old->next;
+ /* Found right old */
+ pos = old;
+ break;
+ }
+
+ if (!pos) {
+ /* Append to list. */
+ for (i = &xtables_matches; *i; i = &(*i)->next);
+ } else if (compare < 0) {
+ /* Prepend it */
+ for (i = &xtables_matches; *i != pos; i = &(*i)->next);
+ } else if (compare > 0) {
+ /* Append it */
+ i = &pos->next;
+ pos = pos->next;
}
- /* Append to list. */
- for (i = &xtables_matches; *i; i = &(*i)->next);
- me->next = NULL;
+ me->next = pos;
*i = me;
me->m = NULL;
@@ -1069,7 +1092,7 @@ void xtables_register_target(struct xtables_target *me)
static bool xtables_fully_register_pending_target(struct xtables_target *me)
{
- struct xtables_target *old;
+ struct xtables_target **i, *old, *pos = NULL;
const char *rn;
int compare;
@@ -1081,9 +1104,7 @@ static bool xtables_fully_register_pending_target(struct xtables_target *me)
}
old = xtables_find_target(me->name, XTF_DURING_LOAD);
- if (old) {
- struct xtables_target **i;
-
+ while (old) {
compare = xtables_target_prefer(old, me);
if (compare == 0) {
fprintf(stderr,
@@ -1094,18 +1115,44 @@ static bool xtables_fully_register_pending_target(struct xtables_target *me)
/* Now we have two (or more) options, check compatibility. */
rn = (old->real_name != NULL) ? old->real_name : old->name;
- if (compare > 0 &&
- compatible_target_revision(rn, old->revision))
- return true;
+ if (compare > 0) {
+ /* Kernel tells old isn't compatible anymore??? */
+ if (!compatible_target_revision(rn, old->revision)) {
+ /* Delete old one. */
+ for (i = &xtables_targets; *i != old;)
+ i = &(*i)->next;
+ *i = old->next;
+ }
+ pos = old;
+ old = old->next;
+ if (!old)
+ break;
+ if (!extension_cmp(me->name, old->name, old->family))
+ break;
+ continue;
+ }
- /* Delete old one. */
- for (i = &xtables_targets; *i!=old; i = &(*i)->next);
- *i = old->next;
+ /* Found right old */
+ pos = old;
+ break;
}
- /* Prepend to list. */
- me->next = xtables_targets;
- xtables_targets = me;
+ if (!pos) {
+ /* Prepend to list. */
+ i = &xtables_targets;
+ pos = xtables_targets;
+ } else if (compare < 0) {
+ /* Prepend it */
+ for (i = &xtables_targets; *i != pos; i = &(*i)->next);
+ } else if (compare > 0) {
+ /* Append it */
+ i = &pos->next;
+ pos = pos->next;
+ }
+
+ me->next = pos;
+ *i = me;
+
me->t = NULL;
me->tflags = 0;