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