summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPablo Neira Ayuso <pablo@netfilter.org>2013-05-12 16:47:11 +0200
committerPablo Neira Ayuso <pablo@netfilter.org>2013-12-30 23:50:29 +0100
commit6838a7f51e6d95f904093e05e8bdc75ada70b93f (patch)
treeff0bedfcab7dbbe0bf547c1a3879bc64f949720c
parent26d3a0d77c67289341361bbd3254f2257eec69a0 (diff)
xtables: add new nft_ops->post_parse hook
Move specific layer 3 protocol post argument parsing code to the respective nft-ipv[4|6].c files. Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
-rw-r--r--iptables/nft-ipv4.c51
-rw-r--r--iptables/nft-ipv6.c67
-rw-r--r--iptables/nft-shared.h21
-rw-r--r--iptables/xtables.c131
4 files changed, 139 insertions, 131 deletions
diff --git a/iptables/nft-ipv4.c b/iptables/nft-ipv4.c
index 0a601243..51ee422c 100644
--- a/iptables/nft-ipv4.c
+++ b/iptables/nft-ipv4.c
@@ -298,12 +298,59 @@ static uint8_t nft_ipv4_print_firewall(const struct iptables_command_state *cs,
return cs->fw.ip.flags;
}
+static void nft_ipv4_post_parse(int command,
+ struct iptables_command_state *cs,
+ struct xtables_args *args)
+{
+ cs->fw.ip.proto = args->proto;
+ cs->fw.ip.invflags = args->invflags;
+ cs->fw.ip.flags = args->flags;
+
+ strncpy(cs->fw.ip.iniface, args->iniface, IFNAMSIZ);
+ memcpy(cs->fw.ip.iniface_mask,
+ args->iniface_mask, IFNAMSIZ*sizeof(unsigned char));
+
+ strncpy(cs->fw.ip.outiface, args->outiface, IFNAMSIZ);
+ memcpy(cs->fw.ip.outiface_mask,
+ args->outiface_mask, IFNAMSIZ*sizeof(unsigned char));
+
+ if (args->goto_set)
+ cs->fw.ip.flags |= IPT_F_GOTO;
+
+ cs->counters.pcnt = args->pcnt_cnt;
+ cs->counters.bcnt = args->bcnt_cnt;
+
+ if (command & (CMD_REPLACE | CMD_INSERT |
+ CMD_DELETE | CMD_APPEND | CMD_CHECK)) {
+ if (!(cs->options & OPT_DESTINATION))
+ args->dhostnetworkmask = "0.0.0.0/0";
+ if (!(cs->options & OPT_SOURCE))
+ args->shostnetworkmask = "0.0.0.0/0";
+ }
+
+ if (args->shostnetworkmask)
+ xtables_ipparse_multiple(args->shostnetworkmask,
+ &args->s.addr.v4, &args->s.mask.v4,
+ &args->s.naddrs);
+ if (args->dhostnetworkmask)
+ xtables_ipparse_multiple(args->dhostnetworkmask,
+ &args->d.addr.v4, &args->d.mask.v4,
+ &args->d.naddrs);
+
+ if ((args->s.naddrs > 1 || args->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");
+}
+
struct nft_family_ops nft_family_ops_ipv4 = {
.add = nft_ipv4_add,
.is_same = nft_ipv4_is_same,
.print_payload = nft_ipv4_print_payload,
.parse_meta = nft_ipv4_parse_meta,
.parse_payload = nft_ipv4_parse_payload,
- .parse_immediate = nft_ipv4_parse_immediate,
- .print_firewall = nft_ipv4_print_firewall,
+ .parse_immediate = nft_ipv4_parse_immediate,
+ .print_firewall = nft_ipv4_print_firewall,
+ .post_parse = nft_ipv4_post_parse,
};
diff --git a/iptables/nft-ipv6.c b/iptables/nft-ipv6.c
index 65a89490..61c660a5 100644
--- a/iptables/nft-ipv6.c
+++ b/iptables/nft-ipv6.c
@@ -208,6 +208,72 @@ static uint8_t nft_ipv6_print_firewall(const struct iptables_command_state *cs,
return cs->fw6.ipv6.flags;
}
+/* 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);
+}
+
+static void nft_ipv6_post_parse(int command, struct iptables_command_state *cs,
+ struct xtables_args *args)
+{
+ if (args->proto != 0)
+ args->flags |= IP6T_F_PROTO;
+
+ cs->fw6.ipv6.proto = args->proto;
+ cs->fw6.ipv6.invflags = args->invflags;
+ cs->fw6.ipv6.flags = args->flags;
+
+ 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, args->iniface, IFNAMSIZ);
+ memcpy(cs->fw6.ipv6.iniface_mask,
+ args->iniface_mask, IFNAMSIZ*sizeof(unsigned char));
+
+ strncpy(cs->fw6.ipv6.outiface, args->outiface, IFNAMSIZ);
+ memcpy(cs->fw6.ipv6.outiface_mask,
+ args->outiface_mask, IFNAMSIZ*sizeof(unsigned char));
+
+ if (args->goto_set)
+ cs->fw6.ipv6.flags |= IP6T_F_GOTO;
+
+ cs->fw6.counters.pcnt = args->pcnt_cnt;
+ cs->fw6.counters.bcnt = args->bcnt_cnt;
+
+ if (command & (CMD_REPLACE | CMD_INSERT |
+ CMD_DELETE | CMD_APPEND | CMD_CHECK)) {
+ if (!(cs->options & OPT_DESTINATION))
+ args->dhostnetworkmask = "::0/0";
+ if (!(cs->options & OPT_SOURCE))
+ args->shostnetworkmask = "::0/0";
+ }
+
+ if (args->shostnetworkmask)
+ xtables_ip6parse_multiple(args->shostnetworkmask,
+ &args->s.addr.v6,
+ &args->s.mask.v6,
+ &args->s.naddrs);
+ if (args->dhostnetworkmask)
+ xtables_ip6parse_multiple(args->dhostnetworkmask,
+ &args->d.addr.v6,
+ &args->d.mask.v6,
+ &args->d.naddrs);
+
+ if ((args->s.naddrs > 1 || args->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");
+}
+
struct nft_family_ops nft_family_ops_ipv6 = {
.add = nft_ipv6_add,
.is_same = nft_ipv6_is_same,
@@ -216,4 +282,5 @@ struct nft_family_ops nft_family_ops_ipv6 = {
.parse_payload = nft_ipv6_parse_payload,
.parse_immediate = nft_ipv6_parse_immediate,
.print_firewall = nft_ipv6_print_firewall,
+ .post_parse = nft_ipv6_post_parse,
};
diff --git a/iptables/nft-shared.h b/iptables/nft-shared.h
index 30e87bb3..59734d9d 100644
--- a/iptables/nft-shared.h
+++ b/iptables/nft-shared.h
@@ -34,6 +34,8 @@
| FMT_NUMERIC | FMT_NOTABLE)
#define FMT(tab,notab) ((format) & FMT_NOTABLE ? (notab) : (tab))
+struct xtables_args;
+
struct nft_family_ops {
int (*add)(struct nft_rule *r, struct iptables_command_state *cs);
bool (*is_same)(const struct iptables_command_state *a,
@@ -49,6 +51,8 @@ struct nft_family_ops {
uint8_t (*print_firewall)(const struct iptables_command_state *cs,
const char *targname, unsigned int num,
unsigned int format);
+ void (*post_parse)(int command, struct iptables_command_state *cs,
+ struct xtables_args *args);
};
void add_meta(struct nft_rule *r, uint32_t key);
@@ -116,4 +120,21 @@ struct xtables_args {
unsigned long long pcnt_cnt, bcnt_cnt;
};
+#define CMD_NONE 0x0000U
+#define CMD_INSERT 0x0001U
+#define CMD_DELETE 0x0002U
+#define CMD_DELETE_NUM 0x0004U
+#define CMD_REPLACE 0x0008U
+#define CMD_APPEND 0x0010U
+#define CMD_LIST 0x0020U
+#define CMD_FLUSH 0x0040U
+#define CMD_ZERO 0x0080U
+#define CMD_NEW_CHAIN 0x0100U
+#define CMD_DELETE_CHAIN 0x0200U
+#define CMD_SET_POLICY 0x0400U
+#define CMD_RENAME_CHAIN 0x0800U
+#define CMD_LIST_RULES 0x1000U
+#define CMD_ZERO_NUM 0x2000U
+#define CMD_CHECK 0x4000U
+
#endif
diff --git a/iptables/xtables.c b/iptables/xtables.c
index 6a1a1646..e3a6c802 100644
--- a/iptables/xtables.c
+++ b/iptables/xtables.c
@@ -50,22 +50,6 @@
#define FALSE 0
#endif
-#define CMD_NONE 0x0000U
-#define CMD_INSERT 0x0001U
-#define CMD_DELETE 0x0002U
-#define CMD_DELETE_NUM 0x0004U
-#define CMD_REPLACE 0x0008U
-#define CMD_APPEND 0x0010U
-#define CMD_LIST 0x0020U
-#define CMD_FLUSH 0x0040U
-#define CMD_ZERO 0x0080U
-#define CMD_NEW_CHAIN 0x0100U
-#define CMD_DELETE_CHAIN 0x0200U
-#define CMD_SET_POLICY 0x0400U
-#define CMD_RENAME_CHAIN 0x0800U
-#define CMD_LIST_RULES 0x1000U
-#define CMD_ZERO_NUM 0x2000U
-#define CMD_CHECK 0x4000U
#define NUMBER_OF_CMD 16
static const char cmdflags[] = { 'I', 'D', 'D', 'R', 'A', 'L', 'F', 'Z',
'N', 'X', 'P', 'E', 'S', 'Z', 'C' };
@@ -376,15 +360,6 @@ 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
@@ -1141,110 +1116,6 @@ int do_commandx(struct nft_handle *h, int argc, char *argv[], char **table)
xtables_error(PARAMETER_PROBLEM,
"nothing appropriate following !");
- switch (args.family) {
- case AF_INET:
- cs.fw.ip.proto = args.proto;
- cs.fw.ip.invflags = args.invflags;
- cs.fw.ip.flags = args.flags;
-
- strncpy(cs.fw.ip.iniface, args.iniface, IFNAMSIZ);
- memcpy(cs.fw.ip.iniface_mask,
- args.iniface_mask, IFNAMSIZ*sizeof(unsigned char));
-
- strncpy(cs.fw.ip.outiface, args.outiface, IFNAMSIZ);
- memcpy(cs.fw.ip.outiface_mask,
- args.outiface_mask, IFNAMSIZ*sizeof(unsigned char));
-
- if (args.goto_set)
- cs.fw.ip.flags |= IPT_F_GOTO;
-
- cs.counters.pcnt = args.pcnt_cnt;
- cs.counters.bcnt = args.bcnt_cnt;
-
- if (command & (CMD_REPLACE | CMD_INSERT |
- CMD_DELETE | CMD_APPEND | CMD_CHECK)) {
- if (!(cs.options & OPT_DESTINATION))
- args.dhostnetworkmask = "0.0.0.0/0";
- if (!(cs.options & OPT_SOURCE))
- args.shostnetworkmask = "0.0.0.0/0";
- }
-
- if (args.shostnetworkmask)
- xtables_ipparse_multiple(args.shostnetworkmask,
- &args.s.addr.v4,
- &args.s.mask.v4,
- &args.s.naddrs);
- if (args.dhostnetworkmask)
- xtables_ipparse_multiple(args.dhostnetworkmask,
- &args.d.addr.v4,
- &args.d.mask.v4,
- &args.d.naddrs);
-
- if ((args.s.naddrs > 1 || args.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 (args.proto != 0)
- args.flags |= IP6T_F_PROTO;
-
- cs.fw6.ipv6.proto = args.proto;
- cs.fw6.ipv6.invflags = args.invflags;
- cs.fw6.ipv6.flags = args.flags;
-
- 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, args.iniface, IFNAMSIZ);
- memcpy(cs.fw6.ipv6.iniface_mask,
- args.iniface_mask, IFNAMSIZ*sizeof(unsigned char));
-
- strncpy(cs.fw6.ipv6.outiface, args.outiface, IFNAMSIZ);
- memcpy(cs.fw6.ipv6.outiface_mask,
- args.outiface_mask, IFNAMSIZ*sizeof(unsigned char));
-
- if (args.goto_set)
- cs.fw6.ipv6.flags |= IP6T_F_GOTO;
-
- cs.fw6.counters.pcnt = args.pcnt_cnt;
- cs.fw6.counters.bcnt = args.bcnt_cnt;
-
- if (command & (CMD_REPLACE | CMD_INSERT |
- CMD_DELETE | CMD_APPEND | CMD_CHECK)) {
- if (!(cs.options & OPT_DESTINATION))
- args.dhostnetworkmask = "::0/0";
- if (!(cs.options & OPT_SOURCE))
- args.shostnetworkmask = "::0/0";
- }
-
- if (args.shostnetworkmask)
- xtables_ip6parse_multiple(args.shostnetworkmask,
- &args.s.addr.v6,
- &args.s.mask.v6,
- &args.s.naddrs);
- if (args.dhostnetworkmask)
- xtables_ip6parse_multiple(args.dhostnetworkmask,
- &args.d.addr.v6,
- &args.d.mask.v6,
- &args.d.naddrs);
-
- if ((args.s.naddrs > 1 || args.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;
- }
-
/* Set only if required, needed by xtables-restore */
if (h->family == AF_UNSPEC)
h->family = args.family;
@@ -1253,6 +1124,8 @@ int do_commandx(struct nft_handle *h, int argc, char *argv[], char **table)
if (h->ops == NULL)
xtables_error(PARAMETER_PROBLEM, "Unknown family");
+ h->ops->post_parse(command, &cs, &args);
+
if (command == CMD_REPLACE &&
(args.s.naddrs != 1 || args.d.naddrs != 1))
xtables_error(PARAMETER_PROBLEM, "Replacement rule does not "