19a0aacb45be55b1b24b125abb09fc2db8a87439
[oweals/openwrt.git] /
1 From: Pablo Neira Ayuso <pablo@netfilter.org>
2 Date: Wed, 20 Dec 2017 16:04:18 +0100
3 Subject: [PATCH] netfilter: move checksum_partial indirection to struct
4  nf_ipv6_ops
5
6 We cannot make a direct call to nf_ip6_checksum_partial() because that
7 would result in autoloading the 'ipv6' module because of symbol
8 dependencies.  Therefore, define checksum_partial indirection in
9 nf_ipv6_ops where this really belongs to.
10
11 For IPv4, we can indeed make a direct function call, which is faster,
12 given IPv4 is built-in in the networking code by default. Still,
13 CONFIG_INET=n and CONFIG_NETFILTER=y is possible, so define empty inline
14 stub for IPv4 in such case.
15
16 Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
17 ---
18
19 --- a/include/linux/netfilter.h
20 +++ b/include/linux/netfilter.h
21 @@ -311,11 +311,6 @@ struct nf_queue_entry;
22  
23  struct nf_afinfo {
24         unsigned short  family;
25 -       __sum16         (*checksum_partial)(struct sk_buff *skb,
26 -                                           unsigned int hook,
27 -                                           unsigned int dataoff,
28 -                                           unsigned int len,
29 -                                           u_int8_t protocol);
30         int             (*route)(struct net *net, struct dst_entry **dst,
31                                  struct flowi *fl, bool strict);
32         void            (*saveroute)(const struct sk_buff *skb,
33 @@ -335,22 +330,9 @@ __sum16 nf_checksum(struct sk_buff *skb,
34                     unsigned int dataoff, u_int8_t protocol,
35                     unsigned short family);
36  
37 -static inline __sum16
38 -nf_checksum_partial(struct sk_buff *skb, unsigned int hook,
39 -                   unsigned int dataoff, unsigned int len,
40 -                   u_int8_t protocol, unsigned short family)
41 -{
42 -       const struct nf_afinfo *afinfo;
43 -       __sum16 csum = 0;
44 -
45 -       rcu_read_lock();
46 -       afinfo = nf_get_afinfo(family);
47 -       if (afinfo)
48 -               csum = afinfo->checksum_partial(skb, hook, dataoff, len,
49 -                                               protocol);
50 -       rcu_read_unlock();
51 -       return csum;
52 -}
53 +__sum16 nf_checksum_partial(struct sk_buff *skb, unsigned int hook,
54 +                           unsigned int dataoff, unsigned int len,
55 +                           u_int8_t protocol, unsigned short family);
56  
57  int nf_register_afinfo(const struct nf_afinfo *afinfo);
58  void nf_unregister_afinfo(const struct nf_afinfo *afinfo);
59 --- a/include/linux/netfilter_ipv4.h
60 +++ b/include/linux/netfilter_ipv4.h
61 @@ -11,12 +11,23 @@ int ip_route_me_harder(struct net *net,
62  #ifdef CONFIG_INET
63  __sum16 nf_ip_checksum(struct sk_buff *skb, unsigned int hook,
64                        unsigned int dataoff, u_int8_t protocol);
65 +__sum16 nf_ip_checksum_partial(struct sk_buff *skb, unsigned int hook,
66 +                              unsigned int dataoff, unsigned int len,
67 +                              u_int8_t protocol);
68  #else
69  static inline __sum16 nf_ip_checksum(struct sk_buff *skb, unsigned int hook,
70                                      unsigned int dataoff, u_int8_t protocol)
71  {
72         return 0;
73  }
74 +static inline __sum16 nf_ip_checksum_partial(struct sk_buff *skb,
75 +                                            unsigned int hook,
76 +                                            unsigned int dataoff,
77 +                                            unsigned int len,
78 +                                            u_int8_t protocol)
79 +{
80 +       return 0;
81 +}
82  #endif /* CONFIG_INET */
83  
84  #endif /*__LINUX_IP_NETFILTER_H*/
85 --- a/include/linux/netfilter_ipv6.h
86 +++ b/include/linux/netfilter_ipv6.h
87 @@ -21,6 +21,9 @@ struct nf_ipv6_ops {
88                         int (*output)(struct net *, struct sock *, struct sk_buff *));
89         __sum16 (*checksum)(struct sk_buff *skb, unsigned int hook,
90                             unsigned int dataoff, u_int8_t protocol);
91 +       __sum16 (*checksum_partial)(struct sk_buff *skb, unsigned int hook,
92 +                                   unsigned int dataoff, unsigned int len,
93 +                                   u_int8_t protocol);
94  };
95  
96  #ifdef CONFIG_NETFILTER
97 --- a/net/bridge/netfilter/nf_tables_bridge.c
98 +++ b/net/bridge/netfilter/nf_tables_bridge.c
99 @@ -106,13 +106,6 @@ static int nf_br_reroute(struct net *net
100         return 0;
101  }
102  
103 -static __sum16 nf_br_checksum_partial(struct sk_buff *skb, unsigned int hook,
104 -                                     unsigned int dataoff, unsigned int len,
105 -                                     u_int8_t protocol)
106 -{
107 -       return 0;
108 -}
109 -
110  static int nf_br_route(struct net *net, struct dst_entry **dst,
111                        struct flowi *fl, bool strict __always_unused)
112  {
113 @@ -121,7 +114,6 @@ static int nf_br_route(struct net *net,
114  
115  static const struct nf_afinfo nf_br_afinfo = {
116         .family                 = AF_BRIDGE,
117 -       .checksum_partial       = nf_br_checksum_partial,
118         .route                  = nf_br_route,
119         .saveroute              = nf_br_saveroute,
120         .reroute                = nf_br_reroute,
121 --- a/net/ipv4/netfilter.c
122 +++ b/net/ipv4/netfilter.c
123 @@ -155,9 +155,9 @@ __sum16 nf_ip_checksum(struct sk_buff *s
124  }
125  EXPORT_SYMBOL(nf_ip_checksum);
126  
127 -static __sum16 nf_ip_checksum_partial(struct sk_buff *skb, unsigned int hook,
128 -                                     unsigned int dataoff, unsigned int len,
129 -                                     u_int8_t protocol)
130 +__sum16 nf_ip_checksum_partial(struct sk_buff *skb, unsigned int hook,
131 +                              unsigned int dataoff, unsigned int len,
132 +                              u_int8_t protocol)
133  {
134         const struct iphdr *iph = ip_hdr(skb);
135         __sum16 csum = 0;
136 @@ -175,6 +175,7 @@ static __sum16 nf_ip_checksum_partial(st
137         }
138         return csum;
139  }
140 +EXPORT_SYMBOL_GPL(nf_ip_checksum_partial);
141  
142  static int nf_ip_route(struct net *net, struct dst_entry **dst,
143                        struct flowi *fl, bool strict __always_unused)
144 @@ -188,7 +189,6 @@ static int nf_ip_route(struct net *net,
145  
146  static const struct nf_afinfo nf_ip_afinfo = {
147         .family                 = AF_INET,
148 -       .checksum_partial       = nf_ip_checksum_partial,
149         .route                  = nf_ip_route,
150         .saveroute              = nf_ip_saveroute,
151         .reroute                = nf_ip_reroute,
152 --- a/net/ipv6/netfilter.c
153 +++ b/net/ipv6/netfilter.c
154 @@ -191,15 +191,15 @@ static __sum16 nf_ip6_checksum_partial(s
155  };
156  
157  static const struct nf_ipv6_ops ipv6ops = {
158 -       .chk_addr       = ipv6_chk_addr,
159 -       .route_input    = ip6_route_input,
160 -       .fragment       = ip6_fragment,
161 -       .checksum       = nf_ip6_checksum,
162 +       .chk_addr               = ipv6_chk_addr,
163 +       .route_input            = ip6_route_input,
164 +       .fragment               = ip6_fragment,
165 +       .checksum               = nf_ip6_checksum,
166 +       .checksum_partial       = nf_ip6_checksum_partial,
167  };
168  
169  static const struct nf_afinfo nf_ip6_afinfo = {
170         .family                 = AF_INET6,
171 -       .checksum_partial       = nf_ip6_checksum_partial,
172         .route                  = nf_ip6_route,
173         .saveroute              = nf_ip6_saveroute,
174         .reroute                = nf_ip6_reroute,
175 --- a/net/netfilter/utils.c
176 +++ b/net/netfilter/utils.c
177 @@ -24,3 +24,27 @@ __sum16 nf_checksum(struct sk_buff *skb,
178         return csum;
179  }
180  EXPORT_SYMBOL_GPL(nf_checksum);
181 +
182 +__sum16 nf_checksum_partial(struct sk_buff *skb, unsigned int hook,
183 +                           unsigned int dataoff, unsigned int len,
184 +                           u_int8_t protocol, unsigned short family)
185 +{
186 +       const struct nf_ipv6_ops *v6ops;
187 +       __sum16 csum = 0;
188 +
189 +       switch (family) {
190 +       case AF_INET:
191 +               csum = nf_ip_checksum_partial(skb, hook, dataoff, len,
192 +                                             protocol);
193 +               break;
194 +       case AF_INET6:
195 +               v6ops = rcu_dereference(nf_ipv6_ops);
196 +               if (v6ops)
197 +                       csum = v6ops->checksum_partial(skb, hook, dataoff, len,
198 +                                                      protocol);
199 +               break;
200 +       }
201 +
202 +       return csum;
203 +}
204 +EXPORT_SYMBOL_GPL(nf_checksum_partial);