1cd958a6c92c84095a439780b53832bb3aae2d512Pablo Neira Ayuso/*
2cd958a6c92c84095a439780b53832bb3aae2d512Pablo Neira Ayuso * (C) 2009 by Pablo Neira Ayuso <pablo@netfilter.org>
3cd958a6c92c84095a439780b53832bb3aae2d512Pablo Neira Ayuso *
4cd958a6c92c84095a439780b53832bb3aae2d512Pablo Neira Ayuso * This program is free software; you can redistribute it and/or modify
5cd958a6c92c84095a439780b53832bb3aae2d512Pablo Neira Ayuso * it under the terms of the GNU General Public License version 2 as
6cd958a6c92c84095a439780b53832bb3aae2d512Pablo Neira Ayuso * published by the Free Software Foundation.
7cd958a6c92c84095a439780b53832bb3aae2d512Pablo Neira Ayuso */
8cd958a6c92c84095a439780b53832bb3aae2d512Pablo Neira Ayuso#include <stdio.h>
9cd958a6c92c84095a439780b53832bb3aae2d512Pablo Neira Ayuso#include <xtables.h>
10cd958a6c92c84095a439780b53832bb3aae2d512Pablo Neira Ayuso#include <linux/netfilter/xt_cluster.h>
11cd958a6c92c84095a439780b53832bb3aae2d512Pablo Neira Ayuso
12cd958a6c92c84095a439780b53832bb3aae2d512Pablo Neira Ayusostatic void
13cd958a6c92c84095a439780b53832bb3aae2d512Pablo Neira Ayusocluster_help(void)
14cd958a6c92c84095a439780b53832bb3aae2d512Pablo Neira Ayuso{
15cd958a6c92c84095a439780b53832bb3aae2d512Pablo Neira Ayuso	printf(
16cd958a6c92c84095a439780b53832bb3aae2d512Pablo Neira Ayuso"cluster match options:\n"
17cd958a6c92c84095a439780b53832bb3aae2d512Pablo Neira Ayuso"  --cluster-total-nodes <num>		Set number of total nodes in cluster\n"
18cd958a6c92c84095a439780b53832bb3aae2d512Pablo Neira Ayuso"  [!] --cluster-local-node <num>	Set the local node number\n"
19cd958a6c92c84095a439780b53832bb3aae2d512Pablo Neira Ayuso"  [!] --cluster-local-nodemask <num>	Set the local node mask\n"
20cd958a6c92c84095a439780b53832bb3aae2d512Pablo Neira Ayuso"  --cluster-hash-seed <num>		Set seed value of the Jenkins hash\n");
21cd958a6c92c84095a439780b53832bb3aae2d512Pablo Neira Ayuso}
22cd958a6c92c84095a439780b53832bb3aae2d512Pablo Neira Ayuso
23cd958a6c92c84095a439780b53832bb3aae2d512Pablo Neira Ayusoenum {
24b18ffe3636b07cd817628de81643136e4755a944Jan Engelhardt	O_CL_TOTAL_NODES = 0,
25b18ffe3636b07cd817628de81643136e4755a944Jan Engelhardt	O_CL_LOCAL_NODE,
26b18ffe3636b07cd817628de81643136e4755a944Jan Engelhardt	O_CL_LOCAL_NODEMASK,
27b18ffe3636b07cd817628de81643136e4755a944Jan Engelhardt	O_CL_HASH_SEED,
28b18ffe3636b07cd817628de81643136e4755a944Jan Engelhardt	F_CL_TOTAL_NODES    = 1 << O_CL_TOTAL_NODES,
29b18ffe3636b07cd817628de81643136e4755a944Jan Engelhardt	F_CL_LOCAL_NODE     = 1 << O_CL_LOCAL_NODE,
30b18ffe3636b07cd817628de81643136e4755a944Jan Engelhardt	F_CL_LOCAL_NODEMASK = 1 << O_CL_LOCAL_NODEMASK,
31b18ffe3636b07cd817628de81643136e4755a944Jan Engelhardt	F_CL_HASH_SEED      = 1 << O_CL_HASH_SEED,
32cd958a6c92c84095a439780b53832bb3aae2d512Pablo Neira Ayuso};
33cd958a6c92c84095a439780b53832bb3aae2d512Pablo Neira Ayuso
34b18ffe3636b07cd817628de81643136e4755a944Jan Engelhardt#define s struct xt_cluster_match_info
35b18ffe3636b07cd817628de81643136e4755a944Jan Engelhardtstatic const struct xt_option_entry cluster_opts[] = {
36b18ffe3636b07cd817628de81643136e4755a944Jan Engelhardt	{.name = "cluster-total-nodes", .id = O_CL_TOTAL_NODES,
37b18ffe3636b07cd817628de81643136e4755a944Jan Engelhardt	 .type = XTTYPE_UINT32, .min = 1, .max = XT_CLUSTER_NODES_MAX,
38b18ffe3636b07cd817628de81643136e4755a944Jan Engelhardt	 .flags = XTOPT_MAND | XTOPT_PUT, XTOPT_POINTER(s, total_nodes)},
39b18ffe3636b07cd817628de81643136e4755a944Jan Engelhardt	{.name = "cluster-local-node", .id = O_CL_LOCAL_NODE,
40b18ffe3636b07cd817628de81643136e4755a944Jan Engelhardt	 .excl = F_CL_LOCAL_NODEMASK, .flags = XTOPT_INVERT,
41b18ffe3636b07cd817628de81643136e4755a944Jan Engelhardt	 .type = XTTYPE_UINT32, .min = 1, .max = XT_CLUSTER_NODES_MAX},
42b18ffe3636b07cd817628de81643136e4755a944Jan Engelhardt	{.name = "cluster-local-nodemask", .id = O_CL_LOCAL_NODEMASK,
43b18ffe3636b07cd817628de81643136e4755a944Jan Engelhardt	 .excl = F_CL_LOCAL_NODE, .type = XTTYPE_UINT32,
44b18ffe3636b07cd817628de81643136e4755a944Jan Engelhardt	 .min = 1, .max = XT_CLUSTER_NODES_MAX,
45b18ffe3636b07cd817628de81643136e4755a944Jan Engelhardt	 .flags = XTOPT_INVERT | XTOPT_PUT, XTOPT_POINTER(s, node_mask)},
46b18ffe3636b07cd817628de81643136e4755a944Jan Engelhardt	{.name = "cluster-hash-seed", .id = O_CL_HASH_SEED,
47b18ffe3636b07cd817628de81643136e4755a944Jan Engelhardt	 .type = XTTYPE_UINT32, .flags = XTOPT_MAND | XTOPT_PUT,
48b18ffe3636b07cd817628de81643136e4755a944Jan Engelhardt	 XTOPT_POINTER(s, hash_seed)},
49b18ffe3636b07cd817628de81643136e4755a944Jan Engelhardt	XTOPT_TABLEEND,
50cd958a6c92c84095a439780b53832bb3aae2d512Pablo Neira Ayuso};
51cd958a6c92c84095a439780b53832bb3aae2d512Pablo Neira Ayuso
52b18ffe3636b07cd817628de81643136e4755a944Jan Engelhardtstatic void cluster_parse(struct xt_option_call *cb)
53cd958a6c92c84095a439780b53832bb3aae2d512Pablo Neira Ayuso{
54b18ffe3636b07cd817628de81643136e4755a944Jan Engelhardt	struct xt_cluster_match_info *info = cb->data;
55cd958a6c92c84095a439780b53832bb3aae2d512Pablo Neira Ayuso
56b18ffe3636b07cd817628de81643136e4755a944Jan Engelhardt	xtables_option_parse(cb);
57b18ffe3636b07cd817628de81643136e4755a944Jan Engelhardt	switch (cb->entry->id) {
58b18ffe3636b07cd817628de81643136e4755a944Jan Engelhardt	case O_CL_LOCAL_NODE:
59b18ffe3636b07cd817628de81643136e4755a944Jan Engelhardt		if (cb->invert)
60e76ec99b48745b0e3c8aecbc91ed5bba186cf25fPablo Neira Ayuso			info->flags |= XT_CLUSTER_F_INV;
61b18ffe3636b07cd817628de81643136e4755a944Jan Engelhardt		info->node_mask = 1 << (cb->val.u32 - 1);
62cd958a6c92c84095a439780b53832bb3aae2d512Pablo Neira Ayuso		break;
63b18ffe3636b07cd817628de81643136e4755a944Jan Engelhardt	case O_CL_LOCAL_NODEMASK:
64b18ffe3636b07cd817628de81643136e4755a944Jan Engelhardt		if (cb->invert)
65e76ec99b48745b0e3c8aecbc91ed5bba186cf25fPablo Neira Ayuso			info->flags |= XT_CLUSTER_F_INV;
66cd958a6c92c84095a439780b53832bb3aae2d512Pablo Neira Ayuso		break;
67cd958a6c92c84095a439780b53832bb3aae2d512Pablo Neira Ayuso	}
68cd958a6c92c84095a439780b53832bb3aae2d512Pablo Neira Ayuso}
69cd958a6c92c84095a439780b53832bb3aae2d512Pablo Neira Ayuso
70b18ffe3636b07cd817628de81643136e4755a944Jan Engelhardtstatic void cluster_check(struct xt_fcheck_call *cb)
71cd958a6c92c84095a439780b53832bb3aae2d512Pablo Neira Ayuso{
72b18ffe3636b07cd817628de81643136e4755a944Jan Engelhardt	const struct xt_cluster_match_info *info = cb->data;
73b18ffe3636b07cd817628de81643136e4755a944Jan Engelhardt	unsigned int test;
74b18ffe3636b07cd817628de81643136e4755a944Jan Engelhardt
75b18ffe3636b07cd817628de81643136e4755a944Jan Engelhardt	test = F_CL_TOTAL_NODES | F_CL_LOCAL_NODE | F_CL_HASH_SEED;
76b18ffe3636b07cd817628de81643136e4755a944Jan Engelhardt	if ((cb->xflags & test) == test) {
77b18ffe3636b07cd817628de81643136e4755a944Jan Engelhardt		if (info->node_mask >= (1ULL << info->total_nodes))
78cd958a6c92c84095a439780b53832bb3aae2d512Pablo Neira Ayuso			xtables_error(PARAMETER_PROBLEM,
79cd958a6c92c84095a439780b53832bb3aae2d512Pablo Neira Ayuso				      "cluster match: "
80cd958a6c92c84095a439780b53832bb3aae2d512Pablo Neira Ayuso				      "`--cluster-local-node' "
81cd958a6c92c84095a439780b53832bb3aae2d512Pablo Neira Ayuso				      "must be <= `--cluster-total-nodes'");
82cd958a6c92c84095a439780b53832bb3aae2d512Pablo Neira Ayuso		return;
83cd958a6c92c84095a439780b53832bb3aae2d512Pablo Neira Ayuso	}
84b18ffe3636b07cd817628de81643136e4755a944Jan Engelhardt
85b18ffe3636b07cd817628de81643136e4755a944Jan Engelhardt	test = F_CL_TOTAL_NODES | F_CL_LOCAL_NODEMASK | F_CL_HASH_SEED;
86b18ffe3636b07cd817628de81643136e4755a944Jan Engelhardt	if ((cb->xflags & test) == test) {
87b18ffe3636b07cd817628de81643136e4755a944Jan Engelhardt		if (info->node_mask >= (1ULL << info->total_nodes))
88cd958a6c92c84095a439780b53832bb3aae2d512Pablo Neira Ayuso			xtables_error(PARAMETER_PROBLEM,
89cd958a6c92c84095a439780b53832bb3aae2d512Pablo Neira Ayuso				      "cluster match: "
90cd958a6c92c84095a439780b53832bb3aae2d512Pablo Neira Ayuso				      "`--cluster-local-nodemask' too big "
91cd958a6c92c84095a439780b53832bb3aae2d512Pablo Neira Ayuso				      "for `--cluster-total-nodes'");
92cd958a6c92c84095a439780b53832bb3aae2d512Pablo Neira Ayuso		return;
93cd958a6c92c84095a439780b53832bb3aae2d512Pablo Neira Ayuso	}
94b18ffe3636b07cd817628de81643136e4755a944Jan Engelhardt	if (!(cb->xflags & (F_CL_LOCAL_NODE | F_CL_LOCAL_NODEMASK)))
95cd958a6c92c84095a439780b53832bb3aae2d512Pablo Neira Ayuso		xtables_error(PARAMETER_PROBLEM,
96cd958a6c92c84095a439780b53832bb3aae2d512Pablo Neira Ayuso			      "cluster match: `--cluster-local-node' or"
97cd958a6c92c84095a439780b53832bb3aae2d512Pablo Neira Ayuso			      "`--cluster-local-nodemask' is missing");
98cd958a6c92c84095a439780b53832bb3aae2d512Pablo Neira Ayuso}
99cd958a6c92c84095a439780b53832bb3aae2d512Pablo Neira Ayuso
100cd958a6c92c84095a439780b53832bb3aae2d512Pablo Neira Ayusostatic void
101cd958a6c92c84095a439780b53832bb3aae2d512Pablo Neira Ayusocluster_print(const void *ip, const struct xt_entry_match *match, int numeric)
102cd958a6c92c84095a439780b53832bb3aae2d512Pablo Neira Ayuso{
103cd958a6c92c84095a439780b53832bb3aae2d512Pablo Neira Ayuso	const struct xt_cluster_match_info *info = (void *)match->data;
104cd958a6c92c84095a439780b53832bb3aae2d512Pablo Neira Ayuso
10573866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt	printf(" cluster ");
106cd958a6c92c84095a439780b53832bb3aae2d512Pablo Neira Ayuso	if (info->flags & XT_CLUSTER_F_INV)
10773866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt		printf("!node_mask=0x%08x", info->node_mask);
108cd958a6c92c84095a439780b53832bb3aae2d512Pablo Neira Ayuso	else
10973866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt		printf("node_mask=0x%08x", info->node_mask);
110cd958a6c92c84095a439780b53832bb3aae2d512Pablo Neira Ayuso
11173866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt	printf(" total_nodes=%u hash_seed=0x%08x",
112cd958a6c92c84095a439780b53832bb3aae2d512Pablo Neira Ayuso		info->total_nodes, info->hash_seed);
113cd958a6c92c84095a439780b53832bb3aae2d512Pablo Neira Ayuso}
114cd958a6c92c84095a439780b53832bb3aae2d512Pablo Neira Ayuso
115cd958a6c92c84095a439780b53832bb3aae2d512Pablo Neira Ayusostatic void
116cd958a6c92c84095a439780b53832bb3aae2d512Pablo Neira Ayusocluster_save(const void *ip, const struct xt_entry_match *match)
117cd958a6c92c84095a439780b53832bb3aae2d512Pablo Neira Ayuso{
118cd958a6c92c84095a439780b53832bb3aae2d512Pablo Neira Ayuso	const struct xt_cluster_match_info *info = (void *)match->data;
119cd958a6c92c84095a439780b53832bb3aae2d512Pablo Neira Ayuso
120cd958a6c92c84095a439780b53832bb3aae2d512Pablo Neira Ayuso	if (info->flags & XT_CLUSTER_F_INV)
12173866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt		printf(" ! --cluster-local-nodemask 0x%08x", info->node_mask);
122cd958a6c92c84095a439780b53832bb3aae2d512Pablo Neira Ayuso	else
12373866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt		printf(" --cluster-local-nodemask 0x%08x", info->node_mask);
124cd958a6c92c84095a439780b53832bb3aae2d512Pablo Neira Ayuso
12573866357e4a7a0fdc1b293bf8863fee2bd56da9eJan Engelhardt	printf(" --cluster-total-nodes %u --cluster-hash-seed 0x%08x",
126cd958a6c92c84095a439780b53832bb3aae2d512Pablo Neira Ayuso		info->total_nodes, info->hash_seed);
127cd958a6c92c84095a439780b53832bb3aae2d512Pablo Neira Ayuso}
128cd958a6c92c84095a439780b53832bb3aae2d512Pablo Neira Ayuso
129cd958a6c92c84095a439780b53832bb3aae2d512Pablo Neira Ayusostatic struct xtables_match cluster_mt_reg = {
13042979363f3958b4436c6d2503753c182c58e55eaJan Engelhardt	.family		= NFPROTO_UNSPEC,
131cd958a6c92c84095a439780b53832bb3aae2d512Pablo Neira Ayuso	.name		= "cluster",
132cd958a6c92c84095a439780b53832bb3aae2d512Pablo Neira Ayuso	.version	= XTABLES_VERSION,
133cd958a6c92c84095a439780b53832bb3aae2d512Pablo Neira Ayuso	.size		= XT_ALIGN(sizeof(struct xt_cluster_match_info)),
134cd958a6c92c84095a439780b53832bb3aae2d512Pablo Neira Ayuso	.userspacesize  = XT_ALIGN(sizeof(struct xt_cluster_match_info)),
135cd958a6c92c84095a439780b53832bb3aae2d512Pablo Neira Ayuso 	.help		= cluster_help,
136cd958a6c92c84095a439780b53832bb3aae2d512Pablo Neira Ayuso	.print		= cluster_print,
137cd958a6c92c84095a439780b53832bb3aae2d512Pablo Neira Ayuso	.save		= cluster_save,
138b18ffe3636b07cd817628de81643136e4755a944Jan Engelhardt	.x6_parse	= cluster_parse,
139b18ffe3636b07cd817628de81643136e4755a944Jan Engelhardt	.x6_fcheck	= cluster_check,
140b18ffe3636b07cd817628de81643136e4755a944Jan Engelhardt	.x6_options	= cluster_opts,
141cd958a6c92c84095a439780b53832bb3aae2d512Pablo Neira Ayuso};
142cd958a6c92c84095a439780b53832bb3aae2d512Pablo Neira Ayuso
143cd958a6c92c84095a439780b53832bb3aae2d512Pablo Neira Ayusovoid _init(void)
144cd958a6c92c84095a439780b53832bb3aae2d512Pablo Neira Ayuso{
145cd958a6c92c84095a439780b53832bb3aae2d512Pablo Neira Ayuso	xtables_register_match(&cluster_mt_reg);
146cd958a6c92c84095a439780b53832bb3aae2d512Pablo Neira Ayuso}
147