xtables: support family in /etc/xtables.conf file

Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
diff --git a/etc/xtables.conf b/etc/xtables.conf
index 6d26ffe..1995b69 100644
--- a/etc/xtables.conf
+++ b/etc/xtables.conf
@@ -1,31 +1,33 @@
-table raw {
-	chain PREROUTING hook NF_INET_PRE_ROUTING prio -300
-	chain OUTPUT hook NF_INET_LOCAL_OUT prio -300
-}
+family ipv4 {
+	table raw {
+		chain PREROUTING hook NF_INET_PRE_ROUTING prio -300
+		chain OUTPUT hook NF_INET_LOCAL_OUT prio -300
+	}
 
-table mangle {
-	chain PREROUTING hook NF_INET_PRE_ROUTING prio -150
-	chain INPUT hook NF_INET_LOCAL_IN prio -150
-	chain FORWARD hook NF_INET_FORWARD prio -150
-	chain OUTPUT hook NF_INET_LOCAL_OUT prio -150
-	chain POSTROUTING hook NF_INET_POST_ROUTING prio -150
-}
+	table mangle {
+		chain PREROUTING hook NF_INET_PRE_ROUTING prio -150
+		chain INPUT hook NF_INET_LOCAL_IN prio -150
+		chain FORWARD hook NF_INET_FORWARD prio -150
+		chain OUTPUT hook NF_INET_LOCAL_OUT prio -150
+		chain POSTROUTING hook NF_INET_POST_ROUTING prio -150
+	}
 
-table filter {
-	chain INPUT hook NF_INET_LOCAL_IN prio 0
-	chain FORWARD hook NF_INET_FORWARD prio 0
-	chain OUTPUT hook NF_INET_LOCAL_OUT prio 0
-}
+	table filter {
+		chain INPUT hook NF_INET_LOCAL_IN prio 0
+		chain FORWARD hook NF_INET_FORWARD prio 0
+		chain OUTPUT hook NF_INET_LOCAL_OUT prio 0
+	}
 
-table nat {
-	chain PREROUTING hook NF_INET_PRE_ROUTING prio -100
-	chain POSTROUTING hook NF_INET_POST_ROUTING prio 100
-	chain INPUT hook NF_INET_LOCAL_IN prio -100
-	chain OUTPUT hook NF_INET_LOCAL_OUT prio 100
-}
+	table nat {
+		chain PREROUTING hook NF_INET_PRE_ROUTING prio -100
+		chain POSTROUTING hook NF_INET_POST_ROUTING prio 100
+		chain INPUT hook NF_INET_LOCAL_IN prio -100
+		chain OUTPUT hook NF_INET_LOCAL_OUT prio 100
+	}
 
-table security {
-	chain INPUT hook NF_INET_LOCAL_IN prio 150
-	chain FORWARD hook NF_INET_FORWARD prio 150
-	chain OUTPUT hook NF_INET_LOCAL_OUT prio 150
+	table security {
+		chain INPUT hook NF_INET_LOCAL_IN prio 150
+		chain FORWARD hook NF_INET_FORWARD prio 150
+		chain OUTPUT hook NF_INET_LOCAL_OUT prio 150
+	}
 }
diff --git a/iptables/xtables-config-parser.y b/iptables/xtables-config-parser.y
index ad5d624..06b6ca9 100644
--- a/iptables/xtables-config-parser.y
+++ b/iptables/xtables-config-parser.y
@@ -84,6 +84,7 @@
 	char	*string;
 }
 
+%token T_FAMILY
 %token T_TABLE
 %token T_CHAIN
 %token T_HOOK
@@ -102,7 +103,18 @@
 		| lines line
 		;
 
-line		: table
+line		: family
+		;
+
+family		: T_FAMILY T_STRING '{' tables '}'
+		{
+			void *data = stack_push(T_FAMILY, strlen($2));
+			stack_put_str(data, $2);
+		}
+		;
+
+tables		: table
+		| tables table
 		;
 
 table		: T_TABLE T_STRING '{' chains '}'
@@ -155,6 +167,16 @@
 	return -1;
 }
 
+static int32_t familytonumber(const char *family)
+{
+	if (strcmp(family, "ipv4") == 0)
+		return AF_INET;
+	else if (strcmp(family, "ipv6") == 0)
+		return AF_INET6;
+
+	return -1;
+}
+
 int xtables_config_parse(char *filename, struct nft_table_list *table_list,
 			 struct nft_chain_list *chain_list)
 {
@@ -163,6 +185,7 @@
 	struct nft_table *table = NULL;
 	struct nft_chain *chain = NULL;
 	int prio = 0;
+	int32_t family = 0;
 
 	fp = fopen(filename, "r");
 	if (!fp)
@@ -174,12 +197,18 @@
 
 	for (e = stack_pop(); e != NULL; e = stack_pop()) {
 		switch(e->token) {
+		case T_FAMILY:
+			family = familytonumber(e->data);
+			if (family == -1)
+				return -1;
+			break;
 		case T_TABLE:
 			table = nft_table_alloc();
 			if (table == NULL) {
 				perror("nft_table_alloc");
 				return -1;
 			}
+			nft_table_attr_set_u32(table, NFT_TABLE_ATTR_FAMILY, family);
 			nft_table_attr_set(table, NFT_TABLE_ATTR_NAME, e->data);
 			nft_table_list_add(table, table_list);
 			break;
@@ -194,6 +223,7 @@
 			}
 			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_s32(chain, NFT_CHAIN_ATTR_PRIO, prio);
 			nft_chain_attr_set(chain, NFT_CHAIN_ATTR_NAME, e->data);
 			nft_chain_list_add(chain, chain_list);
diff --git a/iptables/xtables-config-syntax.l b/iptables/xtables-config-syntax.l
index 7a66ef3..a895c8b 100644
--- a/iptables/xtables-config-syntax.l
+++ b/iptables/xtables-config-syntax.l
@@ -28,6 +28,7 @@
 string		[a-zA-Z][a-zA-Z0-9\.\-\_]*
 
 %%
+"family"		{ return T_FAMILY; }
 "table"			{ return T_TABLE; }
 "chain"			{ return T_CHAIN; }
 "hook"			{ return T_HOOK; }