Warning: This file is not a C or C++ file. It does not have highlighting.

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 int protohdr;
35 u32 pkt_len;
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 if (pkt_len + sizeof(*ip6h) > pkt->skb->len)
47 return -1;
48
49 protohdr = ipv6_find_hdr(pkt->skb, &thoff, -1, &frag_off, &flags);
50 if (protohdr < 0 || thoff > U16_MAX)
51 return -1;
52
53 pkt->flags = NFT_PKTINFO_L4PROTO;
54 pkt->tprot = protohdr;
55 pkt->thoff = thoff;
56 pkt->fragoff = frag_off;
57
58 return 0;
59#else
60 return -1;
61#endif
62}
63
64static inline void nft_set_pktinfo_ipv6_validate(struct nft_pktinfo *pkt)
65{
66 if (__nft_set_pktinfo_ipv6_validate(pkt) < 0)
67 nft_set_pktinfo_unspec(pkt);
68}
69
70static inline int nft_set_pktinfo_ipv6_ingress(struct nft_pktinfo *pkt)
71{
72#if IS_ENABLED(CONFIG_IPV6)
73 unsigned int flags = IP6_FH_F_AUTH;
74 unsigned short frag_off;
75 unsigned int thoff = 0;
76 struct inet6_dev *idev;
77 struct ipv6hdr *ip6h;
78 int protohdr;
79 u32 pkt_len;
80
81 if (!pskb_may_pull(pkt->skb, sizeof(*ip6h)))
82 return -1;
83
84 ip6h = ipv6_hdr(pkt->skb);
85 if (ip6h->version != 6)
86 goto inhdr_error;
87
88 pkt_len = ntohs(ip6h->payload_len);
89 if (pkt_len + sizeof(*ip6h) > pkt->skb->len) {
90 idev = __in6_dev_get(nft_in(pkt));
91 __IP6_INC_STATS(nft_net(pkt), idev, IPSTATS_MIB_INTRUNCATEDPKTS);
92 return -1;
93 }
94
95 protohdr = ipv6_find_hdr(pkt->skb, &thoff, -1, &frag_off, &flags);
96 if (protohdr < 0 || thoff > U16_MAX)
97 goto inhdr_error;
98
99 pkt->flags = NFT_PKTINFO_L4PROTO;
100 pkt->tprot = protohdr;
101 pkt->thoff = thoff;
102 pkt->fragoff = frag_off;
103
104 return 0;
105
106inhdr_error:
107 idev = __in6_dev_get(nft_in(pkt));
108 __IP6_INC_STATS(nft_net(pkt), idev, IPSTATS_MIB_INHDRERRORS);
109 return -1;
110#else
111 return -1;
112#endif
113}
114
115#endif
116

Warning: This file is not a C or C++ file. It does not have highlighting.

source code of linux/include/net/netfilter/nf_tables_ipv6.h