Blame view
net/netfilter/xt_iprange.c
3.78 KB
1da177e4c
|
1 |
/* |
f72e25a89
|
2 |
* xt_iprange - Netfilter module to match IP address ranges |
1da177e4c
|
3 |
* |
f72e25a89
|
4 |
* (C) 2003 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu> |
1a50c5a1f
|
5 |
* (C) CC Computer Consultants GmbH, 2008 |
1da177e4c
|
6 |
* |
f72e25a89
|
7 8 9 |
* This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. |
1da177e4c
|
10 |
*/ |
ff67e4e42
|
11 |
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
1da177e4c
|
12 13 14 |
#include <linux/module.h> #include <linux/skbuff.h> #include <linux/ip.h> |
1a50c5a1f
|
15 |
#include <linux/ipv6.h> |
6709dbbb1
|
16 |
#include <linux/netfilter/x_tables.h> |
5da621f1c
|
17 |
#include <linux/netfilter/xt_iprange.h> |
1da177e4c
|
18 |
|
1a50c5a1f
|
19 |
static bool |
62fc80510
|
20 |
iprange_mt4(const struct sk_buff *skb, struct xt_action_param *par) |
1a50c5a1f
|
21 |
{ |
f7108a20d
|
22 |
const struct xt_iprange_mtinfo *info = par->matchinfo; |
1a50c5a1f
|
23 24 25 26 27 28 |
const struct iphdr *iph = ip_hdr(skb); bool m; if (info->flags & IPRANGE_SRC) { m = ntohl(iph->saddr) < ntohl(info->src_min.ip); m |= ntohl(iph->saddr) > ntohl(info->src_max.ip); |
6def1eb48
|
29 |
m ^= !!(info->flags & IPRANGE_SRC_INV); |
1a50c5a1f
|
30 |
if (m) { |
14d5e834f
|
31 32 33 |
pr_debug("src IP %pI4 NOT in range %s%pI4-%pI4 ", &iph->saddr, |
1a50c5a1f
|
34 |
(info->flags & IPRANGE_SRC_INV) ? "(INV) " : "", |
705ca1471
|
35 |
&info->src_min.ip, |
14d5e834f
|
36 |
&info->src_max.ip); |
1a50c5a1f
|
37 38 39 40 41 42 |
return false; } } if (info->flags & IPRANGE_DST) { m = ntohl(iph->daddr) < ntohl(info->dst_min.ip); m |= ntohl(iph->daddr) > ntohl(info->dst_max.ip); |
6def1eb48
|
43 |
m ^= !!(info->flags & IPRANGE_DST_INV); |
1a50c5a1f
|
44 |
if (m) { |
14d5e834f
|
45 46 47 |
pr_debug("dst IP %pI4 NOT in range %s%pI4-%pI4 ", &iph->daddr, |
1a50c5a1f
|
48 |
(info->flags & IPRANGE_DST_INV) ? "(INV) " : "", |
14d5e834f
|
49 50 |
&info->dst_min.ip, &info->dst_max.ip); |
1a50c5a1f
|
51 52 53 54 55 56 57 |
return false; } } return true; } static inline int |
08b5194b5
|
58 |
iprange_ipv6_lt(const struct in6_addr *a, const struct in6_addr *b) |
1a50c5a1f
|
59 60 |
{ unsigned int i; |
1a50c5a1f
|
61 62 |
for (i = 0; i < 4; ++i) { |
08b5194b5
|
63 64 |
if (a->s6_addr32[i] != b->s6_addr32[i]) return ntohl(a->s6_addr32[i]) < ntohl(b->s6_addr32[i]); |
1a50c5a1f
|
65 66 67 68 69 70 |
} return 0; } static bool |
62fc80510
|
71 |
iprange_mt6(const struct sk_buff *skb, struct xt_action_param *par) |
1a50c5a1f
|
72 |
{ |
f7108a20d
|
73 |
const struct xt_iprange_mtinfo *info = par->matchinfo; |
1a50c5a1f
|
74 75 76 77 |
const struct ipv6hdr *iph = ipv6_hdr(skb); bool m; if (info->flags & IPRANGE_SRC) { |
08b5194b5
|
78 79 |
m = iprange_ipv6_lt(&iph->saddr, &info->src_min.in6); m |= iprange_ipv6_lt(&info->src_max.in6, &iph->saddr); |
6def1eb48
|
80 |
m ^= !!(info->flags & IPRANGE_SRC_INV); |
6a4ddef2a
|
81 82 83 84 85 86 87 |
if (m) { pr_debug("src IP %pI6 NOT in range %s%pI6-%pI6 ", &iph->saddr, (info->flags & IPRANGE_SRC_INV) ? "(INV) " : "", &info->src_min.in6, &info->src_max.in6); |
1a50c5a1f
|
88 |
return false; |
6a4ddef2a
|
89 |
} |
1a50c5a1f
|
90 91 |
} if (info->flags & IPRANGE_DST) { |
08b5194b5
|
92 93 |
m = iprange_ipv6_lt(&iph->daddr, &info->dst_min.in6); m |= iprange_ipv6_lt(&info->dst_max.in6, &iph->daddr); |
6def1eb48
|
94 |
m ^= !!(info->flags & IPRANGE_DST_INV); |
6a4ddef2a
|
95 96 97 98 99 100 101 |
if (m) { pr_debug("dst IP %pI6 NOT in range %s%pI6-%pI6 ", &iph->daddr, (info->flags & IPRANGE_DST_INV) ? "(INV) " : "", &info->dst_min.in6, &info->dst_max.in6); |
1a50c5a1f
|
102 |
return false; |
6a4ddef2a
|
103 |
} |
1a50c5a1f
|
104 105 106 107 108 109 110 |
} return true; } static struct xt_match iprange_mt_reg[] __read_mostly = { { .name = "iprange", |
1a50c5a1f
|
111 |
.revision = 1, |
ee999d8b9
|
112 |
.family = NFPROTO_IPV4, |
1a50c5a1f
|
113 114 115 116 117 118 119 |
.match = iprange_mt4, .matchsize = sizeof(struct xt_iprange_mtinfo), .me = THIS_MODULE, }, { .name = "iprange", .revision = 1, |
ee999d8b9
|
120 |
.family = NFPROTO_IPV6, |
1a50c5a1f
|
121 122 123 124 |
.match = iprange_mt6, .matchsize = sizeof(struct xt_iprange_mtinfo), .me = THIS_MODULE, }, |
1da177e4c
|
125 |
}; |
d3c5ee6d5
|
126 |
static int __init iprange_mt_init(void) |
1da177e4c
|
127 |
{ |
1a50c5a1f
|
128 |
return xt_register_matches(iprange_mt_reg, ARRAY_SIZE(iprange_mt_reg)); |
1da177e4c
|
129 |
} |
d3c5ee6d5
|
130 |
static void __exit iprange_mt_exit(void) |
1da177e4c
|
131 |
{ |
1a50c5a1f
|
132 |
xt_unregister_matches(iprange_mt_reg, ARRAY_SIZE(iprange_mt_reg)); |
1da177e4c
|
133 |
} |
d3c5ee6d5
|
134 135 |
module_init(iprange_mt_init); module_exit(iprange_mt_exit); |
f72e25a89
|
136 |
MODULE_LICENSE("GPL"); |
36d4084dc
|
137 138 |
MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>"); MODULE_AUTHOR("Jan Engelhardt <jengelh@medozas.de>"); |
f72e25a89
|
139 |
MODULE_DESCRIPTION("Xtables: arbitrary IPv4 range matching"); |
01b7a3142
|
140 141 |
MODULE_ALIAS("ipt_iprange"); MODULE_ALIAS("ip6t_iprange"); |