summaryrefslogtreecommitdiffstats
path: root/iptables/nft-ipv6.c
diff options
context:
space:
mode:
Diffstat (limited to 'iptables/nft-ipv6.c')
-rw-r--r--iptables/nft-ipv6.c67
1 files changed, 66 insertions, 1 deletions
diff --git a/iptables/nft-ipv6.c b/iptables/nft-ipv6.c
index 7b27d872..107a84e2 100644
--- a/iptables/nft-ipv6.c
+++ b/iptables/nft-ipv6.c
@@ -1,5 +1,5 @@
/*
- * (C) 2012-2013 by Pablo Neira Ayuso <pablo@netfilter.org>
+ * (C) 2012-2014 by Pablo Neira Ayuso <pablo@netfilter.org>
* (C) 2013 by Tomasz Bursztyka <tomasz.bursztyka@linux.intel.com>
*
* This program is free software; you can redistribute it and/or modify
@@ -17,6 +17,7 @@
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/ip6.h>
+#include <netdb.h>
#include <xtables.h>
@@ -376,6 +377,69 @@ static void nft_ipv6_save_counters(const void *data)
save_counters(cs->counters.pcnt, cs->counters.bcnt);
}
+static void xlate_ipv6_addr(const char *selector, const struct in6_addr *addr,
+ int invert, struct xt_buf *buf)
+{
+ char addr_str[INET6_ADDRSTRLEN];
+
+ if (!invert && IN6_IS_ADDR_UNSPECIFIED(addr))
+ return;
+
+ inet_ntop(AF_INET6, addr, addr_str, INET6_ADDRSTRLEN);
+ xt_buf_add(buf, "%s %s%s ", selector, invert ? "!= " : "", addr_str);
+}
+
+static int nft_ipv6_xlate(const void *data, struct xt_buf *buf)
+{
+ const struct iptables_command_state *cs = data;
+ int ret;
+
+ if (cs->fw6.ipv6.iniface[0] != '\0') {
+ xt_buf_add(buf, "iifname %s%s ",
+ cs->fw6.ipv6.invflags & IP6T_INV_VIA_IN ?
+ "!= " : "",
+ cs->fw6.ipv6.iniface);
+ }
+ if (cs->fw6.ipv6.outiface[0] != '\0') {
+ xt_buf_add(buf, "oifname %s%s ",
+ cs->fw6.ipv6.invflags & IP6T_INV_VIA_OUT ?
+ "!= " : "",
+ cs->fw6.ipv6.outiface);
+ }
+
+ if (cs->fw6.ipv6.proto != 0) {
+ const struct protoent *pent =
+ getprotobynumber(cs->fw6.ipv6.proto);
+ char protonum[strlen("255") + 1];
+
+ if (!xlate_find_match(cs, pent->p_name)) {
+ snprintf(protonum, sizeof(protonum), "%u",
+ cs->fw6.ipv6.proto);
+ protonum[sizeof(protonum) - 1] = '\0';
+ xt_buf_add(buf, "ip protocol %s%s ",
+ cs->fw6.ipv6.invflags & IP6T_INV_PROTO ?
+ "!= " : "",
+ pent ? pent->p_name : protonum);
+ }
+ }
+
+ xlate_ipv6_addr("ip saddr", &cs->fw6.ipv6.src,
+ cs->fw6.ipv6.invflags & IP6T_INV_SRCIP, buf);
+ xlate_ipv6_addr("ip daddr", &cs->fw6.ipv6.dst,
+ cs->fw6.ipv6.invflags & IP6T_INV_DSTIP, buf);
+
+ ret = xlate_matches(cs, buf);
+ if (!ret)
+ return ret;
+
+ /* Always add counters per rule, as in iptables */
+ xt_buf_add(buf, "counter ");
+
+ ret = xlate_action(cs, !!(cs->fw6.ipv6.flags & IP6T_F_GOTO), buf);
+
+ return ret;
+}
+
struct nft_family_ops nft_family_ops_ipv6 = {
.add = nft_ipv6_add,
.is_same = nft_ipv6_is_same,
@@ -390,4 +454,5 @@ struct nft_family_ops nft_family_ops_ipv6 = {
.post_parse = nft_ipv6_post_parse,
.parse_target = nft_ipv6_parse_target,
.rule_find = nft_ipv6_rule_find,
+ .xlate = nft_ipv6_xlate,
};