diff options
author | Pablo Neira Ayuso <pablo@netfilter.org> | 2014-09-26 08:35:14 -0400 |
---|---|---|
committer | Pablo Neira Ayuso <pablo@netfilter.org> | 2014-10-02 12:29:57 -0400 |
commit | 51b0a5d8c21a91801bbef9bcc8639dc0b206c6cd (patch) | |
tree | 62255f89e7725a5173d4b4e4f002f114ad524dda /net/bridge | |
parent | 2c804d0f8fc7799981d9fdd8c88653541b28c1a7 (diff) |
netfilter: nft_reject: introduce icmp code abstraction for inet and bridge
This patch introduces the NFT_REJECT_ICMPX_UNREACH type which provides
an abstraction to the ICMP and ICMPv6 codes that you can use from the
inet and bridge tables, they are:
* NFT_REJECT_ICMPX_NO_ROUTE: no route to host - network unreachable
* NFT_REJECT_ICMPX_PORT_UNREACH: port unreachable
* NFT_REJECT_ICMPX_HOST_UNREACH: host unreachable
* NFT_REJECT_ICMPX_ADMIN_PROHIBITED: administratevely prohibited
You can still use the specific codes when restricting the rule to match
the corresponding layer 3 protocol.
I decided to not overload the existing NFT_REJECT_ICMP_UNREACH to have
different semantics depending on the table family and to allow the user
to specify ICMP family specific codes if they restrict it to the
corresponding family.
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Diffstat (limited to 'net/bridge')
-rw-r--r-- | net/bridge/netfilter/nft_reject_bridge.c | 95 |
1 files changed, 90 insertions, 5 deletions
diff --git a/net/bridge/netfilter/nft_reject_bridge.c b/net/bridge/netfilter/nft_reject_bridge.c index ee3ffe93e14e..a76479535df2 100644 --- a/net/bridge/netfilter/nft_reject_bridge.c +++ b/net/bridge/netfilter/nft_reject_bridge.c | |||
@@ -14,21 +14,106 @@ | |||
14 | #include <linux/netfilter/nf_tables.h> | 14 | #include <linux/netfilter/nf_tables.h> |
15 | #include <net/netfilter/nf_tables.h> | 15 | #include <net/netfilter/nf_tables.h> |
16 | #include <net/netfilter/nft_reject.h> | 16 | #include <net/netfilter/nft_reject.h> |
17 | #include <net/netfilter/ipv4/nf_reject.h> | ||
18 | #include <net/netfilter/ipv6/nf_reject.h> | ||
17 | 19 | ||
18 | static void nft_reject_bridge_eval(const struct nft_expr *expr, | 20 | static void nft_reject_bridge_eval(const struct nft_expr *expr, |
19 | struct nft_data data[NFT_REG_MAX + 1], | 21 | struct nft_data data[NFT_REG_MAX + 1], |
20 | const struct nft_pktinfo *pkt) | 22 | const struct nft_pktinfo *pkt) |
21 | { | 23 | { |
24 | struct nft_reject *priv = nft_expr_priv(expr); | ||
25 | struct net *net = dev_net((pkt->in != NULL) ? pkt->in : pkt->out); | ||
26 | |||
22 | switch (eth_hdr(pkt->skb)->h_proto) { | 27 | switch (eth_hdr(pkt->skb)->h_proto) { |
23 | case htons(ETH_P_IP): | 28 | case htons(ETH_P_IP): |
24 | return nft_reject_ipv4_eval(expr, data, pkt); | 29 | switch (priv->type) { |
30 | case NFT_REJECT_ICMP_UNREACH: | ||
31 | nf_send_unreach(pkt->skb, priv->icmp_code); | ||
32 | break; | ||
33 | case NFT_REJECT_TCP_RST: | ||
34 | nf_send_reset(pkt->skb, pkt->ops->hooknum); | ||
35 | break; | ||
36 | case NFT_REJECT_ICMPX_UNREACH: | ||
37 | nf_send_unreach(pkt->skb, | ||
38 | nft_reject_icmp_code(priv->icmp_code)); | ||
39 | break; | ||
40 | } | ||
41 | break; | ||
25 | case htons(ETH_P_IPV6): | 42 | case htons(ETH_P_IPV6): |
26 | return nft_reject_ipv6_eval(expr, data, pkt); | 43 | switch (priv->type) { |
44 | case NFT_REJECT_ICMP_UNREACH: | ||
45 | nf_send_unreach6(net, pkt->skb, priv->icmp_code, | ||
46 | pkt->ops->hooknum); | ||
47 | break; | ||
48 | case NFT_REJECT_TCP_RST: | ||
49 | nf_send_reset6(net, pkt->skb, pkt->ops->hooknum); | ||
50 | break; | ||
51 | case NFT_REJECT_ICMPX_UNREACH: | ||
52 | nf_send_unreach6(net, pkt->skb, | ||
53 | nft_reject_icmpv6_code(priv->icmp_code), | ||
54 | pkt->ops->hooknum); | ||
55 | break; | ||
56 | } | ||
57 | break; | ||
27 | default: | 58 | default: |
28 | /* No explicit way to reject this protocol, drop it. */ | 59 | /* No explicit way to reject this protocol, drop it. */ |
29 | data[NFT_REG_VERDICT].verdict = NF_DROP; | ||
30 | break; | 60 | break; |
31 | } | 61 | } |
62 | data[NFT_REG_VERDICT].verdict = NF_DROP; | ||
63 | } | ||
64 | |||
65 | static int nft_reject_bridge_init(const struct nft_ctx *ctx, | ||
66 | const struct nft_expr *expr, | ||
67 | const struct nlattr * const tb[]) | ||
68 | { | ||
69 | struct nft_reject *priv = nft_expr_priv(expr); | ||
70 | int icmp_code; | ||
71 | |||
72 | if (tb[NFTA_REJECT_TYPE] == NULL) | ||
73 | return -EINVAL; | ||
74 | |||
75 | priv->type = ntohl(nla_get_be32(tb[NFTA_REJECT_TYPE])); | ||
76 | switch (priv->type) { | ||
77 | case NFT_REJECT_ICMP_UNREACH: | ||
78 | case NFT_REJECT_ICMPX_UNREACH: | ||
79 | if (tb[NFTA_REJECT_ICMP_CODE] == NULL) | ||
80 | return -EINVAL; | ||
81 | |||
82 | icmp_code = nla_get_u8(tb[NFTA_REJECT_ICMP_CODE]); | ||
83 | if (priv->type == NFT_REJECT_ICMPX_UNREACH && | ||
84 | icmp_code > NFT_REJECT_ICMPX_MAX) | ||
85 | return -EINVAL; | ||
86 | |||
87 | priv->icmp_code = icmp_code; | ||
88 | break; | ||
89 | case NFT_REJECT_TCP_RST: | ||
90 | break; | ||
91 | default: | ||
92 | return -EINVAL; | ||
93 | } | ||
94 | return 0; | ||
95 | } | ||
96 | |||
97 | static int nft_reject_bridge_dump(struct sk_buff *skb, | ||
98 | const struct nft_expr *expr) | ||
99 | { | ||
100 | const struct nft_reject *priv = nft_expr_priv(expr); | ||
101 | |||
102 | if (nla_put_be32(skb, NFTA_REJECT_TYPE, htonl(priv->type))) | ||
103 | goto nla_put_failure; | ||
104 | |||
105 | switch (priv->type) { | ||
106 | case NFT_REJECT_ICMP_UNREACH: | ||
107 | case NFT_REJECT_ICMPX_UNREACH: | ||
108 | if (nla_put_u8(skb, NFTA_REJECT_ICMP_CODE, priv->icmp_code)) | ||
109 | goto nla_put_failure; | ||
110 | break; | ||
111 | } | ||
112 | |||
113 | return 0; | ||
114 | |||
115 | nla_put_failure: | ||
116 | return -1; | ||
32 | } | 117 | } |
33 | 118 | ||
34 | static struct nft_expr_type nft_reject_bridge_type; | 119 | static struct nft_expr_type nft_reject_bridge_type; |
@@ -36,8 +121,8 @@ static const struct nft_expr_ops nft_reject_bridge_ops = { | |||
36 | .type = &nft_reject_bridge_type, | 121 | .type = &nft_reject_bridge_type, |
37 | .size = NFT_EXPR_SIZE(sizeof(struct nft_reject)), | 122 | .size = NFT_EXPR_SIZE(sizeof(struct nft_reject)), |
38 | .eval = nft_reject_bridge_eval, | 123 | .eval = nft_reject_bridge_eval, |
39 | .init = nft_reject_init, | 124 | .init = nft_reject_bridge_init, |
40 | .dump = nft_reject_dump, | 125 | .dump = nft_reject_bridge_dump, |
41 | }; | 126 | }; |
42 | 127 | ||
43 | static struct nft_expr_type nft_reject_bridge_type __read_mostly = { | 128 | static struct nft_expr_type nft_reject_bridge_type __read_mostly = { |