* [iptables-nftables RFC PATCH 0/6] IPv6 Support
@ 2013-01-10 14:29 Tomasz Bursztyka
2013-01-10 14:29 ` [iptables-nftables RFC PATCH 1/6] nft: Add a family attribute to nft_handle Tomasz Bursztyka
` (6 more replies)
0 siblings, 7 replies; 9+ messages in thread
From: Tomasz Bursztyka @ 2013-01-10 14:29 UTC (permalink / raw)
To: netfilter-devel; +Cc: Tomasz Bursztyka
Hi,
Here is an attempt to get iptables-nftables supporting IPv6.
I haven't tested it really, so I send it more as an RFC.
Starting from xtables.c which supports only IPv4, patch 2 combines the support for IPv6 in it.
The family attribute provided in patch 1 is set then used in nft.c to use it accordingly, in patch 3.
Patch 4 finalizes it in handling the right informations for rule manipulations depending on the family.
Patch 5 and 6 then adds the support of IPv6 when it comes to respectively save and print the firewall.
Please review,
Tomasz Bursztyka (6):
nft: Add a family attribute to nft_handle
xtables: Combine IPv6 support with IPv4 support
nft: Use handle's family attribute instead of hardcoded AF_INET one
nft: Support IPv6 rules manipulation
nft: Use the right payload parsing function when saving a rule
nft: Handle IPv6 when printing out firewall rules
iptables/nft.c | 651 +++++++++++++++++++++++++++++++++++++++--------------
iptables/nft.h | 1 +
iptables/xtables.c | 378 +++++++++++++++++++++----------
3 files changed, 741 insertions(+), 289 deletions(-)
--
1.8.0.2
^ permalink raw reply [flat|nested] 9+ messages in thread
* [iptables-nftables RFC PATCH 1/6] nft: Add a family attribute to nft_handle
2013-01-10 14:29 [iptables-nftables RFC PATCH 0/6] IPv6 Support Tomasz Bursztyka
@ 2013-01-10 14:29 ` Tomasz Bursztyka
2013-01-10 14:29 ` [iptables-nftables RFC PATCH 2/6] xtables: Combine IPv6 support with IPv4 support Tomasz Bursztyka
` (5 subsequent siblings)
6 siblings, 0 replies; 9+ messages in thread
From: Tomasz Bursztyka @ 2013-01-10 14:29 UTC (permalink / raw)
To: netfilter-devel; +Cc: Tomasz Bursztyka
Signed-off-by: Tomasz Bursztyka <tomasz.bursztyka@linux.intel.com>
---
iptables/nft.h | 1 +
1 file changed, 1 insertion(+)
diff --git a/iptables/nft.h b/iptables/nft.h
index aed2498..1bd9ccc 100644
--- a/iptables/nft.h
+++ b/iptables/nft.h
@@ -4,6 +4,7 @@
#include "xshared.h"
struct nft_handle {
+ int family;
struct mnl_socket *nl;
uint32_t portid;
uint32_t seq;
--
1.8.0.2
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [iptables-nftables RFC PATCH 2/6] xtables: Combine IPv6 support with IPv4 support
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 ` 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
` (4 subsequent siblings)
6 siblings, 1 reply; 9+ messages in thread
From: Tomasz Bursztyka @ 2013-01-10 14:29 UTC (permalink / raw)
To: netfilter-devel; +Cc: Tomasz Bursztyka
Instead of having separate binaries for IPv4 and IPv6, it combines
both supports together in the same place and let the nft handle
knows about which family is in use.
Signed-off-by: Tomasz Bursztyka <tomasz.bursztyka@linux.intel.com>
---
iptables/xtables.c | 378 ++++++++++++++++++++++++++++++++++++-----------------
1 file changed, 261 insertions(+), 117 deletions(-)
diff --git a/iptables/xtables.c b/iptables/xtables.c
index 89ccd7f..284316c 100644
--- a/iptables/xtables.c
+++ b/iptables/xtables.c
@@ -204,6 +204,20 @@ enum {
IPT_DOTTED_MASK
};
+struct addr_mask {
+ union {
+ struct in_addr *v4;
+ struct in6_addr *v6;
+ } addr;
+
+ unsigned int naddrs;
+
+ union {
+ struct in_addr *v4;
+ struct in6_addr *v6;
+ } mask;
+};
+
static void __attribute__((noreturn))
exit_tryhelp(int status)
{
@@ -370,6 +384,15 @@ add_command(unsigned int *cmd, const int newcmd, const int othercmds,
* return global static data.
*/
+/* These are invalid numbers as upper layer protocol */
+static int is_exthdr(uint16_t proto)
+{
+ return (proto == IPPROTO_ROUTING ||
+ proto == IPPROTO_FRAGMENT ||
+ proto == IPPROTO_AH ||
+ proto == IPPROTO_DSTOPTS);
+}
+
/* Christophe Burki wants `-p 6' to imply `-m tcp'. */
/* Can't be zero. */
static int
@@ -430,26 +453,35 @@ static int
add_entry(const char *chain,
const char *table,
struct iptables_command_state *cs,
- unsigned int nsaddrs,
- const struct in_addr saddrs[],
- const struct in_addr smasks[],
- unsigned int ndaddrs,
- const struct in_addr daddrs[],
- const struct in_addr dmasks[],
+ int family,
+ const struct addr_mask s,
+ const struct addr_mask d,
bool verbose, struct nft_handle *h, bool append)
{
unsigned int i, j;
int ret = 1;
- for (i = 0; i < nsaddrs; i++) {
- cs->fw.ip.src.s_addr = saddrs[i].s_addr;
- cs->fw.ip.smsk.s_addr = smasks[i].s_addr;
- for (j = 0; j < ndaddrs; j++) {
- cs->fw.ip.dst.s_addr = daddrs[j].s_addr;
- cs->fw.ip.dmsk.s_addr = dmasks[j].s_addr;
+ for (i = 0; i < s.naddrs; i++) {
+ if (family == AF_INET) {
+ cs->fw.ip.src.s_addr = s.addr.v4[i].s_addr;
+ cs->fw.ip.smsk.s_addr = s.mask.v4[i].s_addr;
+ for (j = 0; j < d.naddrs; j++) {
+ cs->fw.ip.dst.s_addr = d.addr.v4[j].s_addr;
+ cs->fw.ip.dmsk.s_addr = d.mask.v4[j].s_addr;
- ret = nft_rule_add(h, chain, table,
- cs, append, 0, verbose);
+ ret = nft_rule_add(h, chain, table,
+ cs, append, 0, verbose);
+ }
+ } else if (family == AF_INET6) {
+ cs->fw6.ipv6.src = s.addr.v6[i];
+ cs->fw6.ipv6.smsk = s.mask.v6[i];
+ for (j = 0; j < d.naddrs; j++) {
+ cs->fw6.ipv6.dst = d.addr.v6[j];
+ cs->fw6.ipv6.dmsk = d.mask.v6[j];
+
+ ret = nft_rule_add(h, chain, table,
+ cs, append, 0, verbose);
+ }
}
}
@@ -460,14 +492,23 @@ static int
replace_entry(const char *chain, const char *table,
struct iptables_command_state *cs,
unsigned int rulenum,
- const struct in_addr *saddr, const struct in_addr *smask,
- const struct in_addr *daddr, const struct in_addr *dmask,
+ int family,
+ const struct addr_mask s,
+ const struct addr_mask d,
bool verbose, struct nft_handle *h)
{
- cs->fw.ip.src.s_addr = saddr->s_addr;
- cs->fw.ip.dst.s_addr = daddr->s_addr;
- cs->fw.ip.smsk.s_addr = smask->s_addr;
- cs->fw.ip.dmsk.s_addr = dmask->s_addr;
+ if (family == AF_INET) {
+ cs->fw.ip.src.s_addr = s.addr.v4->s_addr;
+ cs->fw.ip.dst.s_addr = d.addr.v4->s_addr;
+ cs->fw.ip.smsk.s_addr = s.mask.v4->s_addr;
+ cs->fw.ip.dmsk.s_addr = d.mask.v4->s_addr;
+ } else if (family == AF_INET6) {
+ cs->fw6.ipv6.src = *s.addr.v6;
+ cs->fw6.ipv6.dst = *d.addr.v6;
+ cs->fw6.ipv6.smsk = *s.mask.v6;
+ cs->fw6.ipv6.dmsk = *d.mask.v6;
+ } else
+ return 1;
return nft_rule_replace(h, chain, table, cs, rulenum, verbose);
}
@@ -475,25 +516,34 @@ replace_entry(const char *chain, const char *table,
static int
delete_entry(const char *chain, const char *table,
struct iptables_command_state *cs,
- unsigned int nsaddrs,
- const struct in_addr saddrs[],
- const struct in_addr smasks[],
- unsigned int ndaddrs,
- const struct in_addr daddrs[],
- const struct in_addr dmasks[],
+ int family,
+ const struct addr_mask s,
+ const struct addr_mask d,
bool verbose,
struct nft_handle *h)
{
unsigned int i, j;
int ret = 1;
- for (i = 0; i < nsaddrs; i++) {
- cs->fw.ip.src.s_addr = saddrs[i].s_addr;
- cs->fw.ip.smsk.s_addr = smasks[i].s_addr;
- for (j = 0; j < ndaddrs; j++) {
- cs->fw.ip.dst.s_addr = daddrs[j].s_addr;
- cs->fw.ip.dmsk.s_addr = dmasks[j].s_addr;
- ret = nft_rule_delete(h, chain, table, cs, verbose);
+ for (i = 0; i < s.naddrs; i++) {
+ if (family == AF_INET) {
+ cs->fw.ip.src.s_addr = s.addr.v4[i].s_addr;
+ cs->fw.ip.smsk.s_addr = s.mask.v4[i].s_addr;
+ for (j = 0; j < d.naddrs; j++) {
+ cs->fw.ip.dst.s_addr = d.addr.v4[j].s_addr;
+ cs->fw.ip.dmsk.s_addr = d.mask.v4[j].s_addr;
+ ret = nft_rule_delete(h, chain,
+ table, cs, verbose);
+ }
+ } else if (family == AF_INET6) {
+ cs->fw6.ipv6.src = s.addr.v6[i];
+ cs->fw6.ipv6.smsk = s.mask.v6[i];
+ for (j = 0; j < d.naddrs; j++) {
+ cs->fw6.ipv6.dst = d.addr.v6[j];
+ cs->fw6.ipv6.dmsk = d.mask.v6[j];
+ ret = nft_rule_delete(h, chain,
+ table, cs, verbose);
+ }
}
}
@@ -503,21 +553,33 @@ delete_entry(const char *chain, const char *table,
static int
check_entry(const char *chain, const char *table,
struct iptables_command_state *cs,
- unsigned int nsaddrs, const struct in_addr *saddrs,
- const struct in_addr *smasks, unsigned int ndaddrs,
- const struct in_addr *daddrs, const struct in_addr *dmasks,
+ int family,
+ const struct addr_mask s,
+ const struct addr_mask d,
bool verbose, struct nft_handle *h)
{
unsigned int i, j;
int ret = 1;
- for (i = 0; i < nsaddrs; i++) {
- cs->fw.ip.src.s_addr = saddrs[i].s_addr;
- cs->fw.ip.smsk.s_addr = smasks[i].s_addr;
- for (j = 0; j < ndaddrs; j++) {
- cs->fw.ip.dst.s_addr = daddrs[j].s_addr;
- cs->fw.ip.dmsk.s_addr = dmasks[j].s_addr;
- ret = nft_rule_check(h, chain, table, cs, verbose);
+ for (i = 0; i < s.naddrs; i++) {
+ if (family == AF_INET) {
+ cs->fw.ip.src.s_addr = s.addr.v4[i].s_addr;
+ cs->fw.ip.smsk.s_addr = s.mask.v4[i].s_addr;
+ for (j = 0; j < d.naddrs; j++) {
+ cs->fw.ip.dst.s_addr = d.addr.v4[j].s_addr;
+ cs->fw.ip.dmsk.s_addr = d.mask.v4[j].s_addr;
+ ret = nft_rule_check(h, chain,
+ table, cs, verbose);
+ }
+ } else if (family == AF_INET6) {
+ cs->fw6.ipv6.src = s.addr.v6[i];
+ cs->fw6.ipv6.smsk = s.mask.v6[i];
+ for (j = 0; j < d.naddrs; j++) {
+ cs->fw6.ipv6.dst = d.addr.v6[j];
+ cs->fw6.ipv6.dmsk = d.mask.v6[j];
+ ret = nft_rule_check(h, chain,
+ table, cs, verbose);
+ }
}
}
@@ -657,9 +719,8 @@ static void command_match(struct iptables_command_state *cs)
int do_commandx(struct nft_handle *h, int argc, char *argv[], char **table)
{
struct iptables_command_state cs;
- unsigned int nsaddrs = 0, ndaddrs = 0;
- struct in_addr *saddrs = NULL, *smasks = NULL;
- struct in_addr *daddrs = NULL, *dmasks = NULL;
+ struct addr_mask s;
+ struct addr_mask d;
int verbose = 0;
const char *chain = NULL;
@@ -671,7 +732,16 @@ int do_commandx(struct nft_handle *h, int argc, char *argv[], char **table)
struct xtables_match *m;
struct xtables_rule_match *matchp;
struct xtables_target *t;
- unsigned long long cnt;
+ unsigned long long pcnt_cnt = 0, bcnt_cnt = 0;
+
+ int family = AF_INET;
+ u_int16_t proto = 0;
+ u_int8_t flags = 0, invflags = 0;
+ char iniface[IFNAMSIZ], outiface[IFNAMSIZ];
+ unsigned char iniface_mask[IFNAMSIZ], outiface_mask[IFNAMSIZ];
+
+ memset(&s, 0, sizeof(s));
+ memset(&d, 0, sizeof(d));
memset(&cs, 0, sizeof(cs));
cs.jumpto = "";
@@ -861,7 +931,7 @@ int do_commandx(struct nft_handle *h, int argc, char *argv[], char **table)
* Option selection
*/
case 'p':
- set_option(&cs.options, OPT_PROTOCOL, &cs.fw.ip.invflags,
+ set_option(&cs.options, OPT_PROTOCOL, &invflags,
cs.invert);
/* Canonicalize into lower case */
@@ -869,31 +939,29 @@ int do_commandx(struct nft_handle *h, int argc, char *argv[], char **table)
*cs.protocol = tolower(*cs.protocol);
cs.protocol = optarg;
- cs.fw.ip.proto = xtables_parse_protocol(cs.protocol);
+ proto = xtables_parse_protocol(cs.protocol);
- if (cs.fw.ip.proto == 0
- && (cs.fw.ip.invflags & XT_INV_PROTO))
+ if (proto == 0 && (invflags & XT_INV_PROTO))
xtables_error(PARAMETER_PROBLEM,
"rule would never match protocol");
break;
case 's':
- set_option(&cs.options, OPT_SOURCE, &cs.fw.ip.invflags,
+ set_option(&cs.options, OPT_SOURCE, &invflags,
cs.invert);
shostnetworkmask = optarg;
break;
case 'd':
- set_option(&cs.options, OPT_DESTINATION, &cs.fw.ip.invflags,
+ set_option(&cs.options, OPT_DESTINATION, &invflags,
cs.invert);
dhostnetworkmask = optarg;
break;
#ifdef IPT_F_GOTO
case 'g':
- set_option(&cs.options, OPT_JUMP, &cs.fw.ip.invflags,
+ set_option(&cs.options, OPT_JUMP, &invflags,
cs.invert);
- cs.fw.ip.flags |= IPT_F_GOTO;
cs.jumpto = parse_target(optarg);
break;
#endif
@@ -908,11 +976,11 @@ int do_commandx(struct nft_handle *h, int argc, char *argv[], char **table)
xtables_error(PARAMETER_PROBLEM,
"Empty interface is likely to be "
"undesired");
- set_option(&cs.options, OPT_VIANAMEIN, &cs.fw.ip.invflags,
+ set_option(&cs.options, OPT_VIANAMEIN, &invflags,
cs.invert);
xtables_parse_interface(optarg,
- cs.fw.ip.iniface,
- cs.fw.ip.iniface_mask);
+ iniface,
+ iniface_mask);
break;
case 'o':
@@ -920,23 +988,23 @@ int do_commandx(struct nft_handle *h, int argc, char *argv[], char **table)
xtables_error(PARAMETER_PROBLEM,
"Empty interface is likely to be "
"undesired");
- set_option(&cs.options, OPT_VIANAMEOUT, &cs.fw.ip.invflags,
+ set_option(&cs.options, OPT_VIANAMEOUT, &invflags,
cs.invert);
xtables_parse_interface(optarg,
- cs.fw.ip.outiface,
- cs.fw.ip.outiface_mask);
+ outiface,
+ outiface_mask);
break;
case 'f':
- set_option(&cs.options, OPT_FRAGMENT, &cs.fw.ip.invflags,
+ set_option(&cs.options, OPT_FRAGMENT, &invflags,
cs.invert);
- cs.fw.ip.flags |= IPT_F_FRAG;
+ flags |= IPT_F_FRAG;
break;
case 'v':
if (!verbose)
set_option(&cs.options, OPT_VERBOSE,
- &cs.fw.ip.invflags, cs.invert);
+ &invflags, cs.invert);
verbose++;
break;
@@ -945,7 +1013,7 @@ int do_commandx(struct nft_handle *h, int argc, char *argv[], char **table)
break;
case 'n':
- set_option(&cs.options, OPT_NUMERIC, &cs.fw.ip.invflags,
+ set_option(&cs.options, OPT_NUMERIC, &invflags,
cs.invert);
break;
@@ -957,7 +1025,7 @@ int do_commandx(struct nft_handle *h, int argc, char *argv[], char **table)
break;
case 'x':
- set_option(&cs.options, OPT_EXPANDED, &cs.fw.ip.invflags,
+ set_option(&cs.options, OPT_EXPANDED, &invflags,
cs.invert);
break;
@@ -970,7 +1038,7 @@ int do_commandx(struct nft_handle *h, int argc, char *argv[], char **table)
exit(0);
case '0':
- set_option(&cs.options, OPT_LINENUMBERS, &cs.fw.ip.invflags,
+ set_option(&cs.options, OPT_LINENUMBERS, &invflags,
cs.invert);
break;
@@ -980,7 +1048,7 @@ int do_commandx(struct nft_handle *h, int argc, char *argv[], char **table)
case 'c':
- set_option(&cs.options, OPT_COUNTERS, &cs.fw.ip.invflags,
+ set_option(&cs.options, OPT_COUNTERS, &invflags,
cs.invert);
pcnt = optarg;
bcnt = strchr(pcnt + 1, ',');
@@ -994,29 +1062,25 @@ int do_commandx(struct nft_handle *h, int argc, char *argv[], char **table)
"-%c requires packet and byte counter",
opt2char(OPT_COUNTERS));
- if (sscanf(pcnt, "%llu", &cnt) != 1)
+ if (sscanf(pcnt, "%llu", &pcnt_cnt) != 1)
xtables_error(PARAMETER_PROBLEM,
"-%c packet counter not numeric",
opt2char(OPT_COUNTERS));
- cs.counters.pcnt = cnt;
- if (sscanf(bcnt, "%llu", &cnt) != 1)
+ if (sscanf(bcnt, "%llu", &bcnt_cnt) != 1)
xtables_error(PARAMETER_PROBLEM,
"-%c byte counter not numeric",
opt2char(OPT_COUNTERS));
- cs.counters.bcnt = cnt;
break;
case '4':
- /* This is indeed the IPv4 iptables */
+ if (family != AF_INET)
+ exit_tryhelp(2);
break;
case '6':
- /* This is not the IPv6 ip6tables */
- if (line != -1)
- return 1; /* success: line ignored */
- fprintf(stderr, "This is the IPv4 version of iptables.\n");
- exit_tryhelp(2);
+ family = AF_INET6;
+ break;
case 1: /* non option */
if (optarg[0] == '!' && optarg[1] == '\0') {
@@ -1063,27 +1127,109 @@ int do_commandx(struct nft_handle *h, int argc, char *argv[], char **table)
xtables_error(PARAMETER_PROBLEM,
"nothing appropriate following !");
- if (command & (CMD_REPLACE | CMD_INSERT | CMD_DELETE | CMD_APPEND | CMD_CHECK)) {
- if (!(cs.options & OPT_DESTINATION))
- dhostnetworkmask = "0.0.0.0/0";
- if (!(cs.options & OPT_SOURCE))
- shostnetworkmask = "0.0.0.0/0";
- }
+ switch (family) {
+ case AF_INET:
+ cs.fw.ip.proto = proto;
+ cs.fw.ip.invflags = invflags;
+ cs.fw.ip.flags = flags;
- if (shostnetworkmask)
- xtables_ipparse_multiple(shostnetworkmask, &saddrs,
- &smasks, &nsaddrs);
+ strncpy(cs.fw.ip.iniface, iniface, IFNAMSIZ);
+ memcpy(cs.fw.ip.iniface_mask,
+ iniface_mask, IFNAMSIZ*sizeof(unsigned char));
- if (dhostnetworkmask)
- xtables_ipparse_multiple(dhostnetworkmask, &daddrs,
- &dmasks, &ndaddrs);
+ strncpy(cs.fw.ip.outiface, outiface, IFNAMSIZ);
+ memcpy(cs.fw.ip.outiface_mask,
+ outiface_mask, IFNAMSIZ*sizeof(unsigned char));
- if ((nsaddrs > 1 || ndaddrs > 1) &&
- (cs.fw.ip.invflags & (IPT_INV_SRCIP | IPT_INV_DSTIP)))
- xtables_error(PARAMETER_PROBLEM, "! not allowed with multiple"
- " source or destination IP addresses");
+ if (strlen(cs.jumpto) != 0)
+ cs.fw.ip.flags |= IPT_F_GOTO;
- if (command == CMD_REPLACE && (nsaddrs != 1 || ndaddrs != 1))
+ cs.counters.pcnt = pcnt_cnt;
+ cs.counters.bcnt = bcnt_cnt;
+
+ if (command & (CMD_REPLACE | CMD_INSERT |
+ CMD_DELETE | CMD_APPEND | CMD_CHECK)) {
+ if (!(cs.options & OPT_DESTINATION))
+ dhostnetworkmask = "0.0.0.0/0";
+ if (!(cs.options & OPT_SOURCE))
+ shostnetworkmask = "0.0.0.0/0";
+ }
+
+ if (shostnetworkmask)
+ xtables_ipparse_multiple(shostnetworkmask, &s.addr.v4,
+ &s.mask.v4, &s.naddrs);
+ if (dhostnetworkmask)
+ xtables_ipparse_multiple(dhostnetworkmask, &d.addr.v4,
+ &d.mask.v4, &d.naddrs);
+
+ if ((s.naddrs > 1 || d.naddrs > 1) &&
+ (cs.fw.ip.invflags & (IPT_INV_SRCIP | IPT_INV_DSTIP)))
+ xtables_error(PARAMETER_PROBLEM,
+ "! not allowed with multiple"
+ " source or destination IP addresses");
+ break;
+ case AF_INET6:
+ if (proto != 0)
+ flags |= IP6T_F_PROTO;
+
+ cs.fw6.ipv6.proto = proto;
+ cs.fw6.ipv6.invflags = invflags;
+ cs.fw6.ipv6.flags = flags;
+
+ if (flags & IPT_F_FRAG)
+ xtables_error(PARAMETER_PROBLEM,
+ "-f is not valid on IPv6");
+
+ if (is_exthdr(cs.fw6.ipv6.proto)
+ && (cs.fw6.ipv6.invflags & XT_INV_PROTO) == 0)
+ fprintf(stderr,
+ "Warning: never matched protocol: %s. "
+ "use extension match instead.\n",
+ cs.protocol);
+
+ strncpy(cs.fw6.ipv6.iniface, iniface, IFNAMSIZ);
+ memcpy(cs.fw6.ipv6.iniface_mask,
+ iniface_mask, IFNAMSIZ*sizeof(unsigned char));
+
+ strncpy(cs.fw6.ipv6.outiface, outiface, IFNAMSIZ);
+ memcpy(cs.fw6.ipv6.outiface_mask,
+ outiface_mask, IFNAMSIZ*sizeof(unsigned char));
+
+ if (strlen(cs.jumpto) != 0)
+ cs.fw6.ipv6.flags |= IP6T_F_GOTO;
+
+ cs.fw6.counters.pcnt = pcnt_cnt;
+ cs.fw6.counters.bcnt = bcnt_cnt;
+
+ if (command & (CMD_REPLACE | CMD_INSERT |
+ CMD_DELETE | CMD_APPEND | CMD_CHECK)) {
+ if (!(cs.options & OPT_DESTINATION))
+ dhostnetworkmask = "::0/0";
+ if (!(cs.options & OPT_SOURCE))
+ shostnetworkmask = "::0/0";
+ }
+
+ if (shostnetworkmask)
+ xtables_ip6parse_multiple(shostnetworkmask, &s.addr.v6,
+ &s.mask.v6, &s.naddrs);
+ if (dhostnetworkmask)
+ xtables_ip6parse_multiple(dhostnetworkmask, &d.addr.v6,
+ &d.mask.v6, &d.naddrs);
+
+ if ((s.naddrs > 1 || d.naddrs > 1) &&
+ (cs.fw6.ipv6.invflags & (IP6T_INV_SRCIP | IP6T_INV_DSTIP)))
+ xtables_error(PARAMETER_PROBLEM,
+ "! not allowed with multiple"
+ " source or destination IP addresses");
+ break;
+ default:
+ exit_tryhelp(2);
+ break;
+ }
+
+ h->family = family;
+
+ if (command == CMD_REPLACE && (s.naddrs != 1 || d.naddrs != 1))
xtables_error(PARAMETER_PROBLEM, "Replacement rule does not "
"specify a unique address");
@@ -1128,39 +1274,30 @@ int do_commandx(struct nft_handle *h, int argc, char *argv[], char **table)
switch (command) {
case CMD_APPEND:
- ret = add_entry(chain, *table, &cs,
- nsaddrs, saddrs, smasks,
- ndaddrs, daddrs, dmasks,
- cs.options&OPT_VERBOSE,
+ ret = add_entry(chain, *table, &cs, family,
+ s, d, cs.options&OPT_VERBOSE,
h, true);
break;
case CMD_DELETE:
- ret = delete_entry(chain, *table, &cs,
- nsaddrs, saddrs, smasks,
- ndaddrs, daddrs, dmasks,
- cs.options&OPT_VERBOSE, h);
+ ret = delete_entry(chain, *table, &cs, family,
+ s, d, cs.options&OPT_VERBOSE, h);
break;
case CMD_DELETE_NUM:
ret = nft_rule_delete_num(h, chain, *table, rulenum - 1, verbose);
break;
case CMD_CHECK:
- ret = check_entry(chain, *table, &cs,
- nsaddrs, saddrs, smasks,
- ndaddrs, daddrs, dmasks,
- cs.options&OPT_VERBOSE, h);
+ ret = check_entry(chain, *table, &cs, family,
+ s, d, cs.options&OPT_VERBOSE, h);
break;
case CMD_REPLACE:
/* FIXME replace at rulenum */
ret = replace_entry(chain, *table, &cs, rulenum - 1,
- saddrs, smasks, daddrs, dmasks,
- cs.options&OPT_VERBOSE, h);
+ family, s, d, cs.options&OPT_VERBOSE, h);
break;
case CMD_INSERT:
/* FIXME insert at rulenum */
- ret = add_entry(chain, *table, &cs,
- nsaddrs, saddrs, smasks,
- ndaddrs, daddrs, dmasks,
- cs.options&OPT_VERBOSE, h, false);
+ ret = add_entry(chain, *table, &cs, family,
+ s, d, cs.options&OPT_VERBOSE, h, false);
break;
case CMD_FLUSH:
ret = nft_rule_flush(h, chain, *table);
@@ -1226,10 +1363,17 @@ int do_commandx(struct nft_handle *h, int argc, char *argv[], char **table)
clear_rule_matches(&cs.matches);
- free(saddrs);
- free(smasks);
- free(daddrs);
- free(dmasks);
+ if (family == AF_INET) {
+ free(s.addr.v4);
+ free(s.mask.v4);
+ free(d.addr.v4);
+ free(d.mask.v4);
+ } else if (family == AF_INET6) {
+ free(s.addr.v6);
+ free(s.mask.v6);
+ free(d.addr.v6);
+ free(d.mask.v6);
+ }
xtables_free_opts(1);
return ret;
--
1.8.0.2
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [iptables-nftables RFC PATCH 3/6] nft: Use handle's family attribute instead of hardcoded AF_INET one
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-10 14:29 ` Tomasz Bursztyka
2013-01-10 14:29 ` [iptables-nftables RFC PATCH 4/6] nft: Support IPv6 rules manipulation Tomasz Bursztyka
` (3 subsequent siblings)
6 siblings, 0 replies; 9+ messages in thread
From: Tomasz Bursztyka @ 2013-01-10 14:29 UTC (permalink / raw)
To: netfilter-devel; +Cc: Tomasz Bursztyka
This permits to deal with the right family in use, provided by xtables.c
Signed-off-by: Tomasz Bursztyka <tomasz.bursztyka@linux.intel.com>
---
iptables/nft.c | 30 +++++++++++++++---------------
1 file changed, 15 insertions(+), 15 deletions(-)
diff --git a/iptables/nft.c b/iptables/nft.c
index 9296b88..78a100e 100644
--- a/iptables/nft.c
+++ b/iptables/nft.c
@@ -248,7 +248,7 @@ nft_table_builtin_add(struct nft_handle *h, struct builtin_table *_t,
NFT_TABLE_F_DORMANT);
}
- nlh = nft_table_nlmsg_build_hdr(buf, NFT_MSG_NEWTABLE, AF_INET,
+ nlh = nft_table_nlmsg_build_hdr(buf, NFT_MSG_NEWTABLE, h->family,
NLM_F_ACK|NLM_F_EXCL, h->seq);
nft_table_nlmsg_build_payload(nlh, t);
nft_table_free(t);
@@ -294,7 +294,7 @@ nft_chain_builtin_add(struct nft_handle *h, struct builtin_table *table,
return;
/* NLM_F_CREATE requests module autoloading */
- nlh = nft_chain_nlmsg_build_hdr(buf, NFT_MSG_NEWCHAIN, AF_INET,
+ nlh = nft_chain_nlmsg_build_hdr(buf, NFT_MSG_NEWCHAIN, h->family,
NLM_F_ACK|NLM_F_EXCL|NLM_F_CREATE,
h->seq);
nft_chain_nlmsg_build_payload(nlh, c);
@@ -410,7 +410,7 @@ int nft_table_add(struct nft_handle *h, const struct nft_table *t)
char buf[MNL_SOCKET_BUFFER_SIZE];
struct nlmsghdr *nlh;
- nlh = nft_table_nlmsg_build_hdr(buf, NFT_MSG_NEWTABLE, AF_INET,
+ nlh = nft_table_nlmsg_build_hdr(buf, NFT_MSG_NEWTABLE, h->family,
NLM_F_ACK|NLM_F_EXCL, h->seq);
nft_table_nlmsg_build_payload(nlh, t);
@@ -422,7 +422,7 @@ int nft_chain_add(struct nft_handle *h, const struct nft_chain *c)
char buf[MNL_SOCKET_BUFFER_SIZE];
struct nlmsghdr *nlh;
- nlh = nft_chain_nlmsg_build_hdr(buf, NFT_MSG_NEWCHAIN, AF_INET,
+ nlh = nft_chain_nlmsg_build_hdr(buf, NFT_MSG_NEWCHAIN, h->family,
NLM_F_ACK|NLM_F_EXCL, h->seq);
nft_chain_nlmsg_build_payload(nlh, c);
@@ -464,7 +464,7 @@ int nft_table_wake_dormant(struct nft_handle *h, const char *table)
nft_table_attr_set(t, NFT_TABLE_ATTR_NAME, (char *)table);
nft_table_attr_set_u32(t, NFT_TABLE_ATTR_FLAGS, 0);
- nlh = nft_table_nlmsg_build_hdr(buf, NFT_MSG_NEWTABLE, AF_INET,
+ nlh = nft_table_nlmsg_build_hdr(buf, NFT_MSG_NEWTABLE, h->family,
NLM_F_ACK, h->seq);
nft_table_nlmsg_build_payload(nlh, t);
nft_table_free(t);
@@ -525,7 +525,7 @@ __nft_chain_set(struct nft_handle *h, const char *table,
counters->pcnt);
}
- nlh = nft_chain_nlmsg_build_hdr(buf, NFT_MSG_NEWCHAIN, AF_INET,
+ nlh = nft_chain_nlmsg_build_hdr(buf, NFT_MSG_NEWCHAIN, h->family,
NLM_F_ACK, h->seq);
nft_chain_nlmsg_build_payload(nlh, c);
@@ -877,7 +877,7 @@ nft_rule_add(struct nft_handle *h, const char *chain, const char *table,
}
nlh = nft_rule_nlmsg_build_hdr(buf, NFT_MSG_NEWRULE,
- AF_INET, flags, h->seq);
+ h->family, flags, h->seq);
nft_rule_nlmsg_build_payload(nlh, r);
@@ -1328,7 +1328,7 @@ static struct nft_chain_list *nft_chain_list_get(struct nft_handle *h)
return 0;
}
- nlh = nft_chain_nlmsg_build_hdr(buf, NFT_MSG_GETCHAIN, AF_INET,
+ nlh = nft_chain_nlmsg_build_hdr(buf, NFT_MSG_GETCHAIN, h->family,
NLM_F_DUMP, h->seq);
ret = mnl_talk(h, nlh, nft_chain_list_cb, list);
@@ -1440,7 +1440,7 @@ static struct nft_rule_list *nft_rule_list_get(struct nft_handle *h)
return 0;
}
- nlh = nft_rule_nlmsg_build_hdr(buf, NFT_MSG_GETRULE, AF_INET,
+ nlh = nft_rule_nlmsg_build_hdr(buf, NFT_MSG_GETRULE, h->family,
NLM_F_DUMP, h->seq);
ret = mnl_talk(h, nlh, nft_rule_list_cb, list);
@@ -1506,7 +1506,7 @@ __nft_rule_flush(struct nft_handle *h, const char *table, const char *chain)
nft_rule_attr_set(r, NFT_RULE_ATTR_CHAIN, (char *)chain);
/* Delete all rules in this table + chain */
- nlh = nft_chain_nlmsg_build_hdr(buf, NFT_MSG_DELRULE, AF_INET,
+ nlh = nft_chain_nlmsg_build_hdr(buf, NFT_MSG_DELRULE, h->family,
NLM_F_ACK, h->seq);
nft_rule_nlmsg_build_payload(nlh, r);
nft_rule_free(r);
@@ -1583,7 +1583,7 @@ int nft_chain_user_add(struct nft_handle *h, const char *chain, const char *tabl
nft_chain_attr_set(c, NFT_CHAIN_ATTR_TABLE, (char *)table);
nft_chain_attr_set(c, NFT_CHAIN_ATTR_NAME, (char *)chain);
- nlh = nft_chain_nlmsg_build_hdr(buf, NFT_MSG_NEWCHAIN, AF_INET,
+ nlh = nft_chain_nlmsg_build_hdr(buf, NFT_MSG_NEWCHAIN, h->family,
NLM_F_ACK|NLM_F_EXCL, h->seq);
nft_chain_nlmsg_build_payload(nlh, c);
nft_chain_free(c);
@@ -1604,7 +1604,7 @@ static int __nft_chain_del(struct nft_handle *h, struct nft_chain *c)
struct nlmsghdr *nlh;
int ret;
- nlh = nft_chain_nlmsg_build_hdr(buf, NFT_MSG_DELCHAIN, AF_INET,
+ nlh = nft_chain_nlmsg_build_hdr(buf, NFT_MSG_DELCHAIN, h->family,
NLM_F_ACK, h->seq);
nft_chain_nlmsg_build_payload(nlh, c);
@@ -1750,7 +1750,7 @@ int nft_chain_user_rename(struct nft_handle *h,const char *chain,
nft_chain_attr_set(c, NFT_CHAIN_ATTR_NAME, (char *)newname);
nft_chain_attr_set_u64(c, NFT_CHAIN_ATTR_HANDLE, handle);
- nlh = nft_chain_nlmsg_build_hdr(buf, NFT_MSG_NEWCHAIN, AF_INET,
+ nlh = nft_chain_nlmsg_build_hdr(buf, NFT_MSG_NEWCHAIN, h->family,
NLM_F_ACK, h->seq);
nft_chain_nlmsg_build_payload(nlh, c);
nft_chain_free(c);
@@ -1803,7 +1803,7 @@ static struct nft_table_list *nft_table_list_get(struct nft_handle *h)
return 0;
}
- nlh = nft_rule_nlmsg_build_hdr(buf, NFT_MSG_GETTABLE, AF_INET,
+ nlh = nft_rule_nlmsg_build_hdr(buf, NFT_MSG_GETTABLE, h->family,
NLM_F_DUMP, h->seq);
ret = mnl_talk(h, nlh, nft_table_list_cb, list);
@@ -2342,7 +2342,7 @@ __nft_rule_del(struct nft_handle *h, struct nft_rule *r)
struct nlmsghdr *nlh;
int ret;
- nlh = nft_rule_nlmsg_build_hdr(buf, NFT_MSG_DELRULE, AF_INET,
+ nlh = nft_rule_nlmsg_build_hdr(buf, NFT_MSG_DELRULE, h->family,
NLM_F_ACK, h->seq);
nft_rule_nlmsg_build_payload(nlh, r);
--
1.8.0.2
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [iptables-nftables RFC PATCH 4/6] nft: Support IPv6 rules manipulation
2013-01-10 14:29 [iptables-nftables RFC PATCH 0/6] IPv6 Support Tomasz Bursztyka
` (2 preceding siblings ...)
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
2013-01-10 14:29 ` [iptables-nftables RFC PATCH 5/6] nft: Use the right payload parsing function when saving a rule Tomasz Bursztyka
` (2 subsequent siblings)
6 siblings, 0 replies; 9+ messages in thread
From: Tomasz Bursztyka @ 2013-01-10 14:29 UTC (permalink / raw)
To: netfilter-devel; +Cc: Tomasz Bursztyka
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
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [iptables-nftables RFC PATCH 5/6] nft: Use the right payload parsing function when saving a rule
2013-01-10 14:29 [iptables-nftables RFC PATCH 0/6] IPv6 Support Tomasz Bursztyka
` (3 preceding siblings ...)
2013-01-10 14:29 ` [iptables-nftables RFC PATCH 4/6] nft: Support IPv6 rules manipulation Tomasz Bursztyka
@ 2013-01-10 14:29 ` 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
6 siblings, 0 replies; 9+ messages in thread
From: Tomasz Bursztyka @ 2013-01-10 14:29 UTC (permalink / raw)
To: netfilter-devel; +Cc: Tomasz Bursztyka
Signed-off-by: Tomasz Bursztyka <tomasz.bursztyka@linux.intel.com>
---
iptables/nft.c | 49 +++++++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 47 insertions(+), 2 deletions(-)
diff --git a/iptables/nft.c b/iptables/nft.c
index f12008a..7b36942 100644
--- a/iptables/nft.c
+++ b/iptables/nft.c
@@ -1269,7 +1269,7 @@ static const char *mask_to_str(uint32_t mask)
}
static void
-nft_print_payload(struct nft_rule_expr *e, struct nft_rule_expr_iter *iter)
+nft_print_payload_ipv4(struct nft_rule_expr *e, struct nft_rule_expr_iter *iter)
{
uint32_t offset;
bool inv;
@@ -1313,6 +1313,48 @@ nft_print_payload(struct nft_rule_expr *e, struct nft_rule_expr_iter *iter)
}
static void
+nft_print_payload_ipv6(struct nft_rule_expr *e, struct nft_rule_expr_iter *iter)
+{
+ uint32_t offset;
+ bool inv;
+
+ offset = nft_rule_expr_get_u32(e, NFT_EXPR_PAYLOAD_OFFSET);
+
+ switch (offset) {
+ char addr_str[INET6_ADDRSTRLEN];
+ struct in6_addr addr;
+ uint8_t proto;
+ case offsetof(struct ip6_hdr, ip6_src):
+ get_cmp_data(iter, &addr, sizeof(addr), &inv);
+ inet_ntop(AF_INET6, &addr, addr_str, INET6_ADDRSTRLEN);
+
+ if (inv)
+ printf("! -s %s ", addr_str);
+ else
+ printf("-s %s ", addr_str);
+
+ break;
+ case offsetof(struct ip6_hdr, ip6_dst):
+ get_cmp_data(iter, &addr, sizeof(addr), &inv);
+ inet_ntop(AF_INET6, &addr, addr_str, INET6_ADDRSTRLEN);
+
+ if (inv)
+ printf("! -d %s ", addr_str);
+ else
+ printf("-d %s ", addr_str);
+
+ break;
+ case offsetof(struct ip6_hdr, ip6_nxt):
+ get_cmp_data(iter, &proto, sizeof(proto), &inv);
+ print_proto(proto, inv);
+ break;
+ default:
+ DEBUGP("unknown payload offset %d\n", offset);
+ break;
+ }
+}
+
+static void
nft_print_counters(struct nft_rule_expr *e, struct nft_rule_expr_iter *iter,
bool counters)
{
@@ -1343,7 +1385,10 @@ static void nft_rule_print_save(struct nft_rule *r, bool counters)
if (strcmp(name, "counter") == 0) {
nft_print_counters(expr, iter, counters);
} else if (strcmp(name, "payload") == 0) {
- nft_print_payload(expr, iter);
+ if (nft_rule_get_family(r) == AF_INET)
+ nft_print_payload_ipv4(expr, iter);
+ else
+ nft_print_payload_ipv6(expr, iter);
} else if (strcmp(name, "meta") == 0) {
nft_print_meta(expr, iter);
} else if (strcmp(name, "match") == 0) {
--
1.8.0.2
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [iptables-nftables RFC PATCH 6/6] nft: Handle IPv6 when printing out firewall rules
2013-01-10 14:29 [iptables-nftables RFC PATCH 0/6] IPv6 Support Tomasz Bursztyka
` (4 preceding siblings ...)
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 ` Tomasz Bursztyka
2013-01-13 19:23 ` [iptables-nftables RFC PATCH 0/6] IPv6 Support Pablo Neira Ayuso
6 siblings, 0 replies; 9+ messages in thread
From: Tomasz Bursztyka @ 2013-01-10 14:29 UTC (permalink / raw)
To: netfilter-devel; +Cc: Tomasz Bursztyka
Signed-off-by: Tomasz Bursztyka <tomasz.bursztyka@linux.intel.com>
---
iptables/nft.c | 374 +++++++++++++++++++++++++++++++++++++++++++--------------
1 file changed, 283 insertions(+), 91 deletions(-)
diff --git a/iptables/nft.c b/iptables/nft.c
index 7b36942..18ce790 100644
--- a/iptables/nft.c
+++ b/iptables/nft.c
@@ -2028,39 +2028,82 @@ match_different(const struct xt_entry_match *a,
}
static bool
-is_same(const struct iptables_command_state *a, const struct iptables_command_state *b)
+is_same(int family, const struct iptables_command_state *a,
+ const struct iptables_command_state *b)
{
unsigned int i;
+ const char *a_outiface, *a_iniface;
+ unsigned const char *a_iniface_mask, *a_outiface_mask;
+ const char *b_outiface, *b_iniface;
+ unsigned const char *b_iniface_mask, *b_outiface_mask;
/* Always compare head structures: ignore mask here. */
- if (a->fw.ip.src.s_addr != b->fw.ip.src.s_addr
- || a->fw.ip.dst.s_addr != b->fw.ip.dst.s_addr
- || a->fw.ip.smsk.s_addr != b->fw.ip.smsk.s_addr
- || a->fw.ip.dmsk.s_addr != b->fw.ip.dmsk.s_addr
- || a->fw.ip.proto != b->fw.ip.proto
- || a->fw.ip.flags != b->fw.ip.flags
- || a->fw.ip.invflags != b->fw.ip.invflags) {
- DEBUGP("different src/dst/proto/flags/invflags\n");
+ switch (family) {
+ case AF_INET:
+ if (a->fw.ip.src.s_addr != b->fw.ip.src.s_addr
+ || a->fw.ip.dst.s_addr != b->fw.ip.dst.s_addr
+ || a->fw.ip.smsk.s_addr != b->fw.ip.smsk.s_addr
+ || a->fw.ip.dmsk.s_addr != b->fw.ip.dmsk.s_addr
+ || a->fw.ip.proto != b->fw.ip.proto
+ || a->fw.ip.flags != b->fw.ip.flags
+ || a->fw.ip.invflags != b->fw.ip.invflags) {
+ DEBUGP("different src/dst/proto/flags/invflags\n");
+ return false;
+ }
+
+ a_iniface_mask = a->fw.ip.iniface_mask;
+ a_iniface = a->fw.ip.iniface;
+ a_outiface_mask = a->fw.ip.outiface_mask;
+ a_outiface = a->fw.ip.outiface;
+
+ b_iniface_mask = b->fw.ip.iniface_mask;
+ b_iniface = b->fw.ip.iniface;
+ b_outiface_mask = b->fw.ip.outiface_mask;
+ b_outiface = b->fw.ip.outiface;
+
+ break;
+ case AF_INET6:
+ if (a->fw6.ipv6.src.s6_addr != b->fw6.ipv6.src.s6_addr
+ || a->fw6.ipv6.dst.s6_addr != b->fw6.ipv6.dst.s6_addr
+ || a->fw6.ipv6.proto != b->fw6.ipv6.proto
+ || a->fw6.ipv6.flags != b->fw6.ipv6.flags
+ || a->fw6.ipv6.invflags != b->fw6.ipv6.invflags) {
+ DEBUGP("different src/dst/proto/flags/invflags\n");
+ return false;
+ }
+
+ a_iniface_mask = a->fw6.ipv6.iniface_mask;
+ a_iniface = a->fw6.ipv6.iniface;
+ a_outiface_mask = a->fw6.ipv6.outiface_mask;
+ a_outiface = a->fw6.ipv6.outiface;
+
+ b_iniface_mask = b->fw6.ipv6.iniface_mask;
+ b_iniface = b->fw6.ipv6.iniface;
+ b_outiface_mask = b->fw6.ipv6.outiface_mask;
+ b_outiface = b->fw6.ipv6.outiface;
+
+ break;
+ default:
return false;
}
for (i = 0; i < IFNAMSIZ; i++) {
- if (a->fw.ip.iniface_mask[i] != b->fw.ip.iniface_mask[i]) {
+ if (a_iniface_mask[i] != b_iniface_mask[i]) {
DEBUGP("different iniface mask %x, %x (%d)\n",
- a->fw.ip.iniface_mask[i] & 0xff, b->fw.ip.iniface_mask[i] & 0xff, i);
+ a_iniface_mask[i] & 0xff, b_iniface_mask[i] & 0xff, i);
return false;
}
- if ((a->fw.ip.iniface[i] & a->fw.ip.iniface_mask[i])
- != (b->fw.ip.iniface[i] & b->fw.ip.iniface_mask[i])) {
+ if ((a_iniface[i] & a_iniface_mask[i])
+ != (b_iniface[i] & b_iniface_mask[i])) {
DEBUGP("different iniface\n");
return false;
}
- if (a->fw.ip.outiface_mask[i] != b->fw.ip.outiface_mask[i]) {
+ if (a_outiface_mask[i] != b_outiface_mask[i]) {
DEBUGP("different outiface mask\n");
return false;
}
- if ((a->fw.ip.outiface[i] & a->fw.ip.outiface_mask[i])
- != (b->fw.ip.outiface[i] & b->fw.ip.outiface_mask[i])) {
+ if ((a_outiface[i] & a_outiface_mask[i])
+ != (b_outiface[i] & b_outiface_mask[i])) {
DEBUGP("different outiface\n");
return false;
}
@@ -2071,13 +2114,16 @@ is_same(const struct iptables_command_state *a, const struct iptables_command_st
static void
nft_parse_meta(struct nft_rule_expr *e, struct nft_rule_expr_iter *iter,
- struct iptables_command_state *cs)
+ int family, struct iptables_command_state *cs)
{
uint8_t key = nft_rule_expr_get_u8(e, NFT_EXPR_META_KEY);
uint32_t value;
const char *name;
const void *ifname;
+ char *iniface, *outiface;
+ unsigned char *iniface_mask, *outiface_mask;
size_t len;
+ uint8_t *invflags;
e = nft_rule_expr_iter_next(iter);
if (e == NULL)
@@ -2089,58 +2135,77 @@ nft_parse_meta(struct nft_rule_expr *e, struct nft_rule_expr_iter *iter,
return;
}
+ switch (family) {
+ case AF_INET:
+ iniface = cs->fw.ip.iniface;
+ outiface = cs->fw.ip.outiface;
+ iniface_mask = cs->fw.ip.iniface_mask;
+ outiface_mask = cs->fw.ip.outiface_mask;
+ invflags = &cs->fw.ip.invflags;
+
+ break;
+ case AF_INET6:
+ iniface = cs->fw6.ipv6.iniface;
+ outiface = cs->fw6.ipv6.outiface;
+ iniface_mask = cs->fw6.ipv6.iniface_mask;
+ outiface_mask = cs->fw6.ipv6.outiface_mask;
+ invflags = &cs->fw6.ipv6.invflags;
+
+ break;
+ default:
+ return;
+ }
+
switch(key) {
case NFT_META_IIF:
value = nft_rule_expr_get_u32(e, NFT_EXPR_CMP_DATA);
if (nft_rule_expr_get_u8(e, NFT_EXPR_CMP_OP) == NFT_CMP_NEQ)
- cs->fw.ip.invflags |= IPT_INV_VIA_IN;
+ *invflags |= IPT_INV_VIA_IN;
- if_indextoname(value, cs->fw.ip.iniface);
+ if_indextoname(value, iniface);
- memset(cs->fw.ip.iniface_mask, 0xff,
- strlen(cs->fw.ip.iniface)+1);
+ memset(iniface_mask, 0xff, strlen(iniface)+1);
break;
case NFT_META_OIF:
value = nft_rule_expr_get_u32(e, NFT_EXPR_CMP_DATA);
if (nft_rule_expr_get_u8(e, NFT_EXPR_CMP_OP) == NFT_CMP_NEQ)
- cs->fw.ip.invflags |= IPT_INV_VIA_OUT;
+ *invflags |= IPT_INV_VIA_OUT;
- if_indextoname(value, cs->fw.ip.outiface);
+ if_indextoname(value, outiface);
- memset(cs->fw.ip.outiface_mask, 0xff,
- strlen(cs->fw.ip.outiface)+1);
+ memset(outiface_mask, 0xff, strlen(outiface)+1);
break;
case NFT_META_IIFNAME:
ifname = nft_rule_expr_get(e, NFT_EXPR_CMP_DATA, &len);
if (nft_rule_expr_get_u8(e, NFT_EXPR_CMP_OP) == NFT_CMP_NEQ)
- cs->fw.ip.invflags |= IPT_INV_VIA_IN;
+ *invflags |= IPT_INV_VIA_IN;
- memcpy(cs->fw.ip.iniface, ifname, len);
- cs->fw.ip.iniface[len] = '\0';
+ memcpy(iniface, ifname, len);
+ iniface[len] = '\0';
/* If zero, then this is an interface mask */
- if (if_nametoindex(cs->fw.ip.iniface) == 0) {
- cs->fw.ip.iniface[len] = '+';
- cs->fw.ip.iniface[len+1] = '\0';
+ if (if_nametoindex(iniface) == 0) {
+ iniface[len] = '+';
+ iniface[len+1] = '\0';
}
- memset(cs->fw.ip.iniface_mask, 0xff, len);
+ memset(iniface_mask, 0xff, len);
break;
case NFT_META_OIFNAME:
ifname = nft_rule_expr_get(e, NFT_EXPR_CMP_DATA, &len);
if (nft_rule_expr_get_u8(e, NFT_EXPR_CMP_OP) == NFT_CMP_NEQ)
- cs->fw.ip.invflags |= IPT_INV_VIA_OUT;
+ *invflags |= IPT_INV_VIA_OUT;
- memcpy(cs->fw.ip.outiface, ifname, len);
- cs->fw.ip.outiface[len] = '\0';
+ memcpy(outiface, ifname, len);
+ outiface[len] = '\0';
/* If zero, then this is an interface mask */
- if (if_nametoindex(cs->fw.ip.outiface) == 0) {
- cs->fw.ip.outiface[len] = '+';
- cs->fw.ip.outiface[len+1] = '\0';
+ if (if_nametoindex(outiface) == 0) {
+ outiface[len] = '+';
+ outiface[len+1] = '\0';
}
- memset(cs->fw.ip.outiface_mask, 0xff, len);
+ memset(outiface_mask, 0xff, len);
break;
default:
DEBUGP("unknown meta key %d\n", key);
@@ -2149,17 +2214,13 @@ nft_parse_meta(struct nft_rule_expr *e, struct nft_rule_expr_iter *iter,
}
static void
-nft_parse_payload(struct nft_rule_expr *e, struct nft_rule_expr_iter *iter,
- struct iptables_command_state *cs)
+nft_parse_payload_ipv4(uint32_t offset, struct nft_rule_expr_iter *iter,
+ struct iptables_command_state *cs)
{
- uint32_t offset;
- bool inv;
-
- offset = nft_rule_expr_get_u32(e, NFT_EXPR_PAYLOAD_OFFSET);
-
switch(offset) {
struct in_addr addr;
uint8_t proto;
+ bool inv;
case offsetof(struct iphdr, saddr):
get_cmp_data(iter, &addr, sizeof(addr), &inv);
@@ -2194,6 +2255,56 @@ nft_parse_payload(struct nft_rule_expr *e, struct nft_rule_expr_iter *iter,
}
static void
+nft_parse_payload_ipv6(uint32_t offset, struct nft_rule_expr_iter *iter,
+ struct iptables_command_state *cs)
+{
+ switch (offset) {
+ struct in6_addr addr;
+ uint8_t proto;
+ bool inv;
+
+ case offsetof(struct ip6_hdr, ip6_src):
+ get_cmp_data(iter, &addr, sizeof(addr), &inv);
+ memcpy(cs->fw6.ipv6.src.s6_addr, &addr, sizeof(addr));
+ if (inv)
+ cs->fw6.ipv6.invflags |= IPT_INV_SRCIP;
+ break;
+ case offsetof(struct ip6_hdr, ip6_dst):
+ get_cmp_data(iter, &addr, sizeof(addr), &inv);
+ memcpy(cs->fw6.ipv6.dst.s6_addr, &addr, sizeof(addr));
+ if (inv)
+ cs->fw6.ipv6.invflags |= IPT_INV_DSTIP;
+ break;
+ case offsetof(struct ip6_hdr, ip6_nxt):
+ get_cmp_data(iter, &proto, sizeof(proto), &inv);
+ cs->fw6.ipv6.proto = proto;
+ if (inv)
+ cs->fw6.ipv6.invflags |= IPT_INV_PROTO;
+ default:
+ DEBUGP("unknown payload offset %d\n", offset);
+ break;
+ }
+}
+
+static void
+nft_parse_payload(struct nft_rule_expr *e, struct nft_rule_expr_iter *iter,
+ int family, struct iptables_command_state *cs)
+{
+ uint32_t offset;
+
+ offset = nft_rule_expr_get_u32(e, NFT_EXPR_PAYLOAD_OFFSET);
+
+ switch (family) {
+ case AF_INET:
+ nft_parse_payload_ipv4(offset, iter, cs);
+ break;
+ case AF_INET6:
+ nft_parse_payload_ipv6(offset, iter, cs);
+ break;
+ }
+}
+
+static void
nft_parse_counter(struct nft_rule_expr *e, struct nft_rule_expr_iter *iter,
struct xt_counters *counters)
{
@@ -2203,7 +2314,7 @@ nft_parse_counter(struct nft_rule_expr *e, struct nft_rule_expr_iter *iter,
static void
nft_parse_immediate(struct nft_rule_expr *e, struct nft_rule_expr_iter *iter,
- struct iptables_command_state *cs)
+ int family, struct iptables_command_state *cs)
{
int verdict = nft_rule_expr_get_u32(e, NFT_EXPR_IMM_VERDICT);
const char *chain = nft_rule_expr_get_str(e, NFT_EXPR_IMM_CHAIN);
@@ -2220,7 +2331,10 @@ nft_parse_immediate(struct nft_rule_expr *e, struct nft_rule_expr_iter *iter,
cs->jumpto = "RETURN";
return;
case NFT_GOTO:
- cs->fw.ip.flags |= IPT_F_GOTO;
+ if (family == AF_INET)
+ cs->fw.ip.flags |= IPT_F_GOTO;
+ else
+ cs->fw6.ipv6.flags |= IPT_F_GOTO;
case NFT_JUMP:
cs->jumpto = chain;
return;
@@ -2233,6 +2347,7 @@ nft_rule_to_iptables_command_state(struct nft_rule *r,
{
struct nft_rule_expr_iter *iter;
struct nft_rule_expr *expr;
+ int family = nft_rule_get_family(r);
iter = nft_rule_expr_iter_create(r);
if (iter == NULL)
@@ -2246,11 +2361,11 @@ nft_rule_to_iptables_command_state(struct nft_rule *r,
if (strcmp(name, "counter") == 0) {
nft_parse_counter(expr, iter, &cs->counters);
} else if (strcmp(name, "payload") == 0) {
- nft_parse_payload(expr, iter, cs);
+ nft_parse_payload(expr, iter, family, cs);
} else if (strcmp(name, "meta") == 0) {
- nft_parse_meta(expr, iter, cs);
+ nft_parse_meta(expr, iter, family, cs);
} else if (strcmp(name, "immediate") == 0) {
- nft_parse_immediate(expr, iter, cs);
+ nft_parse_immediate(expr, iter, family, cs);
}
expr = nft_rule_expr_iter_next(iter);
@@ -2530,7 +2645,7 @@ nft_rule_find(struct nft_rule_list *list, const char *chain, const char *table,
nft_rule_to_iptables_command_state(r, &this);
- if (!is_same(cs, &this))
+ if (!is_same(nft_rule_get_family(r), cs, &this))
goto next;
if (!find_matches(cs->matches, r)) {
@@ -2793,14 +2908,82 @@ print_match(struct nft_rule_expr *expr, int numeric)
}
static void
+print_ipv4_addr(const struct iptables_command_state *cs, unsigned int format)
+{
+ char buf[BUFSIZ];
+
+ fputc(cs->fw.ip.invflags & IPT_INV_SRCIP ? '!' : ' ', stdout);
+ if (cs->fw.ip.smsk.s_addr == 0L && !(format & FMT_NUMERIC))
+ printf(FMT("%-19s ","%s "), "anywhere");
+ else {
+ if (format & FMT_NUMERIC)
+ strcpy(buf, xtables_ipaddr_to_numeric(&cs->fw.ip.src));
+ else
+ strcpy(buf, xtables_ipaddr_to_anyname(&cs->fw.ip.src));
+ strcat(buf, xtables_ipmask_to_numeric(&cs->fw.ip.smsk));
+ printf(FMT("%-19s ","%s "), buf);
+ }
+
+ fputc(cs->fw.ip.invflags & IPT_INV_DSTIP ? '!' : ' ', stdout);
+ if (cs->fw.ip.dmsk.s_addr == 0L && !(format & FMT_NUMERIC))
+ printf(FMT("%-19s ","-> %s"), "anywhere");
+ else {
+ if (format & FMT_NUMERIC)
+ strcpy(buf, xtables_ipaddr_to_numeric(&cs->fw.ip.dst));
+ else
+ strcpy(buf, xtables_ipaddr_to_anyname(&cs->fw.ip.dst));
+ strcat(buf, xtables_ipmask_to_numeric(&cs->fw.ip.dmsk));
+ printf(FMT("%-19s ","-> %s"), buf);
+ }
+}
+
+static void
+print_ipv6_addr(const struct iptables_command_state *cs, unsigned int format)
+{
+ char buf[BUFSIZ];
+
+ fputc(cs->fw6.ipv6.invflags & IPT_INV_SRCIP ? '!' : ' ', stdout);
+ if (IN6_IS_ADDR_UNSPECIFIED(&cs->fw6.ipv6.src)
+ && !(format & FMT_NUMERIC))
+ printf(FMT("%-19s ","%s "), "anywhere");
+ else {
+ if (format & FMT_NUMERIC)
+ strcpy(buf,
+ xtables_ip6addr_to_numeric(&cs->fw6.ipv6.src));
+ else
+ strcpy(buf,
+ xtables_ip6addr_to_anyname(&cs->fw6.ipv6.src));
+ strcat(buf, xtables_ip6mask_to_numeric(&cs->fw6.ipv6.smsk));
+ printf(FMT("%-19s ","%s "), buf);
+ }
+
+
+ fputc(cs->fw6.ipv6.invflags & IPT_INV_DSTIP ? '!' : ' ', stdout);
+ if (IN6_IS_ADDR_UNSPECIFIED(&cs->fw6.ipv6.dst)
+ && !(format & FMT_NUMERIC))
+ printf(FMT("%-19s ","-> %s"), "anywhere");
+ else {
+ if (format & FMT_NUMERIC)
+ strcpy(buf, xtables_ipaddr_to_numeric(&cs->fw.ip.dst));
+ else
+ strcpy(buf, xtables_ipaddr_to_anyname(&cs->fw.ip.dst));
+ strcat(buf, xtables_ip6mask_to_numeric(&cs->fw6.ipv6.dmsk));
+ printf(FMT("%-19s ","-> %s"), buf);
+ }
+}
+
+static void
print_firewall(const struct iptables_command_state *cs, struct nft_rule *r,
unsigned int num, unsigned int format)
{
const struct xtables_target *target = NULL;
const char *targname = NULL;
const void *targinfo = NULL;
- uint8_t flags;
- char buf[BUFSIZ];
+ int family;
+ uint8_t flags = 0;
+ uint8_t invflags = 0;
+ uint8_t proto = 0;
+ const char *iniface = NULL, *outiface = NULL;
struct nft_rule_expr_iter *iter;
struct nft_rule_expr *expr;
struct xt_entry_target *t;
@@ -2818,8 +3001,10 @@ print_firewall(const struct iptables_command_state *cs, struct nft_rule *r,
nft_rule_expr_get_str(expr, NFT_RULE_EXPR_ATTR_NAME);
if (strcmp(name, "target") == 0) {
- targname = nft_rule_expr_get_str(expr, NFT_EXPR_TG_NAME);
- targinfo = nft_rule_expr_get(expr, NFT_EXPR_TG_INFO, &target_len);
+ targname = nft_rule_expr_get_str(expr,
+ NFT_EXPR_TG_NAME);
+ targinfo = nft_rule_expr_get(expr, NFT_EXPR_TG_INFO,
+ &target_len);
break;
} else if (strcmp(name, "immediate") == 0) {
uint32_t verdict =
@@ -2836,10 +3021,12 @@ print_firewall(const struct iptables_command_state *cs, struct nft_rule *r,
targname = "RETURN";
break;
case NFT_GOTO:
- targname = nft_rule_expr_get_str(expr, NFT_EXPR_IMM_CHAIN);
+ targname = nft_rule_expr_get_str(expr,
+ NFT_EXPR_IMM_CHAIN);
break;
case NFT_JUMP:
- targname = nft_rule_expr_get_str(expr, NFT_EXPR_IMM_CHAIN);
+ targname = nft_rule_expr_get_str(expr,
+ NFT_EXPR_IMM_CHAIN);
break;
}
}
@@ -2847,7 +3034,26 @@ print_firewall(const struct iptables_command_state *cs, struct nft_rule *r,
}
nft_rule_expr_iter_destroy(iter);
- flags = cs->fw.ip.flags;
+ family = nft_rule_get_family(r);
+
+ switch (family) {
+ case AF_INET:
+ flags = cs->fw.ip.flags;
+ invflags = flags = cs->fw.ip.invflags;
+ proto = cs->fw.ip.proto;
+ iniface = cs->fw.ip.iniface;
+ outiface = cs->fw.ip.outiface;
+
+ break;
+ case AF_INET6:
+ flags = cs->fw6.ipv6.flags;
+ invflags = cs->fw6.ipv6.invflags;
+ proto = cs->fw6.ipv6.proto;
+ iniface = cs->fw6.ipv6.iniface;
+ outiface = cs->fw6.ipv6.outiface;
+
+ break;
+ }
if (format & FMT_LINENUMBERS)
printf(FMT("%-4u ", "%u "), num);
@@ -2860,82 +3066,68 @@ print_firewall(const struct iptables_command_state *cs, struct nft_rule *r,
if (!(format & FMT_NOTARGET))
printf(FMT("%-9s ", "%s "), targname ? targname : "");
- fputc(cs->fw.ip.invflags & XT_INV_PROTO ? '!' : ' ', stdout);
+ fputc(invflags & XT_INV_PROTO ? '!' : ' ', stdout);
{
const char *pname =
- proto_to_name(cs->fw.ip.proto, format&FMT_NUMERIC);
+ proto_to_name(proto, format&FMT_NUMERIC);
if (pname)
printf(FMT("%-5s", "%s "), pname);
else
- printf(FMT("%-5hu", "%hu "), cs->fw.ip.proto);
+ printf(FMT("%-5hu", "%hu "), proto);
}
if (format & FMT_OPTIONS) {
if (format & FMT_NOTABLE)
fputs("opt ", stdout);
- fputc(cs->fw.ip.invflags & IPT_INV_FRAG ? '!' : '-', stdout);
+ fputc(invflags & IPT_INV_FRAG ? '!' : '-', stdout);
fputc(flags & IPT_F_FRAG ? 'f' : '-', stdout);
fputc(' ', stdout);
}
if (format & FMT_VIA) {
char iface[IFNAMSIZ+2];
- if (cs->fw.ip.invflags & IPT_INV_VIA_IN) {
+ if (invflags & IPT_INV_VIA_IN) {
iface[0] = '!';
iface[1] = '\0';
}
else iface[0] = '\0';
- if (cs->fw.ip.iniface[0] != '\0') {
- strcat(iface, cs->fw.ip.iniface);
+ if (iniface[0] != '\0') {
+ strcat(iface, iniface);
}
else if (format & FMT_NUMERIC) strcat(iface, "*");
else strcat(iface, "any");
printf(FMT(" %-6s ","in %s "), iface);
- if (cs->fw.ip.invflags & IPT_INV_VIA_OUT) {
+ if (invflags & IPT_INV_VIA_OUT) {
iface[0] = '!';
iface[1] = '\0';
}
else iface[0] = '\0';
- if (cs->fw.ip.outiface[0] != '\0') {
- strcat(iface, cs->fw.ip.outiface);
+ if (outiface[0] != '\0') {
+ strcat(iface, outiface);
}
else if (format & FMT_NUMERIC) strcat(iface, "*");
else strcat(iface, "any");
printf(FMT("%-6s ","out %s "), iface);
}
- fputc(cs->fw.ip.invflags & IPT_INV_SRCIP ? '!' : ' ', stdout);
- if (cs->fw.ip.smsk.s_addr == 0L && !(format & FMT_NUMERIC))
- printf(FMT("%-19s ","%s "), "anywhere");
- else {
- if (format & FMT_NUMERIC)
- strcpy(buf, xtables_ipaddr_to_numeric(&cs->fw.ip.src));
- else
- strcpy(buf, xtables_ipaddr_to_anyname(&cs->fw.ip.src));
- strcat(buf, xtables_ipmask_to_numeric(&cs->fw.ip.smsk));
- printf(FMT("%-19s ","%s "), buf);
- }
- fputc(cs->fw.ip.invflags & IPT_INV_DSTIP ? '!' : ' ', stdout);
- if (cs->fw.ip.dmsk.s_addr == 0L && !(format & FMT_NUMERIC))
- printf(FMT("%-19s ","-> %s"), "anywhere");
- else {
- if (format & FMT_NUMERIC)
- strcpy(buf, xtables_ipaddr_to_numeric(&cs->fw.ip.dst));
- else
- strcpy(buf, xtables_ipaddr_to_anyname(&cs->fw.ip.dst));
- strcat(buf, xtables_ipmask_to_numeric(&cs->fw.ip.dmsk));
- printf(FMT("%-19s ","-> %s"), buf);
+ switch (family) {
+ case AF_INET:
+ print_ipv4_addr(cs, format);
+ break;
+ case AF_INET6:
+ print_ipv6_addr(cs, format);
+ break;
}
if (format & FMT_NOTABLE)
fputs(" ", stdout);
#ifdef IPT_F_GOTO
- if(cs->fw.ip.flags & IPT_F_GOTO)
+ if(flags & IPT_F_GOTO)
printf("[goto] ");
#endif
--
1.8.0.2
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [iptables-nftables RFC PATCH - v2 - 2/6] xtables: Combine IPv6 support with IPv4 support
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 ` Tomasz Bursztyka
0 siblings, 0 replies; 9+ messages in thread
From: Tomasz Bursztyka @ 2013-01-11 9:10 UTC (permalink / raw)
To: netfilter-devel; +Cc: Tomasz Bursztyka
Instead of having separate binaries for IPv4 and IPv6, it combines
both supports together in the same place and let the nft handle
knows about which family is in use.
Signed-off-by: Tomasz Bursztyka <tomasz.bursztyka@linux.intel.com>
---
iptables/xtables.c | 389 +++++++++++++++++++++++++++++++++++++----------------
1 file changed, 272 insertions(+), 117 deletions(-)
diff --git a/iptables/xtables.c b/iptables/xtables.c
index 89ccd7f..821c93b 100644
--- a/iptables/xtables.c
+++ b/iptables/xtables.c
@@ -204,6 +204,20 @@ enum {
IPT_DOTTED_MASK
};
+struct addr_mask {
+ union {
+ struct in_addr *v4;
+ struct in6_addr *v6;
+ } addr;
+
+ unsigned int naddrs;
+
+ union {
+ struct in_addr *v4;
+ struct in6_addr *v6;
+ } mask;
+};
+
static void __attribute__((noreturn))
exit_tryhelp(int status)
{
@@ -370,6 +384,15 @@ add_command(unsigned int *cmd, const int newcmd, const int othercmds,
* return global static data.
*/
+/* These are invalid numbers as upper layer protocol */
+static int is_exthdr(uint16_t proto)
+{
+ return (proto == IPPROTO_ROUTING ||
+ proto == IPPROTO_FRAGMENT ||
+ proto == IPPROTO_AH ||
+ proto == IPPROTO_DSTOPTS);
+}
+
/* Christophe Burki wants `-p 6' to imply `-m tcp'. */
/* Can't be zero. */
static int
@@ -430,26 +453,38 @@ static int
add_entry(const char *chain,
const char *table,
struct iptables_command_state *cs,
- unsigned int nsaddrs,
- const struct in_addr saddrs[],
- const struct in_addr smasks[],
- unsigned int ndaddrs,
- const struct in_addr daddrs[],
- const struct in_addr dmasks[],
+ int family,
+ const struct addr_mask s,
+ const struct addr_mask d,
bool verbose, struct nft_handle *h, bool append)
{
unsigned int i, j;
int ret = 1;
- for (i = 0; i < nsaddrs; i++) {
- cs->fw.ip.src.s_addr = saddrs[i].s_addr;
- cs->fw.ip.smsk.s_addr = smasks[i].s_addr;
- for (j = 0; j < ndaddrs; j++) {
- cs->fw.ip.dst.s_addr = daddrs[j].s_addr;
- cs->fw.ip.dmsk.s_addr = dmasks[j].s_addr;
+ for (i = 0; i < s.naddrs; i++) {
+ if (family == AF_INET) {
+ cs->fw.ip.src.s_addr = s.addr.v4[i].s_addr;
+ cs->fw.ip.smsk.s_addr = s.mask.v4[i].s_addr;
+ for (j = 0; j < d.naddrs; j++) {
+ cs->fw.ip.dst.s_addr = d.addr.v4[j].s_addr;
+ cs->fw.ip.dmsk.s_addr = d.mask.v4[j].s_addr;
- ret = nft_rule_add(h, chain, table,
- cs, append, 0, verbose);
+ ret = nft_rule_add(h, chain, table,
+ cs, append, 0, verbose);
+ }
+ } else if (family == AF_INET6) {
+ memcpy(&cs->fw6.ipv6.src,
+ &s.addr.v6[i], sizeof(struct in6_addr));
+ memcpy(&cs->fw6.ipv6.smsk,
+ &s.mask.v6[i], sizeof(struct in6_addr));
+ for (j = 0; j < d.naddrs; j++) {
+ memcpy(&cs->fw6.ipv6.dst,
+ &d.addr.v6[j], sizeof(struct in6_addr));
+ memcpy(&cs->fw6.ipv6.dmsk,
+ &d.mask.v6[j], sizeof(struct in6_addr));
+ ret = nft_rule_add(h, chain, table,
+ cs, append, 0, verbose);
+ }
}
}
@@ -460,14 +495,23 @@ static int
replace_entry(const char *chain, const char *table,
struct iptables_command_state *cs,
unsigned int rulenum,
- const struct in_addr *saddr, const struct in_addr *smask,
- const struct in_addr *daddr, const struct in_addr *dmask,
+ int family,
+ const struct addr_mask s,
+ const struct addr_mask d,
bool verbose, struct nft_handle *h)
{
- cs->fw.ip.src.s_addr = saddr->s_addr;
- cs->fw.ip.dst.s_addr = daddr->s_addr;
- cs->fw.ip.smsk.s_addr = smask->s_addr;
- cs->fw.ip.dmsk.s_addr = dmask->s_addr;
+ if (family == AF_INET) {
+ cs->fw.ip.src.s_addr = s.addr.v4->s_addr;
+ cs->fw.ip.dst.s_addr = d.addr.v4->s_addr;
+ cs->fw.ip.smsk.s_addr = s.mask.v4->s_addr;
+ cs->fw.ip.dmsk.s_addr = d.mask.v4->s_addr;
+ } else if (family == AF_INET6) {
+ memcpy(&cs->fw6.ipv6.src, s.addr.v6, sizeof(struct in6_addr));
+ memcpy(&cs->fw6.ipv6.dst, d.addr.v6, sizeof(struct in6_addr));
+ memcpy(&cs->fw6.ipv6.smsk, s.mask.v6, sizeof(struct in6_addr));
+ memcpy(&cs->fw6.ipv6.dmsk, d.mask.v6, sizeof(struct in6_addr));
+ } else
+ return 1;
return nft_rule_replace(h, chain, table, cs, rulenum, verbose);
}
@@ -475,25 +519,38 @@ replace_entry(const char *chain, const char *table,
static int
delete_entry(const char *chain, const char *table,
struct iptables_command_state *cs,
- unsigned int nsaddrs,
- const struct in_addr saddrs[],
- const struct in_addr smasks[],
- unsigned int ndaddrs,
- const struct in_addr daddrs[],
- const struct in_addr dmasks[],
+ int family,
+ const struct addr_mask s,
+ const struct addr_mask d,
bool verbose,
struct nft_handle *h)
{
unsigned int i, j;
int ret = 1;
- for (i = 0; i < nsaddrs; i++) {
- cs->fw.ip.src.s_addr = saddrs[i].s_addr;
- cs->fw.ip.smsk.s_addr = smasks[i].s_addr;
- for (j = 0; j < ndaddrs; j++) {
- cs->fw.ip.dst.s_addr = daddrs[j].s_addr;
- cs->fw.ip.dmsk.s_addr = dmasks[j].s_addr;
- ret = nft_rule_delete(h, chain, table, cs, verbose);
+ for (i = 0; i < s.naddrs; i++) {
+ if (family == AF_INET) {
+ cs->fw.ip.src.s_addr = s.addr.v4[i].s_addr;
+ cs->fw.ip.smsk.s_addr = s.mask.v4[i].s_addr;
+ for (j = 0; j < d.naddrs; j++) {
+ cs->fw.ip.dst.s_addr = d.addr.v4[j].s_addr;
+ cs->fw.ip.dmsk.s_addr = d.mask.v4[j].s_addr;
+ ret = nft_rule_delete(h, chain,
+ table, cs, verbose);
+ }
+ } else if (family == AF_INET6) {
+ memcpy(&cs->fw6.ipv6.src,
+ &s.addr.v6[i], sizeof(struct in6_addr));
+ memcpy(&cs->fw6.ipv6.smsk,
+ &s.mask.v6[i], sizeof(struct in6_addr));
+ for (j = 0; j < d.naddrs; j++) {
+ memcpy(&cs->fw6.ipv6.dst,
+ &d.addr.v6[j], sizeof(struct in6_addr));
+ memcpy(&cs->fw6.ipv6.dmsk,
+ &d.mask.v6[j], sizeof(struct in6_addr));
+ ret = nft_rule_delete(h, chain,
+ table, cs, verbose);
+ }
}
}
@@ -503,21 +560,37 @@ delete_entry(const char *chain, const char *table,
static int
check_entry(const char *chain, const char *table,
struct iptables_command_state *cs,
- unsigned int nsaddrs, const struct in_addr *saddrs,
- const struct in_addr *smasks, unsigned int ndaddrs,
- const struct in_addr *daddrs, const struct in_addr *dmasks,
+ int family,
+ const struct addr_mask s,
+ const struct addr_mask d,
bool verbose, struct nft_handle *h)
{
unsigned int i, j;
int ret = 1;
- for (i = 0; i < nsaddrs; i++) {
- cs->fw.ip.src.s_addr = saddrs[i].s_addr;
- cs->fw.ip.smsk.s_addr = smasks[i].s_addr;
- for (j = 0; j < ndaddrs; j++) {
- cs->fw.ip.dst.s_addr = daddrs[j].s_addr;
- cs->fw.ip.dmsk.s_addr = dmasks[j].s_addr;
- ret = nft_rule_check(h, chain, table, cs, verbose);
+ for (i = 0; i < s.naddrs; i++) {
+ if (family == AF_INET) {
+ cs->fw.ip.src.s_addr = s.addr.v4[i].s_addr;
+ cs->fw.ip.smsk.s_addr = s.mask.v4[i].s_addr;
+ for (j = 0; j < d.naddrs; j++) {
+ cs->fw.ip.dst.s_addr = d.addr.v4[j].s_addr;
+ cs->fw.ip.dmsk.s_addr = d.mask.v4[j].s_addr;
+ ret = nft_rule_check(h, chain,
+ table, cs, verbose);
+ }
+ } else if (family == AF_INET6) {
+ memcpy(&cs->fw6.ipv6.src,
+ &s.addr.v6[i], sizeof(struct in6_addr));
+ memcpy(&cs->fw6.ipv6.smsk,
+ &s.mask.v6[i], sizeof(struct in6_addr));
+ for (j = 0; j < d.naddrs; j++) {
+ memcpy(&cs->fw6.ipv6.dst,
+ &d.addr.v6[j], sizeof(struct in6_addr));
+ memcpy(&cs->fw6.ipv6.dmsk,
+ &d.mask.v6[j], sizeof(struct in6_addr));
+ ret = nft_rule_check(h, chain,
+ table, cs, verbose);
+ }
}
}
@@ -657,9 +730,8 @@ static void command_match(struct iptables_command_state *cs)
int do_commandx(struct nft_handle *h, int argc, char *argv[], char **table)
{
struct iptables_command_state cs;
- unsigned int nsaddrs = 0, ndaddrs = 0;
- struct in_addr *saddrs = NULL, *smasks = NULL;
- struct in_addr *daddrs = NULL, *dmasks = NULL;
+ struct addr_mask s;
+ struct addr_mask d;
int verbose = 0;
const char *chain = NULL;
@@ -671,7 +743,16 @@ int do_commandx(struct nft_handle *h, int argc, char *argv[], char **table)
struct xtables_match *m;
struct xtables_rule_match *matchp;
struct xtables_target *t;
- unsigned long long cnt;
+ unsigned long long pcnt_cnt = 0, bcnt_cnt = 0;
+
+ int family = AF_INET;
+ u_int16_t proto = 0;
+ u_int8_t flags = 0, invflags = 0;
+ char iniface[IFNAMSIZ], outiface[IFNAMSIZ];
+ unsigned char iniface_mask[IFNAMSIZ], outiface_mask[IFNAMSIZ];
+
+ memset(&s, 0, sizeof(s));
+ memset(&d, 0, sizeof(d));
memset(&cs, 0, sizeof(cs));
cs.jumpto = "";
@@ -861,7 +942,7 @@ int do_commandx(struct nft_handle *h, int argc, char *argv[], char **table)
* Option selection
*/
case 'p':
- set_option(&cs.options, OPT_PROTOCOL, &cs.fw.ip.invflags,
+ set_option(&cs.options, OPT_PROTOCOL, &invflags,
cs.invert);
/* Canonicalize into lower case */
@@ -869,31 +950,29 @@ int do_commandx(struct nft_handle *h, int argc, char *argv[], char **table)
*cs.protocol = tolower(*cs.protocol);
cs.protocol = optarg;
- cs.fw.ip.proto = xtables_parse_protocol(cs.protocol);
+ proto = xtables_parse_protocol(cs.protocol);
- if (cs.fw.ip.proto == 0
- && (cs.fw.ip.invflags & XT_INV_PROTO))
+ if (proto == 0 && (invflags & XT_INV_PROTO))
xtables_error(PARAMETER_PROBLEM,
"rule would never match protocol");
break;
case 's':
- set_option(&cs.options, OPT_SOURCE, &cs.fw.ip.invflags,
+ set_option(&cs.options, OPT_SOURCE, &invflags,
cs.invert);
shostnetworkmask = optarg;
break;
case 'd':
- set_option(&cs.options, OPT_DESTINATION, &cs.fw.ip.invflags,
+ set_option(&cs.options, OPT_DESTINATION, &invflags,
cs.invert);
dhostnetworkmask = optarg;
break;
#ifdef IPT_F_GOTO
case 'g':
- set_option(&cs.options, OPT_JUMP, &cs.fw.ip.invflags,
+ set_option(&cs.options, OPT_JUMP, &invflags,
cs.invert);
- cs.fw.ip.flags |= IPT_F_GOTO;
cs.jumpto = parse_target(optarg);
break;
#endif
@@ -908,11 +987,11 @@ int do_commandx(struct nft_handle *h, int argc, char *argv[], char **table)
xtables_error(PARAMETER_PROBLEM,
"Empty interface is likely to be "
"undesired");
- set_option(&cs.options, OPT_VIANAMEIN, &cs.fw.ip.invflags,
+ set_option(&cs.options, OPT_VIANAMEIN, &invflags,
cs.invert);
xtables_parse_interface(optarg,
- cs.fw.ip.iniface,
- cs.fw.ip.iniface_mask);
+ iniface,
+ iniface_mask);
break;
case 'o':
@@ -920,23 +999,23 @@ int do_commandx(struct nft_handle *h, int argc, char *argv[], char **table)
xtables_error(PARAMETER_PROBLEM,
"Empty interface is likely to be "
"undesired");
- set_option(&cs.options, OPT_VIANAMEOUT, &cs.fw.ip.invflags,
+ set_option(&cs.options, OPT_VIANAMEOUT, &invflags,
cs.invert);
xtables_parse_interface(optarg,
- cs.fw.ip.outiface,
- cs.fw.ip.outiface_mask);
+ outiface,
+ outiface_mask);
break;
case 'f':
- set_option(&cs.options, OPT_FRAGMENT, &cs.fw.ip.invflags,
+ set_option(&cs.options, OPT_FRAGMENT, &invflags,
cs.invert);
- cs.fw.ip.flags |= IPT_F_FRAG;
+ flags |= IPT_F_FRAG;
break;
case 'v':
if (!verbose)
set_option(&cs.options, OPT_VERBOSE,
- &cs.fw.ip.invflags, cs.invert);
+ &invflags, cs.invert);
verbose++;
break;
@@ -945,7 +1024,7 @@ int do_commandx(struct nft_handle *h, int argc, char *argv[], char **table)
break;
case 'n':
- set_option(&cs.options, OPT_NUMERIC, &cs.fw.ip.invflags,
+ set_option(&cs.options, OPT_NUMERIC, &invflags,
cs.invert);
break;
@@ -957,7 +1036,7 @@ int do_commandx(struct nft_handle *h, int argc, char *argv[], char **table)
break;
case 'x':
- set_option(&cs.options, OPT_EXPANDED, &cs.fw.ip.invflags,
+ set_option(&cs.options, OPT_EXPANDED, &invflags,
cs.invert);
break;
@@ -970,7 +1049,7 @@ int do_commandx(struct nft_handle *h, int argc, char *argv[], char **table)
exit(0);
case '0':
- set_option(&cs.options, OPT_LINENUMBERS, &cs.fw.ip.invflags,
+ set_option(&cs.options, OPT_LINENUMBERS, &invflags,
cs.invert);
break;
@@ -980,7 +1059,7 @@ int do_commandx(struct nft_handle *h, int argc, char *argv[], char **table)
case 'c':
- set_option(&cs.options, OPT_COUNTERS, &cs.fw.ip.invflags,
+ set_option(&cs.options, OPT_COUNTERS, &invflags,
cs.invert);
pcnt = optarg;
bcnt = strchr(pcnt + 1, ',');
@@ -994,29 +1073,25 @@ int do_commandx(struct nft_handle *h, int argc, char *argv[], char **table)
"-%c requires packet and byte counter",
opt2char(OPT_COUNTERS));
- if (sscanf(pcnt, "%llu", &cnt) != 1)
+ if (sscanf(pcnt, "%llu", &pcnt_cnt) != 1)
xtables_error(PARAMETER_PROBLEM,
"-%c packet counter not numeric",
opt2char(OPT_COUNTERS));
- cs.counters.pcnt = cnt;
- if (sscanf(bcnt, "%llu", &cnt) != 1)
+ if (sscanf(bcnt, "%llu", &bcnt_cnt) != 1)
xtables_error(PARAMETER_PROBLEM,
"-%c byte counter not numeric",
opt2char(OPT_COUNTERS));
- cs.counters.bcnt = cnt;
break;
case '4':
- /* This is indeed the IPv4 iptables */
+ if (family != AF_INET)
+ exit_tryhelp(2);
break;
case '6':
- /* This is not the IPv6 ip6tables */
- if (line != -1)
- return 1; /* success: line ignored */
- fprintf(stderr, "This is the IPv4 version of iptables.\n");
- exit_tryhelp(2);
+ family = AF_INET6;
+ break;
case 1: /* non option */
if (optarg[0] == '!' && optarg[1] == '\0') {
@@ -1063,27 +1138,109 @@ int do_commandx(struct nft_handle *h, int argc, char *argv[], char **table)
xtables_error(PARAMETER_PROBLEM,
"nothing appropriate following !");
- if (command & (CMD_REPLACE | CMD_INSERT | CMD_DELETE | CMD_APPEND | CMD_CHECK)) {
- if (!(cs.options & OPT_DESTINATION))
- dhostnetworkmask = "0.0.0.0/0";
- if (!(cs.options & OPT_SOURCE))
- shostnetworkmask = "0.0.0.0/0";
- }
+ switch (family) {
+ case AF_INET:
+ cs.fw.ip.proto = proto;
+ cs.fw.ip.invflags = invflags;
+ cs.fw.ip.flags = flags;
- if (shostnetworkmask)
- xtables_ipparse_multiple(shostnetworkmask, &saddrs,
- &smasks, &nsaddrs);
+ strncpy(cs.fw.ip.iniface, iniface, IFNAMSIZ);
+ memcpy(cs.fw.ip.iniface_mask,
+ iniface_mask, IFNAMSIZ*sizeof(unsigned char));
- if (dhostnetworkmask)
- xtables_ipparse_multiple(dhostnetworkmask, &daddrs,
- &dmasks, &ndaddrs);
+ strncpy(cs.fw.ip.outiface, outiface, IFNAMSIZ);
+ memcpy(cs.fw.ip.outiface_mask,
+ outiface_mask, IFNAMSIZ*sizeof(unsigned char));
- if ((nsaddrs > 1 || ndaddrs > 1) &&
- (cs.fw.ip.invflags & (IPT_INV_SRCIP | IPT_INV_DSTIP)))
- xtables_error(PARAMETER_PROBLEM, "! not allowed with multiple"
- " source or destination IP addresses");
+ if (strlen(cs.jumpto) != 0)
+ cs.fw.ip.flags |= IPT_F_GOTO;
- if (command == CMD_REPLACE && (nsaddrs != 1 || ndaddrs != 1))
+ cs.counters.pcnt = pcnt_cnt;
+ cs.counters.bcnt = bcnt_cnt;
+
+ if (command & (CMD_REPLACE | CMD_INSERT |
+ CMD_DELETE | CMD_APPEND | CMD_CHECK)) {
+ if (!(cs.options & OPT_DESTINATION))
+ dhostnetworkmask = "0.0.0.0/0";
+ if (!(cs.options & OPT_SOURCE))
+ shostnetworkmask = "0.0.0.0/0";
+ }
+
+ if (shostnetworkmask)
+ xtables_ipparse_multiple(shostnetworkmask, &s.addr.v4,
+ &s.mask.v4, &s.naddrs);
+ if (dhostnetworkmask)
+ xtables_ipparse_multiple(dhostnetworkmask, &d.addr.v4,
+ &d.mask.v4, &d.naddrs);
+
+ if ((s.naddrs > 1 || d.naddrs > 1) &&
+ (cs.fw.ip.invflags & (IPT_INV_SRCIP | IPT_INV_DSTIP)))
+ xtables_error(PARAMETER_PROBLEM,
+ "! not allowed with multiple"
+ " source or destination IP addresses");
+ break;
+ case AF_INET6:
+ if (proto != 0)
+ flags |= IP6T_F_PROTO;
+
+ cs.fw6.ipv6.proto = proto;
+ cs.fw6.ipv6.invflags = invflags;
+ cs.fw6.ipv6.flags = flags;
+
+ if (flags & IPT_F_FRAG)
+ xtables_error(PARAMETER_PROBLEM,
+ "-f is not valid on IPv6");
+
+ if (is_exthdr(cs.fw6.ipv6.proto)
+ && (cs.fw6.ipv6.invflags & XT_INV_PROTO) == 0)
+ fprintf(stderr,
+ "Warning: never matched protocol: %s. "
+ "use extension match instead.\n",
+ cs.protocol);
+
+ strncpy(cs.fw6.ipv6.iniface, iniface, IFNAMSIZ);
+ memcpy(cs.fw6.ipv6.iniface_mask,
+ iniface_mask, IFNAMSIZ*sizeof(unsigned char));
+
+ strncpy(cs.fw6.ipv6.outiface, outiface, IFNAMSIZ);
+ memcpy(cs.fw6.ipv6.outiface_mask,
+ outiface_mask, IFNAMSIZ*sizeof(unsigned char));
+
+ if (strlen(cs.jumpto) != 0)
+ cs.fw6.ipv6.flags |= IP6T_F_GOTO;
+
+ cs.fw6.counters.pcnt = pcnt_cnt;
+ cs.fw6.counters.bcnt = bcnt_cnt;
+
+ if (command & (CMD_REPLACE | CMD_INSERT |
+ CMD_DELETE | CMD_APPEND | CMD_CHECK)) {
+ if (!(cs.options & OPT_DESTINATION))
+ dhostnetworkmask = "::0/0";
+ if (!(cs.options & OPT_SOURCE))
+ shostnetworkmask = "::0/0";
+ }
+
+ if (shostnetworkmask)
+ xtables_ip6parse_multiple(shostnetworkmask, &s.addr.v6,
+ &s.mask.v6, &s.naddrs);
+ if (dhostnetworkmask)
+ xtables_ip6parse_multiple(dhostnetworkmask, &d.addr.v6,
+ &d.mask.v6, &d.naddrs);
+
+ if ((s.naddrs > 1 || d.naddrs > 1) &&
+ (cs.fw6.ipv6.invflags & (IP6T_INV_SRCIP | IP6T_INV_DSTIP)))
+ xtables_error(PARAMETER_PROBLEM,
+ "! not allowed with multiple"
+ " source or destination IP addresses");
+ break;
+ default:
+ exit_tryhelp(2);
+ break;
+ }
+
+ h->family = family;
+
+ if (command == CMD_REPLACE && (s.naddrs != 1 || d.naddrs != 1))
xtables_error(PARAMETER_PROBLEM, "Replacement rule does not "
"specify a unique address");
@@ -1128,39 +1285,30 @@ int do_commandx(struct nft_handle *h, int argc, char *argv[], char **table)
switch (command) {
case CMD_APPEND:
- ret = add_entry(chain, *table, &cs,
- nsaddrs, saddrs, smasks,
- ndaddrs, daddrs, dmasks,
- cs.options&OPT_VERBOSE,
+ ret = add_entry(chain, *table, &cs, family,
+ s, d, cs.options&OPT_VERBOSE,
h, true);
break;
case CMD_DELETE:
- ret = delete_entry(chain, *table, &cs,
- nsaddrs, saddrs, smasks,
- ndaddrs, daddrs, dmasks,
- cs.options&OPT_VERBOSE, h);
+ ret = delete_entry(chain, *table, &cs, family,
+ s, d, cs.options&OPT_VERBOSE, h);
break;
case CMD_DELETE_NUM:
ret = nft_rule_delete_num(h, chain, *table, rulenum - 1, verbose);
break;
case CMD_CHECK:
- ret = check_entry(chain, *table, &cs,
- nsaddrs, saddrs, smasks,
- ndaddrs, daddrs, dmasks,
- cs.options&OPT_VERBOSE, h);
+ ret = check_entry(chain, *table, &cs, family,
+ s, d, cs.options&OPT_VERBOSE, h);
break;
case CMD_REPLACE:
/* FIXME replace at rulenum */
ret = replace_entry(chain, *table, &cs, rulenum - 1,
- saddrs, smasks, daddrs, dmasks,
- cs.options&OPT_VERBOSE, h);
+ family, s, d, cs.options&OPT_VERBOSE, h);
break;
case CMD_INSERT:
/* FIXME insert at rulenum */
- ret = add_entry(chain, *table, &cs,
- nsaddrs, saddrs, smasks,
- ndaddrs, daddrs, dmasks,
- cs.options&OPT_VERBOSE, h, false);
+ ret = add_entry(chain, *table, &cs, family,
+ s, d, cs.options&OPT_VERBOSE, h, false);
break;
case CMD_FLUSH:
ret = nft_rule_flush(h, chain, *table);
@@ -1226,10 +1374,17 @@ int do_commandx(struct nft_handle *h, int argc, char *argv[], char **table)
clear_rule_matches(&cs.matches);
- free(saddrs);
- free(smasks);
- free(daddrs);
- free(dmasks);
+ if (family == AF_INET) {
+ free(s.addr.v4);
+ free(s.mask.v4);
+ free(d.addr.v4);
+ free(d.mask.v4);
+ } else if (family == AF_INET6) {
+ free(s.addr.v6);
+ free(s.mask.v6);
+ free(d.addr.v6);
+ free(d.mask.v6);
+ }
xtables_free_opts(1);
return ret;
--
1.8.0.2
^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [iptables-nftables RFC PATCH 0/6] IPv6 Support
2013-01-10 14:29 [iptables-nftables RFC PATCH 0/6] IPv6 Support Tomasz Bursztyka
` (5 preceding siblings ...)
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 ` Pablo Neira Ayuso
6 siblings, 0 replies; 9+ messages in thread
From: Pablo Neira Ayuso @ 2013-01-13 19:23 UTC (permalink / raw)
To: Tomasz Bursztyka; +Cc: netfilter-devel
Hi Tomasz,
On Thu, Jan 10, 2013 at 04:29:33PM +0200, Tomasz Bursztyka wrote:
> Hi,
>
> Here is an attempt to get iptables-nftables supporting IPv6. I
> haven't tested it really, so I send it more as an RFC.
>
> Starting from xtables.c which supports only IPv4, patch 2 combines
> the support for IPv6 in it. The family attribute provided in patch
> 1 is set then used in nft.c to use it accordingly, in patch 3.
>
> Patch 4 finalizes it in handling the right informations for rule
> manipulations depending on the family.
>
> Patch 5 and 6 then adds the support of IPv6 when it comes to
> respectively save and print the firewall.
Good job.
I have merged the 6 patches into one single, they all belong to the
same scope.
I have also tested this, fixed a couple of issues (regarding deletion,
xtables-save/-restore, printing IPv6 destination via xtables -6 -L -n
and spot error if `-f' is used with xtables -6, probably something
else, I forgot, you can diff you initial patch and final result).
I have pushed this into the repository:
http://1984.lsi.us.es/git/iptables-nftables/commit/?id=453ece127f96f155146eff5c2a8b30574d08335d
It would be good if you can move all specific IPv4 and IPv6 code to
nft-ipv4.c and nft-ipv6.c files respectively.
You can use a structure with callbacks like:
struct xtables_family {
int (*add)(...);
void (*print)(...);
void (*print_save)(...);
int (*parse)(...);
int (*is_same)(...);
}
By looking at the previous patch and searching for:
switch(h->family) {
case AF_INET:
...
break;
case AF_INET6:
...
break;
}
Should help to identify the code that needs to be moved to the
specific file.
That encapsulation will help to prepare bridging and arp support.
Thanks a lot!
^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2013-01-13 19:24 UTC | newest]
Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
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 ` [iptables-nftables RFC PATCH 4/6] nft: Support IPv6 rules manipulation Tomasz Bursztyka
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
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).