netfilter-devel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Tomasz Bursztyka <tomasz.bursztyka@linux.intel.com>
To: netfilter-devel@vger.kernel.org
Cc: Tomasz Bursztyka <tomasz.bursztyka@linux.intel.com>
Subject: [iptables-nftables RFC PATCH 4/6] nft: Support IPv6 rules manipulation
Date: Thu, 10 Jan 2013 16:29:37 +0200	[thread overview]
Message-ID: <1357828179-18664-5-git-send-email-tomasz.bursztyka@linux.intel.com> (raw)
In-Reply-To: <1357828179-18664-1-git-send-email-tomasz.bursztyka@linux.intel.com>

It firsts moves redondant code into helpers, and then apply the right
sequence according to the family type.

Note: It currently lacks of IPv6 fragments handling support

Signed-off-by: Tomasz Bursztyka <tomasz.bursztyka@linux.intel.com>
---
 iptables/nft.c | 198 ++++++++++++++++++++++++++++++++++++++-------------------
 1 file changed, 134 insertions(+), 64 deletions(-)

diff --git a/iptables/nft.c b/iptables/nft.c
index 78a100e..f12008a 100644
--- a/iptables/nft.c
+++ b/iptables/nft.c
@@ -35,6 +35,8 @@
 
 #include <linux/netfilter/x_tables.h>
 #include <linux/netfilter_ipv4/ip_tables.h>	/* FIXME: only IPV4 by now */
+#include <linux/netfilter_ipv6/ip6_tables.h>
+#include <netinet/ip6.h>
 
 #include <linux/netlink.h>
 #include <linux/netfilter/nfnetlink.h>
@@ -741,6 +743,78 @@ static void add_counters(struct nft_rule *r, uint64_t packets, uint64_t bytes)
 	nft_rule_add_expr(r, expr);
 }
 
+static void add_iniface(struct nft_rule *r, char *iface, int invflags)
+{
+	int iface_len;
+	uint32_t op;
+
+	iface_len = strlen(iface);
+
+	if (invflags & IPT_INV_VIA_IN)
+		op = NFT_CMP_NEQ;
+	else
+		op = NFT_CMP_EQ;
+
+	if (iface[iface_len - 1] == '+') {
+		add_meta(r, NFT_META_IIFNAME);
+		add_cmp_ptr(r, op, iface, iface_len - 1);
+	} else {
+		add_meta(r, NFT_META_IIF);
+		add_cmp_u32(r, if_nametoindex(iface), op);
+	}
+}
+
+static void add_outiface(struct nft_rule *r, char *iface, int invflags)
+{
+	int iface_len;
+	uint32_t op;
+
+	iface_len = strlen(iface);
+
+	if (invflags & IPT_INV_VIA_OUT)
+		op = NFT_CMP_NEQ;
+	else
+		op = NFT_CMP_EQ;
+
+	if (iface[iface_len - 1] == '+') {
+		add_meta(r, NFT_META_OIFNAME);
+		add_cmp_ptr(r, op, iface, iface_len - 1);
+	} else {
+		add_meta(r, NFT_META_OIF);
+		add_cmp_u32(r, if_nametoindex(iface), op);
+	}
+}
+
+static void add_addr(struct nft_rule *r, int offset,
+			void *data, size_t len, int invflags)
+{
+	uint32_t op;
+
+	add_payload(r, offset, len);
+
+	if (invflags & IPT_INV_SRCIP || invflags & IPT_INV_DSTIP)
+		op = NFT_CMP_NEQ;
+	else
+		op = NFT_CMP_EQ;
+
+	add_cmp_ptr(r, op, data, len);
+}
+
+static void add_proto(struct nft_rule *r, int offset, size_t len,
+		      uint32_t proto, int invflags)
+{
+	uint32_t op;
+
+	add_payload(r, offset, len);
+
+	if (invflags & XT_INV_PROTO)
+		op = NFT_CMP_NEQ;
+	else
+		op = NFT_CMP_EQ;
+
+	add_cmp_u32(r, proto, op);
+}
+
 int
 nft_rule_add(struct nft_handle *h, const char *chain, const char *table,
 	     struct iptables_command_state *cs,
@@ -753,6 +827,7 @@ nft_rule_add(struct nft_handle *h, const char *chain, const char *table,
 	int ret = 1;
 	uint32_t op;
 	int flags = append ? NLM_F_APPEND : 0;
+	int ip_flags = 0;
 
 	/* If built-in chains don't exist for this table, create them */
 	nft_chain_builtin_init(h, table, chain, NF_ACCEPT);
@@ -768,77 +843,72 @@ nft_rule_add(struct nft_handle *h, const char *chain, const char *table,
 	nft_rule_attr_set(r, NFT_RULE_ATTR_TABLE, (char *)table);
 	nft_rule_attr_set(r, NFT_RULE_ATTR_CHAIN, (char *)chain);
 
-	if (cs->fw.ip.iniface[0] != '\0') {
-		int iface_len = strlen(cs->fw.ip.iniface);
-
-		if (cs->fw.ip.invflags & IPT_INV_VIA_IN)
-			op = NFT_CMP_NEQ;
-		else
-			op = NFT_CMP_EQ;
-
-		if (cs->fw.ip.iniface[iface_len - 1] == '+') {
-			add_meta(r, NFT_META_IIFNAME);
-			add_cmp_ptr(r, op, cs->fw.ip.iniface, iface_len - 1);
-		} else {
-			add_meta(r, NFT_META_IIF);
-			add_cmp_u32(r, if_nametoindex(cs->fw.ip.iniface), op);
+	switch (h->family) {
+	case AF_INET:
+		if (cs->fw.ip.iniface[0] != '\0')
+			add_iniface(r, cs->fw.ip.iniface, cs->fw.ip.invflags);
+
+		if (cs->fw.ip.outiface[0] != '\0')
+			add_outiface(r, cs->fw.ip.outiface,
+				     cs->fw.ip.invflags);
+
+		if (cs->fw.ip.src.s_addr != 0)
+			add_addr(r, offsetof(struct iphdr, saddr),
+				 &cs->fw.ip.src.s_addr, 4,
+				 cs->fw.ip.invflags);
+
+		if (cs->fw.ip.dst.s_addr != 0)
+			add_addr(r, offsetof(struct iphdr, daddr),
+				 &cs->fw.ip.dst.s_addr, 4,
+				 cs->fw.ip.invflags);
+
+		if (cs->fw.ip.proto != 0)
+			add_proto(r, offsetof(struct iphdr, protocol), 1,
+				  cs->fw.ip.proto, cs->fw.ip.invflags);
+
+		if (cs->fw.ip.flags & IPT_F_FRAG) {
+			add_payload(r, offsetof(struct iphdr, frag_off), 2);
+			/* get the 13 bits that contain the fragment offset */
+			add_bitwise_u16(r, 0x1fff, !0x1fff);
+
+			/* if offset is non-zero, this is a fragment */
+			if (cs->fw.ip.invflags & IPT_INV_FRAG)
+				op = NFT_CMP_EQ;
+			else
+				op = NFT_CMP_NEQ;
+
+			add_cmp_u16(r, 0, op);
 		}
-	}
-	if (cs->fw.ip.outiface[0] != '\0') {
-		int iface_len = strlen(cs->fw.ip.outiface);
 
-		if (cs->fw.ip.invflags & IPT_INV_VIA_OUT)
-			op = NFT_CMP_NEQ;
-		else
-			op = NFT_CMP_EQ;
+		ip_flags = cs->fw.ip.flags;
 
-		if (cs->fw.ip.outiface[iface_len - 1] == '+') {
-			add_meta(r, NFT_META_OIFNAME);
-			add_cmp_ptr(r, op, cs->fw.ip.outiface, iface_len - 1);
-		} else {
-			add_meta(r, NFT_META_OIF);
-			add_cmp_u32(r, if_nametoindex(cs->fw.ip.outiface), op);
-		}
-	}
-	if (cs->fw.ip.src.s_addr != 0) {
-		add_payload(r, offsetof(struct iphdr, saddr), 4);
-		if (cs->fw.ip.invflags & IPT_INV_SRCIP)
-			op = NFT_CMP_NEQ;
-		else
-			op = NFT_CMP_EQ;
+		break;
+	case AF_INET6:
+		if (cs->fw6.ipv6.iniface[0] != '\0')
+			add_iniface(r, cs->fw6.ipv6.iniface,
+				    cs->fw6.ipv6.invflags);
 
-		add_cmp_u32(r, cs->fw.ip.src.s_addr, op);
-	}
-	if (cs->fw.ip.dst.s_addr != 0) {
-		add_payload(r, offsetof(struct iphdr, daddr), 4);
-		if (cs->fw.ip.invflags & IPT_INV_DSTIP)
-			op = NFT_CMP_NEQ;
-		else
-			op = NFT_CMP_EQ;
+		if (cs->fw6.ipv6.outiface[0] != '\0')
+			add_outiface(r, cs->fw6.ipv6.outiface,
+				    cs->fw6.ipv6.invflags);
 
-		add_cmp_u32(r, cs->fw.ip.dst.s_addr, op);
-	}
-	if (cs->fw.ip.proto != 0) {
-		add_payload(r, offsetof(struct iphdr, protocol), 1);
-		if (cs->fw.ip.invflags & XT_INV_PROTO)
-			op = NFT_CMP_NEQ;
-		else
-			op = NFT_CMP_EQ;
+		if (!IN6_IS_ADDR_UNSPECIFIED(&cs->fw6.ipv6.src))
+			add_addr(r, offsetof(struct ip6_hdr, ip6_src),
+				 &cs->fw6.ipv6.src, 16,
+				 cs->fw6.ipv6.invflags);
 
-		add_cmp_u32(r, cs->fw.ip.proto, op);
-	}
-	if (cs->fw.ip.flags & IPT_F_FRAG) {
-		add_payload(r, offsetof(struct iphdr, frag_off), 2);
-		/* get the 13 bits that contain the fragment offset */
-		add_bitwise_u16(r, 0x1fff, !0x1fff);
+		if (!IN6_IS_ADDR_UNSPECIFIED(&cs->fw6.ipv6.dst))
+			add_addr(r, offsetof(struct ip6_hdr, ip6_dst),
+				 &cs->fw6.ipv6.dst, 16,
+				 cs->fw6.ipv6.invflags);
 
-		/* if offset is non-zero, this is a fragment */
-		if (cs->fw.ip.invflags & IPT_INV_FRAG)
-			op = NFT_CMP_EQ;
-		else
-			op = NFT_CMP_NEQ;
+		if (cs->fw6.ipv6.proto != 0)
+			add_proto(r, offsetof(struct ip6_hdr, ip6_nxt), 1,
+				  cs->fw6.ipv6.proto, cs->fw6.ipv6.invflags);
+
+		ip_flags = cs->fw6.ipv6.flags;
 
-		add_cmp_u16(r, 0, op);
+		break;
 	}
 
 	for (matchp = cs->matches; matchp; matchp = matchp->next)
@@ -862,7 +932,7 @@ nft_rule_add(struct nft_handle *h, const char *chain, const char *table,
 			add_target(r, cs->target->t);
 	} else if (strlen(cs->jumpto) > 0) {
 		/* Not standard, then it's a go / jump to chain */
-		if (cs->fw.ip.flags & IPT_F_GOTO)
+		if (ip_flags & IPT_F_GOTO)
 			add_jumpto(r, cs->jumpto, NFT_GOTO);
 		else
 			add_jumpto(r, cs->jumpto, NFT_JUMP);
-- 
1.8.0.2


  parent reply	other threads:[~2013-01-10 14:29 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-01-10 14:29 [iptables-nftables RFC PATCH 0/6] IPv6 Support Tomasz Bursztyka
2013-01-10 14:29 ` [iptables-nftables RFC PATCH 1/6] nft: Add a family attribute to nft_handle Tomasz Bursztyka
2013-01-10 14:29 ` [iptables-nftables RFC PATCH 2/6] xtables: Combine IPv6 support with IPv4 support Tomasz Bursztyka
2013-01-11  9:10   ` [iptables-nftables RFC PATCH - v2 - " Tomasz Bursztyka
2013-01-10 14:29 ` [iptables-nftables RFC PATCH 3/6] nft: Use handle's family attribute instead of hardcoded AF_INET one Tomasz Bursztyka
2013-01-10 14:29 ` Tomasz Bursztyka [this message]
2013-01-10 14:29 ` [iptables-nftables RFC PATCH 5/6] nft: Use the right payload parsing function when saving a rule Tomasz Bursztyka
2013-01-10 14:29 ` [iptables-nftables RFC PATCH 6/6] nft: Handle IPv6 when printing out firewall rules Tomasz Bursztyka
2013-01-13 19:23 ` [iptables-nftables RFC PATCH 0/6] IPv6 Support Pablo Neira Ayuso

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1357828179-18664-5-git-send-email-tomasz.bursztyka@linux.intel.com \
    --to=tomasz.bursztyka@linux.intel.com \
    --cc=netfilter-devel@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).