Merge git://git.netfilter.org/iptables into v1.4.11_upstream

Using theirs, as they have taken some of my prior changes\
with some improvements.


Conflicts:
	include/xtables.h.in
	iptables/xtables.c
	iptables/xtoptions.c

Change-Id: I8e1e537fbb868eeebb448c8f1d9e33b283448aac
diff --git a/.gitignore b/.gitignore
index 894f289..552ec7b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -34,18 +34,3 @@
 /ltmain.sh
 /missing
 /stamp-h1
-/libiptc.pc
-/xtables.pc
-
-/ip6tables
-/ip6tables.8
-/ip6tables-save
-/ip6tables-restore
-/ip6tables-static
-/iptables
-/iptables.8
-/iptables-save
-/iptables-restore
-/iptables-static
-/iptables-xml
-/xtables-multi
diff --git a/COPYING b/COPYING
index a43ea21..d159169 100644
--- a/COPYING
+++ b/COPYING
@@ -1,12 +1,12 @@
-		    GNU GENERAL PUBLIC LICENSE
-		       Version 2, June 1991
+                    GNU GENERAL PUBLIC LICENSE
+                       Version 2, June 1991
 
- Copyright (C) 1989, 1991 Free Software Foundation, Inc.
-                          675 Mass Ave, Cambridge, MA 02139, USA
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  Everyone is permitted to copy and distribute verbatim copies
  of this license document, but changing it is not allowed.
 
-			    Preamble
+                            Preamble
 
   The licenses for most software are designed to take away your
 freedom to share and change it.  By contrast, the GNU General Public
@@ -15,7 +15,7 @@
 General Public License applies to most of the Free Software
 Foundation's software and to any other program whose authors commit to
 using it.  (Some other Free Software Foundation software is covered by
-the GNU Library General Public License instead.)  You can apply it to
+the GNU Lesser General Public License instead.)  You can apply it to
 your programs, too.
 
   When we speak of free software, we are referring to freedom, not
@@ -55,8 +55,8 @@
 
   The precise terms and conditions for copying, distribution and
 modification follow.
-
-		    GNU GENERAL PUBLIC LICENSE
+
+                    GNU GENERAL PUBLIC LICENSE
    TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
 
   0. This License applies to any program or other work which contains
@@ -110,7 +110,7 @@
     License.  (Exception: if the Program itself is interactive but
     does not normally print such an announcement, your work based on
     the Program is not required to print an announcement.)
-
+
 These requirements apply to the modified work as a whole.  If
 identifiable sections of that work are not derived from the Program,
 and can be reasonably considered independent and separate works in
@@ -168,7 +168,7 @@
 access to copy the source code from the same place counts as
 distribution of the source code, even though third parties are not
 compelled to copy the source along with the object code.
-
+
   4. You may not copy, modify, sublicense, or distribute the Program
 except as expressly provided under this License.  Any attempt
 otherwise to copy, modify, sublicense or distribute the Program is
@@ -225,7 +225,7 @@
 
 This section is intended to make thoroughly clear what is believed to
 be a consequence of the rest of this License.
-
+
   8. If the distribution and/or use of the Program is restricted in
 certain countries either by patents or by copyrighted interfaces, the
 original copyright holder who places the Program under this License
@@ -255,7 +255,7 @@
 of preserving the free status of all derivatives of our free software and
 of promoting the sharing and reuse of software generally.
 
-			    NO WARRANTY
+                            NO WARRANTY
 
   11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
 FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
@@ -277,9 +277,9 @@
 PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
 POSSIBILITY OF SUCH DAMAGES.
 
-		     END OF TERMS AND CONDITIONS
-
-	Appendix: How to Apply These Terms to Your New Programs
+                     END OF TERMS AND CONDITIONS
+
+            How to Apply These Terms to Your New Programs
 
   If you develop a new program, and you want it to be of the greatest
 possible use to the public, the best way to achieve this is to make it
@@ -291,7 +291,7 @@
 the "copyright" line and a pointer to where the full notice is found.
 
     <one line to give the program's name and a brief idea of what it does.>
-    Copyright (C) 19yy  <name of author>
+    Copyright (C) <year>  <name of author>
 
     This program is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
@@ -303,16 +303,16 @@
     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     GNU General Public License for more details.
 
-    You should have received a copy of the GNU General Public License
-    along with this program; if not, write to the Free Software
-    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+    You should have received a copy of the GNU General Public License along
+    with this program; if not, write to the Free Software Foundation, Inc.,
+    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 
 Also add information on how to contact you by electronic and paper mail.
 
 If the program is interactive, make it output a short notice like this
 when it starts in an interactive mode:
 
-    Gnomovision version 69, Copyright (C) 19yy name of author
+    Gnomovision version 69, Copyright (C) year name of author
     Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
     This is free software, and you are welcome to redistribute it
     under certain conditions; type `show c' for details.
@@ -335,5 +335,5 @@
 This General Public License does not permit incorporating your program into
 proprietary programs.  If your program is a subroutine library, you may
 consider it more useful to permit linking proprietary applications with the
-library.  If this is what you want to do, use the GNU Library General
+library.  If this is what you want to do, use the GNU Lesser General
 Public License instead of this License.
diff --git a/Makefile.am b/Makefile.am
index 13e144e..34b3501 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -3,8 +3,7 @@
 ACLOCAL_AMFLAGS  = -I m4
 AUTOMAKE_OPTIONS = foreign subdir-objects
 
-AM_CFLAGS        = ${regular_CFLAGS} -I${top_builddir}/include -I${top_srcdir}/include ${kinclude_CFLAGS}
-SUBDIRS          = extensions
+SUBDIRS          = extensions libiptc iptables
 if ENABLE_DEVEL
 SUBDIRS         += include
 endif
@@ -14,72 +13,6 @@
 if HAVE_LIBNFNETLINK
 SUBDIRS         += utils
 endif
-lib_LTLIBRARIES =
-
-# libiptc
-lib_LTLIBRARIES            += libiptc/libip4tc.la libiptc/libip6tc.la libiptc/libiptc.la
-libiptc_libiptc_la_SOURCES  =
-libiptc_libiptc_la_LIBADD   = libiptc/libip4tc.la libiptc/libip6tc.la
-libiptc_libiptc_la_LDFLAGS  = -version-info 0:0:0 ${libiptc_LDFLAGS2}
-libiptc_libip4tc_la_SOURCES = libiptc/libip4tc.c
-libiptc_libip4tc_la_LDFLAGS = -version-info 0:0:0
-libiptc_libip6tc_la_SOURCES = libiptc/libip6tc.c
-libiptc_libip6tc_la_LDFLAGS = -version-info 0:0:0 ${libiptc_LDFLAGS2}
-
-lib_LTLIBRARIES      += libxtables.la
-libxtables_la_SOURCES = xtables.c xtoptions.c
-libxtables_la_LDFLAGS = -version-info ${libxtables_vcurrent}:0:${libxtables_vage}
-if ENABLE_SHARED
-libxtables_la_CFLAGS  = ${AM_CFLAGS}
-libxtables_la_LIBADD  = -ldl
-else
-libxtables_la_CFLAGS  = ${AM_CFLAGS} -DNO_SHARED_LIBS=1
-libxtables_la_LIBADD  =
-endif
-
-xtables_multi_SOURCES  = xtables-multi.c
-xtables_multi_CFLAGS   = ${AM_CFLAGS} -DIPTABLES_MULTI
-xtables_multi_LDFLAGS  = -rdynamic
-xtables_multi_LDADD    = extensions/libext.a
-if ENABLE_STATIC
-xtables_multi_CFLAGS  += -DALL_INCLUSIVE
-endif
-if ENABLE_IPV4
-xtables_multi_SOURCES += iptables-save.c iptables-restore.c iptables-xml.c \
-                         iptables-standalone.c iptables.c
-xtables_multi_CFLAGS  += -DENABLE_IPV4
-xtables_multi_LDADD   += libiptc/libip4tc.la extensions/libext4.a
-endif
-if ENABLE_IPV6
-xtables_multi_SOURCES += ip6tables-save.c ip6tables-restore.c \
-                          ip6tables-standalone.c ip6tables.c
-xtables_multi_CFLAGS  += -DENABLE_IPV6
-xtables_multi_LDADD   += libiptc/libip6tc.la extensions/libext6.a
-endif
-xtables_multi_SOURCES += xshared.c
-xtables_multi_LDADD   += libxtables.la -lm
-
-sbin_PROGRAMS    = xtables-multi
-man_MANS         = iptables.8 iptables-restore.8 iptables-save.8 \
-                   iptables-xml.8 ip6tables.8 ip6tables-restore.8 \
-                   ip6tables-save.8
-CLEANFILES       = iptables.8 ip6tables.8
-
-if ENABLE_IPV4
-v4_bin_links   = iptables-xml
-v4_sbin_links  = iptables iptables-restore iptables-save
-endif
-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' $< >$@;
-
-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' $< >$@;
-
-pkgconfig_DATA = libiptc.pc xtables.pc
 
 .PHONY: tarball
 tarball:
@@ -91,11 +24,3 @@
 
 config.status: extensions/GNUmakefile.in \
 	include/xtables.h.in include/iptables/internal.h.in
-
-# Using if..fi avoids an ugly "error (ignored)" message :)
-install-exec-hook:
-	-if test -z "${DESTDIR}"; then /sbin/ldconfig; fi;
-	${INSTALL} -dm0755 "${DESTDIR}${bindir}";
-	for i in ${v4_bin_links}; do ${LN_S} -f "${sbindir}/iptables-multi" "${DESTDIR}${bindir}/$$i"; done;
-	for i in ${v4_sbin_links}; do ${LN_S} -f iptables-multi "${DESTDIR}${sbindir}/$$i"; done;
-	for i in ${v6_sbin_links}; do ${LN_S} -f ip6tables-multi "${DESTDIR}${sbindir}/$$i"; done;
diff --git a/configure.ac b/configure.ac
index 38b7b79..e902ab9 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,5 +1,5 @@
 
-AC_INIT([iptables], [1.4.10])
+AC_INIT([iptables], [1.4.11.1])
 
 # See libtool.info "Libtool's versioning system"
 libxtables_vcurrent=6
@@ -41,7 +41,7 @@
 	AS_HELP_STRING([--disable-largefile], [Do not build largefile support]),
 	[enable_largefile="$enableval"],
 	[enable_largefile="yes";
-	largefile_cflags='-D_LARGEFILE_SOURCE=1 -D_LARGE_FILES -D_FILE_OFFSET_BITS=64'])
+	largefile_cppflags='-D_LARGEFILE_SOURCE=1 -D_LARGE_FILES -D_FILE_OFFSET_BITS=64'])
 AC_ARG_ENABLE([devel],
 	AS_HELP_STRING([--enable-devel],
 	[Install Xtables development headers]),
@@ -83,22 +83,23 @@
 	[nfnetlink=1], [nfnetlink=0])
 AM_CONDITIONAL([HAVE_LIBNFNETLINK], [test "$nfnetlink" = 1])
 
-regular_CFLAGS="${largefile_cflags} \
-	-D_REENTRANT -Wall -Waggregate-return -Wmissing-declarations \
+regular_CFLAGS="-Wall -Waggregate-return -Wmissing-declarations \
 	-Wmissing-prototypes -Wredundant-decls -Wshadow -Wstrict-prototypes \
-	-Winline -pipe \
+	-Winline -pipe";
+regular_CPPFLAGS="${largefile_cppflags} -D_REENTRANT \
 	-DXTABLES_LIBDIR=\\\"\${xtlibdir}\\\" -DXTABLES_INTERNAL";
-kinclude_CFLAGS="";
+kinclude_CPPFLAGS="";
 if [[ -n "$kbuilddir" ]]; then
-	kinclude_CFLAGS="$kinclude_CFLAGS -I $kbuilddir/include";
+	kinclude_CPPFLAGS="$kinclude_CPPFLAGS -I$kbuilddir/include";
 fi;
 if [[ -n "$ksourcedir" ]]; then
-	kinclude_CFLAGS="$kinclude_CFLAGS -I $ksourcedir/include";
+	kinclude_CPPFLAGS="$kinclude_CPPFLAGS -I$ksourcedir/include";
 fi;
 pkgdatadir='${datadir}/xtables';
 
 AC_SUBST([regular_CFLAGS])
-AC_SUBST([kinclude_CFLAGS])
+AC_SUBST([regular_CPPFLAGS])
+AC_SUBST([kinclude_CPPFLAGS])
 AC_SUBST([kbuilddir])
 AC_SUBST([ksourcedir])
 AC_SUBST([xtlibdir])
@@ -110,6 +111,7 @@
 AC_SUBST([libxtables_vmajor])
 
 AC_CONFIG_FILES([Makefile extensions/GNUmakefile include/Makefile
-	libipq/Makefile utils/Makefile
-	include/xtables.h include/iptables/internal.h libiptc.pc xtables.pc])
+	iptables/Makefile iptables/xtables.pc
+	libipq/Makefile libiptc/Makefile libiptc/libiptc.pc utils/Makefile
+	include/xtables.h include/iptables/internal.h])
 AC_OUTPUT
diff --git a/extensions/GNUmakefile.in b/extensions/GNUmakefile.in
index a511a39..fbaf2ec 100644
--- a/extensions/GNUmakefile.in
+++ b/extensions/GNUmakefile.in
@@ -14,11 +14,14 @@
 CC             := @CC@
 CCLD           := ${CC}
 CFLAGS         := @CFLAGS@
+CPPFLAGS       := @CPPFLAGS@
 LDFLAGS        := @LDFLAGS@
 regular_CFLAGS := @regular_CFLAGS@
-kinclude_CFLAGS := @kinclude_CFLAGS@
+regular_CPPFLAGS := @regular_CPPFLAGS@
+kinclude_CPPFLAGS := @kinclude_CPPFLAGS@
 
-AM_CFLAGS      := ${regular_CFLAGS} -I${top_builddir}/include -I${top_srcdir}/include ${kinclude_CFLAGS}
+AM_CFLAGS      := ${regular_CFLAGS}
+AM_CPPFLAGS     = ${regular_CPPFLAGS} -I${top_builddir}/include -I${top_srcdir}/include ${kinclude_CPPFLAGS}
 AM_DEPFLAGS     = -Wp,-MMD,$(@D)/.$(@F).d,-MT,$@
 
 ifeq (${V},)
@@ -78,7 +81,7 @@
 	rm -f .*.d .*.dd;
 
 init%.o: init%.c
-	${AM_VERBOSE_CC} ${CC} ${AM_DEPFLAGS} ${AM_CFLAGS} -D_INIT=$*_init ${CFLAGS} -o $@ -c $<;
+	${AM_VERBOSE_CC} ${CC} ${AM_CPPFLAGS} ${AM_DEPFLAGS} ${AM_CFLAGS} -D_INIT=$*_init ${CFLAGS} -o $@ -c $<;
 
 -include .*.d
 
@@ -90,7 +93,7 @@
 	${AM_VERBOSE_CCLD} ${CCLD} ${AM_LDFLAGS} -shared ${LDFLAGS} -o $@ $<;
 
 lib%.oo: ${srcdir}/lib%.c
-	${AM_VERBOSE_CC} ${CC} ${AM_DEPFLAGS} ${AM_CFLAGS} -D_INIT=lib$*_init -DPIC -fPIC ${CFLAGS} -o $@ -c $<;
+	${AM_VERBOSE_CC} ${CC} ${AM_CPPFLAGS} ${AM_DEPFLAGS} ${AM_CFLAGS} -D_INIT=lib$*_init -DPIC -fPIC ${CFLAGS} -o $@ -c $<;
 
 
 #
@@ -101,7 +104,7 @@
 #	handling code in the Makefiles.
 #
 lib%.o: ${srcdir}/lib%.c
-	${AM_VERBOSE_CC} ${CC} ${AM_DEPFLAGS} ${AM_CFLAGS} -DNO_SHARED_LIBS=1 -D_INIT=lib$*_init ${CFLAGS} -o $@ -c $<;
+	${AM_VERBOSE_CC} ${CC} ${AM_CPPFLAGS} ${AM_DEPFLAGS} ${AM_CFLAGS} -DNO_SHARED_LIBS=1 -D_INIT=lib$*_init ${CFLAGS} -o $@ -c $<;
 
 libext.a: initext.o ${libext_objs}
 	${AM_VERBOSE_AR} ${AR} crs $@ $^;
diff --git a/extensions/libip6t_ah.c b/extensions/libip6t_ah.c
index d30ddfa..26f8140 100644
--- a/extensions/libip6t_ah.c
+++ b/extensions/libip6t_ah.c
@@ -28,13 +28,6 @@
 };
 #undef s
 
-static void ah_init(struct xt_entry_match *m)
-{
-	struct ip6t_ah *ahinfo = (struct ip6t_ah *)m->data;
-
-	ahinfo->spis[1] = 0xFFFFFFFF;
-}
-
 static void ah_parse(struct xt_option_call *cb)
 {
 	struct ip6t_ah *ahinfo = cb->data;
@@ -42,6 +35,8 @@
 	xtables_option_parse(cb);
 	switch (cb->entry->id) {
 	case O_AHSPI:
+		if (cb->nvals == 1)
+			ahinfo->spis[1] = ahinfo->spis[0];
 		if (cb->invert)
 			ahinfo->invflags |= IP6T_AH_INV_SPI;
 		break;
@@ -132,7 +127,6 @@
 	.size          = XT_ALIGN(sizeof(struct ip6t_ah)),
 	.userspacesize = XT_ALIGN(sizeof(struct ip6t_ah)),
 	.help          = ah_help,
-	.init          = ah_init,
 	.print         = ah_print,
 	.save          = ah_save,
 	.x6_parse      = ah_parse,
diff --git a/extensions/libip6t_frag.c b/extensions/libip6t_frag.c
index 12794e4..4779386 100644
--- a/extensions/libip6t_frag.c
+++ b/extensions/libip6t_frag.c
@@ -41,19 +41,16 @@
 };
 #undef s
 
-static void frag_init(struct xt_entry_match *m)
-{
-	struct ip6t_frag *fraginfo = (struct ip6t_frag *)m->data;
-
-	fraginfo->ids[1] = 0xFFFFFFFF;
-}
-
 static void frag_parse(struct xt_option_call *cb)
 {
 	struct ip6t_frag *fraginfo = cb->data;
 
 	xtables_option_parse(cb);
 	switch (cb->entry->id) {
+	case O_FRAGID:
+		if (cb->nvals == 1)
+			fraginfo->ids[1] = fraginfo->ids[0];
+		break;
 	case O_FRAGRES:
 		fraginfo->flags |= IP6T_FRAG_RES;
 		break;
@@ -160,7 +157,6 @@
 	.size          = XT_ALIGN(sizeof(struct ip6t_frag)),
 	.userspacesize = XT_ALIGN(sizeof(struct ip6t_frag)),
 	.help          = frag_help,
-	.init          = frag_init,
 	.print         = frag_print,
 	.save          = frag_save,
 	.x6_parse      = frag_parse,
diff --git a/extensions/libip6t_rt.c b/extensions/libip6t_rt.c
index 11bfda9..d470488 100644
--- a/extensions/libip6t_rt.c
+++ b/extensions/libip6t_rt.c
@@ -31,15 +31,15 @@
 
 #define s struct ip6t_rt
 static const struct xt_option_entry rt_opts[] = {
-	{.name = "rt-type", .id = O_RT_TYPE, .type = XTTYPE_UINT32RC,
-	 .flags = XTOPT_INVERT},
+	{.name = "rt-type", .id = O_RT_TYPE, .type = XTTYPE_UINT32,
+	 .flags = XTOPT_INVERT | XTOPT_PUT, XTOPT_POINTER(s, rt_type)},
 	{.name = "rt-segsleft", .id = O_RT_SEGSLEFT, .type = XTTYPE_UINT32RC,
 	 .flags = XTOPT_INVERT | XTOPT_PUT, XTOPT_POINTER(s, segsleft)},
 	{.name = "rt-len", .id = O_RT_LEN, .type = XTTYPE_UINT32,
 	 .flags = XTOPT_INVERT | XTOPT_PUT, XTOPT_POINTER(s, hdrlen)},
 	{.name = "rt-0-res", .id = O_RT0RES, .type = XTTYPE_NONE},
 	{.name = "rt-0-addrs", .id = O_RT0ADDRS, .type = XTTYPE_STRING},
-	{.name = "rt-0-not-strict", .id = O_RT0NSTRICT, .type = XTTYPE_STRING},
+	{.name = "rt-0-not-strict", .id = O_RT0NSTRICT, .type = XTTYPE_NONE},
 	XTOPT_TABLEEND,
 };
 #undef s
@@ -99,13 +99,6 @@
 	return i;
 }
 
-static void rt_init(struct xt_entry_match *m)
-{
-	struct ip6t_rt *rtinfo = (struct ip6t_rt *)m->data;
-
-	rtinfo->segsleft[1] = 0xFFFFFFFF;
-}
-
 static void rt_parse(struct xt_option_call *cb)
 {
 	struct ip6t_rt *rtinfo = cb->data;
@@ -118,6 +111,8 @@
 		rtinfo->flags |= IP6T_RT_TYP;
 		break;
 	case O_RT_SEGSLEFT:
+		if (cb->nvals == 1)
+			rtinfo->segsleft[1] = rtinfo->segsleft[0];
 		if (cb->invert)
 			rtinfo->invflags |= IP6T_RT_INV_SGS;
 		rtinfo->flags |= IP6T_RT_SGS;
@@ -250,7 +245,6 @@
 	.size		= XT_ALIGN(sizeof(struct ip6t_rt)),
 	.userspacesize	= XT_ALIGN(sizeof(struct ip6t_rt)),
 	.help		= rt_help,
-	.init		= rt_init,
 	.x6_parse	= rt_parse,
 	.print		= rt_print,
 	.save		= rt_save,
diff --git a/extensions/libipt_DNAT.c b/extensions/libipt_DNAT.c
index 6a46f10..3b55c69 100644
--- a/extensions/libipt_DNAT.c
+++ b/extensions/libipt_DNAT.c
@@ -12,8 +12,10 @@
 	O_TO_DEST = 0,
 	O_RANDOM,
 	O_PERSISTENT,
-	F_TO_DEST = 1 << O_TO_DEST,
-	F_RANDOM  = 1 << O_RANDOM,
+	O_X_TO_DEST, /* hidden flag */
+	F_TO_DEST   = 1 << O_TO_DEST,
+	F_RANDOM    = 1 << O_RANDOM,
+	F_X_TO_DEST = 1 << O_X_TO_DEST,
 };
 
 /* Dest NAT data consists of a multi-range, indicating where to map
@@ -164,17 +166,18 @@
 	xtables_option_parse(cb);
 	switch (cb->entry->id) {
 	case O_TO_DEST:
-		if (cb->xflags & F_TO_DEST) {
+		if (cb->xflags & F_X_TO_DEST) {
 			if (!kernel_version)
 				get_kernel_version();
 			if (kernel_version > LINUX_VERSION(2, 6, 10))
 				xtables_error(PARAMETER_PROBLEM,
-					   "Multiple --to-destination not supported");
+					   "DNAT: Multiple --to-destination not supported");
 		}
 		*cb->target = parse_to(cb->arg, portok, info);
 		/* WTF do we need this for?? */
 		if (cb->xflags & F_RANDOM)
 			info->mr.range[0].flags |= IP_NAT_RANGE_PROTO_RANDOM;
+		cb->xflags |= F_X_TO_DEST;
 		break;
 	case O_RANDOM:
 		if (cb->xflags & F_TO_DEST)
diff --git a/extensions/libipt_MASQUERADE.man b/extensions/libipt_MASQUERADE.man
index 8f42993..2dae964 100644
--- a/extensions/libipt_MASQUERADE.man
+++ b/extensions/libipt_MASQUERADE.man
@@ -10,7 +10,7 @@
 .I forgotten
 when the interface goes down.  This is the correct behavior when the
 next dialup is unlikely to have the same interface address (and hence
-any established connections are lost anyway).  It takes one option:
+any established connections are lost anyway).
 .TP
 \fB\-\-to\-ports\fP \fIport\fP[\fB\-\fP\fIport\fP]
 This specifies a range of source ports to use, overriding the default
diff --git a/extensions/libipt_REDIRECT.c b/extensions/libipt_REDIRECT.c
index 426a746..e67360a 100644
--- a/extensions/libipt_REDIRECT.c
+++ b/extensions/libipt_REDIRECT.c
@@ -23,8 +23,7 @@
 }
 
 static const struct xt_option_entry REDIRECT_opts[] = {
-	{.name = "to-ports", .id = O_TO_PORTS, .type = XTTYPE_STRING,
-	 .flags = XTOPT_MAND},
+	{.name = "to-ports", .id = O_TO_PORTS, .type = XTTYPE_STRING},
 	{.name = "random", .id = O_RANDOM, .type = XTTYPE_NONE},
 	XTOPT_TABLEEND,
 };
diff --git a/extensions/libipt_SNAT.c b/extensions/libipt_SNAT.c
index 9156a7b..8023306 100644
--- a/extensions/libipt_SNAT.c
+++ b/extensions/libipt_SNAT.c
@@ -12,8 +12,10 @@
 	O_TO_SRC = 0,
 	O_RANDOM,
 	O_PERSISTENT,
-	F_TO_SRC = 1 << O_TO_SRC,
-	F_RANDOM = 1 << O_RANDOM,
+	O_X_TO_SRC,
+	F_TO_SRC   = 1 << O_TO_SRC,
+	F_RANDOM   = 1 << O_RANDOM,
+	F_X_TO_SRC = 1 << O_X_TO_SRC,
 };
 
 /* Source NAT data consists of a multi-range, indicating where to map
@@ -164,17 +166,18 @@
 	xtables_option_parse(cb);
 	switch (cb->entry->id) {
 	case O_TO_SRC:
-		if (cb->xflags & F_TO_SRC) {
+		if (cb->xflags & F_X_TO_SRC) {
 			if (!kernel_version)
 				get_kernel_version();
 			if (kernel_version > LINUX_VERSION(2, 6, 10))
 				xtables_error(PARAMETER_PROBLEM,
-					   "Multiple --to-source not supported");
+					   "SNAT: Multiple --to-source not supported");
 		}
 		*cb->target = parse_to(cb->arg, portok, info);
 		/* WTF do we need this for?? */
 		if (cb->xflags & F_RANDOM)
 			info->mr.range[0].flags |= IP_NAT_RANGE_PROTO_RANDOM;
+		cb->xflags |= F_X_TO_SRC;
 		break;
 	case O_RANDOM:
 		if (cb->xflags & F_TO_SRC)
diff --git a/extensions/libipt_SNAT.man b/extensions/libipt_SNAT.man
index 80e2cb9..626b592 100644
--- a/extensions/libipt_SNAT.man
+++ b/extensions/libipt_SNAT.man
@@ -17,7 +17,7 @@
 If no port range is specified, then source ports below 512 will be
 mapped to other ports below 512: those between 512 and 1023 inclusive
 will be mapped to ports below 1024, and other ports will be mapped to
-1024 or above. Where possible, no port alteration will
+1024 or above. Where possible, no port alteration will occur.
 
 In Kernels up to 2.6.10, you can add several \-\-to\-source options. For those
 kernels, if you specify more than one source address, either via an address
diff --git a/extensions/libipt_ah.c b/extensions/libipt_ah.c
index 53adfd8..8cf167c 100644
--- a/extensions/libipt_ah.c
+++ b/extensions/libipt_ah.c
@@ -21,18 +21,13 @@
 	XTOPT_TABLEEND,
 };
 
-static void ah_init(struct xt_entry_match *m)
-{
-	struct ipt_ah *ahinfo = (struct ipt_ah *)m->data;
-
-	ahinfo->spis[1] = 0xFFFFFFFF;
-}
-
 static void ah_parse(struct xt_option_call *cb)
 {
 	struct ipt_ah *ahinfo = cb->data;
 
 	xtables_option_parse(cb);
+	if (cb->nvals == 1)
+		ahinfo->spis[1] = ahinfo->spis[0];
 	if (cb->invert)
 		ahinfo->invflags |= IPT_AH_INV_SPI;
 }
@@ -97,7 +92,6 @@
 	.size		= XT_ALIGN(sizeof(struct ipt_ah)),
 	.userspacesize 	= XT_ALIGN(sizeof(struct ipt_ah)),
 	.help 		= ah_help,
-	.init 		= ah_init,
 	.print 		= ah_print,
 	.save 		= ah_save,
 	.x6_parse	= ah_parse,
diff --git a/extensions/libxt_NFQUEUE.c b/extensions/libxt_NFQUEUE.c
index a86c88a..e47b586 100644
--- a/extensions/libxt_NFQUEUE.c
+++ b/extensions/libxt_NFQUEUE.c
@@ -13,6 +13,8 @@
 	O_QUEUE_NUM = 0,
 	O_QUEUE_BALANCE,
 	O_QUEUE_BYPASS,
+	F_QUEUE_NUM     = 1 << O_QUEUE_NUM,
+	F_QUEUE_BALANCE = 1 << O_QUEUE_BALANCE,
 };
 
 static void NFQUEUE_help(void)
@@ -41,9 +43,10 @@
 #define s struct xt_NFQ_info
 static const struct xt_option_entry NFQUEUE_opts[] = {
 	{.name = "queue-num", .id = O_QUEUE_NUM, .type = XTTYPE_UINT16,
-	 .flags = XTOPT_PUT, XTOPT_POINTER(s, queuenum)},
+	 .flags = XTOPT_PUT, XTOPT_POINTER(s, queuenum),
+	 .excl = F_QUEUE_BALANCE},
 	{.name = "queue-balance", .id = O_QUEUE_BALANCE,
-	 .type = XTTYPE_UINT16RC},
+	 .type = XTTYPE_UINT16RC, .excl = F_QUEUE_NUM},
 	{.name = "queue-bypass", .id = O_QUEUE_BYPASS, .type = XTTYPE_NONE},
 	XTOPT_TABLEEND,
 };
@@ -81,14 +84,11 @@
 {
 	struct xt_NFQ_info_v2 *info = cb->data;
 
-	xtables_option_parse(cb);
+	NFQUEUE_parse_v1(cb);
 	switch (cb->entry->id) {
 	case O_QUEUE_BYPASS:
 		info->bypass = 1;
 		break;
-	default:
-		NFQUEUE_parse_v1(cb);
-		break;
 	}
 }
 
diff --git a/extensions/libxt_TCPMSS.man b/extensions/libxt_TCPMSS.man
index ac8fb4e..8da8e76 100644
--- a/extensions/libxt_TCPMSS.man
+++ b/extensions/libxt_TCPMSS.man
@@ -11,19 +11,13 @@
 problem are that everything works fine from your Linux
 firewall/router, but machines behind it can never exchange large
 packets:
-.PD 0
-.RS 0.1i
-.TP 0.3i
-1)
+.IP 1. 4
 Web browsers connect, then hang with no data received.
-.TP
-2)
+.IP 2. 4
 Small mail works fine, but large emails hang.
-.TP
-3)
+.IP 3. 4
 ssh works fine, but scp hangs after initial handshaking.
-.RE
-.PD
+.PP
 Workaround: activate this option and add a rule to your firewall
 configuration like:
 .IP
diff --git a/extensions/libxt_TPROXY.c b/extensions/libxt_TPROXY.c
index 61646c9..d13ec85 100644
--- a/extensions/libxt_TPROXY.c
+++ b/extensions/libxt_TPROXY.c
@@ -20,8 +20,8 @@
 
 #define s struct xt_tproxy_target_info
 static const struct xt_option_entry tproxy_tg0_opts[] = {
-	{.name = "on-port", .id = P_PORT, .type = XTTYPE_PORT_NE,
-	 .flags = XTOPT_MAND | XTOPT_PUT, XTOPT_POINTER(s, lport)},
+	{.name = "on-port", .id = P_PORT, .type = XTTYPE_PORT,
+	 .flags = XTOPT_MAND | XTOPT_NBO | XTOPT_PUT, XTOPT_POINTER(s, lport)},
 	{.name = "on-ip", .id = P_ADDR, .type = XTTYPE_HOST},
 	{.name = "tproxy-mark", .id = P_MARK, .type = XTTYPE_MARKMASK32},
 	XTOPT_TABLEEND,
@@ -29,8 +29,8 @@
 #undef s
 #define s struct xt_tproxy_target_info_v1
 static const struct xt_option_entry tproxy_tg1_opts[] = {
-	{.name = "on-port", .id = P_PORT, .type = XTTYPE_PORT_NE,
-	 .flags = XTOPT_MAND | XTOPT_PUT, XTOPT_POINTER(s, lport)},
+	{.name = "on-port", .id = P_PORT, .type = XTTYPE_PORT,
+	 .flags = XTOPT_MAND | XTOPT_NBO | XTOPT_PUT, XTOPT_POINTER(s, lport)},
 	{.name = "on-ip", .id = P_ADDR, .type = XTTYPE_HOST,
 	 .flags = XTOPT_PUT, XTOPT_POINTER(s, laddr)},
 	{.name = "tproxy-mark", .id = P_MARK, .type = XTTYPE_MARKMASK32},
diff --git a/extensions/libxt_conntrack.c b/extensions/libxt_conntrack.c
index 2fb3644..e1d8575 100644
--- a/extensions/libxt_conntrack.c
+++ b/extensions/libxt_conntrack.c
@@ -291,69 +291,6 @@
 		xtables_error(PARAMETER_PROBLEM, "Bad ctstatus \"%s\"", arg);
 }
 
-static unsigned long
-parse_expire(const char *s)
-{
-	unsigned int len;
-
-	if (!xtables_strtoui(s, NULL, &len, 0, UINT32_MAX))
-		xtables_error(PARAMETER_PROBLEM, "expire value invalid: \"%s\"\n", s);
-	else
-		return len;
-}
-
-/* If a single value is provided, min and max are both set to the value */
-static void
-parse_expires(const char *s, struct xt_conntrack_info *sinfo)
-{
-	char *buffer;
-	char *cp;
-
-	buffer = strdup(s);
-	if ((cp = strchr(buffer, ':')) == NULL)
-		sinfo->expires_min = sinfo->expires_max =
-			parse_expire(buffer);
-	else {
-		*cp = '\0';
-		cp++;
-
-		sinfo->expires_min = buffer[0] ? parse_expire(buffer) : 0;
-		sinfo->expires_max = cp[0]
-			? parse_expire(cp)
-			: (unsigned long)-1;
-	}
-	free(buffer);
-
-	if (sinfo->expires_min > sinfo->expires_max)
-		xtables_error(PARAMETER_PROBLEM,
-		           "expire min. range value `%lu' greater than max. "
-		           "range value `%lu'", sinfo->expires_min, sinfo->expires_max);
-}
-
-static void
-conntrack_ps_expires(struct xt_conntrack_mtinfo3 *info, const char *s)
-{
-	unsigned int min, max;
-	char *end;
-
-	if (!xtables_strtoui(s, &end, &min, 0, UINT32_MAX))
-		xtables_param_act(XTF_BAD_VALUE, "conntrack", "--expires", s);
-	max = min;
-	if (*end == ':')
-		if (!xtables_strtoui(end + 1, &end, &max, 0, UINT32_MAX))
-			xtables_param_act(XTF_BAD_VALUE, "conntrack", "--expires", s);
-	if (*end != '\0')
-		xtables_param_act(XTF_BAD_VALUE, "conntrack", "--expires", s);
-
-	if (min > max)
-		xtables_error(PARAMETER_PROBLEM,
-		           "expire min. range value \"%u\" greater than max. "
-		           "range value \"%u\"", min, max);
-
-	info->expires_min = min;
-	info->expires_max = max;
-}
-
 static void conntrack_parse(struct xt_option_call *cb)
 {
 	struct xt_conntrack_info *sinfo = cb->data;
@@ -408,7 +345,10 @@
 		sinfo->flags |= XT_CONNTRACK_STATUS;
 		break;
 	case O_CTEXPIRE:
-		parse_expires(cb->arg, sinfo);
+		sinfo->expires_min = cb->val.u32_range[0];
+		sinfo->expires_max = cb->val.u32_range[0];
+		if (cb->nvals >= 2)
+			sinfo->expires_max = cb->val.u32_range[1];
 		if (cb->invert)
 			sinfo->invflags |= XT_CONNTRACK_EXPIRES;
 		sinfo->flags |= XT_CONNTRACK_EXPIRES;
@@ -473,39 +413,38 @@
 			info->invert_flags |= XT_CONNTRACK_STATUS;
 		break;
 	case O_CTEXPIRE:
-		conntrack_ps_expires(info, cb->arg);
+		info->expires_min = cb->val.u32_range[0];
+		info->expires_max = cb->val.u32_range[0];
+		if (cb->nvals >= 2)
+			info->expires_max = cb->val.u32_range[1];
 		info->match_flags |= XT_CONNTRACK_EXPIRES;
 		if (cb->invert)
 			info->invert_flags |= XT_CONNTRACK_EXPIRES;
 		break;
 	case O_CTORIGSRCPORT:
 		info->origsrc_port = cb->val.port_range[0];
-		info->origsrc_port = (cb->nvals == 2) ? cb->val.port_range[1] :
-		                     cb->val.port_range[0];
+		info->origsrc_port_high = cb->val.port_range[cb->nvals >= 2];
 		info->match_flags |= XT_CONNTRACK_ORIGSRC_PORT;
 		if (cb->invert)
 			info->invert_flags |= XT_CONNTRACK_ORIGSRC_PORT;
 		break;
 	case O_CTORIGDSTPORT:
 		info->origdst_port = cb->val.port_range[0];
-		info->origdst_port = (cb->nvals == 2) ? cb->val.port_range[1] :
-		                     cb->val.port_range[0];
+		info->origdst_port_high = cb->val.port_range[cb->nvals >= 2];
 		info->match_flags |= XT_CONNTRACK_ORIGDST_PORT;
 		if (cb->invert)
 			info->invert_flags |= XT_CONNTRACK_ORIGDST_PORT;
 		break;
 	case O_CTREPLSRCPORT:
 		info->replsrc_port = cb->val.port_range[0];
-		info->replsrc_port = (cb->nvals == 2) ? cb->val.port_range[1] :
-		                     cb->val.port_range[0];
+		info->replsrc_port_high = cb->val.port_range[cb->nvals >= 2];
 		info->match_flags |= XT_CONNTRACK_REPLSRC_PORT;
 		if (cb->invert)
 			info->invert_flags |= XT_CONNTRACK_REPLSRC_PORT;
 		break;
 	case O_CTREPLDSTPORT:
 		info->repldst_port = cb->val.port_range[0];
-		info->repldst_port = (cb->nvals == 2) ? cb->val.port_range[1] :
-		                     cb->val.port_range[0];
+		info->repldst_port_high = cb->val.port_range[cb->nvals >= 2];
 		info->match_flags |= XT_CONNTRACK_REPLDST_PORT;
 		if (cb->invert)
 			info->invert_flags |= XT_CONNTRACK_REPLDST_PORT;
@@ -538,6 +477,10 @@
 
 	memset(&up, 0, sizeof(up));
 	cinfo_transform(&up, info);
+	up.origsrc_port_high = up.origsrc_port;
+	up.origdst_port_high = up.origdst_port;
+	up.replsrc_port_high = up.replsrc_port;
+	up.repldst_port_high = up.repldst_port;
 	cb->data = &up;
 	conntrack_mt_parse(cb, 3);
 	if (up.origsrc_port != up.origsrc_port_high ||
@@ -545,7 +488,7 @@
 	    up.replsrc_port != up.replsrc_port_high ||
 	    up.repldst_port != up.repldst_port_high)
 		xtables_error(PARAMETER_PROBLEM,
-			"connlimit rev 1 does not support port ranges");
+			"conntrack rev 1 does not support port ranges");
 	cinfo_transform(info, &up);
 	cb->data = info;
 }
@@ -560,6 +503,10 @@
 
 	memset(&up, 0, sizeof(up));
 	memcpy(&up, info, sizeof(*info));
+	up.origsrc_port_high = up.origsrc_port;
+	up.origdst_port_high = up.origdst_port;
+	up.replsrc_port_high = up.replsrc_port;
+	up.repldst_port_high = up.repldst_port;
 	cb->data = &up;
 	conntrack_mt_parse(cb, 3);
 	if (up.origsrc_port != up.origsrc_port_high ||
@@ -567,7 +514,7 @@
 	    up.replsrc_port != up.replsrc_port_high ||
 	    up.repldst_port != up.repldst_port_high)
 		xtables_error(PARAMETER_PROBLEM,
-			"connlimit rev 2 does not support port ranges");
+			"conntrack rev 2 does not support port ranges");
 	memcpy(info, &up, sizeof(*info));
 	cb->data = info;
 #undef cinfo2_transform
diff --git a/extensions/libxt_devgroup.c b/extensions/libxt_devgroup.c
index a925dd0..4487c83 100644
--- a/extensions/libxt_devgroup.c
+++ b/extensions/libxt_devgroup.c
@@ -70,6 +70,7 @@
 			info->src_group = id;
 			info->src_mask  = 0xffffffff;
 		}
+		info->flags |= XT_DEVGROUP_MATCH_SRC;
 		if (cb->invert)
 			info->flags |= XT_DEVGROUP_INVERT_SRC;
 		break;
@@ -93,6 +94,7 @@
 			info->dst_group = id;
 			info->dst_mask  = 0xffffffff;
 		}
+		info->flags |= XT_DEVGROUP_MATCH_DST;
 		if (cb->invert)
 			info->flags |= XT_DEVGROUP_INVERT_DST;
 		break;
diff --git a/extensions/libxt_esp.c b/extensions/libxt_esp.c
index e9d7990..294338b 100644
--- a/extensions/libxt_esp.c
+++ b/extensions/libxt_esp.c
@@ -21,18 +21,13 @@
 	XTOPT_TABLEEND,
 };
 
-static void esp_init(struct xt_entry_match *m)
-{
-	struct xt_esp *espinfo = (struct xt_esp *)m->data;
-
-	espinfo->spis[1] = 0xFFFFFFFF;
-}
-
 static void esp_parse(struct xt_option_call *cb)
 {
 	struct xt_esp *espinfo = cb->data;
 
 	xtables_option_parse(cb);
+	if (cb->nvals == 1)
+		espinfo->spis[1] = espinfo->spis[0];
 	if (cb->invert)
 		espinfo->invflags |= XT_ESP_INV_SPI;
 }
@@ -91,7 +86,6 @@
 	.size		= XT_ALIGN(sizeof(struct xt_esp)),
 	.userspacesize	= XT_ALIGN(sizeof(struct xt_esp)),
 	.help		= esp_help,
-	.init		= esp_init,
 	.print		= esp_print,
 	.save		= esp_save,
 	.x6_parse	= esp_parse,
diff --git a/extensions/libxt_hashlimit.man b/extensions/libxt_hashlimit.man
index e91d0c6..f90577e 100644
--- a/extensions/libxt_hashlimit.man
+++ b/extensions/libxt_hashlimit.man
@@ -2,16 +2,7 @@
 \fBlimit\fP match) for a group of connections using a \fBsingle\fP iptables
 rule. Grouping can be done per-hostgroup (source and/or destination address)
 and/or per-port. It gives you the ability to express "\fIN\fP packets per time
-quantum per group":
-.TP
-matching on source host
-"1000 packets per second for every host in 192.168.0.0/16"
-.TP
-matching on source port
-"100 packets per second for every service of 192.168.1.1"
-.TP
-matching on subnet
-"10000 packets per minute for every /28 subnet in 10.0.0.0/8"
+quantum per group" (see below for some examples).
 .PP
 A hash limit option (\fB\-\-hashlimit\-upto\fP, \fB\-\-hashlimit\-above\fP) and
 \fB\-\-hashlimit\-name\fP are required.
@@ -57,3 +48,18 @@
 .TP
 \fB\-\-hashlimit\-htable\-gcinterval\fP \fImsec\fP
 How many milliseconds between garbage collection intervals.
+.PP
+Examples:
+.TP
+matching on source host
+"1000 packets per second for every host in 192.168.0.0/16" =>
+\-s 192.168.0.0/16 \-\-hashlimit\-mode srcip \-\-hashlimit\-upto 1000/sec
+.TP
+matching on source port
+"100 packets per second for every service of 192.168.1.1" =>
+\-s 192.168.1.1 \-\-hashlimit\-mode srcport \-\-hashlimit\-upto 100/sec
+.TP
+matching on subnet
+"10000 packets per minute for every /28 subnet (groups of 8 addresses)
+in 10.0.0.0/8" =>
+\-s 10.0.0.8 \-\-hashlimit\-mask 28 \-\-hashlimit\-upto 10000/min
diff --git a/extensions/libxt_ipvs.c b/extensions/libxt_ipvs.c
index 88d235f..4672766 100644
--- a/extensions/libxt_ipvs.c
+++ b/extensions/libxt_ipvs.c
@@ -32,12 +32,14 @@
 	{.name = "vaddr", .id = O_VADDR, .type = XTTYPE_HOSTMASK,
 	 .flags = XTOPT_INVERT},
 	{.name = "vport", .id = O_VPORT, .type = XTTYPE_PORT,
-	 .flags = XTOPT_INVERT | XTOPT_PUT, XTOPT_POINTER(s, vport)},
+	 .flags = XTOPT_NBO | XTOPT_INVERT | XTOPT_PUT,
+	 XTOPT_POINTER(s, vport)},
 	{.name = "vdir", .id = O_VDIR, .type = XTTYPE_STRING},
 	{.name = "vmethod", .id = O_VMETHOD, .type = XTTYPE_STRING,
 	 .flags = XTOPT_INVERT},
 	{.name = "vportctl", .id = O_VPORTCTL, .type = XTTYPE_PORT,
-	 .flags = XTOPT_INVERT | XTOPT_PUT, XTOPT_POINTER(s, vportctl)},
+	 .flags = XTOPT_NBO | XTOPT_INVERT | XTOPT_PUT,
+	 XTOPT_POINTER(s, vportctl)},
 	XTOPT_TABLEEND,
 };
 #undef s
diff --git a/extensions/libxt_length.c b/extensions/libxt_length.c
index 4f3a331..6ea7646 100644
--- a/extensions/libxt_length.c
+++ b/extensions/libxt_length.c
@@ -26,7 +26,9 @@
 
 	xtables_option_parse(cb);
 	info->min = cb->val.u16_range[0];
-	info->max = (cb->nvals == 2) ? cb->val.u16_range[1] : UINT16_MAX;
+	info->max = cb->val.u16_range[0];
+	if (cb->nvals >= 2)
+		info->max = cb->val.u16_range[1];
 	if (cb->invert)
 		info->invert = 1;
 }
diff --git a/extensions/libxt_owner.c b/extensions/libxt_owner.c
index b60f907..d2fdfa9 100644
--- a/extensions/libxt_owner.c
+++ b/extensions/libxt_owner.c
@@ -125,8 +125,10 @@
 #undef s
 
 static const struct xt_option_entry owner_mt_opts[] = {
-	{.name = "uid-owner", .id = O_USER, .type = XTTYPE_STRING},
-	{.name = "gid-owner", .id = O_GROUP, .type = XTTYPE_STRING},
+	{.name = "uid-owner", .id = O_USER, .type = XTTYPE_STRING,
+	 .flags = XTOPT_INVERT},
+	{.name = "gid-owner", .id = O_GROUP, .type = XTTYPE_STRING,
+	 .flags = XTOPT_INVERT},
 	{.name = "socket-exists", .id = O_SOCK_EXISTS, .type = XTTYPE_NONE},
 	XTOPT_TABLEEND,
 };
diff --git a/extensions/libxt_policy.c b/extensions/libxt_policy.c
index a514246..97722d6 100644
--- a/extensions/libxt_policy.c
+++ b/extensions/libxt_policy.c
@@ -16,7 +16,8 @@
 	O_MODE,
 	O_TUNNELSRC,
 	O_TUNNELDST,
-	O_NEXT
+	O_NEXT,
+	F_STRICT = 1 << O_STRICT,
 };
 
 static void policy_help(void)
@@ -28,6 +29,7 @@
 "  --pol none|ipsec		match policy\n"
 "  --strict 			match entire policy instead of single element\n"
 "				at any position\n"
+"These options may be used repeatedly, to describe policy elements:\n"
 "[!] --reqid reqid		match reqid\n"
 "[!] --spi spi			match SPI\n"
 "[!] --proto proto		match protocol (ah/esp/ipcomp)\n"
@@ -42,13 +44,20 @@
 	 .flags = XTOPT_INVERT},
 	{.name = "pol", .id = O_POLICY, .type = XTTYPE_STRING},
 	{.name = "strict", .id = O_STRICT, .type = XTTYPE_NONE},
-	{.name = "reqid", .id = O_REQID, .type = XTTYPE_UINT32},
-	{.name = "spi", .id = O_SPI, .type = XTTYPE_UINT32},
-	{.name = "tunnel-src", .id = O_TUNNELSRC, .type = XTTYPE_HOSTMASK},
-	{.name = "tunnel-dst", .id = O_TUNNELDST, .type = XTTYPE_HOSTMASK},
-	{.name = "proto", .id = O_PROTO, .type = XTTYPE_STRING},
-	{.name = "mode", .id = O_MODE, .type = XTTYPE_STRING},
-	{.name = "next", .id = O_NEXT, .type = XTTYPE_NONE},
+	{.name = "reqid", .id = O_REQID, .type = XTTYPE_UINT32,
+	 .flags = XTOPT_MULTI | XTOPT_INVERT},
+	{.name = "spi", .id = O_SPI, .type = XTTYPE_UINT32,
+	 .flags = XTOPT_MULTI | XTOPT_INVERT},
+	{.name = "tunnel-src", .id = O_TUNNELSRC, .type = XTTYPE_HOSTMASK,
+	 .flags = XTOPT_MULTI | XTOPT_INVERT},
+	{.name = "tunnel-dst", .id = O_TUNNELDST, .type = XTTYPE_HOSTMASK,
+	 .flags = XTOPT_MULTI | XTOPT_INVERT},
+	{.name = "proto", .id = O_PROTO, .type = XTTYPE_PROTOCOL,
+	 .flags = XTOPT_MULTI | XTOPT_INVERT},
+	{.name = "mode", .id = O_MODE, .type = XTTYPE_STRING,
+	 .flags = XTOPT_MULTI | XTOPT_INVERT},
+	{.name = "next", .id = O_NEXT, .type = XTTYPE_NONE,
+	 .flags = XTOPT_MULTI, .also = F_STRICT},
 	XTOPT_TABLEEND,
 };
 
@@ -134,7 +143,7 @@
 		if (e->match.proto)
 			xtables_error(PARAMETER_PROBLEM,
 			           "policy match: double --proto option");
-		e->proto = xtables_parse_protocol(cb->arg);
+		e->proto = cb->val.protocol;
 		if (e->proto != IPPROTO_AH && e->proto != IPPROTO_ESP &&
 		    e->proto != IPPROTO_COMP)
 			xtables_error(PARAMETER_PROBLEM,
@@ -183,9 +192,14 @@
 	} else
 		info->len++;	/* increase len by 1, no --next after last element */
 
+	/*
+	 * This is already represented with O_NEXT requiring F_STRICT in the
+	 * options table, but will keep this code as a comment for reference.
+	 *
 	if (!(info->flags & XT_POLICY_MATCH_STRICT) && info->len > 1)
 		xtables_error(PARAMETER_PROBLEM,
 		           "policy match: multiple elements but no --strict");
+	 */
 
 	for (i = 0; i < info->len; i++) {
 		e = &info->pol[i];
@@ -194,7 +208,10 @@
 		    !(e->match.reqid || e->match.spi || e->match.saddr ||
 		      e->match.daddr || e->match.proto || e->match.mode))
 			xtables_error(PARAMETER_PROBLEM,
-			           "policy match: empty policy element");
+				"policy match: empty policy element %u. "
+				"--strict is in effect, but at least one of "
+				"reqid, spi, tunnel-src, tunnel-dst, proto or "
+				"mode is required.", i);
 
 		if ((e->match.saddr || e->match.daddr)
 		    && ((e->mode == XT_POLICY_MODE_TUNNEL && e->invert.mode) ||
diff --git a/extensions/libxt_policy.man b/extensions/libxt_policy.man
index 3500025..1b834fa 100644
--- a/extensions/libxt_policy.man
+++ b/extensions/libxt_policy.man
@@ -13,11 +13,16 @@
 chains.
 .TP
 \fB\-\-pol\fP {\fBnone\fP|\fBipsec\fP}
-Matches if the packet is subject to IPsec processing.
+Matches if the packet is subject to IPsec processing. \fB\-\-pol none\fP
+cannot be combined with \fB\-\-strict\fP.
 .TP
 \fB\-\-strict\fP
 Selects whether to match the exact policy or match if any rule of
 the policy matches the given policy.
+.PP
+For each policy element that is to be described, one can use one or more of
+the following options. When \fB\-\-strict\fP is in effect, at least one must be
+used per element.
 .TP
 [\fB!\fP] \fB\-\-reqid\fP \fIid\fP
 Matches the reqid of the policy rule. The reqid can be specified with
diff --git a/extensions/libxt_quota.c b/extensions/libxt_quota.c
index dc9b3b0..26fba0b 100644
--- a/extensions/libxt_quota.c
+++ b/extensions/libxt_quota.c
@@ -13,7 +13,8 @@
 
 static const struct xt_option_entry quota_opts[] = {
 	{.name = "quota", .id = O_QUOTA, .type = XTTYPE_UINT64,
-	 .flags = XTOPT_MAND | XTOPT_INVERT},
+	 .flags = XTOPT_MAND | XTOPT_INVERT | XTOPT_PUT,
+	 XTOPT_POINTER(struct xt_quota_info, quota)},
 	XTOPT_TABLEEND,
 };
 
diff --git a/extensions/libxt_rateest.c b/extensions/libxt_rateest.c
index e70edc6..509b3e3 100644
--- a/extensions/libxt_rateest.c
+++ b/extensions/libxt_rateest.c
@@ -65,11 +65,11 @@
 	{ "bit",	1. },
 	{ "Kibit",	1024. },
 	{ "kbit",	1000. },
-	{ "mibit",	1024.*1024. },
+	{ "Mibit",	1024.*1024. },
 	{ "mbit",	1000000. },
-	{ "gibit",	1024.*1024.*1024. },
+	{ "Gibit",	1024.*1024.*1024. },
 	{ "gbit",	1000000000. },
-	{ "tibit",	1024.*1024.*1024.*1024. },
+	{ "Tibit",	1024.*1024.*1024.*1024. },
 	{ "tbit",	1000000000000. },
 	{ "Bps",	8. },
 	{ "KiBps",	8.*1024. },
diff --git a/extensions/libxt_rateest.man b/extensions/libxt_rateest.man
index 75303c5..42a82f3 100644
--- a/extensions/libxt_rateest.man
+++ b/extensions/libxt_rateest.man
@@ -1,25 +1,38 @@
 The rate estimator can match on estimated rates as collected by the RATEEST
 target. It supports matching on absolute bps/pps values, comparing two rate
 estimators and matching on the difference between two rate estimators.
-.TP
-\fB\-\-rateest1\fP \fIname\fP
-Name of the first rate estimator.
-.TP
-\fB\-\-rateest2\fP \fIname\fP
-Name of the second rate estimator (if difference is to be calculated).
+.PP
+For a better understanding of the available options, these are all possible
+combinations:
+.\" * Absolute:
+.IP \(bu 4
+\fBrateest\fP \fIoperator\fP \fBrateest-bps\fP
+.IP \(bu 4
+\fBrateest\fP \fIoperator\fP \fBrateest-pps\fP
+.\" * Absolute + Delta:
+.IP \(bu 4
+(\fBrateest\fP minus \fBrateest-bps1\fP) \fIoperator\fP \fBrateest-bps2\fP
+.IP \(bu 4
+(\fBrateest\fP minus \fBrateest-pps1\fP) \fIoperator\fP \fBrateest-pps2\fP
+.\" * Relative:
+.IP \(bu 4
+\fBrateest1\fP \fIoperator\fP \fBrateest2\fP \fBrateest-bps\fP(without rate!)
+.IP \(bu 4
+\fBrateest1\fP \fIoperator\fP \fBrateest2\fP \fBrateest-pps\fP(without rate!)
+.\" * Relative + Delta:
+.IP \(bu 4
+(\fBrateest1\fP minus \fBrateest-bps1\fP) \fIoperator\fP
+(\fBrateest2\fP minus \fBrateest-bps2\fP)
+.IP \(bu 4
+(\fBrateest1\fP minus \fBrateest-pps1\fP) \fIoperator\fP
+(\fBrateest2\fP minus \fBrateest-pps2\fP)
 .TP
 \fB\-\-rateest\-delta\fP
-Compare difference(s) to given rate(s)
-.TP
-\fB\-\-rateest\-bps1\fP [\fIvalue\fP]
-.TP
-\fB\-\-rateest\-bps2\fP [\fIvalue\fP]
-Compare bytes per second.
-.TP
-\fB\-\-rateest\-pps1\fP [\fIvalue\fP]
-.TP
-\fB\-\-rateest\-pps2\fP [\fIvalue\fP]
-Compare packets per second.
+For each estimator (either absolute or relative mode), calculate the difference
+between the estimator-determined flow rate and the static value chosen with the
+BPS/PPS options. If the flow rate is higher than the specified BPS/PPS, 0 will
+be used instead of a negative value. In other words, "max(0, rateest#_rate -
+rateest#_bps)" is used.
 .TP
 [\fB!\fP] \fB\-\-rateest\-lt\fP
 Match if rate is less than given rate/estimator.
@@ -30,6 +43,34 @@
 [\fB!\fP] \fB\-\-rateest\-eq\fP
 Match if rate is equal to given rate/estimator.
 .PP
+In the so-called "absolute mode", only one rate estimator is used and compared
+against a static value, while in "relative mode", two rate estimators are
+compared against another.
+.TP
+\fB\-\-rateest\fP \fIname\fP
+Name of the one rate estimator for absolute mode.
+.TP
+\fB\-\-rateest1\fP \fIname\fP
+.TP
+\fB\-\-rateest2\fP \fIname\fP
+The names of the two rate estimators for relative mode.
+.TP
+\fB\-\-rateest\-bps\fP [\fIvalue\fP]
+.TP
+\fB\-\-rateest\-pps\fP [\fIvalue\fP]
+.TP
+\fB\-\-rateest\-bps1\fP [\fIvalue\fP]
+.TP
+\fB\-\-rateest\-bps2\fP [\fIvalue\fP]
+.TP
+\fB\-\-rateest\-pps1\fP [\fIvalue\fP]
+.TP
+\fB\-\-rateest\-pps2\fP [\fIvalue\fP]
+Compare the estimator(s) by bytes or packets per second, and compare against
+the chosen value. See the above bullet list for which option is to be used in
+which case. A unit suffix may be used - available ones are: bit, [kmgt]bit,
+[KMGT]ibit, Bps, [KMGT]Bps, [KMGT]iBps.
+.PP
 Example: This is what can be used to route outgoing data connections from an
 FTP server over two lines based on the available bandwidth at the time the data
 connection was started:
diff --git a/extensions/libxt_time.c b/extensions/libxt_time.c
index b538476..44c05b8 100644
--- a/extensions/libxt_time.c
+++ b/extensions/libxt_time.c
@@ -26,6 +26,10 @@
 	O_WEEKDAYS,
 	O_LOCAL_TZ,
 	O_UTC,
+	O_KERNEL_TZ,
+	F_LOCAL_TZ  = 1 << O_LOCAL_TZ,
+	F_UTC       = 1 << O_UTC,
+	F_KERNEL_TZ = 1 << O_KERNEL_TZ,
 };
 
 static const char *const week_days[] = {
@@ -41,8 +45,12 @@
 	 .flags = XTOPT_INVERT},
 	{.name = "monthdays", .id = O_MONTHDAYS, .type = XTTYPE_STRING,
 	 .flags = XTOPT_INVERT},
-	{.name = "localtz", .id = O_LOCAL_TZ, .type = XTTYPE_NONE},
-	{.name = "utc", .id = O_UTC, .type = XTTYPE_NONE},
+	{.name = "localtz", .id = O_LOCAL_TZ, .type = XTTYPE_NONE,
+	 .excl = F_UTC},
+	{.name = "utc", .id = O_UTC, .type = XTTYPE_NONE,
+	 .excl = F_LOCAL_TZ | F_KERNEL_TZ},
+	{.name = "kerneltz", .id = O_KERNEL_TZ, .type = XTTYPE_NONE,
+	 .excl = F_UTC},
 	XTOPT_TABLEEND,
 };
 
@@ -59,7 +67,7 @@
 "[!] --weekdays value     List of weekdays on which to match, sep. by comma\n"
 "                         (Possible days: Mon,Tue,Wed,Thu,Fri,Sat,Sun or 1 to 7\n"
 "                         Defaults to all weekdays.)\n"
-"    --localtz/--utc      Time is interpreted as UTC/local time\n");
+"    --kerneltz           Work with the kernel timezone instead of UTC\n");
 }
 
 static void time_init(struct xt_entry_match *m)
@@ -75,9 +83,6 @@
 	/* ...and have no date-begin or date-end boundary */
 	info->date_start = 0;
 	info->date_stop  = INT_MAX;
-
-	/* local time is default */
-	info->flags |= XT_TIME_LOCAL_TZ;
 }
 
 static time_t time_parse_date(const char *s, bool end)
@@ -136,6 +141,12 @@
 	tm.tm_min  = minute;
 	tm.tm_sec  = second;
 	tm.tm_isdst = 0;
+	/*
+	 * Offsetting, if any, is done by xt_time.ko,
+	 * so we have to disable it here in userspace.
+	 */
+	setenv("TZ", "UTC", true);
+	tzset();
 	ret = mktime(&tm);
 	if (ret >= 0)
 		return ret;
@@ -263,6 +274,12 @@
 		info->daytime_stop = time_parse_minutes(cb->arg);
 		break;
 	case O_LOCAL_TZ:
+		fprintf(stderr, "WARNING: --localtz is being replaced by "
+		        "--kerneltz, since \"local\" is ambiguous. Note the "
+		        "kernel timezone has caveats - "
+		        "see manpage for details.\n");
+		/* fallthrough */
+	case O_KERNEL_TZ:
 		info->flags |= XT_TIME_LOCAL_TZ;
 		break;
 	case O_MONTHDAYS:
@@ -275,9 +292,6 @@
 		if (cb->invert)
 			info->weekdays_match ^= XT_TIME_ALL_WEEKDAYS;
 		break;
-	case O_UTC:
-		info->flags &= ~XT_TIME_LOCAL_TZ;
-		break;
 	}
 }
 
@@ -289,7 +303,7 @@
 	if (date == 0 || date == LONG_MAX)
 		return;
 
-	t = localtime(&date);
+	t = gmtime(&date);
 	if (command != NULL)
 		/*
 		 * Need a contiguous string (no whitespaces), hence using
@@ -413,8 +427,8 @@
 	}
 	time_print_date(info->date_start, "--datestart");
 	time_print_date(info->date_stop, "--datestop");
-	if (!(info->flags & XT_TIME_LOCAL_TZ))
-		printf(" --utc");
+	if (info->flags & XT_TIME_LOCAL_TZ)
+		printf(" --kerneltz");
 }
 
 static struct xtables_match time_match = {
diff --git a/extensions/libxt_time.man b/extensions/libxt_time.man
index 2bceaf6..1d677b9 100644
--- a/extensions/libxt_time.man
+++ b/extensions/libxt_time.man
@@ -1,10 +1,10 @@
 This matches if the packet arrival time/date is within a given range. All
-options are optional, but are ANDed when specified.
+options are optional, but are ANDed when specified. All times are interpreted
+as UTC by default.
 .TP
 \fB\-\-datestart\fP \fIYYYY\fP[\fB\-\fP\fIMM\fP[\fB\-\fP\fIDD\fP[\fBT\fP\fIhh\fP[\fB:\fP\fImm\fP[\fB:\fP\fIss\fP]]]]]
 .TP
 \fB\-\-datestop\fP \fIYYYY\fP[\fB\-\fP\fIMM\fP[\fB\-\fP\fIDD\fP[\fBT\fP\fIhh\fP[\fB:\fP\fImm\fP[\fB:\fP\fIss\fP]]]]]
-.IP
 Only match during the given time, which must be in ISO 8601 "T" notation.
 The possible time range is 1970-01-01T00:00:00 to 2038-01-19T04:17:07.
 .IP
@@ -14,34 +14,51 @@
 \fB\-\-timestart\fP \fIhh\fP\fB:\fP\fImm\fP[\fB:\fP\fIss\fP]
 .TP
 \fB\-\-timestop\fP \fIhh\fP\fB:\fP\fImm\fP[\fB:\fP\fIss\fP]
-.IP
 Only match during the given daytime. The possible time range is 00:00:00 to
 23:59:59. Leading zeroes are allowed (e.g. "06:03") and correctly interpreted
 as base-10.
 .TP
 [\fB!\fP] \fB\-\-monthdays\fP \fIday\fP[\fB,\fP\fIday\fP...]
-.IP
 Only match on the given days of the month. Possible values are \fB1\fP
 to \fB31\fP. Note that specifying \fB31\fP will of course not match
 on months which do not have a 31st day; the same goes for 28- or 29-day
 February.
 .TP
 [\fB!\fP] \fB\-\-weekdays\fP \fIday\fP[\fB,\fP\fIday\fP...]
-.IP
 Only match on the given weekdays. Possible values are \fBMon\fP, \fBTue\fP,
 \fBWed\fP, \fBThu\fP, \fBFri\fP, \fBSat\fP, \fBSun\fP, or values from \fB1\fP
 to \fB7\fP, respectively. You may also use two-character variants (\fBMo\fP,
 \fBTu\fP, etc.).
 .TP
-\fB\-\-utc\fP
-.IP
-Interpret the times given for \fB\-\-datestart\fP, \fB\-\-datestop\fP,
-\fB\-\-timestart\fP and \fB\-\-timestop\fP to be UTC.
-.TP
-\fB\-\-localtz\fP
-.IP
-Interpret the times given for \fB\-\-datestart\fP, \fB\-\-datestop\fP,
-\fB\-\-timestart\fP and \fB\-\-timestop\fP to be local kernel time. (Default)
+\fB\-\-kerneltz\fP
+Use the kernel timezone instead of UTC to determine whether a packet meets the
+time regulations.
+.PP
+About kernel timezones: Linux keeps the system time in UTC, and always does so.
+On boot, system time is initialized from a referential time source. Where this
+time source has no timezone information, such as the x86 CMOS RTC, UTC will be
+assumed. If the time source is however not in UTC, userspace should provide the
+correct system time and timezone to the kernel once it has the information.
+.PP
+Local time is a feature on top of the (timezone independent) system time. Each
+process has its own idea of local time, specified via the TZ environment
+variable. The kernel also has its own timezone offset variable. The TZ
+userspace environment variable specifies how the UTC-based system time is
+displayed, e.g. when you run date(1), or what you see on your desktop clock.
+The TZ string may resolve to different offsets at different dates, which is
+what enables the automatic time-jumping in userspace. when DST changes. The
+kernel's timezone offset variable is used when it has to convert between
+non-UTC sources, such as FAT filesystems, to UTC (since the latter is what the
+rest of the system uses).
+.PP
+The caveat with the kernel timezone is that Linux distributions may ignore to
+set the kernel timezone, and instead only set the system time. Even if a
+particular distribution does set the timezone at boot, it is usually does not
+keep the kernel timezone offset - which is what changes on DST - up to date.
+ntpd will not touch the kernel timezone, so running it will not resolve the
+issue. As such, one may encounter a timezone that is always +0000, or one that
+is wrong half of the time of the year. As such, \fBusing \-\-kerneltz is highly
+discouraged.\fP
 .PP
 EXAMPLES. To match on weekends, use:
 .IP
diff --git a/extensions/libxt_u32.c b/extensions/libxt_u32.c
index 9198edc..774d5ea 100644
--- a/extensions/libxt_u32.c
+++ b/extensions/libxt_u32.c
@@ -23,7 +23,8 @@
 };
 
 static const struct xt_option_entry u32_opts[] = {
-	{.name = "u32", .id = O_U32, .type = XTTYPE_STRING},
+	{.name = "u32", .id = O_U32, .type = XTTYPE_STRING,
+	 .flags = XTOPT_MAND},
 	XTOPT_TABLEEND,
 };
 
diff --git a/include/libiptc/libip6tc.h b/include/libiptc/libip6tc.h
index 9796574..4f2d1f8 100644
--- a/include/libiptc/libip6tc.h
+++ b/include/libiptc/libip6tc.h
@@ -11,11 +11,6 @@
 #endif
 #include <linux/netfilter_ipv6/ip6_tables.h>
 
-#ifndef IP6T_MIN_ALIGN
-#define IP6T_MIN_ALIGN (__alignof__(struct ip6t_entry))
-#endif
-#define IP6T_ALIGN(s) (((s) + (IP6T_MIN_ALIGN-1)) & ~(IP6T_MIN_ALIGN-1))
-
 struct ip6tc_handle;
 
 typedef char ip6t_chainlabel[32];
diff --git a/include/libiptc/libiptc.h b/include/libiptc/libiptc.h
index 4355ac9..3497d6a 100644
--- a/include/libiptc/libiptc.h
+++ b/include/libiptc/libiptc.h
@@ -15,15 +15,6 @@
 extern "C" {
 #endif
 
-#ifndef IPT_MIN_ALIGN
-/* ipt_entry has pointers and u_int64_t's in it, so if you align to
-   it, you'll also align to any crazy matches and targets someone
-   might write */
-#define IPT_MIN_ALIGN (__alignof__(struct ipt_entry))
-#endif
-
-#define IPT_ALIGN(s) (((s) + ((IPT_MIN_ALIGN)-1)) & ~((IPT_MIN_ALIGN)-1))
-
 struct iptc_handle;
 
 typedef char ipt_chainlabel[32];
diff --git a/include/xtables.h.in b/include/xtables.h.in
index 5e9dec7..2565dd2 100644
--- a/include/xtables.h.in
+++ b/include/xtables.h.in
@@ -64,10 +64,9 @@
  * %XTTYPE_HOSTMASK:	one host or address, with an optional prefix length
  * 			(ptr: union nf_inet_addr; only host portion is stored)
  * %XTTYPE_PROTOCOL:	protocol number/name from /etc/protocols (ptr: uint8_t)
- * %XTTYPE_PORT:	16-bit port name or number
- * %XTTYPE_PORT_NE:	16-bit port name or number, stored as network-endian
- * %XTTYPE_PORTRC:	colon-separated port range (names acceptable)
- * %XTTYPE_PORTRC_NE:	same as %XTTYPE_PORTRC, stored in network-endian
+ * %XTTYPE_PORT:	16-bit port name or number (supports %XTOPT_NBO)
+ * %XTTYPE_PORTRC:	colon-separated port range (names acceptable),
+ * 			(supports %XTOPT_NBO)
  * %XTTYPE_PLEN:	prefix length
  * %XTTYPE_PLENMASK:	prefix length (ptr: union nf_inet_addr)
  * %XTTYPE_ETHERMAC:	Ethernet MAC address in hex form
@@ -91,9 +90,7 @@
 	XTTYPE_HOSTMASK,
 	XTTYPE_PROTOCOL,
 	XTTYPE_PORT,
-	XTTYPE_PORT_NE,
 	XTTYPE_PORTRC,
-	XTTYPE_PORTRC_NE,
 	XTTYPE_PLEN,
 	XTTYPE_PLENMASK,
 	XTTYPE_ETHERMAC,
@@ -104,12 +101,15 @@
  * %XTOPT_MAND:		option is mandatory
  * %XTOPT_MULTI:	option may be specified multiple times
  * %XTOPT_PUT:		store value into memory at @ptroff
+ * %XTOPT_NBO:		store value in network-byte order
+ * 			(only certain XTTYPEs recognize this)
  */
 enum xt_option_flags {
 	XTOPT_INVERT = 1 << 0,
 	XTOPT_MAND   = 1 << 1,
 	XTOPT_MULTI  = 1 << 2,
 	XTOPT_PUT    = 1 << 3,
+	XTOPT_NBO    = 1 << 4,
 };
 
 /**
@@ -408,8 +408,8 @@
 extern void xtables_register_target(struct xtables_target *me);
 extern void xtables_register_targets(struct xtables_target *, unsigned int);
 
-extern bool xtables_strtoul(const char *, char **, unsigned long long *,
-	unsigned long, unsigned long);
+extern bool xtables_strtoul(const char *, char **, uintmax_t *,
+	uintmax_t, uintmax_t);
 extern bool xtables_strtoui(const char *, char **, unsigned int *,
 	unsigned int, unsigned int);
 extern int xtables_service_to_port(const char *name, const char *proto);
diff --git a/iptables/.gitignore b/iptables/.gitignore
new file mode 100644
index 0000000..5a08937
--- /dev/null
+++ b/iptables/.gitignore
@@ -0,0 +1,14 @@
+/ip6tables
+/ip6tables.8
+/ip6tables-save
+/ip6tables-restore
+/ip6tables-static
+/iptables
+/iptables.8
+/iptables-save
+/iptables-restore
+/iptables-static
+/iptables-xml
+/xtables-multi
+
+/xtables.pc
diff --git a/iptables/Makefile.am b/iptables/Makefile.am
new file mode 100644
index 0000000..13cca9c
--- /dev/null
+++ b/iptables/Makefile.am
@@ -0,0 +1,67 @@
+# -*- Makefile -*-
+
+AM_CFLAGS        = ${regular_CFLAGS}
+AM_CPPFLAGS      = ${regular_CPPFLAGS} -I${top_builddir}/include -I${top_srcdir}/include ${kinclude_CPPFLAGS}
+
+lib_LTLIBRARIES       = libxtables.la
+libxtables_la_SOURCES = xtables.c xtoptions.c
+libxtables_la_LDFLAGS = -version-info ${libxtables_vcurrent}:0:${libxtables_vage}
+if ENABLE_SHARED
+libxtables_la_CFLAGS  = ${AM_CFLAGS}
+libxtables_la_LIBADD  = -ldl
+else
+libxtables_la_CFLAGS  = ${AM_CFLAGS} -DNO_SHARED_LIBS=1
+libxtables_la_LIBADD  =
+endif
+
+xtables_multi_SOURCES  = xtables-multi.c iptables-xml.c
+xtables_multi_CFLAGS   = ${AM_CFLAGS} -DIPTABLES_MULTI
+xtables_multi_LDFLAGS  = -rdynamic
+xtables_multi_LDADD    = ../extensions/libext.a
+if ENABLE_STATIC
+xtables_multi_CFLAGS  += -DALL_INCLUSIVE
+endif
+if ENABLE_IPV4
+xtables_multi_SOURCES += iptables-save.c iptables-restore.c \
+                         iptables-standalone.c iptables.c
+xtables_multi_CFLAGS  += -DENABLE_IPV4
+xtables_multi_LDADD   += ../libiptc/libip4tc.la ../extensions/libext4.a
+endif
+if ENABLE_IPV6
+xtables_multi_SOURCES += ip6tables-save.c ip6tables-restore.c \
+                          ip6tables-standalone.c ip6tables.c
+xtables_multi_CFLAGS  += -DENABLE_IPV6
+xtables_multi_LDADD   += ../libiptc/libip6tc.la ../extensions/libext6.a
+endif
+xtables_multi_SOURCES += xshared.c
+xtables_multi_LDADD   += 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
+CLEANFILES       = iptables.8 ip6tables.8
+
+vx_bin_links   = iptables-xml
+if ENABLE_IPV4
+v4_sbin_links  = iptables iptables-restore iptables-save
+endif
+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' $< >$@;
+
+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' $< >$@;
+
+pkgconfig_DATA = xtables.pc
+
+# Using if..fi avoids an ugly "error (ignored)" message :)
+install-exec-hook:
+	-if test -z "${DESTDIR}"; then /sbin/ldconfig; fi;
+	${INSTALL} -dm0755 "${DESTDIR}${bindir}";
+	for i in ${vx_bin_links}; do ${LN_S} -f "${sbindir}/xtables-multi" "${DESTDIR}${bindir}/$$i"; done;
+	for i in ${v4_sbin_links}; do ${LN_S} -f xtables-multi "${DESTDIR}${sbindir}/$$i"; done;
+	for i in ${v6_sbin_links}; do ${LN_S} -f xtables-multi "${DESTDIR}${sbindir}/$$i"; done;
diff --git a/ip6tables-multi.h b/iptables/ip6tables-multi.h
similarity index 100%
rename from ip6tables-multi.h
rename to iptables/ip6tables-multi.h
diff --git a/ip6tables-restore.8 b/iptables/ip6tables-restore.8
similarity index 100%
rename from ip6tables-restore.8
rename to iptables/ip6tables-restore.8
diff --git a/ip6tables-restore.c b/iptables/ip6tables-restore.c
similarity index 100%
rename from ip6tables-restore.c
rename to iptables/ip6tables-restore.c
diff --git a/ip6tables-save.8 b/iptables/ip6tables-save.8
similarity index 100%
rename from ip6tables-save.8
rename to iptables/ip6tables-save.8
diff --git a/ip6tables-save.c b/iptables/ip6tables-save.c
similarity index 100%
rename from ip6tables-save.c
rename to iptables/ip6tables-save.c
diff --git a/ip6tables-standalone.c b/iptables/ip6tables-standalone.c
similarity index 100%
rename from ip6tables-standalone.c
rename to iptables/ip6tables-standalone.c
diff --git a/ip6tables.8.in b/iptables/ip6tables.8.in
similarity index 98%
rename from ip6tables.8.in
rename to iptables/ip6tables.8.in
index 61d6667..48ba18e 100644
--- a/ip6tables.8.in
+++ b/iptables/ip6tables.8.in
@@ -243,15 +243,14 @@
 [\fB!\fP] \fB\-p\fP, \fB\-\-protocol\fP \fIprotocol\fP
 The protocol of the rule or of the packet to check.
 The specified protocol can be one of \fBtcp\fP, \fBudp\fP, \fBudplite\fP,
-\fBicmpv6\fP, \fBesp\fP, \fBmh\fP or \fBall\fP,
+\fBicmpv6\fP, \fBesp\fP, \fBmh\fP or the special keyword "\fBall\fP",
 or it can be a numeric value, representing one of these protocols or a
 different one. A protocol name from /etc/protocols is also allowed.
 But IPv6 extension headers except \fBesp\fP are not allowed.
 \fBesp\fP and \fBipv6\-nonext\fP
 can be used with Kernel version 2.6.11 or later.
 A "!" argument before the protocol inverts the
-test.  The number zero is equivalent to \fBall\fP.
-Protocol \fBall\fP
+test.  The number zero is equivalent to \fBall\fP. "\fBall\fP"
 will match with all protocols and is taken as default when this
 option is omitted.
 .TP
diff --git a/ip6tables.c b/iptables/ip6tables.c
similarity index 95%
rename from ip6tables.c
rename to iptables/ip6tables.c
index 967a5f8..4037acf 100644
--- a/ip6tables.c
+++ b/iptables/ip6tables.c
@@ -549,7 +549,6 @@
 {
 	const struct xtables_target *target = NULL;
 	const struct ip6t_entry_target *t;
-	uint8_t flags;
 	char buf[BUFSIZ];
 
 	if (!ip6tc_is_chain(targname, handle))
@@ -559,7 +558,6 @@
 		         XTF_LOAD_MUST_SUCCEED);
 
 	t = ip6t_get_target((struct ip6t_entry *)fw);
-	flags = fw->ipv6.flags;
 
 	if (format & FMT_LINENUMBERS)
 		printf(FMT("%-4u ", "%u "), num);
@@ -768,10 +766,10 @@
 
 	size = sizeof(struct ip6t_entry);
 	for (matchp = matches; matchp; matchp = matchp->next)
-		size += IP6T_ALIGN(sizeof(struct ip6t_entry_match)) + matchp->match->size;
+		size += XT_ALIGN(sizeof(struct ip6t_entry_match)) + matchp->match->size;
 
 	mask = xtables_calloc(1, size
-			 + IP6T_ALIGN(sizeof(struct ip6t_entry_target))
+			 + XT_ALIGN(sizeof(struct ip6t_entry_target))
 			 + target->size);
 
 	memset(mask, 0xFF, sizeof(struct ip6t_entry));
@@ -779,13 +777,13 @@
 
 	for (matchp = matches; matchp; matchp = matchp->next) {
 		memset(mptr, 0xFF,
-		       IP6T_ALIGN(sizeof(struct ip6t_entry_match))
+		       XT_ALIGN(sizeof(struct ip6t_entry_match))
 		       + matchp->match->userspacesize);
-		mptr += IP6T_ALIGN(sizeof(struct ip6t_entry_match)) + matchp->match->size;
+		mptr += XT_ALIGN(sizeof(struct ip6t_entry_match)) + matchp->match->size;
 	}
 
 	memset(mptr, 0xFF,
-	       IP6T_ALIGN(sizeof(struct ip6t_entry_target))
+	       XT_ALIGN(sizeof(struct ip6t_entry_target))
 	       + target->userspacesize);
 
 	return mask;
@@ -1272,73 +1270,6 @@
 	*matches = NULL;
 }
 
-static void command_default(struct iptables_command_state *cs)
-{
-	struct xtables_rule_match *matchp;
-	struct xtables_match *m;
-
-	if (cs->target != NULL &&
-	    (cs->target->parse != NULL || cs->target->x6_parse != NULL) &&
-	    cs->c >= cs->target->option_offset &&
-	    cs->c < cs->target->option_offset + XT_OPTION_OFFSET_SCALE) {
-		xtables_option_tpcall(cs->c, cs->argv, cs->invert,
-				      cs->target, &cs->fw);
-		return;
-	}
-
-	for (matchp = cs->matches; matchp; matchp = matchp->next) {
-		m = matchp->match;
-
-		if (matchp->completed ||
-		    (m->x6_parse == NULL && m->parse == NULL))
-			continue;
-		if (cs->c < matchp->match->option_offset ||
-		    cs->c >= matchp->match->option_offset + XT_OPTION_OFFSET_SCALE)
-			continue;
-		xtables_option_mpcall(cs->c, cs->argv, cs->invert, m, &cs->fw);
-		return;
-	}
-
-	/* Try loading protocol */
-	m = load_proto(cs);
-	if (m != NULL) {
-		size_t size;
-
-		cs->proto_used = 1;
-
-		size = IP6T_ALIGN(sizeof(struct ip6t_entry_match)) + m->size;
-
-		m->m = xtables_calloc(1, size);
-		m->m->u.match_size = size;
-		strcpy(m->m->u.user.name, m->name);
-		m->m->u.user.revision = m->revision;
-		if (m->init != NULL)
-			m->init(m->m);
-
-		if (m->x6_options != NULL)
-			opts = xtables_options_xfrm(ip6tables_globals.orig_opts,
-						    opts, m->x6_options,
-						    &m->option_offset);
-		else
-			opts = xtables_merge_options(ip6tables_globals.orig_opts,
-						     opts,
-						     m->extra_opts,
-						     &m->option_offset);
-		if (opts == NULL)
-			xtables_error(OTHER_PROBLEM, "can't alloc memory!");
-		optind--;
-		return;
-	}
-
-	if (cs->c == ':')
-		xtables_error(PARAMETER_PROBLEM, "option \"%s\" "
-		              "requires an argument", cs->argv[optind-1]);
-	if (cs->c == '?')
-		xtables_error(PARAMETER_PROBLEM, "unknown option "
-			      "\"%s\"", cs->argv[optind-1]);
-	xtables_error(PARAMETER_PROBLEM, "Unknown arg \"%s\"", optarg);
-}
-
 static void command_jump(struct iptables_command_state *cs)
 {
 	size_t size;
@@ -1351,7 +1282,7 @@
 	if (cs->target == NULL)
 		return;
 
-	size = IP6T_ALIGN(sizeof(struct ip6t_entry_target)) + cs->target->size;
+	size = XT_ALIGN(sizeof(struct ip6t_entry_target)) + cs->target->size;
 
 	cs->target->t = xtables_calloc(1, size);
 	cs->target->t->u.target_size = size;
@@ -1381,7 +1312,7 @@
 			   "unexpected ! flag before --match");
 
 	m = xtables_find_match(optarg, XTF_LOAD_MUST_SUCCEED, &cs->matches);
-	size = IP6T_ALIGN(sizeof(struct ip6t_entry_match)) + m->size;
+	size = XT_ALIGN(sizeof(struct ip6t_entry_match)) + m->size;
 	m->m = xtables_calloc(1, size);
 	m->m->u.match_size = size;
 	strcpy(m->m->u.user.name, m->name);
@@ -1785,7 +1716,13 @@
 			exit_tryhelp(2);
 
 		default:
-			command_default(&cs);
+			if (command_default(&cs, &ip6tables_globals) == 1)
+				/*
+				 * If new options were loaded, we must retry
+				 * getopt immediately and not allow
+				 * cs.invert=FALSE to be executed.
+				 */
+				continue;
 			break;
 		}
 		cs.invert = FALSE;
diff --git a/iptables-apply b/iptables/iptables-apply
similarity index 100%
rename from iptables-apply
rename to iptables/iptables-apply
diff --git a/iptables-apply.8 b/iptables/iptables-apply.8
similarity index 100%
rename from iptables-apply.8
rename to iptables/iptables-apply.8
diff --git a/iptables-multi.h b/iptables/iptables-multi.h
similarity index 82%
rename from iptables-multi.h
rename to iptables/iptables-multi.h
index a9912b0..a2bb878 100644
--- a/iptables-multi.h
+++ b/iptables/iptables-multi.h
@@ -4,6 +4,5 @@
 extern int iptables_main(int, char **);
 extern int iptables_save_main(int, char **);
 extern int iptables_restore_main(int, char **);
-extern int iptables_xml_main(int, char **);
 
 #endif /* _IPTABLES_MULTI_H */
diff --git a/iptables-restore.8 b/iptables/iptables-restore.8
similarity index 100%
rename from iptables-restore.8
rename to iptables/iptables-restore.8
diff --git a/iptables-restore.c b/iptables/iptables-restore.c
similarity index 100%
rename from iptables-restore.c
rename to iptables/iptables-restore.c
diff --git a/iptables-save.8 b/iptables/iptables-save.8
similarity index 100%
rename from iptables-save.8
rename to iptables/iptables-save.8
diff --git a/iptables-save.c b/iptables/iptables-save.c
similarity index 100%
rename from iptables-save.c
rename to iptables/iptables-save.c
diff --git a/iptables-standalone.c b/iptables/iptables-standalone.c
similarity index 100%
rename from iptables-standalone.c
rename to iptables/iptables-standalone.c
diff --git a/iptables-xml.8 b/iptables/iptables-xml.1
similarity index 100%
rename from iptables-xml.8
rename to iptables/iptables-xml.1
diff --git a/iptables-xml.c b/iptables/iptables-xml.c
similarity index 98%
rename from iptables-xml.c
rename to iptables/iptables-xml.c
index dc3cd4f..5aa638c 100644
--- a/iptables-xml.c
+++ b/iptables/iptables-xml.c
@@ -1,6 +1,6 @@
 /* Code to convert iptables-save format to xml format,
  * (C) 2006 Ufo Mechanic <azez@ufomechanic.net>
- * based on iptables-restor (C) 2000-2002 by Harald Welte <laforge@gnumonks.org>
+ * based on iptables-restore (C) 2000-2002 by Harald Welte <laforge@gnumonks.org>
  * based on previous code from Rusty Russell <rusty@linuxcare.com.au>
  *
  * This code is distributed under the terms of GNU GPL v2
@@ -14,7 +14,7 @@
 #include <stdarg.h>
 #include "iptables.h"
 #include "libiptc/libiptc.h"
-#include "iptables-multi.h"
+#include "xtables-multi.h"
 #include <xtables.h>
 
 #ifdef DEBUG
@@ -373,7 +373,6 @@
 {
 	int arg = 1;		// ignore leading -A
 	char invert_next = 0;
-	char *thisChain = NULL;
 	char *spacer = "";	// space when needed to assemble arguments
 	char *level1 = NULL;
 	char *level2 = NULL;
@@ -397,8 +396,6 @@
 		} else printf("%s<%s ", (leveli ## LEVEL), (level ## LEVEL)); \
 	} while(0)
 
-	thisChain = argv[arg++];
-
 	if (part == 1) {	/* skip */
 		/* use argvattr to tell which arguments were quoted 
 		   to avoid comparing quoted arguments, like comments, to -j, */
diff --git a/iptables.8.in b/iptables/iptables.8.in
similarity index 98%
rename from iptables.8.in
rename to iptables/iptables.8.in
index 110c599..d09bf7a 100644
--- a/iptables.8.in
+++ b/iptables/iptables.8.in
@@ -246,12 +246,11 @@
 [\fB!\fP] \fB\-p\fP, \fB\-\-protocol\fP \fIprotocol\fP
 The protocol of the rule or of the packet to check.
 The specified protocol can be one of \fBtcp\fP, \fBudp\fP, \fBudplite\fP,
-\fBicmp\fP, \fBesp\fP, \fBah\fP, \fBsctp\fP or \fBall\fP,
+\fBicmp\fP, \fBesp\fP, \fBah\fP, \fBsctp\fP or the special keyword "\fBall\fP",
 or it can be a numeric value, representing one of these protocols or a
 different one.  A protocol name from /etc/protocols is also allowed.
 A "!" argument before the protocol inverts the
-test.  The number zero is equivalent to \fBall\fP.
-Protocol \fBall\fP
+test.  The number zero is equivalent to \fBall\fP. "\fBall\fP"
 will match with all protocols and is taken as default when this
 option is omitted.
 .TP
diff --git a/iptables.c b/iptables/iptables.c
similarity index 95%
rename from iptables.c
rename to iptables/iptables.c
index cc7525a..4ae7541 100644
--- a/iptables.c
+++ b/iptables/iptables.c
@@ -771,10 +771,10 @@
 
 	size = sizeof(struct ipt_entry);
 	for (matchp = matches; matchp; matchp = matchp->next)
-		size += IPT_ALIGN(sizeof(struct ipt_entry_match)) + matchp->match->size;
+		size += XT_ALIGN(sizeof(struct ipt_entry_match)) + matchp->match->size;
 
 	mask = xtables_calloc(1, size
-			 + IPT_ALIGN(sizeof(struct ipt_entry_target))
+			 + XT_ALIGN(sizeof(struct ipt_entry_target))
 			 + target->size);
 
 	memset(mask, 0xFF, sizeof(struct ipt_entry));
@@ -782,13 +782,13 @@
 
 	for (matchp = matches; matchp; matchp = matchp->next) {
 		memset(mptr, 0xFF,
-		       IPT_ALIGN(sizeof(struct ipt_entry_match))
+		       XT_ALIGN(sizeof(struct ipt_entry_match))
 		       + matchp->match->userspacesize);
-		mptr += IPT_ALIGN(sizeof(struct ipt_entry_match)) + matchp->match->size;
+		mptr += XT_ALIGN(sizeof(struct ipt_entry_match)) + matchp->match->size;
 	}
 
 	memset(mptr, 0xFF,
-	       IPT_ALIGN(sizeof(struct ipt_entry_target))
+	       XT_ALIGN(sizeof(struct ipt_entry_target))
 	       + target->userspacesize);
 
 	return mask;
@@ -1296,74 +1296,6 @@
 	kernel_version = LINUX_VERSION(x, y, z);
 }
 
-static void command_default(struct iptables_command_state *cs)
-{
-	struct xtables_rule_match *matchp;
-	struct xtables_match *m;
-
-	if (cs->target != NULL &&
-	    (cs->target->parse != NULL || cs->target->x6_parse != NULL) &&
-	    cs->c >= cs->target->option_offset &&
-	    cs->c < cs->target->option_offset + XT_OPTION_OFFSET_SCALE) {
-		xtables_option_tpcall(cs->c, cs->argv, cs->invert,
-				      cs->target, &cs->fw);
-		return;
-	}
-
-	for (matchp = cs->matches; matchp; matchp = matchp->next) {
-		m = matchp->match;
-
-		if (matchp->completed ||
-		    (m->x6_parse == NULL && m->parse == NULL))
-			continue;
-		if (cs->c < m->option_offset ||
-		    cs->c >= m->option_offset + XT_OPTION_OFFSET_SCALE)
-			continue;
-		xtables_option_mpcall(cs->c, cs->argv, cs->invert, m, &cs->fw);
-		return;
-	}
-
-	/* Try loading protocol */
-	m = load_proto(cs);
-	if (m != NULL) {
-		size_t size;
-
-		cs->proto_used = 1;
-
-		size = IPT_ALIGN(sizeof(struct ipt_entry_match)) + m->size;
-
-		m->m = xtables_calloc(1, size);
-		m->m->u.match_size = size;
-		strcpy(m->m->u.user.name, m->name);
-		m->m->u.user.revision = m->revision;
-		if (m->init != NULL)
-			m->init(m->m);
-
-		if (m->x6_options != NULL)
-			opts = xtables_options_xfrm(iptables_globals.orig_opts,
-						    opts, m->x6_options,
-						    &m->option_offset);
-		else
-			opts = xtables_merge_options(iptables_globals.orig_opts,
-						     opts,
-						     m->extra_opts,
-						     &m->option_offset);
-		if (opts == NULL)
-			xtables_error(OTHER_PROBLEM, "can't alloc memory!");
-
-		optind--;
-		return;
-	}
-
-	if (cs->c == ':')
-		xtables_error(PARAMETER_PROBLEM, "option \"%s\" "
-		              "requires an argument", cs->argv[optind-1]);
-	if (cs->c == '?')
-		xtables_error(PARAMETER_PROBLEM, "unknown option "
-			      "\"%s\"", cs->argv[optind-1]);
-	xtables_error(PARAMETER_PROBLEM, "Unknown arg \"%s\"", optarg);
-}
-
 static void command_jump(struct iptables_command_state *cs)
 {
 	size_t size;
@@ -1376,7 +1308,7 @@
 	if (cs->target == NULL)
 		return;
 
-	size = IPT_ALIGN(sizeof(struct ipt_entry_target))
+	size = XT_ALIGN(sizeof(struct ipt_entry_target))
 		+ cs->target->size;
 
 	cs->target->t = xtables_calloc(1, size);
@@ -1407,7 +1339,7 @@
 			   "unexpected ! flag before --match");
 
 	m = xtables_find_match(optarg, XTF_LOAD_MUST_SUCCEED, &cs->matches);
-	size = IPT_ALIGN(sizeof(struct ipt_entry_match)) + m->size;
+	size = XT_ALIGN(sizeof(struct ipt_entry_match)) + m->size;
 	m->m = xtables_calloc(1, size);
 	m->m->u.match_size = size;
 	strcpy(m->m->u.user.name, m->name);
@@ -1811,7 +1743,9 @@
 			exit_tryhelp(2);
 
 		default:
-			command_default(&cs);
+			if (command_default(&cs, &iptables_globals) == 1)
+				/* cf. ip6tables.c */
+				continue;
 			break;
 		}
 		cs.invert = FALSE;
diff --git a/iptables.xslt b/iptables/iptables.xslt
similarity index 100%
rename from iptables.xslt
rename to iptables/iptables.xslt
diff --git a/xshared.c b/iptables/xshared.c
similarity index 64%
rename from xshared.c
rename to iptables/xshared.c
index 87402b4..0e3857b 100644
--- a/xshared.c
+++ b/iptables/xshared.c
@@ -1,3 +1,4 @@
+#include <getopt.h>
 #include <libgen.h>
 #include <netdb.h>
 #include <stdbool.h>
@@ -103,6 +104,77 @@
 			  cs->options & OPT_NUMERIC, &cs->matches);
 }
 
+int command_default(struct iptables_command_state *cs,
+		    struct xtables_globals *gl)
+{
+	struct xtables_rule_match *matchp;
+	struct xtables_match *m;
+
+	if (cs->target != NULL &&
+	    (cs->target->parse != NULL || cs->target->x6_parse != NULL) &&
+	    cs->c >= cs->target->option_offset &&
+	    cs->c < cs->target->option_offset + XT_OPTION_OFFSET_SCALE) {
+		xtables_option_tpcall(cs->c, cs->argv, cs->invert,
+				      cs->target, &cs->fw);
+		return 0;
+	}
+
+	for (matchp = cs->matches; matchp; matchp = matchp->next) {
+		m = matchp->match;
+
+		if (matchp->completed ||
+		    (m->x6_parse == NULL && m->parse == NULL))
+			continue;
+		if (cs->c < matchp->match->option_offset ||
+		    cs->c >= matchp->match->option_offset + XT_OPTION_OFFSET_SCALE)
+			continue;
+		xtables_option_mpcall(cs->c, cs->argv, cs->invert, m, &cs->fw);
+		return 0;
+	}
+
+	/* Try loading protocol */
+	m = load_proto(cs);
+	if (m != NULL) {
+		size_t size;
+
+		cs->proto_used = 1;
+
+		size = XT_ALIGN(sizeof(struct ip6t_entry_match)) + m->size;
+
+		m->m = xtables_calloc(1, size);
+		m->m->u.match_size = size;
+		strcpy(m->m->u.user.name, m->name);
+		m->m->u.user.revision = m->revision;
+		if (m->init != NULL)
+			m->init(m->m);
+
+		if (m->x6_options != NULL)
+			gl->opts = xtables_options_xfrm(gl->orig_opts,
+							gl->opts,
+							m->x6_options,
+							&m->option_offset);
+		else
+			gl->opts = xtables_merge_options(gl->orig_opts,
+							 gl->opts,
+							 m->extra_opts,
+							 &m->option_offset);
+		if (gl->opts == NULL)
+			xtables_error(OTHER_PROBLEM, "can't alloc memory!");
+		optind--;
+		/* Indicate to rerun getopt *immediately* */
+ 		return 1;
+	}
+
+	if (cs->c == ':')
+		xtables_error(PARAMETER_PROBLEM, "option \"%s\" "
+		              "requires an argument", cs->argv[optind-1]);
+	if (cs->c == '?')
+		xtables_error(PARAMETER_PROBLEM, "unknown option "
+			      "\"%s\"", cs->argv[optind-1]);
+	xtables_error(PARAMETER_PROBLEM, "Unknown arg \"%s\"", optarg);
+	return 0;
+}
+
 static mainfunc_t subcmd_get(const char *cmd, const struct subcommand *cb)
 {
 	for (; cb->name != NULL; ++cb)
diff --git a/xshared.h b/iptables/xshared.h
similarity index 94%
rename from xshared.h
rename to iptables/xshared.h
index 34f3265..b44a3a3 100644
--- a/xshared.h
+++ b/iptables/xshared.h
@@ -23,6 +23,7 @@
 	OPT_COUNTERS    = 1 << 10,
 };
 
+struct xtables_globals;
 struct xtables_rule_match;
 struct xtables_target;
 
@@ -76,6 +77,8 @@
 extern void print_extension_helps(const struct xtables_target *,
 	const struct xtables_rule_match *);
 extern const char *proto_to_name(uint8_t, int);
+extern int command_default(struct iptables_command_state *,
+	struct xtables_globals *);
 extern struct xtables_match *load_proto(struct iptables_command_state *);
 extern int subcmd_main(int, char **, const struct subcommand *);
 
diff --git a/xtables-multi.c b/iptables/xtables-multi.c
similarity index 92%
rename from xtables-multi.c
rename to iptables/xtables-multi.c
index f8d56ce..8014d5f 100644
--- a/xtables-multi.c
+++ b/iptables/xtables-multi.c
@@ -3,6 +3,8 @@
 #include <string.h>
 #include "xshared.h"
 
+#include "xtables-multi.h"
+
 #ifdef ENABLE_IPV4
 #include "iptables-multi.h"
 #endif
@@ -19,9 +21,9 @@
 	{"save4",               iptables_save_main},
 	{"iptables-restore",    iptables_restore_main},
 	{"restore4",            iptables_restore_main},
-	{"iptables-xml",        iptables_xml_main},
-	{"xml4",                iptables_xml_main},
 #endif
+	{"iptables-xml",        iptables_xml_main},
+	{"xml",                 iptables_xml_main},
 #ifdef ENABLE_IPV6
 	{"ip6tables",           ip6tables_main},
 	{"main6",               ip6tables_main},
diff --git a/iptables/xtables-multi.h b/iptables/xtables-multi.h
new file mode 100644
index 0000000..615724b
--- /dev/null
+++ b/iptables/xtables-multi.h
@@ -0,0 +1,6 @@
+#ifndef _XTABLES_MULTI_H
+#define _XTABLES_MULTI_H 1
+
+extern int iptables_xml_main(int, char **);
+
+#endif /* _XTABLES_MULTI_H */
diff --git a/xtables.c b/iptables/xtables.c
similarity index 97%
rename from xtables.c
rename to iptables/xtables.c
index 30977d5..acfcf8b 100644
--- a/xtables.c
+++ b/iptables/xtables.c
@@ -15,9 +15,10 @@
  *	along with this program; if not, write to the Free Software
  *	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
-
+#include <ctype.h>
 #include <errno.h>
 #include <fcntl.h>
+#include <inttypes.h>
 #include <netdb.h>
 #include <stdarg.h>
 #include <stdbool.h>
@@ -31,9 +32,7 @@
 #include <sys/types.h>
 #include <sys/wait.h>
 #include <arpa/inet.h>
-#if !defined(__ANDROID__)
 #include <linux/magic.h> /* for PROC_SUPER_MAGIC */
-#endif
 
 #include <xtables.h>
 #include <limits.h> /* INT_MAX in ip_tables.h/ip6_tables.h */
@@ -428,15 +427,20 @@
  * Returns true/false whether number was accepted. On failure, *value has
  * undefined contents.
  */
-bool xtables_strtoul(const char *s, char **end, unsigned long long *value,
-                     unsigned long min, unsigned long max)
+bool xtables_strtoul(const char *s, char **end, uintmax_t *value,
+                     uintmax_t min, uintmax_t max)
 {
-	unsigned long v;
+	uintmax_t v;
+	const char *p;
 	char *my_end;
 
 	errno = 0;
-	v = strtoul(s, &my_end, 0);
-
+	/* Since strtoul allows leading minus, we have to check for ourself. */
+	for (p = s; isspace(*p); ++p)
+		;
+	if (*p == '-')
+		return false;
+	v = strtoumax(s, &my_end, 0);
 	if (my_end == s)
 		return false;
 	if (end != NULL)
@@ -456,7 +460,7 @@
 bool xtables_strtoui(const char *s, char **end, unsigned int *value,
                      unsigned int min, unsigned int max)
 {
-	unsigned long long v;
+	uintmax_t v;
 	bool ret;
 
 	ret = xtables_strtoul(s, end, &v, min, max);
@@ -1799,37 +1803,30 @@
 uint16_t
 xtables_parse_protocol(const char *s)
 {
-	unsigned int proto;
+	const struct protoent *pent;
+	unsigned int proto, i;
 
-	if (!xtables_strtoui(s, NULL, &proto, 0, UINT8_MAX)) {
-		struct protoent *pent;
+	if (xtables_strtoui(s, NULL, &proto, 0, UINT8_MAX))
+		return proto;
 
-		/* first deal with the special case of 'all' to prevent
-		 * people from being able to redefine 'all' in nsswitch
-		 * and/or provoke expensive [not working] ldap/nis/...
-		 * lookups */
-		if (!strcmp(s, "all"))
-			return 0;
+	/* first deal with the special case of 'all' to prevent
+	 * people from being able to redefine 'all' in nsswitch
+	 * and/or provoke expensive [not working] ldap/nis/...
+	 * lookups */
+	if (strcmp(s, "all") == 0)
+		return 0;
 
-		if ((pent = getprotobyname(s)))
-			proto = pent->p_proto;
-		else {
-			unsigned int i;
-			for (i = 0; i < ARRAY_SIZE(xtables_chain_protos); ++i) {
-				if (xtables_chain_protos[i].name == NULL)
-					continue;
+	pent = getprotobyname(s);
+	if (pent != NULL)
+		return pent->p_proto;
 
-				if (strcmp(s, xtables_chain_protos[i].name) == 0) {
-					proto = xtables_chain_protos[i].num;
-					break;
-				}
-			}
-			if (i == ARRAY_SIZE(xtables_chain_protos))
-				xt_params->exit_err(PARAMETER_PROBLEM,
-					   "unknown protocol `%s' specified",
-					   s);
-		}
+	for (i = 0; i < ARRAY_SIZE(xtables_chain_protos); ++i) {
+		if (xtables_chain_protos[i].name == NULL)
+			continue;
+		if (strcmp(s, xtables_chain_protos[i].name) == 0)
+			return xtables_chain_protos[i].num;
 	}
-
-	return proto;
+	xt_params->exit_err(PARAMETER_PROBLEM,
+		"unknown protocol \"%s\" specified", s);
+	return -1;
 }
diff --git a/xtables.pc.in b/iptables/xtables.pc.in
similarity index 100%
rename from xtables.pc.in
rename to iptables/xtables.pc.in
diff --git a/xtoptions.c b/iptables/xtoptions.c
similarity index 89%
rename from xtoptions.c
rename to iptables/xtoptions.c
index 7a35ffa..ac0601f 100644
--- a/xtoptions.c
+++ b/iptables/xtoptions.c
@@ -41,6 +41,31 @@
 	uint8_t value, mask;
 };
 
+static const size_t xtopt_psize[] = {
+	/*
+	 * All types not listed here, and thus essentially being initialized to
+	 * zero have zero on purpose.
+	 */
+	[XTTYPE_UINT8]       = sizeof(uint8_t),
+	[XTTYPE_UINT16]      = sizeof(uint16_t),
+	[XTTYPE_UINT32]      = sizeof(uint32_t),
+	[XTTYPE_UINT64]      = sizeof(uint64_t),
+	[XTTYPE_UINT8RC]     = sizeof(uint8_t[2]),
+	[XTTYPE_UINT16RC]    = sizeof(uint16_t[2]),
+	[XTTYPE_UINT32RC]    = sizeof(uint32_t[2]),
+	[XTTYPE_UINT64RC]    = sizeof(uint64_t[2]),
+	[XTTYPE_DOUBLE]      = sizeof(double),
+	[XTTYPE_STRING]      = -1,
+	[XTTYPE_SYSLOGLEVEL] = sizeof(uint8_t),
+	[XTTYPE_HOST]        = sizeof(union nf_inet_addr),
+	[XTTYPE_HOSTMASK]    = sizeof(union nf_inet_addr),
+	[XTTYPE_PROTOCOL]    = sizeof(uint8_t),
+	[XTTYPE_PORT]        = sizeof(uint16_t),
+	[XTTYPE_PORTRC]      = sizeof(uint16_t[2]),
+	[XTTYPE_PLENMASK]    = sizeof(union nf_inet_addr),
+	[XTTYPE_ETHERMAC]    = sizeof(uint8_t[6]),
+};
+
 /**
  * Creates getopt options from the x6-style option map, and assigns each a
  * getopt id.
@@ -99,20 +124,57 @@
 }
 
 /**
+ * Give the upper limit for a certain type.
+ */
+static uintmax_t xtopt_max_by_type(enum xt_option_type type)
+{
+	switch (type) {
+	case XTTYPE_UINT8:
+	case XTTYPE_UINT8RC:
+		return UINT8_MAX;
+	case XTTYPE_UINT16:
+	case XTTYPE_UINT16RC:
+		return UINT16_MAX;
+	case XTTYPE_UINT32:
+	case XTTYPE_UINT32RC:
+		return UINT32_MAX;
+	case XTTYPE_UINT64:
+	case XTTYPE_UINT64RC:
+		return UINT64_MAX;
+	default:
+		return 0;
+	}
+}
+
+/**
+ * Return the size of a single entity based upon a type - predominantly an
+ * XTTYPE_UINT*RC type.
+ */
+static size_t xtopt_esize_by_type(enum xt_option_type type)
+{
+	switch (type) {
+	case XTTYPE_UINT8RC:
+		return xtopt_psize[XTTYPE_UINT8];
+	case XTTYPE_UINT16RC:
+		return xtopt_psize[XTTYPE_UINT16];
+	case XTTYPE_UINT32RC:
+		return xtopt_psize[XTTYPE_UINT32];
+	case XTTYPE_UINT64RC:
+		return xtopt_psize[XTTYPE_UINT64];
+	default:
+		return xtopt_psize[type];
+	}
+}
+
+/**
  * Require a simple integer.
  */
 static void xtopt_parse_int(struct xt_option_call *cb)
 {
 	const struct xt_option_entry *entry = cb->entry;
-	unsigned long long lmin = 0, lmax = UINT32_MAX;
-	unsigned long long value;
+	uintmax_t lmin = 0, lmax = xtopt_max_by_type(entry->type);
+	uintmax_t value;
 
-	if (entry->type == XTTYPE_UINT8)
-		lmax = UINT8_MAX;
-	else if (entry->type == XTTYPE_UINT16)
-		lmax = UINT16_MAX;
-	else if (entry->type == XTTYPE_UINT64)
-		lmax = UINT64_MAX;
 	if (cb->entry->min != 0)
 		lmin = cb->entry->min;
 	if (cb->entry->max != 0)
@@ -121,7 +183,7 @@
 	if (!xtables_strtoul(cb->arg, NULL, &value, lmin, lmax))
 		xt_params->exit_err(PARAMETER_PROBLEM,
 			"%s: bad value for option \"--%s\", "
-			"or out of range (%llu-%llu).\n",
+			"or out of range (%ju-%ju).\n",
 			cb->ext_name, entry->name, lmin, lmax);
 
 	if (entry->type == XTTYPE_UINT8) {
@@ -167,6 +229,48 @@
 }
 
 /**
+ * Copy the parsed value to the appropriate entry in cb->val.
+ */
+static void xtopt_mint_value_to_cb(struct xt_option_call *cb, uintmax_t value)
+{
+	const struct xt_option_entry *entry = cb->entry;
+
+	if (cb->nvals >= ARRAY_SIZE(cb->val.u32_range))
+		return;
+	if (entry->type == XTTYPE_UINT8RC)
+		cb->val.u8_range[cb->nvals] = value;
+	else if (entry->type == XTTYPE_UINT16RC)
+		cb->val.u16_range[cb->nvals] = value;
+	else if (entry->type == XTTYPE_UINT32RC)
+		cb->val.u32_range[cb->nvals] = value;
+	else if (entry->type == XTTYPE_UINT64RC)
+		cb->val.u64_range[cb->nvals] = value;
+}
+
+/**
+ * Copy the parsed value to the data area, using appropriate type access.
+ */
+static void xtopt_mint_value_to_ptr(struct xt_option_call *cb, void **datap,
+				    uintmax_t value)
+{
+	const struct xt_option_entry *entry = cb->entry;
+	void *data = *datap;
+
+	if (!(entry->flags & XTOPT_PUT))
+		return;
+	if (entry->type == XTTYPE_UINT8RC)
+		*(uint8_t *)data = value;
+	else if (entry->type == XTTYPE_UINT16RC)
+		*(uint16_t *)data = value;
+	else if (entry->type == XTTYPE_UINT32RC)
+		*(uint32_t *)data = value;
+	else if (entry->type == XTTYPE_UINT64RC)
+		*(uint64_t *)data = value;
+	data += xtopt_esize_by_type(entry->type);
+	*datap = data;
+}
+
+/**
  * Multiple integer parse routine.
  *
  * This function is capable of parsing any number of fields. Only the first
@@ -179,62 +283,46 @@
 {
 	const struct xt_option_entry *entry = cb->entry;
 	const char *arg = cb->arg;
-	size_t esize = sizeof(uint32_t);
-	char *put = XTOPT_MKPTR(cb);
-	unsigned int maxiter, value;
+	size_t esize = xtopt_esize_by_type(entry->type);
+	const uintmax_t lmax = xtopt_max_by_type(entry->type);
+	void *put = XTOPT_MKPTR(cb);
+	unsigned int maxiter;
+	uintmax_t value;
 	char *end = "";
 	char sep = ':';
 
-	if (entry->type == XTTYPE_UINT8RC)
-		esize = sizeof(uint8_t);
-	else if (entry->type == XTTYPE_UINT16RC)
-		esize = sizeof(uint16_t);
-	else if (entry->type == XTTYPE_UINT64RC)
-		esize = sizeof(uint64_t);
 	maxiter = entry->size / esize;
 	if (maxiter == 0)
-		maxiter = 2; /* ARRAY_SIZE(cb->val.uXX_range) */
+		maxiter = ARRAY_SIZE(cb->val.u32_range);
 	if (entry->size % esize != 0)
 		xt_params->exit_err(OTHER_PROBLEM, "%s: memory block does "
 			"not have proper size\n", __func__);
 
 	cb->nvals = 0;
-	for (arg = cb->arg; ; arg = end + 1) {
+	for (arg = cb->arg, end = (char *)arg; ; arg = end + 1) {
 		if (cb->nvals == maxiter)
 			xt_params->exit_err(PARAMETER_PROBLEM, "%s: Too many "
 				"components for option \"--%s\" (max: %u)\n",
 				cb->ext_name, entry->name, maxiter);
-		if (!xtables_strtoui(arg, &end, &value, 0, UINT32_MAX))
-			xt_params->exit_err(PARAMETER_PROBLEM,
-				"%s: bad value for option \"--%s\", "
-				"or out of range (0-%u).\n",
-				cb->ext_name, entry->name, UINT32_MAX);
-		if (*end != '\0' && *end != sep)
-			xt_params->exit_err(PARAMETER_PROBLEM,
-				"%s: Argument to \"--%s\" has unexpected "
-				"characters.\n", cb->ext_name, entry->name);
-		if (cb->nvals < ARRAY_SIZE(cb->val.u32_range)) {
-			if (entry->type == XTTYPE_UINT8RC)
-				cb->val.u8_range[cb->nvals] = value;
-			else if (entry->type == XTTYPE_UINT16RC)
-				cb->val.u16_range[cb->nvals] = value;
-			else if (entry->type == XTTYPE_UINT32RC)
-				cb->val.u32_range[cb->nvals] = value;
-			else if (entry->type == XTTYPE_UINT64RC)
-				cb->val.u64_range[cb->nvals] = value;
+		if (*arg == '\0' || *arg == sep) {
+			/* Default range components when field not spec'd. */
+			end = (char *)arg;
+			value = (cb->nvals == 1) ? lmax : 0;
+		} else {
+			if (!xtables_strtoul(arg, &end, &value, 0, lmax))
+				xt_params->exit_err(PARAMETER_PROBLEM,
+					"%s: bad value for option \"--%s\" near "
+					"\"%s\", or out of range (0-%ju).\n",
+					cb->ext_name, entry->name, arg, lmax);
+			if (*end != '\0' && *end != sep)
+				xt_params->exit_err(PARAMETER_PROBLEM,
+					"%s: Argument to \"--%s\" has "
+					"unexpected characters near \"%s\".\n",
+					cb->ext_name, entry->name, end);
 		}
+		xtopt_mint_value_to_cb(cb, value);
 		++cb->nvals;
-		if (entry->flags & XTOPT_PUT) {
-			if (entry->type == XTTYPE_UINT8RC)
-				*(uint8_t *)put = value;
-			else if (entry->type == XTTYPE_UINT16RC)
-				*(uint16_t *)put = value;
-			else if (entry->type == XTTYPE_UINT32RC)
-				*(uint32_t *)put = value;
-			else if (entry->type == XTTYPE_UINT64RC)
-				*(uint64_t *)put = value;
-			put += esize;
-		}
+		xtopt_mint_value_to_ptr(cb, &put, value);
 		if (*end == '\0')
 			break;
 	}
@@ -498,19 +586,7 @@
  */
 static void xtopt_parse_protocol(struct xt_option_call *cb)
 {
-	const struct protoent *entry;
-	unsigned int value = -1;
-
-	if (xtables_strtoui(cb->arg, NULL, &value, 0, UINT8_MAX)) {
-		cb->val.protocol = value;
-		return;
-	}
-	entry = getprotobyname(cb->arg);
-	if (entry == NULL)
-		xt_params->exit_err(PARAMETER_PROBLEM,
-			"Protocol \"%s\" does not resolve to anything.\n",
-			cb->arg);
-	cb->val.protocol = entry->p_proto;
+	cb->val.protocol = xtables_parse_protocol(cb->arg);
 	if (cb->entry->flags & XTOPT_PUT)
 		*(uint8_t *)XTOPT_MKPTR(cb) = cb->val.protocol;
 }
@@ -521,6 +597,7 @@
  */
 static void xtopt_parse_port(struct xt_option_call *cb)
 {
+	const struct xt_option_entry *entry = cb->entry;
 	int ret;
 
 	ret = xtables_getportbyname(cb->arg);
@@ -528,10 +605,10 @@
 		xt_params->exit_err(PARAMETER_PROBLEM,
 			"Port \"%s\" does not resolve to anything.\n",
 			cb->arg);
+	if (entry->flags & XTOPT_NBO)
+		ret = htons(ret);
 	cb->val.port = ret;
-	if (cb->entry->type == XTTYPE_PORT_NE)
-		cb->val.port = htons(cb->val.port);
-	if (cb->entry->flags & XTOPT_PUT)
+	if (entry->flags & XTOPT_PUT)
 		*(uint16_t *)XTOPT_MKPTR(cb) = cb->val.port;
 }
 
@@ -573,7 +650,7 @@
 			xt_params->exit_err(PARAMETER_PROBLEM,
 				"Port \"%s\" does not resolve to "
 				"anything.\n", arg);
-		if (entry->type == XTTYPE_PORTRC_NE)
+		if (entry->flags & XTOPT_NBO)
 			value = htons(value);
 		if (cb->nvals < ARRAY_SIZE(cb->val.port_range))
 			cb->val.port_range[cb->nvals] = value;
@@ -714,41 +791,12 @@
 	[XTTYPE_HOSTMASK]    = xtopt_parse_hostmask,
 	[XTTYPE_PROTOCOL]    = xtopt_parse_protocol,
 	[XTTYPE_PORT]        = xtopt_parse_port,
-	[XTTYPE_PORT_NE]     = xtopt_parse_port,
 	[XTTYPE_PORTRC]      = xtopt_parse_mport,
-	[XTTYPE_PORTRC_NE]   = xtopt_parse_mport,
 	[XTTYPE_PLEN]        = xtopt_parse_plen,
 	[XTTYPE_PLENMASK]    = xtopt_parse_plenmask,
 	[XTTYPE_ETHERMAC]    = xtopt_parse_ethermac,
 };
 
-static const size_t xtopt_psize[] = {
-	/*
-	 * All types not listed here, and thus essentially being initialized to
-	 * zero have zero on purpose.
-	 */
-	[XTTYPE_UINT8]       = sizeof(uint8_t),
-	[XTTYPE_UINT16]      = sizeof(uint16_t),
-	[XTTYPE_UINT32]      = sizeof(uint32_t),
-	[XTTYPE_UINT64]      = sizeof(uint64_t),
-	[XTTYPE_UINT8RC]     = sizeof(uint8_t[2]),
-	[XTTYPE_UINT16RC]    = sizeof(uint16_t[2]),
-	[XTTYPE_UINT32RC]    = sizeof(uint32_t[2]),
-	[XTTYPE_UINT64RC]    = sizeof(uint64_t[2]),
-	[XTTYPE_DOUBLE]      = sizeof(double),
-	[XTTYPE_STRING]      = -1,
-	[XTTYPE_SYSLOGLEVEL] = sizeof(uint8_t),
-	[XTTYPE_HOST]        = sizeof(union nf_inet_addr),
-	[XTTYPE_HOSTMASK]    = sizeof(union nf_inet_addr),
-	[XTTYPE_PROTOCOL]    = sizeof(uint8_t),
-	[XTTYPE_PORT]        = sizeof(uint16_t),
-	[XTTYPE_PORT_NE]     = sizeof(uint16_t),
-	[XTTYPE_PORTRC]      = sizeof(uint16_t[2]),
-	[XTTYPE_PORTRC_NE]   = sizeof(uint16_t[2]),
-	[XTTYPE_PLENMASK]    = sizeof(union nf_inet_addr),
-	[XTTYPE_ETHERMAC]    = sizeof(uint8_t[6]),
-};
-
 /**
  * The master option parsing routine. May be used for the ".x6_parse"
  * function pointer in extensions if fully automatic parsing is desired.
@@ -949,6 +997,9 @@
 			xt_params->exit_err(PARAMETER_PROBLEM,
 				"%s: option \"--%s\" must be specified\n",
 				name, entry->name);
+		if (!(xflags & (1 << entry->id)))
+			/* Not required, not specified, thus skip. */
+			continue;
 
 		for (i = 0; i < CHAR_BIT * sizeof(entry->id); ++i) {
 			if (entry->id == i)
diff --git a/libipq/Makefile.am b/libipq/Makefile.am
index 556a17b..93e5b1c 100644
--- a/libipq/Makefile.am
+++ b/libipq/Makefile.am
@@ -1,6 +1,7 @@
 # -*- Makefile -*-
 
-AM_CFLAGS = ${regular_CFLAGS} -I${top_builddir}/include -I${top_srcdir}/include
+AM_CFLAGS = ${regular_CFLAGS}
+AM_CPPFLAGS = ${regular_CPPFLAGS} -I${top_builddir}/include -I${top_srcdir}/include
 
 libipq_la_SOURCES = libipq.c
 lib_LTLIBRARIES   = libipq.la
diff --git a/libiptc/.gitignore b/libiptc/.gitignore
new file mode 100644
index 0000000..8767550
--- /dev/null
+++ b/libiptc/.gitignore
@@ -0,0 +1 @@
+/libiptc.pc
diff --git a/libiptc/Makefile.am b/libiptc/Makefile.am
new file mode 100644
index 0000000..22c920f
--- /dev/null
+++ b/libiptc/Makefile.am
@@ -0,0 +1,15 @@
+# -*- Makefile -*-
+
+AM_CFLAGS        = ${regular_CFLAGS}
+AM_CPPFLAGS      = ${regular_CPPFLAGS} -I${top_builddir}/include -I${top_srcdir}/include ${kinclude_CPPFLAGS}
+
+pkgconfig_DATA      = libiptc.pc
+
+lib_LTLIBRARIES     = libip4tc.la libip6tc.la libiptc.la
+libiptc_la_SOURCES  =
+libiptc_la_LIBADD   = libip4tc.la libip6tc.la
+libiptc_la_LDFLAGS  = -version-info 0:0:0 ${libiptc_LDFLAGS2}
+libip4tc_la_SOURCES = libip4tc.c
+libip4tc_la_LDFLAGS = -version-info 0:0:0
+libip6tc_la_SOURCES = libip6tc.c
+libip6tc_la_LDFLAGS = -version-info 0:0:0 ${libiptc_LDFLAGS2}
diff --git a/libiptc/libip4tc.c b/libiptc/libip4tc.c
index 221f276..e9e85c5 100644
--- a/libiptc/libip4tc.c
+++ b/libiptc/libip4tc.c
@@ -112,7 +112,7 @@
 #define LABEL_DROP		IPTC_LABEL_DROP
 #define LABEL_QUEUE		IPTC_LABEL_QUEUE
 
-#define ALIGN			IPT_ALIGN
+#define ALIGN			XT_ALIGN
 #define RETURN			IPT_RETURN
 
 #include "libiptc.c"
@@ -209,7 +209,7 @@
 	mptr = matchmask + sizeof(STRUCT_ENTRY);
 	if (IPT_MATCH_ITERATE(a, match_different, a->elems, b->elems, &mptr))
 		return NULL;
-	mptr += IPT_ALIGN(sizeof(struct ipt_entry_target));
+	mptr += XT_ALIGN(sizeof(struct ipt_entry_target));
 
 	return mptr;
 }
diff --git a/libiptc/libip6tc.c b/libiptc/libip6tc.c
index e557227..a97f397 100644
--- a/libiptc/libip6tc.c
+++ b/libiptc/libip6tc.c
@@ -107,7 +107,7 @@
 #define LABEL_DROP		IP6TC_LABEL_DROP
 #define LABEL_QUEUE		IP6TC_LABEL_QUEUE
 
-#define ALIGN			IP6T_ALIGN
+#define ALIGN			XT_ALIGN
 #define RETURN			IP6T_RETURN
 
 #include "libiptc.c"
@@ -241,7 +241,7 @@
 	mptr = matchmask + sizeof(STRUCT_ENTRY);
 	if (IP6T_MATCH_ITERATE(a, match_different, a->elems, b->elems, &mptr))
 		return NULL;
-	mptr += IP6T_ALIGN(sizeof(struct ip6t_entry_target));
+	mptr += XT_ALIGN(sizeof(struct ip6t_entry_target));
 
 	return mptr;
 }
diff --git a/libiptc/libiptc.c b/libiptc/libiptc.c
index d3b1c51..0b6d5e3 100644
--- a/libiptc/libiptc.c
+++ b/libiptc/libiptc.c
@@ -608,7 +608,7 @@
  */
 static int iptcc_chain_index_delete_chain(struct chain_head *c, struct xtc_handle *h)
 {
-	struct list_head *index_ptr, *index_ptr2, *next;
+	struct list_head *index_ptr, *next;
 	struct chain_head *c2;
 	unsigned int idx, idx2;
 
@@ -628,7 +628,7 @@
 		 * is located in the same index bucket.
 		 */
 		c2         = list_entry(next, struct chain_head, list);
-		index_ptr2 = iptcc_bsearch_chain_index(c2->name, &idx2, h);
+		iptcc_bsearch_chain_index(c2->name, &idx2, h);
 		if (idx != idx2) {
 			/* Rebuild needed */
 			return iptcc_chain_index_rebuild(h);
@@ -1279,11 +1279,8 @@
 static struct xtc_handle *
 alloc_handle(const char *tablename, unsigned int size, unsigned int num_rules)
 {
-	size_t len;
 	struct xtc_handle *h;
 
-	len = sizeof(STRUCT_TC_HANDLE) + size;
-
 	h = malloc(sizeof(STRUCT_TC_HANDLE));
 	if (!h) {
 		errno = ENOMEM;
diff --git a/libiptc.pc.in b/libiptc/libiptc.pc.in
similarity index 100%
rename from libiptc.pc.in
rename to libiptc/libiptc.pc.in
diff --git a/tests/options-ipv4.rules b/tests/options-ipv4.rules
new file mode 100644
index 0000000..b4adc92
--- /dev/null
+++ b/tests/options-ipv4.rules
@@ -0,0 +1,52 @@
+# Generated by iptables-save v1.4.10 on Mon Jan 31 03:03:38 2011
+*mangle
+:PREROUTING ACCEPT [2461:977932]
+:INPUT ACCEPT [2461:977932]
+:FORWARD ACCEPT [0:0]
+:OUTPUT ACCEPT [1740:367048]
+:POSTROUTING ACCEPT [1740:367048]
+
+# libipt_
+-A INPUT -p ah -m ah --ahspi 1
+-A INPUT -p ah -m ah --ahspi :2
+-A INPUT -p ah -m ah --ahspi 0:3
+-A INPUT -p ah -m ah --ahspi 4:
+-A INPUT -p ah -m ah --ahspi 5:4294967295
+
+-A FORWARD -p tcp -j ECN --ecn-tcp-remove
+-A FORWARD -j LOG --log-prefix "hi" --log-tcp-sequence --log-tcp-options --log-ip-options --log-uid --log-macdecode
+-A FORWARD -j TTL --ttl-inc 1
+-A FORWARD -j TTL --ttl-dec 1
+-A FORWARD -j TTL --ttl-set 1
+-A FORWARD -j ULOG --ulog-prefix "abc" --ulog-cprange 2 --ulog-qthreshold 2
+COMMIT
+# Completed on Mon Jan 31 03:03:38 2011
+# Generated by iptables-save v1.4.10 on Mon Jan 31 03:03:38 2011
+*nat
+:PREROUTING ACCEPT [0:0]
+:INPUT ACCEPT [0:0]
+:OUTPUT ACCEPT [0:0]
+:POSTROUTING ACCEPT [0:0]
+-A PREROUTING -d 1.2.3.4/32 -i lo -j CLUSTERIP --new --hashmode sourceip --clustermac 01:02:03:04:05:06 --total-nodes 9 --local-node 2 --hash-init 123456789
+-A PREROUTING -i dummy0 -j DNAT --to-destination 1.2.3.4 --random --persistent
+-A PREROUTING -i dummy0 -p tcp -j REDIRECT --to-ports 1-2 --random
+-A POSTROUTING -o dummy0 -p tcp -j MASQUERADE --to-ports 1-2 --random
+-A POSTROUTING -o dummy0 -p tcp -j NETMAP --to 1.0.0.0/8
+-A POSTROUTING -o dummy0 -p tcp -j SNAT --to-source 1.2.3.4-1.2.3.5 --random --persistent
+COMMIT
+# Completed on Mon Jan 31 03:03:38 2011
+# Generated by iptables-save v1.4.10 on Mon Jan 31 03:03:38 2011
+*filter
+:INPUT ACCEPT [76:13548]
+:FORWARD ACCEPT [0:0]
+:OUTPUT ACCEPT [59:11240]
+#-A INPUT -m addrtype --src-type UNICAST --dst-type UNICAST --limit-iface-in
+-A INPUT -p tcp -m ecn --ecn-tcp-ece --ecn-tcp-cwr --ecn-ip-ect 0
+-A INPUT -p tcp -m ecn --ecn-tcp-ece --ecn-tcp-cwr --ecn-ip-ect 1
+-A INPUT -p icmp -m icmp --icmp-type 5/0
+-A INPUT -p icmp -m icmp --icmp-type 5/1
+-A INPUT -p icmp -m icmp --icmp-type 5
+-A INPUT -m realm --realm 0x1 -m ttl --ttl-eq  64 -m ttl --ttl-lt  64 -m ttl --ttl-gt  64
+-A FORWARD -p tcp -j REJECT --reject-with tcp-reset
+COMMIT
+# Completed on Mon Jan 31 03:03:39 2011
diff --git a/tests/options-most.rules b/tests/options-most.rules
new file mode 100644
index 0000000..6c4a831
--- /dev/null
+++ b/tests/options-most.rules
@@ -0,0 +1,172 @@
+# Generated by ip6tables-save v1.4.10 on Mon Jan 31 02:19:53 2011
+*filter
+:INPUT ACCEPT [0:0]
+:FORWARD ACCEPT [0:0]
+:OUTPUT ACCEPT [0:0]
+:matches - -
+:ntarg - -
+:zmatches - -
+-A INPUT -j matches
+-A INPUT -m u32 --u32 "0x0=0x0&&0x0=0x1" -j ntarg
+-A INPUT -j zmatches
+-A INPUT -m conntrack --ctstate INVALID --ctproto 6 --ctorigsrc fe80::/64 --ctorigdst fe80::/64 --ctreplsrc fe80::/64 --ctrepldst fe80::/64 --ctorigsrcport 12 --ctorigdstport 13 --ctreplsrcport 14 --ctrepldstport 15 --ctstatus EXPECTED --ctexpire 1:2 --ctdir REPLY 
+-A INPUT -p tcp -m cluster --cluster-local-nodemask 0x00000001 --cluster-total-nodes 2 --cluster-hash-seed 0x00000001 -m cluster --cluster-local-nodemask 0x00000001 --cluster-total-nodes 2 --cluster-hash-seed 0x00000001 -m comment --comment foo -m connbytes --connbytes 1:2 --connbytes-mode packets --connbytes-dir both -m connlimit --connlimit-upto 1 --connlimit-mask 8 --connlimit-saddr -m connlimit --connlimit-above 1 --connlimit-mask 9 --connlimit-daddr -m connmark --mark 0x99 -m conntrack --ctstate INVALID --ctproto 6 --ctorigsrc fe80::/64 --ctorigdst fe80::/64 --ctreplsrc fe80::/64 --ctrepldst fe80::/64 --ctorigsrcport 12 --ctorigdstport 13 --ctreplsrcport 14 --ctrepldstport 15 --ctstatus EXPECTED --ctexpire 1:2 --ctdir REPLY -m cpu --cpu 2 -m dscp --dscp 0x04 -m dscp --dscp 0x00 -m hashlimit --hashlimit-upto 1/sec --hashlimit-burst 5 --hashlimit-mode srcip,dstip --hashlimit-name f1 --hashlimit-htable-size 64 --hashlimit-htable-max 128 --hashlimit-htable-gcinterval 60 --hashlimit-htable-expire 120 --hashlimit-srcmask 24 --hashlimit-dstmask 24 -m hashlimit --hashlimit-above 5/sec --hashlimit-burst 5 --hashlimit-name f1 -m helper --helper ftp -m iprange --src-range ::1-::2 --dst-range ::1-::2 -m ipvs --vaddr fe80::/64 --vport 1 --vdir REPLY --vmethod GATE --vportctl 21 -m length --length 1:2 -m limit --limit 1/sec -m mac --mac-source 01:02:03:04:05:06 -m mark --mark 0x1 -m physdev --physdev-in eth0 -m pkttype --pkt-type unicast -m policy --dir in --pol ipsec --strict --reqid 1 --spi 0x1 --proto esp --mode tunnel --tunnel-dst fe80::/64 --tunnel-src fe80::/64 --next --reqid 2 -m quota --quota 0 -m recent --rcheck --name DEFAULT --rsource -m socket --transparent -m string --string "foobar" --algo kmp --from 1 --to 2 --icase -m time --timestart 01:02:03 --timestop 03:04:05 --monthdays 1,2,3,4,5 --weekdays Mon,Fri,Sun --datestart 2001-02-03T04:05:06 --datestop 2012-09-08T09:06:05 --utc -m tos --tos 0xff/0x01 -m u32 --u32 "0x0=0x0" -m u32 --u32 "0x0=0x0" -m hbh -m hbh -m hl --hl-eq 1
+-A INPUT -m ipv6header --header hop-by-hop --soft
+-A INPUT -p tcp -m cluster --cluster-local-nodemask 0x00000001 --cluster-total-nodes 2 --cluster-hash-seed 0x00000001
+-A INPUT -p tcp -m cluster --cluster-local-nodemask 0x00000001 --cluster-total-nodes 2 --cluster-hash-seed 0x00000001
+-A INPUT -p tcp -m comment --comment foo
+-A INPUT -p tcp -m connbytes --connbytes 1:2 --connbytes-mode packets --connbytes-dir both
+-A INPUT -p tcp -m connlimit --connlimit-upto 1 --connlimit-mask 8 --connlimit-saddr
+-A INPUT -p tcp -m connlimit --connlimit-above 1 --connlimit-mask 9 --connlimit-daddr
+-A INPUT -p tcp -m connmark --mark 0x99
+-A INPUT -p tcp -m conntrack --ctstate INVALID --ctproto 6 --ctorigsrc fe80::/64 --ctorigdst fe80::/64 --ctreplsrc fe80::/64 --ctrepldst fe80::/64 --ctorigsrcport 12 --ctorigdstport 13 --ctreplsrcport 14 --ctrepldstport 15 --ctstatus EXPECTED --ctexpire 1:2 --ctdir REPLY
+-A INPUT -p tcp -m cpu --cpu 2
+-A INPUT -p tcp -m dscp --dscp 0x04
+-A INPUT -p tcp -m dscp --dscp 0x00
+-A INPUT -p tcp -m hashlimit --hashlimit-upto 1/sec --hashlimit-burst 5 --hashlimit-mode srcip,dstip --hashlimit-name f1 --hashlimit-htable-size 64 --hashlimit-htable-max 128 --hashlimit-htable-gcinterval 60 --hashlimit-htable-expire 120 --hashlimit-srcmask 24 --hashlimit-dstmask 24
+-A INPUT -p tcp -m hashlimit --hashlimit-above 5/sec --hashlimit-burst 5 --hashlimit-name f1
+-A INPUT -p tcp -m helper --helper ftp
+-A INPUT -p tcp -m iprange --src-range ::1-::2 --dst-range ::1-::2
+-A INPUT -p tcp -m length --length 1:2
+-A INPUT -p tcp -m limit --limit 1/sec
+-A INPUT -p tcp -m mac --mac-source 01:02:03:04:05:06
+-A INPUT -p tcp -m mark --mark 0x1
+-A INPUT -p tcp -m physdev --physdev-in eth0
+-A INPUT -p tcp -m pkttype --pkt-type unicast
+-A INPUT -p tcp -m policy --dir in --pol ipsec --strict --reqid 1 --spi 0x1 --proto esp --mode tunnel --tunnel-dst fe80::/64 --tunnel-src fe80::/64 --next --reqid 2
+-A INPUT -p tcp -m quota --quota 0
+-A INPUT -p tcp -m recent --rcheck --name DEFAULT --rsource
+-A INPUT -p tcp -m socket --transparent
+-A INPUT -p tcp -m string --string "foobar" --algo kmp --from 1 --to 2 --icase
+-A INPUT -p tcp -m tcp ! --tcp-flags FIN,SYN,RST,ACK SYN
+-A INPUT -p tcp -m tcp --tcp-flags FIN,SYN,RST,ACK SYN
+-A INPUT -p tcp -m tos --tos 0xff/0x01
+-A INPUT -p tcp -m u32 --u32 "0x0=0x0" -m u32 --u32 "0x0=0x0"
+-A INPUT -p tcp -m hbh -m hbh -m hl --hl-eq 1 -m ipv6header --header hop-by-hop --soft
+-A INPUT -m ipv6header --header hop-by-hop --soft -m rt --rt-type 2 --rt-segsleft 2 --rt-len 5 -m rt --rt-type 0 --rt-segsleft 2 --rt-len 5 --rt-0-res --rt-0-addrs ::1 --rt-0-not-strict -m rt --rt-type 0 --rt-segsleft 2 --rt-len 5 --rt-0-res --rt-0-addrs ::1,::2 --rt-0-not-strict
+-A INPUT -p tcp -m cpu --cpu 1 -m tcp --sport 1:2 --dport 1:2 --tcp-option 1 --tcp-flags FIN,SYN,RST,ACK SYN -m cpu --cpu 1
+-A INPUT -p dccp -m cpu --cpu 1 -m dccp --sport 1:2 --dport 3:4 -m cpu --cpu 1
+-A INPUT -p udp -m cpu --cpu 1 -m udp --sport 1:2 --dport 3:4 -m cpu --cpu 1
+-A INPUT -p sctp -m cpu --cpu 1 -m sctp --sport 1:2 --dport 3:4 --chunk-types all INIT,SACK -m cpu --cpu 1
+-A INPUT -p esp -m esp --espspi 1:2
+-A INPUT -p tcp -m multiport --dports 1,2 -m multiport --dports 1,2
+-A INPUT -p tcp -m tcpmss --mss 1:2 -m tcp --tcp-flags FIN,SYN,RST,ACK SYN
+-A INPUT -p ipv6-icmp -m icmp6 --icmpv6-type 4/0
+-A INPUT
+-A INPUT -p mobility
+-A INPUT -p mobility -m mh --mh-type 3
+-A OUTPUT -m owner --socket-exists --uid-owner 1-2 --gid-owner 2-3
+-A matches -m connbytes --connbytes 1 --connbytes-mode bytes --connbytes-dir both
+-A matches
+-A matches -m connbytes --connbytes :2 --connbytes-mode bytes --connbytes-dir both
+-A matches
+-A matches -m connbytes --connbytes 0:3 --connbytes-mode bytes --connbytes-dir both
+-A matches
+-A matches -m connbytes --connbytes 4: --connbytes-mode bytes --connbytes-dir both
+-A matches
+-A matches -m connbytes --connbytes 5:18446744073709551615 --connbytes-mode bytes --connbytes-dir both
+-A matches
+-A matches -m conntrack --ctexpire 1
+-A matches
+-A matches -m conntrack --ctexpire :2
+-A matches
+-A matches -m conntrack --ctexpire 0:3
+-A matches
+-A matches -m conntrack --ctexpire 4:
+-A matches
+-A matches -m conntrack --ctexpire 5:4294967295
+-A matches
+-A matches -p esp -m esp --espspi 1
+-A matches
+-A matches -p esp -m esp --espspi :2
+-A matches
+-A matches -p esp -m esp --espspi 0:3
+-A matches
+-A matches -p esp -m esp --espspi 4:
+-A matches
+-A matches -p esp -m esp --espspi 5:4294967295
+-A matches
+-A matches -m ipvs --vaddr fe80::/64 --vport 1 --vdir REPLY --vmethod GATE --vportctl 21
+-A matches
+-A matches -m length --length 1
+-A matches
+-A matches -m length --length :2
+-A matches
+-A matches -m length --length 0:3
+-A matches
+-A matches -m length --length 4:
+-A matches
+-A matches -m length --length 5:65535
+-A matches
+-A matches -p tcp -m tcpmss --mss 1
+-A matches
+-A matches -p tcp -m tcpmss --mss :2
+-A matches
+-A matches -p tcp -m tcpmss --mss 0:3
+-A matches
+-A matches -p tcp -m tcpmss --mss 4:
+-A matches
+-A matches -p tcp -m tcpmss --mss 5:65535
+-A matches
+-A matches -m time --timestart 01:02:03 --timestop 04:05:06 --monthdays 1,2,3,4,5 --weekdays Mon,Fri,Sun --datestart 2001-02-03T04:05:06 --datestop 2012-09-08T09:06:05 --localtz
+-A matches
+-A matches -m time --timestart 01:02:03 --timestop 04:05:06 --monthdays 1,2,3,4,5 --weekdays Mon,Fri,Sun --datestart 2001-02-03T04:05:06 --datestop 2012-09-08T09:06:05 --kerneltz
+-A matches
+-A matches -m time --timestart 01:02:03 --timestop 04:05:06 --monthdays 1,2,3,4,5 --weekdays Mon,Fri,Sun --datestart 2001-02-03T04:05:06 --datestop 2012-09-08T09:06:05
+-A matches
+-A matches -m time --timestart 02:00:00 --timestop 03:00:00 --datestart 1970-01-01T02:00:00 --datestop 1970-01-01T03:00:00
+-A matches
+-A matches -m ah --ahspi 1
+-A matches
+-A matches -m ah --ahspi :2
+-A matches
+-A matches -m ah --ahspi 0:3
+-A matches
+-A matches -m ah --ahspi 4:
+-A matches
+-A matches -m ah --ahspi 5:4294967295
+-A matches
+-A matches -m frag --fragid 1
+-A matches
+-A matches -m frag --fragid :2
+-A matches
+-A matches -m frag --fragid 0:3
+-A matches
+-A matches -m frag --fragid 4:
+-A matches
+-A matches -m frag --fragid 5:4294967295
+-A matches
+-A matches -m rt --rt-segsleft 1
+-A matches
+-A matches -m rt --rt-segsleft :2
+-A matches
+-A matches -m rt --rt-segsleft 0:3
+-A matches
+-A matches -m rt --rt-segsleft 4:
+-A matches
+-A matches -m rt --rt-segsleft 5:4294967295
+-A matches
+-A ntarg -j NFQUEUE --queue-num 1
+-A ntarg
+-A ntarg -j NFQUEUE --queue-balance 8:99
+-A ntarg
+-A ntarg -j RATEEST --rateest-name RE1 --rateest-interval 250.0ms --rateest-ewmalog 500.0ms
+-A ntarg
+-A ntarg -j RATEEST --rateest-name RE2 --rateest-interval 250.0ms --rateest-ewmalog 500.0ms
+-A ntarg
+#-A zmatches -m rateest --rateest RE1 --rateest-lt --rateest-bps 8bit
+#-A zmatches -m rateest --rateest RE1 --rateest-eq --rateest-bps 8bit
+#-A zmatches -m rateest --rateest RE1 --rateest-gt --rateest-bps 8bit
+#-A zmatches -m rateest --rateest RE1 --rateest-lt --rateest-pps 5
+#-A zmatches -m rateest --rateest RE1 --rateest-eq --rateest-pps 5
+#-A zmatches -m rateest --rateest RE1 --rateest-gt --rateest-pps 5
+#-A zmatches -m rateest --rateest-delta --rateest RE1 --rateest-bps1 8bit --rateest-lt --rateest-bps2 16bit
+#-A zmatches -m rateest --rateest1 RE1 --rateest-lt --rateest2 RE2 --bytes
+#-A zmatches -m rateest --rateest1 RE1 --rateest-lt --rateest2 RE2 --packets
+#-A zmatches -m rateest --rateest-delta --rateest RE1 --rateest-bps1 8bit --rateest-eq --rateest-bps2 16bit
+#-A zmatches -m rateest --rateest-delta --rateest RE1 --rateest-bps1 8bit --rateest-gt --rateest-bps2 16bit
+#-A zmatches -m rateest --rateest-delta --rateest RE1 --rateest-pps1 8 --rateest-lt --rateest-pps2 9
+#-A zmatches -m rateest --rateest-delta --rateest RE1 --rateest-pps1 8 --rateest-eq --rateest-pps2 9
+#-A zmatches -m rateest --rateest-delta --rateest RE1 --rateest-pps1 8 --rateest-gt --rateest-pps2 9
+COMMIT
+# Completed on Mon Jan 31 02:19:54 2011
diff --git a/utils/Makefile.am b/utils/Makefile.am
index 79ce34b..306d993 100644
--- a/utils/Makefile.am
+++ b/utils/Makefile.am
@@ -1,6 +1,7 @@
 # -*- Makefile -*-
 
-AM_CFLAGS = ${regular_CFLAGS} -I${top_builddir}/include -I${top_srcdir}/include
+AM_CFLAGS = ${regular_CFLAGS}
+AM_CPPFLAGS = ${regular_CPPFLAGS} -I${top_builddir}/include -I${top_srcdir}/include
 
 sbin_PROGRAMS = nfnl_osf
 pkgdata_DATA = pf.os