308-v4.16-netfilter-move-reroute-indirection-to-struct-nf_ipv6.patch 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. From: Pablo Neira Ayuso <pablo@netfilter.org>
  2. Date: Mon, 27 Nov 2017 22:50:26 +0100
  3. Subject: [PATCH] netfilter: move reroute indirection to struct nf_ipv6_ops
  4. We cannot make a direct call to nf_ip6_reroute() because that would result
  5. in autoloading the 'ipv6' module because of symbol dependencies.
  6. Therefore, define reroute indirection in nf_ipv6_ops where this really
  7. belongs to.
  8. For IPv4, we can indeed make a direct function call, which is faster,
  9. given IPv4 is built-in in the networking code by default. Still,
  10. CONFIG_INET=n and CONFIG_NETFILTER=y is possible, so define empty inline
  11. stub for IPv4 in such case.
  12. Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
  13. ---
  14. --- a/include/linux/netfilter.h
  15. +++ b/include/linux/netfilter.h
  16. @@ -311,8 +311,6 @@ struct nf_queue_entry;
  17. struct nf_afinfo {
  18. unsigned short family;
  19. - int (*reroute)(struct net *net, struct sk_buff *skb,
  20. - const struct nf_queue_entry *entry);
  21. int route_key_size;
  22. };
  23. @@ -331,6 +329,7 @@ __sum16 nf_checksum_partial(struct sk_bu
  24. u_int8_t protocol, unsigned short family);
  25. int nf_route(struct net *net, struct dst_entry **dst, struct flowi *fl,
  26. bool strict, unsigned short family);
  27. +int nf_reroute(struct sk_buff *skb, struct nf_queue_entry *entry);
  28. int nf_register_afinfo(const struct nf_afinfo *afinfo);
  29. void nf_unregister_afinfo(const struct nf_afinfo *afinfo);
  30. --- a/include/linux/netfilter_ipv4.h
  31. +++ b/include/linux/netfilter_ipv4.h
  32. @@ -18,6 +18,8 @@ struct ip_rt_info {
  33. int ip_route_me_harder(struct net *net, struct sk_buff *skb, unsigned addr_type);
  34. +struct nf_queue_entry;
  35. +
  36. #ifdef CONFIG_INET
  37. __sum16 nf_ip_checksum(struct sk_buff *skb, unsigned int hook,
  38. unsigned int dataoff, u_int8_t protocol);
  39. @@ -26,6 +28,7 @@ __sum16 nf_ip_checksum_partial(struct sk
  40. u_int8_t protocol);
  41. int nf_ip_route(struct net *net, struct dst_entry **dst, struct flowi *fl,
  42. bool strict);
  43. +int nf_ip_reroute(struct sk_buff *skb, const struct nf_queue_entry *entry);
  44. #else
  45. static inline __sum16 nf_ip_checksum(struct sk_buff *skb, unsigned int hook,
  46. unsigned int dataoff, u_int8_t protocol)
  47. @@ -45,6 +48,11 @@ static inline int nf_ip_route(struct net
  48. {
  49. return -EOPNOTSUPP;
  50. }
  51. +static inline int nf_ip_reroute(struct sk_buff *skb,
  52. + const struct nf_queue_entry *entry)
  53. +{
  54. + return -EOPNOTSUPP;
  55. +}
  56. #endif /* CONFIG_INET */
  57. #endif /*__LINUX_IP_NETFILTER_H*/
  58. --- a/include/linux/netfilter_ipv6.h
  59. +++ b/include/linux/netfilter_ipv6.h
  60. @@ -18,6 +18,8 @@ struct ip6_rt_info {
  61. u_int32_t mark;
  62. };
  63. +struct nf_queue_entry;
  64. +
  65. /*
  66. * Hook functions for ipv6 to allow xt_* modules to be built-in even
  67. * if IPv6 is a module.
  68. @@ -35,6 +37,7 @@ struct nf_ipv6_ops {
  69. u_int8_t protocol);
  70. int (*route)(struct net *net, struct dst_entry **dst, struct flowi *fl,
  71. bool strict);
  72. + int (*reroute)(struct sk_buff *skb, const struct nf_queue_entry *entry);
  73. };
  74. #ifdef CONFIG_NETFILTER
  75. --- a/net/bridge/netfilter/nf_tables_bridge.c
  76. +++ b/net/bridge/netfilter/nf_tables_bridge.c
  77. @@ -95,15 +95,8 @@ static const struct nf_chain_type filter
  78. (1 << NF_BR_POST_ROUTING),
  79. };
  80. -static int nf_br_reroute(struct net *net, struct sk_buff *skb,
  81. - const struct nf_queue_entry *entry)
  82. -{
  83. - return 0;
  84. -}
  85. -
  86. static const struct nf_afinfo nf_br_afinfo = {
  87. .family = AF_BRIDGE,
  88. - .reroute = nf_br_reroute,
  89. .route_key_size = 0,
  90. };
  91. --- a/net/ipv4/netfilter.c
  92. +++ b/net/ipv4/netfilter.c
  93. @@ -80,8 +80,7 @@ int ip_route_me_harder(struct net *net,
  94. }
  95. EXPORT_SYMBOL(ip_route_me_harder);
  96. -static int nf_ip_reroute(struct net *net, struct sk_buff *skb,
  97. - const struct nf_queue_entry *entry)
  98. +int nf_ip_reroute(struct sk_buff *skb, const struct nf_queue_entry *entry)
  99. {
  100. const struct ip_rt_info *rt_info = nf_queue_entry_reroute(entry);
  101. @@ -92,10 +91,12 @@ static int nf_ip_reroute(struct net *net
  102. skb->mark == rt_info->mark &&
  103. iph->daddr == rt_info->daddr &&
  104. iph->saddr == rt_info->saddr))
  105. - return ip_route_me_harder(net, skb, RTN_UNSPEC);
  106. + return ip_route_me_harder(entry->state.net, skb,
  107. + RTN_UNSPEC);
  108. }
  109. return 0;
  110. }
  111. +EXPORT_SYMBOL_GPL(nf_ip_reroute);
  112. __sum16 nf_ip_checksum(struct sk_buff *skb, unsigned int hook,
  113. unsigned int dataoff, u_int8_t protocol)
  114. @@ -163,7 +164,6 @@ EXPORT_SYMBOL_GPL(nf_ip_route);
  115. static const struct nf_afinfo nf_ip_afinfo = {
  116. .family = AF_INET,
  117. - .reroute = nf_ip_reroute,
  118. .route_key_size = sizeof(struct ip_rt_info),
  119. };
  120. --- a/net/ipv6/netfilter.c
  121. +++ b/net/ipv6/netfilter.c
  122. @@ -72,7 +72,7 @@ int ip6_route_me_harder(struct net *net,
  123. }
  124. EXPORT_SYMBOL(ip6_route_me_harder);
  125. -static int nf_ip6_reroute(struct net *net, struct sk_buff *skb,
  126. +static int nf_ip6_reroute(struct sk_buff *skb,
  127. const struct nf_queue_entry *entry)
  128. {
  129. struct ip6_rt_info *rt_info = nf_queue_entry_reroute(entry);
  130. @@ -82,7 +82,7 @@ static int nf_ip6_reroute(struct net *ne
  131. if (!ipv6_addr_equal(&iph->daddr, &rt_info->daddr) ||
  132. !ipv6_addr_equal(&iph->saddr, &rt_info->saddr) ||
  133. skb->mark != rt_info->mark)
  134. - return ip6_route_me_harder(net, skb);
  135. + return ip6_route_me_harder(entry->state.net, skb);
  136. }
  137. return 0;
  138. }
  139. @@ -175,11 +175,11 @@ static const struct nf_ipv6_ops ipv6ops
  140. .checksum = nf_ip6_checksum,
  141. .checksum_partial = nf_ip6_checksum_partial,
  142. .route = nf_ip6_route,
  143. + .reroute = nf_ip6_reroute,
  144. };
  145. static const struct nf_afinfo nf_ip6_afinfo = {
  146. .family = AF_INET6,
  147. - .reroute = nf_ip6_reroute,
  148. .route_key_size = sizeof(struct ip6_rt_info),
  149. };
  150. --- a/net/netfilter/nf_queue.c
  151. +++ b/net/netfilter/nf_queue.c
  152. @@ -285,7 +285,6 @@ void nf_reinject(struct nf_queue_entry *
  153. const struct nf_hook_entry *hook_entry;
  154. const struct nf_hook_entries *hooks;
  155. struct sk_buff *skb = entry->skb;
  156. - const struct nf_afinfo *afinfo;
  157. const struct net *net;
  158. unsigned int i;
  159. int err;
  160. @@ -312,8 +311,7 @@ void nf_reinject(struct nf_queue_entry *
  161. verdict = nf_hook_entry_hookfn(hook_entry, skb, &entry->state);
  162. if (verdict == NF_ACCEPT) {
  163. - afinfo = nf_get_afinfo(entry->state.pf);
  164. - if (!afinfo || afinfo->reroute(entry->state.net, skb, entry) < 0)
  165. + if (nf_reroute(skb, entry) < 0)
  166. verdict = NF_DROP;
  167. }
  168. --- a/net/netfilter/utils.c
  169. +++ b/net/netfilter/utils.c
  170. @@ -2,6 +2,7 @@
  171. #include <linux/netfilter.h>
  172. #include <linux/netfilter_ipv4.h>
  173. #include <linux/netfilter_ipv6.h>
  174. +#include <net/netfilter/nf_queue.h>
  175. __sum16 nf_checksum(struct sk_buff *skb, unsigned int hook,
  176. unsigned int dataoff, u_int8_t protocol,
  177. @@ -69,3 +70,21 @@ int nf_route(struct net *net, struct dst
  178. return ret;
  179. }
  180. EXPORT_SYMBOL_GPL(nf_route);
  181. +
  182. +int nf_reroute(struct sk_buff *skb, struct nf_queue_entry *entry)
  183. +{
  184. + const struct nf_ipv6_ops *v6ops;
  185. + int ret = 0;
  186. +
  187. + switch (entry->state.pf) {
  188. + case AF_INET:
  189. + ret = nf_ip_reroute(skb, entry);
  190. + break;
  191. + case AF_INET6:
  192. + v6ops = rcu_dereference(nf_ipv6_ops);
  193. + if (v6ops)
  194. + ret = v6ops->reroute(skb, entry);
  195. + break;
  196. + }
  197. + return ret;
  198. +}