xref: /openbmc/linux/net/netfilter/nft_payload.c (revision b9f0bfd1)
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 = &regs->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(&reg->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(&reg->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 = &regs->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