Linux kernel & device driver programming

Cross-Referenced Linux and Device Driver Code

[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ]
Version: [ 2.6.11.8 ] [ 2.6.25 ] [ 2.6.25.8 ] [ 2.6.31.13 ] Architecture: [ i386 ]
  1 /*
  2  *      xt_iprange - Netfilter module to match IP address ranges
  3  *
  4  *      (C) 2003 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
  5  *      (C) CC Computer Consultants GmbH, 2008
  6  *
  7  *      This program is free software; you can redistribute it and/or modify
  8  *      it under the terms of the GNU General Public License version 2 as
  9  *      published by the Free Software Foundation.
 10  */
 11 #include <linux/module.h>
 12 #include <linux/skbuff.h>
 13 #include <linux/ip.h>
 14 #include <linux/ipv6.h>
 15 #include <linux/netfilter/x_tables.h>
 16 #include <linux/netfilter/xt_iprange.h>
 17 #include <linux/netfilter_ipv4/ipt_iprange.h>
 18 
 19 static bool
 20 iprange_mt_v0(const struct sk_buff *skb, const struct net_device *in,
 21               const struct net_device *out, const struct xt_match *match,
 22               const void *matchinfo, int offset, unsigned int protoff,
 23               bool *hotdrop)
 24 {
 25         const struct ipt_iprange_info *info = matchinfo;
 26         const struct iphdr *iph = ip_hdr(skb);
 27 
 28         if (info->flags & IPRANGE_SRC) {
 29                 if ((ntohl(iph->saddr) < ntohl(info->src.min_ip)
 30                           || ntohl(iph->saddr) > ntohl(info->src.max_ip))
 31                          ^ !!(info->flags & IPRANGE_SRC_INV)) {
 32                         pr_debug("src IP %u.%u.%u.%u NOT in range %s"
 33                                  "%u.%u.%u.%u-%u.%u.%u.%u\n",
 34                                  NIPQUAD(iph->saddr),
 35                                  info->flags & IPRANGE_SRC_INV ? "(INV) " : "",
 36                                  NIPQUAD(info->src.min_ip),
 37                                  NIPQUAD(info->src.max_ip));
 38                         return false;
 39                 }
 40         }
 41         if (info->flags & IPRANGE_DST) {
 42                 if ((ntohl(iph->daddr) < ntohl(info->dst.min_ip)
 43                           || ntohl(iph->daddr) > ntohl(info->dst.max_ip))
 44                          ^ !!(info->flags & IPRANGE_DST_INV)) {
 45                         pr_debug("dst IP %u.%u.%u.%u NOT in range %s"
 46                                  "%u.%u.%u.%u-%u.%u.%u.%u\n",
 47                                  NIPQUAD(iph->daddr),
 48                                  info->flags & IPRANGE_DST_INV ? "(INV) " : "",
 49                                  NIPQUAD(info->dst.min_ip),
 50                                  NIPQUAD(info->dst.max_ip));
 51                         return false;
 52                 }
 53         }
 54         return true;
 55 }
 56 
 57 static bool
 58 iprange_mt4(const struct sk_buff *skb, const struct net_device *in,
 59             const struct net_device *out, const struct xt_match *match,
 60             const void *matchinfo, int offset, unsigned int protoff,
 61             bool *hotdrop)
 62 {
 63         const struct xt_iprange_mtinfo *info = matchinfo;
 64         const struct iphdr *iph = ip_hdr(skb);
 65         bool m;
 66 
 67         if (info->flags & IPRANGE_SRC) {
 68                 m  = ntohl(iph->saddr) < ntohl(info->src_min.ip);
 69                 m |= ntohl(iph->saddr) > ntohl(info->src_max.ip);
 70                 m ^= info->flags & IPRANGE_SRC_INV;
 71                 if (m) {
 72                         pr_debug("src IP " NIPQUAD_FMT " NOT in range %s"
 73                                  NIPQUAD_FMT "-" NIPQUAD_FMT "\n",
 74                                  NIPQUAD(iph->saddr),
 75                                  (info->flags & IPRANGE_SRC_INV) ? "(INV) " : "",
 76                                  NIPQUAD(info->src_max.ip),
 77                                  NIPQUAD(info->src_max.ip));
 78                         return false;
 79                 }
 80         }
 81         if (info->flags & IPRANGE_DST) {
 82                 m  = ntohl(iph->daddr) < ntohl(info->dst_min.ip);
 83                 m |= ntohl(iph->daddr) > ntohl(info->dst_max.ip);
 84                 m ^= info->flags & IPRANGE_DST_INV;
 85                 if (m) {
 86                         pr_debug("dst IP " NIPQUAD_FMT " NOT in range %s"
 87                                  NIPQUAD_FMT "-" NIPQUAD_FMT "\n",
 88                                  NIPQUAD(iph->daddr),
 89                                  (info->flags & IPRANGE_DST_INV) ? "(INV) " : "",
 90                                  NIPQUAD(info->dst_min.ip),
 91                                  NIPQUAD(info->dst_max.ip));
 92                         return false;
 93                 }
 94         }
 95         return true;
 96 }
 97 
 98 static inline int
 99 iprange_ipv6_sub(const struct in6_addr *a, const struct in6_addr *b)
100 {
101         unsigned int i;
102         int r;
103 
104         for (i = 0; i < 4; ++i) {
105                 r = ntohl(a->s6_addr32[i]) - ntohl(b->s6_addr32[i]);
106                 if (r != 0)
107                         return r;
108         }
109 
110         return 0;
111 }
112 
113 static bool
114 iprange_mt6(const struct sk_buff *skb, const struct net_device *in,
115             const struct net_device *out, const struct xt_match *match,
116             const void *matchinfo, int offset, unsigned int protoff,
117             bool *hotdrop)
118 {
119         const struct xt_iprange_mtinfo *info = matchinfo;
120         const struct ipv6hdr *iph = ipv6_hdr(skb);
121         bool m;
122 
123         if (info->flags & IPRANGE_SRC) {
124                 m  = iprange_ipv6_sub(&iph->saddr, &info->src_min.in6) < 0;
125                 m |= iprange_ipv6_sub(&iph->saddr, &info->src_max.in6) > 0;
126                 m ^= info->flags & IPRANGE_SRC_INV;
127                 if (m)
128                         return false;
129         }
130         if (info->flags & IPRANGE_DST) {
131                 m  = iprange_ipv6_sub(&iph->daddr, &info->dst_min.in6) < 0;
132                 m |= iprange_ipv6_sub(&iph->daddr, &info->dst_max.in6) > 0;
133                 m ^= info->flags & IPRANGE_DST_INV;
134                 if (m)
135                         return false;
136         }
137         return true;
138 }
139 
140 static struct xt_match iprange_mt_reg[] __read_mostly = {
141         {
142                 .name      = "iprange",
143                 .revision  = 0,
144                 .family    = AF_INET,
145                 .match     = iprange_mt_v0,
146                 .matchsize = sizeof(struct ipt_iprange_info),
147                 .me        = THIS_MODULE,
148         },
149         {
150                 .name      = "iprange",
151                 .revision  = 1,
152                 .family    = AF_INET,
153                 .match     = iprange_mt4,
154                 .matchsize = sizeof(struct xt_iprange_mtinfo),
155                 .me        = THIS_MODULE,
156         },
157         {
158                 .name      = "iprange",
159                 .revision  = 1,
160                 .family    = AF_INET6,
161                 .match     = iprange_mt6,
162                 .matchsize = sizeof(struct xt_iprange_mtinfo),
163                 .me        = THIS_MODULE,
164         },
165 };
166 
167 static int __init iprange_mt_init(void)
168 {
169         return xt_register_matches(iprange_mt_reg, ARRAY_SIZE(iprange_mt_reg));
170 }
171 
172 static void __exit iprange_mt_exit(void)
173 {
174         xt_unregister_matches(iprange_mt_reg, ARRAY_SIZE(iprange_mt_reg));
175 }
176 
177 module_init(iprange_mt_init);
178 module_exit(iprange_mt_exit);
179 MODULE_LICENSE("GPL");
180 MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>, Jan Engelhardt <jengelh@computergmbh.de>");
181 MODULE_DESCRIPTION("Xtables: arbitrary IPv4 range matching");
182 
  This page was automatically generated by the LXR engine.