nft: load only the tables of the current family

This changes nft_xtables_config_load() permit to load only
the tables of the current family.

[ This patch includes a fix for the configuration parser
  that I detected while testing this patch --pablo ]

Signed-off-by: Giuseppe Longo <giuseppelng@gmail.com>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
diff --git a/iptables/nft.c b/iptables/nft.c
index bbe5e39..df4122c 100644
--- a/iptables/nft.c
+++ b/iptables/nft.c
@@ -2853,6 +2853,8 @@
 	struct nft_chain_list_iter *citer;
 	struct nft_table *table;
 	struct nft_chain *chain;
+	uint32_t table_family, chain_family;
+	bool found = false;
 
 	if (xtables_config_parse(filename, table_list, chain_list) < 0) {
 		if (errno == ENOENT) {
@@ -2870,6 +2872,13 @@
 	/* Stage 1) create tables */
 	titer = nft_table_list_iter_create(table_list);
 	while ((table = nft_table_list_iter_next(titer)) != NULL) {
+		table_family = nft_table_attr_get_u32(table,
+						      NFT_TABLE_ATTR_FAMILY);
+		if (h->family != table_family)
+			continue;
+
+		found = true;
+
 		if (nft_table_add(h, table) < 0) {
 			if (errno == EEXIST) {
 				xtables_config_perror(flags,
@@ -2892,9 +2901,17 @@
 	nft_table_list_iter_destroy(titer);
 	nft_table_list_free(table_list);
 
+	if (!found)
+		return -1;
+
 	/* Stage 2) create chains */
 	citer = nft_chain_list_iter_create(chain_list);
 	while ((chain = nft_chain_list_iter_next(citer)) != NULL) {
+		chain_family = nft_chain_attr_get_u32(chain,
+						      NFT_CHAIN_ATTR_TABLE);
+		if (h->family != chain_family)
+			continue;
+
 		if (nft_chain_add(h, chain) < 0) {
 			if (errno == EEXIST) {
 				xtables_config_perror(flags,
diff --git a/iptables/xtables-config-parser.y b/iptables/xtables-config-parser.y
index e7a8a07..36dae38 100644
--- a/iptables/xtables-config-parser.y
+++ b/iptables/xtables-config-parser.y
@@ -228,7 +228,8 @@
 			}
 			nft_chain_attr_set(chain, NFT_CHAIN_ATTR_TABLE,
 				(char *)nft_table_attr_get(table, NFT_TABLE_ATTR_NAME));
-			nft_table_attr_set_u32(table, NFT_CHAIN_ATTR_FAMILY, family);
+			nft_chain_attr_set_u32(chain, NFT_CHAIN_ATTR_FAMILY,
+				nft_table_attr_get_u32(table, NFT_TABLE_ATTR_FAMILY));
 			nft_chain_attr_set_s32(chain, NFT_CHAIN_ATTR_PRIO, prio);
 			nft_chain_attr_set(chain, NFT_CHAIN_ATTR_NAME, e->data);
 			/* Intentionally prepending, instead of appending */