Fork for IVI and add .changes file
[profile/ivi/iptables.git] / extensions / libxt_cluster.c
1 /*
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 */
19 static unsigned int total_nodes;
20 static unsigned int node_mask;
21
22 static void
23 cluster_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
33 enum {
34         CLUSTER_OPT_TOTAL_NODES,
35         CLUSTER_OPT_LOCAL_NODE,
36         CLUSTER_OPT_NODE_MASK,
37         CLUSTER_OPT_HASH_SEED,
38 };
39
40 static 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
48 static int 
49 cluster_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                 }
83                 xtables_check_inverse(optarg, &invert, &optind, 0, argv);
84
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                 }
108                 xtables_check_inverse(optarg, &invert, &optind, 0, argv);
109
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
143 static void
144 cluster_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
192 static void
193 cluster_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
207 static void
208 cluster_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
221 static struct xtables_match cluster_mt_reg = {
222         .family         = NFPROTO_UNSPEC,
223         .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
235 void _init(void)
236 {
237         xtables_register_match(&cluster_mt_reg);
238 }