123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347 |
- #include <stdint.h>
- #include <stdio.h>
- #include <string.h>
- #include <stdlib.h>
- #include <xtables.h>
- #include <linux/netfilter.h>
- #include <linux/netfilter/xt_iprange.h>
- struct ipt_iprange {
- /* Inclusive: network order. */
- __be32 min_ip, max_ip;
- };
- struct ipt_iprange_info {
- struct ipt_iprange src;
- struct ipt_iprange dst;
- /* Flags from above */
- uint8_t flags;
- };
- enum {
- O_SRC_RANGE = 0,
- O_DST_RANGE,
- };
- static void iprange_mt_help(void)
- {
- printf(
- "iprange match options:\n"
- "[!] --src-range ip[-ip] Match source IP in the specified range\n"
- "[!] --dst-range ip[-ip] Match destination IP in the specified range\n");
- }
- static const struct xt_option_entry iprange_mt_opts[] = {
- {.name = "src-range", .id = O_SRC_RANGE, .type = XTTYPE_STRING,
- .flags = XTOPT_INVERT},
- {.name = "dst-range", .id = O_DST_RANGE, .type = XTTYPE_STRING,
- .flags = XTOPT_INVERT},
- XTOPT_TABLEEND,
- };
- static void
- iprange_parse_spec(const char *from, const char *to, union nf_inet_addr *range,
- uint8_t family, const char *optname)
- {
- const char *spec[2] = {from, to};
- struct in6_addr *ia6;
- struct in_addr *ia4;
- unsigned int i;
- memset(range, 0, sizeof(union nf_inet_addr) * 2);
- if (family == NFPROTO_IPV6) {
- for (i = 0; i < ARRAY_SIZE(spec); ++i) {
- ia6 = xtables_numeric_to_ip6addr(spec[i]);
- if (ia6 == NULL)
- xtables_param_act(XTF_BAD_VALUE, "iprange",
- optname, spec[i]);
- range[i].in6 = *ia6;
- }
- } else {
- for (i = 0; i < ARRAY_SIZE(spec); ++i) {
- ia4 = xtables_numeric_to_ipaddr(spec[i]);
- if (ia4 == NULL)
- xtables_param_act(XTF_BAD_VALUE, "iprange",
- optname, spec[i]);
- range[i].in = *ia4;
- }
- }
- }
- static void iprange_parse_range(const char *oarg, union nf_inet_addr *range,
- uint8_t family, const char *optname)
- {
- char *arg = strdup(oarg);
- char *dash;
- if (arg == NULL)
- xtables_error(RESOURCE_PROBLEM, "strdup");
- dash = strchr(arg, '-');
- if (dash == NULL) {
- iprange_parse_spec(arg, arg, range, family, optname);
- free(arg);
- return;
- }
- *dash = '\0';
- iprange_parse_spec(arg, dash + 1, range, family, optname);
- if (memcmp(&range[0], &range[1], sizeof(*range)) > 0)
- fprintf(stderr, "xt_iprange: range %s-%s is reversed and "
- "will never match\n", arg, dash + 1);
- free(arg);
- }
- static void iprange_parse(struct xt_option_call *cb)
- {
- struct ipt_iprange_info *info = cb->data;
- union nf_inet_addr range[2];
- xtables_option_parse(cb);
- switch (cb->entry->id) {
- case O_SRC_RANGE:
- info->flags |= IPRANGE_SRC;
- if (cb->invert)
- info->flags |= IPRANGE_SRC_INV;
- iprange_parse_range(cb->arg, range, NFPROTO_IPV4, "--src-range");
- info->src.min_ip = range[0].ip;
- info->src.max_ip = range[1].ip;
- break;
- case O_DST_RANGE:
- info->flags |= IPRANGE_DST;
- if (cb->invert)
- info->flags |= IPRANGE_DST_INV;
- iprange_parse_range(cb->arg, range, NFPROTO_IPV4, "--dst-range");
- info->dst.min_ip = range[0].ip;
- info->dst.max_ip = range[1].ip;
- break;
- }
- }
- static void iprange_mt_parse(struct xt_option_call *cb, uint8_t nfproto)
- {
- struct xt_iprange_mtinfo *info = cb->data;
- xtables_option_parse(cb);
- switch (cb->entry->id) {
- case O_SRC_RANGE:
- iprange_parse_range(cb->arg, &info->src_min, nfproto,
- "--src-range");
- info->flags |= IPRANGE_SRC;
- if (cb->invert)
- info->flags |= IPRANGE_SRC_INV;
- break;
- case O_DST_RANGE:
- iprange_parse_range(cb->arg, &info->dst_min, nfproto,
- "--dst-range");
- info->flags |= IPRANGE_DST;
- if (cb->invert)
- info->flags |= IPRANGE_DST_INV;
- break;
- }
- }
- static void iprange_mt4_parse(struct xt_option_call *cb)
- {
- iprange_mt_parse(cb, NFPROTO_IPV4);
- }
- static void iprange_mt6_parse(struct xt_option_call *cb)
- {
- iprange_mt_parse(cb, NFPROTO_IPV6);
- }
- static void iprange_mt_check(struct xt_fcheck_call *cb)
- {
- if (cb->xflags == 0)
- xtables_error(PARAMETER_PROBLEM,
- "iprange match: You must specify `--src-range' or `--dst-range'");
- }
- static void
- print_iprange(const struct ipt_iprange *range)
- {
- const unsigned char *byte_min, *byte_max;
- byte_min = (const unsigned char *)&range->min_ip;
- byte_max = (const unsigned char *)&range->max_ip;
- printf(" %u.%u.%u.%u-%u.%u.%u.%u",
- byte_min[0], byte_min[1], byte_min[2], byte_min[3],
- byte_max[0], byte_max[1], byte_max[2], byte_max[3]);
- }
- static void iprange_print(const void *ip, const struct xt_entry_match *match,
- int numeric)
- {
- const struct ipt_iprange_info *info = (const void *)match->data;
- if (info->flags & IPRANGE_SRC) {
- printf(" source IP range");
- if (info->flags & IPRANGE_SRC_INV)
- printf(" !");
- print_iprange(&info->src);
- }
- if (info->flags & IPRANGE_DST) {
- printf(" destination IP range");
- if (info->flags & IPRANGE_DST_INV)
- printf(" !");
- print_iprange(&info->dst);
- }
- }
- static void
- iprange_mt4_print(const void *ip, const struct xt_entry_match *match,
- int numeric)
- {
- const struct xt_iprange_mtinfo *info = (const void *)match->data;
- if (info->flags & IPRANGE_SRC) {
- printf(" source IP range");
- if (info->flags & IPRANGE_SRC_INV)
- printf(" !");
- /*
- * ipaddr_to_numeric() uses a static buffer, so cannot
- * combine the printf() calls.
- */
- printf(" %s", xtables_ipaddr_to_numeric(&info->src_min.in));
- printf("-%s", xtables_ipaddr_to_numeric(&info->src_max.in));
- }
- if (info->flags & IPRANGE_DST) {
- printf(" destination IP range");
- if (info->flags & IPRANGE_DST_INV)
- printf(" !");
- printf(" %s", xtables_ipaddr_to_numeric(&info->dst_min.in));
- printf("-%s", xtables_ipaddr_to_numeric(&info->dst_max.in));
- }
- }
- static void
- iprange_mt6_print(const void *ip, const struct xt_entry_match *match,
- int numeric)
- {
- const struct xt_iprange_mtinfo *info = (const void *)match->data;
- if (info->flags & IPRANGE_SRC) {
- printf(" source IP range");
- if (info->flags & IPRANGE_SRC_INV)
- printf(" !");
- /*
- * ipaddr_to_numeric() uses a static buffer, so cannot
- * combine the printf() calls.
- */
- printf(" %s", xtables_ip6addr_to_numeric(&info->src_min.in6));
- printf("-%s", xtables_ip6addr_to_numeric(&info->src_max.in6));
- }
- if (info->flags & IPRANGE_DST) {
- printf(" destination IP range");
- if (info->flags & IPRANGE_DST_INV)
- printf(" !");
- printf(" %s", xtables_ip6addr_to_numeric(&info->dst_min.in6));
- printf("-%s", xtables_ip6addr_to_numeric(&info->dst_max.in6));
- }
- }
- static void iprange_save(const void *ip, const struct xt_entry_match *match)
- {
- const struct ipt_iprange_info *info = (const void *)match->data;
- if (info->flags & IPRANGE_SRC) {
- if (info->flags & IPRANGE_SRC_INV)
- printf(" !");
- printf(" --src-range");
- print_iprange(&info->src);
- }
- if (info->flags & IPRANGE_DST) {
- if (info->flags & IPRANGE_DST_INV)
- printf(" !");
- printf(" --dst-range");
- print_iprange(&info->dst);
- }
- }
- static void iprange_mt4_save(const void *ip, const struct xt_entry_match *match)
- {
- const struct xt_iprange_mtinfo *info = (const void *)match->data;
- if (info->flags & IPRANGE_SRC) {
- if (info->flags & IPRANGE_SRC_INV)
- printf(" !");
- printf(" --src-range %s", xtables_ipaddr_to_numeric(&info->src_min.in));
- printf("-%s", xtables_ipaddr_to_numeric(&info->src_max.in));
- }
- if (info->flags & IPRANGE_DST) {
- if (info->flags & IPRANGE_DST_INV)
- printf(" !");
- printf(" --dst-range %s", xtables_ipaddr_to_numeric(&info->dst_min.in));
- printf("-%s", xtables_ipaddr_to_numeric(&info->dst_max.in));
- }
- }
- static void iprange_mt6_save(const void *ip, const struct xt_entry_match *match)
- {
- const struct xt_iprange_mtinfo *info = (const void *)match->data;
- if (info->flags & IPRANGE_SRC) {
- if (info->flags & IPRANGE_SRC_INV)
- printf(" !");
- printf(" --src-range %s", xtables_ip6addr_to_numeric(&info->src_min.in6));
- printf("-%s", xtables_ip6addr_to_numeric(&info->src_max.in6));
- }
- if (info->flags & IPRANGE_DST) {
- if (info->flags & IPRANGE_DST_INV)
- printf(" !");
- printf(" --dst-range %s", xtables_ip6addr_to_numeric(&info->dst_min.in6));
- printf("-%s", xtables_ip6addr_to_numeric(&info->dst_max.in6));
- }
- }
- static struct xtables_match iprange_mt_reg[] = {
- {
- .version = XTABLES_VERSION,
- .name = "iprange",
- .revision = 0,
- .family = NFPROTO_IPV4,
- .size = XT_ALIGN(sizeof(struct ipt_iprange_info)),
- .userspacesize = XT_ALIGN(sizeof(struct ipt_iprange_info)),
- .help = iprange_mt_help,
- .x6_parse = iprange_parse,
- .x6_fcheck = iprange_mt_check,
- .print = iprange_print,
- .save = iprange_save,
- .x6_options = iprange_mt_opts,
- },
- {
- .version = XTABLES_VERSION,
- .name = "iprange",
- .revision = 1,
- .family = NFPROTO_IPV4,
- .size = XT_ALIGN(sizeof(struct xt_iprange_mtinfo)),
- .userspacesize = XT_ALIGN(sizeof(struct xt_iprange_mtinfo)),
- .help = iprange_mt_help,
- .x6_parse = iprange_mt4_parse,
- .x6_fcheck = iprange_mt_check,
- .print = iprange_mt4_print,
- .save = iprange_mt4_save,
- .x6_options = iprange_mt_opts,
- },
- {
- .version = XTABLES_VERSION,
- .name = "iprange",
- .revision = 1,
- .family = NFPROTO_IPV6,
- .size = XT_ALIGN(sizeof(struct xt_iprange_mtinfo)),
- .userspacesize = XT_ALIGN(sizeof(struct xt_iprange_mtinfo)),
- .help = iprange_mt_help,
- .x6_parse = iprange_mt6_parse,
- .x6_fcheck = iprange_mt_check,
- .print = iprange_mt6_print,
- .save = iprange_mt6_save,
- .x6_options = iprange_mt_opts,
- },
- };
- void _init(void)
- {
- xtables_register_matches(iprange_mt_reg, ARRAY_SIZE(iprange_mt_reg));
- }
|