Merge branches 'acpi-tables', 'acpi-osl', 'acpi-misc' and 'acpi-tools'
[sfrench/cifs-2.6.git] / net / netfilter / nf_nat_proto.c
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
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
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_make_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
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_make_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
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_make_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
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_make_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
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_make_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
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_make_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
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_make_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
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_make_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
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
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_make_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
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_make_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
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
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
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
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
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)
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
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
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_make_writable(skb, hdrlen + sizeof(*inside)))
566                 return 0;
567         if (nf_ip_checksum(skb, hooknum, hdrlen, 0))
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
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
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
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
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 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
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
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)
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_make_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
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
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
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
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 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
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
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)
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
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 */