1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright (c) 2008-2009 Patrick McHardy <kaber@trash.net>
4 * Copyright (c) 2016 Pablo Neira Ayuso <pablo@netfilter.org>
6 * Development of this code funded by Astaro AG (http://www.astaro.com/)
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>
24 #include <linux/ipv6.h>
26 /* add vlan header into the user buffer for if tag was removed by offloads */
28 nft_payload_copy_vlan(u32 *d, const struct sk_buff *skb, u8 offset, u8 len)
30 int mac_off = skb_mac_header(skb) - skb->data;
31 u8 vlan_len, *vlanh, *dst_u8 = (u8 *) d;
32 struct vlan_ethhdr veth;
35 if (offset < ETH_HLEN) {
36 u8 ethlen = min_t(u8, len, ETH_HLEN - offset);
38 if (skb_copy_bits(skb, mac_off, &veth, ETH_HLEN))
41 veth.h_vlan_proto = skb->vlan_proto;
43 memcpy(dst_u8, vlanh + offset, ethlen);
51 } else if (offset >= VLAN_ETH_HLEN) {
56 veth.h_vlan_TCI = htons(skb_vlan_tag_get(skb));
57 veth.h_vlan_encapsulated_proto = skb->protocol;
61 vlan_len = min_t(u8, len, VLAN_ETH_HLEN - offset);
62 memcpy(dst_u8, vlanh, vlan_len);
70 return skb_copy_bits(skb, offset + mac_off, dst_u8, len) == 0;
73 void nft_payload_eval(const struct nft_expr *expr,
74 struct nft_regs *regs,
75 const struct nft_pktinfo *pkt)
77 const struct nft_payload *priv = nft_expr_priv(expr);
78 const struct sk_buff *skb = pkt->skb;
79 u32 *dest = ®s->data[priv->dreg];
82 dest[priv->len / NFT_REG32_SIZE] = 0;
84 case NFT_PAYLOAD_LL_HEADER:
85 if (!skb_mac_header_was_set(skb))
88 if (skb_vlan_tag_present(skb)) {
89 if (!nft_payload_copy_vlan(dest, skb,
90 priv->offset, priv->len))
94 offset = skb_mac_header(skb) - skb->data;
96 case NFT_PAYLOAD_NETWORK_HEADER:
97 offset = skb_network_offset(skb);
99 case NFT_PAYLOAD_TRANSPORT_HEADER:
102 offset = pkt->xt.thoff;
107 offset += priv->offset;
109 if (skb_copy_bits(skb, offset, dest, priv->len) < 0)
113 regs->verdict.code = NFT_BREAK;
116 static const struct nla_policy nft_payload_policy[NFTA_PAYLOAD_MAX + 1] = {
117 [NFTA_PAYLOAD_SREG] = { .type = NLA_U32 },
118 [NFTA_PAYLOAD_DREG] = { .type = NLA_U32 },
119 [NFTA_PAYLOAD_BASE] = { .type = NLA_U32 },
120 [NFTA_PAYLOAD_OFFSET] = { .type = NLA_U32 },
121 [NFTA_PAYLOAD_LEN] = { .type = NLA_U32 },
122 [NFTA_PAYLOAD_CSUM_TYPE] = { .type = NLA_U32 },
123 [NFTA_PAYLOAD_CSUM_OFFSET] = { .type = NLA_U32 },
126 static int nft_payload_init(const struct nft_ctx *ctx,
127 const struct nft_expr *expr,
128 const struct nlattr * const tb[])
130 struct nft_payload *priv = nft_expr_priv(expr);
132 priv->base = ntohl(nla_get_be32(tb[NFTA_PAYLOAD_BASE]));
133 priv->offset = ntohl(nla_get_be32(tb[NFTA_PAYLOAD_OFFSET]));
134 priv->len = ntohl(nla_get_be32(tb[NFTA_PAYLOAD_LEN]));
135 priv->dreg = nft_parse_register(tb[NFTA_PAYLOAD_DREG]);
137 return nft_validate_register_store(ctx, priv->dreg, NULL,
138 NFT_DATA_VALUE, priv->len);
141 static int nft_payload_dump(struct sk_buff *skb, const struct nft_expr *expr)
143 const struct nft_payload *priv = nft_expr_priv(expr);
145 if (nft_dump_register(skb, NFTA_PAYLOAD_DREG, priv->dreg) ||
146 nla_put_be32(skb, NFTA_PAYLOAD_BASE, htonl(priv->base)) ||
147 nla_put_be32(skb, NFTA_PAYLOAD_OFFSET, htonl(priv->offset)) ||
148 nla_put_be32(skb, NFTA_PAYLOAD_LEN, htonl(priv->len)))
149 goto nla_put_failure;
156 static int nft_payload_offload_ll(struct nft_offload_ctx *ctx,
157 struct nft_flow_rule *flow,
158 const struct nft_payload *priv)
160 struct nft_offload_reg *reg = &ctx->regs[priv->dreg];
162 switch (priv->offset) {
163 case offsetof(struct ethhdr, h_source):
164 if (priv->len != ETH_ALEN)
167 NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_ETH_ADDRS, eth_addrs,
170 case offsetof(struct ethhdr, h_dest):
171 if (priv->len != ETH_ALEN)
174 NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_ETH_ADDRS, eth_addrs,
184 static int nft_payload_offload_ip(struct nft_offload_ctx *ctx,
185 struct nft_flow_rule *flow,
186 const struct nft_payload *priv)
188 struct nft_offload_reg *reg = &ctx->regs[priv->dreg];
190 switch (priv->offset) {
191 case offsetof(struct iphdr, saddr):
192 if (priv->len != sizeof(struct in_addr))
195 NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_IPV4_ADDRS, ipv4, src,
196 sizeof(struct in_addr), reg);
198 case offsetof(struct iphdr, daddr):
199 if (priv->len != sizeof(struct in_addr))
202 NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_IPV4_ADDRS, ipv4, dst,
203 sizeof(struct in_addr), reg);
205 case offsetof(struct iphdr, protocol):
206 if (priv->len != sizeof(__u8))
209 NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_BASIC, basic, ip_proto,
211 nft_offload_set_dependency(ctx, NFT_OFFLOAD_DEP_TRANSPORT);
220 static int nft_payload_offload_ip6(struct nft_offload_ctx *ctx,
221 struct nft_flow_rule *flow,
222 const struct nft_payload *priv)
224 struct nft_offload_reg *reg = &ctx->regs[priv->dreg];
226 switch (priv->offset) {
227 case offsetof(struct ipv6hdr, saddr):
228 if (priv->len != sizeof(struct in6_addr))
231 NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_IPV6_ADDRS, ipv6, src,
232 sizeof(struct in6_addr), reg);
234 case offsetof(struct ipv6hdr, daddr):
235 if (priv->len != sizeof(struct in6_addr))
238 NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_IPV6_ADDRS, ipv6, dst,
239 sizeof(struct in6_addr), reg);
241 case offsetof(struct ipv6hdr, nexthdr):
242 if (priv->len != sizeof(__u8))
245 NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_BASIC, basic, ip_proto,
247 nft_offload_set_dependency(ctx, NFT_OFFLOAD_DEP_TRANSPORT);
256 static int nft_payload_offload_nh(struct nft_offload_ctx *ctx,
257 struct nft_flow_rule *flow,
258 const struct nft_payload *priv)
262 switch (ctx->dep.l3num) {
263 case htons(ETH_P_IP):
264 err = nft_payload_offload_ip(ctx, flow, priv);
266 case htons(ETH_P_IPV6):
267 err = nft_payload_offload_ip6(ctx, flow, priv);
276 static int nft_payload_offload_tcp(struct nft_offload_ctx *ctx,
277 struct nft_flow_rule *flow,
278 const struct nft_payload *priv)
280 struct nft_offload_reg *reg = &ctx->regs[priv->dreg];
282 switch (priv->offset) {
283 case offsetof(struct tcphdr, source):
284 if (priv->len != sizeof(__be16))
287 NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_PORTS, tp, src,
288 sizeof(__be16), reg);
290 case offsetof(struct tcphdr, dest):
291 if (priv->len != sizeof(__be16))
294 NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_PORTS, tp, dst,
295 sizeof(__be16), reg);
304 static int nft_payload_offload_udp(struct nft_offload_ctx *ctx,
305 struct nft_flow_rule *flow,
306 const struct nft_payload *priv)
308 struct nft_offload_reg *reg = &ctx->regs[priv->dreg];
310 switch (priv->offset) {
311 case offsetof(struct udphdr, source):
312 if (priv->len != sizeof(__be16))
315 NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_PORTS, tp, src,
316 sizeof(__be16), reg);
318 case offsetof(struct udphdr, dest):
319 if (priv->len != sizeof(__be16))
322 NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_PORTS, tp, dst,
323 sizeof(__be16), reg);
332 static int nft_payload_offload_th(struct nft_offload_ctx *ctx,
333 struct nft_flow_rule *flow,
334 const struct nft_payload *priv)
338 switch (ctx->dep.protonum) {
340 err = nft_payload_offload_tcp(ctx, flow, priv);
343 err = nft_payload_offload_udp(ctx, flow, priv);
352 static int nft_payload_offload(struct nft_offload_ctx *ctx,
353 struct nft_flow_rule *flow,
354 const struct nft_expr *expr)
356 const struct nft_payload *priv = nft_expr_priv(expr);
359 switch (priv->base) {
360 case NFT_PAYLOAD_LL_HEADER:
361 err = nft_payload_offload_ll(ctx, flow, priv);
363 case NFT_PAYLOAD_NETWORK_HEADER:
364 err = nft_payload_offload_nh(ctx, flow, priv);
366 case NFT_PAYLOAD_TRANSPORT_HEADER:
367 err = nft_payload_offload_th(ctx, flow, priv);
376 static const struct nft_expr_ops nft_payload_ops = {
377 .type = &nft_payload_type,
378 .size = NFT_EXPR_SIZE(sizeof(struct nft_payload)),
379 .eval = nft_payload_eval,
380 .init = nft_payload_init,
381 .dump = nft_payload_dump,
382 .offload = nft_payload_offload,
385 const struct nft_expr_ops nft_payload_fast_ops = {
386 .type = &nft_payload_type,
387 .size = NFT_EXPR_SIZE(sizeof(struct nft_payload)),
388 .eval = nft_payload_eval,
389 .init = nft_payload_init,
390 .dump = nft_payload_dump,
391 .offload = nft_payload_offload,
394 static inline void nft_csum_replace(__sum16 *sum, __wsum fsum, __wsum tsum)
396 *sum = csum_fold(csum_add(csum_sub(~csum_unfold(*sum), fsum), tsum));
398 *sum = CSUM_MANGLED_0;
401 static bool nft_payload_udp_checksum(struct sk_buff *skb, unsigned int thoff)
403 struct udphdr *uh, _uh;
405 uh = skb_header_pointer(skb, thoff, sizeof(_uh), &_uh);
409 return (__force bool)uh->check;
412 static int nft_payload_l4csum_offset(const struct nft_pktinfo *pkt,
414 unsigned int *l4csum_offset)
416 switch (pkt->tprot) {
418 *l4csum_offset = offsetof(struct tcphdr, check);
421 if (!nft_payload_udp_checksum(skb, pkt->xt.thoff))
424 case IPPROTO_UDPLITE:
425 *l4csum_offset = offsetof(struct udphdr, check);
428 *l4csum_offset = offsetof(struct icmp6hdr, icmp6_cksum);
434 *l4csum_offset += pkt->xt.thoff;
438 static int nft_payload_l4csum_update(const struct nft_pktinfo *pkt,
440 __wsum fsum, __wsum tsum)
445 /* If we cannot determine layer 4 checksum offset or this packet doesn't
446 * require layer 4 checksum recalculation, skip this packet.
448 if (nft_payload_l4csum_offset(pkt, skb, &l4csum_offset) < 0)
451 if (skb_copy_bits(skb, l4csum_offset, &sum, sizeof(sum)) < 0)
454 /* Checksum mangling for an arbitrary amount of bytes, based on
455 * inet_proto_csum_replace*() functions.
457 if (skb->ip_summed != CHECKSUM_PARTIAL) {
458 nft_csum_replace(&sum, fsum, tsum);
459 if (skb->ip_summed == CHECKSUM_COMPLETE) {
460 skb->csum = ~csum_add(csum_sub(~(skb->csum), fsum),
464 sum = ~csum_fold(csum_add(csum_sub(csum_unfold(sum), fsum),
468 if (skb_ensure_writable(skb, l4csum_offset + sizeof(sum)) ||
469 skb_store_bits(skb, l4csum_offset, &sum, sizeof(sum)) < 0)
475 static int nft_payload_csum_inet(struct sk_buff *skb, const u32 *src,
476 __wsum fsum, __wsum tsum, int csum_offset)
480 if (skb_copy_bits(skb, csum_offset, &sum, sizeof(sum)) < 0)
483 nft_csum_replace(&sum, fsum, tsum);
484 if (skb_ensure_writable(skb, csum_offset + sizeof(sum)) ||
485 skb_store_bits(skb, csum_offset, &sum, sizeof(sum)) < 0)
491 static void nft_payload_set_eval(const struct nft_expr *expr,
492 struct nft_regs *regs,
493 const struct nft_pktinfo *pkt)
495 const struct nft_payload_set *priv = nft_expr_priv(expr);
496 struct sk_buff *skb = pkt->skb;
497 const u32 *src = ®s->data[priv->sreg];
498 int offset, csum_offset;
501 switch (priv->base) {
502 case NFT_PAYLOAD_LL_HEADER:
503 if (!skb_mac_header_was_set(skb))
505 offset = skb_mac_header(skb) - skb->data;
507 case NFT_PAYLOAD_NETWORK_HEADER:
508 offset = skb_network_offset(skb);
510 case NFT_PAYLOAD_TRANSPORT_HEADER:
513 offset = pkt->xt.thoff;
519 csum_offset = offset + priv->csum_offset;
520 offset += priv->offset;
522 if ((priv->csum_type == NFT_PAYLOAD_CSUM_INET || priv->csum_flags) &&
523 (priv->base != NFT_PAYLOAD_TRANSPORT_HEADER ||
524 skb->ip_summed != CHECKSUM_PARTIAL)) {
525 fsum = skb_checksum(skb, offset, priv->len, 0);
526 tsum = csum_partial(src, priv->len, 0);
528 if (priv->csum_type == NFT_PAYLOAD_CSUM_INET &&
529 nft_payload_csum_inet(skb, src, fsum, tsum, csum_offset))
532 if (priv->csum_flags &&
533 nft_payload_l4csum_update(pkt, skb, fsum, tsum) < 0)
537 if (skb_ensure_writable(skb, max(offset + priv->len, 0)) ||
538 skb_store_bits(skb, offset, src, priv->len) < 0)
543 regs->verdict.code = NFT_BREAK;
546 static int nft_payload_set_init(const struct nft_ctx *ctx,
547 const struct nft_expr *expr,
548 const struct nlattr * const tb[])
550 struct nft_payload_set *priv = nft_expr_priv(expr);
552 priv->base = ntohl(nla_get_be32(tb[NFTA_PAYLOAD_BASE]));
553 priv->offset = ntohl(nla_get_be32(tb[NFTA_PAYLOAD_OFFSET]));
554 priv->len = ntohl(nla_get_be32(tb[NFTA_PAYLOAD_LEN]));
555 priv->sreg = nft_parse_register(tb[NFTA_PAYLOAD_SREG]);
557 if (tb[NFTA_PAYLOAD_CSUM_TYPE])
559 ntohl(nla_get_be32(tb[NFTA_PAYLOAD_CSUM_TYPE]));
560 if (tb[NFTA_PAYLOAD_CSUM_OFFSET])
562 ntohl(nla_get_be32(tb[NFTA_PAYLOAD_CSUM_OFFSET]));
563 if (tb[NFTA_PAYLOAD_CSUM_FLAGS]) {
566 flags = ntohl(nla_get_be32(tb[NFTA_PAYLOAD_CSUM_FLAGS]));
567 if (flags & ~NFT_PAYLOAD_L4CSUM_PSEUDOHDR)
570 priv->csum_flags = flags;
573 switch (priv->csum_type) {
574 case NFT_PAYLOAD_CSUM_NONE:
575 case NFT_PAYLOAD_CSUM_INET:
581 return nft_validate_register_load(priv->sreg, priv->len);
584 static int nft_payload_set_dump(struct sk_buff *skb, const struct nft_expr *expr)
586 const struct nft_payload_set *priv = nft_expr_priv(expr);
588 if (nft_dump_register(skb, NFTA_PAYLOAD_SREG, priv->sreg) ||
589 nla_put_be32(skb, NFTA_PAYLOAD_BASE, htonl(priv->base)) ||
590 nla_put_be32(skb, NFTA_PAYLOAD_OFFSET, htonl(priv->offset)) ||
591 nla_put_be32(skb, NFTA_PAYLOAD_LEN, htonl(priv->len)) ||
592 nla_put_be32(skb, NFTA_PAYLOAD_CSUM_TYPE, htonl(priv->csum_type)) ||
593 nla_put_be32(skb, NFTA_PAYLOAD_CSUM_OFFSET,
594 htonl(priv->csum_offset)) ||
595 nla_put_be32(skb, NFTA_PAYLOAD_CSUM_FLAGS, htonl(priv->csum_flags)))
596 goto nla_put_failure;
603 static const struct nft_expr_ops nft_payload_set_ops = {
604 .type = &nft_payload_type,
605 .size = NFT_EXPR_SIZE(sizeof(struct nft_payload_set)),
606 .eval = nft_payload_set_eval,
607 .init = nft_payload_set_init,
608 .dump = nft_payload_set_dump,
611 static const struct nft_expr_ops *
612 nft_payload_select_ops(const struct nft_ctx *ctx,
613 const struct nlattr * const tb[])
615 enum nft_payload_bases base;
616 unsigned int offset, len;
618 if (tb[NFTA_PAYLOAD_BASE] == NULL ||
619 tb[NFTA_PAYLOAD_OFFSET] == NULL ||
620 tb[NFTA_PAYLOAD_LEN] == NULL)
621 return ERR_PTR(-EINVAL);
623 base = ntohl(nla_get_be32(tb[NFTA_PAYLOAD_BASE]));
625 case NFT_PAYLOAD_LL_HEADER:
626 case NFT_PAYLOAD_NETWORK_HEADER:
627 case NFT_PAYLOAD_TRANSPORT_HEADER:
630 return ERR_PTR(-EOPNOTSUPP);
633 if (tb[NFTA_PAYLOAD_SREG] != NULL) {
634 if (tb[NFTA_PAYLOAD_DREG] != NULL)
635 return ERR_PTR(-EINVAL);
636 return &nft_payload_set_ops;
639 if (tb[NFTA_PAYLOAD_DREG] == NULL)
640 return ERR_PTR(-EINVAL);
642 offset = ntohl(nla_get_be32(tb[NFTA_PAYLOAD_OFFSET]));
643 len = ntohl(nla_get_be32(tb[NFTA_PAYLOAD_LEN]));
645 if (len <= 4 && is_power_of_2(len) && IS_ALIGNED(offset, len) &&
646 base != NFT_PAYLOAD_LL_HEADER)
647 return &nft_payload_fast_ops;
649 return &nft_payload_ops;
652 struct nft_expr_type nft_payload_type __read_mostly = {
654 .select_ops = nft_payload_select_ops,
655 .policy = nft_payload_policy,
656 .maxattr = NFTA_PAYLOAD_MAX,
657 .owner = THIS_MODULE,