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