1 /* Shared library add-on to iptables to add IP range matching support. */
9 #include <linux/netfilter.h>
10 #include <linux/netfilter/xt_iprange.h>
11 #include <linux/netfilter_ipv4/ipt_iprange.h>
18 static void iprange_mt_help(void)
21 "iprange match options:\n"
22 "[!] --src-range ip-ip Match source IP in the specified range\n"
23 "[!] --dst-range ip-ip Match destination IP in the specified range\n");
26 static const struct option iprange_mt_opts[] = {
27 {.name = "src-range", .has_arg = true, .val = '1'},
28 {.name = "dst-range", .has_arg = true, .val = '2'},
33 parse_iprange(char *arg, struct ipt_iprange *range)
36 const struct in_addr *ip;
38 dash = strchr(arg, '-');
42 ip = numeric_to_ipaddr(arg);
44 exit_error(PARAMETER_PROBLEM, "iprange match: Bad IP address `%s'\n",
46 range->min_ip = ip->s_addr;
49 ip = numeric_to_ipaddr(dash+1);
51 exit_error(PARAMETER_PROBLEM, "iprange match: Bad IP address `%s'\n",
53 range->max_ip = ip->s_addr;
55 range->max_ip = range->min_ip;
59 static int iprange_parse(int c, char **argv, int invert, unsigned int *flags,
60 const void *entry, struct xt_entry_match **match)
62 struct ipt_iprange_info *info = (struct ipt_iprange_info *)(*match)->data;
66 if (*flags & IPRANGE_SRC)
67 exit_error(PARAMETER_PROBLEM,
68 "iprange match: Only use --src-range ONCE!");
69 *flags |= IPRANGE_SRC;
71 info->flags |= IPRANGE_SRC;
72 check_inverse(optarg, &invert, &optind, 0);
74 info->flags |= IPRANGE_SRC_INV;
75 parse_iprange(optarg, &info->src);
80 if (*flags & IPRANGE_DST)
81 exit_error(PARAMETER_PROBLEM,
82 "iprange match: Only use --dst-range ONCE!");
83 *flags |= IPRANGE_DST;
85 info->flags |= IPRANGE_DST;
86 check_inverse(optarg, &invert, &optind, 0);
88 info->flags |= IPRANGE_DST_INV;
90 parse_iprange(optarg, &info->dst);
101 iprange_mt4_parse(int c, char **argv, int invert, unsigned int *flags,
102 const void *entry, struct xt_entry_match **match)
104 struct xt_iprange_mtinfo *info = (void *)(*match)->data;
105 const struct in_addr *ia;
109 case '1': /* --src-ip */
110 end = strchr(optarg, '-');
112 param_act(P_BAD_VALUE, "iprange", "--src-ip", optarg);
114 ia = numeric_to_ipaddr(optarg);
116 param_act(P_BAD_VALUE, "iprange", "--src-ip", optarg);
117 memcpy(&info->src_min.in, ia, sizeof(*ia));
118 ia = numeric_to_ipaddr(end+1);
120 param_act(P_BAD_VALUE, "iprange", "--src-ip", end + 1);
121 memcpy(&info->src_max.in, ia, sizeof(*ia));
122 info->flags |= IPRANGE_SRC;
124 info->flags |= IPRANGE_SRC_INV;
128 case '2': /* --dst-ip */
129 end = strchr(optarg, '-');
131 param_act(P_BAD_VALUE, "iprange", "--dst-ip", optarg);
133 ia = numeric_to_ipaddr(optarg);
135 param_act(P_BAD_VALUE, "iprange", "--dst-ip", optarg);
136 memcpy(&info->dst_min.in, ia, sizeof(*ia));
137 ia = numeric_to_ipaddr(end + 1);
139 param_act(P_BAD_VALUE, "iprange", "--dst-ip", end + 1);
140 memcpy(&info->dst_max.in, ia, sizeof(*ia));
141 info->flags |= IPRANGE_DST;
143 info->flags |= IPRANGE_DST_INV;
151 iprange_mt6_parse(int c, char **argv, int invert, unsigned int *flags,
152 const void *entry, struct xt_entry_match **match)
154 struct xt_iprange_mtinfo *info = (void *)(*match)->data;
155 const struct in6_addr *ia;
159 case '1': /* --src-ip */
160 end = strchr(optarg, '-');
162 param_act(P_BAD_VALUE, "iprange", "--src-ip", optarg);
164 ia = numeric_to_ip6addr(optarg);
166 param_act(P_BAD_VALUE, "iprange", "--src-ip", optarg);
167 memcpy(&info->src_min.in, ia, sizeof(*ia));
168 ia = numeric_to_ip6addr(end+1);
170 param_act(P_BAD_VALUE, "iprange", "--src-ip", end + 1);
171 memcpy(&info->src_max.in, ia, sizeof(*ia));
172 info->flags |= IPRANGE_SRC;
174 info->flags |= IPRANGE_SRC_INV;
178 case '2': /* --dst-ip */
179 end = strchr(optarg, '-');
181 param_act(P_BAD_VALUE, "iprange", "--dst-ip", optarg);
183 ia = numeric_to_ip6addr(optarg);
185 param_act(P_BAD_VALUE, "iprange", "--dst-ip", optarg);
186 memcpy(&info->dst_min.in, ia, sizeof(*ia));
187 ia = numeric_to_ip6addr(end + 1);
189 param_act(P_BAD_VALUE, "iprange", "--dst-ip", end + 1);
190 memcpy(&info->dst_max.in, ia, sizeof(*ia));
191 info->flags |= IPRANGE_DST;
193 info->flags |= IPRANGE_DST_INV;
200 static void iprange_mt_check(unsigned int flags)
203 exit_error(PARAMETER_PROBLEM,
204 "iprange match: You must specify `--src-range' or `--dst-range'");
208 print_iprange(const struct ipt_iprange *range)
210 const unsigned char *byte_min, *byte_max;
212 byte_min = (const unsigned char *)&range->min_ip;
213 byte_max = (const unsigned char *)&range->max_ip;
214 printf("%u.%u.%u.%u-%u.%u.%u.%u ",
215 byte_min[0], byte_min[1], byte_min[2], byte_min[3],
216 byte_max[0], byte_max[1], byte_max[2], byte_max[3]);
219 static void iprange_print(const void *ip, const struct xt_entry_match *match,
222 const struct ipt_iprange_info *info = (const void *)match->data;
224 if (info->flags & IPRANGE_SRC) {
225 printf("source IP range ");
226 if (info->flags & IPRANGE_SRC_INV)
228 print_iprange(&info->src);
230 if (info->flags & IPRANGE_DST) {
231 printf("destination IP range ");
232 if (info->flags & IPRANGE_DST_INV)
234 print_iprange(&info->dst);
239 iprange_mt4_print(const void *ip, const struct xt_entry_match *match,
242 const struct xt_iprange_mtinfo *info = (const void *)match->data;
244 if (info->flags & IPRANGE_SRC) {
245 printf("source IP range ");
246 if (info->flags & IPRANGE_SRC_INV)
249 * ipaddr_to_numeric() uses a static buffer, so cannot
250 * combine the printf() calls.
252 printf("%s", ipaddr_to_numeric(&info->src_min.in));
253 printf("-%s ", ipaddr_to_numeric(&info->src_max.in));
255 if (info->flags & IPRANGE_DST) {
256 printf("destination IP range ");
257 if (info->flags & IPRANGE_DST_INV)
259 printf("%s", ipaddr_to_numeric(&info->dst_min.in));
260 printf("-%s ", ipaddr_to_numeric(&info->dst_max.in));
265 iprange_mt6_print(const void *ip, const struct xt_entry_match *match,
268 const struct xt_iprange_mtinfo *info = (const void *)match->data;
270 if (info->flags & IPRANGE_SRC) {
271 printf("source IP range ");
272 if (info->flags & IPRANGE_SRC_INV)
275 * ipaddr_to_numeric() uses a static buffer, so cannot
276 * combine the printf() calls.
278 printf("%s", ip6addr_to_numeric(&info->src_min.in6));
279 printf("-%s ", ip6addr_to_numeric(&info->src_max.in6));
281 if (info->flags & IPRANGE_DST) {
282 printf("destination IP range ");
283 if (info->flags & IPRANGE_DST_INV)
285 printf("%s", ip6addr_to_numeric(&info->dst_min.in6));
286 printf("-%s ", ip6addr_to_numeric(&info->dst_max.in6));
290 static void iprange_save(const void *ip, const struct xt_entry_match *match)
292 const struct ipt_iprange_info *info = (const void *)match->data;
294 if (info->flags & IPRANGE_SRC) {
295 if (info->flags & IPRANGE_SRC_INV)
297 printf("--src-range ");
298 print_iprange(&info->src);
299 if (info->flags & IPRANGE_DST)
302 if (info->flags & IPRANGE_DST) {
303 if (info->flags & IPRANGE_DST_INV)
305 printf("--dst-range ");
306 print_iprange(&info->dst);
310 static void iprange_mt4_save(const void *ip, const struct xt_entry_match *match)
312 const struct xt_iprange_mtinfo *info = (const void *)match->data;
314 if (info->flags & IPRANGE_SRC) {
315 if (info->flags & IPRANGE_SRC_INV)
317 printf("--src-range %s", ipaddr_to_numeric(&info->src_min.in));
318 printf("-%s ", ipaddr_to_numeric(&info->src_max.in));
320 if (info->flags & IPRANGE_DST) {
321 if (info->flags & IPRANGE_DST_INV)
323 printf("--dst-range %s", ipaddr_to_numeric(&info->dst_min.in));
324 printf("-%s ", ipaddr_to_numeric(&info->dst_max.in));
328 static void iprange_mt6_save(const void *ip, const struct xt_entry_match *match)
330 const struct xt_iprange_mtinfo *info = (const void *)match->data;
332 if (info->flags & IPRANGE_SRC) {
333 if (info->flags & IPRANGE_SRC_INV)
335 printf("--src-range %s", ip6addr_to_numeric(&info->src_min.in6));
336 printf("-%s ", ip6addr_to_numeric(&info->src_max.in6));
338 if (info->flags & IPRANGE_DST) {
339 if (info->flags & IPRANGE_DST_INV)
341 printf("--dst-range %s", ip6addr_to_numeric(&info->dst_min.in6));
342 printf("-%s ", ip6addr_to_numeric(&info->dst_max.in6));
346 static struct xtables_match iprange_match = {
347 .version = XTABLES_VERSION,
351 .size = XT_ALIGN(sizeof(struct ipt_iprange_info)),
352 .userspacesize = XT_ALIGN(sizeof(struct ipt_iprange_info)),
353 .help = iprange_mt_help,
354 .parse = iprange_parse,
355 .final_check = iprange_mt_check,
356 .print = iprange_print,
357 .save = iprange_save,
358 .extra_opts = iprange_mt_opts,
361 static struct xtables_match iprange_mt_reg = {
362 .version = XTABLES_VERSION,
366 .size = XT_ALIGN(sizeof(struct xt_iprange_mtinfo)),
367 .userspacesize = XT_ALIGN(sizeof(struct xt_iprange_mtinfo)),
368 .help = iprange_mt_help,
369 .parse = iprange_mt4_parse,
370 .final_check = iprange_mt_check,
371 .print = iprange_mt4_print,
372 .save = iprange_mt4_save,
373 .extra_opts = iprange_mt_opts,
376 static struct xtables_match iprange_mt6_reg = {
377 .version = XTABLES_VERSION,
381 .size = XT_ALIGN(sizeof(struct xt_iprange_mtinfo)),
382 .userspacesize = XT_ALIGN(sizeof(struct xt_iprange_mtinfo)),
383 .help = iprange_mt_help,
384 .parse = iprange_mt6_parse,
385 .final_check = iprange_mt_check,
386 .print = iprange_mt6_print,
387 .save = iprange_mt6_save,
388 .extra_opts = iprange_mt_opts,
393 xtables_register_match(&iprange_match);
394 xtables_register_match(&iprange_mt_reg);
395 xtables_register_match(&iprange_mt6_reg);