1 From: Pablo Neira Ayuso <pablo@netfilter.org>
2 Date: Tue, 23 Mar 2021 00:56:25 +0100
3 Subject: [PATCH] netfilter: flowtable: fast NAT functions never fail
5 Simplify existing fast NAT routines by returning void. After the
6 skb_try_make_writable() call consolidation, these routines cannot ever
9 Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
12 --- a/include/net/netfilter/nf_flow_table.h
13 +++ b/include/net/netfilter/nf_flow_table.h
14 @@ -229,12 +229,12 @@ void nf_flow_table_free(struct nf_flowta
16 void flow_offload_teardown(struct flow_offload *flow);
18 -int nf_flow_snat_port(const struct flow_offload *flow,
19 - struct sk_buff *skb, unsigned int thoff,
20 - u8 protocol, enum flow_offload_tuple_dir dir);
21 -int nf_flow_dnat_port(const struct flow_offload *flow,
22 - struct sk_buff *skb, unsigned int thoff,
23 - u8 protocol, enum flow_offload_tuple_dir dir);
24 +void nf_flow_snat_port(const struct flow_offload *flow,
25 + struct sk_buff *skb, unsigned int thoff,
26 + u8 protocol, enum flow_offload_tuple_dir dir);
27 +void nf_flow_dnat_port(const struct flow_offload *flow,
28 + struct sk_buff *skb, unsigned int thoff,
29 + u8 protocol, enum flow_offload_tuple_dir dir);
33 --- a/net/netfilter/nf_flow_table_core.c
34 +++ b/net/netfilter/nf_flow_table_core.c
35 @@ -389,20 +389,17 @@ static void nf_flow_offload_work_gc(stru
36 queue_delayed_work(system_power_efficient_wq, &flow_table->gc_work, HZ);
40 -static int nf_flow_nat_port_tcp(struct sk_buff *skb, unsigned int thoff,
41 - __be16 port, __be16 new_port)
42 +static void nf_flow_nat_port_tcp(struct sk_buff *skb, unsigned int thoff,
43 + __be16 port, __be16 new_port)
47 tcph = (void *)(skb_network_header(skb) + thoff);
48 inet_proto_csum_replace2(&tcph->check, skb, port, new_port, false);
53 -static int nf_flow_nat_port_udp(struct sk_buff *skb, unsigned int thoff,
54 - __be16 port, __be16 new_port)
55 +static void nf_flow_nat_port_udp(struct sk_buff *skb, unsigned int thoff,
56 + __be16 port, __be16 new_port)
60 @@ -413,30 +410,24 @@ static int nf_flow_nat_port_udp(struct s
62 udph->check = CSUM_MANGLED_0;
68 -static int nf_flow_nat_port(struct sk_buff *skb, unsigned int thoff,
69 - u8 protocol, __be16 port, __be16 new_port)
70 +static void nf_flow_nat_port(struct sk_buff *skb, unsigned int thoff,
71 + u8 protocol, __be16 port, __be16 new_port)
75 - if (nf_flow_nat_port_tcp(skb, thoff, port, new_port) < 0)
77 + nf_flow_nat_port_tcp(skb, thoff, port, new_port);
80 - if (nf_flow_nat_port_udp(skb, thoff, port, new_port) < 0)
82 + nf_flow_nat_port_udp(skb, thoff, port, new_port);
89 -int nf_flow_snat_port(const struct flow_offload *flow,
90 - struct sk_buff *skb, unsigned int thoff,
91 - u8 protocol, enum flow_offload_tuple_dir dir)
92 +void nf_flow_snat_port(const struct flow_offload *flow,
93 + struct sk_buff *skb, unsigned int thoff,
94 + u8 protocol, enum flow_offload_tuple_dir dir)
96 struct flow_ports *hdr;
97 __be16 port, new_port;
98 @@ -456,13 +447,13 @@ int nf_flow_snat_port(const struct flow_
102 - return nf_flow_nat_port(skb, thoff, protocol, port, new_port);
103 + nf_flow_nat_port(skb, thoff, protocol, port, new_port);
105 EXPORT_SYMBOL_GPL(nf_flow_snat_port);
107 -int nf_flow_dnat_port(const struct flow_offload *flow,
108 - struct sk_buff *skb, unsigned int thoff,
109 - u8 protocol, enum flow_offload_tuple_dir dir)
110 +void nf_flow_dnat_port(const struct flow_offload *flow, struct sk_buff *skb,
111 + unsigned int thoff, u8 protocol,
112 + enum flow_offload_tuple_dir dir)
114 struct flow_ports *hdr;
115 __be16 port, new_port;
116 @@ -482,7 +473,7 @@ int nf_flow_dnat_port(const struct flow_
120 - return nf_flow_nat_port(skb, thoff, protocol, port, new_port);
121 + nf_flow_nat_port(skb, thoff, protocol, port, new_port);
123 EXPORT_SYMBOL_GPL(nf_flow_dnat_port);
125 --- a/net/netfilter/nf_flow_table_ip.c
126 +++ b/net/netfilter/nf_flow_table_ip.c
127 @@ -34,19 +34,17 @@ static int nf_flow_state_check(struct fl
131 -static int nf_flow_nat_ip_tcp(struct sk_buff *skb, unsigned int thoff,
132 - __be32 addr, __be32 new_addr)
133 +static void nf_flow_nat_ip_tcp(struct sk_buff *skb, unsigned int thoff,
134 + __be32 addr, __be32 new_addr)
138 tcph = (void *)(skb_network_header(skb) + thoff);
139 inet_proto_csum_replace4(&tcph->check, skb, addr, new_addr, true);
144 -static int nf_flow_nat_ip_udp(struct sk_buff *skb, unsigned int thoff,
145 - __be32 addr, __be32 new_addr)
146 +static void nf_flow_nat_ip_udp(struct sk_buff *skb, unsigned int thoff,
147 + __be32 addr, __be32 new_addr)
151 @@ -57,31 +55,25 @@ static int nf_flow_nat_ip_udp(struct sk_
153 udph->check = CSUM_MANGLED_0;
159 -static int nf_flow_nat_ip_l4proto(struct sk_buff *skb, struct iphdr *iph,
160 - unsigned int thoff, __be32 addr,
162 +static void nf_flow_nat_ip_l4proto(struct sk_buff *skb, struct iphdr *iph,
163 + unsigned int thoff, __be32 addr,
166 switch (iph->protocol) {
168 - if (nf_flow_nat_ip_tcp(skb, thoff, addr, new_addr) < 0)
170 + nf_flow_nat_ip_tcp(skb, thoff, addr, new_addr);
173 - if (nf_flow_nat_ip_udp(skb, thoff, addr, new_addr) < 0)
175 + nf_flow_nat_ip_udp(skb, thoff, addr, new_addr);
182 -static int nf_flow_snat_ip(const struct flow_offload *flow, struct sk_buff *skb,
183 - struct iphdr *iph, unsigned int thoff,
184 - enum flow_offload_tuple_dir dir)
185 +static void nf_flow_snat_ip(const struct flow_offload *flow,
186 + struct sk_buff *skb, struct iphdr *iph,
187 + unsigned int thoff, enum flow_offload_tuple_dir dir)
189 __be32 addr, new_addr;
191 @@ -99,12 +91,12 @@ static int nf_flow_snat_ip(const struct
193 csum_replace4(&iph->check, addr, new_addr);
195 - return nf_flow_nat_ip_l4proto(skb, iph, thoff, addr, new_addr);
196 + nf_flow_nat_ip_l4proto(skb, iph, thoff, addr, new_addr);
199 -static int nf_flow_dnat_ip(const struct flow_offload *flow, struct sk_buff *skb,
200 - struct iphdr *iph, unsigned int thoff,
201 - enum flow_offload_tuple_dir dir)
202 +static void nf_flow_dnat_ip(const struct flow_offload *flow,
203 + struct sk_buff *skb, struct iphdr *iph,
204 + unsigned int thoff, enum flow_offload_tuple_dir dir)
206 __be32 addr, new_addr;
208 @@ -122,24 +114,21 @@ static int nf_flow_dnat_ip(const struct
210 csum_replace4(&iph->check, addr, new_addr);
212 - return nf_flow_nat_ip_l4proto(skb, iph, thoff, addr, new_addr);
213 + nf_flow_nat_ip_l4proto(skb, iph, thoff, addr, new_addr);
216 -static int nf_flow_nat_ip(const struct flow_offload *flow, struct sk_buff *skb,
217 +static void nf_flow_nat_ip(const struct flow_offload *flow, struct sk_buff *skb,
218 unsigned int thoff, enum flow_offload_tuple_dir dir,
221 - if (test_bit(NF_FLOW_SNAT, &flow->flags) &&
222 - (nf_flow_snat_port(flow, skb, thoff, iph->protocol, dir) < 0 ||
223 - nf_flow_snat_ip(flow, skb, iph, thoff, dir) < 0))
226 - if (test_bit(NF_FLOW_DNAT, &flow->flags) &&
227 - (nf_flow_dnat_port(flow, skb, thoff, iph->protocol, dir) < 0 ||
228 - nf_flow_dnat_ip(flow, skb, iph, thoff, dir) < 0))
232 + if (test_bit(NF_FLOW_SNAT, &flow->flags)) {
233 + nf_flow_snat_port(flow, skb, thoff, iph->protocol, dir);
234 + nf_flow_snat_ip(flow, skb, iph, thoff, dir);
236 + if (test_bit(NF_FLOW_DNAT, &flow->flags)) {
237 + nf_flow_dnat_port(flow, skb, thoff, iph->protocol, dir);
238 + nf_flow_dnat_ip(flow, skb, iph, thoff, dir);
242 static bool ip_has_options(unsigned int thoff)
243 @@ -276,8 +265,7 @@ nf_flow_offload_ip_hook(void *priv, stru
247 - if (nf_flow_nat_ip(flow, skb, thoff, dir, iph) < 0)
249 + nf_flow_nat_ip(flow, skb, thoff, dir, iph);
251 ip_decrease_ttl(iph);
253 @@ -301,22 +289,21 @@ nf_flow_offload_ip_hook(void *priv, stru
255 EXPORT_SYMBOL_GPL(nf_flow_offload_ip_hook);
257 -static int nf_flow_nat_ipv6_tcp(struct sk_buff *skb, unsigned int thoff,
258 - struct in6_addr *addr,
259 - struct in6_addr *new_addr)
260 +static void nf_flow_nat_ipv6_tcp(struct sk_buff *skb, unsigned int thoff,
261 + struct in6_addr *addr,
262 + struct in6_addr *new_addr,
263 + struct ipv6hdr *ip6h)
267 tcph = (void *)(skb_network_header(skb) + thoff);
268 inet_proto_csum_replace16(&tcph->check, skb, addr->s6_addr32,
269 new_addr->s6_addr32, true);
274 -static int nf_flow_nat_ipv6_udp(struct sk_buff *skb, unsigned int thoff,
275 - struct in6_addr *addr,
276 - struct in6_addr *new_addr)
277 +static void nf_flow_nat_ipv6_udp(struct sk_buff *skb, unsigned int thoff,
278 + struct in6_addr *addr,
279 + struct in6_addr *new_addr)
283 @@ -327,32 +314,26 @@ static int nf_flow_nat_ipv6_udp(struct s
285 udph->check = CSUM_MANGLED_0;
291 -static int nf_flow_nat_ipv6_l4proto(struct sk_buff *skb, struct ipv6hdr *ip6h,
292 - unsigned int thoff, struct in6_addr *addr,
293 - struct in6_addr *new_addr)
294 +static void nf_flow_nat_ipv6_l4proto(struct sk_buff *skb, struct ipv6hdr *ip6h,
295 + unsigned int thoff, struct in6_addr *addr,
296 + struct in6_addr *new_addr)
298 switch (ip6h->nexthdr) {
300 - if (nf_flow_nat_ipv6_tcp(skb, thoff, addr, new_addr) < 0)
302 + nf_flow_nat_ipv6_tcp(skb, thoff, addr, new_addr, ip6h);
305 - if (nf_flow_nat_ipv6_udp(skb, thoff, addr, new_addr) < 0)
307 + nf_flow_nat_ipv6_udp(skb, thoff, addr, new_addr);
314 -static int nf_flow_snat_ipv6(const struct flow_offload *flow,
315 - struct sk_buff *skb, struct ipv6hdr *ip6h,
316 - unsigned int thoff,
317 - enum flow_offload_tuple_dir dir)
318 +static void nf_flow_snat_ipv6(const struct flow_offload *flow,
319 + struct sk_buff *skb, struct ipv6hdr *ip6h,
320 + unsigned int thoff,
321 + enum flow_offload_tuple_dir dir)
323 struct in6_addr addr, new_addr;
325 @@ -369,13 +350,13 @@ static int nf_flow_snat_ipv6(const struc
329 - return nf_flow_nat_ipv6_l4proto(skb, ip6h, thoff, &addr, &new_addr);
330 + nf_flow_nat_ipv6_l4proto(skb, ip6h, thoff, &addr, &new_addr);
333 -static int nf_flow_dnat_ipv6(const struct flow_offload *flow,
334 - struct sk_buff *skb, struct ipv6hdr *ip6h,
335 - unsigned int thoff,
336 - enum flow_offload_tuple_dir dir)
337 +static void nf_flow_dnat_ipv6(const struct flow_offload *flow,
338 + struct sk_buff *skb, struct ipv6hdr *ip6h,
339 + unsigned int thoff,
340 + enum flow_offload_tuple_dir dir)
342 struct in6_addr addr, new_addr;
344 @@ -392,27 +373,24 @@ static int nf_flow_dnat_ipv6(const struc
348 - return nf_flow_nat_ipv6_l4proto(skb, ip6h, thoff, &addr, &new_addr);
349 + nf_flow_nat_ipv6_l4proto(skb, ip6h, thoff, &addr, &new_addr);
352 -static int nf_flow_nat_ipv6(const struct flow_offload *flow,
353 - struct sk_buff *skb,
354 - enum flow_offload_tuple_dir dir,
355 - struct ipv6hdr *ip6h)
356 +static void nf_flow_nat_ipv6(const struct flow_offload *flow,
357 + struct sk_buff *skb,
358 + enum flow_offload_tuple_dir dir,
359 + struct ipv6hdr *ip6h)
361 unsigned int thoff = sizeof(*ip6h);
363 - if (test_bit(NF_FLOW_SNAT, &flow->flags) &&
364 - (nf_flow_snat_port(flow, skb, thoff, ip6h->nexthdr, dir) < 0 ||
365 - nf_flow_snat_ipv6(flow, skb, ip6h, thoff, dir) < 0))
368 - if (test_bit(NF_FLOW_DNAT, &flow->flags) &&
369 - (nf_flow_dnat_port(flow, skb, thoff, ip6h->nexthdr, dir) < 0 ||
370 - nf_flow_dnat_ipv6(flow, skb, ip6h, thoff, dir) < 0))
374 + if (test_bit(NF_FLOW_SNAT, &flow->flags)) {
375 + nf_flow_snat_port(flow, skb, thoff, ip6h->nexthdr, dir);
376 + nf_flow_snat_ipv6(flow, skb, ip6h, thoff, dir);
378 + if (test_bit(NF_FLOW_DNAT, &flow->flags)) {
379 + nf_flow_dnat_port(flow, skb, thoff, ip6h->nexthdr, dir);
380 + nf_flow_dnat_ipv6(flow, skb, ip6h, thoff, dir);
384 static int nf_flow_tuple_ipv6(struct sk_buff *skb, const struct net_device *dev,
385 @@ -507,8 +485,7 @@ nf_flow_offload_ipv6_hook(void *priv, st
388 ip6h = ipv6_hdr(skb);
389 - if (nf_flow_nat_ipv6(flow, skb, dir, ip6h) < 0)
391 + nf_flow_nat_ipv6(flow, skb, dir, ip6h);