blob: 501f9b6231886cb21fcf112f8fbbf01ed8ca2a76 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
Jan Engelhardtf72e25a2008-01-14 23:42:47 -08002 * xt_iprange - Netfilter module to match IP address ranges
Linus Torvalds1da177e2005-04-16 15:20:36 -07003 *
Jan Engelhardtf72e25a2008-01-14 23:42:47 -08004 * (C) 2003 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
Jan Engelhardt1a50c5a2008-01-14 23:43:03 -08005 * (C) CC Computer Consultants GmbH, 2008
Linus Torvalds1da177e2005-04-16 15:20:36 -07006 *
Jan Engelhardtf72e25a2008-01-14 23:42:47 -08007 * 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.
Linus Torvalds1da177e2005-04-16 15:20:36 -070010 */
11#include <linux/module.h>
12#include <linux/skbuff.h>
13#include <linux/ip.h>
Jan Engelhardt1a50c5a2008-01-14 23:43:03 -080014#include <linux/ipv6.h>
Jan Engelhardt6709dbb2007-02-07 15:11:19 -080015#include <linux/netfilter/x_tables.h>
Jan Engelhardt5da621f2008-02-07 17:57:11 -080016#include <linux/netfilter/xt_iprange.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070017#include <linux/netfilter_ipv4/ipt_iprange.h>
18
Jan Engelhardt1d93a9c2007-07-07 22:15:35 -070019static bool
Jan Engelhardtf7108a22008-10-08 11:35:18 +020020iprange_mt_v0(const struct sk_buff *skb, const struct xt_match_param *par)
Linus Torvalds1da177e2005-04-16 15:20:36 -070021{
Jan Engelhardtf7108a22008-10-08 11:35:18 +020022 const struct ipt_iprange_info *info = par->matchinfo;
Arnaldo Carvalho de Meloeddc9ec2007-04-20 22:47:35 -070023 const struct iphdr *iph = ip_hdr(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -070024
25 if (info->flags & IPRANGE_SRC) {
Jan Engelhardt7c4e36b2007-07-07 22:19:08 -070026 if ((ntohl(iph->saddr) < ntohl(info->src.min_ip)
27 || ntohl(iph->saddr) > ntohl(info->src.max_ip))
Linus Torvalds1da177e2005-04-16 15:20:36 -070028 ^ !!(info->flags & IPRANGE_SRC_INV)) {
Harvey Harrison14d5e832008-10-31 00:54:29 -070029 pr_debug("src IP %pI4 NOT in range %s%pI4-%pI4\n",
30 &iph->saddr,
Patrick McHardy0d537782007-07-07 22:39:38 -070031 info->flags & IPRANGE_SRC_INV ? "(INV) " : "",
Harvey Harrison14d5e832008-10-31 00:54:29 -070032 &info->src.min_ip,
33 &info->src.max_ip);
Jan Engelhardt1d93a9c2007-07-07 22:15:35 -070034 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -070035 }
36 }
37 if (info->flags & IPRANGE_DST) {
Jan Engelhardt7c4e36b2007-07-07 22:19:08 -070038 if ((ntohl(iph->daddr) < ntohl(info->dst.min_ip)
39 || ntohl(iph->daddr) > ntohl(info->dst.max_ip))
Linus Torvalds1da177e2005-04-16 15:20:36 -070040 ^ !!(info->flags & IPRANGE_DST_INV)) {
Harvey Harrison14d5e832008-10-31 00:54:29 -070041 pr_debug("dst IP %pI4 NOT in range %s%pI4-%pI4\n",
42 &iph->daddr,
Patrick McHardy0d537782007-07-07 22:39:38 -070043 info->flags & IPRANGE_DST_INV ? "(INV) " : "",
Harvey Harrison14d5e832008-10-31 00:54:29 -070044 &info->dst.min_ip,
45 &info->dst.max_ip);
Jan Engelhardt1d93a9c2007-07-07 22:15:35 -070046 return false;
Linus Torvalds1da177e2005-04-16 15:20:36 -070047 }
48 }
Jan Engelhardt1d93a9c2007-07-07 22:15:35 -070049 return true;
Linus Torvalds1da177e2005-04-16 15:20:36 -070050}
51
Jan Engelhardt1a50c5a2008-01-14 23:43:03 -080052static bool
Jan Engelhardtf7108a22008-10-08 11:35:18 +020053iprange_mt4(const struct sk_buff *skb, const struct xt_match_param *par)
Jan Engelhardt1a50c5a2008-01-14 23:43:03 -080054{
Jan Engelhardtf7108a22008-10-08 11:35:18 +020055 const struct xt_iprange_mtinfo *info = par->matchinfo;
Jan Engelhardt1a50c5a2008-01-14 23:43:03 -080056 const struct iphdr *iph = ip_hdr(skb);
57 bool m;
58
59 if (info->flags & IPRANGE_SRC) {
60 m = ntohl(iph->saddr) < ntohl(info->src_min.ip);
61 m |= ntohl(iph->saddr) > ntohl(info->src_max.ip);
Alexey Dobriyan6def1eb2008-10-20 03:32:21 -070062 m ^= !!(info->flags & IPRANGE_SRC_INV);
Jan Engelhardt1a50c5a2008-01-14 23:43:03 -080063 if (m) {
Harvey Harrison14d5e832008-10-31 00:54:29 -070064 pr_debug("src IP %pI4 NOT in range %s%pI4-%pI4\n",
65 &iph->saddr,
Jan Engelhardt1a50c5a2008-01-14 23:43:03 -080066 (info->flags & IPRANGE_SRC_INV) ? "(INV) " : "",
Harvey Harrison14d5e832008-10-31 00:54:29 -070067 &info->src_max.ip,
68 &info->src_max.ip);
Jan Engelhardt1a50c5a2008-01-14 23:43:03 -080069 return false;
70 }
71 }
72 if (info->flags & IPRANGE_DST) {
73 m = ntohl(iph->daddr) < ntohl(info->dst_min.ip);
74 m |= ntohl(iph->daddr) > ntohl(info->dst_max.ip);
Alexey Dobriyan6def1eb2008-10-20 03:32:21 -070075 m ^= !!(info->flags & IPRANGE_DST_INV);
Jan Engelhardt1a50c5a2008-01-14 23:43:03 -080076 if (m) {
Harvey Harrison14d5e832008-10-31 00:54:29 -070077 pr_debug("dst IP %pI4 NOT in range %s%pI4-%pI4\n",
78 &iph->daddr,
Jan Engelhardt1a50c5a2008-01-14 23:43:03 -080079 (info->flags & IPRANGE_DST_INV) ? "(INV) " : "",
Harvey Harrison14d5e832008-10-31 00:54:29 -070080 &info->dst_min.ip,
81 &info->dst_max.ip);
Jan Engelhardt1a50c5a2008-01-14 23:43:03 -080082 return false;
83 }
84 }
85 return true;
86}
87
88static inline int
89iprange_ipv6_sub(const struct in6_addr *a, const struct in6_addr *b)
90{
91 unsigned int i;
92 int r;
93
94 for (i = 0; i < 4; ++i) {
Jan Engelhardt27ecb1f2008-02-19 17:20:06 -080095 r = ntohl(a->s6_addr32[i]) - ntohl(b->s6_addr32[i]);
Jan Engelhardt1a50c5a2008-01-14 23:43:03 -080096 if (r != 0)
97 return r;
98 }
99
100 return 0;
101}
102
103static bool
Jan Engelhardtf7108a22008-10-08 11:35:18 +0200104iprange_mt6(const struct sk_buff *skb, const struct xt_match_param *par)
Jan Engelhardt1a50c5a2008-01-14 23:43:03 -0800105{
Jan Engelhardtf7108a22008-10-08 11:35:18 +0200106 const struct xt_iprange_mtinfo *info = par->matchinfo;
Jan Engelhardt1a50c5a2008-01-14 23:43:03 -0800107 const struct ipv6hdr *iph = ipv6_hdr(skb);
108 bool m;
109
110 if (info->flags & IPRANGE_SRC) {
111 m = iprange_ipv6_sub(&iph->saddr, &info->src_min.in6) < 0;
112 m |= iprange_ipv6_sub(&iph->saddr, &info->src_max.in6) > 0;
Alexey Dobriyan6def1eb2008-10-20 03:32:21 -0700113 m ^= !!(info->flags & IPRANGE_SRC_INV);
Jan Engelhardt1a50c5a2008-01-14 23:43:03 -0800114 if (m)
115 return false;
116 }
117 if (info->flags & IPRANGE_DST) {
118 m = iprange_ipv6_sub(&iph->daddr, &info->dst_min.in6) < 0;
119 m |= iprange_ipv6_sub(&iph->daddr, &info->dst_max.in6) > 0;
Alexey Dobriyan6def1eb2008-10-20 03:32:21 -0700120 m ^= !!(info->flags & IPRANGE_DST_INV);
Jan Engelhardt1a50c5a2008-01-14 23:43:03 -0800121 if (m)
122 return false;
123 }
124 return true;
125}
126
127static struct xt_match iprange_mt_reg[] __read_mostly = {
128 {
129 .name = "iprange",
130 .revision = 0,
Jan Engelhardtee999d82008-10-08 11:35:01 +0200131 .family = NFPROTO_IPV4,
Jan Engelhardt1a50c5a2008-01-14 23:43:03 -0800132 .match = iprange_mt_v0,
133 .matchsize = sizeof(struct ipt_iprange_info),
134 .me = THIS_MODULE,
135 },
136 {
137 .name = "iprange",
138 .revision = 1,
Jan Engelhardtee999d82008-10-08 11:35:01 +0200139 .family = NFPROTO_IPV4,
Jan Engelhardt1a50c5a2008-01-14 23:43:03 -0800140 .match = iprange_mt4,
141 .matchsize = sizeof(struct xt_iprange_mtinfo),
142 .me = THIS_MODULE,
143 },
144 {
145 .name = "iprange",
146 .revision = 1,
Jan Engelhardtee999d82008-10-08 11:35:01 +0200147 .family = NFPROTO_IPV6,
Jan Engelhardt1a50c5a2008-01-14 23:43:03 -0800148 .match = iprange_mt6,
149 .matchsize = sizeof(struct xt_iprange_mtinfo),
150 .me = THIS_MODULE,
151 },
Linus Torvalds1da177e2005-04-16 15:20:36 -0700152};
153
Jan Engelhardtd3c5ee62007-12-04 23:24:03 -0800154static int __init iprange_mt_init(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700155{
Jan Engelhardt1a50c5a2008-01-14 23:43:03 -0800156 return xt_register_matches(iprange_mt_reg, ARRAY_SIZE(iprange_mt_reg));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700157}
158
Jan Engelhardtd3c5ee62007-12-04 23:24:03 -0800159static void __exit iprange_mt_exit(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700160{
Jan Engelhardt1a50c5a2008-01-14 23:43:03 -0800161 xt_unregister_matches(iprange_mt_reg, ARRAY_SIZE(iprange_mt_reg));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700162}
163
Jan Engelhardtd3c5ee62007-12-04 23:24:03 -0800164module_init(iprange_mt_init);
165module_exit(iprange_mt_exit);
Jan Engelhardtf72e25a2008-01-14 23:42:47 -0800166MODULE_LICENSE("GPL");
Jan Engelhardt1a50c5a2008-01-14 23:43:03 -0800167MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>, Jan Engelhardt <jengelh@computergmbh.de>");
Jan Engelhardtf72e25a2008-01-14 23:42:47 -0800168MODULE_DESCRIPTION("Xtables: arbitrary IPv4 range matching");
Phil Oester01b7a312008-05-13 23:27:48 -0700169MODULE_ALIAS("ipt_iprange");
170MODULE_ALIAS("ip6t_iprange");