blob: ea5d9fb40dc5a389973985253be0e5a22254b578 [file] [log] [blame]
Pablo Neira Ayusocd958a62009-05-06 13:01:20 +02001/*
2 * (C) 2009 by Pablo Neira Ayuso <pablo@netfilter.org>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 */
8#include <stdio.h>
9#include <string.h>
10#include <stdlib.h>
11#include <getopt.h>
12#include <stddef.h>
13
14#include <xtables.h>
15#include <linux/netfilter/x_tables.h>
16#include <linux/netfilter/xt_cluster.h>
17
18/* hack to keep for check */
19static unsigned int total_nodes;
20static unsigned int node_mask;
21
22static void
23cluster_help(void)
24{
25 printf(
26"cluster match options:\n"
27" --cluster-total-nodes <num> Set number of total nodes in cluster\n"
28" [!] --cluster-local-node <num> Set the local node number\n"
29" [!] --cluster-local-nodemask <num> Set the local node mask\n"
30" --cluster-hash-seed <num> Set seed value of the Jenkins hash\n");
31}
32
33enum {
34 CLUSTER_OPT_TOTAL_NODES,
35 CLUSTER_OPT_LOCAL_NODE,
36 CLUSTER_OPT_NODE_MASK,
37 CLUSTER_OPT_HASH_SEED,
38};
39
40static const struct option cluster_opts[] = {
41 { "cluster-total-nodes", 1, NULL, CLUSTER_OPT_TOTAL_NODES },
42 { "cluster-local-node", 1, NULL, CLUSTER_OPT_LOCAL_NODE },
43 { "cluster-local-nodemask", 1, NULL, CLUSTER_OPT_NODE_MASK },
44 { "cluster-hash-seed", 1, NULL, CLUSTER_OPT_HASH_SEED },
45 { .name = NULL }
46};
47
48static int
49cluster_parse(int c, char **argv, int invert, unsigned int *flags,
50 const void *entry, struct xt_entry_match **match)
51{
52 struct xt_cluster_match_info *info = (void *)(*match)->data;
53 unsigned int num;
54
55 switch (c) {
56 case CLUSTER_OPT_TOTAL_NODES:
57 if (*flags & (1 << c)) {
58 xtables_error(PARAMETER_PROBLEM,
59 "Can only specify "
60 "`--cluster-total-nodes' once");
61 }
62 if (!xtables_strtoui(optarg, NULL, &num, 1,
63 XT_CLUSTER_NODES_MAX)) {
64 xtables_error(PARAMETER_PROBLEM,
65 "Unable to parse `%s' in "
66 "`--cluster-total-nodes'", optarg);
67 }
68 total_nodes = num;
69 info->total_nodes = total_nodes = num;
70 *flags |= 1 << c;
71 break;
72 case CLUSTER_OPT_LOCAL_NODE:
73 if (*flags & (1 << c)) {
74 xtables_error(PARAMETER_PROBLEM,
75 "Can only specify "
76 "`--cluster-local-node' once");
77 }
78 if (*flags & (1 << CLUSTER_OPT_NODE_MASK)) {
79 xtables_error(PARAMETER_PROBLEM, "You cannot use "
80 "`--cluster-local-nodemask' and "
81 "`--cluster-local-node'");
82 }
Jan Engelhardtbf971282009-11-03 19:55:11 +010083 xtables_check_inverse(optarg, &invert, &optind, 0, argv);
Pablo Neira Ayusocd958a62009-05-06 13:01:20 +020084
85 if (!xtables_strtoui(optarg, NULL, &num, 1,
86 XT_CLUSTER_NODES_MAX)) {
87 xtables_error(PARAMETER_PROBLEM,
88 "Unable to parse `%s' in "
89 "`--cluster-local-node'", optarg);
90 }
91 if (invert)
92 info->flags |= (1 << XT_CLUSTER_F_INV);
93
94 info->node_mask = node_mask = (1 << (num - 1));
95 *flags |= 1 << c;
96 break;
97 case CLUSTER_OPT_NODE_MASK:
98 if (*flags & (1 << c)) {
99 xtables_error(PARAMETER_PROBLEM,
100 "Can only specify "
101 "`--cluster-local-node' once");
102 }
103 if (*flags & (1 << CLUSTER_OPT_LOCAL_NODE)) {
104 xtables_error(PARAMETER_PROBLEM, "You cannot use "
105 "`--cluster-local-nodemask' and "
106 "`--cluster-local-node'");
107 }
Jan Engelhardtbf971282009-11-03 19:55:11 +0100108 xtables_check_inverse(optarg, &invert, &optind, 0, argv);
Pablo Neira Ayusocd958a62009-05-06 13:01:20 +0200109
110 if (!xtables_strtoui(optarg, NULL, &num, 1,
111 XT_CLUSTER_NODES_MAX)) {
112 xtables_error(PARAMETER_PROBLEM,
113 "Unable to parse `%s' in "
114 "`--cluster-local-node'", optarg);
115 }
116 if (invert)
117 info->flags |= (1 << XT_CLUSTER_F_INV);
118
119 info->node_mask = node_mask = num;
120 *flags |= 1 << c;
121 break;
122
123 case CLUSTER_OPT_HASH_SEED:
124 if (*flags & (1 << c)) {
125 xtables_error(PARAMETER_PROBLEM,
126 "Can only specify "
127 "`--cluster-hash-seed' once");
128 }
129 if (!xtables_strtoui(optarg, NULL, &num, 0, UINT32_MAX)) {
130 xtables_error(PARAMETER_PROBLEM,
131 "Unable to parse `%s'", optarg);
132 }
133 info->hash_seed = num;
134 *flags |= 1 << c;
135 break;
136 default:
137 return 0;
138 }
139
140 return 1;
141}
142
143static void
144cluster_check(unsigned int flags)
145{
146 if ((flags & ((1 << CLUSTER_OPT_TOTAL_NODES) |
147 (1 << CLUSTER_OPT_LOCAL_NODE) |
148 (1 << CLUSTER_OPT_HASH_SEED)))
149 == ((1 << CLUSTER_OPT_TOTAL_NODES) |
150 (1 << CLUSTER_OPT_LOCAL_NODE) |
151 (1 << CLUSTER_OPT_HASH_SEED))) {
152 if (node_mask >= (1ULL << total_nodes)) {
153 xtables_error(PARAMETER_PROBLEM,
154 "cluster match: "
155 "`--cluster-local-node' "
156 "must be <= `--cluster-total-nodes'");
157 }
158 return;
159 }
160 if ((flags & ((1 << CLUSTER_OPT_TOTAL_NODES) |
161 (1 << CLUSTER_OPT_NODE_MASK) |
162 (1 << CLUSTER_OPT_HASH_SEED)))
163 == ((1 << CLUSTER_OPT_TOTAL_NODES) |
164 (1 << CLUSTER_OPT_NODE_MASK) |
165 (1 << CLUSTER_OPT_HASH_SEED))) {
166 if (node_mask >= (1ULL << total_nodes)) {
167 xtables_error(PARAMETER_PROBLEM,
168 "cluster match: "
169 "`--cluster-local-nodemask' too big "
170 "for `--cluster-total-nodes'");
171 }
172 return;
173 }
174 if (!(flags & (1 << CLUSTER_OPT_TOTAL_NODES))) {
175 xtables_error(PARAMETER_PROBLEM,
176 "cluster match: `--cluster-total-nodes' "
177 "is missing");
178 }
179 if (!(flags & (1 << CLUSTER_OPT_HASH_SEED))) {
180 xtables_error(PARAMETER_PROBLEM,
181 "cluster match: `--cluster-hash-seed' "
182 "is missing");
183 }
184 if (!(flags & ((1 << (CLUSTER_OPT_LOCAL_NODE) |
185 (1 << (CLUSTER_OPT_NODE_MASK)))))) {
186 xtables_error(PARAMETER_PROBLEM,
187 "cluster match: `--cluster-local-node' or"
188 "`--cluster-local-nodemask' is missing");
189 }
190}
191
192static void
193cluster_print(const void *ip, const struct xt_entry_match *match, int numeric)
194{
195 const struct xt_cluster_match_info *info = (void *)match->data;
196
197 printf("cluster ");
198 if (info->flags & XT_CLUSTER_F_INV)
199 printf("!node_mask=0x%08x ", info->node_mask);
200 else
201 printf("node_mask=0x%08x ", info->node_mask);
202
203 printf("total_nodes=%u hash_seed=0x%08x ",
204 info->total_nodes, info->hash_seed);
205}
206
207static void
208cluster_save(const void *ip, const struct xt_entry_match *match)
209{
210 const struct xt_cluster_match_info *info = (void *)match->data;
211
212 if (info->flags & XT_CLUSTER_F_INV)
213 printf("! --cluster-local-nodemask 0x%08x ", info->node_mask);
214 else
215 printf("--cluster-local-nodemask 0x%08x ", info->node_mask);
216
217 printf("--cluster-total-nodes %u --cluster-hash-seed 0x%08x ",
218 info->total_nodes, info->hash_seed);
219}
220
221static struct xtables_match cluster_mt_reg = {
Jan Engelhardt42979362009-06-01 11:56:23 +0200222 .family = NFPROTO_UNSPEC,
Pablo Neira Ayusocd958a62009-05-06 13:01:20 +0200223 .name = "cluster",
224 .version = XTABLES_VERSION,
225 .size = XT_ALIGN(sizeof(struct xt_cluster_match_info)),
226 .userspacesize = XT_ALIGN(sizeof(struct xt_cluster_match_info)),
227 .help = cluster_help,
228 .parse = cluster_parse,
229 .final_check = cluster_check,
230 .print = cluster_print,
231 .save = cluster_save,
232 .extra_opts = cluster_opts,
233};
234
235void _init(void)
236{
237 xtables_register_match(&cluster_mt_reg);
238}