kernel: mark source kernel for netfilter backports
[openwrt/staging/lynxis.git] / target / linux / generic / backport-4.14 / 305-v4.16-netfilter-move-checksum_partial-indirection-to-struc.patch
diff --git a/target/linux/generic/backport-4.14/305-v4.16-netfilter-move-checksum_partial-indirection-to-struc.patch b/target/linux/generic/backport-4.14/305-v4.16-netfilter-move-checksum_partial-indirection-to-struc.patch
new file mode 100644 (file)
index 0000000..7c22312
--- /dev/null
@@ -0,0 +1,204 @@
+From: Pablo Neira Ayuso <pablo@netfilter.org>
+Date: Wed, 20 Dec 2017 16:04:18 +0100
+Subject: [PATCH] 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>
+---
+
+--- a/include/linux/netfilter.h
++++ b/include/linux/netfilter.h
+@@ -274,11 +274,6 @@ struct nf_queue_entry;
+ struct nf_afinfo {
+       unsigned short  family;
+-      __sum16         (*checksum_partial)(struct sk_buff *skb,
+-                                          unsigned int hook,
+-                                          unsigned int dataoff,
+-                                          unsigned int len,
+-                                          u_int8_t protocol);
+       int             (*route)(struct net *net, struct dst_entry **dst,
+                                struct flowi *fl, bool strict);
+       void            (*saveroute)(const struct sk_buff *skb,
+@@ -298,22 +293,9 @@ __sum16 nf_checksum(struct sk_buff *skb,
+                   unsigned int dataoff, u_int8_t protocol,
+                   unsigned short family);
+-static inline __sum16
+-nf_checksum_partial(struct sk_buff *skb, unsigned int hook,
+-                  unsigned int dataoff, unsigned int len,
+-                  u_int8_t protocol, unsigned short family)
+-{
+-      const struct nf_afinfo *afinfo;
+-      __sum16 csum = 0;
+-
+-      rcu_read_lock();
+-      afinfo = nf_get_afinfo(family);
+-      if (afinfo)
+-              csum = afinfo->checksum_partial(skb, hook, dataoff, len,
+-                                              protocol);
+-      rcu_read_unlock();
+-      return csum;
+-}
++__sum16 nf_checksum_partial(struct sk_buff *skb, unsigned int hook,
++                          unsigned int dataoff, unsigned int len,
++                          u_int8_t protocol, unsigned short family);
+ 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
+@@ -11,12 +11,23 @@ int ip_route_me_harder(struct net *net,
+ #ifdef CONFIG_INET
+ __sum16 nf_ip_checksum(struct sk_buff *skb, unsigned int hook,
+                      unsigned int dataoff, u_int8_t protocol);
++__sum16 nf_ip_checksum_partial(struct sk_buff *skb, unsigned int hook,
++                             unsigned int dataoff, unsigned int len,
++                             u_int8_t protocol);
+ #else
+ static inline __sum16 nf_ip_checksum(struct sk_buff *skb, unsigned int hook,
+                                    unsigned int dataoff, u_int8_t protocol)
+ {
+       return 0;
+ }
++static inline __sum16 nf_ip_checksum_partial(struct sk_buff *skb,
++                                           unsigned int hook,
++                                           unsigned int dataoff,
++                                           unsigned int len,
++                                           u_int8_t protocol)
++{
++      return 0;
++}
+ #endif /* CONFIG_INET */
+ #endif /*__LINUX_IP_NETFILTER_H*/
+--- a/include/linux/netfilter_ipv6.h
++++ b/include/linux/netfilter_ipv6.h
+@@ -21,6 +21,9 @@ struct nf_ipv6_ops {
+                       int (*output)(struct net *, struct sock *, struct sk_buff *));
+       __sum16 (*checksum)(struct sk_buff *skb, unsigned int hook,
+                           unsigned int dataoff, u_int8_t protocol);
++      __sum16 (*checksum_partial)(struct sk_buff *skb, unsigned int hook,
++                                  unsigned int dataoff, unsigned int len,
++                                  u_int8_t protocol);
+ };
+ #ifdef CONFIG_NETFILTER
+--- 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
+       return 0;
+ }
+-static __sum16 nf_br_checksum_partial(struct sk_buff *skb, unsigned int hook,
+-                                    unsigned int dataoff, unsigned int len,
+-                                    u_int8_t protocol)
+-{
+-      return 0;
+-}
+-
+ static int nf_br_route(struct net *net, struct dst_entry **dst,
+                      struct flowi *fl, bool strict __always_unused)
+ {
+@@ -121,7 +114,6 @@ static int nf_br_route(struct net *net,
+ static const struct nf_afinfo nf_br_afinfo = {
+       .family                 = AF_BRIDGE,
+-      .checksum_partial       = nf_br_checksum_partial,
+       .route                  = nf_br_route,
+       .saveroute              = nf_br_saveroute,
+       .reroute                = nf_br_reroute,
+--- a/net/ipv4/netfilter.c
++++ b/net/ipv4/netfilter.c
+@@ -155,9 +155,9 @@ __sum16 nf_ip_checksum(struct sk_buff *s
+ }
+ EXPORT_SYMBOL(nf_ip_checksum);
+-static __sum16 nf_ip_checksum_partial(struct sk_buff *skb, unsigned int hook,
+-                                    unsigned int dataoff, unsigned int len,
+-                                    u_int8_t protocol)
++__sum16 nf_ip_checksum_partial(struct sk_buff *skb, unsigned int hook,
++                             unsigned int dataoff, unsigned int len,
++                             u_int8_t protocol)
+ {
+       const struct iphdr *iph = ip_hdr(skb);
+       __sum16 csum = 0;
+@@ -175,6 +175,7 @@ static __sum16 nf_ip_checksum_partial(st
+       }
+       return csum;
+ }
++EXPORT_SYMBOL_GPL(nf_ip_checksum_partial);
+ static int nf_ip_route(struct net *net, struct dst_entry **dst,
+                      struct flowi *fl, bool strict __always_unused)
+@@ -188,7 +189,6 @@ static int nf_ip_route(struct net *net,
+ static const struct nf_afinfo nf_ip_afinfo = {
+       .family                 = AF_INET,
+-      .checksum_partial       = nf_ip_checksum_partial,
+       .route                  = nf_ip_route,
+       .saveroute              = nf_ip_saveroute,
+       .reroute                = nf_ip_reroute,
+--- a/net/ipv6/netfilter.c
++++ b/net/ipv6/netfilter.c
+@@ -191,15 +191,15 @@ static __sum16 nf_ip6_checksum_partial(s
+ };
+ static const struct nf_ipv6_ops ipv6ops = {
+-      .chk_addr       = ipv6_chk_addr,
+-      .route_input    = ip6_route_input,
+-      .fragment       = ip6_fragment,
+-      .checksum       = nf_ip6_checksum,
++      .chk_addr               = ipv6_chk_addr,
++      .route_input            = ip6_route_input,
++      .fragment               = ip6_fragment,
++      .checksum               = nf_ip6_checksum,
++      .checksum_partial       = nf_ip6_checksum_partial,
+ };
+ static const struct nf_afinfo nf_ip6_afinfo = {
+       .family                 = AF_INET6,
+-      .checksum_partial       = nf_ip6_checksum_partial,
+       .route                  = nf_ip6_route,
+       .saveroute              = nf_ip6_saveroute,
+       .reroute                = nf_ip6_reroute,
+--- a/net/netfilter/utils.c
++++ b/net/netfilter/utils.c
+@@ -24,3 +24,27 @@ __sum16 nf_checksum(struct sk_buff *skb,
+       return csum;
+ }
+ EXPORT_SYMBOL_GPL(nf_checksum);
++
++__sum16 nf_checksum_partial(struct sk_buff *skb, unsigned int hook,
++                          unsigned int dataoff, unsigned int len,
++                          u_int8_t protocol, unsigned short family)
++{
++      const struct nf_ipv6_ops *v6ops;
++      __sum16 csum = 0;
++
++      switch (family) {
++      case AF_INET:
++              csum = nf_ip_checksum_partial(skb, hook, dataoff, len,
++                                            protocol);
++              break;
++      case AF_INET6:
++              v6ops = rcu_dereference(nf_ipv6_ops);
++              if (v6ops)
++                      csum = v6ops->checksum_partial(skb, hook, dataoff, len,
++                                                     protocol);
++              break;
++      }
++
++      return csum;
++}
++EXPORT_SYMBOL_GPL(nf_checksum_partial);