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