linux/include/net/netfilter/nf_tables_ipv6.h
<<
>>
Prefs
   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                                        struct sk_buff *skb)
  11{
  12        unsigned int flags = IP6_FH_F_AUTH;
  13        int protohdr, thoff = 0;
  14        unsigned short frag_off;
  15
  16        protohdr = ipv6_find_hdr(pkt->skb, &thoff, -1, &frag_off, &flags);
  17        if (protohdr < 0) {
  18                nft_set_pktinfo_unspec(pkt, skb);
  19                return;
  20        }
  21
  22        pkt->tprot_set = true;
  23        pkt->tprot = protohdr;
  24        pkt->xt.thoff = thoff;
  25        pkt->xt.fragoff = frag_off;
  26}
  27
  28static inline int __nft_set_pktinfo_ipv6_validate(struct nft_pktinfo *pkt,
  29                                                  struct sk_buff *skb)
  30{
  31#if IS_ENABLED(CONFIG_IPV6)
  32        unsigned int flags = IP6_FH_F_AUTH;
  33        struct ipv6hdr *ip6h, _ip6h;
  34        unsigned int thoff = 0;
  35        unsigned short frag_off;
  36        int protohdr;
  37        u32 pkt_len;
  38
  39        ip6h = skb_header_pointer(skb, skb_network_offset(skb), sizeof(*ip6h),
  40                                  &_ip6h);
  41        if (!ip6h)
  42                return -1;
  43
  44        if (ip6h->version != 6)
  45                return -1;
  46
  47        pkt_len = ntohs(ip6h->payload_len);
  48        if (pkt_len + sizeof(*ip6h) > skb->len)
  49                return -1;
  50
  51        protohdr = ipv6_find_hdr(pkt->skb, &thoff, -1, &frag_off, &flags);
  52        if (protohdr < 0)
  53                return -1;
  54
  55        pkt->tprot_set = true;
  56        pkt->tprot = protohdr;
  57        pkt->xt.thoff = thoff;
  58        pkt->xt.fragoff = frag_off;
  59
  60        return 0;
  61#else
  62        return -1;
  63#endif
  64}
  65
  66static inline void nft_set_pktinfo_ipv6_validate(struct nft_pktinfo *pkt,
  67                                                 struct sk_buff *skb)
  68{
  69        if (__nft_set_pktinfo_ipv6_validate(pkt, skb) < 0)
  70                nft_set_pktinfo_unspec(pkt, skb);
  71}
  72
  73static inline int nft_set_pktinfo_ipv6_ingress(struct nft_pktinfo *pkt,
  74                                               struct sk_buff *skb)
  75{
  76#if IS_ENABLED(CONFIG_IPV6)
  77        unsigned int flags = IP6_FH_F_AUTH;
  78        unsigned short frag_off;
  79        unsigned int thoff = 0;
  80        struct inet6_dev *idev;
  81        struct ipv6hdr *ip6h;
  82        int protohdr;
  83        u32 pkt_len;
  84
  85        if (!pskb_may_pull(skb, sizeof(*ip6h)))
  86                return -1;
  87
  88        ip6h = ipv6_hdr(skb);
  89        if (ip6h->version != 6)
  90                goto inhdr_error;
  91
  92        pkt_len = ntohs(ip6h->payload_len);
  93        if (pkt_len + sizeof(*ip6h) > skb->len) {
  94                idev = __in6_dev_get(nft_in(pkt));
  95                __IP6_INC_STATS(nft_net(pkt), idev, IPSTATS_MIB_INTRUNCATEDPKTS);
  96                return -1;
  97        }
  98
  99        protohdr = ipv6_find_hdr(pkt->skb, &thoff, -1, &frag_off, &flags);
 100        if (protohdr < 0)
 101                goto inhdr_error;
 102
 103        pkt->tprot_set = true;
 104        pkt->tprot = protohdr;
 105        pkt->xt.thoff = thoff;
 106        pkt->xt.fragoff = frag_off;
 107
 108        return 0;
 109
 110inhdr_error:
 111        idev = __in6_dev_get(nft_in(pkt));
 112        __IP6_INC_STATS(nft_net(pkt), idev, IPSTATS_MIB_INHDRERRORS);
 113        return -1;
 114#else
 115        return -1;
 116#endif
 117}
 118
 119#endif
 120