]> git.ipfire.org Git - thirdparty/iptables.git/commitdiff
Implement AF_UNSPEC as a wildcard for extensions
authorJan Engelhardt <jengelh@medozas.de>
Thu, 14 Feb 2008 03:23:04 +0000 (04:23 +0100)
committerPatrick McHardy <kaber@trash.net>
Mon, 14 Apr 2008 06:56:58 +0000 (08:56 +0200)
17 files changed:
extensions/libxt_CLASSIFY.c
extensions/libxt_MARK.c
extensions/libxt_RATEEST.c
extensions/libxt_SECMARK.c
extensions/libxt_TRACE.c
extensions/libxt_length.c
extensions/libxt_limit.c
extensions/libxt_mark.c
extensions/libxt_pkttype.c
extensions/libxt_quota.c
extensions/libxt_rateest.c
extensions/libxt_standard.c
extensions/libxt_statistic.c
extensions/libxt_string.c
extensions/libxt_time.c
extensions/libxt_u32.c
xtables.c

index e39367a885a6efbff60f98fa96ff72b06e3b5261..4a3520f8b3fbf023ea7771b678a8ad97d33b1ed4 100644 (file)
@@ -103,21 +103,7 @@ CLASSIFY_save(const void *ip, const struct xt_entry_target *target)
 }
 
 static struct xtables_target classify_target = { 
-       .family         = AF_INET,
-       .name           = "CLASSIFY",
-       .version        = IPTABLES_VERSION,
-       .size           = XT_ALIGN(sizeof(struct xt_classify_target_info)),
-       .userspacesize  = XT_ALIGN(sizeof(struct xt_classify_target_info)),
-       .help           = CLASSIFY_help,
-       .parse          = CLASSIFY_parse,
-       .final_check    = CLASSIFY_final_check,
-       .print          = CLASSIFY_print,
-       .save           = CLASSIFY_save,
-       .extra_opts     = CLASSIFY_opts,
-};
-
-static struct xtables_target classify_target6 = { 
-       .family         = AF_INET6,
+       .family         = AF_UNSPEC,
        .name           = "CLASSIFY",
        .version        = IPTABLES_VERSION,
        .size           = XT_ALIGN(sizeof(struct xt_classify_target_info)),
@@ -133,5 +119,4 @@ static struct xtables_target classify_target6 = {
 void _init(void)
 {
        xtables_register_target(&classify_target);
-       xtables_register_target(&classify_target6);
 }
index 569d2e8c547f33d2a758a571588f4a67ba30e89c..d7d79d574fed6d7ac9bdf25d8e45a866e16d132d 100644 (file)
@@ -333,22 +333,7 @@ static struct xtables_target mark_tg_reg_v2 = {
        .version       = IPTABLES_VERSION,
        .name          = "MARK",
        .revision      = 2,
-       .family        = AF_INET,
-       .size          = XT_ALIGN(sizeof(struct xt_mark_tginfo2)),
-       .userspacesize = XT_ALIGN(sizeof(struct xt_mark_tginfo2)),
-       .help          = mark_tg_help,
-       .parse         = mark_tg_parse,
-       .final_check   = mark_tg_check,
-       .print         = mark_tg_print,
-       .save          = mark_tg_save,
-       .extra_opts    = mark_tg_opts,
-};
-
-static struct xtables_target mark_tg6_reg_v2 = {
-       .version       = IPTABLES_VERSION,
-       .name          = "MARK",
-       .revision      = 2,
-       .family        = AF_INET6,
+       .family        = AF_UNSPEC,
        .size          = XT_ALIGN(sizeof(struct xt_mark_tginfo2)),
        .userspacesize = XT_ALIGN(sizeof(struct xt_mark_tginfo2)),
        .help          = mark_tg_help,
@@ -365,5 +350,4 @@ void _init(void)
        xtables_register_target(&mark_target_v1);
        xtables_register_target(&mark_target6_v0);
        xtables_register_target(&mark_tg_reg_v2);
-       xtables_register_target(&mark_tg6_reg_v2);
 }
index dd7b50339c9c89ae5cba02ecf8a3d5dcc8d6b0fe..ee0d116da1fcea27af7a8a221c05a85f9b461050 100644 (file)
@@ -202,23 +202,8 @@ RATEEST_save(const void *ip, const struct xt_entry_target *target)
        __RATEEST_print(target, "--rateest-");
 }
 
-static struct xtables_target rateest_target4 = {
-       .family         = AF_INET,
-       .name           = "RATEEST",
-       .version        = IPTABLES_VERSION,
-       .size           = XT_ALIGN(sizeof(struct xt_rateest_target_info)),
-       .userspacesize  = XT_ALIGN(sizeof(struct xt_rateest_target_info)),
-       .help           = RATEEST_help,
-       .init           = RATEEST_init,
-       .parse          = RATEEST_parse,
-       .final_check    = RATEEST_final_check,
-       .print          = RATEEST_print,
-       .save           = RATEEST_save,
-       .extra_opts     = RATEEST_opts,
-};
-
-static struct xtables_target rateest_target6 = {
-       .family         = AF_INET6,
+static struct xtables_target rateest_tg_reg = {
+       .family         = AF_UNSPEC,
        .name           = "RATEEST",
        .version        = IPTABLES_VERSION,
        .size           = XT_ALIGN(sizeof(struct xt_rateest_target_info)),
@@ -234,6 +219,5 @@ static struct xtables_target rateest_target6 = {
 
 void _init(void)
 {
-       xtables_register_target(&rateest_target4);
-       xtables_register_target(&rateest_target6);
+       xtables_register_target(&rateest_tg_reg);
 }
index b794e7deb42b68949cdd4c2dd25b491e86be6910..92ba527baa05f5e56e82775a73ae1a63ed52b2ac 100644 (file)
@@ -100,22 +100,7 @@ static void SECMARK_save(const void *ip, const struct xt_entry_target *target)
 }
 
 static struct xtables_target secmark_target = {
-       .family         = AF_INET,
-       .name           = "SECMARK",
-       .version        = IPTABLES_VERSION,
-       .revision       = 0,
-       .size           = XT_ALIGN(sizeof(struct xt_secmark_target_info)),
-       .userspacesize  = XT_ALIGN(sizeof(struct xt_secmark_target_info)),
-       .help           = SECMARK_help,
-       .parse          = SECMARK_parse,
-       .final_check    = SECMARK_check,
-       .print          = SECMARK_print,
-       .save           = SECMARK_save,
-       .extra_opts     = SECMARK_opts,
-};
-
-static struct xtables_target secmark_target6 = {
-       .family         = AF_INET6,
+       .family         = AF_UNSPEC,
        .name           = "SECMARK",
        .version        = IPTABLES_VERSION,
        .revision       = 0,
@@ -132,5 +117,4 @@ static struct xtables_target secmark_target6 = {
 void _init(void)
 {
        xtables_register_target(&secmark_target);
-       xtables_register_target(&secmark_target6);
 }
index c70df6ab27c20e93202745dbada3489473415765..97e3a03f1102bcda06d5038c4a4c2e409e802ad6 100644 (file)
@@ -24,17 +24,7 @@ static int TRACE_parse(int c, char **argv, int invert, unsigned int *flags,
 }
 
 static struct xtables_target trace_target = {
-       .family         = AF_INET,
-       .name           = "TRACE",
-       .version        = IPTABLES_VERSION,
-       .size           = XT_ALIGN(0),
-       .userspacesize  = XT_ALIGN(0),
-       .help           = TRACE_help,
-       .parse          = TRACE_parse,
-};
-
-static struct xtables_target trace_target6 = {
-       .family         = AF_INET6,
+       .family         = AF_UNSPEC,
        .name           = "TRACE",
        .version        = IPTABLES_VERSION,
        .size           = XT_ALIGN(0),
@@ -46,5 +36,4 @@ static struct xtables_target trace_target6 = {
 void _init(void)
 {
        xtables_register_target(&trace_target);
-       xtables_register_target(&trace_target6);
 }
index b812b672c4d1dedfeab43d2211fbca1090f8bdd8..16e00bd9be4e454754c2a5381c55be6e01099bba 100644 (file)
@@ -125,21 +125,7 @@ static void length_save(const void *ip, const struct xt_entry_match *match)
 }
 
 static struct xtables_match length_match = {
-       .family         = AF_INET,
-       .name           = "length",
-       .version        = IPTABLES_VERSION,
-       .size           = XT_ALIGN(sizeof(struct xt_length_info)),
-       .userspacesize  = XT_ALIGN(sizeof(struct xt_length_info)),
-       .help           = length_help,
-       .parse          = length_parse,
-       .final_check    = length_check,
-       .print          = length_print,
-       .save           = length_save,
-       .extra_opts     = length_opts,
-};
-
-static struct xtables_match length_match6 = {
-       .family         = AF_INET6,
+       .family         = AF_UNSPEC,
        .name           = "length",
        .version        = IPTABLES_VERSION,
        .size           = XT_ALIGN(sizeof(struct xt_length_info)),
@@ -155,5 +141,4 @@ static struct xtables_match length_match6 = {
 void _init(void)
 {
        xtables_register_match(&length_match);
-       xtables_register_match(&length_match6);
 }
index 65a8df3ffc4990f2ec72c619d09391eeb21fa1f2..1c86df9827fc86c650f07a7529a39d58ae79fc73 100644 (file)
@@ -165,21 +165,7 @@ static void limit_save(const void *ip, const struct xt_entry_match *match)
 }
 
 static struct xtables_match limit_match = {
-       .family         = AF_INET,
-       .name           = "limit",
-       .version        = IPTABLES_VERSION,
-       .size           = XT_ALIGN(sizeof(struct xt_rateinfo)),
-       .userspacesize  = offsetof(struct xt_rateinfo, prev),
-       .help           = limit_help,
-       .init           = limit_init,
-       .parse          = limit_parse,
-       .print          = limit_print,
-       .save           = limit_save,
-       .extra_opts     = limit_opts,
-};
-
-static struct xtables_match limit_match6 = {
-       .family         = AF_INET6,
+       .family         = AF_UNSPEC,
        .name           = "limit",
        .version        = IPTABLES_VERSION,
        .size           = XT_ALIGN(sizeof(struct xt_rateinfo)),
@@ -195,5 +181,4 @@ static struct xtables_match limit_match6 = {
 void _init(void)
 {
        xtables_register_match(&limit_match);
-       xtables_register_match(&limit_match6);
 }
index af7f844aeed504edabe47c4d30dd120e1be904b6..fab8ecb94ee39af838b4f8a9b4c5ede37f87477e 100644 (file)
@@ -149,22 +149,7 @@ mark_save(const void *ip, const struct xt_entry_match *match)
 }
 
 static struct xtables_match mark_match = {
-       .family         = AF_INET,
-       .name           = "mark",
-       .revision       = 0,
-       .version        = IPTABLES_VERSION,
-       .size           = XT_ALIGN(sizeof(struct xt_mark_info)),
-       .userspacesize  = XT_ALIGN(sizeof(struct xt_mark_info)),
-       .help           = mark_mt_help,
-       .parse          = mark_parse,
-       .final_check    = mark_mt_check,
-       .print          = mark_print,
-       .save           = mark_save,
-       .extra_opts     = mark_mt_opts,
-};
-
-static struct xtables_match mark_match6 = {
-       .family         = AF_INET6,
+       .family         = AF_UNSPEC,
        .name           = "mark",
        .revision       = 0,
        .version        = IPTABLES_VERSION,
@@ -182,22 +167,7 @@ static struct xtables_match mark_mt_reg = {
        .version        = IPTABLES_VERSION,
        .name           = "mark",
        .revision       = 1,
-       .family         = AF_INET,
-       .size           = XT_ALIGN(sizeof(struct xt_mark_mtinfo1)),
-       .userspacesize  = XT_ALIGN(sizeof(struct xt_mark_mtinfo1)),
-       .help           = mark_mt_help,
-       .parse          = mark_mt_parse,
-       .final_check    = mark_mt_check,
-       .print          = mark_mt_print,
-       .save           = mark_mt_save,
-       .extra_opts     = mark_mt_opts,
-};
-
-static struct xtables_match mark_mt6_reg = {
-       .version        = IPTABLES_VERSION,
-       .name           = "mark",
-       .revision       = 1,
-       .family         = AF_INET6,
+       .family         = AF_UNSPEC,
        .size           = XT_ALIGN(sizeof(struct xt_mark_mtinfo1)),
        .userspacesize  = XT_ALIGN(sizeof(struct xt_mark_mtinfo1)),
        .help           = mark_mt_help,
@@ -211,7 +181,5 @@ static struct xtables_match mark_mt6_reg = {
 void _init(void)
 {
        xtables_register_match(&mark_match);
-       xtables_register_match(&mark_match6);
        xtables_register_match(&mark_mt_reg);
-       xtables_register_match(&mark_mt6_reg);
 }
index 75194fcb4fca90cc5f0dd3f34a36aded3189d218..7c469a8d191b2d3e34b9ebfc4d248618144e945d 100644 (file)
@@ -147,21 +147,7 @@ static void pkttype_save(const void *ip, const struct xt_entry_match *match)
 }
 
 static struct xtables_match pkttype_match = {
-       .family         = AF_INET,
-       .name           = "pkttype",
-       .version        = IPTABLES_VERSION,
-       .size           = XT_ALIGN(sizeof(struct xt_pkttype_info)),
-       .userspacesize  = XT_ALIGN(sizeof(struct xt_pkttype_info)),
-       .help           = pkttype_help,
-       .parse          = pkttype_parse,
-       .final_check    = pkttype_check,
-       .print          = pkttype_print,
-       .save           = pkttype_save,
-       .extra_opts     = pkttype_opts,
-};
-
-static struct xtables_match pkttype_match6 = {
-       .family         = AF_INET6,
+       .family         = AF_UNSPEC,
        .name           = "pkttype",
        .version        = IPTABLES_VERSION,
        .size           = XT_ALIGN(sizeof(struct xt_pkttype_info)),
@@ -177,5 +163,4 @@ static struct xtables_match pkttype_match6 = {
 void _init(void)
 {
        xtables_register_match(&pkttype_match);
-       xtables_register_match(&pkttype_match6);
 }
index b4fb78bb35a41f9ac788fd133b9a3c803c0e85ff..590dbfbf8bcbafa8c570c829ea3d204b93be32bd 100644 (file)
@@ -78,20 +78,7 @@ quota_parse(int c, char **argv, int invert, unsigned int *flags,
 }
 
 struct xtables_match quota_match = {
-       .family         = AF_INET,
-       .name           = "quota",
-       .version        = IPTABLES_VERSION,
-       .size           = XT_ALIGN(sizeof (struct xt_quota_info)),
-       .userspacesize  = offsetof(struct xt_quota_info, quota),
-       .help           = quota_help,
-       .parse          = quota_parse,
-       .print          = quota_print,
-       .save           = quota_save,
-       .extra_opts     = quota_opts,
-};
-
-struct xtables_match quota_match6 = {
-       .family         = AF_INET6,
+       .family         = AF_UNSPEC,
        .name           = "quota",
        .version        = IPTABLES_VERSION,
        .size           = XT_ALIGN(sizeof (struct xt_quota_info)),
@@ -107,5 +94,4 @@ void
 _init(void)
 {
        xtables_register_match(&quota_match);
-       xtables_register_match(&quota_match6);
 }
index 5f13340f719c9438c6813f6d8419cf528a416b34..a335781d65eb8fdd76223d7c95032ad6f87daf7f 100644 (file)
@@ -426,22 +426,8 @@ rateest_save(const void *ip, const struct xt_entry_match *match)
        }
 }
 
-static struct xtables_match rateest_match4 = {
-       .family         = AF_INET,
-       .name           = "rateest",
-       .version        = IPTABLES_VERSION,
-       .size           = XT_ALIGN(sizeof(struct xt_rateest_match_info)),
-       .userspacesize  = XT_ALIGN(offsetof(struct xt_rateest_match_info, est1)),
-       .help           = rateest_help,
-       .parse          = rateest_parse,
-       .final_check    = rateest_final_check,
-       .print          = rateest_print,
-       .save           = rateest_save,
-       .extra_opts     = rateest_opts,
-};
-
-static struct xtables_match rateest_match6 = {
-       .family         = AF_INET6,
+static struct xtables_match rateest_mt_reg = {
+       .family         = AF_UNSPEC,
        .name           = "rateest",
        .version        = IPTABLES_VERSION,
        .size           = XT_ALIGN(sizeof(struct xt_rateest_match_info)),
@@ -456,6 +442,5 @@ static struct xtables_match rateest_match6 = {
 
 void _init(void)
 {
-       xtables_register_match(&rateest_match4);
-       xtables_register_match(&rateest_match6);
+       xtables_register_match(&rateest_mt_reg);
 }
index eef9369bf82df51eef2026e6f3be27602cb4c4b8..a50cffe98e8e8caac97b6d8bd17c11705f65a461 100644 (file)
@@ -24,17 +24,7 @@ static int standard_parse(int c, char **argv, int invert, unsigned int *flags,
 }
 
 static struct xtables_target standard_target = {
-       .family         = AF_INET,
-       .name           = "standard",
-       .version        = IPTABLES_VERSION,
-       .size           = XT_ALIGN(sizeof(int)),
-       .userspacesize  = XT_ALIGN(sizeof(int)),
-       .help           = standard_help,
-       .parse          = standard_parse,
-};
-
-static struct xtables_target standard_target6 = {
-       .family         = AF_INET6,
+       .family         = AF_UNSPEC,
        .name           = "standard",
        .version        = IPTABLES_VERSION,
        .size           = XT_ALIGN(sizeof(int)),
@@ -46,5 +36,4 @@ static struct xtables_target standard_target6 = {
 void _init(void)
 {
        xtables_register_target(&standard_target);
-       xtables_register_target(&standard_target6);
 }
index ebb4e914586cdca098f3645ba1589fa2e2ca0b2f..2c2464dcfed1c1ac4a641feb8d6b83a7823d886b 100644 (file)
@@ -164,22 +164,7 @@ static void statistic_save(const void *ip, const struct xt_entry_match *match)
 }
 
 static struct xtables_match statistic_match = {
-       .family         = AF_INET,
-       .name           = "statistic",
-       .version        = IPTABLES_VERSION,
-       .size           = XT_ALIGN(sizeof(struct xt_statistic_info)),
-       .userspacesize  = offsetof(struct xt_statistic_info, u.nth.count),
-       .init           = statistic_mt_init,
-       .help           = statistic_help,
-       .parse          = statistic_parse,
-       .final_check    = statistic_check,
-       .print          = statistic_print,
-       .save           = statistic_save,
-       .extra_opts     = statistic_opts,
-};
-
-static struct xtables_match statistic_match6 = {
-       .family         = AF_INET6,
+       .family         = AF_UNSPEC,
        .name           = "statistic",
        .version        = IPTABLES_VERSION,
        .size           = XT_ALIGN(sizeof(struct xt_statistic_info)),
@@ -196,5 +181,4 @@ static struct xtables_match statistic_match6 = {
 void _init(void)
 {
        xtables_register_match(&statistic_match);
-       xtables_register_match(&statistic_match6);
 }
index f1030bbcbf04d575df4115d783de7bb3598b26fa..dc2cd9d3ebfd594f91ddd4188de2eb076b720b70 100644 (file)
@@ -327,23 +327,7 @@ static void string_save(const void *ip, const struct xt_entry_match *match)
 
 static struct xtables_match string_match = {
     .name              = "string",
-    .family            = AF_INET,
-    .version           = IPTABLES_VERSION,
-    .size              = XT_ALIGN(sizeof(struct xt_string_info)),
-    .userspacesize     = offsetof(struct xt_string_info, config),
-    .help              = string_help,
-    .init              = string_init,
-    .parse             = string_parse,
-    .final_check       = string_check,
-    .print             = string_print,
-    .save              = string_save,
-    .extra_opts                = string_opts,
-};
-
-
-static struct xtables_match string_match6 = {
-    .name              = "string",
-    .family            = AF_INET6,
+    .family            = AF_UNSPEC,
     .version           = IPTABLES_VERSION,
     .size              = XT_ALIGN(sizeof(struct xt_string_info)),
     .userspacesize     = offsetof(struct xt_string_info, config),
@@ -359,5 +343,4 @@ static struct xtables_match string_match6 = {
 void _init(void)
 {
        xtables_register_match(&string_match);
-       xtables_register_match(&string_match6);
 }
index c39ab1a0683dee3db78a76b1d69acccc3d46b535..c551a6fee94098eccf31842b95309017e2d18be4 100644 (file)
@@ -466,21 +466,7 @@ static void time_save(const void *ip, const struct xt_entry_match *match)
 
 static struct xtables_match time_match = {
        .name          = "time",
-       .family        = AF_INET,
-       .version       = IPTABLES_VERSION,
-       .size          = XT_ALIGN(sizeof(struct xt_time_info)),
-       .userspacesize = XT_ALIGN(sizeof(struct xt_time_info)),
-       .help          = time_help,
-       .init          = time_init,
-       .parse         = time_parse,
-       .print         = time_print,
-       .save          = time_save,
-       .extra_opts    = time_opts,
-};
-
-static struct xtables_match time_match6 = {
-       .name          = "time",
-       .family        = AF_INET6,
+       .family        = AF_UNSPEC,
        .version       = IPTABLES_VERSION,
        .size          = XT_ALIGN(sizeof(struct xt_time_info)),
        .userspacesize = XT_ALIGN(sizeof(struct xt_time_info)),
@@ -495,5 +481,4 @@ static struct xtables_match time_match6 = {
 void _init(void)
 {
        xtables_register_match(&time_match);
-       xtables_register_match(&time_match6);
 }
index 251b2d4596929a1cd9efe28dfa6b3b928e991a87..9360c094528b9eaa797135e5ed8c417b643e51c3 100644 (file)
@@ -272,20 +272,7 @@ static void u32_save(const void *ip, const struct xt_entry_match *match)
 
 static struct xtables_match u32_match = {
        .name          = "u32",
-       .family        = AF_INET,
-       .version       = IPTABLES_VERSION,
-       .size          = XT_ALIGN(sizeof(struct xt_u32)),
-       .userspacesize = XT_ALIGN(sizeof(struct xt_u32)),
-       .help          = u32_help,
-       .parse         = u32_parse,
-       .print         = u32_print,
-       .save          = u32_save,
-       .extra_opts    = u32_opts,
-};
-
-static struct xtables_match u32_match6 = {
-       .name          = "u32",
-       .family        = AF_INET6,
+       .family        = AF_UNSPEC,
        .version       = IPTABLES_VERSION,
        .size          = XT_ALIGN(sizeof(struct xt_u32)),
        .userspacesize = XT_ALIGN(sizeof(struct xt_u32)),
@@ -299,6 +286,4 @@ static struct xtables_match u32_match6 = {
 void _init(void)
 {
        xtables_register_match(&u32_match);
-       xtables_register_match(&u32_match6);
-       return;
 }
index b26b416191c46fde7f865da475ec2649b63366a9..21da4b5f5fa807ce6ebac0bdb2751b6b38651c97 100644 (file)
--- a/xtables.c
+++ b/xtables.c
@@ -557,12 +557,13 @@ void xtables_register_match(struct xtables_match *me)
        }
 
        /* ignore not interested match */
-       if (me->family != afinfo.family)
+       if (me->family != afinfo.family && me->family != AF_UNSPEC)
                return;
 
        old = find_match(me->name, DURING_LOAD, NULL);
        if (old) {
-               if (old->revision == me->revision) {
+               if (old->revision == me->revision &&
+                   old->family == me->family) {
                        fprintf(stderr,
                                "%s: match `%s' already registered.\n",
                                program_name, me->name);
@@ -574,10 +575,14 @@ void xtables_register_match(struct xtables_match *me)
                    && old->revision > me->revision)
                        return;
 
-               /* Replace if compatible. */
+               /* See if new match can be used. */
                if (!compatible_match_revision(me->name, me->revision))
                        return;
 
+               /* Prefer !AF_UNSPEC over AF_UNSPEC for same revision. */
+               if (old->revision == me->revision && me->family == AF_UNSPEC)
+                       return;
+
                /* Delete old one. */
                for (i = &xtables_matches; *i!=old; i = &(*i)->next);
                *i = old->next;
@@ -623,14 +628,15 @@ void xtables_register_target(struct xtables_target *me)
        }
 
        /* ignore not interested target */
-       if (me->family != afinfo.family)
+       if (me->family != afinfo.family && me->family != AF_UNSPEC)
                return;
 
        old = find_target(me->name, DURING_LOAD);
        if (old) {
                struct xtables_target **i;
 
-               if (old->revision == me->revision) {
+               if (old->revision == me->revision &&
+                   old->family == me->family) {
                        fprintf(stderr,
                                "%s: target `%s' already registered.\n",
                                program_name, me->name);
@@ -642,10 +648,14 @@ void xtables_register_target(struct xtables_target *me)
                    && old->revision > me->revision)
                        return;
 
-               /* Replace if compatible. */
+               /* See if new target can be used. */
                if (!compatible_target_revision(me->name, me->revision))
                        return;
 
+               /* Prefer !AF_UNSPEC over AF_UNSPEC for same revision. */
+               if (old->revision == me->revision && me->family == AF_UNSPEC)
+                       return;
+
                /* Delete old one. */
                for (i = &xtables_targets; *i!=old; i = &(*i)->next);
                *i = old->next;