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>
6 #include <linux/types.h>
7 #include <linux/export.h>
8 #include <linux/init.h>
10 #include <linux/tcp.h>
11 #include <linux/icmp.h>
12 #include <linux/icmpv6.h>
14 #include <linux/dccp.h>
15 #include <linux/sctp.h>
16 #include <net/sctp/checksum.h>
18 #include <linux/netfilter.h>
19 #include <net/netfilter/nf_nat.h>
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>
29 #include <net/netfilter/nf_conntrack_core.h>
30 #include <net/netfilter/nf_conntrack.h>
31 #include <linux/netfilter/nfnetlink_conntrack.h>
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);
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)
44 __be16 *portptr, newport;
46 if (maniptype == NF_NAT_MANIP_SRC) {
47 /* Get rid of src port */
48 newport = tuple->src.u.udp.port;
49 portptr = &hdr->source;
51 /* Get rid of dst port */
52 newport = tuple->dst.u.udp.port;
56 nf_csum_update(skb, iphdroff, &hdr->check, tuple, maniptype);
57 inet_proto_csum_replace2(&hdr->check, skb, *portptr, newport,
60 hdr->check = CSUM_MANGLED_0;
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)
72 if (skb_ensure_writable(skb, hdroff + sizeof(*hdr)))
75 hdr = (struct udphdr *)(skb->data + hdroff);
76 __udp_manip_pkt(skb, iphdroff, hdr, tuple, maniptype, !!hdr->check);
81 static bool udplite_manip_pkt(struct sk_buff *skb,
82 unsigned int iphdroff, unsigned int hdroff,
83 const struct nf_conntrack_tuple *tuple,
84 enum nf_nat_manip_type maniptype)
86 #ifdef CONFIG_NF_CT_PROTO_UDPLITE
89 if (skb_ensure_writable(skb, hdroff + sizeof(*hdr)))
92 hdr = (struct udphdr *)(skb->data + hdroff);
93 __udp_manip_pkt(skb, iphdroff, hdr, tuple, maniptype, true);
99 sctp_manip_pkt(struct sk_buff *skb,
100 unsigned int iphdroff, unsigned int hdroff,
101 const struct nf_conntrack_tuple *tuple,
102 enum nf_nat_manip_type maniptype)
104 #ifdef CONFIG_NF_CT_PROTO_SCTP
108 /* This could be an inner header returned in imcp packet; in such
109 * cases we cannot update the checksum field since it is outside
110 * of the 8 bytes of transport layer headers we are guaranteed.
112 if (skb->len >= hdroff + sizeof(*hdr))
113 hdrsize = sizeof(*hdr);
115 if (skb_ensure_writable(skb, hdroff + hdrsize))
118 hdr = (struct sctphdr *)(skb->data + hdroff);
120 if (maniptype == NF_NAT_MANIP_SRC) {
121 /* Get rid of src port */
122 hdr->source = tuple->src.u.sctp.port;
124 /* Get rid of dst port */
125 hdr->dest = tuple->dst.u.sctp.port;
128 if (hdrsize < sizeof(*hdr))
131 if (skb->ip_summed != CHECKSUM_PARTIAL) {
132 hdr->checksum = sctp_compute_cksum(skb, hdroff);
133 skb->ip_summed = CHECKSUM_NONE;
141 tcp_manip_pkt(struct sk_buff *skb,
142 unsigned int iphdroff, unsigned int hdroff,
143 const struct nf_conntrack_tuple *tuple,
144 enum nf_nat_manip_type maniptype)
147 __be16 *portptr, newport, oldport;
148 int hdrsize = 8; /* TCP connection tracking guarantees this much */
150 /* this could be a inner header returned in icmp packet; in such
151 cases we cannot update the checksum field since it is outside of
152 the 8 bytes of transport layer headers we are guaranteed */
153 if (skb->len >= hdroff + sizeof(struct tcphdr))
154 hdrsize = sizeof(struct tcphdr);
156 if (skb_ensure_writable(skb, hdroff + hdrsize))
159 hdr = (struct tcphdr *)(skb->data + hdroff);
161 if (maniptype == NF_NAT_MANIP_SRC) {
162 /* Get rid of src port */
163 newport = tuple->src.u.tcp.port;
164 portptr = &hdr->source;
166 /* Get rid of dst port */
167 newport = tuple->dst.u.tcp.port;
168 portptr = &hdr->dest;
174 if (hdrsize < sizeof(*hdr))
177 nf_csum_update(skb, iphdroff, &hdr->check, tuple, maniptype);
178 inet_proto_csum_replace2(&hdr->check, skb, oldport, newport, false);
183 dccp_manip_pkt(struct sk_buff *skb,
184 unsigned int iphdroff, unsigned int hdroff,
185 const struct nf_conntrack_tuple *tuple,
186 enum nf_nat_manip_type maniptype)
188 #ifdef CONFIG_NF_CT_PROTO_DCCP
189 struct dccp_hdr *hdr;
190 __be16 *portptr, oldport, newport;
191 int hdrsize = 8; /* DCCP connection tracking guarantees this much */
193 if (skb->len >= hdroff + sizeof(struct dccp_hdr))
194 hdrsize = sizeof(struct dccp_hdr);
196 if (skb_ensure_writable(skb, hdroff + hdrsize))
199 hdr = (struct dccp_hdr *)(skb->data + hdroff);
201 if (maniptype == NF_NAT_MANIP_SRC) {
202 newport = tuple->src.u.dccp.port;
203 portptr = &hdr->dccph_sport;
205 newport = tuple->dst.u.dccp.port;
206 portptr = &hdr->dccph_dport;
212 if (hdrsize < sizeof(*hdr))
215 nf_csum_update(skb, iphdroff, &hdr->dccph_checksum, tuple, maniptype);
216 inet_proto_csum_replace2(&hdr->dccph_checksum, skb, oldport, newport,
223 icmp_manip_pkt(struct sk_buff *skb,
224 unsigned int iphdroff, unsigned int hdroff,
225 const struct nf_conntrack_tuple *tuple,
226 enum nf_nat_manip_type maniptype)
230 if (skb_ensure_writable(skb, hdroff + sizeof(*hdr)))
233 hdr = (struct icmphdr *)(skb->data + hdroff);
238 case ICMP_TIMESTAMPREPLY:
239 case ICMP_INFO_REQUEST:
240 case ICMP_INFO_REPLY:
242 case ICMP_ADDRESSREPLY:
247 inet_proto_csum_replace2(&hdr->checksum, skb,
248 hdr->un.echo.id, tuple->src.u.icmp.id, false);
249 hdr->un.echo.id = tuple->src.u.icmp.id;
254 icmpv6_manip_pkt(struct sk_buff *skb,
255 unsigned int iphdroff, unsigned int hdroff,
256 const struct nf_conntrack_tuple *tuple,
257 enum nf_nat_manip_type maniptype)
259 struct icmp6hdr *hdr;
261 if (skb_ensure_writable(skb, hdroff + sizeof(*hdr)))
264 hdr = (struct icmp6hdr *)(skb->data + hdroff);
265 nf_csum_update(skb, iphdroff, &hdr->icmp6_cksum, tuple, maniptype);
266 if (hdr->icmp6_type == ICMPV6_ECHO_REQUEST ||
267 hdr->icmp6_type == ICMPV6_ECHO_REPLY) {
268 inet_proto_csum_replace2(&hdr->icmp6_cksum, skb,
269 hdr->icmp6_identifier,
270 tuple->src.u.icmp.id, false);
271 hdr->icmp6_identifier = tuple->src.u.icmp.id;
276 /* manipulate a GRE packet according to maniptype */
278 gre_manip_pkt(struct sk_buff *skb,
279 unsigned int iphdroff, unsigned int hdroff,
280 const struct nf_conntrack_tuple *tuple,
281 enum nf_nat_manip_type maniptype)
283 #if IS_ENABLED(CONFIG_NF_CT_PROTO_GRE)
284 const struct gre_base_hdr *greh;
285 struct pptp_gre_header *pgreh;
287 /* pgreh includes two optional 32bit fields which are not required
288 * to be there. That's where the magic '8' comes from */
289 if (skb_ensure_writable(skb, hdroff + sizeof(*pgreh) - 8))
292 greh = (void *)skb->data + hdroff;
293 pgreh = (struct pptp_gre_header *)greh;
295 /* we only have destination manip of a packet, since 'source key'
296 * is not present in the packet itself */
297 if (maniptype != NF_NAT_MANIP_DST)
300 switch (greh->flags & GRE_VERSION) {
302 /* We do not currently NAT any GREv0 packets.
303 * Try to behave like "nf_nat_proto_unknown" */
306 pr_debug("call_id -> 0x%04x\n", ntohs(tuple->dst.u.gre.key));
307 pgreh->call_id = tuple->dst.u.gre.key;
310 pr_debug("can't nat unknown GRE version\n");
317 static bool l4proto_manip_pkt(struct sk_buff *skb,
318 unsigned int iphdroff, unsigned int hdroff,
319 const struct nf_conntrack_tuple *tuple,
320 enum nf_nat_manip_type maniptype)
322 switch (tuple->dst.protonum) {
324 return tcp_manip_pkt(skb, iphdroff, hdroff,
327 return udp_manip_pkt(skb, iphdroff, hdroff,
329 case IPPROTO_UDPLITE:
330 return udplite_manip_pkt(skb, iphdroff, hdroff,
333 return sctp_manip_pkt(skb, iphdroff, hdroff,
336 return icmp_manip_pkt(skb, iphdroff, hdroff,
339 return icmpv6_manip_pkt(skb, iphdroff, hdroff,
342 return dccp_manip_pkt(skb, iphdroff, hdroff,
345 return gre_manip_pkt(skb, iphdroff, hdroff,
349 /* If we don't know protocol -- no error, pass it unmodified. */
353 static bool nf_nat_ipv4_manip_pkt(struct sk_buff *skb,
354 unsigned int iphdroff,
355 const struct nf_conntrack_tuple *target,
356 enum nf_nat_manip_type maniptype)
361 if (skb_ensure_writable(skb, iphdroff + sizeof(*iph)))
364 iph = (void *)skb->data + iphdroff;
365 hdroff = iphdroff + iph->ihl * 4;
367 if (!l4proto_manip_pkt(skb, iphdroff, hdroff, target, maniptype))
369 iph = (void *)skb->data + iphdroff;
371 if (maniptype == NF_NAT_MANIP_SRC) {
372 csum_replace4(&iph->check, iph->saddr, target->src.u3.ip);
373 iph->saddr = target->src.u3.ip;
375 csum_replace4(&iph->check, iph->daddr, target->dst.u3.ip);
376 iph->daddr = target->dst.u3.ip;
381 static bool nf_nat_ipv6_manip_pkt(struct sk_buff *skb,
382 unsigned int iphdroff,
383 const struct nf_conntrack_tuple *target,
384 enum nf_nat_manip_type maniptype)
386 #if IS_ENABLED(CONFIG_IPV6)
387 struct ipv6hdr *ipv6h;
392 if (skb_ensure_writable(skb, iphdroff + sizeof(*ipv6h)))
395 ipv6h = (void *)skb->data + iphdroff;
396 nexthdr = ipv6h->nexthdr;
397 hdroff = ipv6_skip_exthdr(skb, iphdroff + sizeof(*ipv6h),
398 &nexthdr, &frag_off);
402 if ((frag_off & htons(~0x7)) == 0 &&
403 !l4proto_manip_pkt(skb, iphdroff, hdroff, target, maniptype))
406 /* must reload, offset might have changed */
407 ipv6h = (void *)skb->data + iphdroff;
410 if (maniptype == NF_NAT_MANIP_SRC)
411 ipv6h->saddr = target->src.u3.in6;
413 ipv6h->daddr = target->dst.u3.in6;
419 unsigned int nf_nat_manip_pkt(struct sk_buff *skb, struct nf_conn *ct,
420 enum nf_nat_manip_type mtype,
421 enum ip_conntrack_dir dir)
423 struct nf_conntrack_tuple target;
425 /* We are aiming to look like inverse of other direction. */
426 nf_ct_invert_tuple(&target, &ct->tuplehash[!dir].tuple);
428 switch (target.src.l3num) {
430 if (nf_nat_ipv6_manip_pkt(skb, 0, &target, mtype))
434 if (nf_nat_ipv4_manip_pkt(skb, 0, &target, mtype))
445 static void nf_nat_ipv4_csum_update(struct sk_buff *skb,
446 unsigned int iphdroff, __sum16 *check,
447 const struct nf_conntrack_tuple *t,
448 enum nf_nat_manip_type maniptype)
450 struct iphdr *iph = (struct iphdr *)(skb->data + iphdroff);
453 if (maniptype == NF_NAT_MANIP_SRC) {
455 newip = t->src.u3.ip;
458 newip = t->dst.u3.ip;
460 inet_proto_csum_replace4(check, skb, oldip, newip, true);
463 static void nf_nat_ipv6_csum_update(struct sk_buff *skb,
464 unsigned int iphdroff, __sum16 *check,
465 const struct nf_conntrack_tuple *t,
466 enum nf_nat_manip_type maniptype)
468 #if IS_ENABLED(CONFIG_IPV6)
469 const struct ipv6hdr *ipv6h = (struct ipv6hdr *)(skb->data + iphdroff);
470 const struct in6_addr *oldip, *newip;
472 if (maniptype == NF_NAT_MANIP_SRC) {
473 oldip = &ipv6h->saddr;
474 newip = &t->src.u3.in6;
476 oldip = &ipv6h->daddr;
477 newip = &t->dst.u3.in6;
479 inet_proto_csum_replace16(check, skb, oldip->s6_addr32,
480 newip->s6_addr32, true);
484 static void nf_csum_update(struct sk_buff *skb,
485 unsigned int iphdroff, __sum16 *check,
486 const struct nf_conntrack_tuple *t,
487 enum nf_nat_manip_type maniptype)
489 switch (t->src.l3num) {
491 nf_nat_ipv4_csum_update(skb, iphdroff, check, t, maniptype);
494 nf_nat_ipv6_csum_update(skb, iphdroff, check, t, maniptype);
499 static void nf_nat_ipv4_csum_recalc(struct sk_buff *skb,
500 u8 proto, void *data, __sum16 *check,
501 int datalen, int oldlen)
503 if (skb->ip_summed != CHECKSUM_PARTIAL) {
504 const struct iphdr *iph = ip_hdr(skb);
506 skb->ip_summed = CHECKSUM_PARTIAL;
507 skb->csum_start = skb_headroom(skb) + skb_network_offset(skb) +
509 skb->csum_offset = (void *)check - data;
510 *check = ~csum_tcpudp_magic(iph->saddr, iph->daddr, datalen,
513 inet_proto_csum_replace2(check, skb,
514 htons(oldlen), htons(datalen), true);
518 #if IS_ENABLED(CONFIG_IPV6)
519 static void nf_nat_ipv6_csum_recalc(struct sk_buff *skb,
520 u8 proto, void *data, __sum16 *check,
521 int datalen, int oldlen)
523 if (skb->ip_summed != CHECKSUM_PARTIAL) {
524 const struct ipv6hdr *ipv6h = ipv6_hdr(skb);
526 skb->ip_summed = CHECKSUM_PARTIAL;
527 skb->csum_start = skb_headroom(skb) + skb_network_offset(skb) +
528 (data - (void *)skb->data);
529 skb->csum_offset = (void *)check - data;
530 *check = ~csum_ipv6_magic(&ipv6h->saddr, &ipv6h->daddr,
533 inet_proto_csum_replace2(check, skb,
534 htons(oldlen), htons(datalen), true);
539 void nf_nat_csum_recalc(struct sk_buff *skb,
540 u8 nfproto, u8 proto, void *data, __sum16 *check,
541 int datalen, int oldlen)
545 nf_nat_ipv4_csum_recalc(skb, proto, data, check,
548 #if IS_ENABLED(CONFIG_IPV6)
550 nf_nat_ipv6_csum_recalc(skb, proto, data, check,
559 int nf_nat_icmp_reply_translation(struct sk_buff *skb,
561 enum ip_conntrack_info ctinfo,
562 unsigned int hooknum)
568 enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
569 enum nf_nat_manip_type manip = HOOK2MANIP(hooknum);
570 unsigned int hdrlen = ip_hdrlen(skb);
571 struct nf_conntrack_tuple target;
572 unsigned long statusbit;
574 WARN_ON(ctinfo != IP_CT_RELATED && ctinfo != IP_CT_RELATED_REPLY);
576 if (skb_ensure_writable(skb, hdrlen + sizeof(*inside)))
578 if (nf_ip_checksum(skb, hooknum, hdrlen, IPPROTO_ICMP))
581 inside = (void *)skb->data + hdrlen;
582 if (inside->icmp.type == ICMP_REDIRECT) {
583 if ((ct->status & IPS_NAT_DONE_MASK) != IPS_NAT_DONE_MASK)
585 if (ct->status & IPS_NAT_MASK)
589 if (manip == NF_NAT_MANIP_SRC)
590 statusbit = IPS_SRC_NAT;
592 statusbit = IPS_DST_NAT;
594 /* Invert if this is reply direction */
595 if (dir == IP_CT_DIR_REPLY)
596 statusbit ^= IPS_NAT_MASK;
598 if (!(ct->status & statusbit))
601 if (!nf_nat_ipv4_manip_pkt(skb, hdrlen + sizeof(inside->icmp),
602 &ct->tuplehash[!dir].tuple, !manip))
605 if (skb->ip_summed != CHECKSUM_PARTIAL) {
606 /* Reloading "inside" here since manip_pkt may reallocate */
607 inside = (void *)skb->data + hdrlen;
608 inside->icmp.checksum = 0;
609 inside->icmp.checksum =
610 csum_fold(skb_checksum(skb, hdrlen,
611 skb->len - hdrlen, 0));
614 /* Change outer to look like the reply to an incoming packet */
615 nf_ct_invert_tuple(&target, &ct->tuplehash[!dir].tuple);
616 target.dst.protonum = IPPROTO_ICMP;
617 if (!nf_nat_ipv4_manip_pkt(skb, 0, &target, manip))
622 EXPORT_SYMBOL_GPL(nf_nat_icmp_reply_translation);
625 nf_nat_ipv4_fn(void *priv, struct sk_buff *skb,
626 const struct nf_hook_state *state)
629 enum ip_conntrack_info ctinfo;
631 ct = nf_ct_get(skb, &ctinfo);
635 if (ctinfo == IP_CT_RELATED || ctinfo == IP_CT_RELATED_REPLY) {
636 if (ip_hdr(skb)->protocol == IPPROTO_ICMP) {
637 if (!nf_nat_icmp_reply_translation(skb, ct, ctinfo,
645 return nf_nat_inet_fn(priv, skb, state);
649 nf_nat_ipv4_in(void *priv, struct sk_buff *skb,
650 const struct nf_hook_state *state)
653 __be32 daddr = ip_hdr(skb)->daddr;
655 ret = nf_nat_ipv4_fn(priv, skb, state);
656 if (ret == NF_ACCEPT && daddr != ip_hdr(skb)->daddr)
663 nf_nat_ipv4_out(void *priv, struct sk_buff *skb,
664 const struct nf_hook_state *state)
667 const struct nf_conn *ct;
668 enum ip_conntrack_info ctinfo;
673 ret = nf_nat_ipv4_fn(priv, skb, state);
675 if (ret != NF_ACCEPT)
678 if (IPCB(skb)->flags & IPSKB_XFRM_TRANSFORMED)
681 ct = nf_ct_get(skb, &ctinfo);
683 enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
685 if (ct->tuplehash[dir].tuple.src.u3.ip !=
686 ct->tuplehash[!dir].tuple.dst.u3.ip ||
687 (ct->tuplehash[dir].tuple.dst.protonum != IPPROTO_ICMP &&
688 ct->tuplehash[dir].tuple.src.u.all !=
689 ct->tuplehash[!dir].tuple.dst.u.all)) {
690 err = nf_xfrm_me_harder(state->net, skb, AF_INET);
692 ret = NF_DROP_ERR(err);
700 nf_nat_ipv4_local_fn(void *priv, struct sk_buff *skb,
701 const struct nf_hook_state *state)
703 const struct nf_conn *ct;
704 enum ip_conntrack_info ctinfo;
708 ret = nf_nat_ipv4_fn(priv, skb, state);
709 if (ret != NF_ACCEPT)
712 ct = nf_ct_get(skb, &ctinfo);
714 enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
716 if (ct->tuplehash[dir].tuple.dst.u3.ip !=
717 ct->tuplehash[!dir].tuple.src.u3.ip) {
718 err = ip_route_me_harder(state->net, state->sk, skb, RTN_UNSPEC);
720 ret = NF_DROP_ERR(err);
723 else if (!(IPCB(skb)->flags & IPSKB_XFRM_TRANSFORMED) &&
724 ct->tuplehash[dir].tuple.dst.protonum != IPPROTO_ICMP &&
725 ct->tuplehash[dir].tuple.dst.u.all !=
726 ct->tuplehash[!dir].tuple.src.u.all) {
727 err = nf_xfrm_me_harder(state->net, skb, AF_INET);
729 ret = NF_DROP_ERR(err);
736 static const struct nf_hook_ops nf_nat_ipv4_ops[] = {
737 /* Before packet filtering, change destination */
739 .hook = nf_nat_ipv4_in,
741 .hooknum = NF_INET_PRE_ROUTING,
742 .priority = NF_IP_PRI_NAT_DST,
744 /* After packet filtering, change source */
746 .hook = nf_nat_ipv4_out,
748 .hooknum = NF_INET_POST_ROUTING,
749 .priority = NF_IP_PRI_NAT_SRC,
751 /* Before packet filtering, change destination */
753 .hook = nf_nat_ipv4_local_fn,
755 .hooknum = NF_INET_LOCAL_OUT,
756 .priority = NF_IP_PRI_NAT_DST,
758 /* After packet filtering, change source */
760 .hook = nf_nat_ipv4_fn,
762 .hooknum = NF_INET_LOCAL_IN,
763 .priority = NF_IP_PRI_NAT_SRC,
767 int nf_nat_ipv4_register_fn(struct net *net, const struct nf_hook_ops *ops)
769 return nf_nat_register_fn(net, ops->pf, ops, nf_nat_ipv4_ops,
770 ARRAY_SIZE(nf_nat_ipv4_ops));
772 EXPORT_SYMBOL_GPL(nf_nat_ipv4_register_fn);
774 void nf_nat_ipv4_unregister_fn(struct net *net, const struct nf_hook_ops *ops)
776 nf_nat_unregister_fn(net, ops->pf, ops, ARRAY_SIZE(nf_nat_ipv4_ops));
778 EXPORT_SYMBOL_GPL(nf_nat_ipv4_unregister_fn);
780 #if IS_ENABLED(CONFIG_IPV6)
781 int nf_nat_icmpv6_reply_translation(struct sk_buff *skb,
783 enum ip_conntrack_info ctinfo,
784 unsigned int hooknum,
788 struct icmp6hdr icmp6;
791 enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
792 enum nf_nat_manip_type manip = HOOK2MANIP(hooknum);
793 struct nf_conntrack_tuple target;
794 unsigned long statusbit;
796 WARN_ON(ctinfo != IP_CT_RELATED && ctinfo != IP_CT_RELATED_REPLY);
798 if (skb_ensure_writable(skb, hdrlen + sizeof(*inside)))
800 if (nf_ip6_checksum(skb, hooknum, hdrlen, IPPROTO_ICMPV6))
803 inside = (void *)skb->data + hdrlen;
804 if (inside->icmp6.icmp6_type == NDISC_REDIRECT) {
805 if ((ct->status & IPS_NAT_DONE_MASK) != IPS_NAT_DONE_MASK)
807 if (ct->status & IPS_NAT_MASK)
811 if (manip == NF_NAT_MANIP_SRC)
812 statusbit = IPS_SRC_NAT;
814 statusbit = IPS_DST_NAT;
816 /* Invert if this is reply direction */
817 if (dir == IP_CT_DIR_REPLY)
818 statusbit ^= IPS_NAT_MASK;
820 if (!(ct->status & statusbit))
823 if (!nf_nat_ipv6_manip_pkt(skb, hdrlen + sizeof(inside->icmp6),
824 &ct->tuplehash[!dir].tuple, !manip))
827 if (skb->ip_summed != CHECKSUM_PARTIAL) {
828 struct ipv6hdr *ipv6h = ipv6_hdr(skb);
830 inside = (void *)skb->data + hdrlen;
831 inside->icmp6.icmp6_cksum = 0;
832 inside->icmp6.icmp6_cksum =
833 csum_ipv6_magic(&ipv6h->saddr, &ipv6h->daddr,
834 skb->len - hdrlen, IPPROTO_ICMPV6,
835 skb_checksum(skb, hdrlen,
836 skb->len - hdrlen, 0));
839 nf_ct_invert_tuple(&target, &ct->tuplehash[!dir].tuple);
840 target.dst.protonum = IPPROTO_ICMPV6;
841 if (!nf_nat_ipv6_manip_pkt(skb, 0, &target, manip))
846 EXPORT_SYMBOL_GPL(nf_nat_icmpv6_reply_translation);
849 nf_nat_ipv6_fn(void *priv, struct sk_buff *skb,
850 const struct nf_hook_state *state)
853 enum ip_conntrack_info ctinfo;
858 ct = nf_ct_get(skb, &ctinfo);
859 /* Can't track? It's not due to stress, or conntrack would
860 * have dropped it. Hence it's the user's responsibilty to
861 * packet filter it out, or implement conntrack/NAT for that
867 if (ctinfo == IP_CT_RELATED || ctinfo == IP_CT_RELATED_REPLY) {
868 nexthdr = ipv6_hdr(skb)->nexthdr;
869 hdrlen = ipv6_skip_exthdr(skb, sizeof(struct ipv6hdr),
870 &nexthdr, &frag_off);
872 if (hdrlen >= 0 && nexthdr == IPPROTO_ICMPV6) {
873 if (!nf_nat_icmpv6_reply_translation(skb, ct, ctinfo,
882 return nf_nat_inet_fn(priv, skb, state);
886 nf_nat_ipv6_in(void *priv, struct sk_buff *skb,
887 const struct nf_hook_state *state)
890 struct in6_addr daddr = ipv6_hdr(skb)->daddr;
892 ret = nf_nat_ipv6_fn(priv, skb, state);
893 if (ret != NF_DROP && ret != NF_STOLEN &&
894 ipv6_addr_cmp(&daddr, &ipv6_hdr(skb)->daddr))
901 nf_nat_ipv6_out(void *priv, struct sk_buff *skb,
902 const struct nf_hook_state *state)
905 const struct nf_conn *ct;
906 enum ip_conntrack_info ctinfo;
911 ret = nf_nat_ipv6_fn(priv, skb, state);
913 if (ret != NF_ACCEPT)
916 if (IP6CB(skb)->flags & IP6SKB_XFRM_TRANSFORMED)
918 ct = nf_ct_get(skb, &ctinfo);
920 enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
922 if (!nf_inet_addr_cmp(&ct->tuplehash[dir].tuple.src.u3,
923 &ct->tuplehash[!dir].tuple.dst.u3) ||
924 (ct->tuplehash[dir].tuple.dst.protonum != IPPROTO_ICMPV6 &&
925 ct->tuplehash[dir].tuple.src.u.all !=
926 ct->tuplehash[!dir].tuple.dst.u.all)) {
927 err = nf_xfrm_me_harder(state->net, skb, AF_INET6);
929 ret = NF_DROP_ERR(err);
938 nf_nat_ipv6_local_fn(void *priv, struct sk_buff *skb,
939 const struct nf_hook_state *state)
941 const struct nf_conn *ct;
942 enum ip_conntrack_info ctinfo;
946 ret = nf_nat_ipv6_fn(priv, skb, state);
947 if (ret != NF_ACCEPT)
950 ct = nf_ct_get(skb, &ctinfo);
952 enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
954 if (!nf_inet_addr_cmp(&ct->tuplehash[dir].tuple.dst.u3,
955 &ct->tuplehash[!dir].tuple.src.u3)) {
956 err = nf_ip6_route_me_harder(state->net, state->sk, skb);
958 ret = NF_DROP_ERR(err);
961 else if (!(IP6CB(skb)->flags & IP6SKB_XFRM_TRANSFORMED) &&
962 ct->tuplehash[dir].tuple.dst.protonum != IPPROTO_ICMPV6 &&
963 ct->tuplehash[dir].tuple.dst.u.all !=
964 ct->tuplehash[!dir].tuple.src.u.all) {
965 err = nf_xfrm_me_harder(state->net, skb, AF_INET6);
967 ret = NF_DROP_ERR(err);
975 static const struct nf_hook_ops nf_nat_ipv6_ops[] = {
976 /* Before packet filtering, change destination */
978 .hook = nf_nat_ipv6_in,
980 .hooknum = NF_INET_PRE_ROUTING,
981 .priority = NF_IP6_PRI_NAT_DST,
983 /* After packet filtering, change source */
985 .hook = nf_nat_ipv6_out,
987 .hooknum = NF_INET_POST_ROUTING,
988 .priority = NF_IP6_PRI_NAT_SRC,
990 /* Before packet filtering, change destination */
992 .hook = nf_nat_ipv6_local_fn,
994 .hooknum = NF_INET_LOCAL_OUT,
995 .priority = NF_IP6_PRI_NAT_DST,
997 /* After packet filtering, change source */
999 .hook = nf_nat_ipv6_fn,
1001 .hooknum = NF_INET_LOCAL_IN,
1002 .priority = NF_IP6_PRI_NAT_SRC,
1006 int nf_nat_ipv6_register_fn(struct net *net, const struct nf_hook_ops *ops)
1008 return nf_nat_register_fn(net, ops->pf, ops, nf_nat_ipv6_ops,
1009 ARRAY_SIZE(nf_nat_ipv6_ops));
1011 EXPORT_SYMBOL_GPL(nf_nat_ipv6_register_fn);
1013 void nf_nat_ipv6_unregister_fn(struct net *net, const struct nf_hook_ops *ops)
1015 nf_nat_unregister_fn(net, ops->pf, ops, ARRAY_SIZE(nf_nat_ipv6_ops));
1017 EXPORT_SYMBOL_GPL(nf_nat_ipv6_unregister_fn);
1018 #endif /* CONFIG_IPV6 */
1020 #if defined(CONFIG_NF_TABLES_INET) && IS_ENABLED(CONFIG_NFT_NAT)
1021 int nf_nat_inet_register_fn(struct net *net, const struct nf_hook_ops *ops)
1025 if (WARN_ON_ONCE(ops->pf != NFPROTO_INET))
1028 ret = nf_nat_register_fn(net, NFPROTO_IPV6, ops, nf_nat_ipv6_ops,
1029 ARRAY_SIZE(nf_nat_ipv6_ops));
1033 ret = nf_nat_register_fn(net, NFPROTO_IPV4, ops, nf_nat_ipv4_ops,
1034 ARRAY_SIZE(nf_nat_ipv4_ops));
1036 nf_nat_unregister_fn(net, NFPROTO_IPV6, ops,
1037 ARRAY_SIZE(nf_nat_ipv6_ops));
1040 EXPORT_SYMBOL_GPL(nf_nat_inet_register_fn);
1042 void nf_nat_inet_unregister_fn(struct net *net, const struct nf_hook_ops *ops)
1044 nf_nat_unregister_fn(net, NFPROTO_IPV4, ops, ARRAY_SIZE(nf_nat_ipv4_ops));
1045 nf_nat_unregister_fn(net, NFPROTO_IPV6, ops, ARRAY_SIZE(nf_nat_ipv6_ops));
1047 EXPORT_SYMBOL_GPL(nf_nat_inet_unregister_fn);
1048 #endif /* NFT INET NAT */