xref: /openbmc/linux/net/netfilter/nft_payload.c (revision c040c748)
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 <net/gre.h>
23 #include <linux/icmpv6.h>
24 #include <linux/ip.h>
25 #include <linux/ipv6.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) || pkt->fragoff)
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 	case IPPROTO_GRE: {
105 		u32 offset = sizeof(struct gre_base_hdr);
106 		struct gre_base_hdr *gre, _gre;
107 		__be16 version;
108 
109 		gre = skb_header_pointer(pkt->skb, thoff, sizeof(_gre), &_gre);
110 		if (!gre)
111 			return -1;
112 
113 		version = gre->flags & GRE_VERSION;
114 		switch (version) {
115 		case GRE_VERSION_0:
116 			if (gre->flags & GRE_ROUTING)
117 				return -1;
118 
119 			if (gre->flags & GRE_CSUM) {
120 				offset += sizeof_field(struct gre_full_hdr, csum) +
121 					  sizeof_field(struct gre_full_hdr, reserved1);
122 			}
123 			if (gre->flags & GRE_KEY)
124 				offset += sizeof_field(struct gre_full_hdr, key);
125 
126 			if (gre->flags & GRE_SEQ)
127 				offset += sizeof_field(struct gre_full_hdr, seq);
128 			break;
129 		default:
130 			return -1;
131 		}
132 
133 		pkt->inneroff = thoff + offset;
134 		}
135 		break;
136 	case IPPROTO_IPIP:
137 		pkt->inneroff = thoff;
138 		break;
139 	default:
140 		return -1;
141 	}
142 
143 	pkt->flags |= NFT_PKTINFO_INNER;
144 
145 	return 0;
146 }
147 
148 int nft_payload_inner_offset(const struct nft_pktinfo *pkt)
149 {
150 	if (!(pkt->flags & NFT_PKTINFO_INNER) &&
151 	    __nft_payload_inner_offset((struct nft_pktinfo *)pkt) < 0)
152 		return -1;
153 
154 	return pkt->inneroff;
155 }
156 
157 void nft_payload_eval(const struct nft_expr *expr,
158 		      struct nft_regs *regs,
159 		      const struct nft_pktinfo *pkt)
160 {
161 	const struct nft_payload *priv = nft_expr_priv(expr);
162 	const struct sk_buff *skb = pkt->skb;
163 	u32 *dest = &regs->data[priv->dreg];
164 	int offset;
165 
166 	if (priv->len % NFT_REG32_SIZE)
167 		dest[priv->len / NFT_REG32_SIZE] = 0;
168 
169 	switch (priv->base) {
170 	case NFT_PAYLOAD_LL_HEADER:
171 		if (!skb_mac_header_was_set(skb))
172 			goto err;
173 
174 		if (skb_vlan_tag_present(skb) &&
175 		    priv->offset >= offsetof(struct ethhdr, h_proto)) {
176 			if (!nft_payload_copy_vlan(dest, skb,
177 						   priv->offset, priv->len))
178 				goto err;
179 			return;
180 		}
181 		offset = skb_mac_header(skb) - skb->data;
182 		break;
183 	case NFT_PAYLOAD_NETWORK_HEADER:
184 		offset = skb_network_offset(skb);
185 		break;
186 	case NFT_PAYLOAD_TRANSPORT_HEADER:
187 		if (!(pkt->flags & NFT_PKTINFO_L4PROTO) || pkt->fragoff)
188 			goto err;
189 		offset = nft_thoff(pkt);
190 		break;
191 	case NFT_PAYLOAD_INNER_HEADER:
192 		offset = nft_payload_inner_offset(pkt);
193 		if (offset < 0)
194 			goto err;
195 		break;
196 	default:
197 		WARN_ON_ONCE(1);
198 		goto err;
199 	}
200 	offset += priv->offset;
201 
202 	if (skb_copy_bits(skb, offset, dest, priv->len) < 0)
203 		goto err;
204 	return;
205 err:
206 	regs->verdict.code = NFT_BREAK;
207 }
208 
209 static const struct nla_policy nft_payload_policy[NFTA_PAYLOAD_MAX + 1] = {
210 	[NFTA_PAYLOAD_SREG]		= { .type = NLA_U32 },
211 	[NFTA_PAYLOAD_DREG]		= { .type = NLA_U32 },
212 	[NFTA_PAYLOAD_BASE]		= { .type = NLA_U32 },
213 	[NFTA_PAYLOAD_OFFSET]		= NLA_POLICY_MAX(NLA_BE32, 255),
214 	[NFTA_PAYLOAD_LEN]		= NLA_POLICY_MAX(NLA_BE32, 255),
215 	[NFTA_PAYLOAD_CSUM_TYPE]	= { .type = NLA_U32 },
216 	[NFTA_PAYLOAD_CSUM_OFFSET]	= NLA_POLICY_MAX(NLA_BE32, 255),
217 	[NFTA_PAYLOAD_CSUM_FLAGS]	= { .type = NLA_U32 },
218 };
219 
220 static int nft_payload_init(const struct nft_ctx *ctx,
221 			    const struct nft_expr *expr,
222 			    const struct nlattr * const tb[])
223 {
224 	struct nft_payload *priv = nft_expr_priv(expr);
225 
226 	priv->base   = ntohl(nla_get_be32(tb[NFTA_PAYLOAD_BASE]));
227 	priv->offset = ntohl(nla_get_be32(tb[NFTA_PAYLOAD_OFFSET]));
228 	priv->len    = ntohl(nla_get_be32(tb[NFTA_PAYLOAD_LEN]));
229 
230 	return nft_parse_register_store(ctx, tb[NFTA_PAYLOAD_DREG],
231 					&priv->dreg, NULL, NFT_DATA_VALUE,
232 					priv->len);
233 }
234 
235 static int nft_payload_dump(struct sk_buff *skb,
236 			    const struct nft_expr *expr, bool reset)
237 {
238 	const struct nft_payload *priv = nft_expr_priv(expr);
239 
240 	if (nft_dump_register(skb, NFTA_PAYLOAD_DREG, priv->dreg) ||
241 	    nla_put_be32(skb, NFTA_PAYLOAD_BASE, htonl(priv->base)) ||
242 	    nla_put_be32(skb, NFTA_PAYLOAD_OFFSET, htonl(priv->offset)) ||
243 	    nla_put_be32(skb, NFTA_PAYLOAD_LEN, htonl(priv->len)))
244 		goto nla_put_failure;
245 	return 0;
246 
247 nla_put_failure:
248 	return -1;
249 }
250 
251 static bool nft_payload_reduce(struct nft_regs_track *track,
252 			       const struct nft_expr *expr)
253 {
254 	const struct nft_payload *priv = nft_expr_priv(expr);
255 	const struct nft_payload *payload;
256 
257 	if (!nft_reg_track_cmp(track, expr, priv->dreg)) {
258 		nft_reg_track_update(track, expr, priv->dreg, priv->len);
259 		return false;
260 	}
261 
262 	payload = nft_expr_priv(track->regs[priv->dreg].selector);
263 	if (priv->base != payload->base ||
264 	    priv->offset != payload->offset ||
265 	    priv->len != payload->len) {
266 		nft_reg_track_update(track, expr, priv->dreg, priv->len);
267 		return false;
268 	}
269 
270 	if (!track->regs[priv->dreg].bitwise)
271 		return true;
272 
273 	return nft_expr_reduce_bitwise(track, expr);
274 }
275 
276 static bool nft_payload_offload_mask(struct nft_offload_reg *reg,
277 				     u32 priv_len, u32 field_len)
278 {
279 	unsigned int remainder, delta, k;
280 	struct nft_data mask = {};
281 	__be32 remainder_mask;
282 
283 	if (priv_len == field_len) {
284 		memset(&reg->mask, 0xff, priv_len);
285 		return true;
286 	} else if (priv_len > field_len) {
287 		return false;
288 	}
289 
290 	memset(&mask, 0xff, field_len);
291 	remainder = priv_len % sizeof(u32);
292 	if (remainder) {
293 		k = priv_len / sizeof(u32);
294 		delta = field_len - priv_len;
295 		remainder_mask = htonl(~((1 << (delta * BITS_PER_BYTE)) - 1));
296 		mask.data[k] = (__force u32)remainder_mask;
297 	}
298 
299 	memcpy(&reg->mask, &mask, field_len);
300 
301 	return true;
302 }
303 
304 static int nft_payload_offload_ll(struct nft_offload_ctx *ctx,
305 				  struct nft_flow_rule *flow,
306 				  const struct nft_payload *priv)
307 {
308 	struct nft_offload_reg *reg = &ctx->regs[priv->dreg];
309 
310 	switch (priv->offset) {
311 	case offsetof(struct ethhdr, h_source):
312 		if (!nft_payload_offload_mask(reg, priv->len, ETH_ALEN))
313 			return -EOPNOTSUPP;
314 
315 		NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_ETH_ADDRS, eth_addrs,
316 				  src, ETH_ALEN, reg);
317 		break;
318 	case offsetof(struct ethhdr, h_dest):
319 		if (!nft_payload_offload_mask(reg, priv->len, ETH_ALEN))
320 			return -EOPNOTSUPP;
321 
322 		NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_ETH_ADDRS, eth_addrs,
323 				  dst, ETH_ALEN, reg);
324 		break;
325 	case offsetof(struct ethhdr, h_proto):
326 		if (!nft_payload_offload_mask(reg, priv->len, sizeof(__be16)))
327 			return -EOPNOTSUPP;
328 
329 		NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_BASIC, basic,
330 				  n_proto, sizeof(__be16), reg);
331 		nft_offload_set_dependency(ctx, NFT_OFFLOAD_DEP_NETWORK);
332 		break;
333 	case offsetof(struct vlan_ethhdr, h_vlan_TCI):
334 		if (!nft_payload_offload_mask(reg, priv->len, sizeof(__be16)))
335 			return -EOPNOTSUPP;
336 
337 		NFT_OFFLOAD_MATCH_FLAGS(FLOW_DISSECTOR_KEY_VLAN, vlan,
338 					vlan_tci, sizeof(__be16), reg,
339 					NFT_OFFLOAD_F_NETWORK2HOST);
340 		break;
341 	case offsetof(struct vlan_ethhdr, h_vlan_encapsulated_proto):
342 		if (!nft_payload_offload_mask(reg, priv->len, sizeof(__be16)))
343 			return -EOPNOTSUPP;
344 
345 		NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_VLAN, vlan,
346 				  vlan_tpid, sizeof(__be16), reg);
347 		nft_offload_set_dependency(ctx, NFT_OFFLOAD_DEP_NETWORK);
348 		break;
349 	case offsetof(struct vlan_ethhdr, h_vlan_TCI) + sizeof(struct vlan_hdr):
350 		if (!nft_payload_offload_mask(reg, priv->len, sizeof(__be16)))
351 			return -EOPNOTSUPP;
352 
353 		NFT_OFFLOAD_MATCH_FLAGS(FLOW_DISSECTOR_KEY_CVLAN, cvlan,
354 					vlan_tci, sizeof(__be16), reg,
355 					NFT_OFFLOAD_F_NETWORK2HOST);
356 		break;
357 	case offsetof(struct vlan_ethhdr, h_vlan_encapsulated_proto) +
358 							sizeof(struct vlan_hdr):
359 		if (!nft_payload_offload_mask(reg, priv->len, sizeof(__be16)))
360 			return -EOPNOTSUPP;
361 
362 		NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_CVLAN, cvlan,
363 				  vlan_tpid, sizeof(__be16), reg);
364 		nft_offload_set_dependency(ctx, NFT_OFFLOAD_DEP_NETWORK);
365 		break;
366 	default:
367 		return -EOPNOTSUPP;
368 	}
369 
370 	return 0;
371 }
372 
373 static int nft_payload_offload_ip(struct nft_offload_ctx *ctx,
374 				  struct nft_flow_rule *flow,
375 				  const struct nft_payload *priv)
376 {
377 	struct nft_offload_reg *reg = &ctx->regs[priv->dreg];
378 
379 	switch (priv->offset) {
380 	case offsetof(struct iphdr, saddr):
381 		if (!nft_payload_offload_mask(reg, priv->len,
382 					      sizeof(struct in_addr)))
383 			return -EOPNOTSUPP;
384 
385 		NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_IPV4_ADDRS, ipv4, src,
386 				  sizeof(struct in_addr), reg);
387 		nft_flow_rule_set_addr_type(flow, FLOW_DISSECTOR_KEY_IPV4_ADDRS);
388 		break;
389 	case offsetof(struct iphdr, daddr):
390 		if (!nft_payload_offload_mask(reg, priv->len,
391 					      sizeof(struct in_addr)))
392 			return -EOPNOTSUPP;
393 
394 		NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_IPV4_ADDRS, ipv4, dst,
395 				  sizeof(struct in_addr), reg);
396 		nft_flow_rule_set_addr_type(flow, FLOW_DISSECTOR_KEY_IPV4_ADDRS);
397 		break;
398 	case offsetof(struct iphdr, protocol):
399 		if (!nft_payload_offload_mask(reg, priv->len, sizeof(__u8)))
400 			return -EOPNOTSUPP;
401 
402 		NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_BASIC, basic, ip_proto,
403 				  sizeof(__u8), reg);
404 		nft_offload_set_dependency(ctx, NFT_OFFLOAD_DEP_TRANSPORT);
405 		break;
406 	default:
407 		return -EOPNOTSUPP;
408 	}
409 
410 	return 0;
411 }
412 
413 static int nft_payload_offload_ip6(struct nft_offload_ctx *ctx,
414 				  struct nft_flow_rule *flow,
415 				  const struct nft_payload *priv)
416 {
417 	struct nft_offload_reg *reg = &ctx->regs[priv->dreg];
418 
419 	switch (priv->offset) {
420 	case offsetof(struct ipv6hdr, saddr):
421 		if (!nft_payload_offload_mask(reg, priv->len,
422 					      sizeof(struct in6_addr)))
423 			return -EOPNOTSUPP;
424 
425 		NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_IPV6_ADDRS, ipv6, src,
426 				  sizeof(struct in6_addr), reg);
427 		nft_flow_rule_set_addr_type(flow, FLOW_DISSECTOR_KEY_IPV6_ADDRS);
428 		break;
429 	case offsetof(struct ipv6hdr, daddr):
430 		if (!nft_payload_offload_mask(reg, priv->len,
431 					      sizeof(struct in6_addr)))
432 			return -EOPNOTSUPP;
433 
434 		NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_IPV6_ADDRS, ipv6, dst,
435 				  sizeof(struct in6_addr), reg);
436 		nft_flow_rule_set_addr_type(flow, FLOW_DISSECTOR_KEY_IPV6_ADDRS);
437 		break;
438 	case offsetof(struct ipv6hdr, nexthdr):
439 		if (!nft_payload_offload_mask(reg, priv->len, sizeof(__u8)))
440 			return -EOPNOTSUPP;
441 
442 		NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_BASIC, basic, ip_proto,
443 				  sizeof(__u8), reg);
444 		nft_offload_set_dependency(ctx, NFT_OFFLOAD_DEP_TRANSPORT);
445 		break;
446 	default:
447 		return -EOPNOTSUPP;
448 	}
449 
450 	return 0;
451 }
452 
453 static int nft_payload_offload_nh(struct nft_offload_ctx *ctx,
454 				  struct nft_flow_rule *flow,
455 				  const struct nft_payload *priv)
456 {
457 	int err;
458 
459 	switch (ctx->dep.l3num) {
460 	case htons(ETH_P_IP):
461 		err = nft_payload_offload_ip(ctx, flow, priv);
462 		break;
463 	case htons(ETH_P_IPV6):
464 		err = nft_payload_offload_ip6(ctx, flow, priv);
465 		break;
466 	default:
467 		return -EOPNOTSUPP;
468 	}
469 
470 	return err;
471 }
472 
473 static int nft_payload_offload_tcp(struct nft_offload_ctx *ctx,
474 				   struct nft_flow_rule *flow,
475 				   const struct nft_payload *priv)
476 {
477 	struct nft_offload_reg *reg = &ctx->regs[priv->dreg];
478 
479 	switch (priv->offset) {
480 	case offsetof(struct tcphdr, source):
481 		if (!nft_payload_offload_mask(reg, priv->len, sizeof(__be16)))
482 			return -EOPNOTSUPP;
483 
484 		NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_PORTS, tp, src,
485 				  sizeof(__be16), reg);
486 		break;
487 	case offsetof(struct tcphdr, dest):
488 		if (!nft_payload_offload_mask(reg, priv->len, sizeof(__be16)))
489 			return -EOPNOTSUPP;
490 
491 		NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_PORTS, tp, dst,
492 				  sizeof(__be16), reg);
493 		break;
494 	default:
495 		return -EOPNOTSUPP;
496 	}
497 
498 	return 0;
499 }
500 
501 static int nft_payload_offload_udp(struct nft_offload_ctx *ctx,
502 				   struct nft_flow_rule *flow,
503 				   const struct nft_payload *priv)
504 {
505 	struct nft_offload_reg *reg = &ctx->regs[priv->dreg];
506 
507 	switch (priv->offset) {
508 	case offsetof(struct udphdr, source):
509 		if (!nft_payload_offload_mask(reg, priv->len, sizeof(__be16)))
510 			return -EOPNOTSUPP;
511 
512 		NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_PORTS, tp, src,
513 				  sizeof(__be16), reg);
514 		break;
515 	case offsetof(struct udphdr, dest):
516 		if (!nft_payload_offload_mask(reg, priv->len, sizeof(__be16)))
517 			return -EOPNOTSUPP;
518 
519 		NFT_OFFLOAD_MATCH(FLOW_DISSECTOR_KEY_PORTS, tp, dst,
520 				  sizeof(__be16), reg);
521 		break;
522 	default:
523 		return -EOPNOTSUPP;
524 	}
525 
526 	return 0;
527 }
528 
529 static int nft_payload_offload_th(struct nft_offload_ctx *ctx,
530 				  struct nft_flow_rule *flow,
531 				  const struct nft_payload *priv)
532 {
533 	int err;
534 
535 	switch (ctx->dep.protonum) {
536 	case IPPROTO_TCP:
537 		err = nft_payload_offload_tcp(ctx, flow, priv);
538 		break;
539 	case IPPROTO_UDP:
540 		err = nft_payload_offload_udp(ctx, flow, priv);
541 		break;
542 	default:
543 		return -EOPNOTSUPP;
544 	}
545 
546 	return err;
547 }
548 
549 static int nft_payload_offload(struct nft_offload_ctx *ctx,
550 			       struct nft_flow_rule *flow,
551 			       const struct nft_expr *expr)
552 {
553 	const struct nft_payload *priv = nft_expr_priv(expr);
554 	int err;
555 
556 	switch (priv->base) {
557 	case NFT_PAYLOAD_LL_HEADER:
558 		err = nft_payload_offload_ll(ctx, flow, priv);
559 		break;
560 	case NFT_PAYLOAD_NETWORK_HEADER:
561 		err = nft_payload_offload_nh(ctx, flow, priv);
562 		break;
563 	case NFT_PAYLOAD_TRANSPORT_HEADER:
564 		err = nft_payload_offload_th(ctx, flow, priv);
565 		break;
566 	default:
567 		err = -EOPNOTSUPP;
568 		break;
569 	}
570 	return err;
571 }
572 
573 static const struct nft_expr_ops nft_payload_ops = {
574 	.type		= &nft_payload_type,
575 	.size		= NFT_EXPR_SIZE(sizeof(struct nft_payload)),
576 	.eval		= nft_payload_eval,
577 	.init		= nft_payload_init,
578 	.dump		= nft_payload_dump,
579 	.reduce		= nft_payload_reduce,
580 	.offload	= nft_payload_offload,
581 };
582 
583 const struct nft_expr_ops nft_payload_fast_ops = {
584 	.type		= &nft_payload_type,
585 	.size		= NFT_EXPR_SIZE(sizeof(struct nft_payload)),
586 	.eval		= nft_payload_eval,
587 	.init		= nft_payload_init,
588 	.dump		= nft_payload_dump,
589 	.reduce		= nft_payload_reduce,
590 	.offload	= nft_payload_offload,
591 };
592 
593 void nft_payload_inner_eval(const struct nft_expr *expr, struct nft_regs *regs,
594 			    const struct nft_pktinfo *pkt,
595 			    struct nft_inner_tun_ctx *tun_ctx)
596 {
597 	const struct nft_payload *priv = nft_expr_priv(expr);
598 	const struct sk_buff *skb = pkt->skb;
599 	u32 *dest = &regs->data[priv->dreg];
600 	int offset;
601 
602 	if (priv->len % NFT_REG32_SIZE)
603 		dest[priv->len / NFT_REG32_SIZE] = 0;
604 
605 	switch (priv->base) {
606 	case NFT_PAYLOAD_TUN_HEADER:
607 		if (!(tun_ctx->flags & NFT_PAYLOAD_CTX_INNER_TUN))
608 			goto err;
609 
610 		offset = tun_ctx->inner_tunoff;
611 		break;
612 	case NFT_PAYLOAD_LL_HEADER:
613 		if (!(tun_ctx->flags & NFT_PAYLOAD_CTX_INNER_LL))
614 			goto err;
615 
616 		offset = tun_ctx->inner_lloff;
617 		break;
618 	case NFT_PAYLOAD_NETWORK_HEADER:
619 		if (!(tun_ctx->flags & NFT_PAYLOAD_CTX_INNER_NH))
620 			goto err;
621 
622 		offset = tun_ctx->inner_nhoff;
623 		break;
624 	case NFT_PAYLOAD_TRANSPORT_HEADER:
625 		if (!(tun_ctx->flags & NFT_PAYLOAD_CTX_INNER_TH))
626 			goto err;
627 
628 		offset = tun_ctx->inner_thoff;
629 		break;
630 	default:
631 		WARN_ON_ONCE(1);
632 		goto err;
633 	}
634 	offset += priv->offset;
635 
636 	if (skb_copy_bits(skb, offset, dest, priv->len) < 0)
637 		goto err;
638 
639 	return;
640 err:
641 	regs->verdict.code = NFT_BREAK;
642 }
643 
644 static int nft_payload_inner_init(const struct nft_ctx *ctx,
645 				  const struct nft_expr *expr,
646 				  const struct nlattr * const tb[])
647 {
648 	struct nft_payload *priv = nft_expr_priv(expr);
649 	u32 base;
650 
651 	base   = ntohl(nla_get_be32(tb[NFTA_PAYLOAD_BASE]));
652 	switch (base) {
653 	case NFT_PAYLOAD_TUN_HEADER:
654 	case NFT_PAYLOAD_LL_HEADER:
655 	case NFT_PAYLOAD_NETWORK_HEADER:
656 	case NFT_PAYLOAD_TRANSPORT_HEADER:
657 		break;
658 	default:
659 		return -EOPNOTSUPP;
660 	}
661 
662 	priv->base   = base;
663 	priv->offset = ntohl(nla_get_be32(tb[NFTA_PAYLOAD_OFFSET]));
664 	priv->len    = ntohl(nla_get_be32(tb[NFTA_PAYLOAD_LEN]));
665 
666 	return nft_parse_register_store(ctx, tb[NFTA_PAYLOAD_DREG],
667 					&priv->dreg, NULL, NFT_DATA_VALUE,
668 					priv->len);
669 }
670 
671 static const struct nft_expr_ops nft_payload_inner_ops = {
672 	.type		= &nft_payload_type,
673 	.size		= NFT_EXPR_SIZE(sizeof(struct nft_payload)),
674 	.init		= nft_payload_inner_init,
675 	.dump		= nft_payload_dump,
676 	/* direct call to nft_payload_inner_eval(). */
677 };
678 
679 static inline void nft_csum_replace(__sum16 *sum, __wsum fsum, __wsum tsum)
680 {
681 	*sum = csum_fold(csum_add(csum_sub(~csum_unfold(*sum), fsum), tsum));
682 	if (*sum == 0)
683 		*sum = CSUM_MANGLED_0;
684 }
685 
686 static bool nft_payload_udp_checksum(struct sk_buff *skb, unsigned int thoff)
687 {
688 	struct udphdr *uh, _uh;
689 
690 	uh = skb_header_pointer(skb, thoff, sizeof(_uh), &_uh);
691 	if (!uh)
692 		return false;
693 
694 	return (__force bool)uh->check;
695 }
696 
697 static int nft_payload_l4csum_offset(const struct nft_pktinfo *pkt,
698 				     struct sk_buff *skb,
699 				     unsigned int *l4csum_offset)
700 {
701 	if (pkt->fragoff)
702 		return -1;
703 
704 	switch (pkt->tprot) {
705 	case IPPROTO_TCP:
706 		*l4csum_offset = offsetof(struct tcphdr, check);
707 		break;
708 	case IPPROTO_UDP:
709 		if (!nft_payload_udp_checksum(skb, nft_thoff(pkt)))
710 			return -1;
711 		fallthrough;
712 	case IPPROTO_UDPLITE:
713 		*l4csum_offset = offsetof(struct udphdr, check);
714 		break;
715 	case IPPROTO_ICMPV6:
716 		*l4csum_offset = offsetof(struct icmp6hdr, icmp6_cksum);
717 		break;
718 	default:
719 		return -1;
720 	}
721 
722 	*l4csum_offset += nft_thoff(pkt);
723 	return 0;
724 }
725 
726 static int nft_payload_csum_sctp(struct sk_buff *skb, int offset)
727 {
728 	struct sctphdr *sh;
729 
730 	if (skb_ensure_writable(skb, offset + sizeof(*sh)))
731 		return -1;
732 
733 	sh = (struct sctphdr *)(skb->data + offset);
734 	sh->checksum = sctp_compute_cksum(skb, offset);
735 	skb->ip_summed = CHECKSUM_UNNECESSARY;
736 	return 0;
737 }
738 
739 static int nft_payload_l4csum_update(const struct nft_pktinfo *pkt,
740 				     struct sk_buff *skb,
741 				     __wsum fsum, __wsum tsum)
742 {
743 	int l4csum_offset;
744 	__sum16 sum;
745 
746 	/* If we cannot determine layer 4 checksum offset or this packet doesn't
747 	 * require layer 4 checksum recalculation, skip this packet.
748 	 */
749 	if (nft_payload_l4csum_offset(pkt, skb, &l4csum_offset) < 0)
750 		return 0;
751 
752 	if (skb_copy_bits(skb, l4csum_offset, &sum, sizeof(sum)) < 0)
753 		return -1;
754 
755 	/* Checksum mangling for an arbitrary amount of bytes, based on
756 	 * inet_proto_csum_replace*() functions.
757 	 */
758 	if (skb->ip_summed != CHECKSUM_PARTIAL) {
759 		nft_csum_replace(&sum, fsum, tsum);
760 		if (skb->ip_summed == CHECKSUM_COMPLETE) {
761 			skb->csum = ~csum_add(csum_sub(~(skb->csum), fsum),
762 					      tsum);
763 		}
764 	} else {
765 		sum = ~csum_fold(csum_add(csum_sub(csum_unfold(sum), fsum),
766 					  tsum));
767 	}
768 
769 	if (skb_ensure_writable(skb, l4csum_offset + sizeof(sum)) ||
770 	    skb_store_bits(skb, l4csum_offset, &sum, sizeof(sum)) < 0)
771 		return -1;
772 
773 	return 0;
774 }
775 
776 static int nft_payload_csum_inet(struct sk_buff *skb, const u32 *src,
777 				 __wsum fsum, __wsum tsum, int csum_offset)
778 {
779 	__sum16 sum;
780 
781 	if (skb_copy_bits(skb, csum_offset, &sum, sizeof(sum)) < 0)
782 		return -1;
783 
784 	nft_csum_replace(&sum, fsum, tsum);
785 	if (skb_ensure_writable(skb, csum_offset + sizeof(sum)) ||
786 	    skb_store_bits(skb, csum_offset, &sum, sizeof(sum)) < 0)
787 		return -1;
788 
789 	return 0;
790 }
791 
792 struct nft_payload_set {
793 	enum nft_payload_bases	base:8;
794 	u8			offset;
795 	u8			len;
796 	u8			sreg;
797 	u8			csum_type;
798 	u8			csum_offset;
799 	u8			csum_flags;
800 };
801 
802 static void nft_payload_set_eval(const struct nft_expr *expr,
803 				 struct nft_regs *regs,
804 				 const struct nft_pktinfo *pkt)
805 {
806 	const struct nft_payload_set *priv = nft_expr_priv(expr);
807 	struct sk_buff *skb = pkt->skb;
808 	const u32 *src = &regs->data[priv->sreg];
809 	int offset, csum_offset;
810 	__wsum fsum, tsum;
811 
812 	switch (priv->base) {
813 	case NFT_PAYLOAD_LL_HEADER:
814 		if (!skb_mac_header_was_set(skb))
815 			goto err;
816 		offset = skb_mac_header(skb) - skb->data;
817 		break;
818 	case NFT_PAYLOAD_NETWORK_HEADER:
819 		offset = skb_network_offset(skb);
820 		break;
821 	case NFT_PAYLOAD_TRANSPORT_HEADER:
822 		if (!(pkt->flags & NFT_PKTINFO_L4PROTO) || pkt->fragoff)
823 			goto err;
824 		offset = nft_thoff(pkt);
825 		break;
826 	case NFT_PAYLOAD_INNER_HEADER:
827 		offset = nft_payload_inner_offset(pkt);
828 		if (offset < 0)
829 			goto err;
830 		break;
831 	default:
832 		WARN_ON_ONCE(1);
833 		goto err;
834 	}
835 
836 	csum_offset = offset + priv->csum_offset;
837 	offset += priv->offset;
838 
839 	if ((priv->csum_type == NFT_PAYLOAD_CSUM_INET || priv->csum_flags) &&
840 	    ((priv->base != NFT_PAYLOAD_TRANSPORT_HEADER &&
841 	      priv->base != NFT_PAYLOAD_INNER_HEADER) ||
842 	     skb->ip_summed != CHECKSUM_PARTIAL)) {
843 		fsum = skb_checksum(skb, offset, priv->len, 0);
844 		tsum = csum_partial(src, priv->len, 0);
845 
846 		if (priv->csum_type == NFT_PAYLOAD_CSUM_INET &&
847 		    nft_payload_csum_inet(skb, src, fsum, tsum, csum_offset))
848 			goto err;
849 
850 		if (priv->csum_flags &&
851 		    nft_payload_l4csum_update(pkt, skb, fsum, tsum) < 0)
852 			goto err;
853 	}
854 
855 	if (skb_ensure_writable(skb, max(offset + priv->len, 0)) ||
856 	    skb_store_bits(skb, offset, src, priv->len) < 0)
857 		goto err;
858 
859 	if (priv->csum_type == NFT_PAYLOAD_CSUM_SCTP &&
860 	    pkt->tprot == IPPROTO_SCTP &&
861 	    skb->ip_summed != CHECKSUM_PARTIAL) {
862 		if (pkt->fragoff == 0 &&
863 		    nft_payload_csum_sctp(skb, nft_thoff(pkt)))
864 			goto err;
865 	}
866 
867 	return;
868 err:
869 	regs->verdict.code = NFT_BREAK;
870 }
871 
872 static int nft_payload_set_init(const struct nft_ctx *ctx,
873 				const struct nft_expr *expr,
874 				const struct nlattr * const tb[])
875 {
876 	struct nft_payload_set *priv = nft_expr_priv(expr);
877 	u32 csum_offset, csum_type = NFT_PAYLOAD_CSUM_NONE;
878 	int err;
879 
880 	priv->base        = ntohl(nla_get_be32(tb[NFTA_PAYLOAD_BASE]));
881 	priv->offset      = ntohl(nla_get_be32(tb[NFTA_PAYLOAD_OFFSET]));
882 	priv->len         = ntohl(nla_get_be32(tb[NFTA_PAYLOAD_LEN]));
883 
884 	if (tb[NFTA_PAYLOAD_CSUM_TYPE])
885 		csum_type = ntohl(nla_get_be32(tb[NFTA_PAYLOAD_CSUM_TYPE]));
886 	if (tb[NFTA_PAYLOAD_CSUM_OFFSET]) {
887 		err = nft_parse_u32_check(tb[NFTA_PAYLOAD_CSUM_OFFSET], U8_MAX,
888 					  &csum_offset);
889 		if (err < 0)
890 			return err;
891 
892 		priv->csum_offset = csum_offset;
893 	}
894 	if (tb[NFTA_PAYLOAD_CSUM_FLAGS]) {
895 		u32 flags;
896 
897 		flags = ntohl(nla_get_be32(tb[NFTA_PAYLOAD_CSUM_FLAGS]));
898 		if (flags & ~NFT_PAYLOAD_L4CSUM_PSEUDOHDR)
899 			return -EINVAL;
900 
901 		priv->csum_flags = flags;
902 	}
903 
904 	switch (csum_type) {
905 	case NFT_PAYLOAD_CSUM_NONE:
906 	case NFT_PAYLOAD_CSUM_INET:
907 		break;
908 	case NFT_PAYLOAD_CSUM_SCTP:
909 		if (priv->base != NFT_PAYLOAD_TRANSPORT_HEADER)
910 			return -EINVAL;
911 
912 		if (priv->csum_offset != offsetof(struct sctphdr, checksum))
913 			return -EINVAL;
914 		break;
915 	default:
916 		return -EOPNOTSUPP;
917 	}
918 	priv->csum_type = csum_type;
919 
920 	return nft_parse_register_load(tb[NFTA_PAYLOAD_SREG], &priv->sreg,
921 				       priv->len);
922 }
923 
924 static int nft_payload_set_dump(struct sk_buff *skb,
925 				const struct nft_expr *expr, bool reset)
926 {
927 	const struct nft_payload_set *priv = nft_expr_priv(expr);
928 
929 	if (nft_dump_register(skb, NFTA_PAYLOAD_SREG, priv->sreg) ||
930 	    nla_put_be32(skb, NFTA_PAYLOAD_BASE, htonl(priv->base)) ||
931 	    nla_put_be32(skb, NFTA_PAYLOAD_OFFSET, htonl(priv->offset)) ||
932 	    nla_put_be32(skb, NFTA_PAYLOAD_LEN, htonl(priv->len)) ||
933 	    nla_put_be32(skb, NFTA_PAYLOAD_CSUM_TYPE, htonl(priv->csum_type)) ||
934 	    nla_put_be32(skb, NFTA_PAYLOAD_CSUM_OFFSET,
935 			 htonl(priv->csum_offset)) ||
936 	    nla_put_be32(skb, NFTA_PAYLOAD_CSUM_FLAGS, htonl(priv->csum_flags)))
937 		goto nla_put_failure;
938 	return 0;
939 
940 nla_put_failure:
941 	return -1;
942 }
943 
944 static bool nft_payload_set_reduce(struct nft_regs_track *track,
945 				   const struct nft_expr *expr)
946 {
947 	int i;
948 
949 	for (i = 0; i < NFT_REG32_NUM; i++) {
950 		if (!track->regs[i].selector)
951 			continue;
952 
953 		if (track->regs[i].selector->ops != &nft_payload_ops &&
954 		    track->regs[i].selector->ops != &nft_payload_fast_ops)
955 			continue;
956 
957 		__nft_reg_track_cancel(track, i);
958 	}
959 
960 	return false;
961 }
962 
963 static const struct nft_expr_ops nft_payload_set_ops = {
964 	.type		= &nft_payload_type,
965 	.size		= NFT_EXPR_SIZE(sizeof(struct nft_payload_set)),
966 	.eval		= nft_payload_set_eval,
967 	.init		= nft_payload_set_init,
968 	.dump		= nft_payload_set_dump,
969 	.reduce		= nft_payload_set_reduce,
970 };
971 
972 static const struct nft_expr_ops *
973 nft_payload_select_ops(const struct nft_ctx *ctx,
974 		       const struct nlattr * const tb[])
975 {
976 	enum nft_payload_bases base;
977 	unsigned int offset, len;
978 	int err;
979 
980 	if (tb[NFTA_PAYLOAD_BASE] == NULL ||
981 	    tb[NFTA_PAYLOAD_OFFSET] == NULL ||
982 	    tb[NFTA_PAYLOAD_LEN] == NULL)
983 		return ERR_PTR(-EINVAL);
984 
985 	base = ntohl(nla_get_be32(tb[NFTA_PAYLOAD_BASE]));
986 	switch (base) {
987 	case NFT_PAYLOAD_LL_HEADER:
988 	case NFT_PAYLOAD_NETWORK_HEADER:
989 	case NFT_PAYLOAD_TRANSPORT_HEADER:
990 	case NFT_PAYLOAD_INNER_HEADER:
991 		break;
992 	default:
993 		return ERR_PTR(-EOPNOTSUPP);
994 	}
995 
996 	if (tb[NFTA_PAYLOAD_SREG] != NULL) {
997 		if (tb[NFTA_PAYLOAD_DREG] != NULL)
998 			return ERR_PTR(-EINVAL);
999 		return &nft_payload_set_ops;
1000 	}
1001 
1002 	if (tb[NFTA_PAYLOAD_DREG] == NULL)
1003 		return ERR_PTR(-EINVAL);
1004 
1005 	err = nft_parse_u32_check(tb[NFTA_PAYLOAD_OFFSET], U8_MAX, &offset);
1006 	if (err < 0)
1007 		return ERR_PTR(err);
1008 
1009 	err = nft_parse_u32_check(tb[NFTA_PAYLOAD_LEN], U8_MAX, &len);
1010 	if (err < 0)
1011 		return ERR_PTR(err);
1012 
1013 	if (len <= 4 && is_power_of_2(len) && IS_ALIGNED(offset, len) &&
1014 	    base != NFT_PAYLOAD_LL_HEADER && base != NFT_PAYLOAD_INNER_HEADER)
1015 		return &nft_payload_fast_ops;
1016 	else
1017 		return &nft_payload_ops;
1018 }
1019 
1020 struct nft_expr_type nft_payload_type __read_mostly = {
1021 	.name		= "payload",
1022 	.select_ops	= nft_payload_select_ops,
1023 	.inner_ops	= &nft_payload_inner_ops,
1024 	.policy		= nft_payload_policy,
1025 	.maxattr	= NFTA_PAYLOAD_MAX,
1026 	.owner		= THIS_MODULE,
1027 };
1028