arm64: dts: qcom: sm8550: add TRNG node
[linux-modified.git] / netfilter / nf_tables_ipv6.h
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
9 static 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
27 static 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
64 static 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
70 static 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
106 inhdr_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