FILE
nf_flow_table_ip.c
File preview with syntax highlighting.
linux-6.19.14/net/netfilter/nf_flow_table_ip.c
1// SPDX-License-Identifier: GPL-2.0-only 2#include <linux/kernel.h> 3#include <linux/init.h> 4#include <linux/module.h> 5#include <linux/netfilter.h> 6#include <linux/rhashtable.h> 7#include <linux/ip.h> 8#include <linux/ipv6.h> 9#include <linux/netdevice.h> 10#include <linux/if_ether.h> 11#include <net/gso.h> 12#include <net/ip.h> 13#include <net/ipv6.h> 14#include <net/ip6_route.h> 15#include <net/neighbour.h> 16#include <net/netfilter/nf_flow_table.h> 17#include <net/netfilter/nf_conntrack_acct.h> 18/* For layer 4 checksum field offset. */ 19#include <linux/tcp.h> 20#include <linux/udp.h> 21 22static int nf_flow_state_check(struct flow_offload *flow, int proto, 23 struct sk_buff *skb, unsigned int thoff) 24{ 25 struct tcphdr *tcph; 26 27 if (proto != IPPROTO_TCP) 28 return 0; 29 30 tcph = (void *)(skb_network_header(skb) + thoff); 31 if (tcph->syn && test_bit(NF_FLOW_CLOSING, &flow->flags)) { 32 flow_offload_teardown(flow); 33 return -1; 34 } 35 36 if ((tcph->fin || tcph->rst) && 37 !test_bit(NF_FLOW_CLOSING, &flow->flags)) 38 set_bit(NF_FLOW_CLOSING, &flow->flags); 39 40 return 0; 41} 42 43static void nf_flow_nat_ip_tcp(struct sk_buff *skb, unsigned int thoff, 44 __be32 addr, __be32 new_addr) 45{ 46 struct tcphdr *tcph; 47 48 tcph = (void *)(skb_network_header(skb) + thoff); 49 inet_proto_csum_replace4(&tcph->check, skb, addr, new_addr, true); 50} 51 52static void nf_flow_nat_ip_udp(struct sk_buff *skb, unsigned int thoff, 53 __be32 addr, __be32 new_addr) 54{ 55 struct udphdr *udph; 56 57 udph = (void *)(skb_network_header(skb) + thoff); 58 if (udph->check || skb->ip_summed == CHECKSUM_PARTIAL) { 59 inet_proto_csum_replace4(&udph->check, skb, addr, 60 new_addr, true); 61 if (!udph->check) 62 udph->check = CSUM_MANGLED_0; 63 } 64} 65 66static void nf_flow_nat_ip_l4proto(struct sk_buff *skb, struct iphdr *iph, 67 unsigned int thoff, __be32 addr, 68 __be32 new_addr) 69{ 70 switch (iph->protocol) { 71 case IPPROTO_TCP: 72 nf_flow_nat_ip_tcp(skb, thoff, addr, new_addr); 73 break; 74 case IPPROTO_UDP: 75 nf_flow_nat_ip_udp(skb, thoff, addr, new_addr); 76 break; 77 } 78} 79 80static void nf_flow_snat_ip(const struct flow_offload *flow, 81 struct sk_buff *skb, struct iphdr *iph, 82 unsigned int thoff, enum flow_offload_tuple_dir dir) 83{ 84 __be32 addr, new_addr; 85 86 switch (dir) { 87 case FLOW_OFFLOAD_DIR_ORIGINAL: 88 addr = iph->saddr; 89 new_addr = flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].tuple.dst_v4.s_addr; 90 iph->saddr = new_addr; 91 break; 92 case FLOW_OFFLOAD_DIR_REPLY: 93 addr = iph->daddr; 94 new_addr = flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple.src_v4.s_addr; 95 iph->daddr = new_addr; 96 break; 97 } 98 csum_replace4(&iph->check, addr, new_addr); 99 100 nf_flow_nat_ip_l4proto(skb, iph, thoff, addr, new_addr); 101} 102 103static void nf_flow_dnat_ip(const struct flow_offload *flow, 104 struct sk_buff *skb, struct iphdr *iph, 105 unsigned int thoff, enum flow_offload_tuple_dir dir) 106{ 107 __be32 addr, new_addr; 108 109 switch (dir) { 110 case FLOW_OFFLOAD_DIR_ORIGINAL: 111 addr = iph->daddr; 112 new_addr = flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].tuple.src_v4.s_addr; 113 iph->daddr = new_addr; 114 break; 115 case FLOW_OFFLOAD_DIR_REPLY: 116 addr = iph->saddr; 117 new_addr = flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple.dst_v4.s_addr; 118 iph->saddr = new_addr; 119 break; 120 } 121 csum_replace4(&iph->check, addr, new_addr); 122 123 nf_flow_nat_ip_l4proto(skb, iph, thoff, addr, new_addr); 124} 125 126static void nf_flow_nat_ip(const struct flow_offload *flow, struct sk_buff *skb, 127 unsigned int thoff, enum flow_offload_tuple_dir dir, 128 struct iphdr *iph) 129{ 130 if (test_bit(NF_FLOW_SNAT, &flow->flags)) { 131 nf_flow_snat_port(flow, skb, thoff, iph->protocol, dir); 132 nf_flow_snat_ip(flow, skb, iph, thoff, dir); 133 } 134 if (test_bit(NF_FLOW_DNAT, &flow->flags)) { 135 nf_flow_dnat_port(flow, skb, thoff, iph->protocol, dir); 136 nf_flow_dnat_ip(flow, skb, iph, thoff, dir); 137 } 138} 139 140static bool ip_has_options(unsigned int thoff) 141{ 142 return thoff != sizeof(struct iphdr); 143} 144 145static void nf_flow_tuple_encap(struct sk_buff *skb, 146 struct flow_offload_tuple *tuple) 147{ 148 __be16 inner_proto = skb->protocol; 149 struct vlan_ethhdr *veth; 150 struct pppoe_hdr *phdr; 151 struct iphdr *iph; 152 u16 offset = 0; 153 int i = 0; 154 155 if (skb_vlan_tag_present(skb)) { 156 tuple->encap[i].id = skb_vlan_tag_get(skb); 157 tuple->encap[i].proto = skb->vlan_proto; 158 i++; 159 } 160 switch (skb->protocol) { 161 case htons(ETH_P_8021Q): 162 veth = (struct vlan_ethhdr *)skb_mac_header(skb); 163 tuple->encap[i].id = ntohs(veth->h_vlan_TCI); 164 tuple->encap[i].proto = skb->protocol; 165 inner_proto = veth->h_vlan_encapsulated_proto; 166 offset += VLAN_HLEN; 167 break; 168 case htons(ETH_P_PPP_SES): 169 phdr = (struct pppoe_hdr *)skb_network_header(skb); 170 tuple->encap[i].id = ntohs(phdr->sid); 171 tuple->encap[i].proto = skb->protocol; 172 inner_proto = *((__be16 *)(phdr + 1)); 173 offset += PPPOE_SES_HLEN; 174 break; 175 } 176 177 if (inner_proto == htons(ETH_P_IP)) { 178 iph = (struct iphdr *)(skb_network_header(skb) + offset); 179 if (iph->protocol == IPPROTO_IPIP) { 180 tuple->tun.dst_v4.s_addr = iph->daddr; 181 tuple->tun.src_v4.s_addr = iph->saddr; 182 tuple->tun.l3_proto = IPPROTO_IPIP; 183 } 184 } 185} 186 187struct nf_flowtable_ctx { 188 const struct net_device *in; 189 u32 offset; 190 u32 hdrsize; 191}; 192 193static int nf_flow_tuple_ip(struct nf_flowtable_ctx *ctx, struct sk_buff *skb, 194 struct flow_offload_tuple *tuple) 195{ 196 struct flow_ports *ports; 197 unsigned int thoff; 198 struct iphdr *iph; 199 u8 ipproto; 200 201 if (!pskb_may_pull(skb, sizeof(*iph) + ctx->offset)) 202 return -1; 203 204 iph = (struct iphdr *)(skb_network_header(skb) + ctx->offset); 205 thoff = (iph->ihl * 4); 206 207 if (ip_is_fragment(iph) || 208 unlikely(ip_has_options(thoff))) 209 return -1; 210 211 thoff += ctx->offset; 212 213 ipproto = iph->protocol; 214 switch (ipproto) { 215 case IPPROTO_TCP: 216 ctx->hdrsize = sizeof(struct tcphdr); 217 break; 218 case IPPROTO_UDP: 219 ctx->hdrsize = sizeof(struct udphdr); 220 break; 221#ifdef CONFIG_NF_CT_PROTO_GRE 222 case IPPROTO_GRE: 223 ctx->hdrsize = sizeof(struct gre_base_hdr); 224 break; 225#endif 226 default: 227 return -1; 228 } 229 230 if (iph->ttl <= 1) 231 return -1; 232 233 if (!pskb_may_pull(skb, thoff + ctx->hdrsize)) 234 return -1; 235 236 switch (ipproto) { 237 case IPPROTO_TCP: 238 case IPPROTO_UDP: 239 ports = (struct flow_ports *)(skb_network_header(skb) + thoff); 240 tuple->src_port = ports->source; 241 tuple->dst_port = ports->dest; 242 break; 243 case IPPROTO_GRE: { 244 struct gre_base_hdr *greh; 245 246 greh = (struct gre_base_hdr *)(skb_network_header(skb) + thoff); 247 if ((greh->flags & GRE_VERSION) != GRE_VERSION_0) 248 return -1; 249 break; 250 } 251 } 252 253 iph = (struct iphdr *)(skb_network_header(skb) + ctx->offset); 254 255 tuple->src_v4.s_addr = iph->saddr; 256 tuple->dst_v4.s_addr = iph->daddr; 257 tuple->l3proto = AF_INET; 258 tuple->l4proto = ipproto; 259 tuple->iifidx = ctx->in->ifindex; 260 nf_flow_tuple_encap(skb, tuple); 261 262 return 0; 263} 264 265/* Based on ip_exceeds_mtu(). */ 266static bool nf_flow_exceeds_mtu(const struct sk_buff *skb, unsigned int mtu) 267{ 268 if (skb->len <= mtu) 269 return false; 270 271 if (skb_is_gso(skb) && skb_gso_validate_network_len(skb, mtu)) 272 return false; 273 274 return true; 275} 276 277static inline bool nf_flow_dst_check(struct flow_offload_tuple *tuple) 278{ 279 if (tuple->xmit_type != FLOW_OFFLOAD_XMIT_NEIGH && 280 tuple->xmit_type != FLOW_OFFLOAD_XMIT_XFRM) 281 return true; 282 283 return dst_check(tuple->dst_cache, tuple->dst_cookie); 284} 285 286static unsigned int nf_flow_xmit_xfrm(struct sk_buff *skb, 287 const struct nf_hook_state *state, 288 struct dst_entry *dst) 289{ 290 skb_orphan(skb); 291 skb_dst_set_noref(skb, dst); 292 dst_output(state->net, state->sk, skb); 293 return NF_STOLEN; 294} 295 296static bool nf_flow_ip4_tunnel_proto(struct sk_buff *skb, u32 *psize) 297{ 298 struct iphdr *iph; 299 u16 size; 300 301 if (!pskb_may_pull(skb, sizeof(*iph) + *psize)) 302 return false; 303 304 iph = (struct iphdr *)(skb_network_header(skb) + *psize); 305 size = iph->ihl << 2; 306 307 if (ip_is_fragment(iph) || unlikely(ip_has_options(size))) 308 return false; 309 310 if (iph->ttl <= 1) 311 return false; 312 313 if (iph->protocol == IPPROTO_IPIP) 314 *psize += size; 315 316 return true; 317} 318 319static void nf_flow_ip4_tunnel_pop(struct sk_buff *skb) 320{ 321 struct iphdr *iph = (struct iphdr *)skb_network_header(skb); 322 323 if (iph->protocol != IPPROTO_IPIP) 324 return; 325 326 skb_pull(skb, iph->ihl << 2); 327 skb_reset_network_header(skb); 328} 329 330static bool nf_flow_skb_encap_protocol(struct sk_buff *skb, __be16 proto, 331 u32 *offset) 332{ 333 __be16 inner_proto = skb->protocol; 334 struct vlan_ethhdr *veth; 335 bool ret = false; 336 337 switch (skb->protocol) { 338 case htons(ETH_P_8021Q): 339 if (!pskb_may_pull(skb, skb_mac_offset(skb) + sizeof(*veth))) 340 return false; 341 342 veth = (struct vlan_ethhdr *)skb_mac_header(skb); 343 if (veth->h_vlan_encapsulated_proto == proto) { 344 *offset += VLAN_HLEN; 345 inner_proto = proto; 346 ret = true; 347 } 348 break; 349 case htons(ETH_P_PPP_SES): 350 if (nf_flow_pppoe_proto(skb, &inner_proto) && 351 inner_proto == proto) { 352 *offset += PPPOE_SES_HLEN; 353 ret = true; 354 } 355 break; 356 } 357 358 if (inner_proto == htons(ETH_P_IP)) 359 ret = nf_flow_ip4_tunnel_proto(skb, offset); 360 361 return ret; 362} 363 364static void nf_flow_encap_pop(struct sk_buff *skb, 365 struct flow_offload_tuple_rhash *tuplehash) 366{ 367 struct vlan_hdr *vlan_hdr; 368 int i; 369 370 for (i = 0; i < tuplehash->tuple.encap_num; i++) { 371 if (skb_vlan_tag_present(skb)) { 372 __vlan_hwaccel_clear_tag(skb); 373 continue; 374 } 375 switch (skb->protocol) { 376 case htons(ETH_P_8021Q): 377 vlan_hdr = (struct vlan_hdr *)skb->data; 378 __skb_pull(skb, VLAN_HLEN); 379 vlan_set_encap_proto(skb, vlan_hdr); 380 skb_reset_network_header(skb); 381 break; 382 case htons(ETH_P_PPP_SES): 383 skb->protocol = __nf_flow_pppoe_proto(skb); 384 skb_pull(skb, PPPOE_SES_HLEN); 385 skb_reset_network_header(skb); 386 break; 387 } 388 } 389 390 if (skb->protocol == htons(ETH_P_IP)) 391 nf_flow_ip4_tunnel_pop(skb); 392} 393 394struct nf_flow_xmit { 395 const void *dest; 396 const void *source; 397 struct net_device *outdev; 398}; 399 400static unsigned int nf_flow_queue_xmit(struct net *net, struct sk_buff *skb, 401 struct nf_flow_xmit *xmit) 402{ 403 skb->dev = xmit->outdev; 404 dev_hard_header(skb, skb->dev, ntohs(skb->protocol), 405 xmit->dest, xmit->source, skb->len); 406 dev_queue_xmit(skb); 407 408 return NF_STOLEN; 409} 410 411static struct flow_offload_tuple_rhash * 412nf_flow_offload_lookup(struct nf_flowtable_ctx *ctx, 413 struct nf_flowtable *flow_table, struct sk_buff *skb) 414{ 415 struct flow_offload_tuple tuple = {}; 416 417 if (!nf_flow_skb_encap_protocol(skb, htons(ETH_P_IP), &ctx->offset)) 418 return NULL; 419 420 if (nf_flow_tuple_ip(ctx, skb, &tuple) < 0) 421 return NULL; 422 423 return flow_offload_lookup(flow_table, &tuple); 424} 425 426static int nf_flow_offload_forward(struct nf_flowtable_ctx *ctx, 427 struct nf_flowtable *flow_table, 428 struct flow_offload_tuple_rhash *tuplehash, 429 struct sk_buff *skb) 430{ 431 enum flow_offload_tuple_dir dir; 432 struct flow_offload *flow; 433 unsigned int thoff, mtu; 434 struct iphdr *iph; 435 436 dir = tuplehash->tuple.dir; 437 flow = container_of(tuplehash, struct flow_offload, tuplehash[dir]); 438 439 mtu = flow->tuplehash[dir].tuple.mtu + ctx->offset; 440 if (flow->tuplehash[!dir].tuple.tun_num) 441 mtu -= sizeof(*iph); 442 443 if (unlikely(nf_flow_exceeds_mtu(skb, mtu))) 444 return 0; 445 446 iph = (struct iphdr *)(skb_network_header(skb) + ctx->offset); 447 thoff = (iph->ihl * 4) + ctx->offset; 448 if (nf_flow_state_check(flow, iph->protocol, skb, thoff)) 449 return 0; 450 451 if (!nf_flow_dst_check(&tuplehash->tuple)) { 452 flow_offload_teardown(flow); 453 return 0; 454 } 455 456 if (skb_try_make_writable(skb, thoff + ctx->hdrsize)) 457 return -1; 458 459 flow_offload_refresh(flow_table, flow, false); 460 461 nf_flow_encap_pop(skb, tuplehash); 462 thoff -= ctx->offset; 463 464 iph = ip_hdr(skb); 465 nf_flow_nat_ip(flow, skb, thoff, dir, iph); 466 467 ip_decrease_ttl(iph); 468 skb_clear_tstamp(skb); 469 470 if (flow_table->flags & NF_FLOWTABLE_COUNTER) 471 nf_ct_acct_update(flow->ct, tuplehash->tuple.dir, skb->len); 472 473 return 1; 474} 475 476static int nf_flow_pppoe_push(struct sk_buff *skb, u16 id) 477{ 478 int data_len = skb->len + sizeof(__be16); 479 struct ppp_hdr { 480 struct pppoe_hdr hdr; 481 __be16 proto; 482 } *ph; 483 __be16 proto; 484 485 if (skb_cow_head(skb, PPPOE_SES_HLEN)) 486 return -1; 487 488 switch (skb->protocol) { 489 case htons(ETH_P_IP): 490 proto = htons(PPP_IP); 491 break; 492 case htons(ETH_P_IPV6): 493 proto = htons(PPP_IPV6); 494 break; 495 default: 496 return -1; 497 } 498 499 __skb_push(skb, PPPOE_SES_HLEN); 500 skb_reset_network_header(skb); 501 502 ph = (struct ppp_hdr *)(skb->data); 503 ph->hdr.ver = 1; 504 ph->hdr.type = 1; 505 ph->hdr.code = 0; 506 ph->hdr.sid = htons(id); 507 ph->hdr.length = htons(data_len); 508 ph->proto = proto; 509 skb->protocol = htons(ETH_P_PPP_SES); 510 511 return 0; 512} 513 514static int nf_flow_tunnel_ipip_push(struct net *net, struct sk_buff *skb, 515 struct flow_offload_tuple *tuple, 516 __be32 *ip_daddr) 517{ 518 struct iphdr *iph = (struct iphdr *)skb_network_header(skb); 519 struct rtable *rt = dst_rtable(tuple->dst_cache); 520 u8 tos = iph->tos, ttl = iph->ttl; 521 __be16 frag_off = iph->frag_off; 522 u32 headroom = sizeof(*iph); 523 int err; 524 525 err = iptunnel_handle_offloads(skb, SKB_GSO_IPXIP4); 526 if (err) 527 return err; 528 529 skb_set_inner_ipproto(skb, IPPROTO_IPIP); 530 headroom += LL_RESERVED_SPACE(rt->dst.dev) + rt->dst.header_len; 531 err = skb_cow_head(skb, headroom); 532 if (err) 533 return err; 534 535 skb_scrub_packet(skb, true); 536 skb_clear_hash_if_not_l4(skb); 537 538 /* Push down and install the IP header. */ 539 skb_push(skb, sizeof(*iph)); 540 skb_reset_network_header(skb); 541 542 iph = ip_hdr(skb); 543 iph->version = 4; 544 iph->ihl = sizeof(*iph) >> 2; 545 iph->frag_off = ip_mtu_locked(&rt->dst) ? 0 : frag_off; 546 iph->protocol = tuple->tun.l3_proto; 547 iph->tos = tos; 548 iph->daddr = tuple->tun.src_v4.s_addr; 549 iph->saddr = tuple->tun.dst_v4.s_addr; 550 iph->ttl = ttl; 551 iph->tot_len = htons(skb->len); 552 __ip_select_ident(net, iph, skb_shinfo(skb)->gso_segs ?: 1); 553 ip_send_check(iph); 554 555 *ip_daddr = tuple->tun.src_v4.s_addr; 556 557 return 0; 558} 559 560static int nf_flow_tunnel_v4_push(struct net *net, struct sk_buff *skb, 561 struct flow_offload_tuple *tuple, 562 __be32 *ip_daddr) 563{ 564 if (tuple->tun_num) 565 return nf_flow_tunnel_ipip_push(net, skb, tuple, ip_daddr); 566 567 return 0; 568} 569 570static int nf_flow_encap_push(struct sk_buff *skb, 571 struct flow_offload_tuple *tuple) 572{ 573 int i; 574 575 for (i = 0; i < tuple->encap_num; i++) { 576 switch (tuple->encap[i].proto) { 577 case htons(ETH_P_8021Q): 578 case htons(ETH_P_8021AD): 579 skb_reset_mac_header(skb); 580 if (skb_vlan_push(skb, tuple->encap[i].proto, 581 tuple->encap[i].id) < 0) 582 return -1; 583 break; 584 case htons(ETH_P_PPP_SES): 585 if (nf_flow_pppoe_push(skb, tuple->encap[i].id) < 0) 586 return -1; 587 break; 588 } 589 } 590 591 return 0; 592} 593 594unsigned int 595nf_flow_offload_ip_hook(void *priv, struct sk_buff *skb, 596 const struct nf_hook_state *state) 597{ 598 struct flow_offload_tuple_rhash *tuplehash; 599 struct nf_flowtable *flow_table = priv; 600 struct flow_offload_tuple *other_tuple; 601 enum flow_offload_tuple_dir dir; 602 struct nf_flowtable_ctx ctx = { 603 .in = state->in, 604 }; 605 struct nf_flow_xmit xmit = {}; 606 struct flow_offload *flow; 607 struct neighbour *neigh; 608 struct rtable *rt; 609 __be32 ip_daddr; 610 int ret; 611 612 tuplehash = nf_flow_offload_lookup(&ctx, flow_table, skb); 613 if (!tuplehash) 614 return NF_ACCEPT; 615 616 ret = nf_flow_offload_forward(&ctx, flow_table, tuplehash, skb); 617 if (ret < 0) 618 return NF_DROP; 619 else if (ret == 0) 620 return NF_ACCEPT; 621 622 if (unlikely(tuplehash->tuple.xmit_type == FLOW_OFFLOAD_XMIT_XFRM)) { 623 rt = dst_rtable(tuplehash->tuple.dst_cache); 624 memset(skb->cb, 0, sizeof(struct inet_skb_parm)); 625 IPCB(skb)->iif = skb->dev->ifindex; 626 IPCB(skb)->flags = IPSKB_FORWARDED; 627 return nf_flow_xmit_xfrm(skb, state, &rt->dst); 628 } 629 630 dir = tuplehash->tuple.dir; 631 flow = container_of(tuplehash, struct flow_offload, tuplehash[dir]); 632 other_tuple = &flow->tuplehash[!dir].tuple; 633 ip_daddr = other_tuple->src_v4.s_addr; 634 635 if (nf_flow_tunnel_v4_push(state->net, skb, other_tuple, &ip_daddr) < 0) 636 return NF_DROP; 637 638 if (nf_flow_encap_push(skb, other_tuple) < 0) 639 return NF_DROP; 640 641 switch (tuplehash->tuple.xmit_type) { 642 case FLOW_OFFLOAD_XMIT_NEIGH: 643 rt = dst_rtable(tuplehash->tuple.dst_cache); 644 xmit.outdev = dev_get_by_index_rcu(state->net, tuplehash->tuple.ifidx); 645 if (!xmit.outdev) { 646 flow_offload_teardown(flow); 647 return NF_DROP; 648 } 649 neigh = ip_neigh_gw4(rt->dst.dev, rt_nexthop(rt, ip_daddr)); 650 if (IS_ERR(neigh)) { 651 flow_offload_teardown(flow); 652 return NF_DROP; 653 } 654 xmit.dest = neigh->ha; 655 skb_dst_set_noref(skb, &rt->dst); 656 break; 657 case FLOW_OFFLOAD_XMIT_DIRECT: 658 xmit.outdev = dev_get_by_index_rcu(state->net, tuplehash->tuple.out.ifidx); 659 if (!xmit.outdev) { 660 flow_offload_teardown(flow); 661 return NF_DROP; 662 } 663 xmit.dest = tuplehash->tuple.out.h_dest; 664 xmit.source = tuplehash->tuple.out.h_source; 665 break; 666 default: 667 WARN_ON_ONCE(1); 668 return NF_DROP; 669 } 670 671 return nf_flow_queue_xmit(state->net, skb, &xmit); 672} 673EXPORT_SYMBOL_GPL(nf_flow_offload_ip_hook); 674 675static void nf_flow_nat_ipv6_tcp(struct sk_buff *skb, unsigned int thoff, 676 struct in6_addr *addr, 677 struct in6_addr *new_addr, 678 struct ipv6hdr *ip6h) 679{ 680 struct tcphdr *tcph; 681 682 tcph = (void *)(skb_network_header(skb) + thoff); 683 inet_proto_csum_replace16(&tcph->check, skb, addr->s6_addr32, 684 new_addr->s6_addr32, true); 685} 686 687static void nf_flow_nat_ipv6_udp(struct sk_buff *skb, unsigned int thoff, 688 struct in6_addr *addr, 689 struct in6_addr *new_addr) 690{ 691 struct udphdr *udph; 692 693 udph = (void *)(skb_network_header(skb) + thoff); 694 if (udph->check || skb->ip_summed == CHECKSUM_PARTIAL) { 695 inet_proto_csum_replace16(&udph->check, skb, addr->s6_addr32, 696 new_addr->s6_addr32, true); 697 if (!udph->check) 698 udph->check = CSUM_MANGLED_0; 699 } 700} 701 702static void nf_flow_nat_ipv6_l4proto(struct sk_buff *skb, struct ipv6hdr *ip6h, 703 unsigned int thoff, struct in6_addr *addr, 704 struct in6_addr *new_addr) 705{ 706 switch (ip6h->nexthdr) { 707 case IPPROTO_TCP: 708 nf_flow_nat_ipv6_tcp(skb, thoff, addr, new_addr, ip6h); 709 break; 710 case IPPROTO_UDP: 711 nf_flow_nat_ipv6_udp(skb, thoff, addr, new_addr); 712 break; 713 } 714} 715 716static void nf_flow_snat_ipv6(const struct flow_offload *flow, 717 struct sk_buff *skb, struct ipv6hdr *ip6h, 718 unsigned int thoff, 719 enum flow_offload_tuple_dir dir) 720{ 721 struct in6_addr addr, new_addr; 722 723 switch (dir) { 724 case FLOW_OFFLOAD_DIR_ORIGINAL: 725 addr = ip6h->saddr; 726 new_addr = flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].tuple.dst_v6; 727 ip6h->saddr = new_addr; 728 break; 729 case FLOW_OFFLOAD_DIR_REPLY: 730 addr = ip6h->daddr; 731 new_addr = flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple.src_v6; 732 ip6h->daddr = new_addr; 733 break; 734 } 735 736 nf_flow_nat_ipv6_l4proto(skb, ip6h, thoff, &addr, &new_addr); 737} 738 739static void nf_flow_dnat_ipv6(const struct flow_offload *flow, 740 struct sk_buff *skb, struct ipv6hdr *ip6h, 741 unsigned int thoff, 742 enum flow_offload_tuple_dir dir) 743{ 744 struct in6_addr addr, new_addr; 745 746 switch (dir) { 747 case FLOW_OFFLOAD_DIR_ORIGINAL: 748 addr = ip6h->daddr; 749 new_addr = flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].tuple.src_v6; 750 ip6h->daddr = new_addr; 751 break; 752 case FLOW_OFFLOAD_DIR_REPLY: 753 addr = ip6h->saddr; 754 new_addr = flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple.dst_v6; 755 ip6h->saddr = new_addr; 756 break; 757 } 758 759 nf_flow_nat_ipv6_l4proto(skb, ip6h, thoff, &addr, &new_addr); 760} 761 762static void nf_flow_nat_ipv6(const struct flow_offload *flow, 763 struct sk_buff *skb, 764 enum flow_offload_tuple_dir dir, 765 struct ipv6hdr *ip6h) 766{ 767 unsigned int thoff = sizeof(*ip6h); 768 769 if (test_bit(NF_FLOW_SNAT, &flow->flags)) { 770 nf_flow_snat_port(flow, skb, thoff, ip6h->nexthdr, dir); 771 nf_flow_snat_ipv6(flow, skb, ip6h, thoff, dir); 772 } 773 if (test_bit(NF_FLOW_DNAT, &flow->flags)) { 774 nf_flow_dnat_port(flow, skb, thoff, ip6h->nexthdr, dir); 775 nf_flow_dnat_ipv6(flow, skb, ip6h, thoff, dir); 776 } 777} 778 779static int nf_flow_tuple_ipv6(struct nf_flowtable_ctx *ctx, struct sk_buff *skb, 780 struct flow_offload_tuple *tuple) 781{ 782 struct flow_ports *ports; 783 struct ipv6hdr *ip6h; 784 unsigned int thoff; 785 u8 nexthdr; 786 787 thoff = sizeof(*ip6h) + ctx->offset; 788 if (!pskb_may_pull(skb, thoff)) 789 return -1; 790 791 ip6h = (struct ipv6hdr *)(skb_network_header(skb) + ctx->offset); 792 793 nexthdr = ip6h->nexthdr; 794 switch (nexthdr) { 795 case IPPROTO_TCP: 796 ctx->hdrsize = sizeof(struct tcphdr); 797 break; 798 case IPPROTO_UDP: 799 ctx->hdrsize = sizeof(struct udphdr); 800 break; 801#ifdef CONFIG_NF_CT_PROTO_GRE 802 case IPPROTO_GRE: 803 ctx->hdrsize = sizeof(struct gre_base_hdr); 804 break; 805#endif 806 default: 807 return -1; 808 } 809 810 if (ip6h->hop_limit <= 1) 811 return -1; 812 813 if (!pskb_may_pull(skb, thoff + ctx->hdrsize)) 814 return -1; 815 816 switch (nexthdr) { 817 case IPPROTO_TCP: 818 case IPPROTO_UDP: 819 ports = (struct flow_ports *)(skb_network_header(skb) + thoff); 820 tuple->src_port = ports->source; 821 tuple->dst_port = ports->dest; 822 break; 823 case IPPROTO_GRE: { 824 struct gre_base_hdr *greh; 825 826 greh = (struct gre_base_hdr *)(skb_network_header(skb) + thoff); 827 if ((greh->flags & GRE_VERSION) != GRE_VERSION_0) 828 return -1; 829 break; 830 } 831 } 832 833 ip6h = (struct ipv6hdr *)(skb_network_header(skb) + ctx->offset); 834 835 tuple->src_v6 = ip6h->saddr; 836 tuple->dst_v6 = ip6h->daddr; 837 tuple->l3proto = AF_INET6; 838 tuple->l4proto = nexthdr; 839 tuple->iifidx = ctx->in->ifindex; 840 nf_flow_tuple_encap(skb, tuple); 841 842 return 0; 843} 844 845static int nf_flow_offload_ipv6_forward(struct nf_flowtable_ctx *ctx, 846 struct nf_flowtable *flow_table, 847 struct flow_offload_tuple_rhash *tuplehash, 848 struct sk_buff *skb) 849{ 850 enum flow_offload_tuple_dir dir; 851 struct flow_offload *flow; 852 unsigned int thoff, mtu; 853 struct ipv6hdr *ip6h; 854 855 dir = tuplehash->tuple.dir; 856 flow = container_of(tuplehash, struct flow_offload, tuplehash[dir]); 857 858 mtu = flow->tuplehash[dir].tuple.mtu + ctx->offset; 859 if (unlikely(nf_flow_exceeds_mtu(skb, mtu))) 860 return 0; 861 862 ip6h = (struct ipv6hdr *)(skb_network_header(skb) + ctx->offset); 863 thoff = sizeof(*ip6h) + ctx->offset; 864 if (nf_flow_state_check(flow, ip6h->nexthdr, skb, thoff)) 865 return 0; 866 867 if (!nf_flow_dst_check(&tuplehash->tuple)) { 868 flow_offload_teardown(flow); 869 return 0; 870 } 871 872 if (skb_try_make_writable(skb, thoff + ctx->hdrsize)) 873 return -1; 874 875 flow_offload_refresh(flow_table, flow, false); 876 877 nf_flow_encap_pop(skb, tuplehash); 878 879 ip6h = ipv6_hdr(skb); 880 nf_flow_nat_ipv6(flow, skb, dir, ip6h); 881 882 ip6h->hop_limit--; 883 skb_clear_tstamp(skb); 884 885 if (flow_table->flags & NF_FLOWTABLE_COUNTER) 886 nf_ct_acct_update(flow->ct, tuplehash->tuple.dir, skb->len); 887 888 return 1; 889} 890 891static struct flow_offload_tuple_rhash * 892nf_flow_offload_ipv6_lookup(struct nf_flowtable_ctx *ctx, 893 struct nf_flowtable *flow_table, 894 struct sk_buff *skb) 895{ 896 struct flow_offload_tuple tuple = {}; 897 898 if (skb->protocol != htons(ETH_P_IPV6) && 899 !nf_flow_skb_encap_protocol(skb, htons(ETH_P_IPV6), &ctx->offset)) 900 return NULL; 901 902 if (nf_flow_tuple_ipv6(ctx, skb, &tuple) < 0) 903 return NULL; 904 905 return flow_offload_lookup(flow_table, &tuple); 906} 907 908unsigned int 909nf_flow_offload_ipv6_hook(void *priv, struct sk_buff *skb, 910 const struct nf_hook_state *state) 911{ 912 struct flow_offload_tuple_rhash *tuplehash; 913 struct nf_flowtable *flow_table = priv; 914 struct flow_offload_tuple *other_tuple; 915 enum flow_offload_tuple_dir dir; 916 struct nf_flowtable_ctx ctx = { 917 .in = state->in, 918 }; 919 struct nf_flow_xmit xmit = {}; 920 struct in6_addr *ip6_daddr; 921 struct flow_offload *flow; 922 struct neighbour *neigh; 923 struct rt6_info *rt; 924 int ret; 925 926 tuplehash = nf_flow_offload_ipv6_lookup(&ctx, flow_table, skb); 927 if (tuplehash == NULL) 928 return NF_ACCEPT; 929 930 ret = nf_flow_offload_ipv6_forward(&ctx, flow_table, tuplehash, skb); 931 if (ret < 0) 932 return NF_DROP; 933 else if (ret == 0) 934 return NF_ACCEPT; 935 936 if (unlikely(tuplehash->tuple.xmit_type == FLOW_OFFLOAD_XMIT_XFRM)) { 937 rt = dst_rt6_info(tuplehash->tuple.dst_cache); 938 memset(skb->cb, 0, sizeof(struct inet6_skb_parm)); 939 IP6CB(skb)->iif = skb->dev->ifindex; 940 IP6CB(skb)->flags = IP6SKB_FORWARDED; 941 return nf_flow_xmit_xfrm(skb, state, &rt->dst); 942 } 943 944 dir = tuplehash->tuple.dir; 945 flow = container_of(tuplehash, struct flow_offload, tuplehash[dir]); 946 other_tuple = &flow->tuplehash[!dir].tuple; 947 ip6_daddr = &other_tuple->src_v6; 948 949 if (nf_flow_encap_push(skb, other_tuple) < 0) 950 return NF_DROP; 951 952 switch (tuplehash->tuple.xmit_type) { 953 case FLOW_OFFLOAD_XMIT_NEIGH: 954 rt = dst_rt6_info(tuplehash->tuple.dst_cache); 955 xmit.outdev = dev_get_by_index_rcu(state->net, tuplehash->tuple.ifidx); 956 if (!xmit.outdev) { 957 flow_offload_teardown(flow); 958 return NF_DROP; 959 } 960 neigh = ip_neigh_gw6(rt->dst.dev, rt6_nexthop(rt, ip6_daddr)); 961 if (IS_ERR(neigh)) { 962 flow_offload_teardown(flow); 963 return NF_DROP; 964 } 965 xmit.dest = neigh->ha; 966 skb_dst_set_noref(skb, &rt->dst); 967 break; 968 case FLOW_OFFLOAD_XMIT_DIRECT: 969 xmit.outdev = dev_get_by_index_rcu(state->net, tuplehash->tuple.out.ifidx); 970 if (!xmit.outdev) { 971 flow_offload_teardown(flow); 972 return NF_DROP; 973 } 974 xmit.dest = tuplehash->tuple.out.h_dest; 975 xmit.source = tuplehash->tuple.out.h_source; 976 break; 977 default: 978 WARN_ON_ONCE(1); 979 return NF_DROP; 980 } 981 982 return nf_flow_queue_xmit(state->net, skb, &xmit); 983} 984EXPORT_SYMBOL_GPL(nf_flow_offload_ipv6_hook);
~/
Read-only file preview.