linux/include/net/netfilter/nf_tables_ipv4.h
<<
>>
Prefs
   1/* SPDX-License-Identifier: GPL-2.0 */
   2#ifndef _NF_TABLES_IPV4_H_
   3#define _NF_TABLES_IPV4_H_
   4
   5#include <net/netfilter/nf_tables.h>
   6#include <net/ip.h>
   7
   8static inline void nft_set_pktinfo_ipv4(struct nft_pktinfo *pkt)
   9{
  10        struct iphdr *ip;
  11
  12        ip = ip_hdr(pkt->skb);
  13        pkt->tprot_set = true;
  14        pkt->tprot = ip->protocol;
  15        pkt->thoff = ip_hdrlen(pkt->skb);
  16        pkt->fragoff = ntohs(ip->frag_off) & IP_OFFSET;
  17}
  18
  19static inline int __nft_set_pktinfo_ipv4_validate(struct nft_pktinfo *pkt)
  20{
  21        struct iphdr *iph, _iph;
  22        u32 len, thoff;
  23
  24        iph = skb_header_pointer(pkt->skb, skb_network_offset(pkt->skb),
  25                                 sizeof(*iph), &_iph);
  26        if (!iph)
  27                return -1;
  28
  29        if (iph->ihl < 5 || iph->version != 4)
  30                return -1;
  31
  32        len = ntohs(iph->tot_len);
  33        thoff = iph->ihl * 4;
  34        if (pkt->skb->len < len)
  35                return -1;
  36        else if (len < thoff)
  37                return -1;
  38
  39        pkt->tprot_set = true;
  40        pkt->tprot = iph->protocol;
  41        pkt->thoff = thoff;
  42        pkt->fragoff = ntohs(iph->frag_off) & IP_OFFSET;
  43
  44        return 0;
  45}
  46
  47static inline void nft_set_pktinfo_ipv4_validate(struct nft_pktinfo *pkt)
  48{
  49        if (__nft_set_pktinfo_ipv4_validate(pkt) < 0)
  50                nft_set_pktinfo_unspec(pkt);
  51}
  52
  53static inline int nft_set_pktinfo_ipv4_ingress(struct nft_pktinfo *pkt)
  54{
  55        struct iphdr *iph;
  56        u32 len, thoff;
  57
  58        if (!pskb_may_pull(pkt->skb, sizeof(*iph)))
  59                return -1;
  60
  61        iph = ip_hdr(pkt->skb);
  62        if (iph->ihl < 5 || iph->version != 4)
  63                goto inhdr_error;
  64
  65        len = ntohs(iph->tot_len);
  66        thoff = iph->ihl * 4;
  67        if (pkt->skb->len < len) {
  68                __IP_INC_STATS(nft_net(pkt), IPSTATS_MIB_INTRUNCATEDPKTS);
  69                return -1;
  70        } else if (len < thoff) {
  71                goto inhdr_error;
  72        }
  73
  74        pkt->tprot_set = true;
  75        pkt->tprot = iph->protocol;
  76        pkt->thoff = thoff;
  77        pkt->fragoff = ntohs(iph->frag_off) & IP_OFFSET;
  78
  79        return 0;
  80
  81inhdr_error:
  82        __IP_INC_STATS(nft_net(pkt), IPSTATS_MIB_INHDRERRORS);
  83        return -1;
  84}
  85#endif
  86