File Index
Files and directories
Sign in
FILE

nf_tables_ipv6.h

File preview with syntax highlighting.

linux-6.19.14/include/net/netfilter/nf_tables_ipv6.h C
  1/* SPDX-License-Identifier: GPL-2.0 */
  2#ifndef _NF_TABLES_IPV6_H_
  3#define _NF_TABLES_IPV6_H_
  4
  5#include <linux/netfilter_ipv6/ip6_tables.h>
  6#include <net/ipv6.h>
  7#include <net/netfilter/nf_tables.h>
  8
  9static inline void nft_set_pktinfo_ipv6(struct nft_pktinfo *pkt)
 10{
 11	unsigned int flags = IP6_FH_F_AUTH;
 12	int protohdr, thoff = 0;
 13	unsigned short frag_off;
 14
 15	protohdr = ipv6_find_hdr(pkt->skb, &thoff, -1, &frag_off, &flags);
 16	if (protohdr < 0 || thoff > U16_MAX) {
 17		nft_set_pktinfo_unspec(pkt);
 18		return;
 19	}
 20
 21	pkt->flags = NFT_PKTINFO_L4PROTO;
 22	pkt->tprot = protohdr;
 23	pkt->thoff = thoff;
 24	pkt->fragoff = frag_off;
 25}
 26
 27static inline int __nft_set_pktinfo_ipv6_validate(struct nft_pktinfo *pkt)
 28{
 29#if IS_ENABLED(CONFIG_IPV6)
 30	unsigned int flags = IP6_FH_F_AUTH;
 31	struct ipv6hdr *ip6h, _ip6h;
 32	unsigned int thoff = 0;
 33	unsigned short frag_off;
 34	u32 pkt_len, skb_len;
 35	int protohdr;
 36
 37	ip6h = skb_header_pointer(pkt->skb, skb_network_offset(pkt->skb),
 38				  sizeof(*ip6h), &_ip6h);
 39	if (!ip6h)
 40		return -1;
 41
 42	if (ip6h->version != 6)
 43		return -1;
 44
 45	pkt_len = ntohs(ip6h->payload_len);
 46	skb_len = pkt->skb->len - skb_network_offset(pkt->skb);
 47	if (pkt_len + sizeof(*ip6h) > skb_len)
 48		return -1;
 49
 50	protohdr = ipv6_find_hdr(pkt->skb, &thoff, -1, &frag_off, &flags);
 51	if (protohdr < 0 || thoff > U16_MAX)
 52		return -1;
 53
 54	pkt->flags = NFT_PKTINFO_L4PROTO;
 55	pkt->tprot = protohdr;
 56	pkt->thoff = thoff;
 57	pkt->fragoff = frag_off;
 58
 59	return 0;
 60#else
 61	return -1;
 62#endif
 63}
 64
 65static inline void nft_set_pktinfo_ipv6_validate(struct nft_pktinfo *pkt)
 66{
 67	if (__nft_set_pktinfo_ipv6_validate(pkt) < 0)
 68		nft_set_pktinfo_unspec(pkt);
 69}
 70
 71static inline int nft_set_pktinfo_ipv6_ingress(struct nft_pktinfo *pkt)
 72{
 73#if IS_ENABLED(CONFIG_IPV6)
 74	unsigned int flags = IP6_FH_F_AUTH;
 75	unsigned short frag_off;
 76	unsigned int thoff = 0;
 77	struct inet6_dev *idev;
 78	struct ipv6hdr *ip6h;
 79	int protohdr;
 80	u32 pkt_len;
 81
 82	if (!pskb_may_pull(pkt->skb, sizeof(*ip6h)))
 83		return -1;
 84
 85	ip6h = ipv6_hdr(pkt->skb);
 86	if (ip6h->version != 6)
 87		goto inhdr_error;
 88
 89	pkt_len = ntohs(ip6h->payload_len);
 90	if (pkt_len + sizeof(*ip6h) > pkt->skb->len) {
 91		idev = __in6_dev_get(nft_in(pkt));
 92		__IP6_INC_STATS(nft_net(pkt), idev, IPSTATS_MIB_INTRUNCATEDPKTS);
 93		return -1;
 94	}
 95
 96	protohdr = ipv6_find_hdr(pkt->skb, &thoff, -1, &frag_off, &flags);
 97	if (protohdr < 0 || thoff > U16_MAX)
 98		goto inhdr_error;
 99
100	pkt->flags = NFT_PKTINFO_L4PROTO;
101	pkt->tprot = protohdr;
102	pkt->thoff = thoff;
103	pkt->fragoff = frag_off;
104
105	return 0;
106
107inhdr_error:
108	idev = __in6_dev_get(nft_in(pkt));
109	__IP6_INC_STATS(nft_net(pkt), idev, IPSTATS_MIB_INHDRERRORS);
110	return -1;
111#else
112	return -1;
113#endif
114}
115
116#endif
~/ Read-only file preview.