File Index
Files and directories
Sign in
FILE

nf_flow_table_ip.c

File preview with syntax highlighting.

linux-6.19.14/net/netfilter/nf_flow_table_ip.c C
  1// SPDX-License-Identifier: GPL-2.0-only
  2#include <linux/kernel.h>
  3#include <linux/init.h>
  4#include <linux/module.h>
  5#include <linux/netfilter.h>
  6#include <linux/rhashtable.h>
  7#include <linux/ip.h>
  8#include <linux/ipv6.h>
  9#include <linux/netdevice.h>
 10#include <linux/if_ether.h>
 11#include <net/gso.h>
 12#include <net/ip.h>
 13#include <net/ipv6.h>
 14#include <net/ip6_route.h>
 15#include <net/neighbour.h>
 16#include <net/netfilter/nf_flow_table.h>
 17#include <net/netfilter/nf_conntrack_acct.h>
 18/* For layer 4 checksum field offset. */
 19#include <linux/tcp.h>
 20#include <linux/udp.h>
 21
 22static int nf_flow_state_check(struct flow_offload *flow, int proto,
 23			       struct sk_buff *skb, unsigned int thoff)
 24{
 25	struct tcphdr *tcph;
 26
 27	if (proto != IPPROTO_TCP)
 28		return 0;
 29
 30	tcph = (void *)(skb_network_header(skb) + thoff);
 31	if (tcph->syn && test_bit(NF_FLOW_CLOSING, &flow->flags)) {
 32		flow_offload_teardown(flow);
 33		return -1;
 34	}
 35
 36	if ((tcph->fin || tcph->rst) &&
 37	    !test_bit(NF_FLOW_CLOSING, &flow->flags))
 38		set_bit(NF_FLOW_CLOSING, &flow->flags);
 39
 40	return 0;
 41}
 42
 43static void nf_flow_nat_ip_tcp(struct sk_buff *skb, unsigned int thoff,
 44			       __be32 addr, __be32 new_addr)
 45{
 46	struct tcphdr *tcph;
 47
 48	tcph = (void *)(skb_network_header(skb) + thoff);
 49	inet_proto_csum_replace4(&tcph->check, skb, addr, new_addr, true);
 50}
 51
 52static void nf_flow_nat_ip_udp(struct sk_buff *skb, unsigned int thoff,
 53			       __be32 addr, __be32 new_addr)
 54{
 55	struct udphdr *udph;
 56
 57	udph = (void *)(skb_network_header(skb) + thoff);
 58	if (udph->check || skb->ip_summed == CHECKSUM_PARTIAL) {
 59		inet_proto_csum_replace4(&udph->check, skb, addr,
 60					 new_addr, true);
 61		if (!udph->check)
 62			udph->check = CSUM_MANGLED_0;
 63	}
 64}
 65
 66static void nf_flow_nat_ip_l4proto(struct sk_buff *skb, struct iphdr *iph,
 67				   unsigned int thoff, __be32 addr,
 68				   __be32 new_addr)
 69{
 70	switch (iph->protocol) {
 71	case IPPROTO_TCP:
 72		nf_flow_nat_ip_tcp(skb, thoff, addr, new_addr);
 73		break;
 74	case IPPROTO_UDP:
 75		nf_flow_nat_ip_udp(skb, thoff, addr, new_addr);
 76		break;
 77	}
 78}
 79
 80static void nf_flow_snat_ip(const struct flow_offload *flow,
 81			    struct sk_buff *skb, struct iphdr *iph,
 82			    unsigned int thoff, enum flow_offload_tuple_dir dir)
 83{
 84	__be32 addr, new_addr;
 85
 86	switch (dir) {
 87	case FLOW_OFFLOAD_DIR_ORIGINAL:
 88		addr = iph->saddr;
 89		new_addr = flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].tuple.dst_v4.s_addr;
 90		iph->saddr = new_addr;
 91		break;
 92	case FLOW_OFFLOAD_DIR_REPLY:
 93		addr = iph->daddr;
 94		new_addr = flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple.src_v4.s_addr;
 95		iph->daddr = new_addr;
 96		break;
 97	}
 98	csum_replace4(&iph->check, addr, new_addr);
 99
100	nf_flow_nat_ip_l4proto(skb, iph, thoff, addr, new_addr);
101}
102
103static void nf_flow_dnat_ip(const struct flow_offload *flow,
104			    struct sk_buff *skb, struct iphdr *iph,
105			    unsigned int thoff, enum flow_offload_tuple_dir dir)
106{
107	__be32 addr, new_addr;
108
109	switch (dir) {
110	case FLOW_OFFLOAD_DIR_ORIGINAL:
111		addr = iph->daddr;
112		new_addr = flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].tuple.src_v4.s_addr;
113		iph->daddr = new_addr;
114		break;
115	case FLOW_OFFLOAD_DIR_REPLY:
116		addr = iph->saddr;
117		new_addr = flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple.dst_v4.s_addr;
118		iph->saddr = new_addr;
119		break;
120	}
121	csum_replace4(&iph->check, addr, new_addr);
122
123	nf_flow_nat_ip_l4proto(skb, iph, thoff, addr, new_addr);
124}
125
126static void nf_flow_nat_ip(const struct flow_offload *flow, struct sk_buff *skb,
127			  unsigned int thoff, enum flow_offload_tuple_dir dir,
128			  struct iphdr *iph)
129{
130	if (test_bit(NF_FLOW_SNAT, &flow->flags)) {
131		nf_flow_snat_port(flow, skb, thoff, iph->protocol, dir);
132		nf_flow_snat_ip(flow, skb, iph, thoff, dir);
133	}
134	if (test_bit(NF_FLOW_DNAT, &flow->flags)) {
135		nf_flow_dnat_port(flow, skb, thoff, iph->protocol, dir);
136		nf_flow_dnat_ip(flow, skb, iph, thoff, dir);
137	}
138}
139
140static bool ip_has_options(unsigned int thoff)
141{
142	return thoff != sizeof(struct iphdr);
143}
144
145static void nf_flow_tuple_encap(struct sk_buff *skb,
146				struct flow_offload_tuple *tuple)
147{
148	__be16 inner_proto = skb->protocol;
149	struct vlan_ethhdr *veth;
150	struct pppoe_hdr *phdr;
151	struct iphdr *iph;
152	u16 offset = 0;
153	int i = 0;
154
155	if (skb_vlan_tag_present(skb)) {
156		tuple->encap[i].id = skb_vlan_tag_get(skb);
157		tuple->encap[i].proto = skb->vlan_proto;
158		i++;
159	}
160	switch (skb->protocol) {
161	case htons(ETH_P_8021Q):
162		veth = (struct vlan_ethhdr *)skb_mac_header(skb);
163		tuple->encap[i].id = ntohs(veth->h_vlan_TCI);
164		tuple->encap[i].proto = skb->protocol;
165		inner_proto = veth->h_vlan_encapsulated_proto;
166		offset += VLAN_HLEN;
167		break;
168	case htons(ETH_P_PPP_SES):
169		phdr = (struct pppoe_hdr *)skb_network_header(skb);
170		tuple->encap[i].id = ntohs(phdr->sid);
171		tuple->encap[i].proto = skb->protocol;
172		inner_proto = *((__be16 *)(phdr + 1));
173		offset += PPPOE_SES_HLEN;
174		break;
175	}
176
177	if (inner_proto == htons(ETH_P_IP)) {
178		iph = (struct iphdr *)(skb_network_header(skb) + offset);
179		if (iph->protocol == IPPROTO_IPIP) {
180			tuple->tun.dst_v4.s_addr = iph->daddr;
181			tuple->tun.src_v4.s_addr = iph->saddr;
182			tuple->tun.l3_proto = IPPROTO_IPIP;
183		}
184	}
185}
186
187struct nf_flowtable_ctx {
188	const struct net_device	*in;
189	u32			offset;
190	u32			hdrsize;
191};
192
193static int nf_flow_tuple_ip(struct nf_flowtable_ctx *ctx, struct sk_buff *skb,
194			    struct flow_offload_tuple *tuple)
195{
196	struct flow_ports *ports;
197	unsigned int thoff;
198	struct iphdr *iph;
199	u8 ipproto;
200
201	if (!pskb_may_pull(skb, sizeof(*iph) + ctx->offset))
202		return -1;
203
204	iph = (struct iphdr *)(skb_network_header(skb) + ctx->offset);
205	thoff = (iph->ihl * 4);
206
207	if (ip_is_fragment(iph) ||
208	    unlikely(ip_has_options(thoff)))
209		return -1;
210
211	thoff += ctx->offset;
212
213	ipproto = iph->protocol;
214	switch (ipproto) {
215	case IPPROTO_TCP:
216		ctx->hdrsize = sizeof(struct tcphdr);
217		break;
218	case IPPROTO_UDP:
219		ctx->hdrsize = sizeof(struct udphdr);
220		break;
221#ifdef CONFIG_NF_CT_PROTO_GRE
222	case IPPROTO_GRE:
223		ctx->hdrsize = sizeof(struct gre_base_hdr);
224		break;
225#endif
226	default:
227		return -1;
228	}
229
230	if (iph->ttl <= 1)
231		return -1;
232
233	if (!pskb_may_pull(skb, thoff + ctx->hdrsize))
234		return -1;
235
236	switch (ipproto) {
237	case IPPROTO_TCP:
238	case IPPROTO_UDP:
239		ports = (struct flow_ports *)(skb_network_header(skb) + thoff);
240		tuple->src_port		= ports->source;
241		tuple->dst_port		= ports->dest;
242		break;
243	case IPPROTO_GRE: {
244		struct gre_base_hdr *greh;
245
246		greh = (struct gre_base_hdr *)(skb_network_header(skb) + thoff);
247		if ((greh->flags & GRE_VERSION) != GRE_VERSION_0)
248			return -1;
249		break;
250	}
251	}
252
253	iph = (struct iphdr *)(skb_network_header(skb) + ctx->offset);
254
255	tuple->src_v4.s_addr	= iph->saddr;
256	tuple->dst_v4.s_addr	= iph->daddr;
257	tuple->l3proto		= AF_INET;
258	tuple->l4proto		= ipproto;
259	tuple->iifidx		= ctx->in->ifindex;
260	nf_flow_tuple_encap(skb, tuple);
261
262	return 0;
263}
264
265/* Based on ip_exceeds_mtu(). */
266static bool nf_flow_exceeds_mtu(const struct sk_buff *skb, unsigned int mtu)
267{
268	if (skb->len <= mtu)
269		return false;
270
271	if (skb_is_gso(skb) && skb_gso_validate_network_len(skb, mtu))
272		return false;
273
274	return true;
275}
276
277static inline bool nf_flow_dst_check(struct flow_offload_tuple *tuple)
278{
279	if (tuple->xmit_type != FLOW_OFFLOAD_XMIT_NEIGH &&
280	    tuple->xmit_type != FLOW_OFFLOAD_XMIT_XFRM)
281		return true;
282
283	return dst_check(tuple->dst_cache, tuple->dst_cookie);
284}
285
286static unsigned int nf_flow_xmit_xfrm(struct sk_buff *skb,
287				      const struct nf_hook_state *state,
288				      struct dst_entry *dst)
289{
290	skb_orphan(skb);
291	skb_dst_set_noref(skb, dst);
292	dst_output(state->net, state->sk, skb);
293	return NF_STOLEN;
294}
295
296static bool nf_flow_ip4_tunnel_proto(struct sk_buff *skb, u32 *psize)
297{
298	struct iphdr *iph;
299	u16 size;
300
301	if (!pskb_may_pull(skb, sizeof(*iph) + *psize))
302		return false;
303
304	iph = (struct iphdr *)(skb_network_header(skb) + *psize);
305	size = iph->ihl << 2;
306
307	if (ip_is_fragment(iph) || unlikely(ip_has_options(size)))
308		return false;
309
310	if (iph->ttl <= 1)
311		return false;
312
313	if (iph->protocol == IPPROTO_IPIP)
314		*psize += size;
315
316	return true;
317}
318
319static void nf_flow_ip4_tunnel_pop(struct sk_buff *skb)
320{
321	struct iphdr *iph = (struct iphdr *)skb_network_header(skb);
322
323	if (iph->protocol != IPPROTO_IPIP)
324		return;
325
326	skb_pull(skb, iph->ihl << 2);
327	skb_reset_network_header(skb);
328}
329
330static bool nf_flow_skb_encap_protocol(struct sk_buff *skb, __be16 proto,
331				       u32 *offset)
332{
333	__be16 inner_proto = skb->protocol;
334	struct vlan_ethhdr *veth;
335	bool ret = false;
336
337	switch (skb->protocol) {
338	case htons(ETH_P_8021Q):
339		if (!pskb_may_pull(skb, skb_mac_offset(skb) + sizeof(*veth)))
340			return false;
341
342		veth = (struct vlan_ethhdr *)skb_mac_header(skb);
343		if (veth->h_vlan_encapsulated_proto == proto) {
344			*offset += VLAN_HLEN;
345			inner_proto = proto;
346			ret = true;
347		}
348		break;
349	case htons(ETH_P_PPP_SES):
350		if (nf_flow_pppoe_proto(skb, &inner_proto) &&
351		    inner_proto == proto) {
352			*offset += PPPOE_SES_HLEN;
353			ret = true;
354		}
355		break;
356	}
357
358	if (inner_proto == htons(ETH_P_IP))
359		ret = nf_flow_ip4_tunnel_proto(skb, offset);
360
361	return ret;
362}
363
364static void nf_flow_encap_pop(struct sk_buff *skb,
365			      struct flow_offload_tuple_rhash *tuplehash)
366{
367	struct vlan_hdr *vlan_hdr;
368	int i;
369
370	for (i = 0; i < tuplehash->tuple.encap_num; i++) {
371		if (skb_vlan_tag_present(skb)) {
372			__vlan_hwaccel_clear_tag(skb);
373			continue;
374		}
375		switch (skb->protocol) {
376		case htons(ETH_P_8021Q):
377			vlan_hdr = (struct vlan_hdr *)skb->data;
378			__skb_pull(skb, VLAN_HLEN);
379			vlan_set_encap_proto(skb, vlan_hdr);
380			skb_reset_network_header(skb);
381			break;
382		case htons(ETH_P_PPP_SES):
383			skb->protocol = __nf_flow_pppoe_proto(skb);
384			skb_pull(skb, PPPOE_SES_HLEN);
385			skb_reset_network_header(skb);
386			break;
387		}
388	}
389
390	if (skb->protocol == htons(ETH_P_IP))
391		nf_flow_ip4_tunnel_pop(skb);
392}
393
394struct nf_flow_xmit {
395	const void		*dest;
396	const void		*source;
397	struct net_device	*outdev;
398};
399
400static unsigned int nf_flow_queue_xmit(struct net *net, struct sk_buff *skb,
401				       struct nf_flow_xmit *xmit)
402{
403	skb->dev = xmit->outdev;
404	dev_hard_header(skb, skb->dev, ntohs(skb->protocol),
405			xmit->dest, xmit->source, skb->len);
406	dev_queue_xmit(skb);
407
408	return NF_STOLEN;
409}
410
411static struct flow_offload_tuple_rhash *
412nf_flow_offload_lookup(struct nf_flowtable_ctx *ctx,
413		       struct nf_flowtable *flow_table, struct sk_buff *skb)
414{
415	struct flow_offload_tuple tuple = {};
416
417	if (!nf_flow_skb_encap_protocol(skb, htons(ETH_P_IP), &ctx->offset))
418		return NULL;
419
420	if (nf_flow_tuple_ip(ctx, skb, &tuple) < 0)
421		return NULL;
422
423	return flow_offload_lookup(flow_table, &tuple);
424}
425
426static int nf_flow_offload_forward(struct nf_flowtable_ctx *ctx,
427				   struct nf_flowtable *flow_table,
428				   struct flow_offload_tuple_rhash *tuplehash,
429				   struct sk_buff *skb)
430{
431	enum flow_offload_tuple_dir dir;
432	struct flow_offload *flow;
433	unsigned int thoff, mtu;
434	struct iphdr *iph;
435
436	dir = tuplehash->tuple.dir;
437	flow = container_of(tuplehash, struct flow_offload, tuplehash[dir]);
438
439	mtu = flow->tuplehash[dir].tuple.mtu + ctx->offset;
440	if (flow->tuplehash[!dir].tuple.tun_num)
441		mtu -= sizeof(*iph);
442
443	if (unlikely(nf_flow_exceeds_mtu(skb, mtu)))
444		return 0;
445
446	iph = (struct iphdr *)(skb_network_header(skb) + ctx->offset);
447	thoff = (iph->ihl * 4) + ctx->offset;
448	if (nf_flow_state_check(flow, iph->protocol, skb, thoff))
449		return 0;
450
451	if (!nf_flow_dst_check(&tuplehash->tuple)) {
452		flow_offload_teardown(flow);
453		return 0;
454	}
455
456	if (skb_try_make_writable(skb, thoff + ctx->hdrsize))
457		return -1;
458
459	flow_offload_refresh(flow_table, flow, false);
460
461	nf_flow_encap_pop(skb, tuplehash);
462	thoff -= ctx->offset;
463
464	iph = ip_hdr(skb);
465	nf_flow_nat_ip(flow, skb, thoff, dir, iph);
466
467	ip_decrease_ttl(iph);
468	skb_clear_tstamp(skb);
469
470	if (flow_table->flags & NF_FLOWTABLE_COUNTER)
471		nf_ct_acct_update(flow->ct, tuplehash->tuple.dir, skb->len);
472
473	return 1;
474}
475
476static int nf_flow_pppoe_push(struct sk_buff *skb, u16 id)
477{
478	int data_len = skb->len + sizeof(__be16);
479	struct ppp_hdr {
480		struct pppoe_hdr hdr;
481		__be16 proto;
482	} *ph;
483	__be16 proto;
484
485	if (skb_cow_head(skb, PPPOE_SES_HLEN))
486		return -1;
487
488	switch (skb->protocol) {
489	case htons(ETH_P_IP):
490		proto = htons(PPP_IP);
491		break;
492	case htons(ETH_P_IPV6):
493		proto = htons(PPP_IPV6);
494		break;
495	default:
496		return -1;
497	}
498
499	__skb_push(skb, PPPOE_SES_HLEN);
500	skb_reset_network_header(skb);
501
502	ph = (struct ppp_hdr *)(skb->data);
503	ph->hdr.ver	= 1;
504	ph->hdr.type	= 1;
505	ph->hdr.code	= 0;
506	ph->hdr.sid	= htons(id);
507	ph->hdr.length	= htons(data_len);
508	ph->proto	= proto;
509	skb->protocol	= htons(ETH_P_PPP_SES);
510
511	return 0;
512}
513
514static int nf_flow_tunnel_ipip_push(struct net *net, struct sk_buff *skb,
515				    struct flow_offload_tuple *tuple,
516				    __be32 *ip_daddr)
517{
518	struct iphdr *iph = (struct iphdr *)skb_network_header(skb);
519	struct rtable *rt = dst_rtable(tuple->dst_cache);
520	u8 tos = iph->tos, ttl = iph->ttl;
521	__be16 frag_off = iph->frag_off;
522	u32 headroom = sizeof(*iph);
523	int err;
524
525	err = iptunnel_handle_offloads(skb, SKB_GSO_IPXIP4);
526	if (err)
527		return err;
528
529	skb_set_inner_ipproto(skb, IPPROTO_IPIP);
530	headroom += LL_RESERVED_SPACE(rt->dst.dev) + rt->dst.header_len;
531	err = skb_cow_head(skb, headroom);
532	if (err)
533		return err;
534
535	skb_scrub_packet(skb, true);
536	skb_clear_hash_if_not_l4(skb);
537
538	/* Push down and install the IP header. */
539	skb_push(skb, sizeof(*iph));
540	skb_reset_network_header(skb);
541
542	iph = ip_hdr(skb);
543	iph->version	= 4;
544	iph->ihl	= sizeof(*iph) >> 2;
545	iph->frag_off	= ip_mtu_locked(&rt->dst) ? 0 : frag_off;
546	iph->protocol	= tuple->tun.l3_proto;
547	iph->tos	= tos;
548	iph->daddr	= tuple->tun.src_v4.s_addr;
549	iph->saddr	= tuple->tun.dst_v4.s_addr;
550	iph->ttl	= ttl;
551	iph->tot_len	= htons(skb->len);
552	__ip_select_ident(net, iph, skb_shinfo(skb)->gso_segs ?: 1);
553	ip_send_check(iph);
554
555	*ip_daddr = tuple->tun.src_v4.s_addr;
556
557	return 0;
558}
559
560static int nf_flow_tunnel_v4_push(struct net *net, struct sk_buff *skb,
561				  struct flow_offload_tuple *tuple,
562				  __be32 *ip_daddr)
563{
564	if (tuple->tun_num)
565		return nf_flow_tunnel_ipip_push(net, skb, tuple, ip_daddr);
566
567	return 0;
568}
569
570static int nf_flow_encap_push(struct sk_buff *skb,
571			      struct flow_offload_tuple *tuple)
572{
573	int i;
574
575	for (i = 0; i < tuple->encap_num; i++) {
576		switch (tuple->encap[i].proto) {
577		case htons(ETH_P_8021Q):
578		case htons(ETH_P_8021AD):
579			skb_reset_mac_header(skb);
580			if (skb_vlan_push(skb, tuple->encap[i].proto,
581					  tuple->encap[i].id) < 0)
582				return -1;
583			break;
584		case htons(ETH_P_PPP_SES):
585			if (nf_flow_pppoe_push(skb, tuple->encap[i].id) < 0)
586				return -1;
587			break;
588		}
589	}
590
591	return 0;
592}
593
594unsigned int
595nf_flow_offload_ip_hook(void *priv, struct sk_buff *skb,
596			const struct nf_hook_state *state)
597{
598	struct flow_offload_tuple_rhash *tuplehash;
599	struct nf_flowtable *flow_table = priv;
600	struct flow_offload_tuple *other_tuple;
601	enum flow_offload_tuple_dir dir;
602	struct nf_flowtable_ctx ctx = {
603		.in	= state->in,
604	};
605	struct nf_flow_xmit xmit = {};
606	struct flow_offload *flow;
607	struct neighbour *neigh;
608	struct rtable *rt;
609	__be32 ip_daddr;
610	int ret;
611
612	tuplehash = nf_flow_offload_lookup(&ctx, flow_table, skb);
613	if (!tuplehash)
614		return NF_ACCEPT;
615
616	ret = nf_flow_offload_forward(&ctx, flow_table, tuplehash, skb);
617	if (ret < 0)
618		return NF_DROP;
619	else if (ret == 0)
620		return NF_ACCEPT;
621
622	if (unlikely(tuplehash->tuple.xmit_type == FLOW_OFFLOAD_XMIT_XFRM)) {
623		rt = dst_rtable(tuplehash->tuple.dst_cache);
624		memset(skb->cb, 0, sizeof(struct inet_skb_parm));
625		IPCB(skb)->iif = skb->dev->ifindex;
626		IPCB(skb)->flags = IPSKB_FORWARDED;
627		return nf_flow_xmit_xfrm(skb, state, &rt->dst);
628	}
629
630	dir = tuplehash->tuple.dir;
631	flow = container_of(tuplehash, struct flow_offload, tuplehash[dir]);
632	other_tuple = &flow->tuplehash[!dir].tuple;
633	ip_daddr = other_tuple->src_v4.s_addr;
634
635	if (nf_flow_tunnel_v4_push(state->net, skb, other_tuple, &ip_daddr) < 0)
636		return NF_DROP;
637
638	if (nf_flow_encap_push(skb, other_tuple) < 0)
639		return NF_DROP;
640
641	switch (tuplehash->tuple.xmit_type) {
642	case FLOW_OFFLOAD_XMIT_NEIGH:
643		rt = dst_rtable(tuplehash->tuple.dst_cache);
644		xmit.outdev = dev_get_by_index_rcu(state->net, tuplehash->tuple.ifidx);
645		if (!xmit.outdev) {
646			flow_offload_teardown(flow);
647			return NF_DROP;
648		}
649		neigh = ip_neigh_gw4(rt->dst.dev, rt_nexthop(rt, ip_daddr));
650		if (IS_ERR(neigh)) {
651			flow_offload_teardown(flow);
652			return NF_DROP;
653		}
654		xmit.dest = neigh->ha;
655		skb_dst_set_noref(skb, &rt->dst);
656		break;
657	case FLOW_OFFLOAD_XMIT_DIRECT:
658		xmit.outdev = dev_get_by_index_rcu(state->net, tuplehash->tuple.out.ifidx);
659		if (!xmit.outdev) {
660			flow_offload_teardown(flow);
661			return NF_DROP;
662		}
663		xmit.dest = tuplehash->tuple.out.h_dest;
664		xmit.source = tuplehash->tuple.out.h_source;
665		break;
666	default:
667		WARN_ON_ONCE(1);
668		return NF_DROP;
669	}
670
671	return nf_flow_queue_xmit(state->net, skb, &xmit);
672}
673EXPORT_SYMBOL_GPL(nf_flow_offload_ip_hook);
674
675static void nf_flow_nat_ipv6_tcp(struct sk_buff *skb, unsigned int thoff,
676				 struct in6_addr *addr,
677				 struct in6_addr *new_addr,
678				 struct ipv6hdr *ip6h)
679{
680	struct tcphdr *tcph;
681
682	tcph = (void *)(skb_network_header(skb) + thoff);
683	inet_proto_csum_replace16(&tcph->check, skb, addr->s6_addr32,
684				  new_addr->s6_addr32, true);
685}
686
687static void nf_flow_nat_ipv6_udp(struct sk_buff *skb, unsigned int thoff,
688				 struct in6_addr *addr,
689				 struct in6_addr *new_addr)
690{
691	struct udphdr *udph;
692
693	udph = (void *)(skb_network_header(skb) + thoff);
694	if (udph->check || skb->ip_summed == CHECKSUM_PARTIAL) {
695		inet_proto_csum_replace16(&udph->check, skb, addr->s6_addr32,
696					  new_addr->s6_addr32, true);
697		if (!udph->check)
698			udph->check = CSUM_MANGLED_0;
699	}
700}
701
702static void nf_flow_nat_ipv6_l4proto(struct sk_buff *skb, struct ipv6hdr *ip6h,
703				     unsigned int thoff, struct in6_addr *addr,
704				     struct in6_addr *new_addr)
705{
706	switch (ip6h->nexthdr) {
707	case IPPROTO_TCP:
708		nf_flow_nat_ipv6_tcp(skb, thoff, addr, new_addr, ip6h);
709		break;
710	case IPPROTO_UDP:
711		nf_flow_nat_ipv6_udp(skb, thoff, addr, new_addr);
712		break;
713	}
714}
715
716static void nf_flow_snat_ipv6(const struct flow_offload *flow,
717			      struct sk_buff *skb, struct ipv6hdr *ip6h,
718			      unsigned int thoff,
719			      enum flow_offload_tuple_dir dir)
720{
721	struct in6_addr addr, new_addr;
722
723	switch (dir) {
724	case FLOW_OFFLOAD_DIR_ORIGINAL:
725		addr = ip6h->saddr;
726		new_addr = flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].tuple.dst_v6;
727		ip6h->saddr = new_addr;
728		break;
729	case FLOW_OFFLOAD_DIR_REPLY:
730		addr = ip6h->daddr;
731		new_addr = flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple.src_v6;
732		ip6h->daddr = new_addr;
733		break;
734	}
735
736	nf_flow_nat_ipv6_l4proto(skb, ip6h, thoff, &addr, &new_addr);
737}
738
739static void nf_flow_dnat_ipv6(const struct flow_offload *flow,
740			      struct sk_buff *skb, struct ipv6hdr *ip6h,
741			      unsigned int thoff,
742			      enum flow_offload_tuple_dir dir)
743{
744	struct in6_addr addr, new_addr;
745
746	switch (dir) {
747	case FLOW_OFFLOAD_DIR_ORIGINAL:
748		addr = ip6h->daddr;
749		new_addr = flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].tuple.src_v6;
750		ip6h->daddr = new_addr;
751		break;
752	case FLOW_OFFLOAD_DIR_REPLY:
753		addr = ip6h->saddr;
754		new_addr = flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple.dst_v6;
755		ip6h->saddr = new_addr;
756		break;
757	}
758
759	nf_flow_nat_ipv6_l4proto(skb, ip6h, thoff, &addr, &new_addr);
760}
761
762static void nf_flow_nat_ipv6(const struct flow_offload *flow,
763			     struct sk_buff *skb,
764			     enum flow_offload_tuple_dir dir,
765			     struct ipv6hdr *ip6h)
766{
767	unsigned int thoff = sizeof(*ip6h);
768
769	if (test_bit(NF_FLOW_SNAT, &flow->flags)) {
770		nf_flow_snat_port(flow, skb, thoff, ip6h->nexthdr, dir);
771		nf_flow_snat_ipv6(flow, skb, ip6h, thoff, dir);
772	}
773	if (test_bit(NF_FLOW_DNAT, &flow->flags)) {
774		nf_flow_dnat_port(flow, skb, thoff, ip6h->nexthdr, dir);
775		nf_flow_dnat_ipv6(flow, skb, ip6h, thoff, dir);
776	}
777}
778
779static int nf_flow_tuple_ipv6(struct nf_flowtable_ctx *ctx, struct sk_buff *skb,
780			      struct flow_offload_tuple *tuple)
781{
782	struct flow_ports *ports;
783	struct ipv6hdr *ip6h;
784	unsigned int thoff;
785	u8 nexthdr;
786
787	thoff = sizeof(*ip6h) + ctx->offset;
788	if (!pskb_may_pull(skb, thoff))
789		return -1;
790
791	ip6h = (struct ipv6hdr *)(skb_network_header(skb) + ctx->offset);
792
793	nexthdr = ip6h->nexthdr;
794	switch (nexthdr) {
795	case IPPROTO_TCP:
796		ctx->hdrsize = sizeof(struct tcphdr);
797		break;
798	case IPPROTO_UDP:
799		ctx->hdrsize = sizeof(struct udphdr);
800		break;
801#ifdef CONFIG_NF_CT_PROTO_GRE
802	case IPPROTO_GRE:
803		ctx->hdrsize = sizeof(struct gre_base_hdr);
804		break;
805#endif
806	default:
807		return -1;
808	}
809
810	if (ip6h->hop_limit <= 1)
811		return -1;
812
813	if (!pskb_may_pull(skb, thoff + ctx->hdrsize))
814		return -1;
815
816	switch (nexthdr) {
817	case IPPROTO_TCP:
818	case IPPROTO_UDP:
819		ports = (struct flow_ports *)(skb_network_header(skb) + thoff);
820		tuple->src_port		= ports->source;
821		tuple->dst_port		= ports->dest;
822		break;
823	case IPPROTO_GRE: {
824		struct gre_base_hdr *greh;
825
826		greh = (struct gre_base_hdr *)(skb_network_header(skb) + thoff);
827		if ((greh->flags & GRE_VERSION) != GRE_VERSION_0)
828			return -1;
829		break;
830	}
831	}
832
833	ip6h = (struct ipv6hdr *)(skb_network_header(skb) + ctx->offset);
834
835	tuple->src_v6		= ip6h->saddr;
836	tuple->dst_v6		= ip6h->daddr;
837	tuple->l3proto		= AF_INET6;
838	tuple->l4proto		= nexthdr;
839	tuple->iifidx		= ctx->in->ifindex;
840	nf_flow_tuple_encap(skb, tuple);
841
842	return 0;
843}
844
845static int nf_flow_offload_ipv6_forward(struct nf_flowtable_ctx *ctx,
846					struct nf_flowtable *flow_table,
847					struct flow_offload_tuple_rhash *tuplehash,
848					struct sk_buff *skb)
849{
850	enum flow_offload_tuple_dir dir;
851	struct flow_offload *flow;
852	unsigned int thoff, mtu;
853	struct ipv6hdr *ip6h;
854
855	dir = tuplehash->tuple.dir;
856	flow = container_of(tuplehash, struct flow_offload, tuplehash[dir]);
857
858	mtu = flow->tuplehash[dir].tuple.mtu + ctx->offset;
859	if (unlikely(nf_flow_exceeds_mtu(skb, mtu)))
860		return 0;
861
862	ip6h = (struct ipv6hdr *)(skb_network_header(skb) + ctx->offset);
863	thoff = sizeof(*ip6h) + ctx->offset;
864	if (nf_flow_state_check(flow, ip6h->nexthdr, skb, thoff))
865		return 0;
866
867	if (!nf_flow_dst_check(&tuplehash->tuple)) {
868		flow_offload_teardown(flow);
869		return 0;
870	}
871
872	if (skb_try_make_writable(skb, thoff + ctx->hdrsize))
873		return -1;
874
875	flow_offload_refresh(flow_table, flow, false);
876
877	nf_flow_encap_pop(skb, tuplehash);
878
879	ip6h = ipv6_hdr(skb);
880	nf_flow_nat_ipv6(flow, skb, dir, ip6h);
881
882	ip6h->hop_limit--;
883	skb_clear_tstamp(skb);
884
885	if (flow_table->flags & NF_FLOWTABLE_COUNTER)
886		nf_ct_acct_update(flow->ct, tuplehash->tuple.dir, skb->len);
887
888	return 1;
889}
890
891static struct flow_offload_tuple_rhash *
892nf_flow_offload_ipv6_lookup(struct nf_flowtable_ctx *ctx,
893			    struct nf_flowtable *flow_table,
894			    struct sk_buff *skb)
895{
896	struct flow_offload_tuple tuple = {};
897
898	if (skb->protocol != htons(ETH_P_IPV6) &&
899	    !nf_flow_skb_encap_protocol(skb, htons(ETH_P_IPV6), &ctx->offset))
900		return NULL;
901
902	if (nf_flow_tuple_ipv6(ctx, skb, &tuple) < 0)
903		return NULL;
904
905	return flow_offload_lookup(flow_table, &tuple);
906}
907
908unsigned int
909nf_flow_offload_ipv6_hook(void *priv, struct sk_buff *skb,
910			  const struct nf_hook_state *state)
911{
912	struct flow_offload_tuple_rhash *tuplehash;
913	struct nf_flowtable *flow_table = priv;
914	struct flow_offload_tuple *other_tuple;
915	enum flow_offload_tuple_dir dir;
916	struct nf_flowtable_ctx ctx = {
917		.in	= state->in,
918	};
919	struct nf_flow_xmit xmit = {};
920	struct in6_addr *ip6_daddr;
921	struct flow_offload *flow;
922	struct neighbour *neigh;
923	struct rt6_info *rt;
924	int ret;
925
926	tuplehash = nf_flow_offload_ipv6_lookup(&ctx, flow_table, skb);
927	if (tuplehash == NULL)
928		return NF_ACCEPT;
929
930	ret = nf_flow_offload_ipv6_forward(&ctx, flow_table, tuplehash, skb);
931	if (ret < 0)
932		return NF_DROP;
933	else if (ret == 0)
934		return NF_ACCEPT;
935
936	if (unlikely(tuplehash->tuple.xmit_type == FLOW_OFFLOAD_XMIT_XFRM)) {
937		rt = dst_rt6_info(tuplehash->tuple.dst_cache);
938		memset(skb->cb, 0, sizeof(struct inet6_skb_parm));
939		IP6CB(skb)->iif = skb->dev->ifindex;
940		IP6CB(skb)->flags = IP6SKB_FORWARDED;
941		return nf_flow_xmit_xfrm(skb, state, &rt->dst);
942	}
943
944	dir = tuplehash->tuple.dir;
945	flow = container_of(tuplehash, struct flow_offload, tuplehash[dir]);
946	other_tuple = &flow->tuplehash[!dir].tuple;
947	ip6_daddr = &other_tuple->src_v6;
948
949	if (nf_flow_encap_push(skb, other_tuple) < 0)
950		return NF_DROP;
951
952	switch (tuplehash->tuple.xmit_type) {
953	case FLOW_OFFLOAD_XMIT_NEIGH:
954		rt = dst_rt6_info(tuplehash->tuple.dst_cache);
955		xmit.outdev = dev_get_by_index_rcu(state->net, tuplehash->tuple.ifidx);
956		if (!xmit.outdev) {
957			flow_offload_teardown(flow);
958			return NF_DROP;
959		}
960		neigh = ip_neigh_gw6(rt->dst.dev, rt6_nexthop(rt, ip6_daddr));
961		if (IS_ERR(neigh)) {
962			flow_offload_teardown(flow);
963			return NF_DROP;
964		}
965		xmit.dest = neigh->ha;
966		skb_dst_set_noref(skb, &rt->dst);
967		break;
968	case FLOW_OFFLOAD_XMIT_DIRECT:
969		xmit.outdev = dev_get_by_index_rcu(state->net, tuplehash->tuple.out.ifidx);
970		if (!xmit.outdev) {
971			flow_offload_teardown(flow);
972			return NF_DROP;
973		}
974		xmit.dest = tuplehash->tuple.out.h_dest;
975		xmit.source = tuplehash->tuple.out.h_source;
976		break;
977	default:
978		WARN_ON_ONCE(1);
979		return NF_DROP;
980	}
981
982	return nf_flow_queue_xmit(state->net, skb, &xmit);
983}
984EXPORT_SYMBOL_GPL(nf_flow_offload_ipv6_hook);
~/ Read-only file preview.