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