aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPablo Neira Ayuso <pablo@netfilter.org>2017-12-20 10:04:18 -0500
committerPablo Neira Ayuso <pablo@netfilter.org>2018-01-08 12:01:24 -0500
commitf7dcbe2f36a660140ecb286e15f502028d96ffdf (patch)
tree9cb6039e86358b2ba09230d5737485786bc1cc75
parentef71fe27ec2f1607e38af160ab261a8d8ef8e121 (diff)
netfilter: move checksum_partial indirection to struct nf_ipv6_ops
We cannot make a direct call to nf_ip6_checksum_partial() because that would result in autoloading the 'ipv6' module because of symbol dependencies. Therefore, define checksum_partial indirection in nf_ipv6_ops where this really belongs to. For IPv4, we can indeed make a direct function call, which is faster, given IPv4 is built-in in the networking code by default. Still, CONFIG_INET=n and CONFIG_NETFILTER=y is possible, so define empty inline stub for IPv4 in such case. Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
-rw-r--r--include/linux/netfilter.h24
-rw-r--r--include/linux/netfilter_ipv4.h11
-rw-r--r--include/linux/netfilter_ipv6.h3
-rw-r--r--net/bridge/netfilter/nf_tables_bridge.c8
-rw-r--r--net/ipv4/netfilter.c8
-rw-r--r--net/ipv6/netfilter.c10
-rw-r--r--net/netfilter/utils.c24
7 files changed, 50 insertions, 38 deletions
diff --git a/include/linux/netfilter.h b/include/linux/netfilter.h
index 4c4d38ef1a76..70b238eff29f 100644
--- a/include/linux/netfilter.h
+++ b/include/linux/netfilter.h
@@ -311,11 +311,6 @@ struct nf_queue_entry;
311 311
312struct nf_afinfo { 312struct nf_afinfo {
313 unsigned short family; 313 unsigned short family;
314 __sum16 (*checksum_partial)(struct sk_buff *skb,
315 unsigned int hook,
316 unsigned int dataoff,
317 unsigned int len,
318 u_int8_t protocol);
319 int (*route)(struct net *net, struct dst_entry **dst, 314 int (*route)(struct net *net, struct dst_entry **dst,
320 struct flowi *fl, bool strict); 315 struct flowi *fl, bool strict);
321 void (*saveroute)(const struct sk_buff *skb, 316 void (*saveroute)(const struct sk_buff *skb,
@@ -335,22 +330,9 @@ __sum16 nf_checksum(struct sk_buff *skb, unsigned int hook,
335 unsigned int dataoff, u_int8_t protocol, 330 unsigned int dataoff, u_int8_t protocol,
336 unsigned short family); 331 unsigned short family);
337 332
338static inline __sum16 333__sum16 nf_checksum_partial(struct sk_buff *skb, unsigned int hook,
339nf_checksum_partial(struct sk_buff *skb, unsigned int hook, 334 unsigned int dataoff, unsigned int len,
340 unsigned int dataoff, unsigned int len, 335 u_int8_t protocol, unsigned short family);
341 u_int8_t protocol, unsigned short family)
342{
343 const struct nf_afinfo *afinfo;
344 __sum16 csum = 0;
345
346 rcu_read_lock();
347 afinfo = nf_get_afinfo(family);
348 if (afinfo)
349 csum = afinfo->checksum_partial(skb, hook, dataoff, len,
350 protocol);
351 rcu_read_unlock();
352 return csum;
353}
354 336
355int nf_register_afinfo(const struct nf_afinfo *afinfo); 337int nf_register_afinfo(const struct nf_afinfo *afinfo);
356void nf_unregister_afinfo(const struct nf_afinfo *afinfo); 338void nf_unregister_afinfo(const struct nf_afinfo *afinfo);
diff --git a/include/linux/netfilter_ipv4.h b/include/linux/netfilter_ipv4.h
index c7deb78bac88..811425ece8d5 100644
--- a/include/linux/netfilter_ipv4.h
+++ b/include/linux/netfilter_ipv4.h
@@ -11,12 +11,23 @@ int ip_route_me_harder(struct net *net, struct sk_buff *skb, unsigned addr_type)
11#ifdef CONFIG_INET 11#ifdef CONFIG_INET
12__sum16 nf_ip_checksum(struct sk_buff *skb, unsigned int hook, 12__sum16 nf_ip_checksum(struct sk_buff *skb, unsigned int hook,
13 unsigned int dataoff, u_int8_t protocol); 13 unsigned int dataoff, u_int8_t protocol);
14__sum16 nf_ip_checksum_partial(struct sk_buff *skb, unsigned int hook,
15 unsigned int dataoff, unsigned int len,
16 u_int8_t protocol);
14#else 17#else
15static inline __sum16 nf_ip_checksum(struct sk_buff *skb, unsigned int hook, 18static inline __sum16 nf_ip_checksum(struct sk_buff *skb, unsigned int hook,
16 unsigned int dataoff, u_int8_t protocol) 19 unsigned int dataoff, u_int8_t protocol)
17{ 20{
18 return 0; 21 return 0;
19} 22}
23static inline __sum16 nf_ip_checksum_partial(struct sk_buff *skb,
24 unsigned int hook,
25 unsigned int dataoff,
26 unsigned int len,
27 u_int8_t protocol)
28{
29 return 0;
30}
20#endif /* CONFIG_INET */ 31#endif /* CONFIG_INET */
21 32
22#endif /*__LINUX_IP_NETFILTER_H*/ 33#endif /*__LINUX_IP_NETFILTER_H*/
diff --git a/include/linux/netfilter_ipv6.h b/include/linux/netfilter_ipv6.h
index b136101b5cde..29e8f1286584 100644
--- a/include/linux/netfilter_ipv6.h
+++ b/include/linux/netfilter_ipv6.h
@@ -21,6 +21,9 @@ struct nf_ipv6_ops {
21 int (*output)(struct net *, struct sock *, struct sk_buff *)); 21 int (*output)(struct net *, struct sock *, struct sk_buff *));
22 __sum16 (*checksum)(struct sk_buff *skb, unsigned int hook, 22 __sum16 (*checksum)(struct sk_buff *skb, unsigned int hook,
23 unsigned int dataoff, u_int8_t protocol); 23 unsigned int dataoff, u_int8_t protocol);
24 __sum16 (*checksum_partial)(struct sk_buff *skb, unsigned int hook,
25 unsigned int dataoff, unsigned int len,
26 u_int8_t protocol);
24}; 27};
25 28
26#ifdef CONFIG_NETFILTER 29#ifdef CONFIG_NETFILTER
diff --git a/net/bridge/netfilter/nf_tables_bridge.c b/net/bridge/netfilter/nf_tables_bridge.c
index b850c17f02f5..b24ac11cacc9 100644
--- a/net/bridge/netfilter/nf_tables_bridge.c
+++ b/net/bridge/netfilter/nf_tables_bridge.c
@@ -106,13 +106,6 @@ static int nf_br_reroute(struct net *net, struct sk_buff *skb,
106 return 0; 106 return 0;
107} 107}
108 108
109static __sum16 nf_br_checksum_partial(struct sk_buff *skb, unsigned int hook,
110 unsigned int dataoff, unsigned int len,
111 u_int8_t protocol)
112{
113 return 0;
114}
115
116static int nf_br_route(struct net *net, struct dst_entry **dst, 109static int nf_br_route(struct net *net, struct dst_entry **dst,
117 struct flowi *fl, bool strict __always_unused) 110 struct flowi *fl, bool strict __always_unused)
118{ 111{
@@ -121,7 +114,6 @@ static int nf_br_route(struct net *net, struct dst_entry **dst,
121 114
122static const struct nf_afinfo nf_br_afinfo = { 115static const struct nf_afinfo nf_br_afinfo = {
123 .family = AF_BRIDGE, 116 .family = AF_BRIDGE,
124 .checksum_partial = nf_br_checksum_partial,
125 .route = nf_br_route, 117 .route = nf_br_route,
126 .saveroute = nf_br_saveroute, 118 .saveroute = nf_br_saveroute,
127 .reroute = nf_br_reroute, 119 .reroute = nf_br_reroute,
diff --git a/net/ipv4/netfilter.c b/net/ipv4/netfilter.c
index 2f7ffefd2732..010c75fddf7e 100644
--- a/net/ipv4/netfilter.c
+++ b/net/ipv4/netfilter.c
@@ -155,9 +155,9 @@ __sum16 nf_ip_checksum(struct sk_buff *skb, unsigned int hook,
155} 155}
156EXPORT_SYMBOL(nf_ip_checksum); 156EXPORT_SYMBOL(nf_ip_checksum);
157 157
158static __sum16 nf_ip_checksum_partial(struct sk_buff *skb, unsigned int hook, 158__sum16 nf_ip_checksum_partial(struct sk_buff *skb, unsigned int hook,
159 unsigned int dataoff, unsigned int len, 159 unsigned int dataoff, unsigned int len,
160 u_int8_t protocol) 160 u_int8_t protocol)
161{ 161{
162 const struct iphdr *iph = ip_hdr(skb); 162 const struct iphdr *iph = ip_hdr(skb);
163 __sum16 csum = 0; 163 __sum16 csum = 0;
@@ -175,6 +175,7 @@ static __sum16 nf_ip_checksum_partial(struct sk_buff *skb, unsigned int hook,
175 } 175 }
176 return csum; 176 return csum;
177} 177}
178EXPORT_SYMBOL_GPL(nf_ip_checksum_partial);
178 179
179static int nf_ip_route(struct net *net, struct dst_entry **dst, 180static int nf_ip_route(struct net *net, struct dst_entry **dst,
180 struct flowi *fl, bool strict __always_unused) 181 struct flowi *fl, bool strict __always_unused)
@@ -188,7 +189,6 @@ static int nf_ip_route(struct net *net, struct dst_entry **dst,
188 189
189static const struct nf_afinfo nf_ip_afinfo = { 190static const struct nf_afinfo nf_ip_afinfo = {
190 .family = AF_INET, 191 .family = AF_INET,
191 .checksum_partial = nf_ip_checksum_partial,
192 .route = nf_ip_route, 192 .route = nf_ip_route,
193 .saveroute = nf_ip_saveroute, 193 .saveroute = nf_ip_saveroute,
194 .reroute = nf_ip_reroute, 194 .reroute = nf_ip_reroute,
diff --git a/net/ipv6/netfilter.c b/net/ipv6/netfilter.c
index db69c8af95aa..a57546ce54a6 100644
--- a/net/ipv6/netfilter.c
+++ b/net/ipv6/netfilter.c
@@ -190,15 +190,15 @@ static __sum16 nf_ip6_checksum_partial(struct sk_buff *skb, unsigned int hook,
190}; 190};
191 191
192static const struct nf_ipv6_ops ipv6ops = { 192static const struct nf_ipv6_ops ipv6ops = {
193 .chk_addr = ipv6_chk_addr, 193 .chk_addr = ipv6_chk_addr,
194 .route_input = ip6_route_input, 194 .route_input = ip6_route_input,
195 .fragment = ip6_fragment, 195 .fragment = ip6_fragment,
196 .checksum = nf_ip6_checksum, 196 .checksum = nf_ip6_checksum,
197 .checksum_partial = nf_ip6_checksum_partial,
197}; 198};
198 199
199static const struct nf_afinfo nf_ip6_afinfo = { 200static const struct nf_afinfo nf_ip6_afinfo = {
200 .family = AF_INET6, 201 .family = AF_INET6,
201 .checksum_partial = nf_ip6_checksum_partial,
202 .route = nf_ip6_route, 202 .route = nf_ip6_route,
203 .saveroute = nf_ip6_saveroute, 203 .saveroute = nf_ip6_saveroute,
204 .reroute = nf_ip6_reroute, 204 .reroute = nf_ip6_reroute,
diff --git a/net/netfilter/utils.c b/net/netfilter/utils.c
index 159a9cdcfe1e..ca6d8d62496d 100644
--- a/net/netfilter/utils.c
+++ b/net/netfilter/utils.c
@@ -24,3 +24,27 @@ __sum16 nf_checksum(struct sk_buff *skb, unsigned int hook,
24 return csum; 24 return csum;
25} 25}
26EXPORT_SYMBOL_GPL(nf_checksum); 26EXPORT_SYMBOL_GPL(nf_checksum);
27
28__sum16 nf_checksum_partial(struct sk_buff *skb, unsigned int hook,
29 unsigned int dataoff, unsigned int len,
30 u_int8_t protocol, unsigned short family)
31{
32 const struct nf_ipv6_ops *v6ops;
33 __sum16 csum = 0;
34
35 switch (family) {
36 case AF_INET:
37 csum = nf_ip_checksum_partial(skb, hook, dataoff, len,
38 protocol);
39 break;
40 case AF_INET6:
41 v6ops = rcu_dereference(nf_ipv6_ops);
42 if (v6ops)
43 csum = v6ops->checksum_partial(skb, hook, dataoff, len,
44 protocol);
45 break;
46 }
47
48 return csum;
49}
50EXPORT_SYMBOL_GPL(nf_checksum_partial);