root/net/netfilter/nf_nat_proto.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. __udp_manip_pkt
  2. udp_manip_pkt
  3. udplite_manip_pkt
  4. sctp_manip_pkt
  5. tcp_manip_pkt
  6. dccp_manip_pkt
  7. icmp_manip_pkt
  8. icmpv6_manip_pkt
  9. gre_manip_pkt
  10. l4proto_manip_pkt
  11. nf_nat_ipv4_manip_pkt
  12. nf_nat_ipv6_manip_pkt
  13. nf_nat_manip_pkt
  14. nf_nat_ipv4_csum_update
  15. nf_nat_ipv6_csum_update
  16. nf_csum_update
  17. nf_nat_ipv4_csum_recalc
  18. nf_nat_ipv6_csum_recalc
  19. nf_nat_csum_recalc
  20. nf_nat_icmp_reply_translation
  21. nf_nat_ipv4_fn
  22. nf_nat_ipv4_in
  23. nf_nat_ipv4_out
  24. nf_nat_ipv4_local_fn
  25. nf_nat_ipv4_register_fn
  26. nf_nat_ipv4_unregister_fn
  27. nf_nat_icmpv6_reply_translation
  28. nf_nat_ipv6_fn
  29. nf_nat_ipv6_in
  30. nf_nat_ipv6_out
  31. nf_nat_ipv6_local_fn
  32. nf_nat_ipv6_register_fn
  33. nf_nat_ipv6_unregister_fn
  34. nf_nat_inet_register_fn
  35. nf_nat_inet_unregister_fn

   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 
  72         if (skb_ensure_writable(skb, hdroff + sizeof(*hdr)))
  73                 return false;
  74 
  75         hdr = (struct udphdr *)(skb->data + hdroff);
  76         __udp_manip_pkt(skb, iphdroff, hdr, tuple, maniptype, !!hdr->check);
  77 
  78         return true;
  79 }
  80 
  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)
  85 {
  86 #ifdef CONFIG_NF_CT_PROTO_UDPLITE
  87         struct udphdr *hdr;
  88 
  89         if (skb_ensure_writable(skb, hdroff + sizeof(*hdr)))
  90                 return false;
  91 
  92         hdr = (struct udphdr *)(skb->data + hdroff);
  93         __udp_manip_pkt(skb, iphdroff, hdr, tuple, maniptype, true);
  94 #endif
  95         return true;
  96 }
  97 
  98 static bool
  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)
 103 {
 104 #ifdef CONFIG_NF_CT_PROTO_SCTP
 105         struct sctphdr *hdr;
 106         int hdrsize = 8;
 107 
 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.
 111          */
 112         if (skb->len >= hdroff + sizeof(*hdr))
 113                 hdrsize = sizeof(*hdr);
 114 
 115         if (skb_ensure_writable(skb, hdroff + hdrsize))
 116                 return false;
 117 
 118         hdr = (struct sctphdr *)(skb->data + hdroff);
 119 
 120         if (maniptype == NF_NAT_MANIP_SRC) {
 121                 /* Get rid of src port */
 122                 hdr->source = tuple->src.u.sctp.port;
 123         } else {
 124                 /* Get rid of dst port */
 125                 hdr->dest = tuple->dst.u.sctp.port;
 126         }
 127 
 128         if (hdrsize < sizeof(*hdr))
 129                 return true;
 130 
 131         if (skb->ip_summed != CHECKSUM_PARTIAL) {
 132                 hdr->checksum = sctp_compute_cksum(skb, hdroff);
 133                 skb->ip_summed = CHECKSUM_NONE;
 134         }
 135 
 136 #endif
 137         return true;
 138 }
 139 
 140 static bool
 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)
 145 {
 146         struct tcphdr *hdr;
 147         __be16 *portptr, newport, oldport;
 148         int hdrsize = 8; /* TCP connection tracking guarantees this much */
 149 
 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);
 155 
 156         if (skb_ensure_writable(skb, hdroff + hdrsize))
 157                 return false;
 158 
 159         hdr = (struct tcphdr *)(skb->data + hdroff);
 160 
 161         if (maniptype == NF_NAT_MANIP_SRC) {
 162                 /* Get rid of src port */
 163                 newport = tuple->src.u.tcp.port;
 164                 portptr = &hdr->source;
 165         } else {
 166                 /* Get rid of dst port */
 167                 newport = tuple->dst.u.tcp.port;
 168                 portptr = &hdr->dest;
 169         }
 170 
 171         oldport = *portptr;
 172         *portptr = newport;
 173 
 174         if (hdrsize < sizeof(*hdr))
 175                 return true;
 176 
 177         nf_csum_update(skb, iphdroff, &hdr->check, tuple, maniptype);
 178         inet_proto_csum_replace2(&hdr->check, skb, oldport, newport, false);
 179         return true;
 180 }
 181 
 182 static bool
 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)
 187 {
 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 */
 192 
 193         if (skb->len >= hdroff + sizeof(struct dccp_hdr))
 194                 hdrsize = sizeof(struct dccp_hdr);
 195 
 196         if (skb_ensure_writable(skb, hdroff + hdrsize))
 197                 return false;
 198 
 199         hdr = (struct dccp_hdr *)(skb->data + hdroff);
 200 
 201         if (maniptype == NF_NAT_MANIP_SRC) {
 202                 newport = tuple->src.u.dccp.port;
 203                 portptr = &hdr->dccph_sport;
 204         } else {
 205                 newport = tuple->dst.u.dccp.port;
 206                 portptr = &hdr->dccph_dport;
 207         }
 208 
 209         oldport = *portptr;
 210         *portptr = newport;
 211 
 212         if (hdrsize < sizeof(*hdr))
 213                 return true;
 214 
 215         nf_csum_update(skb, iphdroff, &hdr->dccph_checksum, tuple, maniptype);
 216         inet_proto_csum_replace2(&hdr->dccph_checksum, skb, oldport, newport,
 217                                  false);
 218 #endif
 219         return true;
 220 }
 221 
 222 static bool
 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)
 227 {
 228         struct icmphdr *hdr;
 229 
 230         if (skb_ensure_writable(skb, hdroff + sizeof(*hdr)))
 231                 return false;
 232 
 233         hdr = (struct icmphdr *)(skb->data + hdroff);
 234         switch (hdr->type) {
 235         case ICMP_ECHO:
 236         case ICMP_ECHOREPLY:
 237         case ICMP_TIMESTAMP:
 238         case ICMP_TIMESTAMPREPLY:
 239         case ICMP_INFO_REQUEST:
 240         case ICMP_INFO_REPLY:
 241         case ICMP_ADDRESS:
 242         case ICMP_ADDRESSREPLY:
 243                 break;
 244         default:
 245                 return true;
 246         }
 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;
 250         return true;
 251 }
 252 
 253 static bool
 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)
 258 {
 259         struct icmp6hdr *hdr;
 260 
 261         if (skb_ensure_writable(skb, hdroff + sizeof(*hdr)))
 262                 return false;
 263 
 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;
 272         }
 273         return true;
 274 }
 275 
 276 /* manipulate a GRE packet according to maniptype */
 277 static bool
 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)
 282 {
 283 #if IS_ENABLED(CONFIG_NF_CT_PROTO_GRE)
 284         const struct gre_base_hdr *greh;
 285         struct pptp_gre_header *pgreh;
 286 
 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))
 290                 return false;
 291 
 292         greh = (void *)skb->data + hdroff;
 293         pgreh = (struct pptp_gre_header *)greh;
 294 
 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)
 298                 return true;
 299 
 300         switch (greh->flags & GRE_VERSION) {
 301         case GRE_VERSION_0:
 302                 /* We do not currently NAT any GREv0 packets.
 303                  * Try to behave like "nf_nat_proto_unknown" */
 304                 break;
 305         case GRE_VERSION_1:
 306                 pr_debug("call_id -> 0x%04x\n", ntohs(tuple->dst.u.gre.key));
 307                 pgreh->call_id = tuple->dst.u.gre.key;
 308                 break;
 309         default:
 310                 pr_debug("can't nat unknown GRE version\n");
 311                 return false;
 312         }
 313 #endif
 314         return true;
 315 }
 316 
 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)
 321 {
 322         switch (tuple->dst.protonum) {
 323         case IPPROTO_TCP:
 324                 return tcp_manip_pkt(skb, iphdroff, hdroff,
 325                                      tuple, maniptype);
 326         case IPPROTO_UDP:
 327                 return udp_manip_pkt(skb, iphdroff, hdroff,
 328                                      tuple, maniptype);
 329         case IPPROTO_UDPLITE:
 330                 return udplite_manip_pkt(skb, iphdroff, hdroff,
 331                                          tuple, maniptype);
 332         case IPPROTO_SCTP:
 333                 return sctp_manip_pkt(skb, iphdroff, hdroff,
 334                                       tuple, maniptype);
 335         case IPPROTO_ICMP:
 336                 return icmp_manip_pkt(skb, iphdroff, hdroff,
 337                                       tuple, maniptype);
 338         case IPPROTO_ICMPV6:
 339                 return icmpv6_manip_pkt(skb, iphdroff, hdroff,
 340                                         tuple, maniptype);
 341         case IPPROTO_DCCP:
 342                 return dccp_manip_pkt(skb, iphdroff, hdroff,
 343                                       tuple, maniptype);
 344         case IPPROTO_GRE:
 345                 return gre_manip_pkt(skb, iphdroff, hdroff,
 346                                      tuple, maniptype);
 347         }
 348 
 349         /* If we don't know protocol -- no error, pass it unmodified. */
 350         return true;
 351 }
 352 
 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)
 357 {
 358         struct iphdr *iph;
 359         unsigned int hdroff;
 360 
 361         if (skb_ensure_writable(skb, iphdroff + sizeof(*iph)))
 362                 return false;
 363 
 364         iph = (void *)skb->data + iphdroff;
 365         hdroff = iphdroff + iph->ihl * 4;
 366 
 367         if (!l4proto_manip_pkt(skb, iphdroff, hdroff, target, maniptype))
 368                 return false;
 369         iph = (void *)skb->data + iphdroff;
 370 
 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;
 374         } else {
 375                 csum_replace4(&iph->check, iph->daddr, target->dst.u3.ip);
 376                 iph->daddr = target->dst.u3.ip;
 377         }
 378         return true;
 379 }
 380 
 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)
 385 {
 386 #if IS_ENABLED(CONFIG_IPV6)
 387         struct ipv6hdr *ipv6h;
 388         __be16 frag_off;
 389         int hdroff;
 390         u8 nexthdr;
 391 
 392         if (skb_ensure_writable(skb, iphdroff + sizeof(*ipv6h)))
 393                 return false;
 394 
 395         ipv6h = (void *)skb->data + iphdroff;
 396         nexthdr = ipv6h->nexthdr;
 397         hdroff = ipv6_skip_exthdr(skb, iphdroff + sizeof(*ipv6h),
 398                                   &nexthdr, &frag_off);
 399         if (hdroff < 0)
 400                 goto manip_addr;
 401 
 402         if ((frag_off & htons(~0x7)) == 0 &&
 403             !l4proto_manip_pkt(skb, iphdroff, hdroff, target, maniptype))
 404                 return false;
 405 
 406         /* must reload, offset might have changed */
 407         ipv6h = (void *)skb->data + iphdroff;
 408 
 409 manip_addr:
 410         if (maniptype == NF_NAT_MANIP_SRC)
 411                 ipv6h->saddr = target->src.u3.in6;
 412         else
 413                 ipv6h->daddr = target->dst.u3.in6;
 414 
 415 #endif
 416         return true;
 417 }
 418 
 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)
 422 {
 423         struct nf_conntrack_tuple target;
 424 
 425         /* We are aiming to look like inverse of other direction. */
 426         nf_ct_invert_tuple(&target, &ct->tuplehash[!dir].tuple);
 427 
 428         switch (target.src.l3num) {
 429         case NFPROTO_IPV6:
 430                 if (nf_nat_ipv6_manip_pkt(skb, 0, &target, mtype))
 431                         return NF_ACCEPT;
 432                 break;
 433         case NFPROTO_IPV4:
 434                 if (nf_nat_ipv4_manip_pkt(skb, 0, &target, mtype))
 435                         return NF_ACCEPT;
 436                 break;
 437         default:
 438                 WARN_ON_ONCE(1);
 439                 break;
 440         }
 441 
 442         return NF_DROP;
 443 }
 444 
 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)
 449 {
 450         struct iphdr *iph = (struct iphdr *)(skb->data + iphdroff);
 451         __be32 oldip, newip;
 452 
 453         if (maniptype == NF_NAT_MANIP_SRC) {
 454                 oldip = iph->saddr;
 455                 newip = t->src.u3.ip;
 456         } else {
 457                 oldip = iph->daddr;
 458                 newip = t->dst.u3.ip;
 459         }
 460         inet_proto_csum_replace4(check, skb, oldip, newip, true);
 461 }
 462 
 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)
 467 {
 468 #if IS_ENABLED(CONFIG_IPV6)
 469         const struct ipv6hdr *ipv6h = (struct ipv6hdr *)(skb->data + iphdroff);
 470         const struct in6_addr *oldip, *newip;
 471 
 472         if (maniptype == NF_NAT_MANIP_SRC) {
 473                 oldip = &ipv6h->saddr;
 474                 newip = &t->src.u3.in6;
 475         } else {
 476                 oldip = &ipv6h->daddr;
 477                 newip = &t->dst.u3.in6;
 478         }
 479         inet_proto_csum_replace16(check, skb, oldip->s6_addr32,
 480                                   newip->s6_addr32, true);
 481 #endif
 482 }
 483 
 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)
 488 {
 489         switch (t->src.l3num) {
 490         case NFPROTO_IPV4:
 491                 nf_nat_ipv4_csum_update(skb, iphdroff, check, t, maniptype);
 492                 return;
 493         case NFPROTO_IPV6:
 494                 nf_nat_ipv6_csum_update(skb, iphdroff, check, t, maniptype);
 495                 return;
 496         }
 497 }
 498 
 499 static void nf_nat_ipv4_csum_recalc(struct sk_buff *skb,
 500                                     u8 proto, void *data, __sum16 *check,
 501                                     int datalen, int oldlen)
 502 {
 503         if (skb->ip_summed != CHECKSUM_PARTIAL) {
 504                 const struct iphdr *iph = ip_hdr(skb);
 505 
 506                 skb->ip_summed = CHECKSUM_PARTIAL;
 507                 skb->csum_start = skb_headroom(skb) + skb_network_offset(skb) +
 508                         ip_hdrlen(skb);
 509                 skb->csum_offset = (void *)check - data;
 510                 *check = ~csum_tcpudp_magic(iph->saddr, iph->daddr, datalen,
 511                                             proto, 0);
 512         } else {
 513                 inet_proto_csum_replace2(check, skb,
 514                                          htons(oldlen), htons(datalen), true);
 515         }
 516 }
 517 
 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)
 522 {
 523         if (skb->ip_summed != CHECKSUM_PARTIAL) {
 524                 const struct ipv6hdr *ipv6h = ipv6_hdr(skb);
 525 
 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,
 531                                           datalen, proto, 0);
 532         } else {
 533                 inet_proto_csum_replace2(check, skb,
 534                                          htons(oldlen), htons(datalen), true);
 535         }
 536 }
 537 #endif
 538 
 539 void nf_nat_csum_recalc(struct sk_buff *skb,
 540                         u8 nfproto, u8 proto, void *data, __sum16 *check,
 541                         int datalen, int oldlen)
 542 {
 543         switch (nfproto) {
 544         case NFPROTO_IPV4:
 545                 nf_nat_ipv4_csum_recalc(skb, proto, data, check,
 546                                         datalen, oldlen);
 547                 return;
 548 #if IS_ENABLED(CONFIG_IPV6)
 549         case NFPROTO_IPV6:
 550                 nf_nat_ipv6_csum_recalc(skb, proto, data, check,
 551                                         datalen, oldlen);
 552                 return;
 553 #endif
 554         }
 555 
 556         WARN_ON_ONCE(1);
 557 }
 558 
 559 int nf_nat_icmp_reply_translation(struct sk_buff *skb,
 560                                   struct nf_conn *ct,
 561                                   enum ip_conntrack_info ctinfo,
 562                                   unsigned int hooknum)
 563 {
 564         struct {
 565                 struct icmphdr  icmp;
 566                 struct iphdr    ip;
 567         } *inside;
 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;
 573 
 574         WARN_ON(ctinfo != IP_CT_RELATED && ctinfo != IP_CT_RELATED_REPLY);
 575 
 576         if (skb_ensure_writable(skb, hdrlen + sizeof(*inside)))
 577                 return 0;
 578         if (nf_ip_checksum(skb, hooknum, hdrlen, IPPROTO_ICMP))
 579                 return 0;
 580 
 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)
 584                         return 0;
 585                 if (ct->status & IPS_NAT_MASK)
 586                         return 0;
 587         }
 588 
 589         if (manip == NF_NAT_MANIP_SRC)
 590                 statusbit = IPS_SRC_NAT;
 591         else
 592                 statusbit = IPS_DST_NAT;
 593 
 594         /* Invert if this is reply direction */
 595         if (dir == IP_CT_DIR_REPLY)
 596                 statusbit ^= IPS_NAT_MASK;
 597 
 598         if (!(ct->status & statusbit))
 599                 return 1;
 600 
 601         if (!nf_nat_ipv4_manip_pkt(skb, hdrlen + sizeof(inside->icmp),
 602                                    &ct->tuplehash[!dir].tuple, !manip))
 603                 return 0;
 604 
 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));
 612         }
 613 
 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))
 618                 return 0;
 619 
 620         return 1;
 621 }
 622 EXPORT_SYMBOL_GPL(nf_nat_icmp_reply_translation);
 623 
 624 static unsigned int
 625 nf_nat_ipv4_fn(void *priv, struct sk_buff *skb,
 626                const struct nf_hook_state *state)
 627 {
 628         struct nf_conn *ct;
 629         enum ip_conntrack_info ctinfo;
 630 
 631         ct = nf_ct_get(skb, &ctinfo);
 632         if (!ct)
 633                 return NF_ACCEPT;
 634 
 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,
 638                                                            state->hook))
 639                                 return NF_DROP;
 640                         else
 641                                 return NF_ACCEPT;
 642                 }
 643         }
 644 
 645         return nf_nat_inet_fn(priv, skb, state);
 646 }
 647 
 648 static unsigned int
 649 nf_nat_ipv4_in(void *priv, struct sk_buff *skb,
 650                const struct nf_hook_state *state)
 651 {
 652         unsigned int ret;
 653         __be32 daddr = ip_hdr(skb)->daddr;
 654 
 655         ret = nf_nat_ipv4_fn(priv, skb, state);
 656         if (ret == NF_ACCEPT && daddr != ip_hdr(skb)->daddr)
 657                 skb_dst_drop(skb);
 658 
 659         return ret;
 660 }
 661 
 662 static unsigned int
 663 nf_nat_ipv4_out(void *priv, struct sk_buff *skb,
 664                 const struct nf_hook_state *state)
 665 {
 666 #ifdef CONFIG_XFRM
 667         const struct nf_conn *ct;
 668         enum ip_conntrack_info ctinfo;
 669         int err;
 670 #endif
 671         unsigned int ret;
 672 
 673         ret = nf_nat_ipv4_fn(priv, skb, state);
 674 #ifdef CONFIG_XFRM
 675         if (ret != NF_ACCEPT)
 676                 return ret;
 677 
 678         if (IPCB(skb)->flags & IPSKB_XFRM_TRANSFORMED)
 679                 return ret;
 680 
 681         ct = nf_ct_get(skb, &ctinfo);
 682         if (ct) {
 683                 enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
 684 
 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);
 691                         if (err < 0)
 692                                 ret = NF_DROP_ERR(err);
 693                 }
 694         }
 695 #endif
 696         return ret;
 697 }
 698 
 699 static unsigned int
 700 nf_nat_ipv4_local_fn(void *priv, struct sk_buff *skb,
 701                      const struct nf_hook_state *state)
 702 {
 703         const struct nf_conn *ct;
 704         enum ip_conntrack_info ctinfo;
 705         unsigned int ret;
 706         int err;
 707 
 708         ret = nf_nat_ipv4_fn(priv, skb, state);
 709         if (ret != NF_ACCEPT)
 710                 return ret;
 711 
 712         ct = nf_ct_get(skb, &ctinfo);
 713         if (ct) {
 714                 enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
 715 
 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, skb, RTN_UNSPEC);
 719                         if (err < 0)
 720                                 ret = NF_DROP_ERR(err);
 721                 }
 722 #ifdef CONFIG_XFRM
 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);
 728                         if (err < 0)
 729                                 ret = NF_DROP_ERR(err);
 730                 }
 731 #endif
 732         }
 733         return ret;
 734 }
 735 
 736 static const struct nf_hook_ops nf_nat_ipv4_ops[] = {
 737         /* Before packet filtering, change destination */
 738         {
 739                 .hook           = nf_nat_ipv4_in,
 740                 .pf             = NFPROTO_IPV4,
 741                 .hooknum        = NF_INET_PRE_ROUTING,
 742                 .priority       = NF_IP_PRI_NAT_DST,
 743         },
 744         /* After packet filtering, change source */
 745         {
 746                 .hook           = nf_nat_ipv4_out,
 747                 .pf             = NFPROTO_IPV4,
 748                 .hooknum        = NF_INET_POST_ROUTING,
 749                 .priority       = NF_IP_PRI_NAT_SRC,
 750         },
 751         /* Before packet filtering, change destination */
 752         {
 753                 .hook           = nf_nat_ipv4_local_fn,
 754                 .pf             = NFPROTO_IPV4,
 755                 .hooknum        = NF_INET_LOCAL_OUT,
 756                 .priority       = NF_IP_PRI_NAT_DST,
 757         },
 758         /* After packet filtering, change source */
 759         {
 760                 .hook           = nf_nat_ipv4_fn,
 761                 .pf             = NFPROTO_IPV4,
 762                 .hooknum        = NF_INET_LOCAL_IN,
 763                 .priority       = NF_IP_PRI_NAT_SRC,
 764         },
 765 };
 766 
 767 int nf_nat_ipv4_register_fn(struct net *net, const struct nf_hook_ops *ops)
 768 {
 769         return nf_nat_register_fn(net, ops->pf, ops, nf_nat_ipv4_ops,
 770                                   ARRAY_SIZE(nf_nat_ipv4_ops));
 771 }
 772 EXPORT_SYMBOL_GPL(nf_nat_ipv4_register_fn);
 773 
 774 void nf_nat_ipv4_unregister_fn(struct net *net, const struct nf_hook_ops *ops)
 775 {
 776         nf_nat_unregister_fn(net, ops->pf, ops, ARRAY_SIZE(nf_nat_ipv4_ops));
 777 }
 778 EXPORT_SYMBOL_GPL(nf_nat_ipv4_unregister_fn);
 779 
 780 #if IS_ENABLED(CONFIG_IPV6)
 781 int nf_nat_icmpv6_reply_translation(struct sk_buff *skb,
 782                                     struct nf_conn *ct,
 783                                     enum ip_conntrack_info ctinfo,
 784                                     unsigned int hooknum,
 785                                     unsigned int hdrlen)
 786 {
 787         struct {
 788                 struct icmp6hdr icmp6;
 789                 struct ipv6hdr  ip6;
 790         } *inside;
 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;
 795 
 796         WARN_ON(ctinfo != IP_CT_RELATED && ctinfo != IP_CT_RELATED_REPLY);
 797 
 798         if (skb_ensure_writable(skb, hdrlen + sizeof(*inside)))
 799                 return 0;
 800         if (nf_ip6_checksum(skb, hooknum, hdrlen, IPPROTO_ICMPV6))
 801                 return 0;
 802 
 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)
 806                         return 0;
 807                 if (ct->status & IPS_NAT_MASK)
 808                         return 0;
 809         }
 810 
 811         if (manip == NF_NAT_MANIP_SRC)
 812                 statusbit = IPS_SRC_NAT;
 813         else
 814                 statusbit = IPS_DST_NAT;
 815 
 816         /* Invert if this is reply direction */
 817         if (dir == IP_CT_DIR_REPLY)
 818                 statusbit ^= IPS_NAT_MASK;
 819 
 820         if (!(ct->status & statusbit))
 821                 return 1;
 822 
 823         if (!nf_nat_ipv6_manip_pkt(skb, hdrlen + sizeof(inside->icmp6),
 824                                    &ct->tuplehash[!dir].tuple, !manip))
 825                 return 0;
 826 
 827         if (skb->ip_summed != CHECKSUM_PARTIAL) {
 828                 struct ipv6hdr *ipv6h = ipv6_hdr(skb);
 829 
 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));
 837         }
 838 
 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))
 842                 return 0;
 843 
 844         return 1;
 845 }
 846 EXPORT_SYMBOL_GPL(nf_nat_icmpv6_reply_translation);
 847 
 848 static unsigned int
 849 nf_nat_ipv6_fn(void *priv, struct sk_buff *skb,
 850                const struct nf_hook_state *state)
 851 {
 852         struct nf_conn *ct;
 853         enum ip_conntrack_info ctinfo;
 854         __be16 frag_off;
 855         int hdrlen;
 856         u8 nexthdr;
 857 
 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
 862          * protocol. 8) --RR
 863          */
 864         if (!ct)
 865                 return NF_ACCEPT;
 866 
 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);
 871 
 872                 if (hdrlen >= 0 && nexthdr == IPPROTO_ICMPV6) {
 873                         if (!nf_nat_icmpv6_reply_translation(skb, ct, ctinfo,
 874                                                              state->hook,
 875                                                              hdrlen))
 876                                 return NF_DROP;
 877                         else
 878                                 return NF_ACCEPT;
 879                 }
 880         }
 881 
 882         return nf_nat_inet_fn(priv, skb, state);
 883 }
 884 
 885 static unsigned int
 886 nf_nat_ipv6_in(void *priv, struct sk_buff *skb,
 887                const struct nf_hook_state *state)
 888 {
 889         unsigned int ret;
 890         struct in6_addr daddr = ipv6_hdr(skb)->daddr;
 891 
 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))
 895                 skb_dst_drop(skb);
 896 
 897         return ret;
 898 }
 899 
 900 static unsigned int
 901 nf_nat_ipv6_out(void *priv, struct sk_buff *skb,
 902                 const struct nf_hook_state *state)
 903 {
 904 #ifdef CONFIG_XFRM
 905         const struct nf_conn *ct;
 906         enum ip_conntrack_info ctinfo;
 907         int err;
 908 #endif
 909         unsigned int ret;
 910 
 911         ret = nf_nat_ipv6_fn(priv, skb, state);
 912 #ifdef CONFIG_XFRM
 913         if (ret != NF_ACCEPT)
 914                 return ret;
 915 
 916         if (IP6CB(skb)->flags & IP6SKB_XFRM_TRANSFORMED)
 917                 return ret;
 918         ct = nf_ct_get(skb, &ctinfo);
 919         if (ct) {
 920                 enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
 921 
 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);
 928                         if (err < 0)
 929                                 ret = NF_DROP_ERR(err);
 930                 }
 931         }
 932 #endif
 933 
 934         return ret;
 935 }
 936 
 937 static unsigned int
 938 nf_nat_ipv6_local_fn(void *priv, struct sk_buff *skb,
 939                      const struct nf_hook_state *state)
 940 {
 941         const struct nf_conn *ct;
 942         enum ip_conntrack_info ctinfo;
 943         unsigned int ret;
 944         int err;
 945 
 946         ret = nf_nat_ipv6_fn(priv, skb, state);
 947         if (ret != NF_ACCEPT)
 948                 return ret;
 949 
 950         ct = nf_ct_get(skb, &ctinfo);
 951         if (ct) {
 952                 enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
 953 
 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, skb);
 957                         if (err < 0)
 958                                 ret = NF_DROP_ERR(err);
 959                 }
 960 #ifdef CONFIG_XFRM
 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);
 966                         if (err < 0)
 967                                 ret = NF_DROP_ERR(err);
 968                 }
 969 #endif
 970         }
 971 
 972         return ret;
 973 }
 974 
 975 static const struct nf_hook_ops nf_nat_ipv6_ops[] = {
 976         /* Before packet filtering, change destination */
 977         {
 978                 .hook           = nf_nat_ipv6_in,
 979                 .pf             = NFPROTO_IPV6,
 980                 .hooknum        = NF_INET_PRE_ROUTING,
 981                 .priority       = NF_IP6_PRI_NAT_DST,
 982         },
 983         /* After packet filtering, change source */
 984         {
 985                 .hook           = nf_nat_ipv6_out,
 986                 .pf             = NFPROTO_IPV6,
 987                 .hooknum        = NF_INET_POST_ROUTING,
 988                 .priority       = NF_IP6_PRI_NAT_SRC,
 989         },
 990         /* Before packet filtering, change destination */
 991         {
 992                 .hook           = nf_nat_ipv6_local_fn,
 993                 .pf             = NFPROTO_IPV6,
 994                 .hooknum        = NF_INET_LOCAL_OUT,
 995                 .priority       = NF_IP6_PRI_NAT_DST,
 996         },
 997         /* After packet filtering, change source */
 998         {
 999                 .hook           = nf_nat_ipv6_fn,
1000                 .pf             = NFPROTO_IPV6,
1001                 .hooknum        = NF_INET_LOCAL_IN,
1002                 .priority       = NF_IP6_PRI_NAT_SRC,
1003         },
1004 };
1005 
1006 int nf_nat_ipv6_register_fn(struct net *net, const struct nf_hook_ops *ops)
1007 {
1008         return nf_nat_register_fn(net, ops->pf, ops, nf_nat_ipv6_ops,
1009                                   ARRAY_SIZE(nf_nat_ipv6_ops));
1010 }
1011 EXPORT_SYMBOL_GPL(nf_nat_ipv6_register_fn);
1012 
1013 void nf_nat_ipv6_unregister_fn(struct net *net, const struct nf_hook_ops *ops)
1014 {
1015         nf_nat_unregister_fn(net, ops->pf, ops, ARRAY_SIZE(nf_nat_ipv6_ops));
1016 }
1017 EXPORT_SYMBOL_GPL(nf_nat_ipv6_unregister_fn);
1018 #endif /* CONFIG_IPV6 */
1019 
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)
1022 {
1023         int ret;
1024 
1025         if (WARN_ON_ONCE(ops->pf != NFPROTO_INET))
1026                 return -EINVAL;
1027 
1028         ret = nf_nat_register_fn(net, NFPROTO_IPV6, ops, nf_nat_ipv6_ops,
1029                                  ARRAY_SIZE(nf_nat_ipv6_ops));
1030         if (ret)
1031                 return ret;
1032 
1033         ret = nf_nat_register_fn(net, NFPROTO_IPV4, ops, nf_nat_ipv4_ops,
1034                                  ARRAY_SIZE(nf_nat_ipv4_ops));
1035         if (ret)
1036                 nf_nat_unregister_fn(net, NFPROTO_IPV6, ops,
1037                                         ARRAY_SIZE(nf_nat_ipv6_ops));
1038         return ret;
1039 }
1040 EXPORT_SYMBOL_GPL(nf_nat_inet_register_fn);
1041 
1042 void nf_nat_inet_unregister_fn(struct net *net, const struct nf_hook_ops *ops)
1043 {
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));
1046 }
1047 EXPORT_SYMBOL_GPL(nf_nat_inet_unregister_fn);
1048 #endif /* NFT INET NAT */

/* [<][>][^][v][top][bottom][index][help] */