root/net/ipv6/netfilter/ip6t_ipv6header.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. ipv6header_mt6
  2. ipv6header_mt6_check
  3. ipv6header_mt6_init
  4. ipv6header_mt6_exit

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /* ipv6header match - matches IPv6 packets based
   3    on whether they contain certain headers */
   4 
   5 /* Original idea: Brad Chapman
   6  * Rewritten by: Andras Kis-Szabo <kisza@sch.bme.hu> */
   7 
   8 /* (C) 2001-2002 Andras Kis-Szabo <kisza@sch.bme.hu>
   9  */
  10 
  11 #include <linux/module.h>
  12 #include <linux/skbuff.h>
  13 #include <linux/ipv6.h>
  14 #include <linux/types.h>
  15 #include <net/checksum.h>
  16 #include <net/ipv6.h>
  17 
  18 #include <linux/netfilter/x_tables.h>
  19 #include <linux/netfilter_ipv6.h>
  20 #include <linux/netfilter_ipv6/ip6t_ipv6header.h>
  21 
  22 MODULE_LICENSE("GPL");
  23 MODULE_DESCRIPTION("Xtables: IPv6 header types match");
  24 MODULE_AUTHOR("Andras Kis-Szabo <kisza@sch.bme.hu>");
  25 
  26 static bool
  27 ipv6header_mt6(const struct sk_buff *skb, struct xt_action_param *par)
  28 {
  29         const struct ip6t_ipv6header_info *info = par->matchinfo;
  30         unsigned int temp;
  31         int len;
  32         u8 nexthdr;
  33         unsigned int ptr;
  34 
  35         /* Make sure this isn't an evil packet */
  36 
  37         /* type of the 1st exthdr */
  38         nexthdr = ipv6_hdr(skb)->nexthdr;
  39         /* pointer to the 1st exthdr */
  40         ptr = sizeof(struct ipv6hdr);
  41         /* available length */
  42         len = skb->len - ptr;
  43         temp = 0;
  44 
  45         while (nf_ip6_ext_hdr(nexthdr)) {
  46                 const struct ipv6_opt_hdr *hp;
  47                 struct ipv6_opt_hdr _hdr;
  48                 int hdrlen;
  49 
  50                 /* No more exthdr -> evaluate */
  51                 if (nexthdr == NEXTHDR_NONE) {
  52                         temp |= MASK_NONE;
  53                         break;
  54                 }
  55                 /* Is there enough space for the next ext header? */
  56                 if (len < (int)sizeof(struct ipv6_opt_hdr))
  57                         return false;
  58                 /* ESP -> evaluate */
  59                 if (nexthdr == NEXTHDR_ESP) {
  60                         temp |= MASK_ESP;
  61                         break;
  62                 }
  63 
  64                 hp = skb_header_pointer(skb, ptr, sizeof(_hdr), &_hdr);
  65                 if (!hp) {
  66                         par->hotdrop = true;
  67                         return false;
  68                 }
  69 
  70                 /* Calculate the header length */
  71                 if (nexthdr == NEXTHDR_FRAGMENT)
  72                         hdrlen = 8;
  73                 else if (nexthdr == NEXTHDR_AUTH)
  74                         hdrlen = ipv6_authlen(hp);
  75                 else
  76                         hdrlen = ipv6_optlen(hp);
  77 
  78                 /* set the flag */
  79                 switch (nexthdr) {
  80                 case NEXTHDR_HOP:
  81                         temp |= MASK_HOPOPTS;
  82                         break;
  83                 case NEXTHDR_ROUTING:
  84                         temp |= MASK_ROUTING;
  85                         break;
  86                 case NEXTHDR_FRAGMENT:
  87                         temp |= MASK_FRAGMENT;
  88                         break;
  89                 case NEXTHDR_AUTH:
  90                         temp |= MASK_AH;
  91                         break;
  92                 case NEXTHDR_DEST:
  93                         temp |= MASK_DSTOPTS;
  94                         break;
  95                 default:
  96                         return false;
  97                 }
  98 
  99                 nexthdr = hp->nexthdr;
 100                 len -= hdrlen;
 101                 ptr += hdrlen;
 102                 if (ptr > skb->len)
 103                         break;
 104         }
 105 
 106         if (nexthdr != NEXTHDR_NONE && nexthdr != NEXTHDR_ESP)
 107                 temp |= MASK_PROTO;
 108 
 109         if (info->modeflag)
 110                 return !((temp ^ info->matchflags ^ info->invflags)
 111                          & info->matchflags);
 112         else {
 113                 if (info->invflags)
 114                         return temp != info->matchflags;
 115                 else
 116                         return temp == info->matchflags;
 117         }
 118 }
 119 
 120 static int ipv6header_mt6_check(const struct xt_mtchk_param *par)
 121 {
 122         const struct ip6t_ipv6header_info *info = par->matchinfo;
 123 
 124         /* invflags is 0 or 0xff in hard mode */
 125         if ((!info->modeflag) && info->invflags != 0x00 &&
 126             info->invflags != 0xFF)
 127                 return -EINVAL;
 128 
 129         return 0;
 130 }
 131 
 132 static struct xt_match ipv6header_mt6_reg __read_mostly = {
 133         .name           = "ipv6header",
 134         .family         = NFPROTO_IPV6,
 135         .match          = ipv6header_mt6,
 136         .matchsize      = sizeof(struct ip6t_ipv6header_info),
 137         .checkentry     = ipv6header_mt6_check,
 138         .destroy        = NULL,
 139         .me             = THIS_MODULE,
 140 };
 141 
 142 static int __init ipv6header_mt6_init(void)
 143 {
 144         return xt_register_match(&ipv6header_mt6_reg);
 145 }
 146 
 147 static void __exit ipv6header_mt6_exit(void)
 148 {
 149         xt_unregister_match(&ipv6header_mt6_reg);
 150 }
 151 
 152 module_init(ipv6header_mt6_init);
 153 module_exit(ipv6header_mt6_exit);

/* [<][>][^][v][top][bottom][index][help] */