blob: 2c9ea99266dcda39e7e1b550fd9f54aa9a267dde [file] [log] [blame]
Jan Engelhardtce4b7952011-05-07 14:39:08 +02001#include <stdint.h>
Joszef Kadlecsik9cb66152003-04-23 13:27:09 +00002#include <stdio.h>
Joszef Kadlecsik9cb66152003-04-23 13:27:09 +00003#include <string.h>
4#include <stdlib.h>
Jan Engelhardtfc11b0b2008-01-20 13:43:49 +00005#include <xtables.h>
6#include <linux/netfilter.h>
7#include <linux/netfilter/xt_iprange.h>
Jan Engelhardt350661a2010-01-31 22:42:52 +01008
9struct ipt_iprange {
10 /* Inclusive: network order. */
11 __be32 min_ip, max_ip;
12};
13
14struct ipt_iprange_info {
15 struct ipt_iprange src;
16 struct ipt_iprange dst;
17
18 /* Flags from above */
Jan Engelhardt7ac40522011-01-07 12:34:04 +010019 uint8_t flags;
Jan Engelhardt350661a2010-01-31 22:42:52 +010020};
Joszef Kadlecsik9cb66152003-04-23 13:27:09 +000021
Jan Engelhardtfc11b0b2008-01-20 13:43:49 +000022enum {
Jan Engelhardtce4b7952011-05-07 14:39:08 +020023 O_SRC_RANGE = 0,
24 O_DST_RANGE,
Jan Engelhardtfc11b0b2008-01-20 13:43:49 +000025};
26
Jan Engelhardt41daaa02008-01-20 13:42:43 +000027static void iprange_mt_help(void)
Joszef Kadlecsik9cb66152003-04-23 13:27:09 +000028{
29 printf(
Jan Engelhardt41daaa02008-01-20 13:42:43 +000030"iprange match options:\n"
Jan Engelhardta10a12a2009-09-18 09:59:26 +020031"[!] --src-range ip[-ip] Match source IP in the specified range\n"
32"[!] --dst-range ip[-ip] Match destination IP in the specified range\n");
Joszef Kadlecsik9cb66152003-04-23 13:27:09 +000033}
34
Jan Engelhardtce4b7952011-05-07 14:39:08 +020035static const struct xt_option_entry iprange_mt_opts[] = {
36 {.name = "src-range", .id = O_SRC_RANGE, .type = XTTYPE_STRING,
37 .flags = XTOPT_INVERT},
38 {.name = "dst-range", .id = O_DST_RANGE, .type = XTTYPE_STRING,
39 .flags = XTOPT_INVERT},
40 XTOPT_TABLEEND,
Joszef Kadlecsik9cb66152003-04-23 13:27:09 +000041};
42
Jan Engelhardt648a7ba2009-09-18 13:01:05 +020043static void
44iprange_parse_spec(const char *from, const char *to, union nf_inet_addr *range,
45 uint8_t family, const char *optname)
Joszef Kadlecsik9cb66152003-04-23 13:27:09 +000046{
Jan Engelhardt7fa73292009-09-18 13:07:09 +020047 const char *spec[2] = {from, to};
Jan Engelhardta10a12a2009-09-18 09:59:26 +020048 struct in6_addr *ia6;
49 struct in_addr *ia4;
Jan Engelhardt7fa73292009-09-18 13:07:09 +020050 unsigned int i;
Joszef Kadlecsik9cb66152003-04-23 13:27:09 +000051
Jan Engelhardta10a12a2009-09-18 09:59:26 +020052 memset(range, 0, sizeof(union nf_inet_addr) * 2);
Jan Engelhardt41daaa02008-01-20 13:42:43 +000053
Jan Engelhardta10a12a2009-09-18 09:59:26 +020054 if (family == NFPROTO_IPV6) {
Jan Engelhardt7fa73292009-09-18 13:07:09 +020055 for (i = 0; i < ARRAY_SIZE(spec); ++i) {
56 ia6 = xtables_numeric_to_ip6addr(spec[i]);
57 if (ia6 == NULL)
58 xtables_param_act(XTF_BAD_VALUE, "iprange",
59 optname, spec[i]);
60 range[i].in6 = *ia6;
61 }
Jan Engelhardt41daaa02008-01-20 13:42:43 +000062 } else {
Jan Engelhardt7fa73292009-09-18 13:07:09 +020063 for (i = 0; i < ARRAY_SIZE(spec); ++i) {
64 ia4 = xtables_numeric_to_ipaddr(spec[i]);
65 if (ia4 == NULL)
66 xtables_param_act(XTF_BAD_VALUE, "iprange",
67 optname, spec[i]);
68 range[i].in = *ia4;
69 }
Jan Engelhardt41daaa02008-01-20 13:42:43 +000070 }
Joszef Kadlecsik9cb66152003-04-23 13:27:09 +000071}
72
Jan Engelhardtce4b7952011-05-07 14:39:08 +020073static void iprange_parse_range(const char *oarg, union nf_inet_addr *range,
Jan Engelhardt7ac40522011-01-07 12:34:04 +010074 uint8_t family, const char *optname)
Jan Engelhardt648a7ba2009-09-18 13:01:05 +020075{
Jan Engelhardtce4b7952011-05-07 14:39:08 +020076 char *arg = strdup(oarg);
Jan Engelhardt648a7ba2009-09-18 13:01:05 +020077 char *dash;
78
Jan Engelhardtce4b7952011-05-07 14:39:08 +020079 if (arg == NULL)
80 xtables_error(RESOURCE_PROBLEM, "strdup");
Jan Engelhardt648a7ba2009-09-18 13:01:05 +020081 dash = strchr(arg, '-');
82 if (dash == NULL) {
83 iprange_parse_spec(arg, arg, range, family, optname);
Jan Engelhardtce4b7952011-05-07 14:39:08 +020084 free(arg);
Jan Engelhardt648a7ba2009-09-18 13:01:05 +020085 return;
86 }
87
88 *dash = '\0';
89 iprange_parse_spec(arg, dash + 1, range, family, optname);
90 if (memcmp(&range[0], &range[1], sizeof(*range)) > 0)
91 fprintf(stderr, "xt_iprange: range %s-%s is reversed and "
92 "will never match\n", arg, dash + 1);
Jan Engelhardtce4b7952011-05-07 14:39:08 +020093 free(arg);
Jan Engelhardt648a7ba2009-09-18 13:01:05 +020094}
95
Jan Engelhardtce4b7952011-05-07 14:39:08 +020096static void iprange_parse(struct xt_option_call *cb)
Joszef Kadlecsik9cb66152003-04-23 13:27:09 +000097{
Jan Engelhardtce4b7952011-05-07 14:39:08 +020098 struct ipt_iprange_info *info = cb->data;
Jan Engelhardta10a12a2009-09-18 09:59:26 +020099 union nf_inet_addr range[2];
Joszef Kadlecsik9cb66152003-04-23 13:27:09 +0000100
Jan Engelhardtce4b7952011-05-07 14:39:08 +0200101 xtables_option_parse(cb);
102 switch (cb->entry->id) {
103 case O_SRC_RANGE:
Joszef Kadlecsik9cb66152003-04-23 13:27:09 +0000104 info->flags |= IPRANGE_SRC;
Jan Engelhardtce4b7952011-05-07 14:39:08 +0200105 if (cb->invert)
Joszef Kadlecsik9cb66152003-04-23 13:27:09 +0000106 info->flags |= IPRANGE_SRC_INV;
Jan Engelhardtce4b7952011-05-07 14:39:08 +0200107 iprange_parse_range(cb->arg, range, NFPROTO_IPV4, "--src-range");
Vincent Bernatada4ff62010-04-21 14:48:26 +0200108 info->src.min_ip = range[0].ip;
109 info->src.max_ip = range[1].ip;
Joszef Kadlecsik9cb66152003-04-23 13:27:09 +0000110 break;
Jan Engelhardtce4b7952011-05-07 14:39:08 +0200111 case O_DST_RANGE:
Joszef Kadlecsik9cb66152003-04-23 13:27:09 +0000112 info->flags |= IPRANGE_DST;
Jan Engelhardtce4b7952011-05-07 14:39:08 +0200113 if (cb->invert)
Joszef Kadlecsik9cb66152003-04-23 13:27:09 +0000114 info->flags |= IPRANGE_DST_INV;
Jan Engelhardtce4b7952011-05-07 14:39:08 +0200115 iprange_parse_range(cb->arg, range, NFPROTO_IPV4, "--dst-range");
Vincent Bernatada4ff62010-04-21 14:48:26 +0200116 info->dst.min_ip = range[0].ip;
117 info->dst.max_ip = range[1].ip;
Joszef Kadlecsik9cb66152003-04-23 13:27:09 +0000118 break;
Joszef Kadlecsik9cb66152003-04-23 13:27:09 +0000119 }
Joszef Kadlecsik9cb66152003-04-23 13:27:09 +0000120}
121
Jan Engelhardtce4b7952011-05-07 14:39:08 +0200122static void iprange_mt_parse(struct xt_option_call *cb, uint8_t nfproto)
Jan Engelhardtfc11b0b2008-01-20 13:43:49 +0000123{
Jan Engelhardtce4b7952011-05-07 14:39:08 +0200124 struct xt_iprange_mtinfo *info = cb->data;
Jan Engelhardtfc11b0b2008-01-20 13:43:49 +0000125
Jan Engelhardtce4b7952011-05-07 14:39:08 +0200126 xtables_option_parse(cb);
127 switch (cb->entry->id) {
128 case O_SRC_RANGE:
129 iprange_parse_range(cb->arg, &info->src_min, nfproto,
Jan Engelhardta10a12a2009-09-18 09:59:26 +0200130 "--src-range");
Jan Engelhardt6a0cd582008-06-13 17:59:29 +0200131 info->flags |= IPRANGE_SRC;
Jan Engelhardtce4b7952011-05-07 14:39:08 +0200132 if (cb->invert)
Jan Engelhardt6a0cd582008-06-13 17:59:29 +0200133 info->flags |= IPRANGE_SRC_INV;
Jan Engelhardtce4b7952011-05-07 14:39:08 +0200134 break;
135 case O_DST_RANGE:
136 iprange_parse_range(cb->arg, &info->dst_min, nfproto,
Jan Engelhardta10a12a2009-09-18 09:59:26 +0200137 "--dst-range");
Jan Engelhardt6a0cd582008-06-13 17:59:29 +0200138 info->flags |= IPRANGE_DST;
Jan Engelhardtce4b7952011-05-07 14:39:08 +0200139 if (cb->invert)
Jan Engelhardt6a0cd582008-06-13 17:59:29 +0200140 info->flags |= IPRANGE_DST_INV;
Jan Engelhardtce4b7952011-05-07 14:39:08 +0200141 break;
Jan Engelhardtfc11b0b2008-01-20 13:43:49 +0000142 }
Jan Engelhardtfc11b0b2008-01-20 13:43:49 +0000143}
144
Jan Engelhardtce4b7952011-05-07 14:39:08 +0200145static void iprange_mt4_parse(struct xt_option_call *cb)
Jan Engelhardtfc11b0b2008-01-20 13:43:49 +0000146{
Jan Engelhardtce4b7952011-05-07 14:39:08 +0200147 iprange_mt_parse(cb, NFPROTO_IPV4);
Jan Engelhardtfc11b0b2008-01-20 13:43:49 +0000148}
149
Jan Engelhardtce4b7952011-05-07 14:39:08 +0200150static void iprange_mt6_parse(struct xt_option_call *cb)
Joszef Kadlecsik9cb66152003-04-23 13:27:09 +0000151{
Jan Engelhardtce4b7952011-05-07 14:39:08 +0200152 iprange_mt_parse(cb, NFPROTO_IPV6);
153}
154
155static void iprange_mt_check(struct xt_fcheck_call *cb)
156{
157 if (cb->xflags == 0)
Jan Engelhardt1829ed42009-02-21 03:29:44 +0100158 xtables_error(PARAMETER_PROBLEM,
Joszef Kadlecsik9cb66152003-04-23 13:27:09 +0000159 "iprange match: You must specify `--src-range' or `--dst-range'");
160}
161
162static void
163print_iprange(const struct ipt_iprange *range)
164{
165 const unsigned char *byte_min, *byte_max;
166
Jan Engelhardt41daaa02008-01-20 13:42:43 +0000167 byte_min = (const unsigned char *)&range->min_ip;
168 byte_max = (const unsigned char *)&range->max_ip;
Jan Engelhardt73866352010-12-18 02:04:59 +0100169 printf(" %u.%u.%u.%u-%u.%u.%u.%u",
Joszef Kadlecsik9cb66152003-04-23 13:27:09 +0000170 byte_min[0], byte_min[1], byte_min[2], byte_min[3],
171 byte_max[0], byte_max[1], byte_max[2], byte_max[3]);
172}
173
Jan Engelhardt59d16402007-10-04 16:28:39 +0000174static void iprange_print(const void *ip, const struct xt_entry_match *match,
175 int numeric)
Joszef Kadlecsik9cb66152003-04-23 13:27:09 +0000176{
Jan Engelhardt41daaa02008-01-20 13:42:43 +0000177 const struct ipt_iprange_info *info = (const void *)match->data;
Joszef Kadlecsik9cb66152003-04-23 13:27:09 +0000178
179 if (info->flags & IPRANGE_SRC) {
Jan Engelhardt73866352010-12-18 02:04:59 +0100180 printf(" source IP range");
Joszef Kadlecsik9cb66152003-04-23 13:27:09 +0000181 if (info->flags & IPRANGE_SRC_INV)
Jan Engelhardt73866352010-12-18 02:04:59 +0100182 printf(" !");
Joszef Kadlecsik9cb66152003-04-23 13:27:09 +0000183 print_iprange(&info->src);
184 }
185 if (info->flags & IPRANGE_DST) {
Jan Engelhardt73866352010-12-18 02:04:59 +0100186 printf(" destination IP range");
Joszef Kadlecsik9cb66152003-04-23 13:27:09 +0000187 if (info->flags & IPRANGE_DST_INV)
Jan Engelhardt73866352010-12-18 02:04:59 +0100188 printf(" !");
Joszef Kadlecsik9cb66152003-04-23 13:27:09 +0000189 print_iprange(&info->dst);
190 }
191}
192
Jan Engelhardtfc11b0b2008-01-20 13:43:49 +0000193static void
194iprange_mt4_print(const void *ip, const struct xt_entry_match *match,
195 int numeric)
196{
197 const struct xt_iprange_mtinfo *info = (const void *)match->data;
198
199 if (info->flags & IPRANGE_SRC) {
Jan Engelhardt73866352010-12-18 02:04:59 +0100200 printf(" source IP range");
Jan Engelhardtfc11b0b2008-01-20 13:43:49 +0000201 if (info->flags & IPRANGE_SRC_INV)
Jan Engelhardt73866352010-12-18 02:04:59 +0100202 printf(" !");
Jan Engelhardtfc11b0b2008-01-20 13:43:49 +0000203 /*
204 * ipaddr_to_numeric() uses a static buffer, so cannot
205 * combine the printf() calls.
206 */
Jan Engelhardt73866352010-12-18 02:04:59 +0100207 printf(" %s", xtables_ipaddr_to_numeric(&info->src_min.in));
208 printf("-%s", xtables_ipaddr_to_numeric(&info->src_max.in));
Jan Engelhardtfc11b0b2008-01-20 13:43:49 +0000209 }
210 if (info->flags & IPRANGE_DST) {
Jan Engelhardt73866352010-12-18 02:04:59 +0100211 printf(" destination IP range");
Jan Engelhardtfc11b0b2008-01-20 13:43:49 +0000212 if (info->flags & IPRANGE_DST_INV)
Jan Engelhardt73866352010-12-18 02:04:59 +0100213 printf(" !");
214 printf(" %s", xtables_ipaddr_to_numeric(&info->dst_min.in));
215 printf("-%s", xtables_ipaddr_to_numeric(&info->dst_max.in));
Jan Engelhardtfc11b0b2008-01-20 13:43:49 +0000216 }
217}
218
219static void
220iprange_mt6_print(const void *ip, const struct xt_entry_match *match,
221 int numeric)
222{
223 const struct xt_iprange_mtinfo *info = (const void *)match->data;
224
225 if (info->flags & IPRANGE_SRC) {
Jan Engelhardt73866352010-12-18 02:04:59 +0100226 printf(" source IP range");
Jan Engelhardtfc11b0b2008-01-20 13:43:49 +0000227 if (info->flags & IPRANGE_SRC_INV)
Jan Engelhardt73866352010-12-18 02:04:59 +0100228 printf(" !");
Jan Engelhardtfc11b0b2008-01-20 13:43:49 +0000229 /*
230 * ipaddr_to_numeric() uses a static buffer, so cannot
231 * combine the printf() calls.
232 */
Jan Engelhardt73866352010-12-18 02:04:59 +0100233 printf(" %s", xtables_ip6addr_to_numeric(&info->src_min.in6));
234 printf("-%s", xtables_ip6addr_to_numeric(&info->src_max.in6));
Jan Engelhardtfc11b0b2008-01-20 13:43:49 +0000235 }
236 if (info->flags & IPRANGE_DST) {
Jan Engelhardt73866352010-12-18 02:04:59 +0100237 printf(" destination IP range");
Jan Engelhardtfc11b0b2008-01-20 13:43:49 +0000238 if (info->flags & IPRANGE_DST_INV)
Jan Engelhardt73866352010-12-18 02:04:59 +0100239 printf(" !");
240 printf(" %s", xtables_ip6addr_to_numeric(&info->dst_min.in6));
241 printf("-%s", xtables_ip6addr_to_numeric(&info->dst_max.in6));
Jan Engelhardtfc11b0b2008-01-20 13:43:49 +0000242 }
243}
244
Jan Engelhardt59d16402007-10-04 16:28:39 +0000245static void iprange_save(const void *ip, const struct xt_entry_match *match)
Joszef Kadlecsik9cb66152003-04-23 13:27:09 +0000246{
Jan Engelhardt41daaa02008-01-20 13:42:43 +0000247 const struct ipt_iprange_info *info = (const void *)match->data;
Joszef Kadlecsik9cb66152003-04-23 13:27:09 +0000248
249 if (info->flags & IPRANGE_SRC) {
250 if (info->flags & IPRANGE_SRC_INV)
Jan Engelhardt73866352010-12-18 02:04:59 +0100251 printf(" !");
252 printf(" --src-range");
Joszef Kadlecsik9cb66152003-04-23 13:27:09 +0000253 print_iprange(&info->src);
Joszef Kadlecsik9cb66152003-04-23 13:27:09 +0000254 }
255 if (info->flags & IPRANGE_DST) {
256 if (info->flags & IPRANGE_DST_INV)
Jan Engelhardt73866352010-12-18 02:04:59 +0100257 printf(" !");
258 printf(" --dst-range");
Joszef Kadlecsik9cb66152003-04-23 13:27:09 +0000259 print_iprange(&info->dst);
260 }
261}
262
Jan Engelhardtfc11b0b2008-01-20 13:43:49 +0000263static void iprange_mt4_save(const void *ip, const struct xt_entry_match *match)
264{
265 const struct xt_iprange_mtinfo *info = (const void *)match->data;
266
267 if (info->flags & IPRANGE_SRC) {
268 if (info->flags & IPRANGE_SRC_INV)
Jan Engelhardt73866352010-12-18 02:04:59 +0100269 printf(" !");
270 printf(" --src-range %s", xtables_ipaddr_to_numeric(&info->src_min.in));
271 printf("-%s", xtables_ipaddr_to_numeric(&info->src_max.in));
Jan Engelhardtfc11b0b2008-01-20 13:43:49 +0000272 }
273 if (info->flags & IPRANGE_DST) {
274 if (info->flags & IPRANGE_DST_INV)
Jan Engelhardt73866352010-12-18 02:04:59 +0100275 printf(" !");
276 printf(" --dst-range %s", xtables_ipaddr_to_numeric(&info->dst_min.in));
277 printf("-%s", xtables_ipaddr_to_numeric(&info->dst_max.in));
Jan Engelhardtfc11b0b2008-01-20 13:43:49 +0000278 }
279}
280
281static void iprange_mt6_save(const void *ip, const struct xt_entry_match *match)
282{
283 const struct xt_iprange_mtinfo *info = (const void *)match->data;
284
285 if (info->flags & IPRANGE_SRC) {
286 if (info->flags & IPRANGE_SRC_INV)
Jan Engelhardt73866352010-12-18 02:04:59 +0100287 printf(" !");
288 printf(" --src-range %s", xtables_ip6addr_to_numeric(&info->src_min.in6));
289 printf("-%s", xtables_ip6addr_to_numeric(&info->src_max.in6));
Jan Engelhardtfc11b0b2008-01-20 13:43:49 +0000290 }
291 if (info->flags & IPRANGE_DST) {
292 if (info->flags & IPRANGE_DST_INV)
Jan Engelhardt73866352010-12-18 02:04:59 +0100293 printf(" !");
294 printf(" --dst-range %s", xtables_ip6addr_to_numeric(&info->dst_min.in6));
295 printf("-%s", xtables_ip6addr_to_numeric(&info->dst_max.in6));
Jan Engelhardtfc11b0b2008-01-20 13:43:49 +0000296 }
297}
298
Jan Engelhardtf2a77522009-06-25 20:12:12 +0200299static struct xtables_match iprange_mt_reg[] = {
300 {
301 .version = XTABLES_VERSION,
302 .name = "iprange",
303 .revision = 0,
304 .family = NFPROTO_IPV4,
305 .size = XT_ALIGN(sizeof(struct ipt_iprange_info)),
306 .userspacesize = XT_ALIGN(sizeof(struct ipt_iprange_info)),
307 .help = iprange_mt_help,
Jan Engelhardtce4b7952011-05-07 14:39:08 +0200308 .x6_parse = iprange_parse,
309 .x6_fcheck = iprange_mt_check,
Jan Engelhardtf2a77522009-06-25 20:12:12 +0200310 .print = iprange_print,
311 .save = iprange_save,
Jan Engelhardtce4b7952011-05-07 14:39:08 +0200312 .x6_options = iprange_mt_opts,
Jan Engelhardtf2a77522009-06-25 20:12:12 +0200313 },
314 {
315 .version = XTABLES_VERSION,
316 .name = "iprange",
317 .revision = 1,
318 .family = NFPROTO_IPV4,
319 .size = XT_ALIGN(sizeof(struct xt_iprange_mtinfo)),
320 .userspacesize = XT_ALIGN(sizeof(struct xt_iprange_mtinfo)),
321 .help = iprange_mt_help,
Jan Engelhardtce4b7952011-05-07 14:39:08 +0200322 .x6_parse = iprange_mt4_parse,
323 .x6_fcheck = iprange_mt_check,
Jan Engelhardtf2a77522009-06-25 20:12:12 +0200324 .print = iprange_mt4_print,
325 .save = iprange_mt4_save,
Jan Engelhardtce4b7952011-05-07 14:39:08 +0200326 .x6_options = iprange_mt_opts,
Jan Engelhardtf2a77522009-06-25 20:12:12 +0200327 },
328 {
329 .version = XTABLES_VERSION,
330 .name = "iprange",
331 .revision = 1,
332 .family = NFPROTO_IPV6,
333 .size = XT_ALIGN(sizeof(struct xt_iprange_mtinfo)),
334 .userspacesize = XT_ALIGN(sizeof(struct xt_iprange_mtinfo)),
335 .help = iprange_mt_help,
Jan Engelhardtce4b7952011-05-07 14:39:08 +0200336 .x6_parse = iprange_mt6_parse,
337 .x6_fcheck = iprange_mt_check,
Jan Engelhardtf2a77522009-06-25 20:12:12 +0200338 .print = iprange_mt6_print,
339 .save = iprange_mt6_save,
Jan Engelhardtce4b7952011-05-07 14:39:08 +0200340 .x6_options = iprange_mt_opts,
Jan Engelhardtf2a77522009-06-25 20:12:12 +0200341 },
Jan Engelhardtfc11b0b2008-01-20 13:43:49 +0000342};
343
Joszef Kadlecsik9cb66152003-04-23 13:27:09 +0000344void _init(void)
345{
Jan Engelhardtf2a77522009-06-25 20:12:12 +0200346 xtables_register_matches(iprange_mt_reg, ARRAY_SIZE(iprange_mt_reg));
Joszef Kadlecsik9cb66152003-04-23 13:27:09 +0000347}