diff options
Diffstat (limited to 'extensions/libxt_connbytes.c')
-rw-r--r-- | extensions/libxt_connbytes.c | 172 |
1 files changed, 74 insertions, 98 deletions
diff --git a/extensions/libxt_connbytes.c b/extensions/libxt_connbytes.c index 5ebdd34..ed2ad25 100644 --- a/extensions/libxt_connbytes.c +++ b/extensions/libxt_connbytes.c @@ -1,13 +1,14 @@ -/* Shared library add-on to iptables to add byte tracking support. */ #include <stdio.h> -#include <netdb.h> #include <string.h> -#include <stdlib.h> -#include <getopt.h> #include <xtables.h> -#include <linux/netfilter/nf_conntrack_common.h> #include <linux/netfilter/xt_connbytes.h> +enum { + O_CONNBYTES = 0, + O_CONNBYTES_DIR, + O_CONNBYTES_MODE, +}; + static void connbytes_help(void) { printf( @@ -17,105 +18,78 @@ static void connbytes_help(void) " --connbytes-mode [packets, bytes, avgpkt]\n"); } -static const struct option connbytes_opts[] = { - { "connbytes", 1, NULL, '1' }, - { "connbytes-dir", 1, NULL, '2' }, - { "connbytes-mode", 1, NULL, '3' }, - { .name = NULL } +static const struct xt_option_entry connbytes_opts[] = { + {.name = "connbytes", .id = O_CONNBYTES, .type = XTTYPE_UINT64RC, + .flags = XTOPT_MAND | XTOPT_INVERT}, + {.name = "connbytes-dir", .id = O_CONNBYTES_DIR, .type = XTTYPE_STRING, + .flags = XTOPT_MAND}, + {.name = "connbytes-mode", .id = O_CONNBYTES_MODE, + .type = XTTYPE_STRING, .flags = XTOPT_MAND}, + XTOPT_TABLEEND, }; -static void -parse_range(const char *arg, struct xt_connbytes_info *si) +static void connbytes_parse(struct xt_option_call *cb) { - char *colon,*p; - - si->count.from = strtoul(arg,&colon,10); - if (*colon != ':') - xtables_error(PARAMETER_PROBLEM, "Bad range \"%s\"", arg); - si->count.to = strtoul(colon+1,&p,10); - if (p == colon+1) { - /* second number omited */ - si->count.to = 0xffffffff; - } - if (si->count.from > si->count.to) - xtables_error(PARAMETER_PROBLEM, "%llu should be less than %llu", - (unsigned long long)si->count.from, - (unsigned long long)si->count.to); -} - -static int -connbytes_parse(int c, char **argv, int invert, unsigned int *flags, - const void *entry, struct xt_entry_match **match) -{ - struct xt_connbytes_info *sinfo = (struct xt_connbytes_info *)(*match)->data; - unsigned long i; - - switch (c) { - case '1': - if (xtables_check_inverse(optarg, &invert, &optind, 0, argv)) - optind++; - - parse_range(optarg, sinfo); - if (invert) { + struct xt_connbytes_info *sinfo = cb->data; + unsigned long long i; + + xtables_option_parse(cb); + switch (cb->entry->id) { + case O_CONNBYTES: + sinfo->count.from = cb->val.u64_range[0]; + sinfo->count.to = UINT64_MAX; + if (cb->nvals == 2) + sinfo->count.to = cb->val.u64_range[1]; + + if (sinfo->count.to < sinfo->count.from) + xtables_error(PARAMETER_PROBLEM, "%llu should be less than %llu", + (unsigned long long)sinfo->count.from, + (unsigned long long)sinfo->count.to); + if (cb->invert) { i = sinfo->count.from; sinfo->count.from = sinfo->count.to; sinfo->count.to = i; } - *flags |= 1; break; - case '2': - if (!strcmp(optarg, "original")) + case O_CONNBYTES_DIR: + if (strcmp(cb->arg, "original") == 0) sinfo->direction = XT_CONNBYTES_DIR_ORIGINAL; - else if (!strcmp(optarg, "reply")) + else if (strcmp(cb->arg, "reply") == 0) sinfo->direction = XT_CONNBYTES_DIR_REPLY; - else if (!strcmp(optarg, "both")) + else if (strcmp(cb->arg, "both") == 0) sinfo->direction = XT_CONNBYTES_DIR_BOTH; else xtables_error(PARAMETER_PROBLEM, - "Unknown --connbytes-dir `%s'", optarg); - - *flags |= 2; + "Unknown --connbytes-dir `%s'", cb->arg); break; - case '3': - if (!strcmp(optarg, "packets")) + case O_CONNBYTES_MODE: + if (strcmp(cb->arg, "packets") == 0) sinfo->what = XT_CONNBYTES_PKTS; - else if (!strcmp(optarg, "bytes")) + else if (strcmp(cb->arg, "bytes") == 0) sinfo->what = XT_CONNBYTES_BYTES; - else if (!strcmp(optarg, "avgpkt")) + else if (strcmp(cb->arg, "avgpkt") == 0) sinfo->what = XT_CONNBYTES_AVGPKT; else xtables_error(PARAMETER_PROBLEM, - "Unknown --connbytes-mode `%s'", optarg); - *flags |= 4; + "Unknown --connbytes-mode `%s'", cb->arg); break; - default: - return 0; } - - return 1; -} - -static void connbytes_check(unsigned int flags) -{ - if (flags != 7) - xtables_error(PARAMETER_PROBLEM, "You must specify `--connbytes'" - "`--connbytes-dir' and `--connbytes-mode'"); } static void print_mode(const struct xt_connbytes_info *sinfo) { switch (sinfo->what) { case XT_CONNBYTES_PKTS: - fputs("packets ", stdout); + fputs(" packets", stdout); break; case XT_CONNBYTES_BYTES: - fputs("bytes ", stdout); + fputs(" bytes", stdout); break; case XT_CONNBYTES_AVGPKT: - fputs("avgpkt ", stdout); + fputs(" avgpkt", stdout); break; default: - fputs("unknown ", stdout); + fputs(" unknown", stdout); break; } } @@ -124,38 +98,48 @@ static void print_direction(const struct xt_connbytes_info *sinfo) { switch (sinfo->direction) { case XT_CONNBYTES_DIR_ORIGINAL: - fputs("original ", stdout); + fputs(" original", stdout); break; case XT_CONNBYTES_DIR_REPLY: - fputs("reply ", stdout); + fputs(" reply", stdout); break; case XT_CONNBYTES_DIR_BOTH: - fputs("both ", stdout); + fputs(" both", stdout); break; default: - fputs("unknown ", stdout); + fputs(" unknown", stdout); break; } } +static void print_from_to(const struct xt_connbytes_info *sinfo, const char *prefix) +{ + unsigned long long from, to; + + if (sinfo->count.from > sinfo->count.to) { + fputs(" !", stdout); + from = sinfo->count.to; + to = sinfo->count.from; + } else { + to = sinfo->count.to; + from = sinfo->count.from; + } + printf(" %sconnbytes %llu", prefix, from); + if (to && to < UINT64_MAX) + printf(":%llu", to); +} + static void connbytes_print(const void *ip, const struct xt_entry_match *match, int numeric) { const struct xt_connbytes_info *sinfo = (const void *)match->data; - if (sinfo->count.from > sinfo->count.to) - printf("connbytes ! %llu:%llu ", - (unsigned long long)sinfo->count.to, - (unsigned long long)sinfo->count.from); - else - printf("connbytes %llu:%llu ", - (unsigned long long)sinfo->count.from, - (unsigned long long)sinfo->count.to); + print_from_to(sinfo, ""); - fputs("connbytes mode ", stdout); + fputs(" connbytes mode", stdout); print_mode(sinfo); - fputs("connbytes direction ", stdout); + fputs(" connbytes direction", stdout); print_direction(sinfo); } @@ -163,19 +147,12 @@ static void connbytes_save(const void *ip, const struct xt_entry_match *match) { const struct xt_connbytes_info *sinfo = (const void *)match->data; - if (sinfo->count.from > sinfo->count.to) - printf("! --connbytes %llu:%llu ", - (unsigned long long)sinfo->count.to, - (unsigned long long)sinfo->count.from); - else - printf("--connbytes %llu:%llu ", - (unsigned long long)sinfo->count.from, - (unsigned long long)sinfo->count.to); + print_from_to(sinfo, "--"); - fputs("--connbytes-mode ", stdout); + fputs(" --connbytes-mode", stdout); print_mode(sinfo); - fputs("--connbytes-dir ", stdout); + fputs(" --connbytes-dir", stdout); print_direction(sinfo); } @@ -186,11 +163,10 @@ static struct xtables_match connbytes_match = { .size = XT_ALIGN(sizeof(struct xt_connbytes_info)), .userspacesize = XT_ALIGN(sizeof(struct xt_connbytes_info)), .help = connbytes_help, - .parse = connbytes_parse, - .final_check = connbytes_check, .print = connbytes_print, .save = connbytes_save, - .extra_opts = connbytes_opts, + .x6_parse = connbytes_parse, + .x6_options = connbytes_opts, }; void _init(void) |