diff options
Diffstat (limited to 'extensions/libxt_cluster.c')
-rw-r--r-- | extensions/libxt_cluster.c | 238 |
1 files changed, 238 insertions, 0 deletions
diff --git a/extensions/libxt_cluster.c b/extensions/libxt_cluster.c new file mode 100644 index 00000000..1659a60e --- /dev/null +++ b/extensions/libxt_cluster.c @@ -0,0 +1,238 @@ +/* + * (C) 2009 by Pablo Neira Ayuso <pablo@netfilter.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <getopt.h> +#include <stddef.h> + +#include <xtables.h> +#include <linux/netfilter/x_tables.h> +#include <linux/netfilter/xt_cluster.h> + +/* hack to keep for check */ +static unsigned int total_nodes; +static unsigned int node_mask; + +static void +cluster_help(void) +{ + printf( +"cluster match options:\n" +" --cluster-total-nodes <num> Set number of total nodes in cluster\n" +" [!] --cluster-local-node <num> Set the local node number\n" +" [!] --cluster-local-nodemask <num> Set the local node mask\n" +" --cluster-hash-seed <num> Set seed value of the Jenkins hash\n"); +} + +enum { + CLUSTER_OPT_TOTAL_NODES, + CLUSTER_OPT_LOCAL_NODE, + CLUSTER_OPT_NODE_MASK, + CLUSTER_OPT_HASH_SEED, +}; + +static const struct option cluster_opts[] = { + { "cluster-total-nodes", 1, NULL, CLUSTER_OPT_TOTAL_NODES }, + { "cluster-local-node", 1, NULL, CLUSTER_OPT_LOCAL_NODE }, + { "cluster-local-nodemask", 1, NULL, CLUSTER_OPT_NODE_MASK }, + { "cluster-hash-seed", 1, NULL, CLUSTER_OPT_HASH_SEED }, + { .name = NULL } +}; + +static int +cluster_parse(int c, char **argv, int invert, unsigned int *flags, + const void *entry, struct xt_entry_match **match) +{ + struct xt_cluster_match_info *info = (void *)(*match)->data; + unsigned int num; + + switch (c) { + case CLUSTER_OPT_TOTAL_NODES: + if (*flags & (1 << c)) { + xtables_error(PARAMETER_PROBLEM, + "Can only specify " + "`--cluster-total-nodes' once"); + } + if (!xtables_strtoui(optarg, NULL, &num, 1, + XT_CLUSTER_NODES_MAX)) { + xtables_error(PARAMETER_PROBLEM, + "Unable to parse `%s' in " + "`--cluster-total-nodes'", optarg); + } + total_nodes = num; + info->total_nodes = total_nodes = num; + *flags |= 1 << c; + break; + case CLUSTER_OPT_LOCAL_NODE: + if (*flags & (1 << c)) { + xtables_error(PARAMETER_PROBLEM, + "Can only specify " + "`--cluster-local-node' once"); + } + if (*flags & (1 << CLUSTER_OPT_NODE_MASK)) { + xtables_error(PARAMETER_PROBLEM, "You cannot use " + "`--cluster-local-nodemask' and " + "`--cluster-local-node'"); + } + xtables_check_inverse(optarg, &invert, &optind, 0); + + if (!xtables_strtoui(optarg, NULL, &num, 1, + XT_CLUSTER_NODES_MAX)) { + xtables_error(PARAMETER_PROBLEM, + "Unable to parse `%s' in " + "`--cluster-local-node'", optarg); + } + if (invert) + info->flags |= (1 << XT_CLUSTER_F_INV); + + info->node_mask = node_mask = (1 << (num - 1)); + *flags |= 1 << c; + break; + case CLUSTER_OPT_NODE_MASK: + if (*flags & (1 << c)) { + xtables_error(PARAMETER_PROBLEM, + "Can only specify " + "`--cluster-local-node' once"); + } + if (*flags & (1 << CLUSTER_OPT_LOCAL_NODE)) { + xtables_error(PARAMETER_PROBLEM, "You cannot use " + "`--cluster-local-nodemask' and " + "`--cluster-local-node'"); + } + xtables_check_inverse(optarg, &invert, &optind, 0); + + if (!xtables_strtoui(optarg, NULL, &num, 1, + XT_CLUSTER_NODES_MAX)) { + xtables_error(PARAMETER_PROBLEM, + "Unable to parse `%s' in " + "`--cluster-local-node'", optarg); + } + if (invert) + info->flags |= (1 << XT_CLUSTER_F_INV); + + info->node_mask = node_mask = num; + *flags |= 1 << c; + break; + + case CLUSTER_OPT_HASH_SEED: + if (*flags & (1 << c)) { + xtables_error(PARAMETER_PROBLEM, + "Can only specify " + "`--cluster-hash-seed' once"); + } + if (!xtables_strtoui(optarg, NULL, &num, 0, UINT32_MAX)) { + xtables_error(PARAMETER_PROBLEM, + "Unable to parse `%s'", optarg); + } + info->hash_seed = num; + *flags |= 1 << c; + break; + default: + return 0; + } + + return 1; +} + +static void +cluster_check(unsigned int flags) +{ + if ((flags & ((1 << CLUSTER_OPT_TOTAL_NODES) | + (1 << CLUSTER_OPT_LOCAL_NODE) | + (1 << CLUSTER_OPT_HASH_SEED))) + == ((1 << CLUSTER_OPT_TOTAL_NODES) | + (1 << CLUSTER_OPT_LOCAL_NODE) | + (1 << CLUSTER_OPT_HASH_SEED))) { + if (node_mask >= (1ULL << total_nodes)) { + xtables_error(PARAMETER_PROBLEM, + "cluster match: " + "`--cluster-local-node' " + "must be <= `--cluster-total-nodes'"); + } + return; + } + if ((flags & ((1 << CLUSTER_OPT_TOTAL_NODES) | + (1 << CLUSTER_OPT_NODE_MASK) | + (1 << CLUSTER_OPT_HASH_SEED))) + == ((1 << CLUSTER_OPT_TOTAL_NODES) | + (1 << CLUSTER_OPT_NODE_MASK) | + (1 << CLUSTER_OPT_HASH_SEED))) { + if (node_mask >= (1ULL << total_nodes)) { + xtables_error(PARAMETER_PROBLEM, + "cluster match: " + "`--cluster-local-nodemask' too big " + "for `--cluster-total-nodes'"); + } + return; + } + if (!(flags & (1 << CLUSTER_OPT_TOTAL_NODES))) { + xtables_error(PARAMETER_PROBLEM, + "cluster match: `--cluster-total-nodes' " + "is missing"); + } + if (!(flags & (1 << CLUSTER_OPT_HASH_SEED))) { + xtables_error(PARAMETER_PROBLEM, + "cluster match: `--cluster-hash-seed' " + "is missing"); + } + if (!(flags & ((1 << (CLUSTER_OPT_LOCAL_NODE) | + (1 << (CLUSTER_OPT_NODE_MASK)))))) { + xtables_error(PARAMETER_PROBLEM, + "cluster match: `--cluster-local-node' or" + "`--cluster-local-nodemask' is missing"); + } +} + +static void +cluster_print(const void *ip, const struct xt_entry_match *match, int numeric) +{ + const struct xt_cluster_match_info *info = (void *)match->data; + + printf("cluster "); + if (info->flags & XT_CLUSTER_F_INV) + printf("!node_mask=0x%08x ", info->node_mask); + else + printf("node_mask=0x%08x ", info->node_mask); + + printf("total_nodes=%u hash_seed=0x%08x ", + info->total_nodes, info->hash_seed); +} + +static void +cluster_save(const void *ip, const struct xt_entry_match *match) +{ + const struct xt_cluster_match_info *info = (void *)match->data; + + if (info->flags & XT_CLUSTER_F_INV) + printf("! --cluster-local-nodemask 0x%08x ", info->node_mask); + else + printf("--cluster-local-nodemask 0x%08x ", info->node_mask); + + printf("--cluster-total-nodes %u --cluster-hash-seed 0x%08x ", + info->total_nodes, info->hash_seed); +} + +static struct xtables_match cluster_mt_reg = { + .family = AF_UNSPEC, + .name = "cluster", + .version = XTABLES_VERSION, + .size = XT_ALIGN(sizeof(struct xt_cluster_match_info)), + .userspacesize = XT_ALIGN(sizeof(struct xt_cluster_match_info)), + .help = cluster_help, + .parse = cluster_parse, + .final_check = cluster_check, + .print = cluster_print, + .save = cluster_save, + .extra_opts = cluster_opts, +}; + +void _init(void) +{ + xtables_register_match(&cluster_mt_reg); +} |