summaryrefslogtreecommitdiffstats
path: root/extensions/libxt_cluster.c
diff options
context:
space:
mode:
Diffstat (limited to 'extensions/libxt_cluster.c')
-rw-r--r--extensions/libxt_cluster.c238
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);
+}