diff options
author | Arturo Borrero <arturo.borrero.glez@gmail.com> | 2015-01-29 13:34:42 -0500 |
---|---|---|
committer | Pablo Neira Ayuso <pablo@netfilter.org> | 2015-01-30 13:07:59 -0500 |
commit | 5191f4d82daf22b7ee9446f83527d2795e225974 (patch) | |
tree | 3f1a493da6099a40a54e4949a13d949aab2ec8d6 /net | |
parent | 4c72c53be5e3c8cf319a020ea671ab0fc32ec96f (diff) |
netfilter: nft_compat: add ebtables support
This patch extends nft_compat to support ebtables extensions.
ebtables verdict codes are translated to the ones used by the nf_tables engine,
so we can properly use ebtables target extensions from nft_compat.
This patch extends previous work by Giuseppe Longo <giuseppelng@gmail.com>.
Signed-off-by: Arturo Borrero Gonzalez <arturo.borrero.glez@gmail.com>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Diffstat (limited to 'net')
-rw-r--r-- | net/netfilter/nft_compat.c | 63 |
1 files changed, 57 insertions, 6 deletions
diff --git a/net/netfilter/nft_compat.c b/net/netfilter/nft_compat.c index 265e190f2218..c598f74063a1 100644 --- a/net/netfilter/nft_compat.c +++ b/net/netfilter/nft_compat.c | |||
@@ -19,6 +19,7 @@ | |||
19 | #include <linux/netfilter/x_tables.h> | 19 | #include <linux/netfilter/x_tables.h> |
20 | #include <linux/netfilter_ipv4/ip_tables.h> | 20 | #include <linux/netfilter_ipv4/ip_tables.h> |
21 | #include <linux/netfilter_ipv6/ip6_tables.h> | 21 | #include <linux/netfilter_ipv6/ip6_tables.h> |
22 | #include <linux/netfilter_bridge/ebtables.h> | ||
22 | #include <net/netfilter/nf_tables.h> | 23 | #include <net/netfilter/nf_tables.h> |
23 | 24 | ||
24 | static int nft_compat_chain_validate_dependency(const char *tablename, | 25 | static int nft_compat_chain_validate_dependency(const char *tablename, |
@@ -40,6 +41,7 @@ static int nft_compat_chain_validate_dependency(const char *tablename, | |||
40 | union nft_entry { | 41 | union nft_entry { |
41 | struct ipt_entry e4; | 42 | struct ipt_entry e4; |
42 | struct ip6t_entry e6; | 43 | struct ip6t_entry e6; |
44 | struct ebt_entry ebt; | ||
43 | }; | 45 | }; |
44 | 46 | ||
45 | static inline void | 47 | static inline void |
@@ -50,9 +52,9 @@ nft_compat_set_par(struct xt_action_param *par, void *xt, const void *xt_info) | |||
50 | par->hotdrop = false; | 52 | par->hotdrop = false; |
51 | } | 53 | } |
52 | 54 | ||
53 | static void nft_target_eval(const struct nft_expr *expr, | 55 | static void nft_target_eval_xt(const struct nft_expr *expr, |
54 | struct nft_data data[NFT_REG_MAX + 1], | 56 | struct nft_data data[NFT_REG_MAX + 1], |
55 | const struct nft_pktinfo *pkt) | 57 | const struct nft_pktinfo *pkt) |
56 | { | 58 | { |
57 | void *info = nft_expr_priv(expr); | 59 | void *info = nft_expr_priv(expr); |
58 | struct xt_target *target = expr->ops->data; | 60 | struct xt_target *target = expr->ops->data; |
@@ -66,7 +68,7 @@ static void nft_target_eval(const struct nft_expr *expr, | |||
66 | if (pkt->xt.hotdrop) | 68 | if (pkt->xt.hotdrop) |
67 | ret = NF_DROP; | 69 | ret = NF_DROP; |
68 | 70 | ||
69 | switch(ret) { | 71 | switch (ret) { |
70 | case XT_CONTINUE: | 72 | case XT_CONTINUE: |
71 | data[NFT_REG_VERDICT].verdict = NFT_CONTINUE; | 73 | data[NFT_REG_VERDICT].verdict = NFT_CONTINUE; |
72 | break; | 74 | break; |
@@ -74,7 +76,41 @@ static void nft_target_eval(const struct nft_expr *expr, | |||
74 | data[NFT_REG_VERDICT].verdict = ret; | 76 | data[NFT_REG_VERDICT].verdict = ret; |
75 | break; | 77 | break; |
76 | } | 78 | } |
77 | return; | 79 | } |
80 | |||
81 | static void nft_target_eval_bridge(const struct nft_expr *expr, | ||
82 | struct nft_data data[NFT_REG_MAX + 1], | ||
83 | const struct nft_pktinfo *pkt) | ||
84 | { | ||
85 | void *info = nft_expr_priv(expr); | ||
86 | struct xt_target *target = expr->ops->data; | ||
87 | struct sk_buff *skb = pkt->skb; | ||
88 | int ret; | ||
89 | |||
90 | nft_compat_set_par((struct xt_action_param *)&pkt->xt, target, info); | ||
91 | |||
92 | ret = target->target(skb, &pkt->xt); | ||
93 | |||
94 | if (pkt->xt.hotdrop) | ||
95 | ret = NF_DROP; | ||
96 | |||
97 | switch (ret) { | ||
98 | case EBT_ACCEPT: | ||
99 | data[NFT_REG_VERDICT].verdict = NF_ACCEPT; | ||
100 | break; | ||
101 | case EBT_DROP: | ||
102 | data[NFT_REG_VERDICT].verdict = NF_DROP; | ||
103 | break; | ||
104 | case EBT_CONTINUE: | ||
105 | data[NFT_REG_VERDICT].verdict = NFT_CONTINUE; | ||
106 | break; | ||
107 | case EBT_RETURN: | ||
108 | data[NFT_REG_VERDICT].verdict = NFT_RETURN; | ||
109 | break; | ||
110 | default: | ||
111 | data[NFT_REG_VERDICT].verdict = ret; | ||
112 | break; | ||
113 | } | ||
78 | } | 114 | } |
79 | 115 | ||
80 | static const struct nla_policy nft_target_policy[NFTA_TARGET_MAX + 1] = { | 116 | static const struct nla_policy nft_target_policy[NFTA_TARGET_MAX + 1] = { |
@@ -100,6 +136,10 @@ nft_target_set_tgchk_param(struct xt_tgchk_param *par, | |||
100 | entry->e6.ipv6.proto = proto; | 136 | entry->e6.ipv6.proto = proto; |
101 | entry->e6.ipv6.invflags = inv ? IP6T_INV_PROTO : 0; | 137 | entry->e6.ipv6.invflags = inv ? IP6T_INV_PROTO : 0; |
102 | break; | 138 | break; |
139 | case NFPROTO_BRIDGE: | ||
140 | entry->ebt.ethproto = proto; | ||
141 | entry->ebt.invflags = inv ? EBT_IPROTO : 0; | ||
142 | break; | ||
103 | } | 143 | } |
104 | par->entryinfo = entry; | 144 | par->entryinfo = entry; |
105 | par->target = target; | 145 | par->target = target; |
@@ -307,6 +347,10 @@ nft_match_set_mtchk_param(struct xt_mtchk_param *par, const struct nft_ctx *ctx, | |||
307 | entry->e6.ipv6.proto = proto; | 347 | entry->e6.ipv6.proto = proto; |
308 | entry->e6.ipv6.invflags = inv ? IP6T_INV_PROTO : 0; | 348 | entry->e6.ipv6.invflags = inv ? IP6T_INV_PROTO : 0; |
309 | break; | 349 | break; |
350 | case NFPROTO_BRIDGE: | ||
351 | entry->ebt.ethproto = proto; | ||
352 | entry->ebt.invflags = inv ? EBT_IPROTO : 0; | ||
353 | break; | ||
310 | } | 354 | } |
311 | par->entryinfo = entry; | 355 | par->entryinfo = entry; |
312 | par->match = match; | 356 | par->match = match; |
@@ -490,6 +534,9 @@ nfnl_compat_get(struct sock *nfnl, struct sk_buff *skb, | |||
490 | case AF_INET6: | 534 | case AF_INET6: |
491 | fmt = "ip6t_%s"; | 535 | fmt = "ip6t_%s"; |
492 | break; | 536 | break; |
537 | case NFPROTO_BRIDGE: | ||
538 | fmt = "ebt_%s"; | ||
539 | break; | ||
493 | default: | 540 | default: |
494 | pr_err("nft_compat: unsupported protocol %d\n", | 541 | pr_err("nft_compat: unsupported protocol %d\n", |
495 | nfmsg->nfgen_family); | 542 | nfmsg->nfgen_family); |
@@ -663,13 +710,17 @@ nft_target_select_ops(const struct nft_ctx *ctx, | |||
663 | 710 | ||
664 | nft_target->ops.type = &nft_target_type; | 711 | nft_target->ops.type = &nft_target_type; |
665 | nft_target->ops.size = NFT_EXPR_SIZE(XT_ALIGN(target->targetsize)); | 712 | nft_target->ops.size = NFT_EXPR_SIZE(XT_ALIGN(target->targetsize)); |
666 | nft_target->ops.eval = nft_target_eval; | ||
667 | nft_target->ops.init = nft_target_init; | 713 | nft_target->ops.init = nft_target_init; |
668 | nft_target->ops.destroy = nft_target_destroy; | 714 | nft_target->ops.destroy = nft_target_destroy; |
669 | nft_target->ops.dump = nft_target_dump; | 715 | nft_target->ops.dump = nft_target_dump; |
670 | nft_target->ops.validate = nft_target_validate; | 716 | nft_target->ops.validate = nft_target_validate; |
671 | nft_target->ops.data = target; | 717 | nft_target->ops.data = target; |
672 | 718 | ||
719 | if (family == NFPROTO_BRIDGE) | ||
720 | nft_target->ops.eval = nft_target_eval_bridge; | ||
721 | else | ||
722 | nft_target->ops.eval = nft_target_eval_xt; | ||
723 | |||
673 | list_add(&nft_target->head, &nft_target_list); | 724 | list_add(&nft_target->head, &nft_target_list); |
674 | 725 | ||
675 | return &nft_target->ops; | 726 | return &nft_target->ops; |