1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (c) 2008-2009 Patrick McHardy <kaber@trash.net> 4 * Copyright (c) 2016 Pablo Neira Ayuso <pablo@netfilter.org> 5 * 6 * Development of this code funded by Astaro AG (http://www.astaro.com/) 7 */ 8 9 #include <linux/kernel.h> 10 #include <linux/if_vlan.h> 11 #include <linux/init.h> 12 #include <linux/module.h> 13 #include <linux/netlink.h> 14 #include <linux/netfilter.h> 15 #include <linux/netfilter/nf_tables.h> 16 #include <net/netfilter/nf_tables_core.h> 17 #include <net/netfilter/nf_tables.h> 18 #include <net/netfilter/nf_tables_offload.h> 19 /* For layer 4 checksum field offset. */ 20 #include <linux/tcp.h> 21 #include <linux/udp.h> 22 #include <linux/icmpv6.h> 23 #include <linux/ip.h> 24 #include <linux/ipv6.h> 25 #include <linux/ip.h> 26 #include <net/sctp/checksum.h> 27 28 static bool nft_payload_rebuild_vlan_hdr(const struct sk_buff *skb, int mac_off, 29 struct vlan_ethhdr *veth) 30 { 31 if (skb_copy_bits(skb, mac_off, veth, ETH_HLEN)) 32 return false; 33 34 veth->h_vlan_proto = skb->vlan_proto; 35 veth->h_vlan_TCI = htons(skb_vlan_tag_get(skb)); 36 veth->h_vlan_encapsulated_proto = skb->protocol; 37 38 return true; 39 } 40 41 /* add vlan header into the user buffer for if tag was removed by offloads */ 42 static bool 43 nft_payload_copy_vlan(u32 *d, const struct sk_buff *skb, u8 offset, u8 len) 44 { 45 int mac_off = skb_mac_header(skb) - skb->data; 46 u8 *vlanh, *dst_u8 = (u8 *) d; 47 struct vlan_ethhdr veth; 48 u8 vlan_hlen = 0; 49 50 if ((skb->protocol == htons(ETH_P_8021AD) || 51 skb->protocol == htons(ETH_P_8021Q)) && 52 offset >= VLAN_ETH_HLEN && offset < VLAN_ETH_HLEN + VLAN_HLEN) 53 vlan_hlen += VLAN_HLEN; 54 55 vlanh = (u8 *) &veth; 56 if (offset < VLAN_ETH_HLEN + vlan_hlen) { 57 u8 ethlen = len; 58 59 if (vlan_hlen && 60 skb_copy_bits(skb, mac_off, &veth, VLAN_ETH_HLEN) < 0) 61 return false; 62 else if (!nft_payload_rebuild_vlan_hdr(skb, mac_off, &veth)) 63 return false; 64 65 if (offset + len > VLAN_ETH_HLEN + vlan_hlen) 66 ethlen -= offset + len - VLAN_ETH_HLEN + vlan_hlen; 67 68 memcpy(dst_u8, vlanh + offset - vlan_hlen, ethlen); 69 70 len -= ethlen; 71 if (len == 0) 72 return true; 73 74 dst_u8 += ethlen; 75 offset = ETH_HLEN + vlan_hlen; 76 } else { 77 offset -= VLAN_HLEN + vlan_hlen; 78 } 79 80 return skb_copy_bits(skb, offset + mac_off, dst_u8, len) == 0; 81 } 82 83 static int __nft_payload_inner_offset(struct nft_pktinfo *pkt) 84 { 85 unsigned int thoff = nft_thoff(pkt); 86 87 if (!(pkt->flags & NFT_PKTINFO_L4PROTO)) 88 return -1; 89 90 switch (pkt->tprot) { 91 case IPPROTO_UDP: 92 pkt->inneroff = thoff + sizeof(struct udphdr); 93 break; 94 case IPPROTO_TCP: { 95 struct tcphdr *th, _tcph; 96 97 th = skb_header_pointer(pkt->skb, thoff, sizeof(_tcph), &_tcph); 98 if (!th) 99 return -1; 100 101 pkt->inneroff = thoff + __tcp_hdrlen(th); 102 } 103 break; 104 default: 105 return -1; 106 } 107 108 pkt->flags |= NFT_PKTINFO_INNER; 109 110 return 0; 111 } 112 113 static int nft_payload_inner_offset(const struct nft_pktinfo *pkt) 114 { 115 if (!(pkt->flags & NFT_PKTINFO_INNER) && 116 __nft_payload_inner_offset((struct nft_pktinfo *)pkt) < 0) 117 return -1; 118 119 return pkt->inneroff; 120 } 121 122 void nft_payload_eval(const struct nft_expr *expr, 123 struct nft_regs *regs, 124 const struct nft_pktinfo *pkt) 125 { 126 const struct nft_payload *priv = nft_expr_priv(expr); 127 const struct sk_buff *skb = pkt->skb; 128 u32 *dest = ®s->data[priv->dreg]; 129 int offset; 130 131 if (priv->len % NFT_REG32_SIZE) 132 dest[priv->len / NFT_REG32_SIZE] = 0; 133 134 switch (priv->base) { 135 case NFT_PAYLOAD_LL_HEADER: 136 if (!skb_mac_header_was_set(skb)) 137 goto err; 138 139 if (skb_vlan_tag_present(skb)) { 140 if (!nft_payload_copy_vlan(dest, skb, 141 priv->offset, priv->len)) 142 goto err; 143 return; 144 } 145 offset = skb_mac_header(skb) - skb->data; 146 break; 147 case NFT_PAYLOAD_NETWORK_HEADER: 148 offset = skb_network_offset(skb); 149 break; 150 case NFT_PAYLOAD_TRANSPORT_HEADER: 151 if (!(pkt->flags & NFT_PKTINFO_L4PROTO)) 152 goto err; 153 offset = nft_thoff(pkt); 154 break; 155 case NFT_PAYLOAD_INNER_HEADER: 156 offset = nft_payload_inner_offset(pkt); 157 if (offset < 0) 158 goto err; 159 break; 160 default: 161 BUG(); 162 } 163 offset += priv->offset; 164 165 if (skb_copy_bits(skb, offset, dest, priv->len) < 0) 166 goto err; 167 return; 168 err: 169 regs->verdict.code = NFT_BREAK; 170 } 171 172 static const struct nla_policy nft_payload_policy[NFTA_PAYLOAD_MAX + 1] = { 173 [NFTA_PAYLOAD_SREG] = { .type = NLA_U32 }, 174 [NFTA_PAYLOAD_DREG] = { .type = NLA_U32 }, 175 [NFTA_PAYLOAD_BASE] = { .type = NLA_U32 }, 176 [NFTA_PAYLOAD_OFFSET] = { .type = NLA_U32 }, 177 [NFTA_PAYLOAD_LEN] = { .type = NLA_U32 }, 178 [NFTA_PAYLOAD_CSUM_TYPE] = { .type = NLA_U32 }, 179 [NFTA_PAYLOAD_CSUM_OFFSET] = { .type = NLA_U32 }, 180 [NFTA_PAYLOAD_CSUM_FLAGS] = { .type = NLA_U32 }, 181 }; 182 183 static int nft_payload_init(const struct nft_ctx *ctx, 184 const struct nft_expr *expr, 185 const struct nlattr * const tb[]) 186 { 187 struct nft_payload *priv = nft_expr_priv(expr); 188 189 priv->base = ntohl(nla_get_be32(tb[NFTA_PAYLOAD_BASE])); 190 priv->offset = ntohl(nla_get_be32(tb[NFTA_PAYLOAD_OFFSET])); 191 priv->len = ntohl(nla_get_be32(tb[NFTA_PAYLOAD_LEN])); 192 193 return nft_parse_register_store(ctx, tb[NFTA_PAYLOAD_DREG], 194 &priv->dreg, NULL, NFT_DATA_VALUE, 195 priv->len); 196 } 197 198 static int nft_payload_dump(struct sk_buff *skb, const struct nft_expr *expr) 199 { 200 const struct nft_payload *priv = nft_expr_priv(expr); 201 202 if (nft_dump_register(skb, NFTA_PAYLOAD_DREG, priv->dreg) || 203 nla_put_be32(skb, NFTA_PAYLOAD_BASE, htonl(priv->base)) || 204 nla_put_be32(skb, NFTA_PAYLOAD_OFFSET, htonl(priv->offset)) || 205 nla_put_be32(skb, NFTA_PAYLOAD_LEN, htonl(priv->len))) 206 goto nla_put_failure; 207 return 0; 208 209 nla_put_failure: 210 return -1; 211 } 212 213 static bool nft_payload_offload_mask(struct nft_offload_reg *reg, 214 u32 priv_len, u32 field_len) 215 { 216 unsigned int remainder, delta, k; 217 struct nft_data mask = {}; 218 __be32 remainder_mask; 219 220 if (priv_len == field_len) { 221 memset(®->mask, 0xff, priv_len); 222 return true; 223 } else if (priv_len > field_len) { 224 return false; 225 } 226 227 memset(&mask, 0xff, field_len); 228 remainder = priv_len % sizeof(u32); 229 if (remainder) { 230 k = priv_len / sizeof(u32); 231 delta = field_len - priv_len; 232 remainder_mask = htonl(~((1 << (delta * BITS_PER_BYTE)) - 1)); 233 mask.data[k] = (__force u32)remainder_mask; 234 } 235 236 memcpy(®->mask, &mask, field_len); 237 238 return true; 239 } 240 241 static int nft_payload_offload_ll(struct nft_offload_ctx *ctx, 242 struct nft_flow_rule *flow, 243 const struct nft_payload *priv) 244 { 245 struct nft_offload_reg *reg = &ctx->regs[priv->dreg]; 246 247 switch (priv->offset) { 248 case offsetof(struct ethhdr, h_source): 249 if (!nft_payload_offload_mask(reg, priv->len, ETH_ALEN)) 250 return -EOPNOTSUPP; 251 252 NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_ETH_ADDRS, eth_addrs, 253 src, ETH_ALEN, reg); 254 break; 255 case offsetof(struct ethhdr, h_dest): 256 if (!nft_payload_offload_mask(reg, priv->len, ETH_ALEN)) 257 return -EOPNOTSUPP; 258 259 NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_ETH_ADDRS, eth_addrs, 260 dst, ETH_ALEN, reg); 261 break; 262 case offsetof(struct ethhdr, h_proto): 263 if (!nft_payload_offload_mask(reg, priv->len, sizeof(__be16))) 264 return -EOPNOTSUPP; 265 266 NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_BASIC, basic, 267 n_proto, sizeof(__be16), reg); 268 nft_offload_set_dependency(ctx, NFT_OFFLOAD_DEP_NETWORK); 269 break; 270 case offsetof(struct vlan_ethhdr, h_vlan_TCI): 271 if (!nft_payload_offload_mask(reg, priv->len, sizeof(__be16))) 272 return -EOPNOTSUPP; 273 274 NFT_OFFLOAD_MATCH_FLAGS(FLOW_DISSECTOR_KEY_VLAN, vlan, 275 vlan_tci, sizeof(__be16), reg, 276 NFT_OFFLOAD_F_NETWORK2HOST); 277 break; 278 case offsetof(struct vlan_ethhdr, h_vlan_encapsulated_proto): 279 if (!nft_payload_offload_mask(reg, priv->len, sizeof(__be16))) 280 return -EOPNOTSUPP; 281 282 NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_VLAN, vlan, 283 vlan_tpid, sizeof(__be16), reg); 284 nft_offload_set_dependency(ctx, NFT_OFFLOAD_DEP_NETWORK); 285 break; 286 case offsetof(struct vlan_ethhdr, h_vlan_TCI) + sizeof(struct vlan_hdr): 287 if (!nft_payload_offload_mask(reg, priv->len, sizeof(__be16))) 288 return -EOPNOTSUPP; 289 290 NFT_OFFLOAD_MATCH_FLAGS(FLOW_DISSECTOR_KEY_CVLAN, cvlan, 291 vlan_tci, sizeof(__be16), reg, 292 NFT_OFFLOAD_F_NETWORK2HOST); 293 break; 294 case offsetof(struct vlan_ethhdr, h_vlan_encapsulated_proto) + 295 sizeof(struct vlan_hdr): 296 if (!nft_payload_offload_mask(reg, priv->len, sizeof(__be16))) 297 return -EOPNOTSUPP; 298 299 NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_CVLAN, cvlan, 300 vlan_tpid, sizeof(__be16), reg); 301 nft_offload_set_dependency(ctx, NFT_OFFLOAD_DEP_NETWORK); 302 break; 303 default: 304 return -EOPNOTSUPP; 305 } 306 307 return 0; 308 } 309 310 static int nft_payload_offload_ip(struct nft_offload_ctx *ctx, 311 struct nft_flow_rule *flow, 312 const struct nft_payload *priv) 313 { 314 struct nft_offload_reg *reg = &ctx->regs[priv->dreg]; 315 316 switch (priv->offset) { 317 case offsetof(struct iphdr, saddr): 318 if (!nft_payload_offload_mask(reg, priv->len, 319 sizeof(struct in_addr))) 320 return -EOPNOTSUPP; 321 322 NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_IPV4_ADDRS, ipv4, src, 323 sizeof(struct in_addr), reg); 324 nft_flow_rule_set_addr_type(flow, FLOW_DISSECTOR_KEY_IPV4_ADDRS); 325 break; 326 case offsetof(struct iphdr, daddr): 327 if (!nft_payload_offload_mask(reg, priv->len, 328 sizeof(struct in_addr))) 329 return -EOPNOTSUPP; 330 331 NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_IPV4_ADDRS, ipv4, dst, 332 sizeof(struct in_addr), reg); 333 nft_flow_rule_set_addr_type(flow, FLOW_DISSECTOR_KEY_IPV4_ADDRS); 334 break; 335 case offsetof(struct iphdr, protocol): 336 if (!nft_payload_offload_mask(reg, priv->len, sizeof(__u8))) 337 return -EOPNOTSUPP; 338 339 NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_BASIC, basic, ip_proto, 340 sizeof(__u8), reg); 341 nft_offload_set_dependency(ctx, NFT_OFFLOAD_DEP_TRANSPORT); 342 break; 343 default: 344 return -EOPNOTSUPP; 345 } 346 347 return 0; 348 } 349 350 static int nft_payload_offload_ip6(struct nft_offload_ctx *ctx, 351 struct nft_flow_rule *flow, 352 const struct nft_payload *priv) 353 { 354 struct nft_offload_reg *reg = &ctx->regs[priv->dreg]; 355 356 switch (priv->offset) { 357 case offsetof(struct ipv6hdr, saddr): 358 if (!nft_payload_offload_mask(reg, priv->len, 359 sizeof(struct in6_addr))) 360 return -EOPNOTSUPP; 361 362 NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_IPV6_ADDRS, ipv6, src, 363 sizeof(struct in6_addr), reg); 364 nft_flow_rule_set_addr_type(flow, FLOW_DISSECTOR_KEY_IPV6_ADDRS); 365 break; 366 case offsetof(struct ipv6hdr, daddr): 367 if (!nft_payload_offload_mask(reg, priv->len, 368 sizeof(struct in6_addr))) 369 return -EOPNOTSUPP; 370 371 NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_IPV6_ADDRS, ipv6, dst, 372 sizeof(struct in6_addr), reg); 373 nft_flow_rule_set_addr_type(flow, FLOW_DISSECTOR_KEY_IPV6_ADDRS); 374 break; 375 case offsetof(struct ipv6hdr, nexthdr): 376 if (!nft_payload_offload_mask(reg, priv->len, sizeof(__u8))) 377 return -EOPNOTSUPP; 378 379 NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_BASIC, basic, ip_proto, 380 sizeof(__u8), reg); 381 nft_offload_set_dependency(ctx, NFT_OFFLOAD_DEP_TRANSPORT); 382 break; 383 default: 384 return -EOPNOTSUPP; 385 } 386 387 return 0; 388 } 389 390 static int nft_payload_offload_nh(struct nft_offload_ctx *ctx, 391 struct nft_flow_rule *flow, 392 const struct nft_payload *priv) 393 { 394 int err; 395 396 switch (ctx->dep.l3num) { 397 case htons(ETH_P_IP): 398 err = nft_payload_offload_ip(ctx, flow, priv); 399 break; 400 case htons(ETH_P_IPV6): 401 err = nft_payload_offload_ip6(ctx, flow, priv); 402 break; 403 default: 404 return -EOPNOTSUPP; 405 } 406 407 return err; 408 } 409 410 static int nft_payload_offload_tcp(struct nft_offload_ctx *ctx, 411 struct nft_flow_rule *flow, 412 const struct nft_payload *priv) 413 { 414 struct nft_offload_reg *reg = &ctx->regs[priv->dreg]; 415 416 switch (priv->offset) { 417 case offsetof(struct tcphdr, source): 418 if (!nft_payload_offload_mask(reg, priv->len, sizeof(__be16))) 419 return -EOPNOTSUPP; 420 421 NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_PORTS, tp, src, 422 sizeof(__be16), reg); 423 break; 424 case offsetof(struct tcphdr, dest): 425 if (!nft_payload_offload_mask(reg, priv->len, sizeof(__be16))) 426 return -EOPNOTSUPP; 427 428 NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_PORTS, tp, dst, 429 sizeof(__be16), reg); 430 break; 431 default: 432 return -EOPNOTSUPP; 433 } 434 435 return 0; 436 } 437 438 static int nft_payload_offload_udp(struct nft_offload_ctx *ctx, 439 struct nft_flow_rule *flow, 440 const struct nft_payload *priv) 441 { 442 struct nft_offload_reg *reg = &ctx->regs[priv->dreg]; 443 444 switch (priv->offset) { 445 case offsetof(struct udphdr, source): 446 if (!nft_payload_offload_mask(reg, priv->len, sizeof(__be16))) 447 return -EOPNOTSUPP; 448 449 NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_PORTS, tp, src, 450 sizeof(__be16), reg); 451 break; 452 case offsetof(struct udphdr, dest): 453 if (!nft_payload_offload_mask(reg, priv->len, sizeof(__be16))) 454 return -EOPNOTSUPP; 455 456 NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_PORTS, tp, dst, 457 sizeof(__be16), reg); 458 break; 459 default: 460 return -EOPNOTSUPP; 461 } 462 463 return 0; 464 } 465 466 static int nft_payload_offload_th(struct nft_offload_ctx *ctx, 467 struct nft_flow_rule *flow, 468 const struct nft_payload *priv) 469 { 470 int err; 471 472 switch (ctx->dep.protonum) { 473 case IPPROTO_TCP: 474 err = nft_payload_offload_tcp(ctx, flow, priv); 475 break; 476 case IPPROTO_UDP: 477 err = nft_payload_offload_udp(ctx, flow, priv); 478 break; 479 default: 480 return -EOPNOTSUPP; 481 } 482 483 return err; 484 } 485 486 static int nft_payload_offload(struct nft_offload_ctx *ctx, 487 struct nft_flow_rule *flow, 488 const struct nft_expr *expr) 489 { 490 const struct nft_payload *priv = nft_expr_priv(expr); 491 int err; 492 493 switch (priv->base) { 494 case NFT_PAYLOAD_LL_HEADER: 495 err = nft_payload_offload_ll(ctx, flow, priv); 496 break; 497 case NFT_PAYLOAD_NETWORK_HEADER: 498 err = nft_payload_offload_nh(ctx, flow, priv); 499 break; 500 case NFT_PAYLOAD_TRANSPORT_HEADER: 501 err = nft_payload_offload_th(ctx, flow, priv); 502 break; 503 default: 504 err = -EOPNOTSUPP; 505 break; 506 } 507 return err; 508 } 509 510 static const struct nft_expr_ops nft_payload_ops = { 511 .type = &nft_payload_type, 512 .size = NFT_EXPR_SIZE(sizeof(struct nft_payload)), 513 .eval = nft_payload_eval, 514 .init = nft_payload_init, 515 .dump = nft_payload_dump, 516 .offload = nft_payload_offload, 517 }; 518 519 const struct nft_expr_ops nft_payload_fast_ops = { 520 .type = &nft_payload_type, 521 .size = NFT_EXPR_SIZE(sizeof(struct nft_payload)), 522 .eval = nft_payload_eval, 523 .init = nft_payload_init, 524 .dump = nft_payload_dump, 525 .offload = nft_payload_offload, 526 }; 527 528 static inline void nft_csum_replace(__sum16 *sum, __wsum fsum, __wsum tsum) 529 { 530 *sum = csum_fold(csum_add(csum_sub(~csum_unfold(*sum), fsum), tsum)); 531 if (*sum == 0) 532 *sum = CSUM_MANGLED_0; 533 } 534 535 static bool nft_payload_udp_checksum(struct sk_buff *skb, unsigned int thoff) 536 { 537 struct udphdr *uh, _uh; 538 539 uh = skb_header_pointer(skb, thoff, sizeof(_uh), &_uh); 540 if (!uh) 541 return false; 542 543 return (__force bool)uh->check; 544 } 545 546 static int nft_payload_l4csum_offset(const struct nft_pktinfo *pkt, 547 struct sk_buff *skb, 548 unsigned int *l4csum_offset) 549 { 550 switch (pkt->tprot) { 551 case IPPROTO_TCP: 552 *l4csum_offset = offsetof(struct tcphdr, check); 553 break; 554 case IPPROTO_UDP: 555 if (!nft_payload_udp_checksum(skb, nft_thoff(pkt))) 556 return -1; 557 fallthrough; 558 case IPPROTO_UDPLITE: 559 *l4csum_offset = offsetof(struct udphdr, check); 560 break; 561 case IPPROTO_ICMPV6: 562 *l4csum_offset = offsetof(struct icmp6hdr, icmp6_cksum); 563 break; 564 default: 565 return -1; 566 } 567 568 *l4csum_offset += nft_thoff(pkt); 569 return 0; 570 } 571 572 static int nft_payload_csum_sctp(struct sk_buff *skb, int offset) 573 { 574 struct sctphdr *sh; 575 576 if (skb_ensure_writable(skb, offset + sizeof(*sh))) 577 return -1; 578 579 sh = (struct sctphdr *)(skb->data + offset); 580 sh->checksum = sctp_compute_cksum(skb, offset); 581 skb->ip_summed = CHECKSUM_UNNECESSARY; 582 return 0; 583 } 584 585 static int nft_payload_l4csum_update(const struct nft_pktinfo *pkt, 586 struct sk_buff *skb, 587 __wsum fsum, __wsum tsum) 588 { 589 int l4csum_offset; 590 __sum16 sum; 591 592 /* If we cannot determine layer 4 checksum offset or this packet doesn't 593 * require layer 4 checksum recalculation, skip this packet. 594 */ 595 if (nft_payload_l4csum_offset(pkt, skb, &l4csum_offset) < 0) 596 return 0; 597 598 if (skb_copy_bits(skb, l4csum_offset, &sum, sizeof(sum)) < 0) 599 return -1; 600 601 /* Checksum mangling for an arbitrary amount of bytes, based on 602 * inet_proto_csum_replace*() functions. 603 */ 604 if (skb->ip_summed != CHECKSUM_PARTIAL) { 605 nft_csum_replace(&sum, fsum, tsum); 606 if (skb->ip_summed == CHECKSUM_COMPLETE) { 607 skb->csum = ~csum_add(csum_sub(~(skb->csum), fsum), 608 tsum); 609 } 610 } else { 611 sum = ~csum_fold(csum_add(csum_sub(csum_unfold(sum), fsum), 612 tsum)); 613 } 614 615 if (skb_ensure_writable(skb, l4csum_offset + sizeof(sum)) || 616 skb_store_bits(skb, l4csum_offset, &sum, sizeof(sum)) < 0) 617 return -1; 618 619 return 0; 620 } 621 622 static int nft_payload_csum_inet(struct sk_buff *skb, const u32 *src, 623 __wsum fsum, __wsum tsum, int csum_offset) 624 { 625 __sum16 sum; 626 627 if (skb_copy_bits(skb, csum_offset, &sum, sizeof(sum)) < 0) 628 return -1; 629 630 nft_csum_replace(&sum, fsum, tsum); 631 if (skb_ensure_writable(skb, csum_offset + sizeof(sum)) || 632 skb_store_bits(skb, csum_offset, &sum, sizeof(sum)) < 0) 633 return -1; 634 635 return 0; 636 } 637 638 static void nft_payload_set_eval(const struct nft_expr *expr, 639 struct nft_regs *regs, 640 const struct nft_pktinfo *pkt) 641 { 642 const struct nft_payload_set *priv = nft_expr_priv(expr); 643 struct sk_buff *skb = pkt->skb; 644 const u32 *src = ®s->data[priv->sreg]; 645 int offset, csum_offset; 646 __wsum fsum, tsum; 647 648 switch (priv->base) { 649 case NFT_PAYLOAD_LL_HEADER: 650 if (!skb_mac_header_was_set(skb)) 651 goto err; 652 offset = skb_mac_header(skb) - skb->data; 653 break; 654 case NFT_PAYLOAD_NETWORK_HEADER: 655 offset = skb_network_offset(skb); 656 break; 657 case NFT_PAYLOAD_TRANSPORT_HEADER: 658 if (!(pkt->flags & NFT_PKTINFO_L4PROTO)) 659 goto err; 660 offset = nft_thoff(pkt); 661 break; 662 case NFT_PAYLOAD_INNER_HEADER: 663 offset = nft_payload_inner_offset(pkt); 664 if (offset < 0) 665 goto err; 666 break; 667 default: 668 BUG(); 669 } 670 671 csum_offset = offset + priv->csum_offset; 672 offset += priv->offset; 673 674 if ((priv->csum_type == NFT_PAYLOAD_CSUM_INET || priv->csum_flags) && 675 ((priv->base != NFT_PAYLOAD_TRANSPORT_HEADER && 676 priv->base != NFT_PAYLOAD_INNER_HEADER) || 677 skb->ip_summed != CHECKSUM_PARTIAL)) { 678 fsum = skb_checksum(skb, offset, priv->len, 0); 679 tsum = csum_partial(src, priv->len, 0); 680 681 if (priv->csum_type == NFT_PAYLOAD_CSUM_INET && 682 nft_payload_csum_inet(skb, src, fsum, tsum, csum_offset)) 683 goto err; 684 685 if (priv->csum_flags && 686 nft_payload_l4csum_update(pkt, skb, fsum, tsum) < 0) 687 goto err; 688 } 689 690 if (skb_ensure_writable(skb, max(offset + priv->len, 0)) || 691 skb_store_bits(skb, offset, src, priv->len) < 0) 692 goto err; 693 694 if (priv->csum_type == NFT_PAYLOAD_CSUM_SCTP && 695 pkt->tprot == IPPROTO_SCTP && 696 skb->ip_summed != CHECKSUM_PARTIAL) { 697 if (nft_payload_csum_sctp(skb, nft_thoff(pkt))) 698 goto err; 699 } 700 701 return; 702 err: 703 regs->verdict.code = NFT_BREAK; 704 } 705 706 static int nft_payload_set_init(const struct nft_ctx *ctx, 707 const struct nft_expr *expr, 708 const struct nlattr * const tb[]) 709 { 710 struct nft_payload_set *priv = nft_expr_priv(expr); 711 712 priv->base = ntohl(nla_get_be32(tb[NFTA_PAYLOAD_BASE])); 713 priv->offset = ntohl(nla_get_be32(tb[NFTA_PAYLOAD_OFFSET])); 714 priv->len = ntohl(nla_get_be32(tb[NFTA_PAYLOAD_LEN])); 715 716 if (tb[NFTA_PAYLOAD_CSUM_TYPE]) 717 priv->csum_type = 718 ntohl(nla_get_be32(tb[NFTA_PAYLOAD_CSUM_TYPE])); 719 if (tb[NFTA_PAYLOAD_CSUM_OFFSET]) 720 priv->csum_offset = 721 ntohl(nla_get_be32(tb[NFTA_PAYLOAD_CSUM_OFFSET])); 722 if (tb[NFTA_PAYLOAD_CSUM_FLAGS]) { 723 u32 flags; 724 725 flags = ntohl(nla_get_be32(tb[NFTA_PAYLOAD_CSUM_FLAGS])); 726 if (flags & ~NFT_PAYLOAD_L4CSUM_PSEUDOHDR) 727 return -EINVAL; 728 729 priv->csum_flags = flags; 730 } 731 732 switch (priv->csum_type) { 733 case NFT_PAYLOAD_CSUM_NONE: 734 case NFT_PAYLOAD_CSUM_INET: 735 break; 736 case NFT_PAYLOAD_CSUM_SCTP: 737 if (priv->base != NFT_PAYLOAD_TRANSPORT_HEADER) 738 return -EINVAL; 739 740 if (priv->csum_offset != offsetof(struct sctphdr, checksum)) 741 return -EINVAL; 742 break; 743 default: 744 return -EOPNOTSUPP; 745 } 746 747 return nft_parse_register_load(tb[NFTA_PAYLOAD_SREG], &priv->sreg, 748 priv->len); 749 } 750 751 static int nft_payload_set_dump(struct sk_buff *skb, const struct nft_expr *expr) 752 { 753 const struct nft_payload_set *priv = nft_expr_priv(expr); 754 755 if (nft_dump_register(skb, NFTA_PAYLOAD_SREG, priv->sreg) || 756 nla_put_be32(skb, NFTA_PAYLOAD_BASE, htonl(priv->base)) || 757 nla_put_be32(skb, NFTA_PAYLOAD_OFFSET, htonl(priv->offset)) || 758 nla_put_be32(skb, NFTA_PAYLOAD_LEN, htonl(priv->len)) || 759 nla_put_be32(skb, NFTA_PAYLOAD_CSUM_TYPE, htonl(priv->csum_type)) || 760 nla_put_be32(skb, NFTA_PAYLOAD_CSUM_OFFSET, 761 htonl(priv->csum_offset)) || 762 nla_put_be32(skb, NFTA_PAYLOAD_CSUM_FLAGS, htonl(priv->csum_flags))) 763 goto nla_put_failure; 764 return 0; 765 766 nla_put_failure: 767 return -1; 768 } 769 770 static const struct nft_expr_ops nft_payload_set_ops = { 771 .type = &nft_payload_type, 772 .size = NFT_EXPR_SIZE(sizeof(struct nft_payload_set)), 773 .eval = nft_payload_set_eval, 774 .init = nft_payload_set_init, 775 .dump = nft_payload_set_dump, 776 }; 777 778 static const struct nft_expr_ops * 779 nft_payload_select_ops(const struct nft_ctx *ctx, 780 const struct nlattr * const tb[]) 781 { 782 enum nft_payload_bases base; 783 unsigned int offset, len; 784 785 if (tb[NFTA_PAYLOAD_BASE] == NULL || 786 tb[NFTA_PAYLOAD_OFFSET] == NULL || 787 tb[NFTA_PAYLOAD_LEN] == NULL) 788 return ERR_PTR(-EINVAL); 789 790 base = ntohl(nla_get_be32(tb[NFTA_PAYLOAD_BASE])); 791 switch (base) { 792 case NFT_PAYLOAD_LL_HEADER: 793 case NFT_PAYLOAD_NETWORK_HEADER: 794 case NFT_PAYLOAD_TRANSPORT_HEADER: 795 case NFT_PAYLOAD_INNER_HEADER: 796 break; 797 default: 798 return ERR_PTR(-EOPNOTSUPP); 799 } 800 801 if (tb[NFTA_PAYLOAD_SREG] != NULL) { 802 if (tb[NFTA_PAYLOAD_DREG] != NULL) 803 return ERR_PTR(-EINVAL); 804 return &nft_payload_set_ops; 805 } 806 807 if (tb[NFTA_PAYLOAD_DREG] == NULL) 808 return ERR_PTR(-EINVAL); 809 810 offset = ntohl(nla_get_be32(tb[NFTA_PAYLOAD_OFFSET])); 811 len = ntohl(nla_get_be32(tb[NFTA_PAYLOAD_LEN])); 812 813 if (len <= 4 && is_power_of_2(len) && IS_ALIGNED(offset, len) && 814 base != NFT_PAYLOAD_LL_HEADER && base != NFT_PAYLOAD_INNER_HEADER) 815 return &nft_payload_fast_ops; 816 else 817 return &nft_payload_ops; 818 } 819 820 struct nft_expr_type nft_payload_type __read_mostly = { 821 .name = "payload", 822 .select_ops = nft_payload_select_ops, 823 .policy = nft_payload_policy, 824 .maxattr = NFTA_PAYLOAD_MAX, 825 .owner = THIS_MODULE, 826 }; 827