diff options
-rw-r--r-- | .gitignore | 2 | ||||
-rw-r--r-- | Makefile.am | 2 | ||||
-rw-r--r-- | configure.ac | 7 | ||||
-rw-r--r-- | extensions/GNUmakefile.in | 6 | ||||
-rw-r--r-- | extensions/libxt_CT.c | 40 | ||||
-rw-r--r-- | extensions/libxt_NOTRACK.c | 15 | ||||
-rw-r--r-- | extensions/libxt_conntrack.c | 191 | ||||
-rw-r--r-- | extensions/libxt_state.c | 137 | ||||
-rw-r--r-- | include/Makefile.am | 2 | ||||
-rw-r--r-- | include/xtables-version.h.in | 2 | ||||
-rw-r--r-- | include/xtables.h (renamed from include/xtables.h.in) | 7 | ||||
-rw-r--r-- | iptables/ip6tables.c | 13 | ||||
-rw-r--r-- | iptables/iptables.c | 14 | ||||
-rw-r--r-- | libxtables/xtables.c | 95 |
14 files changed, 351 insertions, 182 deletions
@@ -9,7 +9,7 @@ Makefile Makefile.in -/include/xtables.h +/include/xtables-version.h /include/iptables/internal.h /aclocal.m4 diff --git a/Makefile.am b/Makefile.am index 4eb63ebe..6400ba41 100644 --- a/Makefile.am +++ b/Makefile.am @@ -27,4 +27,4 @@ tarball: rm -Rf /tmp/${PACKAGE_TARNAME}-${PACKAGE_VERSION}; config.status: extensions/GNUmakefile.in \ - include/xtables.h.in include/iptables/internal.h.in + include/xtables-version.h.in include/iptables/internal.h.in diff --git a/configure.ac b/configure.ac index 179c2d82..adda50e4 100644 --- a/configure.ac +++ b/configure.ac @@ -2,8 +2,8 @@ AC_INIT([iptables], [1.4.15]) # See libtool.info "Libtool's versioning system" -libxtables_vcurrent=8 -libxtables_vage=1 +libxtables_vcurrent=9 +libxtables_vage=0 AC_CONFIG_AUX_DIR([build-aux]) AC_CONFIG_HEADERS([config.h]) @@ -13,6 +13,7 @@ AM_INIT_AUTOMAKE([-Wall]) AC_PROG_CC AM_PROG_CC_C_O AC_DISABLE_STATIC +m4_ifdef([AM_PROG_AR], [AM_PROG_AR]) AM_PROG_LIBTOOL AC_ARG_WITH([kernel], @@ -126,5 +127,5 @@ AC_CONFIG_FILES([Makefile extensions/GNUmakefile include/Makefile libiptc/Makefile libiptc/libiptc.pc libiptc/libip4tc.pc libiptc/libip6tc.pc libxtables/Makefile utils/Makefile - include/xtables.h include/iptables/internal.h]) + include/xtables-version.h include/iptables/internal.h]) AC_OUTPUT diff --git a/extensions/GNUmakefile.in b/extensions/GNUmakefile.in index 4a8ff49d..16390300 100644 --- a/extensions/GNUmakefile.in +++ b/extensions/GNUmakefile.in @@ -39,6 +39,7 @@ endif # Wildcard module list # pfx_build_mod := $(patsubst ${srcdir}/libxt_%.c,%,$(sort $(wildcard ${srcdir}/libxt_*.c))) +pfx_build_mod += NOTRACK state @ENABLE_IPV4_TRUE@ pf4_build_mod := $(patsubst ${srcdir}/libipt_%.c,%,$(sort $(wildcard ${srcdir}/libipt_*.c))) @ENABLE_IPV6_TRUE@ pf6_build_mod := $(patsubst ${srcdir}/libip6t_%.c,%,$(sort $(wildcard ${srcdir}/libip6t_*.c))) pfx_build_mod := $(filter-out @blacklist_modules@,${pfx_build_mod}) @@ -96,6 +97,11 @@ lib%.so: lib%.oo lib%.oo: ${srcdir}/lib%.c ${AM_VERBOSE_CC} ${CC} ${AM_CPPFLAGS} ${AM_DEPFLAGS} ${AM_CFLAGS} -D_INIT=lib$*_init -DPIC -fPIC ${CFLAGS} -o $@ -c $<; +libxt_NOTRACK.so: libxt_CT.so + ln -fs $< $@ +libxt_state.so: libxt_conntrack.so + ln -fs $< $@ + # Need the LIBADDs in iptables/Makefile.am too for libxtables_la_LIBADD xt_RATEEST_LIBADD = -lm xt_statistic_LIBADD = -lm diff --git a/extensions/libxt_CT.c b/extensions/libxt_CT.c index 27a20e2e..a576a953 100644 --- a/extensions/libxt_CT.c +++ b/extensions/libxt_CT.c @@ -248,6 +248,20 @@ static void ct_save_v1(const void *ip, const struct xt_entry_target *target) printf(" --zone %u", info->zone); } +static void notrack_ct0_tg_init(struct xt_entry_target *target) +{ + struct xt_ct_target_info *info = (void *)target->data; + + info->flags = XT_CT_NOTRACK; +} + +static void notrack_ct1_tg_init(struct xt_entry_target *target) +{ + struct xt_ct_target_info_v1 *info = (void *)target->data; + + info->flags = XT_CT_NOTRACK; +} + static struct xtables_target ct_target_reg[] = { { .family = NFPROTO_UNSPEC, @@ -274,6 +288,32 @@ static struct xtables_target ct_target_reg[] = { .x6_parse = ct_parse_v1, .x6_options = ct_opts_v1, }, + { + .family = NFPROTO_UNSPEC, + .name = "NOTRACK", + .real_name = "CT", + .revision = 0, + .version = XTABLES_VERSION, + .size = XT_ALIGN(sizeof(struct xt_ct_target_info)), + .userspacesize = offsetof(struct xt_ct_target_info, ct), + .init = notrack_ct0_tg_init, + }, + { + .family = NFPROTO_UNSPEC, + .name = "NOTRACK", + .real_name = "CT", + .revision = 1, + .version = XTABLES_VERSION, + .size = XT_ALIGN(sizeof(struct xt_ct_target_info_v1)), + .userspacesize = offsetof(struct xt_ct_target_info_v1, ct), + .init = notrack_ct1_tg_init, + }, + { + .family = NFPROTO_UNSPEC, + .name = "NOTRACK", + .revision = 0, + .version = XTABLES_VERSION, + }, }; void _init(void) diff --git a/extensions/libxt_NOTRACK.c b/extensions/libxt_NOTRACK.c deleted file mode 100644 index ca587002..00000000 --- a/extensions/libxt_NOTRACK.c +++ /dev/null @@ -1,15 +0,0 @@ -/* Shared library add-on to iptables to add NOTRACK target support. */ -#include <xtables.h> - -static struct xtables_target notrack_target = { - .family = NFPROTO_UNSPEC, - .name = "NOTRACK", - .version = XTABLES_VERSION, - .size = XT_ALIGN(0), - .userspacesize = XT_ALIGN(0), -}; - -void _init(void) -{ - xtables_register_target(¬rack_target); -} diff --git a/extensions/libxt_conntrack.c b/extensions/libxt_conntrack.c index fff69f8a..c37f14d2 100644 --- a/extensions/libxt_conntrack.c +++ b/extensions/libxt_conntrack.c @@ -13,7 +13,11 @@ #include <string.h> #include <xtables.h> #include <linux/netfilter/xt_conntrack.h> +#include <linux/netfilter/xt_state.h> #include <linux/netfilter/nf_conntrack_common.h> +#ifndef XT_STATE_UNTRACKED +#define XT_STATE_UNTRACKED (1 << (IP_CT_NUMBER + 1)) +#endif struct ip_conntrack_old_tuple { struct { @@ -1003,6 +1007,144 @@ conntrack1_mt6_save(const void *ip, const struct xt_entry_match *match) conntrack_dump(&up, "--", NFPROTO_IPV6, true, false); } +static void +state_help(void) +{ + printf( +"state match options:\n" +" [!] --state [INVALID|ESTABLISHED|NEW|RELATED|UNTRACKED][,...]\n" +" State(s) to match\n"); +} + +static const struct xt_option_entry state_opts[] = { + {.name = "state", .id = O_CTSTATE, .type = XTTYPE_STRING, + .flags = XTOPT_MAND | XTOPT_INVERT}, + XTOPT_TABLEEND, +}; + +static unsigned int +state_parse_state(const char *state, size_t len) +{ + if (strncasecmp(state, "INVALID", len) == 0) + return XT_STATE_INVALID; + else if (strncasecmp(state, "NEW", len) == 0) + return XT_STATE_BIT(IP_CT_NEW); + else if (strncasecmp(state, "ESTABLISHED", len) == 0) + return XT_STATE_BIT(IP_CT_ESTABLISHED); + else if (strncasecmp(state, "RELATED", len) == 0) + return XT_STATE_BIT(IP_CT_RELATED); + else if (strncasecmp(state, "UNTRACKED", len) == 0) + return XT_STATE_UNTRACKED; + return 0; +} + +static unsigned int +state_parse_states(const char *arg) +{ + const char *comma; + unsigned int mask = 0, flag; + + while ((comma = strchr(arg, ',')) != NULL) { + if (comma == arg) + goto badstate; + flag = state_parse_state(arg, comma-arg); + if (flag == 0) + goto badstate; + mask |= flag; + arg = comma+1; + } + if (!*arg) + xtables_error(PARAMETER_PROBLEM, "\"--state\" requires a list of " + "states with no spaces, e.g. " + "ESTABLISHED,RELATED"); + if (strlen(arg) == 0) + goto badstate; + flag = state_parse_state(arg, strlen(arg)); + if (flag == 0) + goto badstate; + mask |= flag; + return mask; + badstate: + xtables_error(PARAMETER_PROBLEM, "Bad state \"%s\"", arg); +} + +static void state_parse(struct xt_option_call *cb) +{ + struct xt_state_info *sinfo = cb->data; + + xtables_option_parse(cb); + sinfo->statemask = state_parse_states(cb->arg); + if (cb->invert) + sinfo->statemask = ~sinfo->statemask; +} + +static void state_ct1_parse(struct xt_option_call *cb) +{ + struct xt_conntrack_mtinfo1 *sinfo = cb->data; + + xtables_option_parse(cb); + sinfo->match_flags = XT_CONNTRACK_STATE; + sinfo->state_mask = state_parse_states(cb->arg); + if (cb->invert) + sinfo->invert_flags |= XT_CONNTRACK_STATE; +} + +static void state_ct23_parse(struct xt_option_call *cb) +{ + struct xt_conntrack_mtinfo3 *sinfo = cb->data; + + xtables_option_parse(cb); + sinfo->match_flags = XT_CONNTRACK_STATE; + sinfo->state_mask = state_parse_states(cb->arg); + if (cb->invert) + sinfo->invert_flags |= XT_CONNTRACK_STATE; +} + +static void state_print_state(unsigned int statemask) +{ + const char *sep = ""; + + if (statemask & XT_STATE_INVALID) { + printf("%sINVALID", sep); + sep = ","; + } + if (statemask & XT_STATE_BIT(IP_CT_NEW)) { + printf("%sNEW", sep); + sep = ","; + } + if (statemask & XT_STATE_BIT(IP_CT_RELATED)) { + printf("%sRELATED", sep); + sep = ","; + } + if (statemask & XT_STATE_BIT(IP_CT_ESTABLISHED)) { + printf("%sESTABLISHED", sep); + sep = ","; + } + if (statemask & XT_STATE_UNTRACKED) { + printf("%sUNTRACKED", sep); + sep = ","; + } +} + +static void +state_print(const void *ip, + const struct xt_entry_match *match, + int numeric) +{ + const struct xt_state_info *sinfo = (const void *)match->data; + + printf(" state "); + state_print_state(sinfo->statemask); +} + +static void state_save(const void *ip, const struct xt_entry_match *match) +{ + const struct xt_state_info *sinfo = (const void *)match->data; + + printf(" --state "); + state_print_state(sinfo->statemask); +} + static struct xtables_match conntrack_mt_reg[] = { { .version = XTABLES_VERSION, @@ -1102,6 +1244,55 @@ static struct xtables_match conntrack_mt_reg[] = { .save = conntrack3_mt6_save, .x6_options = conntrack3_mt_opts, }, + { + .family = NFPROTO_UNSPEC, + .name = "state", + .real_name = "conntrack", + .revision = 1, + .version = XTABLES_VERSION, + .size = XT_ALIGN(sizeof(struct xt_conntrack_mtinfo1)), + .userspacesize = XT_ALIGN(sizeof(struct xt_conntrack_mtinfo1)), + .help = state_help, + .x6_parse = state_ct1_parse, + .x6_options = state_opts, + }, + { + .family = NFPROTO_UNSPEC, + .name = "state", + .real_name = "conntrack", + .revision = 2, + .version = XTABLES_VERSION, + .size = XT_ALIGN(sizeof(struct xt_conntrack_mtinfo2)), + .userspacesize = XT_ALIGN(sizeof(struct xt_conntrack_mtinfo2)), + .help = state_help, + .x6_parse = state_ct23_parse, + .x6_options = state_opts, + }, + { + .family = NFPROTO_UNSPEC, + .name = "state", + .real_name = "conntrack", + .revision = 3, + .version = XTABLES_VERSION, + .size = XT_ALIGN(sizeof(struct xt_conntrack_mtinfo3)), + .userspacesize = XT_ALIGN(sizeof(struct xt_conntrack_mtinfo3)), + .help = state_help, + .x6_parse = state_ct23_parse, + .x6_options = state_opts, + }, + { + .family = NFPROTO_UNSPEC, + .name = "state", + .revision = 0, + .version = XTABLES_VERSION, + .size = XT_ALIGN(sizeof(struct xt_state_info)), + .userspacesize = XT_ALIGN(sizeof(struct xt_state_info)), + .help = state_help, + .print = state_print, + .save = state_save, + .x6_parse = state_parse, + .x6_options = state_opts, + }, }; void _init(void) diff --git a/extensions/libxt_state.c b/extensions/libxt_state.c deleted file mode 100644 index eff444c8..00000000 --- a/extensions/libxt_state.c +++ /dev/null @@ -1,137 +0,0 @@ -#include <stdio.h> -#include <string.h> -#include <xtables.h> -#include <linux/netfilter/nf_conntrack_common.h> -#include <linux/netfilter/xt_state.h> - -#ifndef XT_STATE_UNTRACKED -#define XT_STATE_UNTRACKED (1 << (IP_CT_NUMBER + 1)) -#endif - -enum { - O_STATE = 0, -}; - -static void -state_help(void) -{ - printf( -"state match options:\n" -" [!] --state [INVALID|ESTABLISHED|NEW|RELATED|UNTRACKED][,...]\n" -" State(s) to match\n"); -} - -static const struct xt_option_entry state_opts[] = { - {.name = "state", .id = O_STATE, .type = XTTYPE_STRING, - .flags = XTOPT_MAND | XTOPT_INVERT}, - XTOPT_TABLEEND, -}; - -static int -state_parse_state(const char *state, size_t len, struct xt_state_info *sinfo) -{ - if (strncasecmp(state, "INVALID", len) == 0) - sinfo->statemask |= XT_STATE_INVALID; - else if (strncasecmp(state, "NEW", len) == 0) - sinfo->statemask |= XT_STATE_BIT(IP_CT_NEW); - else if (strncasecmp(state, "ESTABLISHED", len) == 0) - sinfo->statemask |= XT_STATE_BIT(IP_CT_ESTABLISHED); - else if (strncasecmp(state, "RELATED", len) == 0) - sinfo->statemask |= XT_STATE_BIT(IP_CT_RELATED); - else if (strncasecmp(state, "UNTRACKED", len) == 0) - sinfo->statemask |= XT_STATE_UNTRACKED; - else - return 0; - return 1; -} - -static void -state_parse_states(const char *arg, struct xt_state_info *sinfo) -{ - const char *comma; - - while ((comma = strchr(arg, ',')) != NULL) { - if (comma == arg || !state_parse_state(arg, comma-arg, sinfo)) - xtables_error(PARAMETER_PROBLEM, "Bad state \"%s\"", arg); - arg = comma+1; - } - if (!*arg) - xtables_error(PARAMETER_PROBLEM, "\"--state\" requires a list of " - "states with no spaces, e.g. " - "ESTABLISHED,RELATED"); - if (strlen(arg) == 0 || !state_parse_state(arg, strlen(arg), sinfo)) - xtables_error(PARAMETER_PROBLEM, "Bad state \"%s\"", arg); -} - -static void state_parse(struct xt_option_call *cb) -{ - struct xt_state_info *sinfo = cb->data; - - xtables_option_parse(cb); - state_parse_states(cb->arg, sinfo); - if (cb->invert) - sinfo->statemask = ~sinfo->statemask; -} - -static void state_print_state(unsigned int statemask) -{ - const char *sep = ""; - - if (statemask & XT_STATE_INVALID) { - printf("%sINVALID", sep); - sep = ","; - } - if (statemask & XT_STATE_BIT(IP_CT_NEW)) { - printf("%sNEW", sep); - sep = ","; - } - if (statemask & XT_STATE_BIT(IP_CT_RELATED)) { - printf("%sRELATED", sep); - sep = ","; - } - if (statemask & XT_STATE_BIT(IP_CT_ESTABLISHED)) { - printf("%sESTABLISHED", sep); - sep = ","; - } - if (statemask & XT_STATE_UNTRACKED) { - printf("%sUNTRACKED", sep); - sep = ","; - } -} - -static void -state_print(const void *ip, - const struct xt_entry_match *match, - int numeric) -{ - const struct xt_state_info *sinfo = (const void *)match->data; - - printf(" state "); - state_print_state(sinfo->statemask); -} - -static void state_save(const void *ip, const struct xt_entry_match *match) -{ - const struct xt_state_info *sinfo = (const void *)match->data; - - printf(" --state "); - state_print_state(sinfo->statemask); -} - -static struct xtables_match state_match = { - .family = NFPROTO_UNSPEC, - .name = "state", - .version = XTABLES_VERSION, - .size = XT_ALIGN(sizeof(struct xt_state_info)), - .userspacesize = XT_ALIGN(sizeof(struct xt_state_info)), - .help = state_help, - .print = state_print, - .save = state_save, - .x6_parse = state_parse, - .x6_options = state_opts, -}; - -void _init(void) -{ - xtables_register_match(&state_match); -} diff --git a/include/Makefile.am b/include/Makefile.am index 6f7da598..e6951209 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -1,7 +1,7 @@ # -*- Makefile -*- include_HEADERS = -nobase_include_HEADERS = xtables.h +nobase_include_HEADERS = xtables.h xtables-version.h if ENABLE_LIBIPQ include_HEADERS += libipq/libipq.h diff --git a/include/xtables-version.h.in b/include/xtables-version.h.in new file mode 100644 index 00000000..cb13827c --- /dev/null +++ b/include/xtables-version.h.in @@ -0,0 +1,2 @@ +#define XTABLES_VERSION "libxtables.so.@libxtables_vmajor@" +#define XTABLES_VERSION_CODE @libxtables_vmajor@ diff --git a/include/xtables.h.in b/include/xtables.h index db69c03b..2cc1a028 100644 --- a/include/xtables.h.in +++ b/include/xtables.h @@ -31,8 +31,7 @@ #define IPPROTO_UDPLITE 136 #endif -#define XTABLES_VERSION "libxtables.so.@libxtables_vmajor@" -#define XTABLES_VERSION_CODE @libxtables_vmajor@ +#include <xtables-version.h> struct in_addr; @@ -214,6 +213,7 @@ struct xtables_match struct xtables_match *next; const char *name; + const char *real_name; /* Revision of match (0 by default). */ u_int8_t revision; @@ -283,6 +283,9 @@ struct xtables_target const char *name; + /* Real target behind this, if any. */ + const char *real_name; + /* Revision of target (0 by default). */ u_int8_t revision; diff --git a/iptables/ip6tables.c b/iptables/ip6tables.c index 7a16b974..36612161 100644 --- a/iptables/ip6tables.c +++ b/iptables/ip6tables.c @@ -1286,8 +1286,13 @@ static void command_jump(struct iptables_command_state *cs) cs->target->t = xtables_calloc(1, size); cs->target->t->u.target_size = size; - strcpy(cs->target->t->u.user.name, cs->jumpto); + strcpy(cs->target->t->u.user.name, cs->target->real_name); cs->target->t->u.user.revision = cs->target->revision; + if (cs->target->real_name != cs->target->name) + fprintf(stderr, "WARNING: The %s target is obsolete. " + "Use %s instead.\n", + cs->jumpto, cs->target->real_name); + xs_init_target(cs->target); if (cs->target->x6_options != NULL) opts = xtables_options_xfrm(ip6tables_globals.orig_opts, opts, @@ -1314,8 +1319,12 @@ static void command_match(struct iptables_command_state *cs) size = XT_ALIGN(sizeof(struct xt_entry_match)) + m->size; m->m = xtables_calloc(1, size); m->m->u.match_size = size; - strcpy(m->m->u.user.name, m->name); + strcpy(m->m->u.user.name, m->real_name); m->m->u.user.revision = m->revision; + if (m->real_name != m->name) + fprintf(stderr, "WARNING: The %s match is obsolete. " + "Use %s instead.\n", m->name, m->real_name); + xs_init_match(m); if (m == m->next) return; diff --git a/iptables/iptables.c b/iptables/iptables.c index 9e3d696a..e935f651 100644 --- a/iptables/iptables.c +++ b/iptables/iptables.c @@ -1295,8 +1295,14 @@ static void command_jump(struct iptables_command_state *cs) cs->target->t = xtables_calloc(1, size); cs->target->t->u.target_size = size; - strcpy(cs->target->t->u.user.name, cs->jumpto); + strcpy(cs->target->t->u.user.name, cs->target->real_name); cs->target->t->u.user.revision = cs->target->revision; + if (cs->target->real_name != cs->target->name) + /* Alias support for userspace side */ + fprintf(stderr, "WARNING: The %s target is obsolete. " + "Use %s instead.\n", + cs->jumpto, cs->target->real_name); + xs_init_target(cs->target); if (cs->target->x6_options != NULL) @@ -1324,8 +1330,12 @@ static void command_match(struct iptables_command_state *cs) size = XT_ALIGN(sizeof(struct xt_entry_match)) + m->size; m->m = xtables_calloc(1, size); m->m->u.match_size = size; - strcpy(m->m->u.user.name, m->name); + strcpy(m->m->u.user.name, m->real_name); m->m->u.user.revision = m->revision; + if (m->real_name != m->name) + fprintf(stderr, "WARNING: The %s match is obsolete. " + "Use %s instead.\n", m->name, m->real_name); + xs_init_match(m); if (m == m->next) return; diff --git a/libxtables/xtables.c b/libxtables/xtables.c index d8185796..82c3643b 100644 --- a/libxtables/xtables.c +++ b/libxtables/xtables.c @@ -848,6 +848,8 @@ void xtables_register_match(struct xtables_match *me) exit(1); } + if (me->real_name == NULL) + me->real_name = me->name; if (me->x6_options != NULL) xtables_option_metavalidate(me->name, me->x6_options); if (me->extra_opts != NULL) @@ -862,14 +864,76 @@ void xtables_register_match(struct xtables_match *me) xtables_pending_matches = me; } +/** + * Compare two actions for their preference + * @a: one action + * @b: another + * + * Like strcmp, returns a negative number if @a is less preferred than @b, + * positive number if @a is more preferred than @b, or zero if equally + * preferred. + */ +static int +xtables_mt_prefer(bool a_alias, unsigned int a_rev, unsigned int a_fam, + bool b_alias, unsigned int b_rev, unsigned int b_fam) +{ + /* + * Alias ranks higher than no alias. + * (We want the new action to be used whenever possible.) + */ + if (!a_alias && b_alias) + return -1; + if (a_alias && !b_alias) + return 1; + + /* Higher revision ranks higher. */ + if (a_rev < b_rev) + return -1; + if (a_rev > b_rev) + return 1; + + /* NFPROTO_<specific> ranks higher than NFPROTO_UNSPEC. */ + if (a_fam == NFPROTO_UNSPEC && b_fam != NFPROTO_UNSPEC) + return -1; + if (a_fam != NFPROTO_UNSPEC && b_fam == NFPROTO_UNSPEC) + return 1; + + /* Must be the same thing. */ + return 0; +} + +static int xtables_match_prefer(const struct xtables_match *a, + const struct xtables_match *b) +{ + return xtables_mt_prefer(a->name != a->real_name, + a->revision, a->family, + b->name != b->real_name, + b->revision, b->family); +} + +static int xtables_target_prefer(const struct xtables_target *a, + const struct xtables_target *b) +{ + /* + * Note that if x->real_name==NULL, it will be set to x->name in + * xtables_register_*; the direct pointer comparison here is therefore + * legitimate to detect an alias. + */ + return xtables_mt_prefer(a->name != a->real_name, + a->revision, a->family, + b->name != b->real_name, + b->revision, b->family); +} + static void xtables_fully_register_pending_match(struct xtables_match *me) { struct xtables_match **i, *old; + int compare; old = xtables_find_match(me->name, XTF_DURING_LOAD, NULL); if (old) { - if (old->revision == me->revision && - old->family == me->family) { + compare = xtables_match_prefer(old, me); + if (compare == 0) { fprintf(stderr, "%s: match `%s' already registered.\n", xt_params->program_name, me->name); @@ -877,16 +941,12 @@ static void xtables_fully_register_pending_match(struct xtables_match *me) } /* Now we have two (or more) options, check compatibility. */ - if (compatible_match_revision(old->name, old->revision) - && old->revision > me->revision) + if (compare > 0 && + compatible_match_revision(old->real_name, old->revision)) return; /* 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) + if (!compatible_match_revision(me->real_name, me->revision)) return; /* Delete old one. */ @@ -945,6 +1005,8 @@ void xtables_register_target(struct xtables_target *me) exit(1); } + if (me->real_name == NULL) + me->real_name = me->name; if (me->x6_options != NULL) xtables_option_metavalidate(me->name, me->x6_options); if (me->extra_opts != NULL) @@ -962,13 +1024,14 @@ void xtables_register_target(struct xtables_target *me) static void xtables_fully_register_pending_target(struct xtables_target *me) { struct xtables_target *old; + int compare; old = xtables_find_target(me->name, XTF_DURING_LOAD); if (old) { struct xtables_target **i; - if (old->revision == me->revision && - old->family == me->family) { + compare = xtables_target_prefer(old, me); + if (compare == 0) { fprintf(stderr, "%s: target `%s' already registered.\n", xt_params->program_name, me->name); @@ -976,16 +1039,12 @@ static void xtables_fully_register_pending_target(struct xtables_target *me) } /* Now we have two (or more) options, check compatibility. */ - if (compatible_target_revision(old->name, old->revision) - && old->revision > me->revision) + if (compare > 0 && + compatible_target_revision(old->real_name, old->revision)) return; /* 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) + if (!compatible_target_revision(me->real_name, me->revision)) return; /* Delete old one. */ |