123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223 |
- From: Pablo Neira Ayuso <pablo@netfilter.org>
- Date: Mon, 27 Nov 2017 22:50:26 +0100
- Subject: [PATCH] netfilter: move reroute indirection to struct nf_ipv6_ops
- We cannot make a direct call to nf_ip6_reroute() because that would result
- in autoloading the 'ipv6' module because of symbol dependencies.
- Therefore, define reroute 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>
- ---
- --- a/include/linux/netfilter.h
- +++ b/include/linux/netfilter.h
- @@ -311,8 +311,6 @@ struct nf_queue_entry;
-
- struct nf_afinfo {
- unsigned short family;
- - int (*reroute)(struct net *net, struct sk_buff *skb,
- - const struct nf_queue_entry *entry);
- int route_key_size;
- };
-
- @@ -331,6 +329,7 @@ __sum16 nf_checksum_partial(struct sk_bu
- u_int8_t protocol, unsigned short family);
- int nf_route(struct net *net, struct dst_entry **dst, struct flowi *fl,
- bool strict, unsigned short family);
- +int nf_reroute(struct sk_buff *skb, struct nf_queue_entry *entry);
-
- int nf_register_afinfo(const struct nf_afinfo *afinfo);
- void nf_unregister_afinfo(const struct nf_afinfo *afinfo);
- --- a/include/linux/netfilter_ipv4.h
- +++ b/include/linux/netfilter_ipv4.h
- @@ -18,6 +18,8 @@ struct ip_rt_info {
-
- int ip_route_me_harder(struct net *net, struct sk_buff *skb, unsigned addr_type);
-
- +struct nf_queue_entry;
- +
- #ifdef CONFIG_INET
- __sum16 nf_ip_checksum(struct sk_buff *skb, unsigned int hook,
- unsigned int dataoff, u_int8_t protocol);
- @@ -26,6 +28,7 @@ __sum16 nf_ip_checksum_partial(struct sk
- u_int8_t protocol);
- int nf_ip_route(struct net *net, struct dst_entry **dst, struct flowi *fl,
- bool strict);
- +int nf_ip_reroute(struct sk_buff *skb, const struct nf_queue_entry *entry);
- #else
- static inline __sum16 nf_ip_checksum(struct sk_buff *skb, unsigned int hook,
- unsigned int dataoff, u_int8_t protocol)
- @@ -45,6 +48,11 @@ static inline int nf_ip_route(struct net
- {
- return -EOPNOTSUPP;
- }
- +static inline int nf_ip_reroute(struct sk_buff *skb,
- + const struct nf_queue_entry *entry)
- +{
- + return -EOPNOTSUPP;
- +}
- #endif /* CONFIG_INET */
-
- #endif /*__LINUX_IP_NETFILTER_H*/
- --- a/include/linux/netfilter_ipv6.h
- +++ b/include/linux/netfilter_ipv6.h
- @@ -18,6 +18,8 @@ struct ip6_rt_info {
- u_int32_t mark;
- };
-
- +struct nf_queue_entry;
- +
- /*
- * Hook functions for ipv6 to allow xt_* modules to be built-in even
- * if IPv6 is a module.
- @@ -35,6 +37,7 @@ struct nf_ipv6_ops {
- u_int8_t protocol);
- int (*route)(struct net *net, struct dst_entry **dst, struct flowi *fl,
- bool strict);
- + int (*reroute)(struct sk_buff *skb, const struct nf_queue_entry *entry);
- };
-
- #ifdef CONFIG_NETFILTER
- --- a/net/bridge/netfilter/nf_tables_bridge.c
- +++ b/net/bridge/netfilter/nf_tables_bridge.c
- @@ -95,15 +95,8 @@ static const struct nf_chain_type filter
- (1 << NF_BR_POST_ROUTING),
- };
-
- -static int nf_br_reroute(struct net *net, struct sk_buff *skb,
- - const struct nf_queue_entry *entry)
- -{
- - return 0;
- -}
- -
- static const struct nf_afinfo nf_br_afinfo = {
- .family = AF_BRIDGE,
- - .reroute = nf_br_reroute,
- .route_key_size = 0,
- };
-
- --- a/net/ipv4/netfilter.c
- +++ b/net/ipv4/netfilter.c
- @@ -80,8 +80,7 @@ int ip_route_me_harder(struct net *net,
- }
- EXPORT_SYMBOL(ip_route_me_harder);
-
- -static int nf_ip_reroute(struct net *net, struct sk_buff *skb,
- - const struct nf_queue_entry *entry)
- +int nf_ip_reroute(struct sk_buff *skb, const struct nf_queue_entry *entry)
- {
- const struct ip_rt_info *rt_info = nf_queue_entry_reroute(entry);
-
- @@ -92,10 +91,12 @@ static int nf_ip_reroute(struct net *net
- skb->mark == rt_info->mark &&
- iph->daddr == rt_info->daddr &&
- iph->saddr == rt_info->saddr))
- - return ip_route_me_harder(net, skb, RTN_UNSPEC);
- + return ip_route_me_harder(entry->state.net, skb,
- + RTN_UNSPEC);
- }
- return 0;
- }
- +EXPORT_SYMBOL_GPL(nf_ip_reroute);
-
- __sum16 nf_ip_checksum(struct sk_buff *skb, unsigned int hook,
- unsigned int dataoff, u_int8_t protocol)
- @@ -163,7 +164,6 @@ EXPORT_SYMBOL_GPL(nf_ip_route);
-
- static const struct nf_afinfo nf_ip_afinfo = {
- .family = AF_INET,
- - .reroute = nf_ip_reroute,
- .route_key_size = sizeof(struct ip_rt_info),
- };
-
- --- a/net/ipv6/netfilter.c
- +++ b/net/ipv6/netfilter.c
- @@ -72,7 +72,7 @@ int ip6_route_me_harder(struct net *net,
- }
- EXPORT_SYMBOL(ip6_route_me_harder);
-
- -static int nf_ip6_reroute(struct net *net, struct sk_buff *skb,
- +static int nf_ip6_reroute(struct sk_buff *skb,
- const struct nf_queue_entry *entry)
- {
- struct ip6_rt_info *rt_info = nf_queue_entry_reroute(entry);
- @@ -82,7 +82,7 @@ static int nf_ip6_reroute(struct net *ne
- if (!ipv6_addr_equal(&iph->daddr, &rt_info->daddr) ||
- !ipv6_addr_equal(&iph->saddr, &rt_info->saddr) ||
- skb->mark != rt_info->mark)
- - return ip6_route_me_harder(net, skb);
- + return ip6_route_me_harder(entry->state.net, skb);
- }
- return 0;
- }
- @@ -175,11 +175,11 @@ static const struct nf_ipv6_ops ipv6ops
- .checksum = nf_ip6_checksum,
- .checksum_partial = nf_ip6_checksum_partial,
- .route = nf_ip6_route,
- + .reroute = nf_ip6_reroute,
- };
-
- static const struct nf_afinfo nf_ip6_afinfo = {
- .family = AF_INET6,
- - .reroute = nf_ip6_reroute,
- .route_key_size = sizeof(struct ip6_rt_info),
- };
-
- --- a/net/netfilter/nf_queue.c
- +++ b/net/netfilter/nf_queue.c
- @@ -285,7 +285,6 @@ void nf_reinject(struct nf_queue_entry *
- const struct nf_hook_entry *hook_entry;
- const struct nf_hook_entries *hooks;
- struct sk_buff *skb = entry->skb;
- - const struct nf_afinfo *afinfo;
- const struct net *net;
- unsigned int i;
- int err;
- @@ -312,8 +311,7 @@ void nf_reinject(struct nf_queue_entry *
- verdict = nf_hook_entry_hookfn(hook_entry, skb, &entry->state);
-
- if (verdict == NF_ACCEPT) {
- - afinfo = nf_get_afinfo(entry->state.pf);
- - if (!afinfo || afinfo->reroute(entry->state.net, skb, entry) < 0)
- + if (nf_reroute(skb, entry) < 0)
- verdict = NF_DROP;
- }
-
- --- a/net/netfilter/utils.c
- +++ b/net/netfilter/utils.c
- @@ -2,6 +2,7 @@
- #include <linux/netfilter.h>
- #include <linux/netfilter_ipv4.h>
- #include <linux/netfilter_ipv6.h>
- +#include <net/netfilter/nf_queue.h>
-
- __sum16 nf_checksum(struct sk_buff *skb, unsigned int hook,
- unsigned int dataoff, u_int8_t protocol,
- @@ -69,3 +70,21 @@ int nf_route(struct net *net, struct dst
- return ret;
- }
- EXPORT_SYMBOL_GPL(nf_route);
- +
- +int nf_reroute(struct sk_buff *skb, struct nf_queue_entry *entry)
- +{
- + const struct nf_ipv6_ops *v6ops;
- + int ret = 0;
- +
- + switch (entry->state.pf) {
- + case AF_INET:
- + ret = nf_ip_reroute(skb, entry);
- + break;
- + case AF_INET6:
- + v6ops = rcu_dereference(nf_ipv6_ops);
- + if (v6ops)
- + ret = v6ops->reroute(skb, entry);
- + break;
- + }
- + return ret;
- +}
|