aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPatrick McHardy <kaber@trash.net>2014-01-03 07:16:13 -0500
committerPablo Neira Ayuso <pablo@netfilter.org>2014-01-07 17:50:43 -0500
commit3b088c4bc0035da662faa81818ba217e34c4bba4 (patch)
tree1d43e3ff229e464491a5764efae37ed030d11bd7
parent688d18636f77e360ae9078d7cd78a2556a1f35c1 (diff)
netfilter: nf_tables: make chain types override the default AF functions
Currently the AF-specific hook functions override the chain-type specific hook functions. That doesn't make too much sense since the chain types are a special case of the AF-specific hooks. Make the AF-specific hook functions the default and make the optional chain type hooks override them. As a side effect, the necessary code restructuring reduces the code size, f.i. in case of nf_tables_ipv4.o: nf_tables_ipv4_init_net | -24 nft_do_chain_ipv4 | -113 2 functions changed, 137 bytes removed, diff: -137 Signed-off-by: Patrick McHardy <kaber@trash.net> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
-rw-r--r--net/bridge/netfilter/nf_tables_bridge.c38
-rw-r--r--net/ipv4/netfilter/nf_tables_arp.c38
-rw-r--r--net/ipv4/netfilter/nf_tables_ipv4.c43
-rw-r--r--net/ipv6/netfilter/nf_tables_ipv6.c48
-rw-r--r--net/netfilter/nf_tables_api.c10
5 files changed, 81 insertions, 96 deletions
diff --git a/net/bridge/netfilter/nf_tables_bridge.c b/net/bridge/netfilter/nf_tables_bridge.c
index cf54b22818c8..c5fdd9a693be 100644
--- a/net/bridge/netfilter/nf_tables_bridge.c
+++ b/net/bridge/netfilter/nf_tables_bridge.c
@@ -14,10 +14,29 @@
14#include <linux/netfilter_bridge.h> 14#include <linux/netfilter_bridge.h>
15#include <net/netfilter/nf_tables.h> 15#include <net/netfilter/nf_tables.h>
16 16
17static unsigned int
18nft_do_chain_bridge(const struct nf_hook_ops *ops,
19 struct sk_buff *skb,
20 const struct net_device *in,
21 const struct net_device *out,
22 int (*okfn)(struct sk_buff *))
23{
24 struct nft_pktinfo pkt;
25
26 nft_set_pktinfo(&pkt, ops, skb, in, out);
27
28 return nft_do_chain_pktinfo(&pkt, ops);
29}
30
17static struct nft_af_info nft_af_bridge __read_mostly = { 31static struct nft_af_info nft_af_bridge __read_mostly = {
18 .family = NFPROTO_BRIDGE, 32 .family = NFPROTO_BRIDGE,
19 .nhooks = NF_BR_NUMHOOKS, 33 .nhooks = NF_BR_NUMHOOKS,
20 .owner = THIS_MODULE, 34 .owner = THIS_MODULE,
35 .hooks = {
36 [NF_BR_LOCAL_IN] = nft_do_chain_bridge,
37 [NF_BR_FORWARD] = nft_do_chain_bridge,
38 [NF_BR_LOCAL_OUT] = nft_do_chain_bridge,
39 },
21}; 40};
22 41
23static int nf_tables_bridge_init_net(struct net *net) 42static int nf_tables_bridge_init_net(struct net *net)
@@ -48,20 +67,6 @@ static struct pernet_operations nf_tables_bridge_net_ops = {
48 .exit = nf_tables_bridge_exit_net, 67 .exit = nf_tables_bridge_exit_net,
49}; 68};
50 69
51static unsigned int
52nft_do_chain_bridge(const struct nf_hook_ops *ops,
53 struct sk_buff *skb,
54 const struct net_device *in,
55 const struct net_device *out,
56 int (*okfn)(struct sk_buff *))
57{
58 struct nft_pktinfo pkt;
59
60 nft_set_pktinfo(&pkt, ops, skb, in, out);
61
62 return nft_do_chain_pktinfo(&pkt, ops);
63}
64
65static struct nf_chain_type filter_bridge = { 70static struct nf_chain_type filter_bridge = {
66 .family = NFPROTO_BRIDGE, 71 .family = NFPROTO_BRIDGE,
67 .name = "filter", 72 .name = "filter",
@@ -69,11 +74,6 @@ static struct nf_chain_type filter_bridge = {
69 .hook_mask = (1 << NF_BR_LOCAL_IN) | 74 .hook_mask = (1 << NF_BR_LOCAL_IN) |
70 (1 << NF_BR_FORWARD) | 75 (1 << NF_BR_FORWARD) |
71 (1 << NF_BR_LOCAL_OUT), 76 (1 << NF_BR_LOCAL_OUT),
72 .fn = {
73 [NF_BR_LOCAL_IN] = nft_do_chain_bridge,
74 [NF_BR_FORWARD] = nft_do_chain_bridge,
75 [NF_BR_LOCAL_OUT] = nft_do_chain_bridge,
76 },
77}; 77};
78 78
79static int __init nf_tables_bridge_init(void) 79static int __init nf_tables_bridge_init(void)
diff --git a/net/ipv4/netfilter/nf_tables_arp.c b/net/ipv4/netfilter/nf_tables_arp.c
index 3e67ef1c676f..31bb778cebb8 100644
--- a/net/ipv4/netfilter/nf_tables_arp.c
+++ b/net/ipv4/netfilter/nf_tables_arp.c
@@ -14,10 +14,29 @@
14#include <linux/netfilter_arp.h> 14#include <linux/netfilter_arp.h>
15#include <net/netfilter/nf_tables.h> 15#include <net/netfilter/nf_tables.h>
16 16
17static unsigned int
18nft_do_chain_arp(const struct nf_hook_ops *ops,
19 struct sk_buff *skb,
20 const struct net_device *in,
21 const struct net_device *out,
22 int (*okfn)(struct sk_buff *))
23{
24 struct nft_pktinfo pkt;
25
26 nft_set_pktinfo(&pkt, ops, skb, in, out);
27
28 return nft_do_chain_pktinfo(&pkt, ops);
29}
30
17static struct nft_af_info nft_af_arp __read_mostly = { 31static struct nft_af_info nft_af_arp __read_mostly = {
18 .family = NFPROTO_ARP, 32 .family = NFPROTO_ARP,
19 .nhooks = NF_ARP_NUMHOOKS, 33 .nhooks = NF_ARP_NUMHOOKS,
20 .owner = THIS_MODULE, 34 .owner = THIS_MODULE,
35 .hooks = {
36 [NF_ARP_IN] = nft_do_chain_arp,
37 [NF_ARP_OUT] = nft_do_chain_arp,
38 [NF_ARP_FORWARD] = nft_do_chain_arp,
39 },
21}; 40};
22 41
23static int nf_tables_arp_init_net(struct net *net) 42static int nf_tables_arp_init_net(struct net *net)
@@ -48,20 +67,6 @@ static struct pernet_operations nf_tables_arp_net_ops = {
48 .exit = nf_tables_arp_exit_net, 67 .exit = nf_tables_arp_exit_net,
49}; 68};
50 69
51static unsigned int
52nft_do_chain_arp(const struct nf_hook_ops *ops,
53 struct sk_buff *skb,
54 const struct net_device *in,
55 const struct net_device *out,
56 int (*okfn)(struct sk_buff *))
57{
58 struct nft_pktinfo pkt;
59
60 nft_set_pktinfo(&pkt, ops, skb, in, out);
61
62 return nft_do_chain_pktinfo(&pkt, ops);
63}
64
65static struct nf_chain_type filter_arp = { 70static struct nf_chain_type filter_arp = {
66 .family = NFPROTO_ARP, 71 .family = NFPROTO_ARP,
67 .name = "filter", 72 .name = "filter",
@@ -69,11 +74,6 @@ static struct nf_chain_type filter_arp = {
69 .hook_mask = (1 << NF_ARP_IN) | 74 .hook_mask = (1 << NF_ARP_IN) |
70 (1 << NF_ARP_OUT) | 75 (1 << NF_ARP_OUT) |
71 (1 << NF_ARP_FORWARD), 76 (1 << NF_ARP_FORWARD),
72 .fn = {
73 [NF_ARP_IN] = nft_do_chain_arp,
74 [NF_ARP_OUT] = nft_do_chain_arp,
75 [NF_ARP_FORWARD] = nft_do_chain_arp,
76 },
77}; 77};
78 78
79static int __init nf_tables_arp_init(void) 79static int __init nf_tables_arp_init(void)
diff --git a/net/ipv4/netfilter/nf_tables_ipv4.c b/net/ipv4/netfilter/nf_tables_ipv4.c
index 0f4cbfeb19bd..ed7e15a93410 100644
--- a/net/ipv4/netfilter/nf_tables_ipv4.c
+++ b/net/ipv4/netfilter/nf_tables_ipv4.c
@@ -18,14 +18,25 @@
18#include <net/ip.h> 18#include <net/ip.h>
19#include <net/netfilter/nf_tables_ipv4.h> 19#include <net/netfilter/nf_tables_ipv4.h>
20 20
21static unsigned int nft_do_chain_ipv4(const struct nf_hook_ops *ops,
22 struct sk_buff *skb,
23 const struct net_device *in,
24 const struct net_device *out,
25 int (*okfn)(struct sk_buff *))
26{
27 struct nft_pktinfo pkt;
28
29 nft_set_pktinfo_ipv4(&pkt, ops, skb, in, out);
30
31 return nft_do_chain_pktinfo(&pkt, ops);
32}
33
21static unsigned int nft_ipv4_output(const struct nf_hook_ops *ops, 34static unsigned int nft_ipv4_output(const struct nf_hook_ops *ops,
22 struct sk_buff *skb, 35 struct sk_buff *skb,
23 const struct net_device *in, 36 const struct net_device *in,
24 const struct net_device *out, 37 const struct net_device *out,
25 int (*okfn)(struct sk_buff *)) 38 int (*okfn)(struct sk_buff *))
26{ 39{
27 struct nft_pktinfo pkt;
28
29 if (unlikely(skb->len < sizeof(struct iphdr) || 40 if (unlikely(skb->len < sizeof(struct iphdr) ||
30 ip_hdr(skb)->ihl < sizeof(struct iphdr) / 4)) { 41 ip_hdr(skb)->ihl < sizeof(struct iphdr) / 4)) {
31 if (net_ratelimit()) 42 if (net_ratelimit())
@@ -33,9 +44,8 @@ static unsigned int nft_ipv4_output(const struct nf_hook_ops *ops,
33 "packet\n"); 44 "packet\n");
34 return NF_ACCEPT; 45 return NF_ACCEPT;
35 } 46 }
36 nft_set_pktinfo_ipv4(&pkt, ops, skb, in, out);
37 47
38 return nft_do_chain_pktinfo(&pkt, ops); 48 return nft_do_chain_ipv4(ops, skb, in, out, okfn);
39} 49}
40 50
41static struct nft_af_info nft_af_ipv4 __read_mostly = { 51static struct nft_af_info nft_af_ipv4 __read_mostly = {
@@ -43,7 +53,11 @@ static struct nft_af_info nft_af_ipv4 __read_mostly = {
43 .nhooks = NF_INET_NUMHOOKS, 53 .nhooks = NF_INET_NUMHOOKS,
44 .owner = THIS_MODULE, 54 .owner = THIS_MODULE,
45 .hooks = { 55 .hooks = {
56 [NF_INET_LOCAL_IN] = nft_do_chain_ipv4,
46 [NF_INET_LOCAL_OUT] = nft_ipv4_output, 57 [NF_INET_LOCAL_OUT] = nft_ipv4_output,
58 [NF_INET_FORWARD] = nft_do_chain_ipv4,
59 [NF_INET_PRE_ROUTING] = nft_do_chain_ipv4,
60 [NF_INET_POST_ROUTING] = nft_do_chain_ipv4,
47 }, 61 },
48}; 62};
49 63
@@ -75,20 +89,6 @@ static struct pernet_operations nf_tables_ipv4_net_ops = {
75 .exit = nf_tables_ipv4_exit_net, 89 .exit = nf_tables_ipv4_exit_net,
76}; 90};
77 91
78static unsigned int
79nft_do_chain_ipv4(const struct nf_hook_ops *ops,
80 struct sk_buff *skb,
81 const struct net_device *in,
82 const struct net_device *out,
83 int (*okfn)(struct sk_buff *))
84{
85 struct nft_pktinfo pkt;
86
87 nft_set_pktinfo_ipv4(&pkt, ops, skb, in, out);
88
89 return nft_do_chain_pktinfo(&pkt, ops);
90}
91
92static struct nf_chain_type filter_ipv4 = { 92static struct nf_chain_type filter_ipv4 = {
93 .family = NFPROTO_IPV4, 93 .family = NFPROTO_IPV4,
94 .name = "filter", 94 .name = "filter",
@@ -98,13 +98,6 @@ static struct nf_chain_type filter_ipv4 = {
98 (1 << NF_INET_FORWARD) | 98 (1 << NF_INET_FORWARD) |
99 (1 << NF_INET_PRE_ROUTING) | 99 (1 << NF_INET_PRE_ROUTING) |
100 (1 << NF_INET_POST_ROUTING), 100 (1 << NF_INET_POST_ROUTING),
101 .fn = {
102 [NF_INET_LOCAL_IN] = nft_do_chain_ipv4,
103 [NF_INET_LOCAL_OUT] = nft_ipv4_output,
104 [NF_INET_FORWARD] = nft_do_chain_ipv4,
105 [NF_INET_PRE_ROUTING] = nft_do_chain_ipv4,
106 [NF_INET_POST_ROUTING] = nft_do_chain_ipv4,
107 },
108}; 101};
109 102
110static int __init nf_tables_ipv4_init(void) 103static int __init nf_tables_ipv4_init(void)
diff --git a/net/ipv6/netfilter/nf_tables_ipv6.c b/net/ipv6/netfilter/nf_tables_ipv6.c
index d77db8a13505..54a2bcdc8a17 100644
--- a/net/ipv6/netfilter/nf_tables_ipv6.c
+++ b/net/ipv6/netfilter/nf_tables_ipv6.c
@@ -16,24 +16,35 @@
16#include <net/netfilter/nf_tables.h> 16#include <net/netfilter/nf_tables.h>
17#include <net/netfilter/nf_tables_ipv6.h> 17#include <net/netfilter/nf_tables_ipv6.h>
18 18
19static unsigned int nft_do_chain_ipv6(const struct nf_hook_ops *ops,
20 struct sk_buff *skb,
21 const struct net_device *in,
22 const struct net_device *out,
23 int (*okfn)(struct sk_buff *))
24{
25 struct nft_pktinfo pkt;
26
27 /* malformed packet, drop it */
28 if (nft_set_pktinfo_ipv6(&pkt, ops, skb, in, out) < 0)
29 return NF_DROP;
30
31 return nft_do_chain_pktinfo(&pkt, ops);
32}
33
19static unsigned int nft_ipv6_output(const struct nf_hook_ops *ops, 34static unsigned int nft_ipv6_output(const struct nf_hook_ops *ops,
20 struct sk_buff *skb, 35 struct sk_buff *skb,
21 const struct net_device *in, 36 const struct net_device *in,
22 const struct net_device *out, 37 const struct net_device *out,
23 int (*okfn)(struct sk_buff *)) 38 int (*okfn)(struct sk_buff *))
24{ 39{
25 struct nft_pktinfo pkt;
26
27 if (unlikely(skb->len < sizeof(struct ipv6hdr))) { 40 if (unlikely(skb->len < sizeof(struct ipv6hdr))) {
28 if (net_ratelimit()) 41 if (net_ratelimit())
29 pr_info("nf_tables_ipv6: ignoring short SOCK_RAW " 42 pr_info("nf_tables_ipv6: ignoring short SOCK_RAW "
30 "packet\n"); 43 "packet\n");
31 return NF_ACCEPT; 44 return NF_ACCEPT;
32 } 45 }
33 if (nft_set_pktinfo_ipv6(&pkt, ops, skb, in, out) < 0)
34 return NF_DROP;
35 46
36 return nft_do_chain_pktinfo(&pkt, ops); 47 return nft_do_chain_ipv6(ops, skb, in, out, okfn);
37} 48}
38 49
39static struct nft_af_info nft_af_ipv6 __read_mostly = { 50static struct nft_af_info nft_af_ipv6 __read_mostly = {
@@ -41,7 +52,11 @@ static struct nft_af_info nft_af_ipv6 __read_mostly = {
41 .nhooks = NF_INET_NUMHOOKS, 52 .nhooks = NF_INET_NUMHOOKS,
42 .owner = THIS_MODULE, 53 .owner = THIS_MODULE,
43 .hooks = { 54 .hooks = {
55 [NF_INET_LOCAL_IN] = nft_do_chain_ipv6,
44 [NF_INET_LOCAL_OUT] = nft_ipv6_output, 56 [NF_INET_LOCAL_OUT] = nft_ipv6_output,
57 [NF_INET_FORWARD] = nft_do_chain_ipv6,
58 [NF_INET_PRE_ROUTING] = nft_do_chain_ipv6,
59 [NF_INET_POST_ROUTING] = nft_do_chain_ipv6,
45 }, 60 },
46}; 61};
47 62
@@ -73,22 +88,6 @@ static struct pernet_operations nf_tables_ipv6_net_ops = {
73 .exit = nf_tables_ipv6_exit_net, 88 .exit = nf_tables_ipv6_exit_net,
74}; 89};
75 90
76static unsigned int
77nft_do_chain_ipv6(const struct nf_hook_ops *ops,
78 struct sk_buff *skb,
79 const struct net_device *in,
80 const struct net_device *out,
81 int (*okfn)(struct sk_buff *))
82{
83 struct nft_pktinfo pkt;
84
85 /* malformed packet, drop it */
86 if (nft_set_pktinfo_ipv6(&pkt, ops, skb, in, out) < 0)
87 return NF_DROP;
88
89 return nft_do_chain_pktinfo(&pkt, ops);
90}
91
92static struct nf_chain_type filter_ipv6 = { 91static struct nf_chain_type filter_ipv6 = {
93 .family = NFPROTO_IPV6, 92 .family = NFPROTO_IPV6,
94 .name = "filter", 93 .name = "filter",
@@ -98,13 +97,6 @@ static struct nf_chain_type filter_ipv6 = {
98 (1 << NF_INET_FORWARD) | 97 (1 << NF_INET_FORWARD) |
99 (1 << NF_INET_PRE_ROUTING) | 98 (1 << NF_INET_PRE_ROUTING) |
100 (1 << NF_INET_POST_ROUTING), 99 (1 << NF_INET_POST_ROUTING),
101 .fn = {
102 [NF_INET_LOCAL_IN] = nft_do_chain_ipv6,
103 [NF_INET_LOCAL_OUT] = nft_ipv6_output,
104 [NF_INET_FORWARD] = nft_do_chain_ipv6,
105 [NF_INET_PRE_ROUTING] = nft_do_chain_ipv6,
106 [NF_INET_POST_ROUTING] = nft_do_chain_ipv6,
107 },
108}; 100};
109 101
110static int __init nf_tables_ipv6_init(void) 102static int __init nf_tables_ipv6_init(void)
diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c
index 1fcef1ec1dc1..d568626bc0f9 100644
--- a/net/netfilter/nf_tables_api.c
+++ b/net/netfilter/nf_tables_api.c
@@ -927,9 +927,9 @@ static int nf_tables_newchain(struct sock *nlsk, struct sk_buff *skb,
927 if (hooknum >= afi->nhooks) 927 if (hooknum >= afi->nhooks)
928 return -EINVAL; 928 return -EINVAL;
929 929
930 hookfn = chain_type[family][type]->fn[hooknum]; 930 if (!(chain_type[family][type]->hook_mask & (1 << hooknum)))
931 if (hookfn == NULL)
932 return -EOPNOTSUPP; 931 return -EOPNOTSUPP;
932 hookfn = chain_type[family][type]->fn[hooknum];
933 933
934 basechain = kzalloc(sizeof(*basechain), GFP_KERNEL); 934 basechain = kzalloc(sizeof(*basechain), GFP_KERNEL);
935 if (basechain == NULL) 935 if (basechain == NULL)
@@ -944,9 +944,9 @@ static int nf_tables_newchain(struct sock *nlsk, struct sk_buff *skb,
944 ops->hooknum = ntohl(nla_get_be32(ha[NFTA_HOOK_HOOKNUM])); 944 ops->hooknum = ntohl(nla_get_be32(ha[NFTA_HOOK_HOOKNUM]));
945 ops->priority = ntohl(nla_get_be32(ha[NFTA_HOOK_PRIORITY])); 945 ops->priority = ntohl(nla_get_be32(ha[NFTA_HOOK_PRIORITY]));
946 ops->priv = chain; 946 ops->priv = chain;
947 ops->hook = hookfn; 947 ops->hook = afi->hooks[ops->hooknum];
948 if (afi->hooks[ops->hooknum]) 948 if (hookfn)
949 ops->hook = afi->hooks[ops->hooknum]; 949 ops->hook = hookfn;
950 950
951 chain->flags |= NFT_BASE_CHAIN; 951 chain->flags |= NFT_BASE_CHAIN;
952 952