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 <xtables.h> 10#include <linux/netfilter/xt_cluster.h> 11 12static void 13cluster_help(void) 14{ 15 printf( 16"cluster match options:\n" 17" --cluster-total-nodes <num> Set number of total nodes in cluster\n" 18" [!] --cluster-local-node <num> Set the local node number\n" 19" [!] --cluster-local-nodemask <num> Set the local node mask\n" 20" --cluster-hash-seed <num> Set seed value of the Jenkins hash\n"); 21} 22 23enum { 24 O_CL_TOTAL_NODES = 0, 25 O_CL_LOCAL_NODE, 26 O_CL_LOCAL_NODEMASK, 27 O_CL_HASH_SEED, 28 F_CL_TOTAL_NODES = 1 << O_CL_TOTAL_NODES, 29 F_CL_LOCAL_NODE = 1 << O_CL_LOCAL_NODE, 30 F_CL_LOCAL_NODEMASK = 1 << O_CL_LOCAL_NODEMASK, 31 F_CL_HASH_SEED = 1 << O_CL_HASH_SEED, 32}; 33 34#define s struct xt_cluster_match_info 35static const struct xt_option_entry cluster_opts[] = { 36 {.name = "cluster-total-nodes", .id = O_CL_TOTAL_NODES, 37 .type = XTTYPE_UINT32, .min = 1, .max = XT_CLUSTER_NODES_MAX, 38 .flags = XTOPT_MAND | XTOPT_PUT, XTOPT_POINTER(s, total_nodes)}, 39 {.name = "cluster-local-node", .id = O_CL_LOCAL_NODE, 40 .excl = F_CL_LOCAL_NODEMASK, .flags = XTOPT_INVERT, 41 .type = XTTYPE_UINT32, .min = 1, .max = XT_CLUSTER_NODES_MAX}, 42 {.name = "cluster-local-nodemask", .id = O_CL_LOCAL_NODEMASK, 43 .excl = F_CL_LOCAL_NODE, .type = XTTYPE_UINT32, 44 .min = 1, .max = XT_CLUSTER_NODES_MAX, 45 .flags = XTOPT_INVERT | XTOPT_PUT, XTOPT_POINTER(s, node_mask)}, 46 {.name = "cluster-hash-seed", .id = O_CL_HASH_SEED, 47 .type = XTTYPE_UINT32, .flags = XTOPT_MAND | XTOPT_PUT, 48 XTOPT_POINTER(s, hash_seed)}, 49 XTOPT_TABLEEND, 50}; 51 52static void cluster_parse(struct xt_option_call *cb) 53{ 54 struct xt_cluster_match_info *info = cb->data; 55 56 xtables_option_parse(cb); 57 switch (cb->entry->id) { 58 case O_CL_LOCAL_NODE: 59 if (cb->invert) 60 info->flags |= XT_CLUSTER_F_INV; 61 info->node_mask = 1 << (cb->val.u32 - 1); 62 break; 63 case O_CL_LOCAL_NODEMASK: 64 if (cb->invert) 65 info->flags |= XT_CLUSTER_F_INV; 66 break; 67 } 68} 69 70static void cluster_check(struct xt_fcheck_call *cb) 71{ 72 const struct xt_cluster_match_info *info = cb->data; 73 unsigned int test; 74 75 test = F_CL_TOTAL_NODES | F_CL_LOCAL_NODE | F_CL_HASH_SEED; 76 if ((cb->xflags & test) == test) { 77 if (info->node_mask >= (1ULL << info->total_nodes)) 78 xtables_error(PARAMETER_PROBLEM, 79 "cluster match: " 80 "`--cluster-local-node' " 81 "must be <= `--cluster-total-nodes'"); 82 return; 83 } 84 85 test = F_CL_TOTAL_NODES | F_CL_LOCAL_NODEMASK | F_CL_HASH_SEED; 86 if ((cb->xflags & test) == test) { 87 if (info->node_mask >= (1ULL << info->total_nodes)) 88 xtables_error(PARAMETER_PROBLEM, 89 "cluster match: " 90 "`--cluster-local-nodemask' too big " 91 "for `--cluster-total-nodes'"); 92 return; 93 } 94 if (!(cb->xflags & (F_CL_LOCAL_NODE | F_CL_LOCAL_NODEMASK))) 95 xtables_error(PARAMETER_PROBLEM, 96 "cluster match: `--cluster-local-node' or" 97 "`--cluster-local-nodemask' is missing"); 98} 99 100static void 101cluster_print(const void *ip, const struct xt_entry_match *match, int numeric) 102{ 103 const struct xt_cluster_match_info *info = (void *)match->data; 104 105 printf(" cluster "); 106 if (info->flags & XT_CLUSTER_F_INV) 107 printf("!node_mask=0x%08x", info->node_mask); 108 else 109 printf("node_mask=0x%08x", info->node_mask); 110 111 printf(" total_nodes=%u hash_seed=0x%08x", 112 info->total_nodes, info->hash_seed); 113} 114 115static void 116cluster_save(const void *ip, const struct xt_entry_match *match) 117{ 118 const struct xt_cluster_match_info *info = (void *)match->data; 119 120 if (info->flags & XT_CLUSTER_F_INV) 121 printf(" ! --cluster-local-nodemask 0x%08x", info->node_mask); 122 else 123 printf(" --cluster-local-nodemask 0x%08x", info->node_mask); 124 125 printf(" --cluster-total-nodes %u --cluster-hash-seed 0x%08x", 126 info->total_nodes, info->hash_seed); 127} 128 129static struct xtables_match cluster_mt_reg = { 130 .family = NFPROTO_UNSPEC, 131 .name = "cluster", 132 .version = XTABLES_VERSION, 133 .size = XT_ALIGN(sizeof(struct xt_cluster_match_info)), 134 .userspacesize = XT_ALIGN(sizeof(struct xt_cluster_match_info)), 135 .help = cluster_help, 136 .print = cluster_print, 137 .save = cluster_save, 138 .x6_parse = cluster_parse, 139 .x6_fcheck = cluster_check, 140 .x6_options = cluster_opts, 141}; 142 143void _init(void) 144{ 145 xtables_register_match(&cluster_mt_reg); 146} 147