diff options
author | Jan Engelhardt <jengelh@computergmbh.de> | 2008-01-15 02:43:03 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-01-28 18:02:28 -0500 |
commit | 1a50c5a1fe20864f1f902ef76862519a65d14723 (patch) | |
tree | 4f3d0151d3b1dfa92754d8ea3d28ce8a98ed1548 /net | |
parent | f72e25a897c7edda03a0e1f767925d98772684da (diff) |
[NETFILTER]: xt_iprange match, revision 1
Adds IPv6 support to xt_iprange, making it possible to match on IPv6
address ranges with ip6tables.
Signed-off-by: Jan Engelhardt <jengelh@computergmbh.de>
Signed-off-by: Patrick McHardy <kaber@trash.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r-- | net/netfilter/xt_iprange.c | 122 |
1 files changed, 113 insertions, 9 deletions
diff --git a/net/netfilter/xt_iprange.c b/net/netfilter/xt_iprange.c index c57a6cf8a081..dbea0e0893f3 100644 --- a/net/netfilter/xt_iprange.c +++ b/net/netfilter/xt_iprange.c | |||
@@ -2,6 +2,7 @@ | |||
2 | * xt_iprange - Netfilter module to match IP address ranges | 2 | * xt_iprange - Netfilter module to match IP address ranges |
3 | * | 3 | * |
4 | * (C) 2003 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu> | 4 | * (C) 2003 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu> |
5 | * (C) CC Computer Consultants GmbH, 2008 | ||
5 | * | 6 | * |
6 | * This program is free software; you can redistribute it and/or modify | 7 | * This program is free software; you can redistribute it and/or modify |
7 | * it under the terms of the GNU General Public License version 2 as | 8 | * it under the terms of the GNU General Public License version 2 as |
@@ -10,6 +11,7 @@ | |||
10 | #include <linux/module.h> | 11 | #include <linux/module.h> |
11 | #include <linux/skbuff.h> | 12 | #include <linux/skbuff.h> |
12 | #include <linux/ip.h> | 13 | #include <linux/ip.h> |
14 | #include <linux/ipv6.h> | ||
13 | #include <linux/netfilter/x_tables.h> | 15 | #include <linux/netfilter/x_tables.h> |
14 | #include <linux/netfilter_ipv4/ipt_iprange.h> | 16 | #include <linux/netfilter_ipv4/ipt_iprange.h> |
15 | 17 | ||
@@ -51,26 +53,128 @@ iprange_mt_v0(const struct sk_buff *skb, const struct net_device *in, | |||
51 | return true; | 53 | return true; |
52 | } | 54 | } |
53 | 55 | ||
54 | static struct xt_match iprange_mt_reg __read_mostly = { | 56 | static bool |
55 | .name = "iprange", | 57 | iprange_mt4(const struct sk_buff *skb, const struct net_device *in, |
56 | .family = AF_INET, | 58 | const struct net_device *out, const struct xt_match *match, |
57 | .match = iprange_mt_v0, | 59 | const void *matchinfo, int offset, unsigned int protoff, |
58 | .matchsize = sizeof(struct ipt_iprange_info), | 60 | bool *hotdrop) |
59 | .me = THIS_MODULE | 61 | { |
62 | const struct xt_iprange_mtinfo *info = matchinfo; | ||
63 | const struct iphdr *iph = ip_hdr(skb); | ||
64 | bool m; | ||
65 | |||
66 | if (info->flags & IPRANGE_SRC) { | ||
67 | m = ntohl(iph->saddr) < ntohl(info->src_min.ip); | ||
68 | m |= ntohl(iph->saddr) > ntohl(info->src_max.ip); | ||
69 | m ^= info->flags & IPRANGE_SRC_INV; | ||
70 | if (m) { | ||
71 | pr_debug("src IP " NIPQUAD_FMT " NOT in range %s" | ||
72 | NIPQUAD_FMT "-" NIPQUAD_FMT "\n", | ||
73 | NIPQUAD(iph->saddr), | ||
74 | (info->flags & IPRANGE_SRC_INV) ? "(INV) " : "", | ||
75 | NIPQUAD(info->src_max.ip), | ||
76 | NIPQUAD(info->src_max.ip)); | ||
77 | return false; | ||
78 | } | ||
79 | } | ||
80 | if (info->flags & IPRANGE_DST) { | ||
81 | m = ntohl(iph->daddr) < ntohl(info->dst_min.ip); | ||
82 | m |= ntohl(iph->daddr) > ntohl(info->dst_max.ip); | ||
83 | m ^= info->flags & IPRANGE_DST_INV; | ||
84 | if (m) { | ||
85 | pr_debug("dst IP " NIPQUAD_FMT " NOT in range %s" | ||
86 | NIPQUAD_FMT "-" NIPQUAD_FMT "\n", | ||
87 | NIPQUAD(iph->daddr), | ||
88 | (info->flags & IPRANGE_DST_INV) ? "(INV) " : "", | ||
89 | NIPQUAD(info->dst_min.ip), | ||
90 | NIPQUAD(info->dst_max.ip)); | ||
91 | return false; | ||
92 | } | ||
93 | } | ||
94 | return true; | ||
95 | } | ||
96 | |||
97 | static inline int | ||
98 | iprange_ipv6_sub(const struct in6_addr *a, const struct in6_addr *b) | ||
99 | { | ||
100 | unsigned int i; | ||
101 | int r; | ||
102 | |||
103 | for (i = 0; i < 4; ++i) { | ||
104 | r = a->s6_addr32[i] - b->s6_addr32[i]; | ||
105 | if (r != 0) | ||
106 | return r; | ||
107 | } | ||
108 | |||
109 | return 0; | ||
110 | } | ||
111 | |||
112 | static bool | ||
113 | iprange_mt6(const struct sk_buff *skb, const struct net_device *in, | ||
114 | const struct net_device *out, const struct xt_match *match, | ||
115 | const void *matchinfo, int offset, unsigned int protoff, | ||
116 | bool *hotdrop) | ||
117 | { | ||
118 | const struct xt_iprange_mtinfo *info = matchinfo; | ||
119 | const struct ipv6hdr *iph = ipv6_hdr(skb); | ||
120 | bool m; | ||
121 | |||
122 | if (info->flags & IPRANGE_SRC) { | ||
123 | m = iprange_ipv6_sub(&iph->saddr, &info->src_min.in6) < 0; | ||
124 | m |= iprange_ipv6_sub(&iph->saddr, &info->src_max.in6) > 0; | ||
125 | m ^= info->flags & IPRANGE_SRC_INV; | ||
126 | if (m) | ||
127 | return false; | ||
128 | } | ||
129 | if (info->flags & IPRANGE_DST) { | ||
130 | m = iprange_ipv6_sub(&iph->daddr, &info->dst_min.in6) < 0; | ||
131 | m |= iprange_ipv6_sub(&iph->daddr, &info->dst_max.in6) > 0; | ||
132 | m ^= info->flags & IPRANGE_DST_INV; | ||
133 | if (m) | ||
134 | return false; | ||
135 | } | ||
136 | return true; | ||
137 | } | ||
138 | |||
139 | static struct xt_match iprange_mt_reg[] __read_mostly = { | ||
140 | { | ||
141 | .name = "iprange", | ||
142 | .revision = 0, | ||
143 | .family = AF_INET, | ||
144 | .match = iprange_mt_v0, | ||
145 | .matchsize = sizeof(struct ipt_iprange_info), | ||
146 | .me = THIS_MODULE, | ||
147 | }, | ||
148 | { | ||
149 | .name = "iprange", | ||
150 | .revision = 1, | ||
151 | .family = AF_INET6, | ||
152 | .match = iprange_mt4, | ||
153 | .matchsize = sizeof(struct xt_iprange_mtinfo), | ||
154 | .me = THIS_MODULE, | ||
155 | }, | ||
156 | { | ||
157 | .name = "iprange", | ||
158 | .revision = 1, | ||
159 | .family = AF_INET6, | ||
160 | .match = iprange_mt6, | ||
161 | .matchsize = sizeof(struct xt_iprange_mtinfo), | ||
162 | .me = THIS_MODULE, | ||
163 | }, | ||
60 | }; | 164 | }; |
61 | 165 | ||
62 | static int __init iprange_mt_init(void) | 166 | static int __init iprange_mt_init(void) |
63 | { | 167 | { |
64 | return xt_register_match(&iprange_mt_reg); | 168 | return xt_register_matches(iprange_mt_reg, ARRAY_SIZE(iprange_mt_reg)); |
65 | } | 169 | } |
66 | 170 | ||
67 | static void __exit iprange_mt_exit(void) | 171 | static void __exit iprange_mt_exit(void) |
68 | { | 172 | { |
69 | xt_unregister_match(&iprange_mt_reg); | 173 | xt_unregister_matches(iprange_mt_reg, ARRAY_SIZE(iprange_mt_reg)); |
70 | } | 174 | } |
71 | 175 | ||
72 | module_init(iprange_mt_init); | 176 | module_init(iprange_mt_init); |
73 | module_exit(iprange_mt_exit); | 177 | module_exit(iprange_mt_exit); |
74 | MODULE_LICENSE("GPL"); | 178 | MODULE_LICENSE("GPL"); |
75 | MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>"); | 179 | MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>, Jan Engelhardt <jengelh@computergmbh.de>"); |
76 | MODULE_DESCRIPTION("Xtables: arbitrary IPv4 range matching"); | 180 | MODULE_DESCRIPTION("Xtables: arbitrary IPv4 range matching"); |