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{
  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) {
  17                nft_set_pktinfo_unspec(pkt);
  18                return;
  19        }
  20
  21        pkt->tprot_set = true;
  22        pkt->tprot = protohdr;
  23        pkt->thoff = thoff;
  24        pkt->fragoff = frag_off;
  25}
  26
  27static 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)
  51                return -1;
  52
  53        pkt->tprot_set = true;
  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
  64static 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
  70static 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)
  97                goto inhdr_error;
  98
  99        pkt->tprot_set = true;
 100        pkt->tprot = protohdr;
 101        pkt->thoff = thoff;
 102        pkt->fragoff = frag_off;
 103
 104        return 0;
 105
 106inhdr_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
 116