libxt_cluster.c revision 32b8e61e4e5bd405d9ad07bf9468498dfbb19f9e
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 default: 138 return 0; 139 } 140 141 return 1; 142} 143 144static void 145cluster_check(unsigned int flags) 146{ 147 if ((flags & ((1 << CLUSTER_OPT_TOTAL_NODES) | 148 (1 << CLUSTER_OPT_LOCAL_NODE) | 149 (1 << CLUSTER_OPT_HASH_SEED))) 150 == ((1 << CLUSTER_OPT_TOTAL_NODES) | 151 (1 << CLUSTER_OPT_LOCAL_NODE) | 152 (1 << CLUSTER_OPT_HASH_SEED))) { 153 if (node_mask >= (1ULL << total_nodes)) { 154 xtables_error(PARAMETER_PROBLEM, 155 "cluster match: " 156 "`--cluster-local-node' " 157 "must be <= `--cluster-total-nodes'"); 158 } 159 return; 160 } 161 if ((flags & ((1 << CLUSTER_OPT_TOTAL_NODES) | 162 (1 << CLUSTER_OPT_NODE_MASK) | 163 (1 << CLUSTER_OPT_HASH_SEED))) 164 == ((1 << CLUSTER_OPT_TOTAL_NODES) | 165 (1 << CLUSTER_OPT_NODE_MASK) | 166 (1 << CLUSTER_OPT_HASH_SEED))) { 167 if (node_mask >= (1ULL << total_nodes)) { 168 xtables_error(PARAMETER_PROBLEM, 169 "cluster match: " 170 "`--cluster-local-nodemask' too big " 171 "for `--cluster-total-nodes'"); 172 } 173 return; 174 } 175 if (!(flags & (1 << CLUSTER_OPT_TOTAL_NODES))) { 176 xtables_error(PARAMETER_PROBLEM, 177 "cluster match: `--cluster-total-nodes' " 178 "is missing"); 179 } 180 if (!(flags & (1 << CLUSTER_OPT_HASH_SEED))) { 181 xtables_error(PARAMETER_PROBLEM, 182 "cluster match: `--cluster-hash-seed' " 183 "is missing"); 184 } 185 if (!(flags & ((1 << (CLUSTER_OPT_LOCAL_NODE) | 186 (1 << (CLUSTER_OPT_NODE_MASK)))))) { 187 xtables_error(PARAMETER_PROBLEM, 188 "cluster match: `--cluster-local-node' or" 189 "`--cluster-local-nodemask' is missing"); 190 } 191} 192 193static void 194cluster_print(const void *ip, const struct xt_entry_match *match, int numeric) 195{ 196 const struct xt_cluster_match_info *info = (void *)match->data; 197 198 printf("cluster "); 199 if (info->flags & XT_CLUSTER_F_INV) 200 printf("!node_mask=0x%08x ", info->node_mask); 201 else 202 printf("node_mask=0x%08x ", info->node_mask); 203 204 printf("total_nodes=%u hash_seed=0x%08x ", 205 info->total_nodes, info->hash_seed); 206} 207 208static void 209cluster_save(const void *ip, const struct xt_entry_match *match) 210{ 211 const struct xt_cluster_match_info *info = (void *)match->data; 212 213 if (info->flags & XT_CLUSTER_F_INV) 214 printf("! --cluster-local-nodemask 0x%08x ", info->node_mask); 215 else 216 printf("--cluster-local-nodemask 0x%08x ", info->node_mask); 217 218 printf("--cluster-total-nodes %u --cluster-hash-seed 0x%08x ", 219 info->total_nodes, info->hash_seed); 220} 221 222static struct xtables_match cluster_mt_reg = { 223 .family = NFPROTO_UNSPEC, 224 .name = "cluster", 225 .version = XTABLES_VERSION, 226 .size = XT_ALIGN(sizeof(struct xt_cluster_match_info)), 227 .userspacesize = XT_ALIGN(sizeof(struct xt_cluster_match_info)), 228 .help = cluster_help, 229 .parse = cluster_parse, 230 .final_check = cluster_check, 231 .print = cluster_print, 232 .save = cluster_save, 233 .extra_opts = cluster_opts, 234}; 235 236void _init(void) 237{ 238 xtables_register_match(&cluster_mt_reg); 239} 240