netfilter-devel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Pablo Neira Ayuso <pablo@netfilter.org>
To: netfilter-devel@vger.kernel.org
Cc: kaber@trash.net
Subject: [PATCH] iptables: cluster match support
Date: Wed, 28 Jan 2009 16:05:26 +0100	[thread overview]
Message-ID: <20090128150526.7973.92287.stgit@Decadence> (raw)

This patch adds support for the cluster match to iptables.

Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---

 extensions/libxt_cluster.c           |  200 ++++++++++++++++++++++++++++++++++
 include/linux/netfilter/xt_cluster.h |   21 ++++
 2 files changed, 221 insertions(+), 0 deletions(-)
 create mode 100644 extensions/libxt_cluster.c
 create mode 100644 include/linux/netfilter/xt_cluster.h

diff --git a/extensions/libxt_cluster.c b/extensions/libxt_cluster.c
new file mode 100644
index 0000000..1f82ac3
--- /dev/null
+++ b/extensions/libxt_cluster.c
@@ -0,0 +1,200 @@
+/*
+ * (C) 2008 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>
+
+/* maximum 16 nodes */
+#define CLUSTER_MAX_NODES	16
+
+/* hack to keep for check */
+static int total_nodes;
+static int local_node;
+
+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-hash-seed <num>		Set seed value of the Jenkins hash\n"
+"  --cluster-proc-name <string>		Proc interface name\n");
+}
+
+enum {
+	CLUSTER_OPT_DEVICE,
+	CLUSTER_OPT_TOTAL_NODES,
+	CLUSTER_OPT_LOCAL_NODE,
+	CLUSTER_OPT_HASH_SEED,
+	CLUSTER_OPT_PROC_NAME,
+};
+
+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-hash-seed",		1, NULL, CLUSTER_OPT_HASH_SEED },
+	{ "cluster-proc-name",		1, NULL, CLUSTER_OPT_PROC_NAME },
+	{ .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))
+			exit_error(PARAMETER_PROBLEM,
+				   "Can only specify "
+				   "`--cluster-total-nodes' once");
+
+		if (string_to_number(optarg, 1, CLUSTER_MAX_NODES, &num) < 0)
+			exit_error(PARAMETER_PROBLEM, 
+				    "Unable to parse `%s' in "
+				    "`--cluster-total-nodes'", optarg);
+
+		total_nodes = num;
+		info->total_nodes = (u_int16_t)num;
+		*flags |= 1 << c;
+		break;
+	case CLUSTER_OPT_LOCAL_NODE:
+		if (*flags & (1 << c))
+			exit_error(PARAMETER_PROBLEM,
+				   "Can only specify "
+				   "`--cluster-local-node' once");
+
+		check_inverse(optarg, &invert, &optind, 0);
+
+		if (string_to_number(optarg, 1, CLUSTER_MAX_NODES, &num) < 0)
+			exit_error(PARAMETER_PROBLEM,
+				   "Unable to parse `%s' in "
+				   "`--cluster-local-node'", optarg);
+
+		if (invert)
+			info->flags |= (1 << XT_CLUSTER_F_INV);
+
+		info->node_id = (u_int16_t)num;
+		*flags |= 1 << c;
+		break;
+	case CLUSTER_OPT_HASH_SEED:
+		if (*flags & (1 << c))
+			exit_error(PARAMETER_PROBLEM,
+				   "Can only specify "
+				   "`--cluster-hash-seed' once");
+
+		if (string_to_number(optarg, 0, UINT_MAX, &num) < 0)
+			exit_error(PARAMETER_PROBLEM,
+				   "Unable to parse `%s'", optarg);
+
+		info->hash_seed = num;
+		*flags |= 1 << c;
+		break;
+	case CLUSTER_OPT_PROC_NAME:
+		if (*flags & (1 << c))
+			exit_error(PARAMETER_PROBLEM,
+				   "Can only specify "
+				   "`--cluster-proc-name' once");
+
+		if (strlen(optarg) > sizeof(info->proc_name))
+			exit_error(PARAMETER_PROBLEM,
+				   "--cluster-proc-name string too long");
+
+		strncpy(info->proc_name, optarg, sizeof(info->proc_name));
+		info->proc_name[sizeof(info->proc_name)-1] = '\0';
+		*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_PROC_NAME)))
+		== ((1 << CLUSTER_OPT_TOTAL_NODES) |
+		    (1 << CLUSTER_OPT_LOCAL_NODE) |
+		    (1 << CLUSTER_OPT_PROC_NAME))) {
+		if (local_node > total_nodes)
+			exit_error(PARAMETER_PROBLEM,
+				   "cluster match: `--cluster-local-node' "
+				   "must be <= `--cluster-total-nodes'");
+		return;
+	}
+
+	exit_error(PARAMETER_PROBLEM,
+		   "cluster match: Invalid parameter combination");
+}
+
+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_id=%u ", info->node_id);
+	else
+		printf("node_id=%u ", info->node_id);
+
+	printf("total_nodes=%u hash_seed=%u proc=%s ", 
+		info->total_nodes,
+		info->hash_seed,
+		info->proc_name);
+}
+
+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-this-node %u ", info->node_id);
+	else
+		printf("--cluster-this-node %u ", info->node_id);
+
+	printf("--cluster-total-nodes %u "
+	       "--cluster-hash-seed %u "
+	       "--cluster-proc-entry %s ",
+		info->total_nodes,
+		info->hash_seed,
+		info->proc_name);
+}
+
+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(offsetof(struct xt_cluster_match_info,data)),
+ 	.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);
+}
diff --git a/include/linux/netfilter/xt_cluster.h b/include/linux/netfilter/xt_cluster.h
new file mode 100644
index 0000000..85ab07f
--- /dev/null
+++ b/include/linux/netfilter/xt_cluster.h
@@ -0,0 +1,21 @@
+#ifndef _XT_CLUSTER_MATCH_H
+#define _XT_CLUSTER_MATCH_H
+
+struct proc_dir_entry;
+
+enum xt_cluster_flags {
+	XT_CLUSTER_F_INV = 0,
+};
+
+struct xt_cluster_match_info {
+	u_int16_t		total_nodes;
+	u_int16_t		node_id;
+	u_int32_t		hash_seed;
+	char			proc_name[16];
+	unsigned int		flags;
+
+	/* Used internally by the kernel */
+	void			*data __attribute__((aligned(8)));
+};
+
+#endif /* _XT_CLUSTER_MATCH_H */


                 reply	other threads:[~2009-01-28 15:05 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20090128150526.7973.92287.stgit@Decadence \
    --to=pablo@netfilter.org \
    --cc=kaber@trash.net \
    --cc=netfilter-devel@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).