blob: d150b50662017378644c8f3ccf0218ecceaa2331 [file] [log] [blame]
Pablo Neira Ayuso0ca743a2013-10-14 00:06:06 +02001#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
Pablo Neira Ayuso71212c92016-09-09 12:42:53 +02007static inline void
Pablo Neira Ayuso0ca743a2013-10-14 00:06:06 +02008nft_set_pktinfo_ipv6(struct nft_pktinfo *pkt,
Pablo Neira Ayuso0ca743a2013-10-14 00:06:06 +02009 struct sk_buff *skb,
David S. Miller073bfd52015-04-03 21:16:25 -040010 const struct nf_hook_state *state)
Pablo Neira Ayuso0ca743a2013-10-14 00:06:06 +020011{
12 int protohdr, thoff = 0;
13 unsigned short frag_off;
14
Eric W. Biederman6aa187f2015-09-18 14:32:57 -050015 nft_set_pktinfo(pkt, skb, state);
Pablo Neira Ayuso0ca743a2013-10-14 00:06:06 +020016
17 protohdr = ipv6_find_hdr(pkt->skb, &thoff, -1, &frag_off, NULL);
Pablo Neira Ayuso8df9e322016-09-09 12:42:50 +020018 if (protohdr < 0) {
19 nft_set_pktinfo_proto_unspec(pkt, skb);
Pablo Neira Ayuso71212c92016-09-09 12:42:53 +020020 return;
Pablo Neira Ayuso8df9e322016-09-09 12:42:50 +020021 }
Pablo Neira Ayuso0ca743a2013-10-14 00:06:06 +020022
Pablo Neira Ayusobeac5af2016-09-09 12:42:49 +020023 pkt->tprot_set = true;
Patrick McHardy4566bf22014-01-03 12:16:18 +000024 pkt->tprot = protohdr;
Pablo Neira Ayuso0ca743a2013-10-14 00:06:06 +020025 pkt->xt.thoff = thoff;
26 pkt->xt.fragoff = frag_off;
Pablo Neira Ayuso0ca743a2013-10-14 00:06:06 +020027}
28
Pablo Neira Ayusoddc8b602016-09-09 12:42:51 +020029static inline int
30__nft_set_pktinfo_ipv6_validate(struct nft_pktinfo *pkt,
31 struct sk_buff *skb,
32 const struct nf_hook_state *state)
33{
34#if IS_ENABLED(CONFIG_IPV6)
35 struct ipv6hdr *ip6h, _ip6h;
36 unsigned int thoff = 0;
37 unsigned short frag_off;
38 int protohdr;
39 u32 pkt_len;
40
41 ip6h = skb_header_pointer(skb, skb_network_offset(skb), sizeof(*ip6h),
42 &_ip6h);
43 if (!ip6h)
44 return -1;
45
46 if (ip6h->version != 6)
47 return -1;
48
49 pkt_len = ntohs(ip6h->payload_len);
50 if (pkt_len + sizeof(*ip6h) > skb->len)
51 return -1;
52
53 protohdr = ipv6_find_hdr(pkt->skb, &thoff, -1, &frag_off, NULL);
54 if (protohdr < 0)
55 return -1;
56
57 pkt->tprot_set = true;
58 pkt->tprot = protohdr;
59 pkt->xt.thoff = thoff;
60 pkt->xt.fragoff = frag_off;
61
62 return 0;
63#else
64 return -1;
65#endif
66}
67
68static inline void
69nft_set_pktinfo_ipv6_validate(struct nft_pktinfo *pkt,
70 struct sk_buff *skb,
71 const struct nf_hook_state *state)
72{
73 nft_set_pktinfo(pkt, skb, state);
74 if (__nft_set_pktinfo_ipv6_validate(pkt, skb, state) < 0)
75 nft_set_pktinfo_proto_unspec(pkt, skb);
76}
77
Patrick McHardy1d491442014-01-03 12:16:16 +000078extern struct nft_af_info nft_af_ipv6;
79
Pablo Neira Ayuso0ca743a2013-10-14 00:06:06 +020080#endif