FILE
nf_nat_proto.c
File preview with syntax highlighting.
linux-6.19.14/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 33static 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 38static 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 65static 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 81static 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 98static bool 99sctp_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 140static bool 141tcp_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 182static bool 183icmp_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 struct icmphdr *hdr; 189 190 if (skb_ensure_writable(skb, hdroff + sizeof(*hdr))) 191 return false; 192 193 hdr = (struct icmphdr *)(skb->data + hdroff); 194 switch (hdr->type) { 195 case ICMP_ECHO: 196 case ICMP_ECHOREPLY: 197 case ICMP_TIMESTAMP: 198 case ICMP_TIMESTAMPREPLY: 199 case ICMP_INFO_REQUEST: 200 case ICMP_INFO_REPLY: 201 case ICMP_ADDRESS: 202 case ICMP_ADDRESSREPLY: 203 break; 204 default: 205 return true; 206 } 207 inet_proto_csum_replace2(&hdr->checksum, skb, 208 hdr->un.echo.id, tuple->src.u.icmp.id, false); 209 hdr->un.echo.id = tuple->src.u.icmp.id; 210 return true; 211} 212 213static bool 214icmpv6_manip_pkt(struct sk_buff *skb, 215 unsigned int iphdroff, unsigned int hdroff, 216 const struct nf_conntrack_tuple *tuple, 217 enum nf_nat_manip_type maniptype) 218{ 219 struct icmp6hdr *hdr; 220 221 if (skb_ensure_writable(skb, hdroff + sizeof(*hdr))) 222 return false; 223 224 hdr = (struct icmp6hdr *)(skb->data + hdroff); 225 nf_csum_update(skb, iphdroff, &hdr->icmp6_cksum, tuple, maniptype); 226 if (hdr->icmp6_type == ICMPV6_ECHO_REQUEST || 227 hdr->icmp6_type == ICMPV6_ECHO_REPLY) { 228 inet_proto_csum_replace2(&hdr->icmp6_cksum, skb, 229 hdr->icmp6_identifier, 230 tuple->src.u.icmp.id, false); 231 hdr->icmp6_identifier = tuple->src.u.icmp.id; 232 } 233 return true; 234} 235 236/* manipulate a GRE packet according to maniptype */ 237static bool 238gre_manip_pkt(struct sk_buff *skb, 239 unsigned int iphdroff, unsigned int hdroff, 240 const struct nf_conntrack_tuple *tuple, 241 enum nf_nat_manip_type maniptype) 242{ 243#if IS_ENABLED(CONFIG_NF_CT_PROTO_GRE) 244 const struct gre_base_hdr *greh; 245 struct pptp_gre_header *pgreh; 246 247 /* pgreh includes two optional 32bit fields which are not required 248 * to be there. That's where the magic '8' comes from */ 249 if (skb_ensure_writable(skb, hdroff + sizeof(*pgreh) - 8)) 250 return false; 251 252 greh = (void *)skb->data + hdroff; 253 pgreh = (struct pptp_gre_header *)greh; 254 255 /* we only have destination manip of a packet, since 'source key' 256 * is not present in the packet itself */ 257 if (maniptype != NF_NAT_MANIP_DST) 258 return true; 259 260 switch (greh->flags & GRE_VERSION) { 261 case GRE_VERSION_0: 262 /* We do not currently NAT any GREv0 packets. 263 * Try to behave like "nf_nat_proto_unknown" */ 264 break; 265 case GRE_VERSION_1: 266 pr_debug("call_id -> 0x%04x\n", ntohs(tuple->dst.u.gre.key)); 267 pgreh->call_id = tuple->dst.u.gre.key; 268 break; 269 default: 270 pr_debug("can't nat unknown GRE version\n"); 271 return false; 272 } 273#endif 274 return true; 275} 276 277static bool l4proto_manip_pkt(struct sk_buff *skb, 278 unsigned int iphdroff, unsigned int hdroff, 279 const struct nf_conntrack_tuple *tuple, 280 enum nf_nat_manip_type maniptype) 281{ 282 switch (tuple->dst.protonum) { 283 case IPPROTO_TCP: 284 return tcp_manip_pkt(skb, iphdroff, hdroff, 285 tuple, maniptype); 286 case IPPROTO_UDP: 287 return udp_manip_pkt(skb, iphdroff, hdroff, 288 tuple, maniptype); 289 case IPPROTO_UDPLITE: 290 return udplite_manip_pkt(skb, iphdroff, hdroff, 291 tuple, maniptype); 292 case IPPROTO_SCTP: 293 return sctp_manip_pkt(skb, iphdroff, hdroff, 294 tuple, maniptype); 295 case IPPROTO_ICMP: 296 return icmp_manip_pkt(skb, iphdroff, hdroff, 297 tuple, maniptype); 298 case IPPROTO_ICMPV6: 299 return icmpv6_manip_pkt(skb, iphdroff, hdroff, 300 tuple, maniptype); 301 case IPPROTO_GRE: 302 return gre_manip_pkt(skb, iphdroff, hdroff, 303 tuple, maniptype); 304 } 305 306 /* If we don't know protocol -- no error, pass it unmodified. */ 307 return true; 308} 309 310static bool nf_nat_ipv4_manip_pkt(struct sk_buff *skb, 311 unsigned int iphdroff, 312 const struct nf_conntrack_tuple *target, 313 enum nf_nat_manip_type maniptype) 314{ 315 struct iphdr *iph; 316 unsigned int hdroff; 317 318 if (skb_ensure_writable(skb, iphdroff + sizeof(*iph))) 319 return false; 320 321 iph = (void *)skb->data + iphdroff; 322 hdroff = iphdroff + iph->ihl * 4; 323 324 if (!l4proto_manip_pkt(skb, iphdroff, hdroff, target, maniptype)) 325 return false; 326 iph = (void *)skb->data + iphdroff; 327 328 if (maniptype == NF_NAT_MANIP_SRC) { 329 csum_replace4(&iph->check, iph->saddr, target->src.u3.ip); 330 iph->saddr = target->src.u3.ip; 331 } else { 332 csum_replace4(&iph->check, iph->daddr, target->dst.u3.ip); 333 iph->daddr = target->dst.u3.ip; 334 } 335 return true; 336} 337 338static bool nf_nat_ipv6_manip_pkt(struct sk_buff *skb, 339 unsigned int iphdroff, 340 const struct nf_conntrack_tuple *target, 341 enum nf_nat_manip_type maniptype) 342{ 343#if IS_ENABLED(CONFIG_IPV6) 344 struct ipv6hdr *ipv6h; 345 __be16 frag_off; 346 int hdroff; 347 u8 nexthdr; 348 349 if (skb_ensure_writable(skb, iphdroff + sizeof(*ipv6h))) 350 return false; 351 352 ipv6h = (void *)skb->data + iphdroff; 353 nexthdr = ipv6h->nexthdr; 354 hdroff = ipv6_skip_exthdr(skb, iphdroff + sizeof(*ipv6h), 355 &nexthdr, &frag_off); 356 if (hdroff < 0) 357 goto manip_addr; 358 359 if ((frag_off & htons(~0x7)) == 0 && 360 !l4proto_manip_pkt(skb, iphdroff, hdroff, target, maniptype)) 361 return false; 362 363 /* must reload, offset might have changed */ 364 ipv6h = (void *)skb->data + iphdroff; 365 366manip_addr: 367 if (maniptype == NF_NAT_MANIP_SRC) 368 ipv6h->saddr = target->src.u3.in6; 369 else 370 ipv6h->daddr = target->dst.u3.in6; 371 372#endif 373 return true; 374} 375 376unsigned int nf_nat_manip_pkt(struct sk_buff *skb, struct nf_conn *ct, 377 enum nf_nat_manip_type mtype, 378 enum ip_conntrack_dir dir) 379{ 380 struct nf_conntrack_tuple target; 381 382 /* We are aiming to look like inverse of other direction. */ 383 nf_ct_invert_tuple(&target, &ct->tuplehash[!dir].tuple); 384 385 switch (target.src.l3num) { 386 case NFPROTO_IPV6: 387 if (nf_nat_ipv6_manip_pkt(skb, 0, &target, mtype)) 388 return NF_ACCEPT; 389 break; 390 case NFPROTO_IPV4: 391 if (nf_nat_ipv4_manip_pkt(skb, 0, &target, mtype)) 392 return NF_ACCEPT; 393 break; 394 default: 395 WARN_ON_ONCE(1); 396 break; 397 } 398 399 return NF_DROP; 400} 401 402static void nf_nat_ipv4_csum_update(struct sk_buff *skb, 403 unsigned int iphdroff, __sum16 *check, 404 const struct nf_conntrack_tuple *t, 405 enum nf_nat_manip_type maniptype) 406{ 407 struct iphdr *iph = (struct iphdr *)(skb->data + iphdroff); 408 __be32 oldip, newip; 409 410 if (maniptype == NF_NAT_MANIP_SRC) { 411 oldip = iph->saddr; 412 newip = t->src.u3.ip; 413 } else { 414 oldip = iph->daddr; 415 newip = t->dst.u3.ip; 416 } 417 inet_proto_csum_replace4(check, skb, oldip, newip, true); 418} 419 420static void nf_nat_ipv6_csum_update(struct sk_buff *skb, 421 unsigned int iphdroff, __sum16 *check, 422 const struct nf_conntrack_tuple *t, 423 enum nf_nat_manip_type maniptype) 424{ 425#if IS_ENABLED(CONFIG_IPV6) 426 const struct ipv6hdr *ipv6h = (struct ipv6hdr *)(skb->data + iphdroff); 427 const struct in6_addr *oldip, *newip; 428 429 if (maniptype == NF_NAT_MANIP_SRC) { 430 oldip = &ipv6h->saddr; 431 newip = &t->src.u3.in6; 432 } else { 433 oldip = &ipv6h->daddr; 434 newip = &t->dst.u3.in6; 435 } 436 inet_proto_csum_replace16(check, skb, oldip->s6_addr32, 437 newip->s6_addr32, true); 438#endif 439} 440 441static void nf_csum_update(struct sk_buff *skb, 442 unsigned int iphdroff, __sum16 *check, 443 const struct nf_conntrack_tuple *t, 444 enum nf_nat_manip_type maniptype) 445{ 446 switch (t->src.l3num) { 447 case NFPROTO_IPV4: 448 nf_nat_ipv4_csum_update(skb, iphdroff, check, t, maniptype); 449 return; 450 case NFPROTO_IPV6: 451 nf_nat_ipv6_csum_update(skb, iphdroff, check, t, maniptype); 452 return; 453 } 454} 455 456static void nf_nat_ipv4_csum_recalc(struct sk_buff *skb, 457 u8 proto, void *data, __sum16 *check, 458 int datalen, int oldlen) 459{ 460 if (skb->ip_summed != CHECKSUM_PARTIAL) { 461 const struct iphdr *iph = ip_hdr(skb); 462 463 skb->ip_summed = CHECKSUM_PARTIAL; 464 skb->csum_start = skb_headroom(skb) + skb_network_offset(skb) + 465 ip_hdrlen(skb); 466 skb->csum_offset = (void *)check - data; 467 *check = ~csum_tcpudp_magic(iph->saddr, iph->daddr, datalen, 468 proto, 0); 469 } else { 470 inet_proto_csum_replace2(check, skb, 471 htons(oldlen), htons(datalen), true); 472 } 473} 474 475#if IS_ENABLED(CONFIG_IPV6) 476static void nf_nat_ipv6_csum_recalc(struct sk_buff *skb, 477 u8 proto, void *data, __sum16 *check, 478 int datalen, int oldlen) 479{ 480 if (skb->ip_summed != CHECKSUM_PARTIAL) { 481 const struct ipv6hdr *ipv6h = ipv6_hdr(skb); 482 483 skb->ip_summed = CHECKSUM_PARTIAL; 484 skb->csum_start = skb_headroom(skb) + skb_network_offset(skb) + 485 (data - (void *)skb->data); 486 skb->csum_offset = (void *)check - data; 487 *check = ~csum_ipv6_magic(&ipv6h->saddr, &ipv6h->daddr, 488 datalen, proto, 0); 489 } else { 490 inet_proto_csum_replace2(check, skb, 491 htons(oldlen), htons(datalen), true); 492 } 493} 494#endif 495 496void nf_nat_csum_recalc(struct sk_buff *skb, 497 u8 nfproto, u8 proto, void *data, __sum16 *check, 498 int datalen, int oldlen) 499{ 500 switch (nfproto) { 501 case NFPROTO_IPV4: 502 nf_nat_ipv4_csum_recalc(skb, proto, data, check, 503 datalen, oldlen); 504 return; 505#if IS_ENABLED(CONFIG_IPV6) 506 case NFPROTO_IPV6: 507 nf_nat_ipv6_csum_recalc(skb, proto, data, check, 508 datalen, oldlen); 509 return; 510#endif 511 } 512 513 WARN_ON_ONCE(1); 514} 515 516int nf_nat_icmp_reply_translation(struct sk_buff *skb, 517 struct nf_conn *ct, 518 enum ip_conntrack_info ctinfo, 519 unsigned int hooknum) 520{ 521 struct { 522 struct icmphdr icmp; 523 struct iphdr ip; 524 } *inside; 525 enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo); 526 enum nf_nat_manip_type manip = HOOK2MANIP(hooknum); 527 unsigned int hdrlen = ip_hdrlen(skb); 528 struct nf_conntrack_tuple target; 529 unsigned long statusbit; 530 531 WARN_ON(ctinfo != IP_CT_RELATED && ctinfo != IP_CT_RELATED_REPLY); 532 533 if (skb_ensure_writable(skb, hdrlen + sizeof(*inside))) 534 return 0; 535 if (nf_ip_checksum(skb, hooknum, hdrlen, IPPROTO_ICMP)) 536 return 0; 537 538 inside = (void *)skb->data + hdrlen; 539 if (inside->icmp.type == ICMP_REDIRECT) { 540 if ((ct->status & IPS_NAT_DONE_MASK) != IPS_NAT_DONE_MASK) 541 return 0; 542 if (ct->status & IPS_NAT_MASK) 543 return 0; 544 } 545 546 if (manip == NF_NAT_MANIP_SRC) 547 statusbit = IPS_SRC_NAT; 548 else 549 statusbit = IPS_DST_NAT; 550 551 /* Invert if this is reply direction */ 552 if (dir == IP_CT_DIR_REPLY) 553 statusbit ^= IPS_NAT_MASK; 554 555 if (!(ct->status & statusbit)) 556 return 1; 557 558 if (!nf_nat_ipv4_manip_pkt(skb, hdrlen + sizeof(inside->icmp), 559 &ct->tuplehash[!dir].tuple, !manip)) 560 return 0; 561 562 if (skb->ip_summed != CHECKSUM_PARTIAL) { 563 /* Reloading "inside" here since manip_pkt may reallocate */ 564 inside = (void *)skb->data + hdrlen; 565 inside->icmp.checksum = 0; 566 inside->icmp.checksum = 567 csum_fold(skb_checksum(skb, hdrlen, 568 skb->len - hdrlen, 0)); 569 } 570 571 /* Change outer to look like the reply to an incoming packet */ 572 nf_ct_invert_tuple(&target, &ct->tuplehash[!dir].tuple); 573 target.dst.protonum = IPPROTO_ICMP; 574 if (!nf_nat_ipv4_manip_pkt(skb, 0, &target, manip)) 575 return 0; 576 577 return 1; 578} 579EXPORT_SYMBOL_GPL(nf_nat_icmp_reply_translation); 580 581static unsigned int 582nf_nat_ipv4_fn(void *priv, struct sk_buff *skb, 583 const struct nf_hook_state *state) 584{ 585 struct nf_conn *ct; 586 enum ip_conntrack_info ctinfo; 587 588 ct = nf_ct_get(skb, &ctinfo); 589 if (!ct) 590 return NF_ACCEPT; 591 592 if (ctinfo == IP_CT_RELATED || ctinfo == IP_CT_RELATED_REPLY) { 593 if (ip_hdr(skb)->protocol == IPPROTO_ICMP) { 594 if (!nf_nat_icmp_reply_translation(skb, ct, ctinfo, 595 state->hook)) 596 return NF_DROP; 597 else 598 return NF_ACCEPT; 599 } 600 } 601 602 return nf_nat_inet_fn(priv, skb, state); 603} 604 605static unsigned int 606nf_nat_ipv4_pre_routing(void *priv, struct sk_buff *skb, 607 const struct nf_hook_state *state) 608{ 609 unsigned int ret; 610 __be32 daddr = ip_hdr(skb)->daddr; 611 612 ret = nf_nat_ipv4_fn(priv, skb, state); 613 if (ret == NF_ACCEPT && daddr != ip_hdr(skb)->daddr) 614 skb_dst_drop(skb); 615 616 return ret; 617} 618 619#ifdef CONFIG_XFRM 620static int nf_xfrm_me_harder(struct net *net, struct sk_buff *skb, unsigned int family) 621{ 622 struct sock *sk = skb->sk; 623 struct dst_entry *dst; 624 unsigned int hh_len; 625 struct flowi fl; 626 int err; 627 628 err = xfrm_decode_session(net, skb, &fl, family); 629 if (err < 0) 630 return err; 631 632 dst = skb_dst(skb); 633 if (dst->xfrm) 634 dst = ((struct xfrm_dst *)dst)->route; 635 if (!dst_hold_safe(dst)) 636 return -EHOSTUNREACH; 637 638 if (sk && !net_eq(net, sock_net(sk))) 639 sk = NULL; 640 641 dst = xfrm_lookup(net, dst, &fl, sk, 0); 642 if (IS_ERR(dst)) 643 return PTR_ERR(dst); 644 645 skb_dst_drop(skb); 646 skb_dst_set(skb, dst); 647 648 /* Change in oif may mean change in hh_len. */ 649 hh_len = skb_dst(skb)->dev->hard_header_len; 650 if (skb_headroom(skb) < hh_len && 651 pskb_expand_head(skb, hh_len - skb_headroom(skb), 0, GFP_ATOMIC)) 652 return -ENOMEM; 653 return 0; 654} 655#endif 656 657static bool nf_nat_inet_port_was_mangled(const struct sk_buff *skb, __be16 sport) 658{ 659 enum ip_conntrack_info ctinfo; 660 enum ip_conntrack_dir dir; 661 const struct nf_conn *ct; 662 663 ct = nf_ct_get(skb, &ctinfo); 664 if (!ct) 665 return false; 666 667 switch (nf_ct_protonum(ct)) { 668 case IPPROTO_TCP: 669 case IPPROTO_UDP: 670 break; 671 default: 672 return false; 673 } 674 675 dir = CTINFO2DIR(ctinfo); 676 if (dir != IP_CT_DIR_ORIGINAL) 677 return false; 678 679 return ct->tuplehash[!dir].tuple.dst.u.all != sport; 680} 681 682static unsigned int 683nf_nat_ipv4_local_in(void *priv, struct sk_buff *skb, 684 const struct nf_hook_state *state) 685{ 686 __be32 saddr = ip_hdr(skb)->saddr; 687 struct sock *sk = skb->sk; 688 unsigned int ret; 689 690 ret = nf_nat_ipv4_fn(priv, skb, state); 691 692 if (ret != NF_ACCEPT || !sk || inet_sk_transparent(sk)) 693 return ret; 694 695 /* skb has a socket assigned via tcp edemux. We need to check 696 * if nf_nat_ipv4_fn() has mangled the packet in a way that 697 * edemux would not have found this socket. 698 * 699 * This includes both changes to the source address and changes 700 * to the source port, which are both handled by the 701 * nf_nat_ipv4_fn() call above -- long after tcp/udp early demux 702 * might have found a socket for the old (pre-snat) address. 703 */ 704 if (saddr != ip_hdr(skb)->saddr || 705 nf_nat_inet_port_was_mangled(skb, sk->sk_dport)) 706 skb_orphan(skb); /* TCP edemux obtained wrong socket */ 707 708 return ret; 709} 710 711static unsigned int 712nf_nat_ipv4_out(void *priv, struct sk_buff *skb, 713 const struct nf_hook_state *state) 714{ 715#ifdef CONFIG_XFRM 716 const struct nf_conn *ct; 717 enum ip_conntrack_info ctinfo; 718 int err; 719#endif 720 unsigned int ret; 721 722 ret = nf_nat_ipv4_fn(priv, skb, state); 723#ifdef CONFIG_XFRM 724 if (ret != NF_ACCEPT) 725 return ret; 726 727 if (IPCB(skb)->flags & IPSKB_XFRM_TRANSFORMED) 728 return ret; 729 730 ct = nf_ct_get(skb, &ctinfo); 731 if (ct) { 732 enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo); 733 734 if (ct->tuplehash[dir].tuple.src.u3.ip != 735 ct->tuplehash[!dir].tuple.dst.u3.ip || 736 (ct->tuplehash[dir].tuple.dst.protonum != IPPROTO_ICMP && 737 ct->tuplehash[dir].tuple.src.u.all != 738 ct->tuplehash[!dir].tuple.dst.u.all)) { 739 err = nf_xfrm_me_harder(state->net, skb, AF_INET); 740 if (err < 0) 741 ret = NF_DROP_ERR(err); 742 } 743 } 744#endif 745 return ret; 746} 747 748static unsigned int 749nf_nat_ipv4_local_fn(void *priv, struct sk_buff *skb, 750 const struct nf_hook_state *state) 751{ 752 const struct nf_conn *ct; 753 enum ip_conntrack_info ctinfo; 754 unsigned int ret; 755 int err; 756 757 ret = nf_nat_ipv4_fn(priv, skb, state); 758 if (ret != NF_ACCEPT) 759 return ret; 760 761 ct = nf_ct_get(skb, &ctinfo); 762 if (ct) { 763 enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo); 764 765 if (ct->tuplehash[dir].tuple.dst.u3.ip != 766 ct->tuplehash[!dir].tuple.src.u3.ip) { 767 err = ip_route_me_harder(state->net, state->sk, skb, RTN_UNSPEC); 768 if (err < 0) 769 ret = NF_DROP_ERR(err); 770 } 771#ifdef CONFIG_XFRM 772 else if (!(IPCB(skb)->flags & IPSKB_XFRM_TRANSFORMED) && 773 ct->tuplehash[dir].tuple.dst.protonum != IPPROTO_ICMP && 774 ct->tuplehash[dir].tuple.dst.u.all != 775 ct->tuplehash[!dir].tuple.src.u.all) { 776 err = nf_xfrm_me_harder(state->net, skb, AF_INET); 777 if (err < 0) 778 ret = NF_DROP_ERR(err); 779 } 780#endif 781 } 782 return ret; 783} 784 785static const struct nf_hook_ops nf_nat_ipv4_ops[] = { 786 /* Before packet filtering, change destination */ 787 { 788 .hook = nf_nat_ipv4_pre_routing, 789 .pf = NFPROTO_IPV4, 790 .hooknum = NF_INET_PRE_ROUTING, 791 .priority = NF_IP_PRI_NAT_DST, 792 }, 793 /* After packet filtering, change source */ 794 { 795 .hook = nf_nat_ipv4_out, 796 .pf = NFPROTO_IPV4, 797 .hooknum = NF_INET_POST_ROUTING, 798 .priority = NF_IP_PRI_NAT_SRC, 799 }, 800 /* Before packet filtering, change destination */ 801 { 802 .hook = nf_nat_ipv4_local_fn, 803 .pf = NFPROTO_IPV4, 804 .hooknum = NF_INET_LOCAL_OUT, 805 .priority = NF_IP_PRI_NAT_DST, 806 }, 807 /* After packet filtering, change source */ 808 { 809 .hook = nf_nat_ipv4_local_in, 810 .pf = NFPROTO_IPV4, 811 .hooknum = NF_INET_LOCAL_IN, 812 .priority = NF_IP_PRI_NAT_SRC, 813 }, 814}; 815 816int nf_nat_ipv4_register_fn(struct net *net, const struct nf_hook_ops *ops) 817{ 818 return nf_nat_register_fn(net, ops->pf, ops, nf_nat_ipv4_ops, 819 ARRAY_SIZE(nf_nat_ipv4_ops)); 820} 821EXPORT_SYMBOL_GPL(nf_nat_ipv4_register_fn); 822 823void nf_nat_ipv4_unregister_fn(struct net *net, const struct nf_hook_ops *ops) 824{ 825 nf_nat_unregister_fn(net, ops->pf, ops, ARRAY_SIZE(nf_nat_ipv4_ops)); 826} 827EXPORT_SYMBOL_GPL(nf_nat_ipv4_unregister_fn); 828 829#if IS_ENABLED(CONFIG_IPV6) 830int nf_nat_icmpv6_reply_translation(struct sk_buff *skb, 831 struct nf_conn *ct, 832 enum ip_conntrack_info ctinfo, 833 unsigned int hooknum, 834 unsigned int hdrlen) 835{ 836 struct { 837 struct icmp6hdr icmp6; 838 struct ipv6hdr ip6; 839 } *inside; 840 enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo); 841 enum nf_nat_manip_type manip = HOOK2MANIP(hooknum); 842 struct nf_conntrack_tuple target; 843 unsigned long statusbit; 844 845 WARN_ON(ctinfo != IP_CT_RELATED && ctinfo != IP_CT_RELATED_REPLY); 846 847 if (skb_ensure_writable(skb, hdrlen + sizeof(*inside))) 848 return 0; 849 if (nf_ip6_checksum(skb, hooknum, hdrlen, IPPROTO_ICMPV6)) 850 return 0; 851 852 inside = (void *)skb->data + hdrlen; 853 if (inside->icmp6.icmp6_type == NDISC_REDIRECT) { 854 if ((ct->status & IPS_NAT_DONE_MASK) != IPS_NAT_DONE_MASK) 855 return 0; 856 if (ct->status & IPS_NAT_MASK) 857 return 0; 858 } 859 860 if (manip == NF_NAT_MANIP_SRC) 861 statusbit = IPS_SRC_NAT; 862 else 863 statusbit = IPS_DST_NAT; 864 865 /* Invert if this is reply direction */ 866 if (dir == IP_CT_DIR_REPLY) 867 statusbit ^= IPS_NAT_MASK; 868 869 if (!(ct->status & statusbit)) 870 return 1; 871 872 if (!nf_nat_ipv6_manip_pkt(skb, hdrlen + sizeof(inside->icmp6), 873 &ct->tuplehash[!dir].tuple, !manip)) 874 return 0; 875 876 if (skb->ip_summed != CHECKSUM_PARTIAL) { 877 struct ipv6hdr *ipv6h = ipv6_hdr(skb); 878 879 inside = (void *)skb->data + hdrlen; 880 inside->icmp6.icmp6_cksum = 0; 881 inside->icmp6.icmp6_cksum = 882 csum_ipv6_magic(&ipv6h->saddr, &ipv6h->daddr, 883 skb->len - hdrlen, IPPROTO_ICMPV6, 884 skb_checksum(skb, hdrlen, 885 skb->len - hdrlen, 0)); 886 } 887 888 nf_ct_invert_tuple(&target, &ct->tuplehash[!dir].tuple); 889 target.dst.protonum = IPPROTO_ICMPV6; 890 if (!nf_nat_ipv6_manip_pkt(skb, 0, &target, manip)) 891 return 0; 892 893 return 1; 894} 895EXPORT_SYMBOL_GPL(nf_nat_icmpv6_reply_translation); 896 897static unsigned int 898nf_nat_ipv6_fn(void *priv, struct sk_buff *skb, 899 const struct nf_hook_state *state) 900{ 901 struct nf_conn *ct; 902 enum ip_conntrack_info ctinfo; 903 __be16 frag_off; 904 int hdrlen; 905 u8 nexthdr; 906 907 ct = nf_ct_get(skb, &ctinfo); 908 /* Can't track? It's not due to stress, or conntrack would 909 * have dropped it. Hence it's the user's responsibilty to 910 * packet filter it out, or implement conntrack/NAT for that 911 * protocol. 8) --RR 912 */ 913 if (!ct) 914 return NF_ACCEPT; 915 916 if (ctinfo == IP_CT_RELATED || ctinfo == IP_CT_RELATED_REPLY) { 917 nexthdr = ipv6_hdr(skb)->nexthdr; 918 hdrlen = ipv6_skip_exthdr(skb, sizeof(struct ipv6hdr), 919 &nexthdr, &frag_off); 920 921 if (hdrlen >= 0 && nexthdr == IPPROTO_ICMPV6) { 922 if (!nf_nat_icmpv6_reply_translation(skb, ct, ctinfo, 923 state->hook, 924 hdrlen)) 925 return NF_DROP; 926 else 927 return NF_ACCEPT; 928 } 929 } 930 931 return nf_nat_inet_fn(priv, skb, state); 932} 933 934static unsigned int 935nf_nat_ipv6_local_in(void *priv, struct sk_buff *skb, 936 const struct nf_hook_state *state) 937{ 938 struct in6_addr saddr = ipv6_hdr(skb)->saddr; 939 struct sock *sk = skb->sk; 940 unsigned int ret; 941 942 ret = nf_nat_ipv6_fn(priv, skb, state); 943 944 if (ret != NF_ACCEPT || !sk || inet_sk_transparent(sk)) 945 return ret; 946 947 /* see nf_nat_ipv4_local_in */ 948 if (ipv6_addr_cmp(&saddr, &ipv6_hdr(skb)->saddr) || 949 nf_nat_inet_port_was_mangled(skb, sk->sk_dport)) 950 skb_orphan(skb); 951 952 return ret; 953} 954 955static unsigned int 956nf_nat_ipv6_in(void *priv, struct sk_buff *skb, 957 const struct nf_hook_state *state) 958{ 959 unsigned int ret, verdict; 960 struct in6_addr daddr = ipv6_hdr(skb)->daddr; 961 962 ret = nf_nat_ipv6_fn(priv, skb, state); 963 verdict = ret & NF_VERDICT_MASK; 964 if (verdict != NF_DROP && verdict != NF_STOLEN && 965 ipv6_addr_cmp(&daddr, &ipv6_hdr(skb)->daddr)) 966 skb_dst_drop(skb); 967 968 return ret; 969} 970 971static unsigned int 972nf_nat_ipv6_out(void *priv, struct sk_buff *skb, 973 const struct nf_hook_state *state) 974{ 975#ifdef CONFIG_XFRM 976 const struct nf_conn *ct; 977 enum ip_conntrack_info ctinfo; 978 int err; 979#endif 980 unsigned int ret; 981 982 ret = nf_nat_ipv6_fn(priv, skb, state); 983#ifdef CONFIG_XFRM 984 if (ret != NF_ACCEPT) 985 return ret; 986 987 if (IP6CB(skb)->flags & IP6SKB_XFRM_TRANSFORMED) 988 return ret; 989 ct = nf_ct_get(skb, &ctinfo); 990 if (ct) { 991 enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo); 992 993 if (!nf_inet_addr_cmp(&ct->tuplehash[dir].tuple.src.u3, 994 &ct->tuplehash[!dir].tuple.dst.u3) || 995 (ct->tuplehash[dir].tuple.dst.protonum != IPPROTO_ICMPV6 && 996 ct->tuplehash[dir].tuple.src.u.all != 997 ct->tuplehash[!dir].tuple.dst.u.all)) { 998 err = nf_xfrm_me_harder(state->net, skb, AF_INET6); 999 if (err < 0) 1000 ret = NF_DROP_ERR(err); 1001 } 1002 } 1003#endif 1004 1005 return ret; 1006} 1007 1008static unsigned int 1009nf_nat_ipv6_local_fn(void *priv, struct sk_buff *skb, 1010 const struct nf_hook_state *state) 1011{ 1012 const struct nf_conn *ct; 1013 enum ip_conntrack_info ctinfo; 1014 unsigned int ret; 1015 int err; 1016 1017 ret = nf_nat_ipv6_fn(priv, skb, state); 1018 if (ret != NF_ACCEPT) 1019 return ret; 1020 1021 ct = nf_ct_get(skb, &ctinfo); 1022 if (ct) { 1023 enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo); 1024 1025 if (!nf_inet_addr_cmp(&ct->tuplehash[dir].tuple.dst.u3, 1026 &ct->tuplehash[!dir].tuple.src.u3)) { 1027 err = nf_ip6_route_me_harder(state->net, state->sk, skb); 1028 if (err < 0) 1029 ret = NF_DROP_ERR(err); 1030 } 1031#ifdef CONFIG_XFRM 1032 else if (!(IP6CB(skb)->flags & IP6SKB_XFRM_TRANSFORMED) && 1033 ct->tuplehash[dir].tuple.dst.protonum != IPPROTO_ICMPV6 && 1034 ct->tuplehash[dir].tuple.dst.u.all != 1035 ct->tuplehash[!dir].tuple.src.u.all) { 1036 err = nf_xfrm_me_harder(state->net, skb, AF_INET6); 1037 if (err < 0) 1038 ret = NF_DROP_ERR(err); 1039 } 1040#endif 1041 } 1042 1043 return ret; 1044} 1045 1046static const struct nf_hook_ops nf_nat_ipv6_ops[] = { 1047 /* Before packet filtering, change destination */ 1048 { 1049 .hook = nf_nat_ipv6_in, 1050 .pf = NFPROTO_IPV6, 1051 .hooknum = NF_INET_PRE_ROUTING, 1052 .priority = NF_IP6_PRI_NAT_DST, 1053 }, 1054 /* After packet filtering, change source */ 1055 { 1056 .hook = nf_nat_ipv6_out, 1057 .pf = NFPROTO_IPV6, 1058 .hooknum = NF_INET_POST_ROUTING, 1059 .priority = NF_IP6_PRI_NAT_SRC, 1060 }, 1061 /* Before packet filtering, change destination */ 1062 { 1063 .hook = nf_nat_ipv6_local_fn, 1064 .pf = NFPROTO_IPV6, 1065 .hooknum = NF_INET_LOCAL_OUT, 1066 .priority = NF_IP6_PRI_NAT_DST, 1067 }, 1068 /* After packet filtering, change source */ 1069 { 1070 .hook = nf_nat_ipv6_local_in, 1071 .pf = NFPROTO_IPV6, 1072 .hooknum = NF_INET_LOCAL_IN, 1073 .priority = NF_IP6_PRI_NAT_SRC, 1074 }, 1075}; 1076 1077int nf_nat_ipv6_register_fn(struct net *net, const struct nf_hook_ops *ops) 1078{ 1079 return nf_nat_register_fn(net, ops->pf, ops, nf_nat_ipv6_ops, 1080 ARRAY_SIZE(nf_nat_ipv6_ops)); 1081} 1082EXPORT_SYMBOL_GPL(nf_nat_ipv6_register_fn); 1083 1084void nf_nat_ipv6_unregister_fn(struct net *net, const struct nf_hook_ops *ops) 1085{ 1086 nf_nat_unregister_fn(net, ops->pf, ops, ARRAY_SIZE(nf_nat_ipv6_ops)); 1087} 1088EXPORT_SYMBOL_GPL(nf_nat_ipv6_unregister_fn); 1089#endif /* CONFIG_IPV6 */ 1090 1091#if defined(CONFIG_NF_TABLES_INET) && IS_ENABLED(CONFIG_NFT_NAT) 1092int nf_nat_inet_register_fn(struct net *net, const struct nf_hook_ops *ops) 1093{ 1094 int ret; 1095 1096 if (WARN_ON_ONCE(ops->pf != NFPROTO_INET)) 1097 return -EINVAL; 1098 1099 ret = nf_nat_register_fn(net, NFPROTO_IPV6, ops, nf_nat_ipv6_ops, 1100 ARRAY_SIZE(nf_nat_ipv6_ops)); 1101 if (ret) 1102 return ret; 1103 1104 ret = nf_nat_register_fn(net, NFPROTO_IPV4, ops, nf_nat_ipv4_ops, 1105 ARRAY_SIZE(nf_nat_ipv4_ops)); 1106 if (ret) 1107 nf_nat_unregister_fn(net, NFPROTO_IPV6, ops, 1108 ARRAY_SIZE(nf_nat_ipv6_ops)); 1109 return ret; 1110} 1111EXPORT_SYMBOL_GPL(nf_nat_inet_register_fn); 1112 1113void nf_nat_inet_unregister_fn(struct net *net, const struct nf_hook_ops *ops) 1114{ 1115 nf_nat_unregister_fn(net, NFPROTO_IPV4, ops, ARRAY_SIZE(nf_nat_ipv4_ops)); 1116 nf_nat_unregister_fn(net, NFPROTO_IPV6, ops, ARRAY_SIZE(nf_nat_ipv6_ops)); 1117} 1118EXPORT_SYMBOL_GPL(nf_nat_inet_unregister_fn); 1119#endif /* NFT INET NAT */
~/
Read-only file preview.