summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore2
-rw-r--r--Makefile.am2
-rw-r--r--configure.ac9
-rw-r--r--extensions/.gitignore4
-rw-r--r--extensions/GNUmakefile.in45
-rw-r--r--extensions/libxt_CT.c40
-rw-r--r--extensions/libxt_HMARK.man2
-rw-r--r--extensions/libxt_NOTRACK.c15
-rw-r--r--extensions/libxt_NOTRACK.man6
-rw-r--r--extensions/libxt_conntrack.c191
-rw-r--r--extensions/libxt_conntrack.man18
-rw-r--r--extensions/libxt_hashlimit.c2
-rw-r--r--extensions/libxt_limit.c2
-rw-r--r--extensions/libxt_set.c98
-rw-r--r--extensions/libxt_set.man6
-rw-r--r--extensions/libxt_state.c137
-rw-r--r--extensions/libxt_state.man28
-rw-r--r--include/Makefile.am2
-rw-r--r--include/linux/netfilter/ipset/ip_set.h2
-rw-r--r--include/xtables-version.h.in2
-rw-r--r--include/xtables.h (renamed from include/xtables.h.in)7
-rw-r--r--iptables/.gitignore1
-rw-r--r--iptables/Makefile.am16
-rw-r--r--iptables/ip6tables.8.in21
-rw-r--r--iptables/ip6tables.c19
-rw-r--r--iptables/iptables-apply.82
-rw-r--r--iptables/iptables-extensions.8.in27
-rw-r--r--iptables/iptables.8.in23
-rw-r--r--iptables/iptables.c20
-rw-r--r--libxtables/xtables.c97
30 files changed, 562 insertions, 284 deletions
diff --git a/.gitignore b/.gitignore
index b7c3dfb8..fa86c482 100644
--- a/.gitignore
+++ b/.gitignore
@@ -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..c3b253a6 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,9 +1,9 @@
-AC_INIT([iptables], [1.4.15])
+AC_INIT([iptables], [1.4.16.3])
# 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/.gitignore b/extensions/.gitignore
index 2e74faf7..b1260f0b 100644
--- a/extensions/.gitignore
+++ b/extensions/.gitignore
@@ -5,5 +5,5 @@
/GNUmakefile
/initext.c
/initext?.c
-/matches?.man
-/targets?.man
+/matches.man
+/targets.man
diff --git a/extensions/GNUmakefile.in b/extensions/GNUmakefile.in
index 2492d184..e71e3ff9 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_symlinks := 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})
@@ -47,7 +48,7 @@ pf6_build_mod := $(filter-out @blacklist_modules@,${pf6_build_mod})
pfx_objs := $(patsubst %,libxt_%.o,${pfx_build_mod})
pf4_objs := $(patsubst %,libipt_%.o,${pf4_build_mod})
pf6_objs := $(patsubst %,libip6t_%.o,${pf6_build_mod})
-pfx_solibs := $(patsubst %,libxt_%.so,${pfx_build_mod})
+pfx_solibs := $(patsubst %,libxt_%.so,${pfx_build_mod} ${pfx_symlinks})
pf4_solibs := $(patsubst %,libipt_%.so,${pf4_build_mod})
pf6_solibs := $(patsubst %,libip6t_%.so,${pf6_build_mod})
@@ -55,9 +56,7 @@ pf6_solibs := $(patsubst %,libip6t_%.so,${pf6_build_mod})
#
# Building blocks
#
-targets := libext.a libext4.a libext6.a \
- matches4.man matches6.man \
- targets4.man targets6.man
+targets := libext.a libext4.a libext6.a matches.man targets.man
targets_install :=
@ENABLE_STATIC_TRUE@ libext_objs := ${pfx_objs}
@ENABLE_STATIC_TRUE@ libext4_objs := ${pf4_objs}
@@ -76,10 +75,10 @@ install: ${targets_install}
if test -n "${targets_install}"; then install -pm0755 $^ "${DESTDIR}${xtlibdir}/"; fi;
clean:
- rm -f *.o *.oo *.so *.a {matches,targets}[46].man initext.c initext4.c initext6.c;
+ rm -f *.o *.oo *.so *.a {matches,targets}.man initext.c initext4.c initext6.c;
+ rm -f .*.d .*.dd;
distclean: clean
- rm -f .*.d .*.dd;
init%.o: init%.c
${AM_VERBOSE_CC} ${CC} ${AM_CPPFLAGS} ${AM_DEPFLAGS} ${AM_CFLAGS} -D_INIT=$*_init ${CFLAGS} -o $@ -c $<;
@@ -96,6 +95,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
ip6t_NETMAP_LIBADD = -lip6tc
xt_RATEEST_LIBADD = -lm
@@ -196,30 +200,27 @@ man_run = \
${AM_VERBOSE_GEN} \
for ext in $(sort ${1}); do \
f="${srcdir}/libxt_$$ext.man"; \
- cf="${srcdir}/libxt_$$ext.c"; \
- if [ -f "$$f" ] && grep -Eq "$(3)|NFPROTO_UNSPEC" "$$cf"; then \
+ if [ -f "$$f" ]; then \
echo -e "\t+ $$f" >&2; \
echo ".SS $$ext"; \
cat "$$f" || exit $$?; \
- continue; \
fi; \
- f="${srcdir}/lib$(2)t_$$ext.man"; \
+ f="${srcdir}/libip6t_$$ext.man"; \
if [ -f "$$f" ]; then \
echo -e "\t+ $$f" >&2; \
- echo ".SS $$ext"; \
+ echo ".SS $$ext (IPv6-specific)"; \
+ cat "$$f" || exit $$?; \
+ fi; \
+ f="${srcdir}/libipt_$$ext.man"; \
+ if [ -f "$$f" ]; then \
+ echo -e "\t+ $$f" >&2; \
+ echo ".SS $$ext (IPv4-specific)"; \
cat "$$f" || exit $$?; \
- continue; \
fi; \
done >$@;
-matches4.man: .initext.dd .initext4.dd $(wildcard ${srcdir}/lib*.man)
- $(call man_run,$(call ex_matches,${pfx_build_mod} ${pf4_build_mod}),ip,NFPROTO_IPV4)
-
-matches6.man: .initext.dd .initext6.dd $(wildcard ${srcdir}/lib*.man)
- $(call man_run,$(call ex_matches,${pfx_build_mod} ${pf6_build_mod}),ip6,NFPROTO_IPV6)
-
-targets4.man: .initext.dd .initext4.dd $(wildcard ${srcdir}/lib*.man)
- $(call man_run,$(call ex_targets,${pfx_build_mod} ${pf4_build_mod}),ip,NFPROTO_IPV4)
+matches.man: .initext.dd .initext4.dd .initext6.dd $(wildcard ${srcdir}/lib*.man)
+ $(call man_run,$(call ex_matches,${pfx_build_mod} ${pf4_build_mod} ${pf6_build_mod} ${pfx_symlinks}))
-targets6.man: .initext.dd .initext6.dd $(wildcard ${srcdir}/lib*.man)
- $(call man_run,$(call ex_targets,${pfx_build_mod} ${pf6_build_mod}),ip6,NFPROTO_IPV6)
+targets.man: .initext.dd .initext4.dd .initext6.dd $(wildcard ${srcdir}/lib*.man)
+ $(call man_run,$(call ex_targets,${pfx_build_mod} ${pf4_build_mod} ${pf6_build_mod} ${pfx_symlinks}))
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_HMARK.man b/extensions/libxt_HMARK.man
index 0b418842..e7b5426d 100644
--- a/extensions/libxt_HMARK.man
+++ b/extensions/libxt_HMARK.man
@@ -52,7 +52,7 @@ A 32 bit random custom value to feed hash calculation.
.PP
\fIExamples:\fP
.PP
-iptables \-t mangle \-A PREROUTING \-m state \-\-state NEW
+iptables \-t mangle \-A PREROUTING \-m conntrack \-\-ctstate NEW
\-j HMARK \-\-hmark-tuple ct,src,dst,proto \-\-hmark-offset 10000
\-\-hmark\-mod 10 \-\-hmark\-rnd 0xfeedcafe
.PP
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(&notrack_target);
-}
diff --git a/extensions/libxt_NOTRACK.man b/extensions/libxt_NOTRACK.man
index c2cdf5a6..633b965e 100644
--- a/extensions/libxt_NOTRACK.man
+++ b/extensions/libxt_NOTRACK.man
@@ -1,5 +1,3 @@
This target disables connection tracking for all packets matching that rule.
-.PP
-It can only be used in the
-.B raw
-table.
+It is obsoleted by \-j CT \-\-notrack. Like CT, NOTRACK can only be used in
+the \fBraw\fP table.
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_conntrack.man b/extensions/libxt_conntrack.man
index c397f742..15fd1ddf 100644
--- a/extensions/libxt_conntrack.man
+++ b/extensions/libxt_conntrack.man
@@ -42,23 +42,23 @@ specified at all, matches packets in both directions.
States for \fB\-\-ctstate\fP:
.TP
\fBINVALID\fP
-meaning that the packet is associated with no known connection
+The packet is associated with no known connection.
.TP
\fBNEW\fP
-meaning that the packet has started a new connection, or otherwise associated
-with a connection which has not seen packets in both directions, and
+The packet has started a new connection, or otherwise associated
+with a connection which has not seen packets in both directions.
.TP
\fBESTABLISHED\fP
-meaning that the packet is associated with a connection which has seen packets
-in both directions,
+The packet is associated with a connection which has seen packets
+in both directions.
.TP
\fBRELATED\fP
-meaning that the packet is starting a new connection, but is associated with an
+The packet is starting a new connection, but is associated with an
existing connection, such as an FTP data transfer, or an ICMP error.
.TP
\fBUNTRACKED\fP
-meaning that the packet is not tracked at all, which happens if you use
-the NOTRACK target in raw table.
+The packet is not tracked at all, which happens if you explicitly untrack it
+by using \-j CT \-\-notrack in the raw table.
.TP
\fBSNAT\fP
A virtual state, matching if the original source address differs from the reply
@@ -74,7 +74,7 @@ Statuses for \fB\-\-ctstatus\fP:
None of the below.
.TP
\fBEXPECTED\fP
-This is an expected connection (i.e. a conntrack helper set it up)
+This is an expected connection (i.e. a conntrack helper set it up).
.TP
\fBSEEN_REPLY\fP
Conntrack has seen packets in both directions.
diff --git a/extensions/libxt_hashlimit.c b/extensions/libxt_hashlimit.c
index 831345b7..c5b8d779 100644
--- a/extensions/libxt_hashlimit.c
+++ b/extensions/libxt_hashlimit.c
@@ -10,6 +10,8 @@
*
* Error corections by nmalykh@bilim.com (22.01.2005)
*/
+#define _BSD_SOURCE 1
+#define _ISOC99_SOURCE 1
#include <math.h>
#include <stdbool.h>
#include <stdint.h>
diff --git a/extensions/libxt_limit.c b/extensions/libxt_limit.c
index 023500cf..f75ef2f8 100644
--- a/extensions/libxt_limit.c
+++ b/extensions/libxt_limit.c
@@ -3,6 +3,8 @@
* Jérôme de Vivie <devivie@info.enserb.u-bordeaux.fr>
* Hervé Eychenne <rv@wallfire.org>
*/
+#define _BSD_SOURCE 1
+#define _ISOC99_SOURCE 1
#include <math.h>
#include <stdio.h>
#include <string.h>
diff --git a/extensions/libxt_set.c b/extensions/libxt_set.c
index 77e3f07e..e0111568 100644
--- a/extensions/libxt_set.c
+++ b/extensions/libxt_set.c
@@ -205,6 +205,90 @@ set_save_v1(const void *ip, const struct xt_entry_match *match)
print_match("--match-set", &info->match_set);
}
+/* Revision 2 */
+static void
+set_help_v2(void)
+{
+ printf("set match options:\n"
+ " [!] --match-set name flags [--return-nomatch]\n"
+ " 'name' is the set name from to match,\n"
+ " 'flags' are the comma separated list of\n"
+ " 'src' and 'dst' specifications.\n");
+}
+
+static const struct option set_opts_v2[] = {
+ {.name = "match-set", .has_arg = true, .val = '1'},
+ {.name = "set", .has_arg = true, .val = '2'},
+ {.name = "return-nomatch", .has_arg = false, .val = '3'},
+ XT_GETOPT_TABLEEND,
+};
+
+static int
+set_parse_v2(int c, char **argv, int invert, unsigned int *flags,
+ const void *entry, struct xt_entry_match **match)
+{
+ struct xt_set_info_match_v1 *myinfo =
+ (struct xt_set_info_match_v1 *) (*match)->data;
+ struct xt_set_info *info = &myinfo->match_set;
+
+ switch (c) {
+ case '3':
+ info->flags |= IPSET_RETURN_NOMATCH;
+ break;
+ case '2':
+ fprintf(stderr,
+ "--set option deprecated, please use --match-set\n");
+ case '1': /* --match-set <set> <flag>[,<flag> */
+ if (info->dim)
+ xtables_error(PARAMETER_PROBLEM,
+ "--match-set can be specified only once");
+ if (invert)
+ info->flags |= IPSET_INV_MATCH;
+
+ if (!argv[optind]
+ || argv[optind][0] == '-'
+ || argv[optind][0] == '!')
+ xtables_error(PARAMETER_PROBLEM,
+ "--match-set requires two args.");
+
+ if (strlen(optarg) > IPSET_MAXNAMELEN - 1)
+ xtables_error(PARAMETER_PROBLEM,
+ "setname `%s' too long, max %d characters.",
+ optarg, IPSET_MAXNAMELEN - 1);
+
+ get_set_byname(optarg, info);
+ parse_dirs(argv[optind], info);
+ DEBUGP("parse: set index %u\n", info->index);
+ optind++;
+
+ *flags = 1;
+ break;
+ }
+
+ return 1;
+}
+
+/* Prints out the matchinfo. */
+static void
+set_print_v2(const void *ip, const struct xt_entry_match *match, int numeric)
+{
+ const struct xt_set_info_match_v1 *info = (const void *)match->data;
+
+ print_match("match-set", &info->match_set);
+ if (info->match_set.flags & IPSET_RETURN_NOMATCH)
+ printf(" return-nomatch");
+}
+
+static void
+set_save_v2(const void *ip, const struct xt_entry_match *match)
+{
+ const struct xt_set_info_match_v1 *info = (const void *)match->data;
+
+ print_match("--match-set", &info->match_set);
+ if (info->match_set.flags & IPSET_RETURN_NOMATCH)
+ printf(" --return-nomatch");
+}
+
static struct xtables_match set_mt_reg[] = {
{
.name = "set",
@@ -234,6 +318,20 @@ static struct xtables_match set_mt_reg[] = {
.save = set_save_v1,
.extra_opts = set_opts_v0,
},
+ {
+ .name = "set",
+ .revision = 2,
+ .version = XTABLES_VERSION,
+ .family = NFPROTO_UNSPEC,
+ .size = XT_ALIGN(sizeof(struct xt_set_info_match_v1)),
+ .userspacesize = XT_ALIGN(sizeof(struct xt_set_info_match_v1)),
+ .help = set_help_v2,
+ .parse = set_parse_v2,
+ .final_check = set_check_v0,
+ .print = set_print_v2,
+ .save = set_save_v2,
+ .extra_opts = set_opts_v2,
+ },
};
void _init(void)
diff --git a/extensions/libxt_set.man b/extensions/libxt_set.man
index 1ad90859..ac60f148 100644
--- a/extensions/libxt_set.man
+++ b/extensions/libxt_set.man
@@ -14,6 +14,12 @@ address and destination port pair can be found in the specified set. If
the set type of the specified set is single dimension (for example ipmap),
then the command will match packets for which the source address can be
found in the specified set.
+.TP
+\fB\-\-return\-\-nomatch\fP
+If the \fB\-\-return\-\-nomatch\fP option is specified and the set type
+supports the \fBnomatch\fP flag, then the matching is reversed: a match
+with an element flagged with \fBnomatch\fP returns \fBtrue\fP, while a
+match with a plain element returns \fBfalse\fP.
.PP
The option \fB\-\-match\-set\fP can be replaced by \fB\-\-set\fP if that does
not clash with an option of other extensions.
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/extensions/libxt_state.man b/extensions/libxt_state.man
index 37d095bc..bd60468f 100644
--- a/extensions/libxt_state.man
+++ b/extensions/libxt_state.man
@@ -1,24 +1,8 @@
-This module, when combined with connection tracking, allows access to
-the connection tracking state for this packet.
+The "state" module is an obsolete version of "conntrack".
+"state" allows access to the connection tracking state for this packet.
.TP
[\fB!\fP] \fB\-\-state\fP \fIstate\fP
-Where state is a comma separated list of the connection states to
-match. Possible states are
-.B INVALID
-meaning that the packet could not be identified for some reason which
-includes running out of memory and ICMP errors which don't correspond to any
-known connection,
-.B ESTABLISHED
-meaning that the packet is associated with a connection which has seen
-packets in both directions,
-.B NEW
-meaning that the packet has started a new connection, or otherwise
-associated with a connection which has not seen packets in both
-directions, and
-.B RELATED
-meaning that the packet is starting a new connection, but is
-associated with an existing connection, such as an FTP data transfer,
-or an ICMP error.
-.B UNTRACKED
-meaning that the packet is not tracked at all, which happens if you use
-the NOTRACK target in raw table.
+Where state is a comma separated list of the connection states to match. Only a
+subset of the states unterstood by "conntrack" are recognized: \fBINVALID\fP,
+\fBESTABLISHED\fP, \fBNEW\fP, \fBRELATED\fP or \fBUNTRACKED\fP. For their
+description, see the "conntrack" heading in this manpage.
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/linux/netfilter/ipset/ip_set.h b/include/linux/netfilter/ipset/ip_set.h
index 79cb0779..fff191d6 100644
--- a/include/linux/netfilter/ipset/ip_set.h
+++ b/include/linux/netfilter/ipset/ip_set.h
@@ -186,6 +186,7 @@ enum ip_set_dim {
* If changed, new revision of iptables match/target is required.
*/
IPSET_DIM_MAX = 6,
+ IPSET_BIT_RETURN_NOMATCH = 7,
};
/* Option flags for kernel operations */
@@ -194,6 +195,7 @@ enum ip_set_kopt {
IPSET_DIM_ONE_SRC = (1 << IPSET_DIM_ONE),
IPSET_DIM_TWO_SRC = (1 << IPSET_DIM_TWO),
IPSET_DIM_THREE_SRC = (1 << IPSET_DIM_THREE),
+ IPSET_RETURN_NOMATCH = (1 << IPSET_BIT_RETURN_NOMATCH),
};
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/.gitignore b/iptables/.gitignore
index 5a089376..4fc63aa4 100644
--- a/iptables/.gitignore
+++ b/iptables/.gitignore
@@ -5,6 +5,7 @@
/ip6tables-static
/iptables
/iptables.8
+/iptables-extensions.8
/iptables-save
/iptables-restore
/iptables-static
diff --git a/iptables/Makefile.am b/iptables/Makefile.am
index bdd4da11..61e78db9 100644
--- a/iptables/Makefile.am
+++ b/iptables/Makefile.am
@@ -27,7 +27,7 @@ xtables_multi_LDADD += ../libxtables/libxtables.la -lm
sbin_PROGRAMS = xtables-multi
man_MANS = iptables.8 iptables-restore.8 iptables-save.8 \
iptables-xml.1 ip6tables.8 ip6tables-restore.8 \
- ip6tables-save.8
+ ip6tables-save.8 iptables-extensions.8
CLEANFILES = iptables.8 ip6tables.8
vx_bin_links = iptables-xml
@@ -38,11 +38,17 @@ if ENABLE_IPV6
v6_sbin_links = ip6tables ip6tables-restore ip6tables-save
endif
-iptables.8: ${srcdir}/iptables.8.in ../extensions/matches4.man ../extensions/targets4.man
- ${AM_VERBOSE_GEN} sed -e 's/@PACKAGE_AND_VERSION@/${PACKAGE} ${PACKAGE_VERSION}/g' -e '/@MATCH@/ r ../extensions/matches4.man' -e '/@TARGET@/ r ../extensions/targets4.man' $< >$@;
+iptables.8: ${srcdir}/iptables.8.in
+ ${AM_VERBOSE_GEN} sed -e 's/@PACKAGE_AND_VERSION@/${PACKAGE} ${PACKAGE_VERSION}/g' $< >$@;
-ip6tables.8: ${srcdir}/ip6tables.8.in ../extensions/matches6.man ../extensions/targets6.man
- ${AM_VERBOSE_GEN} sed -e 's/@PACKAGE_AND_VERSION@/${PACKAGE} ${PACKAGE_VERSION}/g' -e '/@MATCH@/ r ../extensions/matches6.man' -e '/@TARGET@/ r ../extensions/targets6.man' $< >$@;
+ip6tables.8: ${srcdir}/ip6tables.8.in
+ ${AM_VERBOSE_GEN} sed -e 's/@PACKAGE_AND_VERSION@/${PACKAGE} ${PACKAGE_VERSION}/g' $< >$@;
+
+iptables-extensions.8: ${srcdir}/iptables-extensions.8.in ../extensions/matches.man ../extensions/targets.man
+ ${AM_VERBOSE_GEN} sed -e \
+ 's/@PACKAGE_AND_VERSION@/${PACKAGE} ${PACKAGE_VERSION}/g' \
+ -e '/@MATCH@/ r ../extensions/matches.man' \
+ -e '/@TARGET@/ r ../extensions/targets.man' $< >$@;
pkgconfig_DATA = xtables.pc
diff --git a/iptables/ip6tables.8.in b/iptables/ip6tables.8.in
index 65f38646..078bcacd 100644
--- a/iptables/ip6tables.8.in
+++ b/iptables/ip6tables.8.in
@@ -362,23 +362,8 @@ When adding or inserting rules into a chain, use \fIcommand\fP
to load any necessary modules (targets, match extensions, etc).
.SH MATCH EXTENSIONS
.PP
-ip6tables can use extended packet matching modules
-with the \fB\-m\fP or \fB\-\-match\fP
-options, followed by the matching module name; after these, various
-extra command line options become available, depending on the specific
-module. You can specify multiple extended match modules in one line,
-and you can use the \fB\-h\fP or \fB\-\-help\fP
-options after the module has been specified to receive help specific
-to that module.
-.PP
-If the \fB\-p\fP or \fB\-\-protocol\fP was specified and if and only if an
-unknown option is encountered, ip6tables will try load a match module of the
-same name as the protocol, to try making the option available.
-.\" @MATCH@
-.SH TARGET EXTENSIONS
-ip6tables can use extended target modules: the following are included
-in the standard distribution.
-.\" @TARGET@
+iptables can use extended packet matching and target modules.
+A list of these is available in the \fBiptables\-extensions\fP(8) manpage.
.SH DIAGNOSTICS
Various error messages are printed to standard error. The exit code
is 0 for correct functioning. Errors which appear to be caused by
@@ -405,6 +390,8 @@ There are several other changes in ip6tables.
\fBip6tables\-save\fP(8),
\fBip6tables\-restore\fP(8),
\fBiptables\fP(8),
+\fBiptables\-apply\fP(8),
+\fBiptables\-extensions\fP(8),
\fBiptables\-save\fP(8),
\fBiptables\-restore\fP(8),
\fBlibipq\fP(3).
diff --git a/iptables/ip6tables.c b/iptables/ip6tables.c
index 7a16b974..0e11a9e1 100644
--- a/iptables/ip6tables.c
+++ b/iptables/ip6tables.c
@@ -1286,8 +1286,16 @@ 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);
+ if (cs->target->real_name == NULL) {
+ strcpy(cs->target->t->u.user.name, cs->jumpto);
+ } else {
+ strcpy(cs->target->t->u.user.name, cs->target->real_name);
+ fprintf(stderr, "WARNING: The %s target is obsolete. "
+ "Use %s instead.\n",
+ cs->jumpto, cs->target->real_name);
+ }
cs->target->t->u.user.revision = cs->target->revision;
+
xs_init_target(cs->target);
if (cs->target->x6_options != NULL)
opts = xtables_options_xfrm(ip6tables_globals.orig_opts, opts,
@@ -1314,8 +1322,15 @@ 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);
+ if (m->real_name == NULL) {
+ strcpy(m->m->u.user.name, m->name);
+ } else {
+ strcpy(m->m->u.user.name, m->real_name);
+ fprintf(stderr, "WARNING: The %s match is obsolete. "
+ "Use %s instead.\n", m->name, m->real_name);
+ }
m->m->u.user.revision = m->revision;
+
xs_init_match(m);
if (m == m->next)
return;
diff --git a/iptables/iptables-apply.8 b/iptables/iptables-apply.8
index 8208fd0f..66eaf57a 100644
--- a/iptables/iptables-apply.8
+++ b/iptables/iptables-apply.8
@@ -18,7 +18,7 @@ connection, the user will not be able to answer affirmatively. In this
case, the script rolls back to the previous ruleset after the timeout
expired. The timeout can be set with \fB\-t\fP.
.PP
-When called as ip6tables\-apply, the script will use
+When called as \fBip6tables\-apply\fP, the script will use
ip6tables\-save/\-restore instead.
.SH OPTIONS
.TP
diff --git a/iptables/iptables-extensions.8.in b/iptables/iptables-extensions.8.in
new file mode 100644
index 00000000..e02c81fb
--- /dev/null
+++ b/iptables/iptables-extensions.8.in
@@ -0,0 +1,27 @@
+.TH iptables-extensions 8 "" "@PACKAGE_AND_VERSION@" "@PACKAGE_AND_VERSION@"
+.SH NAME
+iptables-extensions \(em list of extensions in the standard iptables distribution
+.SH SYNOPSIS
+\fBip6tables\fP [\fB\-m\fP \fIname\fP [\fImodule-options\fP...]]
+[\fB\-j\fP \fItarget-name\fP [\fItarget-options\fP...]
+.PP
+\fBiptables\fP [\fB\-m\fP \fIname\fP [\fImodule-options\fP...]]
+[\fB\-j\fP \fItarget-name\fP [\fItarget-options\fP...]
+.SH MATCH EXTENSIONS
+iptables can use extended packet matching modules
+with the \fB\-m\fP or \fB\-\-match\fP
+options, followed by the matching module name; after these, various
+extra command line options become available, depending on the specific
+module. You can specify multiple extended match modules in one line,
+and you can use the \fB\-h\fP or \fB\-\-help\fP
+options after the module has been specified to receive help specific
+to that module.
+.PP
+If the \fB\-p\fP or \fB\-\-protocol\fP was specified and if and only if an
+unknown option is encountered, iptables will try load a match module of the
+same name as the protocol, to try making the option available.
+.\" @MATCH@
+.SH TARGET EXTENSIONS
+iptables can use extended target modules: the following are included
+in the standard distribution.
+.\" @TARGET@
diff --git a/iptables/iptables.8.in b/iptables/iptables.8.in
index 59d6e040..d6b409d0 100644
--- a/iptables/iptables.8.in
+++ b/iptables/iptables.8.in
@@ -355,25 +355,10 @@ corresponding to that rule's position in the chain.
\fB\-\-modprobe=\fP\fIcommand\fP
When adding or inserting rules into a chain, use \fIcommand\fP
to load any necessary modules (targets, match extensions, etc).
-.SH MATCH EXTENSIONS
+.SH MATCH AND TARGET EXTENSIONS
.PP
-iptables can use extended packet matching modules
-with the \fB\-m\fP or \fB\-\-match\fP
-options, followed by the matching module name; after these, various
-extra command line options become available, depending on the specific
-module. You can specify multiple extended match modules in one line,
-and you can use the \fB\-h\fP or \fB\-\-help\fP
-options after the module has been specified to receive help specific
-to that module.
-.PP
-If the \fB\-p\fP or \fB\-\-protocol\fP was specified and if and only if an
-unknown option is encountered, iptables will try load a match module of the
-same name as the protocol, to try making the option available.
-.\" @MATCH@
-.SH TARGET EXTENSIONS
-iptables can use extended target modules: the following are included
-in the standard distribution.
-.\" @TARGET@
+iptables can use extended packet matching and target modules.
+A list of these is available in the \fBiptables\-extensions\fP(8) manpage.
.SH DIAGNOSTICS
Various error messages are printed to standard error. The exit code
is 0 for correct functioning. Errors which appear to be caused by
@@ -408,8 +393,10 @@ seen previously. So the following options are handled differently:
.fi
There are several other changes in iptables.
.SH SEE ALSO
+\fBiptables\-apply\fP(8),
\fBiptables\-save\fP(8),
\fBiptables\-restore\fP(8),
+\fBiptables\-extensions\fP(8),
\fBip6tables\fP(8),
\fBip6tables\-save\fP(8),
\fBip6tables\-restore\fP(8),
diff --git a/iptables/iptables.c b/iptables/iptables.c
index 9e3d696a..f765cf98 100644
--- a/iptables/iptables.c
+++ b/iptables/iptables.c
@@ -1295,8 +1295,17 @@ 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);
+ if (cs->target->real_name == NULL) {
+ strcpy(cs->target->t->u.user.name, cs->jumpto);
+ } else {
+ /* Alias support for userspace side */
+ strcpy(cs->target->t->u.user.name, cs->target->real_name);
+ fprintf(stderr, "WARNING: The %s target is obsolete. "
+ "Use %s instead.\n",
+ cs->jumpto, cs->target->real_name);
+ }
cs->target->t->u.user.revision = cs->target->revision;
+
xs_init_target(cs->target);
if (cs->target->x6_options != NULL)
@@ -1324,8 +1333,15 @@ 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);
+ if (m->real_name == NULL) {
+ strcpy(m->m->u.user.name, m->name);
+ } else {
+ strcpy(m->m->u.user.name, m->real_name);
+ fprintf(stderr, "WARNING: The %s match is obsolete. "
+ "Use %s instead.\n", m->name, m->real_name);
+ }
m->m->u.user.revision = m->revision;
+
xs_init_match(m);
if (m == m->next)
return;
diff --git a/libxtables/xtables.c b/libxtables/xtables.c
index d8185796..4c912860 100644
--- a/libxtables/xtables.c
+++ b/libxtables/xtables.c
@@ -862,14 +862,77 @@ 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->real_name != NULL,
+ a->revision, a->family,
+ b->real_name != NULL,
+ 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->real_name != NULL,
+ a->revision, a->family,
+ b->real_name != NULL,
+ b->revision, b->family);
+}
+
static void xtables_fully_register_pending_match(struct xtables_match *me)
{
struct xtables_match **i, *old;
+ const char *rn;
+ 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 +940,14 @@ 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)
+ rn = (old->real_name != NULL) ? old->real_name : old->name;
+ if (compare > 0 &&
+ compatible_match_revision(rn, 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)
+ rn = (me->real_name != NULL) ? me->real_name : me->name;
+ if (!compatible_match_revision(rn, me->revision))
return;
/* Delete old one. */
@@ -962,13 +1023,15 @@ void xtables_register_target(struct xtables_target *me)
static void xtables_fully_register_pending_target(struct xtables_target *me)
{
struct xtables_target *old;
+ const char *rn;
+ 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,14 @@ 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)
+ rn = (old->real_name != NULL) ? old->real_name : old->name;
+ if (compare > 0 &&
+ compatible_target_revision(rn, 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)
+ rn = (me->real_name != NULL) ? me->real_name : me->name;
+ if (!compatible_target_revision(rn, me->revision))
return;
/* Delete old one. */