1 // SPDX-License-Identifier: GPL-2.0-only
2 /* (C) 1999-2001 Paul `Rusty' Russell
3 * (C) 2002-2006 Netfilter Core Team <coreteam@netfilter.org>
4 */
5
6 #include <linux/types.h>
7 #include <linux/export.h>
8 #include <linux/init.h>
9 #include <linux/udp.h>
10 #include <linux/tcp.h>
11 #include <linux/icmp.h>
12 #include <linux/icmpv6.h>
13
14 #include <linux/dccp.h>
15 #include <linux/sctp.h>
16 #include <net/sctp/checksum.h>
17
18 #include <linux/netfilter.h>
19 #include <net/netfilter/nf_nat.h>
20
21 #include <linux/ipv6.h>
22 #include <linux/netfilter_ipv6.h>
23 #include <net/checksum.h>
24 #include <net/ip6_checksum.h>
25 #include <net/ip6_route.h>
26 #include <net/xfrm.h>
27 #include <net/ipv6.h>
28
29 #include <net/netfilter/nf_conntrack_core.h>
30 #include <net/netfilter/nf_conntrack.h>
31 #include <linux/netfilter/nfnetlink_conntrack.h>
32
33 static void nf_csum_update(struct sk_buff *skb,
34 unsigned int iphdroff, __sum16 *check,
35 const struct nf_conntrack_tuple *t,
36 enum nf_nat_manip_type maniptype);
37
38 static void
__udp_manip_pkt(struct sk_buff * skb,unsigned int iphdroff,struct udphdr * hdr,const struct nf_conntrack_tuple * tuple,enum nf_nat_manip_type maniptype,bool do_csum)39 __udp_manip_pkt(struct sk_buff *skb,
40 unsigned int iphdroff, struct udphdr *hdr,
41 const struct nf_conntrack_tuple *tuple,
42 enum nf_nat_manip_type maniptype, bool do_csum)
43 {
44 __be16 *portptr, newport;
45
46 if (maniptype == NF_NAT_MANIP_SRC) {
47 /* Get rid of src port */
48 newport = tuple->src.u.udp.port;
49 portptr = &hdr->source;
50 } else {
51 /* Get rid of dst port */
52 newport = tuple->dst.u.udp.port;
53 portptr = &hdr->dest;
54 }
55 if (do_csum) {
56 nf_csum_update(skb, iphdroff, &hdr->check, tuple, maniptype);
57 inet_proto_csum_replace2(&hdr->check, skb, *portptr, newport,
58 false);
59 if (!hdr->check)
60 hdr->check = CSUM_MANGLED_0;
61 }
62 *portptr = newport;
63 }
64
udp_manip_pkt(struct sk_buff * skb,unsigned int iphdroff,unsigned int hdroff,const struct nf_conntrack_tuple * tuple,enum nf_nat_manip_type maniptype)65 static bool udp_manip_pkt(struct sk_buff *skb,
66 unsigned int iphdroff, unsigned int hdroff,
67 const struct nf_conntrack_tuple *tuple,
68 enum nf_nat_manip_type maniptype)
69 {
70 struct udphdr *hdr;
71 bool do_csum;
72
73 if (skb_ensure_writable(skb, hdroff + sizeof(*hdr)))
74 return false;
75
76 hdr = (struct udphdr *)(skb->data + hdroff);
77 do_csum = hdr->check || skb->ip_summed == CHECKSUM_PARTIAL;
78
79 __udp_manip_pkt(skb, iphdroff, hdr, tuple, maniptype, do_csum);
80 return true;
81 }
82
udplite_manip_pkt(struct sk_buff * skb,unsigned int iphdroff,unsigned int hdroff,const struct nf_conntrack_tuple * tuple,enum nf_nat_manip_type maniptype)83 static bool udplite_manip_pkt(struct sk_buff *skb,
84 unsigned int iphdroff, unsigned int hdroff,
85 const struct nf_conntrack_tuple *tuple,
86 enum nf_nat_manip_type maniptype)
87 {
88 #ifdef CONFIG_NF_CT_PROTO_UDPLITE
89 struct udphdr *hdr;
90
91 if (skb_ensure_writable(skb, hdroff + sizeof(*hdr)))
92 return false;
93
94 hdr = (struct udphdr *)(skb->data + hdroff);
95 __udp_manip_pkt(skb, iphdroff, hdr, tuple, maniptype, true);
96 #endif
97 return true;
98 }
99
100 static bool
sctp_manip_pkt(struct sk_buff * skb,unsigned int iphdroff,unsigned int hdroff,const struct nf_conntrack_tuple * tuple,enum nf_nat_manip_type maniptype)101 sctp_manip_pkt(struct sk_buff *skb,
102 unsigned int iphdroff, unsigned int hdroff,
103 const struct nf_conntrack_tuple *tuple,
104 enum nf_nat_manip_type maniptype)
105 {
106 #ifdef CONFIG_NF_CT_PROTO_SCTP
107 struct sctphdr *hdr;
108 int hdrsize = 8;
109
110 /* This could be an inner header returned in imcp packet; in such
111 * cases we cannot update the checksum field since it is outside
112 * of the 8 bytes of transport layer headers we are guaranteed.
113 */
114 if (skb->len >= hdroff + sizeof(*hdr))
115 hdrsize = sizeof(*hdr);
116
117 if (skb_ensure_writable(skb, hdroff + hdrsize))
118 return false;
119
120 hdr = (struct sctphdr *)(skb->data + hdroff);
121
122 if (maniptype == NF_NAT_MANIP_SRC) {
123 /* Get rid of src port */
124 hdr->source = tuple->src.u.sctp.port;
125 } else {
126 /* Get rid of dst port */
127 hdr->dest = tuple->dst.u.sctp.port;
128 }
129
130 if (hdrsize < sizeof(*hdr))
131 return true;
132
133 if (skb->ip_summed != CHECKSUM_PARTIAL) {
134 hdr->checksum = sctp_compute_cksum(skb, hdroff);
135 skb->ip_summed = CHECKSUM_NONE;
136 }
137
138 #endif
139 return true;
140 }
141
142 static bool
tcp_manip_pkt(struct sk_buff * skb,unsigned int iphdroff,unsigned int hdroff,const struct nf_conntrack_tuple * tuple,enum nf_nat_manip_type maniptype)143 tcp_manip_pkt(struct sk_buff *skb,
144 unsigned int iphdroff, unsigned int hdroff,
145 const struct nf_conntrack_tuple *tuple,
146 enum nf_nat_manip_type maniptype)
147 {
148 struct tcphdr *hdr;
149 __be16 *portptr, newport, oldport;
150 int hdrsize = 8; /* TCP connection tracking guarantees this much */
151
152 /* this could be a inner header returned in icmp packet; in such
153 cases we cannot update the checksum field since it is outside of
154 the 8 bytes of transport layer headers we are guaranteed */
155 if (skb->len >= hdroff + sizeof(struct tcphdr))
156 hdrsize = sizeof(struct tcphdr);
157
158 if (skb_ensure_writable(skb, hdroff + hdrsize))
159 return false;
160
161 hdr = (struct tcphdr *)(skb->data + hdroff);
162
163 if (maniptype == NF_NAT_MANIP_SRC) {
164 /* Get rid of src port */
165 newport = tuple->src.u.tcp.port;
166 portptr = &hdr->source;
167 } else {
168 /* Get rid of dst port */
169 newport = tuple->dst.u.tcp.port;
170 portptr = &hdr->dest;
171 }
172
173 oldport = *portptr;
174 *portptr = newport;
175
176 if (hdrsize < sizeof(*hdr))
177 return true;
178
179 nf_csum_update(skb, iphdroff, &hdr->check, tuple, maniptype);
180 inet_proto_csum_replace2(&hdr->check, skb, oldport, newport, false);
181 return true;
182 }
183
184 static bool
dccp_manip_pkt(struct sk_buff * skb,unsigned int iphdroff,unsigned int hdroff,const struct nf_conntrack_tuple * tuple,enum nf_nat_manip_type maniptype)185 dccp_manip_pkt(struct sk_buff *skb,
186 unsigned int iphdroff, unsigned int hdroff,
187 const struct nf_conntrack_tuple *tuple,
188 enum nf_nat_manip_type maniptype)
189 {
190 #ifdef CONFIG_NF_CT_PROTO_DCCP
191 struct dccp_hdr *hdr;
192 __be16 *portptr, oldport, newport;
193 int hdrsize = 8; /* DCCP connection tracking guarantees this much */
194
195 if (skb->len >= hdroff + sizeof(struct dccp_hdr))
196 hdrsize = sizeof(struct dccp_hdr);
197
198 if (skb_ensure_writable(skb, hdroff + hdrsize))
199 return false;
200
201 hdr = (struct dccp_hdr *)(skb->data + hdroff);
202
203 if (maniptype == NF_NAT_MANIP_SRC) {
204 newport = tuple->src.u.dccp.port;
205 portptr = &hdr->dccph_sport;
206 } else {
207 newport = tuple->dst.u.dccp.port;
208 portptr = &hdr->dccph_dport;
209 }
210
211 oldport = *portptr;
212 *portptr = newport;
213
214 if (hdrsize < sizeof(*hdr))
215 return true;
216
217 nf_csum_update(skb, iphdroff, &hdr->dccph_checksum, tuple, maniptype);
218 inet_proto_csum_replace2(&hdr->dccph_checksum, skb, oldport, newport,
219 false);
220 #endif
221 return true;
222 }
223
224 static bool
icmp_manip_pkt(struct sk_buff * skb,unsigned int iphdroff,unsigned int hdroff,const struct nf_conntrack_tuple * tuple,enum nf_nat_manip_type maniptype)225 icmp_manip_pkt(struct sk_buff *skb,
226 unsigned int iphdroff, unsigned int hdroff,
227 const struct nf_conntrack_tuple *tuple,
228 enum nf_nat_manip_type maniptype)
229 {
230 struct icmphdr *hdr;
231
232 if (skb_ensure_writable(skb, hdroff + sizeof(*hdr)))
233 return false;
234
235 hdr = (struct icmphdr *)(skb->data + hdroff);
236 inet_proto_csum_replace2(&hdr->checksum, skb,
237 hdr->un.echo.id, tuple->src.u.icmp.id, false);
238 hdr->un.echo.id = tuple->src.u.icmp.id;
239 return true;
240 }
241
242 static bool
icmpv6_manip_pkt(struct sk_buff * skb,unsigned int iphdroff,unsigned int hdroff,const struct nf_conntrack_tuple * tuple,enum nf_nat_manip_type maniptype)243 icmpv6_manip_pkt(struct sk_buff *skb,
244 unsigned int iphdroff, unsigned int hdroff,
245 const struct nf_conntrack_tuple *tuple,
246 enum nf_nat_manip_type maniptype)
247 {
248 struct icmp6hdr *hdr;
249
250 if (skb_ensure_writable(skb, hdroff + sizeof(*hdr)))
251 return false;
252
253 hdr = (struct icmp6hdr *)(skb->data + hdroff);
254 nf_csum_update(skb, iphdroff, &hdr->icmp6_cksum, tuple, maniptype);
255 if (hdr->icmp6_type == ICMPV6_ECHO_REQUEST ||
256 hdr->icmp6_type == ICMPV6_ECHO_REPLY) {
257 inet_proto_csum_replace2(&hdr->icmp6_cksum, skb,
258 hdr->icmp6_identifier,
259 tuple->src.u.icmp.id, false);
260 hdr->icmp6_identifier = tuple->src.u.icmp.id;
261 }
262 return true;
263 }
264
265 /* manipulate a GRE packet according to maniptype */
266 static bool
gre_manip_pkt(struct sk_buff * skb,unsigned int iphdroff,unsigned int hdroff,const struct nf_conntrack_tuple * tuple,enum nf_nat_manip_type maniptype)267 gre_manip_pkt(struct sk_buff *skb,
268 unsigned int iphdroff, unsigned int hdroff,
269 const struct nf_conntrack_tuple *tuple,
270 enum nf_nat_manip_type maniptype)
271 {
272 #if IS_ENABLED(CONFIG_NF_CT_PROTO_GRE)
273 const struct gre_base_hdr *greh;
274 struct pptp_gre_header *pgreh;
275
276 /* pgreh includes two optional 32bit fields which are not required
277 * to be there. That's where the magic '8' comes from */
278 if (skb_ensure_writable(skb, hdroff + sizeof(*pgreh) - 8))
279 return false;
280
281 greh = (void *)skb->data + hdroff;
282 pgreh = (struct pptp_gre_header *)greh;
283
284 /* we only have destination manip of a packet, since 'source key'
285 * is not present in the packet itself */
286 if (maniptype != NF_NAT_MANIP_DST)
287 return true;
288
289 switch (greh->flags & GRE_VERSION) {
290 case GRE_VERSION_0:
291 /* We do not currently NAT any GREv0 packets.
292 * Try to behave like "nf_nat_proto_unknown" */
293 break;
294 case GRE_VERSION_1:
295 pr_debug("call_id -> 0x%04x\n", ntohs(tuple->dst.u.gre.key));
296 pgreh->call_id = tuple->dst.u.gre.key;
297 break;
298 default:
299 pr_debug("can't nat unknown GRE version\n");
300 return false;
301 }
302 #endif
303 return true;
304 }
305
l4proto_manip_pkt(struct sk_buff * skb,unsigned int iphdroff,unsigned int hdroff,const struct nf_conntrack_tuple * tuple,enum nf_nat_manip_type maniptype)306 static bool l4proto_manip_pkt(struct sk_buff *skb,
307 unsigned int iphdroff, unsigned int hdroff,
308 const struct nf_conntrack_tuple *tuple,
309 enum nf_nat_manip_type maniptype)
310 {
311 switch (tuple->dst.protonum) {
312 case IPPROTO_TCP:
313 return tcp_manip_pkt(skb, iphdroff, hdroff,
314 tuple, maniptype);
315 case IPPROTO_UDP:
316 return udp_manip_pkt(skb, iphdroff, hdroff,
317 tuple, maniptype);
318 case IPPROTO_UDPLITE:
319 return udplite_manip_pkt(skb, iphdroff, hdroff,
320 tuple, maniptype);
321 case IPPROTO_SCTP:
322 return sctp_manip_pkt(skb, iphdroff, hdroff,
323 tuple, maniptype);
324 case IPPROTO_ICMP:
325 return icmp_manip_pkt(skb, iphdroff, hdroff,
326 tuple, maniptype);
327 case IPPROTO_ICMPV6:
328 return icmpv6_manip_pkt(skb, iphdroff, hdroff,
329 tuple, maniptype);
330 case IPPROTO_DCCP:
331 return dccp_manip_pkt(skb, iphdroff, hdroff,
332 tuple, maniptype);
333 case IPPROTO_GRE:
334 return gre_manip_pkt(skb, iphdroff, hdroff,
335 tuple, maniptype);
336 }
337
338 /* If we don't know protocol -- no error, pass it unmodified. */
339 return true;
340 }
341
nf_nat_ipv4_manip_pkt(struct sk_buff * skb,unsigned int iphdroff,const struct nf_conntrack_tuple * target,enum nf_nat_manip_type maniptype)342 static bool nf_nat_ipv4_manip_pkt(struct sk_buff *skb,
343 unsigned int iphdroff,
344 const struct nf_conntrack_tuple *target,
345 enum nf_nat_manip_type maniptype)
346 {
347 struct iphdr *iph;
348 unsigned int hdroff;
349
350 if (skb_ensure_writable(skb, iphdroff + sizeof(*iph)))
351 return false;
352
353 iph = (void *)skb->data + iphdroff;
354 hdroff = iphdroff + iph->ihl * 4;
355
356 if (!l4proto_manip_pkt(skb, iphdroff, hdroff, target, maniptype))
357 return false;
358 iph = (void *)skb->data + iphdroff;
359
360 if (maniptype == NF_NAT_MANIP_SRC) {
361 csum_replace4(&iph->check, iph->saddr, target->src.u3.ip);
362 iph->saddr = target->src.u3.ip;
363 } else {
364 csum_replace4(&iph->check, iph->daddr, target->dst.u3.ip);
365 iph->daddr = target->dst.u3.ip;
366 }
367 return true;
368 }
369
nf_nat_ipv6_manip_pkt(struct sk_buff * skb,unsigned int iphdroff,const struct nf_conntrack_tuple * target,enum nf_nat_manip_type maniptype)370 static bool nf_nat_ipv6_manip_pkt(struct sk_buff *skb,
371 unsigned int iphdroff,
372 const struct nf_conntrack_tuple *target,
373 enum nf_nat_manip_type maniptype)
374 {
375 #if IS_ENABLED(CONFIG_IPV6)
376 struct ipv6hdr *ipv6h;
377 __be16 frag_off;
378 int hdroff;
379 u8 nexthdr;
380
381 if (skb_ensure_writable(skb, iphdroff + sizeof(*ipv6h)))
382 return false;
383
384 ipv6h = (void *)skb->data + iphdroff;
385 nexthdr = ipv6h->nexthdr;
386 hdroff = ipv6_skip_exthdr(skb, iphdroff + sizeof(*ipv6h),
387 &nexthdr, &frag_off);
388 if (hdroff < 0)
389 goto manip_addr;
390
391 if ((frag_off & htons(~0x7)) == 0 &&
392 !l4proto_manip_pkt(skb, iphdroff, hdroff, target, maniptype))
393 return false;
394
395 /* must reload, offset might have changed */
396 ipv6h = (void *)skb->data + iphdroff;
397
398 manip_addr:
399 if (maniptype == NF_NAT_MANIP_SRC)
400 ipv6h->saddr = target->src.u3.in6;
401 else
402 ipv6h->daddr = target->dst.u3.in6;
403
404 #endif
405 return true;
406 }
407
nf_nat_manip_pkt(struct sk_buff * skb,struct nf_conn * ct,enum nf_nat_manip_type mtype,enum ip_conntrack_dir dir)408 unsigned int nf_nat_manip_pkt(struct sk_buff *skb, struct nf_conn *ct,
409 enum nf_nat_manip_type mtype,
410 enum ip_conntrack_dir dir)
411 {
412 struct nf_conntrack_tuple target;
413
414 /* We are aiming to look like inverse of other direction. */
415 nf_ct_invert_tuple(&target, &ct->tuplehash[!dir].tuple);
416
417 switch (target.src.l3num) {
418 case NFPROTO_IPV6:
419 if (nf_nat_ipv6_manip_pkt(skb, 0, &target, mtype))
420 return NF_ACCEPT;
421 break;
422 case NFPROTO_IPV4:
423 if (nf_nat_ipv4_manip_pkt(skb, 0, &target, mtype))
424 return NF_ACCEPT;
425 break;
426 default:
427 WARN_ON_ONCE(1);
428 break;
429 }
430
431 return NF_DROP;
432 }
433
nf_nat_ipv4_csum_update(struct sk_buff * skb,unsigned int iphdroff,__sum16 * check,const struct nf_conntrack_tuple * t,enum nf_nat_manip_type maniptype)434 static void nf_nat_ipv4_csum_update(struct sk_buff *skb,
435 unsigned int iphdroff, __sum16 *check,
436 const struct nf_conntrack_tuple *t,
437 enum nf_nat_manip_type maniptype)
438 {
439 struct iphdr *iph = (struct iphdr *)(skb->data + iphdroff);
440 __be32 oldip, newip;
441
442 if (maniptype == NF_NAT_MANIP_SRC) {
443 oldip = iph->saddr;
444 newip = t->src.u3.ip;
445 } else {
446 oldip = iph->daddr;
447 newip = t->dst.u3.ip;
448 }
449 inet_proto_csum_replace4(check, skb, oldip, newip, true);
450 }
451
nf_nat_ipv6_csum_update(struct sk_buff * skb,unsigned int iphdroff,__sum16 * check,const struct nf_conntrack_tuple * t,enum nf_nat_manip_type maniptype)452 static void nf_nat_ipv6_csum_update(struct sk_buff *skb,
453 unsigned int iphdroff, __sum16 *check,
454 const struct nf_conntrack_tuple *t,
455 enum nf_nat_manip_type maniptype)
456 {
457 #if IS_ENABLED(CONFIG_IPV6)
458 const struct ipv6hdr *ipv6h = (struct ipv6hdr *)(skb->data + iphdroff);
459 const struct in6_addr *oldip, *newip;
460
461 if (maniptype == NF_NAT_MANIP_SRC) {
462 oldip = &ipv6h->saddr;
463 newip = &t->src.u3.in6;
464 } else {
465 oldip = &ipv6h->daddr;
466 newip = &t->dst.u3.in6;
467 }
468 inet_proto_csum_replace16(check, skb, oldip->s6_addr32,
469 newip->s6_addr32, true);
470 #endif
471 }
472
nf_csum_update(struct sk_buff * skb,unsigned int iphdroff,__sum16 * check,const struct nf_conntrack_tuple * t,enum nf_nat_manip_type maniptype)473 static void nf_csum_update(struct sk_buff *skb,
474 unsigned int iphdroff, __sum16 *check,
475 const struct nf_conntrack_tuple *t,
476 enum nf_nat_manip_type maniptype)
477 {
478 switch (t->src.l3num) {
479 case NFPROTO_IPV4:
480 nf_nat_ipv4_csum_update(skb, iphdroff, check, t, maniptype);
481 return;
482 case NFPROTO_IPV6:
483 nf_nat_ipv6_csum_update(skb, iphdroff, check, t, maniptype);
484 return;
485 }
486 }
487
nf_nat_ipv4_csum_recalc(struct sk_buff * skb,u8 proto,void * data,__sum16 * check,int datalen,int oldlen)488 static void nf_nat_ipv4_csum_recalc(struct sk_buff *skb,
489 u8 proto, void *data, __sum16 *check,
490 int datalen, int oldlen)
491 {
492 if (skb->ip_summed != CHECKSUM_PARTIAL) {
493 const struct iphdr *iph = ip_hdr(skb);
494
495 skb->ip_summed = CHECKSUM_PARTIAL;
496 skb->csum_start = skb_headroom(skb) + skb_network_offset(skb) +
497 ip_hdrlen(skb);
498 skb->csum_offset = (void *)check - data;
499 *check = ~csum_tcpudp_magic(iph->saddr, iph->daddr, datalen,
500 proto, 0);
501 } else {
502 inet_proto_csum_replace2(check, skb,
503 htons(oldlen), htons(datalen), true);
504 }
505 }
506
507 #if IS_ENABLED(CONFIG_IPV6)
nf_nat_ipv6_csum_recalc(struct sk_buff * skb,u8 proto,void * data,__sum16 * check,int datalen,int oldlen)508 static void nf_nat_ipv6_csum_recalc(struct sk_buff *skb,
509 u8 proto, void *data, __sum16 *check,
510 int datalen, int oldlen)
511 {
512 if (skb->ip_summed != CHECKSUM_PARTIAL) {
513 const struct ipv6hdr *ipv6h = ipv6_hdr(skb);
514
515 skb->ip_summed = CHECKSUM_PARTIAL;
516 skb->csum_start = skb_headroom(skb) + skb_network_offset(skb) +
517 (data - (void *)skb->data);
518 skb->csum_offset = (void *)check - data;
519 *check = ~csum_ipv6_magic(&ipv6h->saddr, &ipv6h->daddr,
520 datalen, proto, 0);
521 } else {
522 inet_proto_csum_replace2(check, skb,
523 htons(oldlen), htons(datalen), true);
524 }
525 }
526 #endif
527
nf_nat_csum_recalc(struct sk_buff * skb,u8 nfproto,u8 proto,void * data,__sum16 * check,int datalen,int oldlen)528 void nf_nat_csum_recalc(struct sk_buff *skb,
529 u8 nfproto, u8 proto, void *data, __sum16 *check,
530 int datalen, int oldlen)
531 {
532 switch (nfproto) {
533 case NFPROTO_IPV4:
534 nf_nat_ipv4_csum_recalc(skb, proto, data, check,
535 datalen, oldlen);
536 return;
537 #if IS_ENABLED(CONFIG_IPV6)
538 case NFPROTO_IPV6:
539 nf_nat_ipv6_csum_recalc(skb, proto, data, check,
540 datalen, oldlen);
541 return;
542 #endif
543 }
544
545 WARN_ON_ONCE(1);
546 }
547
nf_nat_icmp_reply_translation(struct sk_buff * skb,struct nf_conn * ct,enum ip_conntrack_info ctinfo,unsigned int hooknum)548 int nf_nat_icmp_reply_translation(struct sk_buff *skb,
549 struct nf_conn *ct,
550 enum ip_conntrack_info ctinfo,
551 unsigned int hooknum)
552 {
553 struct {
554 struct icmphdr icmp;
555 struct iphdr ip;
556 } *inside;
557 enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
558 enum nf_nat_manip_type manip = HOOK2MANIP(hooknum);
559 unsigned int hdrlen = ip_hdrlen(skb);
560 struct nf_conntrack_tuple target;
561 unsigned long statusbit;
562
563 WARN_ON(ctinfo != IP_CT_RELATED && ctinfo != IP_CT_RELATED_REPLY);
564
565 if (skb_ensure_writable(skb, hdrlen + sizeof(*inside)))
566 return 0;
567 if (nf_ip_checksum(skb, hooknum, hdrlen, IPPROTO_ICMP))
568 return 0;
569
570 inside = (void *)skb->data + hdrlen;
571 if (inside->icmp.type == ICMP_REDIRECT) {
572 if ((ct->status & IPS_NAT_DONE_MASK) != IPS_NAT_DONE_MASK)
573 return 0;
574 if (ct->status & IPS_NAT_MASK)
575 return 0;
576 }
577
578 if (manip == NF_NAT_MANIP_SRC)
579 statusbit = IPS_SRC_NAT;
580 else
581 statusbit = IPS_DST_NAT;
582
583 /* Invert if this is reply direction */
584 if (dir == IP_CT_DIR_REPLY)
585 statusbit ^= IPS_NAT_MASK;
586
587 if (!(ct->status & statusbit))
588 return 1;
589
590 if (!nf_nat_ipv4_manip_pkt(skb, hdrlen + sizeof(inside->icmp),
591 &ct->tuplehash[!dir].tuple, !manip))
592 return 0;
593
594 if (skb->ip_summed != CHECKSUM_PARTIAL) {
595 /* Reloading "inside" here since manip_pkt may reallocate */
596 inside = (void *)skb->data + hdrlen;
597 inside->icmp.checksum = 0;
598 inside->icmp.checksum =
599 csum_fold(skb_checksum(skb, hdrlen,
600 skb->len - hdrlen, 0));
601 }
602
603 /* Change outer to look like the reply to an incoming packet */
604 nf_ct_invert_tuple(&target, &ct->tuplehash[!dir].tuple);
605 target.dst.protonum = IPPROTO_ICMP;
606 if (!nf_nat_ipv4_manip_pkt(skb, 0, &target, manip))
607 return 0;
608
609 return 1;
610 }
611 EXPORT_SYMBOL_GPL(nf_nat_icmp_reply_translation);
612
613 static unsigned int
nf_nat_ipv4_fn(void * priv,struct sk_buff * skb,const struct nf_hook_state * state)614 nf_nat_ipv4_fn(void *priv, struct sk_buff *skb,
615 const struct nf_hook_state *state)
616 {
617 struct nf_conn *ct;
618 enum ip_conntrack_info ctinfo;
619
620 ct = nf_ct_get(skb, &ctinfo);
621 if (!ct)
622 return NF_ACCEPT;
623
624 if (ctinfo == IP_CT_RELATED || ctinfo == IP_CT_RELATED_REPLY) {
625 if (ip_hdr(skb)->protocol == IPPROTO_ICMP) {
626 if (!nf_nat_icmp_reply_translation(skb, ct, ctinfo,
627 state->hook))
628 return NF_DROP;
629 else
630 return NF_ACCEPT;
631 }
632 }
633
634 return nf_nat_inet_fn(priv, skb, state);
635 }
636
637 static unsigned int
nf_nat_ipv4_in(void * priv,struct sk_buff * skb,const struct nf_hook_state * state)638 nf_nat_ipv4_in(void *priv, struct sk_buff *skb,
639 const struct nf_hook_state *state)
640 {
641 unsigned int ret;
642 __be32 daddr = ip_hdr(skb)->daddr;
643
644 ret = nf_nat_ipv4_fn(priv, skb, state);
645 if (ret == NF_ACCEPT && daddr != ip_hdr(skb)->daddr)
646 skb_dst_drop(skb);
647
648 return ret;
649 }
650
651 static unsigned int
nf_nat_ipv4_out(void * priv,struct sk_buff * skb,const struct nf_hook_state * state)652 nf_nat_ipv4_out(void *priv, struct sk_buff *skb,
653 const struct nf_hook_state *state)
654 {
655 #ifdef CONFIG_XFRM
656 const struct nf_conn *ct;
657 enum ip_conntrack_info ctinfo;
658 int err;
659 #endif
660 unsigned int ret;
661
662 ret = nf_nat_ipv4_fn(priv, skb, state);
663 #ifdef CONFIG_XFRM
664 if (ret != NF_ACCEPT)
665 return ret;
666
667 if (IPCB(skb)->flags & IPSKB_XFRM_TRANSFORMED)
668 return ret;
669
670 ct = nf_ct_get(skb, &ctinfo);
671 if (ct) {
672 enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
673
674 if (ct->tuplehash[dir].tuple.src.u3.ip !=
675 ct->tuplehash[!dir].tuple.dst.u3.ip ||
676 (ct->tuplehash[dir].tuple.dst.protonum != IPPROTO_ICMP &&
677 ct->tuplehash[dir].tuple.src.u.all !=
678 ct->tuplehash[!dir].tuple.dst.u.all)) {
679 err = nf_xfrm_me_harder(state->net, skb, AF_INET);
680 if (err < 0)
681 ret = NF_DROP_ERR(err);
682 }
683 }
684 #endif
685 return ret;
686 }
687
688 static unsigned int
nf_nat_ipv4_local_fn(void * priv,struct sk_buff * skb,const struct nf_hook_state * state)689 nf_nat_ipv4_local_fn(void *priv, struct sk_buff *skb,
690 const struct nf_hook_state *state)
691 {
692 const struct nf_conn *ct;
693 enum ip_conntrack_info ctinfo;
694 unsigned int ret;
695 int err;
696
697 ret = nf_nat_ipv4_fn(priv, skb, state);
698 if (ret != NF_ACCEPT)
699 return ret;
700
701 ct = nf_ct_get(skb, &ctinfo);
702 if (ct) {
703 enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
704
705 if (ct->tuplehash[dir].tuple.dst.u3.ip !=
706 ct->tuplehash[!dir].tuple.src.u3.ip) {
707 err = ip_route_me_harder(state->net, skb, RTN_UNSPEC);
708 if (err < 0)
709 ret = NF_DROP_ERR(err);
710 }
711 #ifdef CONFIG_XFRM
712 else if (!(IPCB(skb)->flags & IPSKB_XFRM_TRANSFORMED) &&
713 ct->tuplehash[dir].tuple.dst.protonum != IPPROTO_ICMP &&
714 ct->tuplehash[dir].tuple.dst.u.all !=
715 ct->tuplehash[!dir].tuple.src.u.all) {
716 err = nf_xfrm_me_harder(state->net, skb, AF_INET);
717 if (err < 0)
718 ret = NF_DROP_ERR(err);
719 }
720 #endif
721 }
722 return ret;
723 }
724
725 static const struct nf_hook_ops nf_nat_ipv4_ops[] = {
726 /* Before packet filtering, change destination */
727 {
728 .hook = nf_nat_ipv4_in,
729 .pf = NFPROTO_IPV4,
730 .hooknum = NF_INET_PRE_ROUTING,
731 .priority = NF_IP_PRI_NAT_DST,
732 },
733 /* After packet filtering, change source */
734 {
735 .hook = nf_nat_ipv4_out,
736 .pf = NFPROTO_IPV4,
737 .hooknum = NF_INET_POST_ROUTING,
738 .priority = NF_IP_PRI_NAT_SRC,
739 },
740 /* Before packet filtering, change destination */
741 {
742 .hook = nf_nat_ipv4_local_fn,
743 .pf = NFPROTO_IPV4,
744 .hooknum = NF_INET_LOCAL_OUT,
745 .priority = NF_IP_PRI_NAT_DST,
746 },
747 /* After packet filtering, change source */
748 {
749 .hook = nf_nat_ipv4_fn,
750 .pf = NFPROTO_IPV4,
751 .hooknum = NF_INET_LOCAL_IN,
752 .priority = NF_IP_PRI_NAT_SRC,
753 },
754 };
755
nf_nat_ipv4_register_fn(struct net * net,const struct nf_hook_ops * ops)756 int nf_nat_ipv4_register_fn(struct net *net, const struct nf_hook_ops *ops)
757 {
758 return nf_nat_register_fn(net, ops->pf, ops, nf_nat_ipv4_ops,
759 ARRAY_SIZE(nf_nat_ipv4_ops));
760 }
761 EXPORT_SYMBOL_GPL(nf_nat_ipv4_register_fn);
762
nf_nat_ipv4_unregister_fn(struct net * net,const struct nf_hook_ops * ops)763 void nf_nat_ipv4_unregister_fn(struct net *net, const struct nf_hook_ops *ops)
764 {
765 nf_nat_unregister_fn(net, ops->pf, ops, ARRAY_SIZE(nf_nat_ipv4_ops));
766 }
767 EXPORT_SYMBOL_GPL(nf_nat_ipv4_unregister_fn);
768
769 #if IS_ENABLED(CONFIG_IPV6)
nf_nat_icmpv6_reply_translation(struct sk_buff * skb,struct nf_conn * ct,enum ip_conntrack_info ctinfo,unsigned int hooknum,unsigned int hdrlen)770 int nf_nat_icmpv6_reply_translation(struct sk_buff *skb,
771 struct nf_conn *ct,
772 enum ip_conntrack_info ctinfo,
773 unsigned int hooknum,
774 unsigned int hdrlen)
775 {
776 struct {
777 struct icmp6hdr icmp6;
778 struct ipv6hdr ip6;
779 } *inside;
780 enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
781 enum nf_nat_manip_type manip = HOOK2MANIP(hooknum);
782 struct nf_conntrack_tuple target;
783 unsigned long statusbit;
784
785 WARN_ON(ctinfo != IP_CT_RELATED && ctinfo != IP_CT_RELATED_REPLY);
786
787 if (skb_ensure_writable(skb, hdrlen + sizeof(*inside)))
788 return 0;
789 if (nf_ip6_checksum(skb, hooknum, hdrlen, IPPROTO_ICMPV6))
790 return 0;
791
792 inside = (void *)skb->data + hdrlen;
793 if (inside->icmp6.icmp6_type == NDISC_REDIRECT) {
794 if ((ct->status & IPS_NAT_DONE_MASK) != IPS_NAT_DONE_MASK)
795 return 0;
796 if (ct->status & IPS_NAT_MASK)
797 return 0;
798 }
799
800 if (manip == NF_NAT_MANIP_SRC)
801 statusbit = IPS_SRC_NAT;
802 else
803 statusbit = IPS_DST_NAT;
804
805 /* Invert if this is reply direction */
806 if (dir == IP_CT_DIR_REPLY)
807 statusbit ^= IPS_NAT_MASK;
808
809 if (!(ct->status & statusbit))
810 return 1;
811
812 if (!nf_nat_ipv6_manip_pkt(skb, hdrlen + sizeof(inside->icmp6),
813 &ct->tuplehash[!dir].tuple, !manip))
814 return 0;
815
816 if (skb->ip_summed != CHECKSUM_PARTIAL) {
817 struct ipv6hdr *ipv6h = ipv6_hdr(skb);
818
819 inside = (void *)skb->data + hdrlen;
820 inside->icmp6.icmp6_cksum = 0;
821 inside->icmp6.icmp6_cksum =
822 csum_ipv6_magic(&ipv6h->saddr, &ipv6h->daddr,
823 skb->len - hdrlen, IPPROTO_ICMPV6,
824 skb_checksum(skb, hdrlen,
825 skb->len - hdrlen, 0));
826 }
827
828 nf_ct_invert_tuple(&target, &ct->tuplehash[!dir].tuple);
829 target.dst.protonum = IPPROTO_ICMPV6;
830 if (!nf_nat_ipv6_manip_pkt(skb, 0, &target, manip))
831 return 0;
832
833 return 1;
834 }
835 EXPORT_SYMBOL_GPL(nf_nat_icmpv6_reply_translation);
836
837 static unsigned int
nf_nat_ipv6_fn(void * priv,struct sk_buff * skb,const struct nf_hook_state * state)838 nf_nat_ipv6_fn(void *priv, struct sk_buff *skb,
839 const struct nf_hook_state *state)
840 {
841 struct nf_conn *ct;
842 enum ip_conntrack_info ctinfo;
843 __be16 frag_off;
844 int hdrlen;
845 u8 nexthdr;
846
847 ct = nf_ct_get(skb, &ctinfo);
848 /* Can't track? It's not due to stress, or conntrack would
849 * have dropped it. Hence it's the user's responsibilty to
850 * packet filter it out, or implement conntrack/NAT for that
851 * protocol. 8) --RR
852 */
853 if (!ct)
854 return NF_ACCEPT;
855
856 if (ctinfo == IP_CT_RELATED || ctinfo == IP_CT_RELATED_REPLY) {
857 nexthdr = ipv6_hdr(skb)->nexthdr;
858 hdrlen = ipv6_skip_exthdr(skb, sizeof(struct ipv6hdr),
859 &nexthdr, &frag_off);
860
861 if (hdrlen >= 0 && nexthdr == IPPROTO_ICMPV6) {
862 if (!nf_nat_icmpv6_reply_translation(skb, ct, ctinfo,
863 state->hook,
864 hdrlen))
865 return NF_DROP;
866 else
867 return NF_ACCEPT;
868 }
869 }
870
871 return nf_nat_inet_fn(priv, skb, state);
872 }
873
874 static unsigned int
nf_nat_ipv6_in(void * priv,struct sk_buff * skb,const struct nf_hook_state * state)875 nf_nat_ipv6_in(void *priv, struct sk_buff *skb,
876 const struct nf_hook_state *state)
877 {
878 unsigned int ret;
879 struct in6_addr daddr = ipv6_hdr(skb)->daddr;
880
881 ret = nf_nat_ipv6_fn(priv, skb, state);
882 if (ret != NF_DROP && ret != NF_STOLEN &&
883 ipv6_addr_cmp(&daddr, &ipv6_hdr(skb)->daddr))
884 skb_dst_drop(skb);
885
886 return ret;
887 }
888
889 static unsigned int
nf_nat_ipv6_out(void * priv,struct sk_buff * skb,const struct nf_hook_state * state)890 nf_nat_ipv6_out(void *priv, struct sk_buff *skb,
891 const struct nf_hook_state *state)
892 {
893 #ifdef CONFIG_XFRM
894 const struct nf_conn *ct;
895 enum ip_conntrack_info ctinfo;
896 int err;
897 #endif
898 unsigned int ret;
899
900 ret = nf_nat_ipv6_fn(priv, skb, state);
901 #ifdef CONFIG_XFRM
902 if (ret != NF_ACCEPT)
903 return ret;
904
905 if (IP6CB(skb)->flags & IP6SKB_XFRM_TRANSFORMED)
906 return ret;
907 ct = nf_ct_get(skb, &ctinfo);
908 if (ct) {
909 enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
910
911 if (!nf_inet_addr_cmp(&ct->tuplehash[dir].tuple.src.u3,
912 &ct->tuplehash[!dir].tuple.dst.u3) ||
913 (ct->tuplehash[dir].tuple.dst.protonum != IPPROTO_ICMPV6 &&
914 ct->tuplehash[dir].tuple.src.u.all !=
915 ct->tuplehash[!dir].tuple.dst.u.all)) {
916 err = nf_xfrm_me_harder(state->net, skb, AF_INET6);
917 if (err < 0)
918 ret = NF_DROP_ERR(err);
919 }
920 }
921 #endif
922
923 return ret;
924 }
925
926 static unsigned int
nf_nat_ipv6_local_fn(void * priv,struct sk_buff * skb,const struct nf_hook_state * state)927 nf_nat_ipv6_local_fn(void *priv, struct sk_buff *skb,
928 const struct nf_hook_state *state)
929 {
930 const struct nf_conn *ct;
931 enum ip_conntrack_info ctinfo;
932 unsigned int ret;
933 int err;
934
935 ret = nf_nat_ipv6_fn(priv, skb, state);
936 if (ret != NF_ACCEPT)
937 return ret;
938
939 ct = nf_ct_get(skb, &ctinfo);
940 if (ct) {
941 enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
942
943 if (!nf_inet_addr_cmp(&ct->tuplehash[dir].tuple.dst.u3,
944 &ct->tuplehash[!dir].tuple.src.u3)) {
945 err = nf_ip6_route_me_harder(state->net, skb);
946 if (err < 0)
947 ret = NF_DROP_ERR(err);
948 }
949 #ifdef CONFIG_XFRM
950 else if (!(IP6CB(skb)->flags & IP6SKB_XFRM_TRANSFORMED) &&
951 ct->tuplehash[dir].tuple.dst.protonum != IPPROTO_ICMPV6 &&
952 ct->tuplehash[dir].tuple.dst.u.all !=
953 ct->tuplehash[!dir].tuple.src.u.all) {
954 err = nf_xfrm_me_harder(state->net, skb, AF_INET6);
955 if (err < 0)
956 ret = NF_DROP_ERR(err);
957 }
958 #endif
959 }
960
961 return ret;
962 }
963
964 static const struct nf_hook_ops nf_nat_ipv6_ops[] = {
965 /* Before packet filtering, change destination */
966 {
967 .hook = nf_nat_ipv6_in,
968 .pf = NFPROTO_IPV6,
969 .hooknum = NF_INET_PRE_ROUTING,
970 .priority = NF_IP6_PRI_NAT_DST,
971 },
972 /* After packet filtering, change source */
973 {
974 .hook = nf_nat_ipv6_out,
975 .pf = NFPROTO_IPV6,
976 .hooknum = NF_INET_POST_ROUTING,
977 .priority = NF_IP6_PRI_NAT_SRC,
978 },
979 /* Before packet filtering, change destination */
980 {
981 .hook = nf_nat_ipv6_local_fn,
982 .pf = NFPROTO_IPV6,
983 .hooknum = NF_INET_LOCAL_OUT,
984 .priority = NF_IP6_PRI_NAT_DST,
985 },
986 /* After packet filtering, change source */
987 {
988 .hook = nf_nat_ipv6_fn,
989 .pf = NFPROTO_IPV6,
990 .hooknum = NF_INET_LOCAL_IN,
991 .priority = NF_IP6_PRI_NAT_SRC,
992 },
993 };
994
nf_nat_ipv6_register_fn(struct net * net,const struct nf_hook_ops * ops)995 int nf_nat_ipv6_register_fn(struct net *net, const struct nf_hook_ops *ops)
996 {
997 return nf_nat_register_fn(net, ops->pf, ops, nf_nat_ipv6_ops,
998 ARRAY_SIZE(nf_nat_ipv6_ops));
999 }
1000 EXPORT_SYMBOL_GPL(nf_nat_ipv6_register_fn);
1001
nf_nat_ipv6_unregister_fn(struct net * net,const struct nf_hook_ops * ops)1002 void nf_nat_ipv6_unregister_fn(struct net *net, const struct nf_hook_ops *ops)
1003 {
1004 nf_nat_unregister_fn(net, ops->pf, ops, ARRAY_SIZE(nf_nat_ipv6_ops));
1005 }
1006 EXPORT_SYMBOL_GPL(nf_nat_ipv6_unregister_fn);
1007 #endif /* CONFIG_IPV6 */
1008
1009 #if defined(CONFIG_NF_TABLES_INET) && IS_ENABLED(CONFIG_NFT_NAT)
nf_nat_inet_register_fn(struct net * net,const struct nf_hook_ops * ops)1010 int nf_nat_inet_register_fn(struct net *net, const struct nf_hook_ops *ops)
1011 {
1012 int ret;
1013
1014 if (WARN_ON_ONCE(ops->pf != NFPROTO_INET))
1015 return -EINVAL;
1016
1017 ret = nf_nat_register_fn(net, NFPROTO_IPV6, ops, nf_nat_ipv6_ops,
1018 ARRAY_SIZE(nf_nat_ipv6_ops));
1019 if (ret)
1020 return ret;
1021
1022 ret = nf_nat_register_fn(net, NFPROTO_IPV4, ops, nf_nat_ipv4_ops,
1023 ARRAY_SIZE(nf_nat_ipv4_ops));
1024 if (ret)
1025 nf_nat_ipv6_unregister_fn(net, ops);
1026
1027 return ret;
1028 }
1029 EXPORT_SYMBOL_GPL(nf_nat_inet_register_fn);
1030
nf_nat_inet_unregister_fn(struct net * net,const struct nf_hook_ops * ops)1031 void nf_nat_inet_unregister_fn(struct net *net, const struct nf_hook_ops *ops)
1032 {
1033 nf_nat_unregister_fn(net, NFPROTO_IPV4, ops, ARRAY_SIZE(nf_nat_ipv4_ops));
1034 nf_nat_unregister_fn(net, NFPROTO_IPV6, ops, ARRAY_SIZE(nf_nat_ipv6_ops));
1035 }
1036 EXPORT_SYMBOL_GPL(nf_nat_inet_unregister_fn);
1037 #endif /* NFT INET NAT */
1038