diff --git a/SOURCES/iptables-1.4.21-configure_set_lock_file_path.patch b/SOURCES/iptables-1.4.21-configure_set_lock_file_path.patch
new file mode 100644
index 0000000..4132f96
--- /dev/null
+++ b/SOURCES/iptables-1.4.21-configure_set_lock_file_path.patch
@@ -0,0 +1,97 @@
+Adapted version of
+
+commit b91af533f4da15854893ba5cc082e1df6bcf9a97
+Author: Lorenzo Colitti <lorenzo@google.com>
+Date:   Tue Mar 14 17:55:50 2017 +0900
+
+    iptables: set the path of the lock file via a configure option.
+    
+    Currently the iptables lock is hardcoded as "/run/xtables.lock".
+    Allow users to change this path using the --with-xt-lock-name
+    option to ./configure option. This is useful on systems like
+    Android which do not have /run.
+    
+    Tested on Ubuntu, as follows:
+    
+    1. By default, the lock is placed in /run/xtables.lock:
+    
+    $ make distclean-recursive && ./autogen.sh &&
+      ./configure --disable-nftables --prefix /tmp/iptables &&
+      make -j64 &&
+      make install &&
+      sudo strace -e open,flock /tmp/iptables/sbin/iptables -L foo
+    ...
+    open("/run/xtables.lock", O_RDONLY|O_CREAT, 0600) = 3
+    flock(3, LOCK_EX|LOCK_NB)               = 0
+    iptables: No chain/target/match by that name.
+    
+    2. Specifying the lock results in the expected location being
+       used:
+    
+    $ make distclean-recursive && ./autogen.sh && \
+      ./configure --disable-nftables --prefix /tmp/iptables \
+      --with-xt-lock-name=/tmp/iptables/run/xtables.lock &&
+      make -j64 &&
+      make install &&
+      sudo strace -e open,flock /tmp/iptables/sbin/iptables -L foo
+    ...
+    open("/tmp/iptables/run/xtables.lock", O_RDONLY|O_CREAT, 0600) = 3
+    flock(3, LOCK_EX|LOCK_NB)               = 0
+    iptables: No chain/target/match by that name.
+    
+    Signed-off-by: Lorenzo Colitti <lorenzo@google.com>
+    Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
+
+diff -up iptables-1.4.21/configure.ac.configure_set_lock_file_path iptables-1.4.21/configure.ac
+--- iptables-1.4.21/configure.ac.configure_set_lock_file_path	2013-11-22 12:18:13.000000000 +0100
++++ iptables-1.4.21/configure.ac	2017-04-05 14:47:17.308782472 +0200
+@@ -60,6 +60,10 @@ AC_ARG_ENABLE([nfsynproxy],
+ AC_ARG_WITH([pkgconfigdir], AS_HELP_STRING([--with-pkgconfigdir=PATH],
+ 	[Path to the pkgconfig directory [[LIBDIR/pkgconfig]]]),
+ 	[pkgconfigdir="$withval"], [pkgconfigdir='${libdir}/pkgconfig'])
++AC_ARG_WITH([xt-lock-name], AS_HELP_STRING([--with-xt-lock-name=PATH],
++	[Path to the xtables lock [[/run/xtables.lock]]]),
++	[xt_lock_name="$withval"],
++	[xt_lock_name="/run/xtables.lock"])
+ 
+ libiptc_LDFLAGS2="";
+ AX_CHECK_LINKER_FLAGS([-Wl,--no-as-needed],
+@@ -118,7 +122,7 @@ AM_CONDITIONAL([HAVE_LIBNFNETLINK], [tes
+ regular_CFLAGS="-Wall -Waggregate-return -Wmissing-declarations \
+ 	-Wmissing-prototypes -Wredundant-decls -Wshadow -Wstrict-prototypes \
+ 	-Winline -pipe";
+-regular_CPPFLAGS="${largefile_cppflags} -D_REENTRANT \
++regular_CPPFLAGS="${largefile_cppflags} -DXT_LOCK_NAME=\\\"\${xt_lock_name}\\\" -D_REENTRANT \
+ 	-DXTABLES_LIBDIR=\\\"\${xtlibdir}\\\" -DXTABLES_INTERNAL";
+ kinclude_CPPFLAGS="";
+ if [[ -n "$kbuilddir" ]]; then
+@@ -156,6 +160,7 @@ AC_SUBST([libxtables_vcurrent])
+ AC_SUBST([libxtables_vage])
+ libxtables_vmajor=$(($libxtables_vcurrent - $libxtables_vage));
+ AC_SUBST([libxtables_vmajor])
++AC_SUBST([xt_lock_name])
+ 
+ AC_CONFIG_FILES([Makefile extensions/GNUmakefile include/Makefile
+ 	iptables/Makefile iptables/xtables.pc
+@@ -188,7 +193,8 @@ Build parameters:
+   Support plugins via dlopen (shared):	${enable_shared}
+   Installation prefix (--prefix):	${prefix}
+   Xtables extension directory:		${e_xtlibdir}
+-  Pkg-config directory:			${e_pkgconfigdir}"
++  Pkg-config directory:			${e_pkgconfigdir}
++  Xtables lock file:			${xt_lock_name}"
+ 
+ if [[ -n "$ksourcedir" ]]; then
+ 	echo "  Kernel source directory:		${ksourcedir}"
+diff -up iptables-1.4.21/iptables/xshared.c.configure_set_lock_file_path iptables-1.4.21/iptables/xshared.c
+--- iptables-1.4.21/iptables/xshared.c.configure_set_lock_file_path	2017-04-05 14:46:47.861540910 +0200
++++ iptables-1.4.21/iptables/xshared.c	2017-04-05 14:46:47.863540927 +0200
+@@ -17,8 +17,6 @@
+ #include <math.h>
+ #include "xshared.h"
+ 
+-#define XT_LOCK_NAME	"/run/xtables.lock"
+-
+ /*
+  * Print out any special helps. A user might like to be able to add a --help
+  * to the commandline, and see expected results. So we call help for all
diff --git a/SOURCES/iptables-1.4.21-move_XT_LOCK_NAME_to_config.h.patch b/SOURCES/iptables-1.4.21-move_XT_LOCK_NAME_to_config.h.patch
new file mode 100644
index 0000000..07836ca
--- /dev/null
+++ b/SOURCES/iptables-1.4.21-move_XT_LOCK_NAME_to_config.h.patch
@@ -0,0 +1,67 @@
+Adapted version of
+
+commit 836846f0d747e1be8e37d2d43b215a68b30ea1a9
+Author: Lorenzo Colitti <lorenzo@google.com>
+Date:   Thu Mar 16 12:54:20 2017 +0900
+
+    iptables: move XT_LOCK_NAME from CFLAGS to config.h.
+    
+    This slightly simplifies configure.ac and results in more
+    correct dependencies.
+    
+    Tested by running ./configure with --with-xt-lock-name and
+    without, and using strace to verify that the right lock is used.
+    
+    $ make distclean-recursive && ./autogen.sh &&
+      ./configure --disable-nftables --prefix /tmp/iptables &&
+      make -j64 &&
+      make install &&
+      sudo strace -e open,flock /tmp/iptables/sbin/iptables -L foo
+    ...
+    open("/run/xtables.lock", O_RDONLY|O_CREAT, 0600) = 3
+    flock(3, LOCK_EX|LOCK_NB)               = 0
+    
+    $ make distclean-recursive && ./autogen.sh && \
+      ./configure --disable-nftables --prefix /tmp/iptables \
+      --with-xt-lock-name=/tmp/iptables/run/xtables.lock &&
+      make -j64 &&
+      make install &&
+      sudo strace -e open,flock /tmp/iptables/sbin/iptables -L foo
+    ...
+    open("/tmp/iptables/run/xtables.lock", O_RDONLY|O_CREAT, 0600) = 3
+    flock(3, LOCK_EX|LOCK_NB)               = 0
+    
+    Signed-off-by: Lorenzo Colitti <lorenzo@google.com>
+    Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
+
+diff -up iptables-1.4.21/configure.ac.move_XT_LOCK_NAME_to_config.h iptables-1.4.21/configure.ac
+--- iptables-1.4.21/configure.ac.move_XT_LOCK_NAME_to_config.h	2017-04-05 14:48:11.855229929 +0200
++++ iptables-1.4.21/configure.ac	2017-04-05 14:48:11.856229937 +0200
+@@ -122,7 +122,7 @@ AM_CONDITIONAL([HAVE_LIBNFNETLINK], [tes
+ regular_CFLAGS="-Wall -Waggregate-return -Wmissing-declarations \
+ 	-Wmissing-prototypes -Wredundant-decls -Wshadow -Wstrict-prototypes \
+ 	-Winline -pipe";
+-regular_CPPFLAGS="${largefile_cppflags} -DXT_LOCK_NAME=\\\"\${xt_lock_name}\\\" -D_REENTRANT \
++regular_CPPFLAGS="${largefile_cppflags} -D_REENTRANT \
+ 	-DXTABLES_LIBDIR=\\\"\${xtlibdir}\\\" -DXTABLES_INTERNAL";
+ kinclude_CPPFLAGS="";
+ if [[ -n "$kbuilddir" ]]; then
+@@ -160,7 +160,9 @@ AC_SUBST([libxtables_vcurrent])
+ AC_SUBST([libxtables_vage])
+ libxtables_vmajor=$(($libxtables_vcurrent - $libxtables_vage));
+ AC_SUBST([libxtables_vmajor])
+-AC_SUBST([xt_lock_name])
++
++AC_DEFINE_UNQUOTED([XT_LOCK_NAME], "${xt_lock_name}",
++	[Location of the iptables lock file])
+ 
+ AC_CONFIG_FILES([Makefile extensions/GNUmakefile include/Makefile
+ 	iptables/Makefile iptables/xtables.pc
+diff -up iptables-1.4.21/iptables/xshared.c.move_XT_LOCK_NAME_to_config.h iptables-1.4.21/iptables/xshared.c
+--- iptables-1.4.21/iptables/xshared.c.move_XT_LOCK_NAME_to_config.h	2017-04-05 14:48:11.855229929 +0200
++++ iptables-1.4.21/iptables/xshared.c	2017-04-05 14:48:11.856229937 +0200
+@@ -1,3 +1,4 @@
++#include <config.h>
+ #include <getopt.h>
+ #include <errno.h>
+ #include <libgen.h>
diff --git a/SOURCES/iptables-1.4.21-remove_duplicated_argument_parsing.patch b/SOURCES/iptables-1.4.21-remove_duplicated_argument_parsing.patch
new file mode 100644
index 0000000..a0fe335
--- /dev/null
+++ b/SOURCES/iptables-1.4.21-remove_duplicated_argument_parsing.patch
@@ -0,0 +1,401 @@
+Adapted version of
+
+commit 6e2e169eb66b63d2991e1c7ada931e3cdb0ced32
+Author: Lorenzo Colitti <lorenzo@google.com>
+Date:   Thu Mar 16 16:55:01 2017 +0900
+
+    iptables: remove duplicated argument parsing code
+    
+    1. Factor out repeated code to a new xs_has_arg function.
+    2. Add a new parse_wait_time option to parse the value of -w.
+    3. Make parse_wait_interval take argc and argv so its callers
+       can be simpler.
+    
+    Signed-off-by: Lorenzo Colitti <lorenzo@google.com>
+    Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
+
+diff -up iptables-1.4.21/iptables/ip6tables.c.remove_duplicated_argument_parsing iptables-1.4.21/iptables/ip6tables.c
+--- iptables-1.4.21/iptables/ip6tables.c.remove_duplicated_argument_parsing	2017-04-05 14:51:44.033970476 +0200
++++ iptables-1.4.21/iptables/ip6tables.c	2017-04-05 14:51:44.044970566 +0200
+@@ -1388,8 +1388,7 @@ int do_command6(int argc, char *argv[],
+ 			add_command(&command, CMD_DELETE, CMD_NONE,
+ 				    cs.invert);
+ 			chain = optarg;
+-			if (optind < argc && argv[optind][0] != '-'
+-			    && argv[optind][0] != '!') {
++			if (xs_has_arg(argc, argv)) {
+ 				rulenum = parse_rulenumber(argv[optind++]);
+ 				command = CMD_DELETE_NUM;
+ 			}
+@@ -1399,8 +1398,7 @@ int do_command6(int argc, char *argv[],
+ 			add_command(&command, CMD_REPLACE, CMD_NONE,
+ 				    cs.invert);
+ 			chain = optarg;
+-			if (optind < argc && argv[optind][0] != '-'
+-			    && argv[optind][0] != '!')
++			if (xs_has_arg(argc, argv))
+ 				rulenum = parse_rulenumber(argv[optind++]);
+ 			else
+ 				xtables_error(PARAMETER_PROBLEM,
+@@ -1412,8 +1410,7 @@ int do_command6(int argc, char *argv[],
+ 			add_command(&command, CMD_INSERT, CMD_NONE,
+ 				    cs.invert);
+ 			chain = optarg;
+-			if (optind < argc && argv[optind][0] != '-'
+-			    && argv[optind][0] != '!')
++			if (xs_has_arg(argc, argv))
+ 				rulenum = parse_rulenumber(argv[optind++]);
+ 			else rulenum = 1;
+ 			break;
+@@ -1422,11 +1419,9 @@ int do_command6(int argc, char *argv[],
+ 			add_command(&command, CMD_LIST,
+ 				    CMD_ZERO | CMD_ZERO_NUM, cs.invert);
+ 			if (optarg) chain = optarg;
+-			else if (optind < argc && argv[optind][0] != '-'
+-				 && argv[optind][0] != '!')
++			else if (xs_has_arg(argc, argv))
+ 				chain = argv[optind++];
+-			if (optind < argc && argv[optind][0] != '-'
+-			    && argv[optind][0] != '!')
++			if (xs_has_arg(argc, argv))
+ 				rulenum = parse_rulenumber(argv[optind++]);
+ 			break;
+ 
+@@ -1434,11 +1429,9 @@ int do_command6(int argc, char *argv[],
+ 			add_command(&command, CMD_LIST_RULES,
+ 				    CMD_ZERO | CMD_ZERO_NUM, cs.invert);
+ 			if (optarg) chain = optarg;
+-			else if (optind < argc && argv[optind][0] != '-'
+-				 && argv[optind][0] != '!')
++			else if (xs_has_arg(argc, argv))
+ 				chain = argv[optind++];
+-			if (optind < argc && argv[optind][0] != '-'
+-			    && argv[optind][0] != '!')
++			if (xs_has_arg(argc, argv))
+ 				rulenum = parse_rulenumber(argv[optind++]);
+ 			break;
+ 
+@@ -1446,8 +1439,7 @@ int do_command6(int argc, char *argv[],
+ 			add_command(&command, CMD_FLUSH, CMD_NONE,
+ 				    cs.invert);
+ 			if (optarg) chain = optarg;
+-			else if (optind < argc && argv[optind][0] != '-'
+-				 && argv[optind][0] != '!')
++			else if (xs_has_arg(argc, argv))
+ 				chain = argv[optind++];
+ 			break;
+ 
+@@ -1455,11 +1447,9 @@ int do_command6(int argc, char *argv[],
+ 			add_command(&command, CMD_ZERO, CMD_LIST|CMD_LIST_RULES,
+ 				    cs.invert);
+ 			if (optarg) chain = optarg;
+-			else if (optind < argc && argv[optind][0] != '-'
+-				&& argv[optind][0] != '!')
++			else if (xs_has_arg(argc, argv))
+ 				chain = argv[optind++];
+-			if (optind < argc && argv[optind][0] != '-'
+-				&& argv[optind][0] != '!') {
++			if (xs_has_arg(argc, argv)) {
+ 				rulenum = parse_rulenumber(argv[optind++]);
+ 				command = CMD_ZERO_NUM;
+ 			}
+@@ -1476,8 +1466,7 @@ int do_command6(int argc, char *argv[],
+ 			add_command(&command, CMD_DELETE_CHAIN, CMD_NONE,
+ 				    cs.invert);
+ 			if (optarg) chain = optarg;
+-			else if (optind < argc && argv[optind][0] != '-'
+-				 && argv[optind][0] != '!')
++			else if (xs_has_arg(argc, argv))
+ 				chain = argv[optind++];
+ 			break;
+ 
+@@ -1485,8 +1474,7 @@ int do_command6(int argc, char *argv[],
+ 			add_command(&command, CMD_RENAME_CHAIN, CMD_NONE,
+ 				    cs.invert);
+ 			chain = optarg;
+-			if (optind < argc && argv[optind][0] != '-'
+-			    && argv[optind][0] != '!')
++			if (xs_has_arg(argc, argv))
+ 				newname = argv[optind++];
+ 			else
+ 				xtables_error(PARAMETER_PROBLEM,
+@@ -1499,8 +1487,7 @@ int do_command6(int argc, char *argv[],
+ 			add_command(&command, CMD_SET_POLICY, CMD_NONE,
+ 				    cs.invert);
+ 			chain = optarg;
+-			if (optind < argc && argv[optind][0] != '-'
+-			    && argv[optind][0] != '!')
++			if (xs_has_arg(argc, argv))
+ 				policy = argv[optind++];
+ 			else
+ 				xtables_error(PARAMETER_PROBLEM,
+@@ -1610,16 +1597,7 @@ int do_command6(int argc, char *argv[],
+ 					      "You cannot use `-w' from "
+ 					      "ip6tables-restore");
+ 			}
+-			wait = -1;
+-			if (optarg) {
+-				if (sscanf(optarg, "%i", &wait) != 1)
+-					xtables_error(PARAMETER_PROBLEM,
+-						"wait seconds not numeric");
+-			} else if (optind < argc && argv[optind][0] != '-'
+-						 && argv[optind][0] != '!')
+-				if (sscanf(argv[optind++], "%i", &wait) != 1)
+-					xtables_error(PARAMETER_PROBLEM,
+-						"wait seconds not numeric");
++			wait = parse_wait_time(argc, argv);
+ 			break;
+ 
+ 		case 'W':
+@@ -1628,14 +1606,7 @@ int do_command6(int argc, char *argv[],
+ 					      "You cannot use `-W' from "
+ 					      "ip6tables-restore");
+ 			}
+-			if (optarg)
+-				parse_wait_interval(optarg, &wait_interval);
+-			else if (optind < argc &&
+-				argv[optind][0] != '-' &&
+-				argv[optind][0] != '!')
+-				parse_wait_interval(argv[optind++],
+-						    &wait_interval);
+-
++			parse_wait_interval(argc, argv, &wait_interval);
+ 			wait_interval_set = true;
+ 			break;
+ 
+@@ -1685,8 +1656,7 @@ int do_command6(int argc, char *argv[],
+ 			bcnt = strchr(pcnt + 1, ',');
+ 			if (bcnt)
+ 			    bcnt++;
+-			if (!bcnt && optind < argc && argv[optind][0] != '-'
+-			    && argv[optind][0] != '!')
++			if (!bcnt && xs_has_arg(argc, argv))
+ 				bcnt = argv[optind++];
+ 			if (!bcnt)
+ 				xtables_error(PARAMETER_PROBLEM,
+diff -up iptables-1.4.21/iptables/iptables.c.remove_duplicated_argument_parsing iptables-1.4.21/iptables/iptables.c
+--- iptables-1.4.21/iptables/iptables.c.remove_duplicated_argument_parsing	2017-04-05 14:51:44.034970484 +0200
++++ iptables-1.4.21/iptables/iptables.c	2017-04-05 14:51:44.044970566 +0200
+@@ -1381,8 +1381,7 @@ int do_command4(int argc, char *argv[],
+ 			add_command(&command, CMD_DELETE, CMD_NONE,
+ 				    cs.invert);
+ 			chain = optarg;
+-			if (optind < argc && argv[optind][0] != '-'
+-			    && argv[optind][0] != '!') {
++			if (xs_has_arg(argc, argv)) {
+ 				rulenum = parse_rulenumber(argv[optind++]);
+ 				command = CMD_DELETE_NUM;
+ 			}
+@@ -1392,8 +1391,7 @@ int do_command4(int argc, char *argv[],
+ 			add_command(&command, CMD_REPLACE, CMD_NONE,
+ 				    cs.invert);
+ 			chain = optarg;
+-			if (optind < argc && argv[optind][0] != '-'
+-			    && argv[optind][0] != '!')
++			if (xs_has_arg(argc, argv))
+ 				rulenum = parse_rulenumber(argv[optind++]);
+ 			else
+ 				xtables_error(PARAMETER_PROBLEM,
+@@ -1405,8 +1403,7 @@ int do_command4(int argc, char *argv[],
+ 			add_command(&command, CMD_INSERT, CMD_NONE,
+ 				    cs.invert);
+ 			chain = optarg;
+-			if (optind < argc && argv[optind][0] != '-'
+-			    && argv[optind][0] != '!')
++			if (xs_has_arg(argc, argv))
+ 				rulenum = parse_rulenumber(argv[optind++]);
+ 			else rulenum = 1;
+ 			break;
+@@ -1415,11 +1412,9 @@ int do_command4(int argc, char *argv[],
+ 			add_command(&command, CMD_LIST,
+ 				    CMD_ZERO | CMD_ZERO_NUM, cs.invert);
+ 			if (optarg) chain = optarg;
+-			else if (optind < argc && argv[optind][0] != '-'
+-				 && argv[optind][0] != '!')
++			else if (xs_has_arg(argc, argv))
+ 				chain = argv[optind++];
+-			if (optind < argc && argv[optind][0] != '-'
+-			    && argv[optind][0] != '!')
++			if (xs_has_arg(argc, argv))
+ 				rulenum = parse_rulenumber(argv[optind++]);
+ 			break;
+ 
+@@ -1427,11 +1422,9 @@ int do_command4(int argc, char *argv[],
+ 			add_command(&command, CMD_LIST_RULES,
+ 				    CMD_ZERO|CMD_ZERO_NUM, cs.invert);
+ 			if (optarg) chain = optarg;
+-			else if (optind < argc && argv[optind][0] != '-'
+-				 && argv[optind][0] != '!')
++			else if (xs_has_arg(argc, argv))
+ 				chain = argv[optind++];
+-			if (optind < argc && argv[optind][0] != '-'
+-			    && argv[optind][0] != '!')
++			if (xs_has_arg(argc, argv))
+ 				rulenum = parse_rulenumber(argv[optind++]);
+ 			break;
+ 
+@@ -1439,8 +1432,7 @@ int do_command4(int argc, char *argv[],
+ 			add_command(&command, CMD_FLUSH, CMD_NONE,
+ 				    cs.invert);
+ 			if (optarg) chain = optarg;
+-			else if (optind < argc && argv[optind][0] != '-'
+-				 && argv[optind][0] != '!')
++			else if (xs_has_arg(argc, argv))
+ 				chain = argv[optind++];
+ 			break;
+ 
+@@ -1448,11 +1440,9 @@ int do_command4(int argc, char *argv[],
+ 			add_command(&command, CMD_ZERO, CMD_LIST|CMD_LIST_RULES,
+ 				    cs.invert);
+ 			if (optarg) chain = optarg;
+-			else if (optind < argc && argv[optind][0] != '-'
+-				&& argv[optind][0] != '!')
++			else if (xs_has_arg(argc, argv))
+ 				chain = argv[optind++];
+-			if (optind < argc && argv[optind][0] != '-'
+-				&& argv[optind][0] != '!') {
++			if (xs_has_arg(argc, argv)) {
+ 				rulenum = parse_rulenumber(argv[optind++]);
+ 				command = CMD_ZERO_NUM;
+ 			}
+@@ -1469,8 +1459,7 @@ int do_command4(int argc, char *argv[],
+ 			add_command(&command, CMD_DELETE_CHAIN, CMD_NONE,
+ 				    cs.invert);
+ 			if (optarg) chain = optarg;
+-			else if (optind < argc && argv[optind][0] != '-'
+-				 && argv[optind][0] != '!')
++			else if (xs_has_arg(argc, argv))
+ 				chain = argv[optind++];
+ 			break;
+ 
+@@ -1478,8 +1467,7 @@ int do_command4(int argc, char *argv[],
+ 			add_command(&command, CMD_RENAME_CHAIN, CMD_NONE,
+ 				    cs.invert);
+ 			chain = optarg;
+-			if (optind < argc && argv[optind][0] != '-'
+-			    && argv[optind][0] != '!')
++			if (xs_has_arg(argc, argv))
+ 				newname = argv[optind++];
+ 			else
+ 				xtables_error(PARAMETER_PROBLEM,
+@@ -1492,8 +1480,7 @@ int do_command4(int argc, char *argv[],
+ 			add_command(&command, CMD_SET_POLICY, CMD_NONE,
+ 				    cs.invert);
+ 			chain = optarg;
+-			if (optind < argc && argv[optind][0] != '-'
+-			    && argv[optind][0] != '!')
++			if (xs_has_arg(argc, argv))
+ 				policy = argv[optind++];
+ 			else
+ 				xtables_error(PARAMETER_PROBLEM,
+@@ -1601,16 +1588,7 @@ int do_command4(int argc, char *argv[],
+ 					      "You cannot use `-w' from "
+ 					      "iptables-restore");
+ 			}
+-			wait = -1;
+-			if (optarg) {
+-				if (sscanf(optarg, "%i", &wait) != 1)
+-					xtables_error(PARAMETER_PROBLEM,
+-						"wait seconds not numeric");
+-			} else if (optind < argc && argv[optind][0] != '-'
+-						 && argv[optind][0] != '!')
+-				if (sscanf(argv[optind++], "%i", &wait) != 1)
+-					xtables_error(PARAMETER_PROBLEM,
+-						"wait seconds not numeric");
++			wait = parse_wait_time(argc, argv);
+ 			break;
+ 
+ 		case 'W':
+@@ -1619,14 +1597,7 @@ int do_command4(int argc, char *argv[],
+ 					      "You cannot use `-W' from "
+ 					      "iptables-restore");
+ 			}
+-			if (optarg)
+-				parse_wait_interval(optarg, &wait_interval);
+-			else if (optind < argc &&
+-				 argv[optind][0] != '-' &&
+-				 argv[optind][0] != '!')
+-				parse_wait_interval(argv[optind++],
+-						    &wait_interval);
+-
++			parse_wait_interval(argc, argv, &wait_interval);
+ 			wait_interval_set = true;
+ 			break;
+ 
+@@ -1676,8 +1647,7 @@ int do_command4(int argc, char *argv[],
+ 			bcnt = strchr(pcnt + 1, ',');
+ 			if (bcnt)
+ 			    bcnt++;
+-			if (!bcnt && optind < argc && argv[optind][0] != '-'
+-			    && argv[optind][0] != '!')
++			if (!bcnt && xs_has_arg(argc, argv))
+ 				bcnt = argv[optind++];
+ 			if (!bcnt)
+ 				xtables_error(PARAMETER_PROBLEM,
+diff -up iptables-1.4.21/iptables/xshared.c.remove_duplicated_argument_parsing iptables-1.4.21/iptables/xshared.c
+--- iptables-1.4.21/iptables/xshared.c.remove_duplicated_argument_parsing	2017-04-05 14:51:44.042970550 +0200
++++ iptables-1.4.21/iptables/xshared.c	2017-04-05 14:51:44.045970574 +0200
+@@ -285,12 +285,36 @@ bool xtables_lock(int wait, struct timev
+ 	}
+ }
+ 
+-void parse_wait_interval(const char *str, struct timeval *wait_interval)
++int parse_wait_time(int argc, char *argv[])
+ {
++	int wait = -1;
++
++	if (optarg) {
++		if (sscanf(optarg, "%i", &wait) != 1)
++			xtables_error(PARAMETER_PROBLEM,
++				"wait seconds not numeric");
++	} else if (xs_has_arg(argc, argv))
++		if (sscanf(argv[optind++], "%i", &wait) != 1)
++			xtables_error(PARAMETER_PROBLEM,
++				"wait seconds not numeric");
++
++	return wait;
++}
++
++void parse_wait_interval(int argc, char *argv[], struct timeval *wait_interval)
++{
++	const char *arg;
+ 	unsigned int usec;
+ 	int ret;
+ 
+-	ret = sscanf(str, "%u", &usec);
++	if (optarg)
++		arg = optarg;
++	else if (xs_has_arg(argc, argv))
++		arg = argv[optind++];
++	else
++		return;
++
++	ret = sscanf(arg, "%u", &usec);
+ 	if (ret == 1) {
+ 		if (usec > 999999)
+ 			xtables_error(PARAMETER_PROBLEM,
+@@ -303,3 +327,10 @@ void parse_wait_interval(const char *str
+ 	}
+ 	xtables_error(PARAMETER_PROBLEM, "wait interval not numeric");
+ }
++
++inline bool xs_has_arg(int argc, char *argv[])
++{
++	return optind < argc &&
++	       argv[optind][0] != '-' &&
++	       argv[optind][0] != '!';
++}
+diff -up iptables-1.4.21/iptables/xshared.h.remove_duplicated_argument_parsing iptables-1.4.21/iptables/xshared.h
+--- iptables-1.4.21/iptables/xshared.h.remove_duplicated_argument_parsing	2017-04-05 14:51:44.034970484 +0200
++++ iptables-1.4.21/iptables/xshared.h	2017-04-05 14:51:44.045970574 +0200
+@@ -86,7 +86,9 @@ extern void xs_init_target(struct xtable
+ extern void xs_init_match(struct xtables_match *);
+ bool xtables_lock(int wait, struct timeval *wait_interval);
+ 
+-void parse_wait_interval(const char *str, struct timeval *wait_interval);
++int parse_wait_time(int argc, char *argv[]);
++void parse_wait_interval(int argc, char *argv[], struct timeval *wait_interval);
++bool xs_has_arg(int argc, char *argv[]);
+ 
+ extern const struct xtables_afinfo *afinfo;
+ 
diff --git a/SOURCES/iptables-1.4.21-restore_support_acquiring_the_lock.patch b/SOURCES/iptables-1.4.21-restore_support_acquiring_the_lock.patch
new file mode 100644
index 0000000..77e1aff
--- /dev/null
+++ b/SOURCES/iptables-1.4.21-restore_support_acquiring_the_lock.patch
@@ -0,0 +1,414 @@
+Adapted version of
+
+commit 999eaa241212d3952ddff39a99d0d55a74e3639e
+Author: Lorenzo Colitti <lorenzo@google.com>
+Date:   Thu Mar 16 16:55:02 2017 +0900
+
+    iptables-restore: support acquiring the lock.
+    
+    Currently, ip[6]tables-restore does not perform any locking, so it
+    is not safe to use concurrently with ip[6]tables.
+    
+    This patch makes ip[6]tables-restore wait for the lock if -w
+    was specified. Arguments to -w and -W are supported in the same
+    was as they are in ip[6]tables.
+    
+    The lock is not acquired on startup. Instead, it is acquired when
+    a new table handle is created (on encountering '*') and released
+    when the table is committed (COMMIT). This makes it possible to
+    keep long-running iptables-restore processes in the background
+    (for example, reading commands from a pipe opened by a system
+    management daemon) and simultaneously run iptables commands.
+    
+    If -w is not specified, then the command proceeds without taking
+    the lock.
+    
+    Tested as follows:
+    
+    1. Run iptables-restore -w, and check that iptables commands work
+       with or without -w.
+    2. Type "*filter" into the iptables-restore input. Verify that
+       a) ip[6]tables commands without -w fail with "another app is
+          currently holding the xtables lock...".
+       b) ip[6]tables commands with "-w 2" fail after 2 seconds.
+       c) ip[6]tables commands with "-w" hang until "COMMIT" is
+          typed into the iptables-restore window.
+    3. With the lock held by an ip6tables-restore process:
+         strace -e flock /tmp/iptables/sbin/iptables-restore -w 1 -W 100000
+       shows 11 calls to flock and fails.
+    4. Run an iptables-restore with -w and one without -w, and check:
+       a) Type "*filter" in the first and then the second, and the
+          second exits with an error.
+       b) Type "*filter" in the second and "*filter" "-S" "COMMIT"
+          into the first. The rules are listed only when the first
+          copy sees "COMMIT".
+    
+    Signed-off-by: Narayan Kamath <narayan@google.com>
+    Signed-off-by: Lorenzo Colitti <lorenzo@google.com>
+    Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
+
+diff -up iptables-1.4.21/iptables/ip6tables.c.restore_support_acquiring_the_lock iptables-1.4.21/iptables/ip6tables.c
+--- iptables-1.4.21/iptables/ip6tables.c.restore_support_acquiring_the_lock	2017-04-05 14:55:52.561008864 +0200
++++ iptables-1.4.21/iptables/ip6tables.c	2017-04-05 14:55:52.564008888 +0200
+@@ -1767,7 +1767,7 @@ int do_command6(int argc, char *argv[],
+ 	generic_opt_check(command, cs.options);
+ 
+ 	/* Attempt to acquire the xtables lock */
+-	if (!restore && !xtables_lock(wait, &wait_interval)) {
++	if (!restore && xtables_lock(wait, &wait_interval) == XT_LOCK_BUSY) {
+ 		fprintf(stderr, "Another app is currently holding the xtables lock. ");
+ 		if (wait == 0)
+ 			fprintf(stderr, "Perhaps you want to use the -w option?\n");
+diff -up iptables-1.4.21/iptables/ip6tables-restore.c.restore_support_acquiring_the_lock iptables-1.4.21/iptables/ip6tables-restore.c
+--- iptables-1.4.21/iptables/ip6tables-restore.c.restore_support_acquiring_the_lock	2013-11-22 12:18:13.000000000 +0100
++++ iptables-1.4.21/iptables/ip6tables-restore.c	2017-04-05 14:58:41.513393942 +0200
+@@ -15,6 +15,7 @@
+ #include <stdio.h>
+ #include <stdlib.h>
+ #include "ip6tables.h"
++#include "xshared.h"
+ #include "xtables.h"
+ #include "libiptc/libip6tc.h"
+ #include "ip6tables-multi.h"
+@@ -25,18 +26,24 @@
+ #define DEBUGP(x, args...)
+ #endif
+ 
+-static int binary = 0, counters = 0, verbose = 0, noflush = 0;
++static int binary = 0, counters = 0, verbose = 0, noflush = 0, wait = 0;
++
++static struct timeval wait_interval = {
++	.tv_sec	= 1,
++};
+ 
+ /* Keeping track of external matches and targets.  */
+ static const struct option options[] = {
+-	{.name = "binary",   .has_arg = false, .val = 'b'},
+-	{.name = "counters", .has_arg = false, .val = 'c'},
+-	{.name = "verbose",  .has_arg = false, .val = 'v'},
+-	{.name = "test",     .has_arg = false, .val = 't'},
+-	{.name = "help",     .has_arg = false, .val = 'h'},
+-	{.name = "noflush",  .has_arg = false, .val = 'n'},
+-	{.name = "modprobe", .has_arg = true,  .val = 'M'},
+-	{.name = "table",    .has_arg = true,  .val = 'T'},
++	{.name = "binary",        .has_arg = 0, .val = 'b'},
++	{.name = "counters",      .has_arg = 0, .val = 'c'},
++	{.name = "verbose",       .has_arg = 0, .val = 'v'},
++	{.name = "test",          .has_arg = 0, .val = 't'},
++	{.name = "help",          .has_arg = 0, .val = 'h'},
++	{.name = "noflush",       .has_arg = 0, .val = 'n'},
++	{.name = "modprobe",      .has_arg = 1, .val = 'M'},
++	{.name = "table",         .has_arg = 1, .val = 'T'},
++	{.name = "wait",          .has_arg = 2, .val = 'w'},
++	{.name = "wait-interval", .has_arg = 2, .val = 'W'},
+ 	{NULL},
+ };
+ 
+@@ -44,14 +51,16 @@ static void print_usage(const char *name
+ 
+ static void print_usage(const char *name, const char *version)
+ {
+-	fprintf(stderr, "Usage: %s [-b] [-c] [-v] [-t] [-h]\n"
++	fprintf(stderr, "Usage: %s [-b] [-c] [-v] [-t] [-h] [-w secs] [-W usecs]\n"
+ 			"	   [ --binary ]\n"
+ 			"	   [ --counters ]\n"
+ 			"	   [ --verbose ]\n"
+ 			"	   [ --test ]\n"
+ 			"	   [ --help ]\n"
++			"	   [ --wait=<seconds>\n"
++			"	   [ --wait-interval=<usecs>\n"
+ 			"	   [ --noflush ]\n"
+-			"          [ --modprobe=<command>]\n", name);
++			"	   [ --modprobe=<command>]\n", name);
+ 
+ 	exit(1);
+ }
+@@ -182,7 +191,7 @@ int ip6tables_restore_main(int argc, cha
+ {
+ 	struct xtc_handle *handle = NULL;
+ 	char buffer[10240];
+-	int c;
++	int c, lock;
+ 	char curtable[XT_TABLE_MAXNAMELEN + 1];
+ 	FILE *in;
+ 	int in_table = 0, testing = 0;
+@@ -190,6 +199,7 @@ int ip6tables_restore_main(int argc, cha
+ 	const struct xtc_ops *ops = &ip6tc_ops;
+ 
+ 	line = 0;
++	lock = XT_LOCK_NOT_ACQUIRED;
+ 
+ 	ip6tables_globals.program_name = "ip6tables-restore";
+ 	c = xtables_init_all(&ip6tables_globals, NFPROTO_IPV6);
+@@ -204,7 +214,7 @@ int ip6tables_restore_main(int argc, cha
+ 	init_extensions6();
+ #endif
+ 
+-	while ((c = getopt_long(argc, argv, "bcvthnM:T:", options, NULL)) != -1) {
++	while ((c = getopt_long(argc, argv, "bcvthnwWM:T:", options, NULL)) != -1) {
+ 		switch (c) {
+ 			case 'b':
+ 				binary = 1;
+@@ -225,6 +235,12 @@ int ip6tables_restore_main(int argc, cha
+ 			case 'n':
+ 				noflush = 1;
+ 				break;
++			case 'w':
++				wait = parse_wait_time(argc, argv);
++				break;
++			case 'W':
++				parse_wait_interval(argc, argv, &wait_interval);
++				break;
+ 			case 'M':
+ 				xtables_modprobe_program = optarg;
+ 				break;
+@@ -269,8 +285,23 @@ int ip6tables_restore_main(int argc, cha
+ 				DEBUGP("Not calling commit, testing\n");
+ 				ret = 1;
+ 			}
++
++			/* Done with the current table, release the lock. */
++			if (lock >= 0) {
++				xtables_unlock(lock);
++				lock = XT_LOCK_NOT_ACQUIRED;
++			}
++
+ 			in_table = 0;
+ 		} else if ((buffer[0] == '*') && (!in_table)) {
++			/* Acquire a lock before we create a new table handle */
++			lock = xtables_lock(wait, &wait_interval);
++			if (lock == XT_LOCK_BUSY) {
++				fprintf(stderr, "Another app is currently holding the xtables lock. "
++					"Perhaps you want to use the -w option?\n");
++				exit(RESOURCE_PROBLEM);
++			}
++
+ 			/* New table */
+ 			char *table;
+ 
+diff -up iptables-1.4.21/iptables/iptables.c.restore_support_acquiring_the_lock iptables-1.4.21/iptables/iptables.c
+--- iptables-1.4.21/iptables/iptables.c.restore_support_acquiring_the_lock	2017-04-05 14:55:52.562008872 +0200
++++ iptables-1.4.21/iptables/iptables.c	2017-04-05 14:55:52.564008888 +0200
+@@ -1754,7 +1754,7 @@ int do_command4(int argc, char *argv[],
+ 	generic_opt_check(command, cs.options);
+ 
+ 	/* Attempt to acquire the xtables lock */
+-	if (!restore && !xtables_lock(wait, &wait_interval)) {
++	if (!restore && xtables_lock(wait, &wait_interval) == XT_LOCK_BUSY) {
+ 		fprintf(stderr, "Another app is currently holding the xtables lock. ");
+ 		if (wait == 0)
+ 			fprintf(stderr, "Perhaps you want to use the -w option?\n");
+diff -up iptables-1.4.21/iptables/iptables-restore.c.restore_support_acquiring_the_lock iptables-1.4.21/iptables/iptables-restore.c
+--- iptables-1.4.21/iptables/iptables-restore.c.restore_support_acquiring_the_lock	2013-11-22 12:18:13.000000000 +0100
++++ iptables-1.4.21/iptables/iptables-restore.c	2017-04-05 15:00:17.389179935 +0200
+@@ -12,6 +12,7 @@
+ #include <stdio.h>
+ #include <stdlib.h>
+ #include "iptables.h"
++#include "xshared.h"
+ #include "xtables.h"
+ #include "libiptc/libiptc.h"
+ #include "iptables-multi.h"
+@@ -22,18 +23,24 @@
+ #define DEBUGP(x, args...)
+ #endif
+ 
+-static int binary = 0, counters = 0, verbose = 0, noflush = 0;
++static int binary = 0, counters = 0, verbose = 0, noflush = 0, wait = 0;
++
++static struct timeval wait_interval = {
++	.tv_sec	= 1,
++};
+ 
+ /* Keeping track of external matches and targets.  */
+ static const struct option options[] = {
+-	{.name = "binary",   .has_arg = false, .val = 'b'},
+-	{.name = "counters", .has_arg = false, .val = 'c'},
+-	{.name = "verbose",  .has_arg = false, .val = 'v'},
+-	{.name = "test",     .has_arg = false, .val = 't'},
+-	{.name = "help",     .has_arg = false, .val = 'h'},
+-	{.name = "noflush",  .has_arg = false, .val = 'n'},
+-	{.name = "modprobe", .has_arg = true,  .val = 'M'},
+-	{.name = "table",    .has_arg = true,  .val = 'T'},
++	{.name = "binary",        .has_arg = 0, .val = 'b'},
++	{.name = "counters",      .has_arg = 0, .val = 'c'},
++	{.name = "verbose",       .has_arg = 0, .val = 'v'},
++	{.name = "test",          .has_arg = 0, .val = 't'},
++	{.name = "help",          .has_arg = 0, .val = 'h'},
++	{.name = "noflush",       .has_arg = 0, .val = 'n'},
++	{.name = "modprobe",      .has_arg = 1, .val = 'M'},
++	{.name = "table",         .has_arg = 1, .val = 'T'},
++	{.name = "wait",          .has_arg = 2, .val = 'w'},
++	{.name = "wait-interval", .has_arg = 2, .val = 'W'},
+ 	{NULL},
+ };
+ 
+@@ -43,15 +50,17 @@ static void print_usage(const char *name
+ 
+ static void print_usage(const char *name, const char *version)
+ {
+-	fprintf(stderr, "Usage: %s [-b] [-c] [-v] [-t] [-h]\n"
++	fprintf(stderr, "Usage: %s [-b] [-c] [-v] [-t] [-h] [-W usecs]\n"
+ 			"	   [ --binary ]\n"
+ 			"	   [ --counters ]\n"
+ 			"	   [ --verbose ]\n"
+ 			"	   [ --test ]\n"
+ 			"	   [ --help ]\n"
+ 			"	   [ --noflush ]\n"
++			"	   [ --wait=<seconds>\n"
++			"	   [ --wait-interval=<usecs>\n"
+ 			"	   [ --table=<TABLE> ]\n"
+-			"          [ --modprobe=<command>]\n", name);
++			"	   [ --modprobe=<command>]\n", name);
+ 
+ 	exit(1);
+ }
+@@ -182,7 +191,7 @@ iptables_restore_main(int argc, char *ar
+ {
+ 	struct xtc_handle *handle = NULL;
+ 	char buffer[10240];
+-	int c;
++	int c, lock;
+ 	char curtable[XT_TABLE_MAXNAMELEN + 1];
+ 	FILE *in;
+ 	int in_table = 0, testing = 0;
+@@ -190,6 +199,7 @@ iptables_restore_main(int argc, char *ar
+ 	const struct xtc_ops *ops = &iptc_ops;
+ 
+ 	line = 0;
++	lock = XT_LOCK_NOT_ACQUIRED;
+ 
+ 	iptables_globals.program_name = "iptables-restore";
+ 	c = xtables_init_all(&iptables_globals, NFPROTO_IPV4);
+@@ -204,7 +214,7 @@ iptables_restore_main(int argc, char *ar
+ 	init_extensions4();
+ #endif
+ 
+-	while ((c = getopt_long(argc, argv, "bcvthnM:T:", options, NULL)) != -1) {
++	while ((c = getopt_long(argc, argv, "bcvthnwWM:T:", options, NULL)) != -1) {
+ 		switch (c) {
+ 			case 'b':
+ 				binary = 1;
+@@ -225,6 +235,12 @@ iptables_restore_main(int argc, char *ar
+ 			case 'n':
+ 				noflush = 1;
+ 				break;
++			case 'w':
++				wait = parse_wait_time(argc, argv);
++				break;
++			case 'W':
++				parse_wait_interval(argc, argv, &wait_interval);
++				break;
+ 			case 'M':
+ 				xtables_modprobe_program = optarg;
+ 				break;
+@@ -269,8 +285,23 @@ iptables_restore_main(int argc, char *ar
+ 				DEBUGP("Not calling commit, testing\n");
+ 				ret = 1;
+ 			}
++
++			/* Done with the current table, release the lock. */
++			if (lock >= 0) {
++				xtables_unlock(lock);
++				lock = XT_LOCK_NOT_ACQUIRED;
++			}
++
+ 			in_table = 0;
+ 		} else if ((buffer[0] == '*') && (!in_table)) {
++			/* Acquire a lock before we create a new table handle */
++			lock = xtables_lock(wait, &wait_interval);
++			if (lock == XT_LOCK_BUSY) {
++				fprintf(stderr, "Another app is currently holding the xtables lock. "
++					"Perhaps you want to use the -w option?\n");
++				exit(RESOURCE_PROBLEM);
++			}
++
+ 			/* New table */
+ 			char *table;
+ 
+diff -up iptables-1.4.21/iptables/xshared.c.restore_support_acquiring_the_lock iptables-1.4.21/iptables/xshared.c
+--- iptables-1.4.21/iptables/xshared.c.restore_support_acquiring_the_lock	2017-04-05 14:55:52.562008872 +0200
++++ iptables-1.4.21/iptables/xshared.c	2017-04-05 14:55:52.565008896 +0200
+@@ -246,7 +246,7 @@ void xs_init_match(struct xtables_match
+ 		match->init(match->m);
+ }
+ 
+-bool xtables_lock(int wait, struct timeval *wait_interval)
++int xtables_lock(int wait, struct timeval *wait_interval)
+ {
+ 	struct timeval time_left, wait_time;
+ 	int fd, i = 0;
+@@ -256,22 +256,22 @@ bool xtables_lock(int wait, struct timev
+ 
+ 	fd = open(XT_LOCK_NAME, O_CREAT, 0600);
+ 	if (fd < 0)
+-		return true;
++		return XT_LOCK_UNSUPPORTED;
+ 
+ 	if (wait == -1) {
+ 		if (flock(fd, LOCK_EX) == 0)
+-			return true;
++			return fd;
+ 
+ 		fprintf(stderr, "Can't lock %s: %s\n", XT_LOCK_NAME,
+ 			strerror(errno));
+-		return false;
++		return XT_LOCK_BUSY;
+ 	}
+ 
+ 	while (1) {
+ 		if (flock(fd, LOCK_EX | LOCK_NB) == 0)
+-			return true;
++			return fd;
+ 		else if (timercmp(&time_left, wait_interval, <))
+-			return false;
++			return XT_LOCK_BUSY;
+ 
+ 		if (++i % 10 == 0) {
+ 			fprintf(stderr, "Another app is currently holding the xtables lock; "
+@@ -285,6 +285,12 @@ bool xtables_lock(int wait, struct timev
+ 	}
+ }
+ 
++void xtables_unlock(int lock)
++{
++	if (lock >= 0)
++		close(lock);
++}
++
+ int parse_wait_time(int argc, char *argv[])
+ {
+ 	int wait = -1;
+diff -up iptables-1.4.21/iptables/xshared.h.restore_support_acquiring_the_lock iptables-1.4.21/iptables/xshared.h
+--- iptables-1.4.21/iptables/xshared.h.restore_support_acquiring_the_lock	2017-04-05 14:55:52.562008872 +0200
++++ iptables-1.4.21/iptables/xshared.h	2017-04-05 14:55:52.565008896 +0200
+@@ -84,7 +84,28 @@ extern struct xtables_match *load_proto(
+ extern int subcmd_main(int, char **, const struct subcommand *);
+ extern void xs_init_target(struct xtables_target *);
+ extern void xs_init_match(struct xtables_match *);
+-bool xtables_lock(int wait, struct timeval *wait_interval);
++
++/**
++ * Values for the iptables lock.
++ *
++ * A value >= 0 indicates the lock filedescriptor. Other values are:
++ *
++ * XT_LOCK_UNSUPPORTED : The system does not support locking, execution will
++ * proceed lockless.
++ *
++ * XT_LOCK_BUSY : The lock was held by another process. xtables_lock only
++ * returns this value when |wait| == false. If |wait| == true, xtables_lock
++ * will not return unless the lock has been acquired.
++ *
++ * XT_LOCK_NOT_ACQUIRED : We have not yet attempted to acquire the lock.
++ */
++enum {
++	XT_LOCK_BUSY = -1,
++	XT_LOCK_UNSUPPORTED  = -2,
++	XT_LOCK_NOT_ACQUIRED  = -3,
++};
++extern int xtables_lock(int wait, struct timeval *tv);
++extern void xtables_unlock(int lock);
+ 
+ int parse_wait_time(int argc, char *argv[]);
+ void parse_wait_interval(int argc, char *argv[], struct timeval *wait_interval);
diff --git a/SOURCES/iptables-1.4.21-restore_version.patch b/SOURCES/iptables-1.4.21-restore_version.patch
new file mode 100644
index 0000000..bee5903
--- /dev/null
+++ b/SOURCES/iptables-1.4.21-restore_version.patch
@@ -0,0 +1,143 @@
+Adapted version of
+
+commit 9cd3adbed2fd8cdb6366293f3799573b811be89b
+Author: Dan Williams <dcbw@redhat.com>
+Date:   Mon Apr 10 12:31:56 2017 -0500
+
+    iptables-restore/ip6tables-restore: add --version/-V argument
+    
+    Prints program version just like iptables/ip6tables.
+    
+    Signed-off-by: Dan Williams <dcbw@redhat.com>
+    Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
+
+diff -up iptables-1.4.21/iptables/ip6tables-restore.c.restore_version iptables-1.4.21/iptables/ip6tables-restore.c
+--- iptables-1.4.21/iptables/ip6tables-restore.c.restore_version	2017-04-20 16:49:34.253130005 +0200
++++ iptables-1.4.21/iptables/ip6tables-restore.c	2017-04-20 16:51:43.931089903 +0200
+@@ -37,6 +37,7 @@ static const struct option options[] = {
+ 	{.name = "binary",        .has_arg = 0, .val = 'b'},
+ 	{.name = "counters",      .has_arg = 0, .val = 'c'},
+ 	{.name = "verbose",       .has_arg = 0, .val = 'v'},
++	{.name = "version",       .has_arg = 0, .val = 'V'},
+ 	{.name = "test",          .has_arg = 0, .val = 't'},
+ 	{.name = "help",          .has_arg = 0, .val = 'h'},
+ 	{.name = "noflush",       .has_arg = 0, .val = 'n'},
+@@ -49,12 +50,16 @@ static const struct option options[] = {
+ 
+ static void print_usage(const char *name, const char *version) __attribute__((noreturn));
+ 
++#define prog_name ip6tables_globals.program_name
++#define prog_vers ip6tables_globals.program_version
++
+ static void print_usage(const char *name, const char *version)
+ {
+-	fprintf(stderr, "Usage: %s [-b] [-c] [-v] [-t] [-h] [-w secs] [-W usecs]\n"
++	fprintf(stderr, "Usage: %s [-b] [-c] [-v] [-V] [-t] [-h] [-w secs] [-W usecs]\n"
+ 			"	   [ --binary ]\n"
+ 			"	   [ --counters ]\n"
+ 			"	   [ --verbose ]\n"
++			"	   [ --version]\n"
+ 			"	   [ --test ]\n"
+ 			"	   [ --help ]\n"
+ 			"	   [ --wait=<seconds>\n"
+@@ -79,8 +84,7 @@ static struct xtc_handle *create_handle(
+ 
+ 	if (!handle) {
+ 		xtables_error(PARAMETER_PROBLEM, "%s: unable to initialize "
+-			"table '%s'\n", ip6tables_globals.program_name,
+-			tablename);
++			"table '%s'\n", prog_name, tablename);
+ 		exit(1);
+ 	}
+ 	return handle;
+@@ -214,7 +218,7 @@ int ip6tables_restore_main(int argc, cha
+ 	init_extensions6();
+ #endif
+ 
+-	while ((c = getopt_long(argc, argv, "bcvthnwWM:T:", options, NULL)) != -1) {
++	while ((c = getopt_long(argc, argv, "bcvVthnwWM:T:", options, NULL)) != -1) {
+ 		switch (c) {
+ 			case 'b':
+ 				binary = 1;
+@@ -225,6 +229,9 @@ int ip6tables_restore_main(int argc, cha
+ 			case 'v':
+ 				verbose = 1;
+ 				break;
++			case 'V':
++				printf("%s v%s\n", prog_name, prog_vers);
++				exit(0);
+ 			case 't':
+ 				testing = 1;
+ 				break;
+diff -up iptables-1.4.21/iptables/iptables-restore.8.in.restore_version iptables-1.4.21/iptables/iptables-restore.8.in
+--- iptables-1.4.21/iptables/iptables-restore.8.in.restore_version	2013-11-22 12:18:13.000000000 +0100
++++ iptables-1.4.21/iptables/iptables-restore.8.in	2017-04-20 16:52:20.883299806 +0200
+@@ -23,9 +23,9 @@ iptables-restore \(em Restore IP Tables
+ .P
+ ip6tables-restore \(em Restore IPv6 Tables
+ .SH SYNOPSIS
+-\fBiptables\-restore\fP [\fB\-chntv\fP] [\fB\-M\fP \fImodprobe\fP]
++\fBiptables\-restore\fP [\fB\-chntvV\fP] [\fB\-M\fP \fImodprobe\fP]
+ .P
+-\fBip6tables\-restore\fP [\fB\-chntv\fP] [\fB\-M\fP \fImodprobe\fP]
++\fBip6tables\-restore\fP [\fB\-chntvV\fP] [\fB\-M\fP \fImodprobe\fP]
+ [\fB\-T\fP \fIname\fP]
+ .SH DESCRIPTION
+ .PP
+@@ -51,6 +51,9 @@ Only parse and construct the ruleset, bu
+ \fB\-v\fP, \fB\-\-verbose\fP
+ Print additional debug info during ruleset processing.
+ .TP
++\fB\-V\fP, \fB\-\-version\fP
++Print the program version number.
++.TP
+ \fB\-M\fP, \fB\-\-modprobe\fP \fImodprobe_program\fP
+ Specify the path to the modprobe program. By default, iptables-restore will
+ inspect /proc/sys/kernel/modprobe to determine the executable's path.
+diff -up iptables-1.4.21/iptables/iptables-restore.c.restore_version iptables-1.4.21/iptables/iptables-restore.c
+--- iptables-1.4.21/iptables/iptables-restore.c.restore_version	2017-04-20 16:49:34.253130005 +0200
++++ iptables-1.4.21/iptables/iptables-restore.c	2017-04-20 17:29:32.495390523 +0200
+@@ -34,6 +34,7 @@ static const struct option options[] = {
+ 	{.name = "binary",        .has_arg = 0, .val = 'b'},
+ 	{.name = "counters",      .has_arg = 0, .val = 'c'},
+ 	{.name = "verbose",       .has_arg = 0, .val = 'v'},
++	{.name = "version",       .has_arg = 0, .val = 'V'},
+ 	{.name = "test",          .has_arg = 0, .val = 't'},
+ 	{.name = "help",          .has_arg = 0, .val = 'h'},
+ 	{.name = "noflush",       .has_arg = 0, .val = 'n'},
+@@ -47,13 +48,15 @@ static const struct option options[] = {
+ static void print_usage(const char *name, const char *version) __attribute__((noreturn));
+ 
+ #define prog_name iptables_globals.program_name
++#define prog_vers iptables_globals.program_version
+ 
+ static void print_usage(const char *name, const char *version)
+ {
+-	fprintf(stderr, "Usage: %s [-b] [-c] [-v] [-t] [-h] [-W usecs]\n"
++	fprintf(stderr, "Usage: %s [-b] [-c] [-v] [-V]  [-t] [-h] [-W usecs]\n"
+ 			"	   [ --binary ]\n"
+ 			"	   [ --counters ]\n"
+ 			"	   [ --verbose ]\n"
++			"	   [ --version]\n"
+ 			"	   [ --test ]\n"
+ 			"	   [ --help ]\n"
+ 			"	   [ --noflush ]\n"
+@@ -214,7 +217,7 @@ iptables_restore_main(int argc, char *ar
+ 	init_extensions4();
+ #endif
+ 
+-	while ((c = getopt_long(argc, argv, "bcvthnwWM:T:", options, NULL)) != -1) {
++	while ((c = getopt_long(argc, argv, "bcvVthnwWM:T:", options, NULL)) != -1) {
+ 		switch (c) {
+ 			case 'b':
+ 				binary = 1;
+@@ -225,6 +228,9 @@ iptables_restore_main(int argc, char *ar
+ 			case 'v':
+ 				verbose = 1;
+ 				break;
++			case 'V':
++				printf("%s v%s\n", prog_name, prog_vers);
++				exit(0);
+ 			case 't':
+ 				testing = 1;
+ 				break;
diff --git a/SOURCES/iptables-1.4.21-restore_wait_man.patch b/SOURCES/iptables-1.4.21-restore_wait_man.patch
new file mode 100644
index 0000000..4d3b3df
--- /dev/null
+++ b/SOURCES/iptables-1.4.21-restore_wait_man.patch
@@ -0,0 +1,51 @@
+Adapted version of
+
+commit 65801d02a482befd2745c792d6596ec75d434934
+Author: Dan Williams <dcbw@redhat.com>
+Date:   Mon Apr 10 12:35:18 2017 -0500
+
+    iptables-restore.8: document -w/-W options
+    
+    Fixes: 999eaa241212 ("iptables-restore: support acquiring the lock.")
+    Signed-off-by: Dan Williams <dcbw@redhat.com>
+    Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
+
+diff -up iptables-1.4.21/iptables/iptables-restore.8.in.restore_wait_man iptables-1.4.21/iptables/iptables-restore.8.in
+--- iptables-1.4.21/iptables/iptables-restore.8.in.restore_wait_man	2017-04-20 17:33:23.386401192 +0200
++++ iptables-1.4.21/iptables/iptables-restore.8.in	2017-04-20 17:35:13.562713997 +0200
+@@ -23,9 +23,11 @@ iptables-restore \(em Restore IP Tables
+ .P
+ ip6tables-restore \(em Restore IPv6 Tables
+ .SH SYNOPSIS
+-\fBiptables\-restore\fP [\fB\-chntvV\fP] [\fB\-M\fP \fImodprobe\fP]
++\fBiptables\-restore\fP [\fB\-chntvV\fP] [\fB\-w\fP \fIsecs\fP]
+++[\fB\-W\fP \fIusecs\fP] [\fB\-M\fP \fImodprobe\fP]
+ .P
+-\fBip6tables\-restore\fP [\fB\-chntvV\fP] [\fB\-M\fP \fImodprobe\fP]
++\fBip6tables\-restore\fP [\fB\-chntvV\fP] [\fB\-w\fP \fIsecs\fP]
+++[\fB\-W\fP \fIusecs\fP] [\fB\-M\fP \fImodprobe\fP]
+ [\fB\-T\fP \fIname\fP]
+ .SH DESCRIPTION
+ .PP
+@@ -54,6 +56,21 @@ Print additional debug info during rules
+ \fB\-V\fP, \fB\-\-version\fP
+ Print the program version number.
+ .TP
++\fB\-w\fP, \fB\-\-wait\fP [\fIseconds\fP]
++Wait for the xtables lock.
++To prevent multiple instances of the program from running concurrently,
++an attempt will be made to obtain an exclusive lock at launch.  By default,
++the program will exit if the lock cannot be obtained.  This option will
++make the program wait (indefinitely or for optional \fIseconds\fP) until
++the exclusive lock can be obtained.
++.TP
++\fB\-W\fP, \fB\-\-wait-interval\fP \fImicroseconds\fP
++Interval to wait per each iteration.
++When running latency sensitive applications, waiting for the xtables lock
++for extended durations may not be acceptable. This option will make each
++iteration take the amount of time specified. The default interval is
++1 second. This option only works with \fB\-w\fP.
++.TP
+ \fB\-M\fP, \fB\-\-modprobe\fP \fImodprobe_program\fP
+ Specify the path to the modprobe program. By default, iptables-restore will
+ inspect /proc/sys/kernel/modprobe to determine the executable's path.
diff --git a/SOURCES/iptables-1.4.21-wait-interval.patch b/SOURCES/iptables-1.4.21-wait-interval.patch
new file mode 100644
index 0000000..ac116d8
--- /dev/null
+++ b/SOURCES/iptables-1.4.21-wait-interval.patch
@@ -0,0 +1,330 @@
+Adapted version of
+
+commit e8f857a5a1514c3e7d0d8ea0f7d2d571f0e37bd1
+Author: Subash Abhinov Kasiviswanathan <subashab@codeaurora.org>
+Date:   Thu Jun 23 18:44:06 2016 -0600
+
+    xtables: Add an interval option for xtables lock wait
+    
+    ip[6]tables currently waits for 1 second for the xtables lock to be
+    freed if the -w option is used. We have seen that the lock is held
+    much less than that resulting in unnecessary delay when trying to
+    acquire the lock. This problem is even severe in case of latency
+    sensitive applications.
+    
+    Introduce a new option 'W' to specify the wait interval in microseconds.
+    If this option is not specified, the command sleeps for 1 second by
+    default.
+    
+    v1->v2: Change behavior to take millisecond sleep as an argument to
+    -w as suggested by Pablo. Also maintain current behavior for -w to
+    sleep for 1 second as mentioned by Liping.
+    
+    v2->v3: Move the millisecond behavior to a new option as suggested
+    by Pablo.
+    
+    v3->v4: Use select instead of usleep. Sleep every iteration for
+    the time specified in the "-W" argument. Update man page.
+    
+    v4->v5: Fix compilation error when enabling nftables
+    
+    v5->v6: Simplify -W so it only takes the interval wait in microseconds.
+    Bail out if -W is specific but -w is not.
+    
+    Joint work with Pablo Neira.
+    
+    Signed-off-by: Subash Abhinov Kasiviswanathan <subashab@codeaurora.org>
+    Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
+
+diff -up iptables-1.4.21/iptables/ip6tables.c.wait-interval iptables-1.4.21/iptables/ip6tables.c
+--- iptables-1.4.21/iptables/ip6tables.c.wait-interval	2017-04-05 14:04:04.560346651 +0200
++++ iptables-1.4.21/iptables/ip6tables.c	2017-04-05 14:04:04.562346670 +0200
+@@ -103,6 +103,7 @@ static struct option original_opts[] = {
+ 	{.name = "out-interface", .has_arg = 1, .val = 'o'},
+ 	{.name = "verbose",       .has_arg = 0, .val = 'v'},
+ 	{.name = "wait",          .has_arg = 2, .val = 'w'},
++	{.name = "wait-interval", .has_arg = 2, .val = 'W'},
+ 	{.name = "exact",         .has_arg = 0, .val = 'x'},
+ 	{.name = "version",       .has_arg = 0, .val = 'V'},
+ 	{.name = "help",          .has_arg = 2, .val = 'h'},
+@@ -258,7 +259,10 @@ exit_printhelp(const struct xtables_rule
+ "				network interface name ([+] for wildcard)\n"
+ "  --table	-t table	table to manipulate (default: `filter')\n"
+ "  --verbose	-v		verbose mode\n"
+-"  --wait	-w [seconds]	wait for the xtables lock\n"
++"  --wait	-w [seconds]	maximum wait to acquire xtables lock before give up\n"
++"  --wait-interval -W [usecs]	wait time to try to acquire xtables lock\n"
++"				interval to wait for xtables lock\n"
++"				default is 1 second\n"
+ "  --line-numbers		print line numbers when listing\n"
+ "  --exact	-x		expand numbers (display exact values)\n"
+ /*"[!] --fragment	-f		match second or further fragments only\n"*/
+@@ -1323,6 +1327,10 @@ int do_command6(int argc, char *argv[],
+ 
+ 	int verbose = 0;
+ 	int wait = 0;
++	struct timeval wait_interval = {
++		.tv_sec	= 1,
++	};
++	bool wait_interval_set = false;
+ 	const char *chain = NULL;
+ 	const char *shostnetworkmask = NULL, *dhostnetworkmask = NULL;
+ 	const char *policy = NULL, *newname = NULL;
+@@ -1358,7 +1366,7 @@ int do_command6(int argc, char *argv[],
+ 
+ 	opts = xt_params->orig_opts;
+ 	while ((cs.c = getopt_long(argc, argv,
+-	   "-:A:C:D:R:I:L::S::M:F::Z::N:X::E:P:Vh::o:p:s:d:j:i:bvw::nt:m:xc:g:46",
++	   "-:A:C:D:R:I:L::S::M:F::Z::N:X::E:P:Vh::o:p:s:d:j:i:bvw::W::nt:m:xc:g:46",
+ 					   opts, NULL)) != -1) {
+ 		switch (cs.c) {
+ 			/*
+@@ -1614,6 +1622,23 @@ int do_command6(int argc, char *argv[],
+ 						"wait seconds not numeric");
+ 			break;
+ 
++		case 'W':
++			if (restore) {
++				xtables_error(PARAMETER_PROBLEM,
++					      "You cannot use `-W' from "
++					      "ip6tables-restore");
++			}
++			if (optarg)
++				parse_wait_interval(optarg, &wait_interval);
++			else if (optind < argc &&
++				argv[optind][0] != '-' &&
++				argv[optind][0] != '!')
++				parse_wait_interval(argv[optind++],
++						    &wait_interval);
++
++			wait_interval_set = true;
++			break;
++
+ 		case 'm':
+ 			command_match(&cs);
+ 			break;
+@@ -1718,6 +1743,10 @@ int do_command6(int argc, char *argv[],
+ 		cs.invert = FALSE;
+ 	}
+ 
++	if (!wait && wait_interval_set)
++		xtables_error(PARAMETER_PROBLEM,
++			      "--wait-interval only makes sense with --wait\n");
++
+ 	if (strcmp(*table, "nat") == 0 &&
+ 	    ((policy != NULL && strcmp(policy, "DROP") == 0) ||
+ 	    (cs.jumpto != NULL && strcmp(cs.jumpto, "DROP") == 0)))
+@@ -1768,7 +1797,7 @@ int do_command6(int argc, char *argv[],
+ 	generic_opt_check(command, cs.options);
+ 
+ 	/* Attempt to acquire the xtables lock */
+-	if (!restore && !xtables_lock(wait)) {
++	if (!restore && !xtables_lock(wait, &wait_interval)) {
+ 		fprintf(stderr, "Another app is currently holding the xtables lock. ");
+ 		if (wait == 0)
+ 			fprintf(stderr, "Perhaps you want to use the -w option?\n");
+diff -up iptables-1.4.21/iptables/iptables.8.in.wait-interval iptables-1.4.21/iptables/iptables.8.in
+--- iptables-1.4.21/iptables/iptables.8.in.wait-interval	2017-04-05 14:04:04.555346605 +0200
++++ iptables-1.4.21/iptables/iptables.8.in	2017-04-05 14:04:04.562346670 +0200
+@@ -369,6 +369,13 @@ the program will exit if the lock cannot
+ make the program wait (indefinitely or for optional \fIseconds\fP) until
+ the exclusive lock can be obtained.
+ .TP
++\fB\-W\fP, \fB\-\-wait-interval\fP \fImicroseconds\fP
++Interval to wait per each iteration.
++When running latency sensitive applications, waiting for the xtables lock
++for extended durations may not be acceptable. This option will make each
++iteration take the amount of time specified. The default interval is
++1 second. This option only works with \fB\-w\fP.
++.TP
+ \fB\-n\fP, \fB\-\-numeric\fP
+ Numeric output.
+ IP addresses and port numbers will be printed in numeric format.
+diff -up iptables-1.4.21/iptables/iptables.c.wait-interval iptables-1.4.21/iptables/iptables.c
+--- iptables-1.4.21/iptables/iptables.c.wait-interval	2017-04-05 14:04:04.555346605 +0200
++++ iptables-1.4.21/iptables/iptables.c	2017-04-05 14:04:04.563346679 +0200
+@@ -100,6 +100,7 @@ static struct option original_opts[] = {
+ 	{.name = "out-interface", .has_arg = 1, .val = 'o'},
+ 	{.name = "verbose",       .has_arg = 0, .val = 'v'},
+ 	{.name = "wait",          .has_arg = 2, .val = 'w'},
++	{.name = "wait-interval", .has_arg = 2, .val = 'W'},
+ 	{.name = "exact",         .has_arg = 0, .val = 'x'},
+ 	{.name = "fragments",     .has_arg = 0, .val = 'f'},
+ 	{.name = "version",       .has_arg = 0, .val = 'V'},
+@@ -252,7 +253,9 @@ exit_printhelp(const struct xtables_rule
+ "				network interface name ([+] for wildcard)\n"
+ "  --table	-t table	table to manipulate (default: `filter')\n"
+ "  --verbose	-v		verbose mode\n"
+-"  --wait	-w [seconds]	wait for the xtables lock\n"
++"  --wait	-w [seconds]	maximum wait to acquire xtables lock before give up\n"
++"  --wait-interval -W [usecs]	wait time to try to acquire xtables lock\n"
++"				default is 1 second\n"
+ "  --line-numbers		print line numbers when listing\n"
+ "  --exact	-x		expand numbers (display exact values)\n"
+ "[!] --fragment	-f		match second or further fragments only\n"
+@@ -1316,7 +1319,10 @@ int do_command4(int argc, char *argv[],
+ 	unsigned int nsaddrs = 0, ndaddrs = 0;
+ 	struct in_addr *saddrs = NULL, *smasks = NULL;
+ 	struct in_addr *daddrs = NULL, *dmasks = NULL;
+-
++	struct timeval wait_interval = {
++		.tv_sec = 1,
++	};
++	bool wait_interval_set = false;
+ 	int verbose = 0;
+ 	int wait = 0;
+ 	const char *chain = NULL;
+@@ -1353,7 +1359,7 @@ int do_command4(int argc, char *argv[],
+ 	opterr = 0;
+ 	opts = xt_params->orig_opts;
+ 	while ((cs.c = getopt_long(argc, argv,
+-	   "-:A:C:D:R:I:L::S::M:F::Z::N:X::E:P:Vh::o:p:s:d:j:i:fbvw::nt:m:xc:g:46",
++	   "-:A:C:D:R:I:L::S::M:F::Z::N:X::E:P:Vh::o:p:s:d:j:i:fbvw::W::nt:m:xc:g:46",
+ 					   opts, NULL)) != -1) {
+ 		switch (cs.c) {
+ 			/*
+@@ -1607,6 +1613,23 @@ int do_command4(int argc, char *argv[],
+ 						"wait seconds not numeric");
+ 			break;
+ 
++		case 'W':
++			if (restore) {
++				xtables_error(PARAMETER_PROBLEM,
++					      "You cannot use `-W' from "
++					      "iptables-restore");
++			}
++			if (optarg)
++				parse_wait_interval(optarg, &wait_interval);
++			else if (optind < argc &&
++				 argv[optind][0] != '-' &&
++				 argv[optind][0] != '!')
++				parse_wait_interval(argv[optind++],
++						    &wait_interval);
++
++			wait_interval_set = true;
++			break;
++
+ 		case 'm':
+ 			command_match(&cs);
+ 			break;
+@@ -1707,6 +1730,10 @@ int do_command4(int argc, char *argv[],
+ 		cs.invert = FALSE;
+ 	}
+ 
++	if (!wait && wait_interval_set)
++		xtables_error(PARAMETER_PROBLEM,
++			      "--wait-interval only makes sense with --wait\n");
++
+ 	if (strcmp(*table, "nat") == 0 &&
+ 	    ((policy != NULL && strcmp(policy, "DROP") == 0) ||
+ 	    (cs.jumpto != NULL && strcmp(cs.jumpto, "DROP") == 0)))
+@@ -1757,7 +1784,7 @@ int do_command4(int argc, char *argv[],
+ 	generic_opt_check(command, cs.options);
+ 
+ 	/* Attempt to acquire the xtables lock */
+-	if (!restore && !xtables_lock(wait)) {
++	if (!restore && !xtables_lock(wait, &wait_interval)) {
+ 		fprintf(stderr, "Another app is currently holding the xtables lock. ");
+ 		if (wait == 0)
+ 			fprintf(stderr, "Perhaps you want to use the -w option?\n");
+diff -up iptables-1.4.21/iptables/xshared.c.wait-interval iptables-1.4.21/iptables/xshared.c
+--- iptables-1.4.21/iptables/xshared.c.wait-interval	2017-04-05 14:04:04.557346624 +0200
++++ iptables-1.4.21/iptables/xshared.c	2017-04-05 14:04:04.563346679 +0200
+@@ -9,12 +9,15 @@
+ #include <sys/file.h>
+ #include <sys/socket.h>
+ #include <sys/un.h>
++#include <sys/time.h>
+ #include <unistd.h>
+ #include <fcntl.h>
+ #include <xtables.h>
++#include <math.h>
+ #include "xshared.h"
+ 
+ #define XT_LOCK_NAME	"/run/xtables.lock"
++#define BASE_MICROSECONDS	100000
+ 
+ /*
+  * Print out any special helps. A user might like to be able to add a --help
+@@ -244,9 +247,15 @@ void xs_init_match(struct xtables_match
+ 		match->init(match->m);
+ }
+ 
+-bool xtables_lock(int wait)
++bool xtables_lock(int wait, struct timeval *wait_interval)
+ {
+-	int fd, waited = 0, i = 0;
++	struct timeval time_left, wait_time, waited_time;
++	int fd, i = 0;
++
++	time_left.tv_sec = wait;
++	time_left.tv_usec = 0;
++	waited_time.tv_sec = 0;
++	waited_time.tv_usec = 0;
+ 
+ 	fd = open(XT_LOCK_NAME, O_CREAT, 0600);
+ 	if (fd < 0)
+@@ -255,12 +264,43 @@ bool xtables_lock(int wait)
+ 	while (1) {
+ 		if (flock(fd, LOCK_EX | LOCK_NB) == 0)
+ 			return true;
+-		else if (wait >= 0 && waited >= wait)
++		if (++i % 10 == 0) {
++			if (wait != -1)
++				fprintf(stderr, "Another app is currently holding the xtables lock; "
++					"still %lds %ldus time ahead to have a chance to grab the lock...\n",
++					time_left.tv_sec, time_left.tv_usec);
++			else
++				fprintf(stderr, "Another app is currently holding the xtables lock; "
++						"waiting for it to exit...\n");
++		}
++
++		wait_time = *wait_interval;
++		select(0, NULL, NULL, NULL, &wait_time);
++		if (wait == -1)
++			continue;
++
++		timeradd(&waited_time, wait_interval, &waited_time);
++		timersub(&time_left, wait_interval, &time_left);
++		if (!timerisset(&time_left))
+ 			return false;
+-		if (++i % 2 == 0)
+-			fprintf(stderr, "Another app is currently holding the xtables lock; "
+-				"waiting (%ds) for it to exit...\n", waited);
+-		waited++;
+-		sleep(1);
+ 	}
+ }
++
++void parse_wait_interval(const char *str, struct timeval *wait_interval)
++{
++	unsigned int usec;
++	int ret;
++
++	ret = sscanf(str, "%u", &usec);
++	if (ret == 1) {
++		if (usec > 999999)
++			xtables_error(PARAMETER_PROBLEM,
++				      "too long usec wait %u > 999999 usec",
++				      usec);
++
++		wait_interval->tv_sec = 0;
++		wait_interval->tv_usec = usec;
++		return;
++	}
++	xtables_error(PARAMETER_PROBLEM, "wait interval not numeric");
++}
+diff -up iptables-1.4.21/iptables/xshared.h.wait-interval iptables-1.4.21/iptables/xshared.h
+--- iptables-1.4.21/iptables/xshared.h.wait-interval	2017-04-05 14:04:04.555346605 +0200
++++ iptables-1.4.21/iptables/xshared.h	2017-04-05 14:04:04.563346679 +0200
+@@ -84,7 +84,9 @@ extern struct xtables_match *load_proto(
+ extern int subcmd_main(int, char **, const struct subcommand *);
+ extern void xs_init_target(struct xtables_target *);
+ extern void xs_init_match(struct xtables_match *);
+-extern bool xtables_lock(int wait);
++bool xtables_lock(int wait, struct timeval *wait_interval);
++
++void parse_wait_interval(const char *str, struct timeval *wait_interval);
+ 
+ extern const struct xtables_afinfo *afinfo;
+ 
diff --git a/SOURCES/iptables-do_not_lock_again_and_again.patch b/SOURCES/iptables-do_not_lock_again_and_again.patch
new file mode 100644
index 0000000..6d4913d
--- /dev/null
+++ b/SOURCES/iptables-do_not_lock_again_and_again.patch
@@ -0,0 +1,78 @@
+commit 24f8174646123c2833bc87967b366796231b04e0
+Author: Liping Zhang <zlpnobody@gmail.com>
+Date:   Sun Feb 5 21:57:34 2017 +0800
+
+    xshared: do not lock again and again if "-w" option is not specified
+    
+    After running the following commands, some confusing messages was printed
+    out:
+      # while : ; do
+      iptables -A INPUT &
+      iptables -D INPUT &
+      done
+      [...]
+      Another app is currently holding the xtables lock; still -9s 0us time
+      ahead to have a chance to grab the lock...
+      Another app is currently holding the xtables lock; still -29s 0us time
+      ahead to have a chance to grab the lock...
+    
+    If "-w" option is not specified, the "wait" will be zero, so we should
+    check whether the timer_left is less than wait_interval before we call
+    select to sleep.
+    
+    Also remove unused "BASE_MICROSECONDS" and "struct timeval waited_time"
+    introduced by commit e8f857a5a151 ("xtables: Add an interval option for
+    xtables lock wait").
+    
+    Fixes: e8f857a5a151 ("xtables: Add an interval option for xtables lock wait")
+    Signed-off-by: Liping Zhang <zlpnobody@gmail.com>
+    Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
+
+diff --git a/iptables/xshared.c b/iptables/xshared.c
+index cccb8ae..055acf2 100644
+--- a/iptables/xshared.c
++++ b/iptables/xshared.c
+@@ -17,7 +17,6 @@
+ #include "xshared.h"
+ 
+ #define XT_LOCK_NAME	"/run/xtables.lock"
+-#define BASE_MICROSECONDS	100000
+ 
+ /*
+  * Print out any special helps. A user might like to be able to add a --help
+@@ -249,13 +248,11 @@ void xs_init_match(struct xtables_match *match)
+ 
+ bool xtables_lock(int wait, struct timeval *wait_interval)
+ {
+-	struct timeval time_left, wait_time, waited_time;
++	struct timeval time_left, wait_time;
+ 	int fd, i = 0;
+ 
+ 	time_left.tv_sec = wait;
+ 	time_left.tv_usec = 0;
+-	waited_time.tv_sec = 0;
+-	waited_time.tv_usec = 0;
+ 
+ 	fd = open(XT_LOCK_NAME, O_CREAT, 0600);
+ 	if (fd < 0)
+@@ -264,6 +261,9 @@ bool xtables_lock(int wait, struct timeval *wait_interval)
+ 	while (1) {
+ 		if (flock(fd, LOCK_EX | LOCK_NB) == 0)
+ 			return true;
++		else if (wait >= 0 && timercmp(&time_left, wait_interval, <))
++			return false;
++
+ 		if (++i % 10 == 0) {
+ 			if (wait != -1)
+ 				fprintf(stderr, "Another app is currently holding the xtables lock; "
+@@ -279,10 +279,7 @@ bool xtables_lock(int wait, struct timeval *wait_interval)
+ 		if (wait == -1)
+ 			continue;
+ 
+-		timeradd(&waited_time, wait_interval, &waited_time);
+ 		timersub(&time_left, wait_interval, &time_left);
+-		if (!timerisset(&time_left))
+-			return false;
+ 	}
+ }
+ 
diff --git a/SOURCES/iptables-do_not_set_changed_for_check_options.patch b/SOURCES/iptables-do_not_set_changed_for_check_options.patch
new file mode 100644
index 0000000..f36e064
--- /dev/null
+++ b/SOURCES/iptables-do_not_set_changed_for_check_options.patch
@@ -0,0 +1,79 @@
+commit 9b8cb7564a53865bf0e239bbc3e057de70edf65d
+Author: Dan Williams <dcbw@redhat.com>
+Date:   Sat Feb 25 22:02:03 2017 -0600
+
+    libiptc: don't set_changed() when checking rules with module jumps
+    
+    Checking a rule that includes a jump to a module-based target currently
+    sets the "changed" flag on the handle, which then causes TC_COMMIT() to
+    run through the whole SO_SET_REPLACE/SO_SET_ADD_COUNTERS path.  This
+    seems wrong for simply checking rules, an operation which is documented
+    as "...does not alter the existing iptables configuration..." but yet
+    it clearly could do so.
+    
+    Fix that by ensuring that rule check operations for module targets
+    don't set the changed flag, and thus exit early from TC_COMMIT().
+    
+    Signed-off-by: Dan Williams <dcbw@redhat.com>
+    Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
+
+diff --git a/libiptc/libiptc.c b/libiptc/libiptc.c
+index 2c66d04..a6e7057 100644
+--- a/libiptc/libiptc.c
++++ b/libiptc/libiptc.c
+@@ -1686,7 +1686,8 @@ iptcc_standard_map(struct rule_head *r, int verdict)
+ 
+ static int
+ iptcc_map_target(struct xtc_handle *const handle,
+-	   struct rule_head *r)
++	   struct rule_head *r,
++	   bool dry_run)
+ {
+ 	STRUCT_ENTRY *e = r->entry;
+ 	STRUCT_ENTRY_TARGET *t = GET_TARGET(e);
+@@ -1731,7 +1732,8 @@ iptcc_map_target(struct xtc_handle *const handle,
+ 	       0,
+ 	       FUNCTION_MAXNAMELEN - 1 - strlen(t->u.user.name));
+ 	r->type = IPTCC_R_MODULE;
+-	set_changed(handle);
++	if (!dry_run)
++		set_changed(handle);
+ 	return 1;
+ }
+ 
+@@ -1781,7 +1783,7 @@ TC_INSERT_ENTRY(const IPT_CHAINLABEL chain,
+ 	memcpy(r->entry, e, e->next_offset);
+ 	r->counter_map.maptype = COUNTER_MAP_SET;
+ 
+-	if (!iptcc_map_target(handle, r)) {
++	if (!iptcc_map_target(handle, r, false)) {
+ 		free(r);
+ 		return 0;
+ 	}
+@@ -1831,7 +1833,7 @@ TC_REPLACE_ENTRY(const IPT_CHAINLABEL chain,
+ 	memcpy(r->entry, e, e->next_offset);
+ 	r->counter_map.maptype = COUNTER_MAP_SET;
+ 
+-	if (!iptcc_map_target(handle, r)) {
++	if (!iptcc_map_target(handle, r, false)) {
+ 		free(r);
+ 		return 0;
+ 	}
+@@ -1870,7 +1872,7 @@ TC_APPEND_ENTRY(const IPT_CHAINLABEL chain,
+ 	memcpy(r->entry, e, e->next_offset);
+ 	r->counter_map.maptype = COUNTER_MAP_SET;
+ 
+-	if (!iptcc_map_target(handle, r)) {
++	if (!iptcc_map_target(handle, r, false)) {
+ 		DEBUGP("unable to map target of rule for chain `%s'\n", chain);
+ 		free(r);
+ 		return 0;
+@@ -1976,7 +1978,7 @@ static int delete_entry(const IPT_CHAINLABEL chain, const STRUCT_ENTRY *origfw,
+ 
+ 	memcpy(r->entry, origfw, origfw->next_offset);
+ 	r->counter_map.maptype = COUNTER_MAP_NOMAP;
+-	if (!iptcc_map_target(handle, r)) {
++	if (!iptcc_map_target(handle, r, dry_run)) {
+ 		DEBUGP("unable to map target of rule for chain `%s'\n", chain);
+ 		free(r);
+ 		return 0;
diff --git a/SOURCES/iptables-use_the_blocking_file_lock_request.patch b/SOURCES/iptables-use_the_blocking_file_lock_request.patch
new file mode 100644
index 0000000..1cddc36
--- /dev/null
+++ b/SOURCES/iptables-use_the_blocking_file_lock_request.patch
@@ -0,0 +1,91 @@
+commit 72bb3dbf0ecdf3ec96aee80e5d152c8be4394da1
+Author: Liping Zhang <zlpnobody@gmail.com>
+Date:   Mon Feb 6 19:47:47 2017 +0800
+
+    xshared: using the blocking file lock request when we wait indefinitely
+    
+    When using "-w" to avoid concurrent instances, we try to do flock() every
+    one second until it success. But one second maybe too long in some
+    situations, and it's hard to select a suitable interval time. So when
+    using "iptables -w" to wait indefinitely, it's better to block until
+    it become success.
+    
+    Now do some performance tests. First, flush all the iptables rules in
+    filter table, and run "iptables -w -S" endlessly:
+      # iptables -F
+      # iptables -X
+      # while : ; do
+      iptables -w -S >&- &
+      done
+    
+    Second, after adding and deleting the iptables rules 100 times, measure
+    the time cost:
+      # time for i in $(seq 100); do
+      iptables -w -A INPUT
+      iptables -w -D INPUT
+      done
+    
+    Before this patch:
+      real  1m15.962s
+      user  0m0.224s
+      sys   0m1.475s
+    
+    Apply this patch:
+      real  0m1.830s
+      user  0m0.168s
+      sys   0m1.130s
+    
+    Signed-off-by: Liping Zhang <zlpnobody@gmail.com>
+    Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
+
+diff --git a/iptables/xshared.c b/iptables/xshared.c
+index 055acf2..f0a5ddd 100644
+--- a/iptables/xshared.c
++++ b/iptables/xshared.c
+@@ -1,4 +1,5 @@
+ #include <getopt.h>
++#include <errno.h>
+ #include <libgen.h>
+ #include <netdb.h>
+ #include <stdbool.h>
+@@ -258,27 +259,29 @@ bool xtables_lock(int wait, struct timeval *wait_interval)
+ 	if (fd < 0)
+ 		return true;
+ 
++	if (wait == -1) {
++		if (flock(fd, LOCK_EX) == 0)
++			return true;
++
++		fprintf(stderr, "Can't lock %s: %s\n", XT_LOCK_NAME,
++			strerror(errno));
++		return false;
++	}
++
+ 	while (1) {
+ 		if (flock(fd, LOCK_EX | LOCK_NB) == 0)
+ 			return true;
+-		else if (wait >= 0 && timercmp(&time_left, wait_interval, <))
++		else if (timercmp(&time_left, wait_interval, <))
+ 			return false;
+ 
+ 		if (++i % 10 == 0) {
+-			if (wait != -1)
+-				fprintf(stderr, "Another app is currently holding the xtables lock; "
+-					"still %lds %ldus time ahead to have a chance to grab the lock...\n",
+-					time_left.tv_sec, time_left.tv_usec);
+-			else
+-				fprintf(stderr, "Another app is currently holding the xtables lock; "
+-						"waiting for it to exit...\n");
++			fprintf(stderr, "Another app is currently holding the xtables lock; "
++				"still %lds %ldus time ahead to have a chance to grab the lock...\n",
++				time_left.tv_sec, time_left.tv_usec);
+ 		}
+ 
+ 		wait_time = *wait_interval;
+ 		select(0, NULL, NULL, NULL, &wait_time);
+-		if (wait == -1)
+-			continue;
+-
+ 		timersub(&time_left, wait_interval, &time_left);
+ 	}
+ }
diff --git a/SPECS/iptables.spec b/SPECS/iptables.spec
index 9e237dd..91c3aa2 100644
--- a/SPECS/iptables.spec
+++ b/SPECS/iptables.spec
@@ -7,7 +7,7 @@
 Name: iptables
 Summary: Tools for managing Linux kernel packet filtering capabilities
 Version: 1.4.21
-Release: 17%{?dist}
+Release: 18%{?dist}
 Source: http://www.netfilter.org/projects/iptables/files/%{name}-%{version}.tar.bz2
 Source1: iptables.init
 Source2: iptables-config
@@ -22,6 +22,18 @@ Patch3: iptables-1.4.21-wait_seconds.patch
 Patch4: iptables-1.4.21-flock_wait.patch
 Patch5: iptables-1.4.21-rhbz_1261238.patch
 Patch6: iptables-c513cc3-rhbz_1298879.patch
+Patch7: iptables-1.4.21-wait-interval.patch
+Patch8: iptables-do_not_lock_again_and_again.patch
+Patch9: iptables-use_the_blocking_file_lock_request.patch
+Patch10: iptables-1.4.21-configure_set_lock_file_path.patch
+Patch11: iptables-1.4.21-move_XT_LOCK_NAME_to_config.h.patch
+Patch12: iptables-1.4.21-remove_duplicated_argument_parsing.patch
+Patch13: iptables-1.4.21-restore_support_acquiring_the_lock.patch
+# One patch invalid: 1cf4ba6fbe85b3cbe9828a7947000290e1989986
+Patch14: iptables-do_not_set_changed_for_check_options.patch
+Patch15: iptables-1.4.21-restore_version.patch
+Patch16: iptables-1.4.21-restore_wait_man.patch
+
 Group: System Environment/Base
 URL: http://www.netfilter.org/
 License: GPLv2
@@ -32,6 +44,8 @@ BuildRequires: libnfnetlink-devel
 BuildRequires: libselinux-devel
 BuildRequires: kernel-headers
 BuildRequires: systemd
+BuildRequires: automake
+BuildRequires: autoconf
 
 %description
 The iptables utility controls the network packet filtering code in the
@@ -90,6 +104,16 @@ Currently only provides nfnl_osf with the pf.os database.
 %patch4 -p1 -b .flock_wait
 %patch5 -p1 -b .rhbz_1261238
 %patch6 -p1 -b .rhbz_1298879
+%patch7 -p1 -b .wait-interval
+%patch8 -p1 -b .do_not_lock_again_and_again
+%patch9 -p1 -b .use_the_blocking_file_lock_request
+%patch10 -p1 -b .configure_set_lock_file_path
+%patch11 -p1 -b .move_XT_LOCK_NAME_to_config.h
+%patch12 -p1 -b .remove_duplicated_argument_parsing
+%patch13 -p1 -b .restore_support_acquiring_the_lock
+%patch14 -p1 -b .do_not_set_changed_for_check_options
+%patch15 -p1 -b .restore_version
+%patch16 -p1 -b .restore_wait_man
 
 %build
 CFLAGS="$RPM_OPT_FLAGS -fno-strict-aliasing " \
@@ -243,6 +267,12 @@ done
 
 
 %changelog
+* Mon Apr 24 2017 Thomas Woerner <twoerner@redhat.com> 1.4.21-18
+- Add support for --wait options to restore commands (RHBZ#1438597)
+- Do not set changed flag for rule check operations with module targets
+  (RHBZ#1438597)
+- Add version option to restore commands (RHBZ#1438597)
+
 * Fri Jul  1 2016 Thomas Woerner <twoerner@redhat.com> 1.4.21-17
 - Fixed init script not to fail on missing restorecon (RHBZ#1246380)
 - Adapted man page snipplet for TRACE to use proper logging backend names