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
next prev 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).