Merge remote-tracking branch 'spi/topic/core' into spi-next
[sfrench/cifs-2.6.git] / include / net / 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
8 static inline void
9 nft_set_pktinfo_ipv6(struct nft_pktinfo *pkt,
10                      struct sk_buff *skb,
11                      const struct nf_hook_state *state)
12 {
13         unsigned int flags = IP6_FH_F_AUTH;
14         int protohdr, thoff = 0;
15         unsigned short frag_off;
16
17         nft_set_pktinfo(pkt, skb, state);
18
19         protohdr = ipv6_find_hdr(pkt->skb, &thoff, -1, &frag_off, &flags);
20         if (protohdr < 0) {
21                 nft_set_pktinfo_proto_unspec(pkt, skb);
22                 return;
23         }
24
25         pkt->tprot_set = true;
26         pkt->tprot = protohdr;
27         pkt->xt.thoff = thoff;
28         pkt->xt.fragoff = frag_off;
29 }
30
31 static inline int
32 __nft_set_pktinfo_ipv6_validate(struct nft_pktinfo *pkt,
33                                 struct sk_buff *skb,
34                                 const struct nf_hook_state *state)
35 {
36 #if IS_ENABLED(CONFIG_IPV6)
37         unsigned int flags = IP6_FH_F_AUTH;
38         struct ipv6hdr *ip6h, _ip6h;
39         unsigned int thoff = 0;
40         unsigned short frag_off;
41         int protohdr;
42         u32 pkt_len;
43
44         ip6h = skb_header_pointer(skb, skb_network_offset(skb), sizeof(*ip6h),
45                                   &_ip6h);
46         if (!ip6h)
47                 return -1;
48
49         if (ip6h->version != 6)
50                 return -1;
51
52         pkt_len = ntohs(ip6h->payload_len);
53         if (pkt_len + sizeof(*ip6h) > skb->len)
54                 return -1;
55
56         protohdr = ipv6_find_hdr(pkt->skb, &thoff, -1, &frag_off, &flags);
57         if (protohdr < 0)
58                 return -1;
59
60         pkt->tprot_set = true;
61         pkt->tprot = protohdr;
62         pkt->xt.thoff = thoff;
63         pkt->xt.fragoff = frag_off;
64
65         return 0;
66 #else
67         return -1;
68 #endif
69 }
70
71 static inline void
72 nft_set_pktinfo_ipv6_validate(struct nft_pktinfo *pkt,
73                               struct sk_buff *skb,
74                               const struct nf_hook_state *state)
75 {
76         nft_set_pktinfo(pkt, skb, state);
77         if (__nft_set_pktinfo_ipv6_validate(pkt, skb, state) < 0)
78                 nft_set_pktinfo_proto_unspec(pkt, skb);
79 }
80
81 extern struct nft_af_info nft_af_ipv6;
82
83 #endif