123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195 |
- /* Shared library add-on to iptables to add CLUSTERIP target support.
- * (C) 2003 by Harald Welte <laforge@gnumonks.org>
- *
- * Development of this code was funded by SuSE AG, http://www.suse.com/
- */
- #include <stdbool.h>
- #include <stdio.h>
- #include <string.h>
- #include <stdlib.h>
- #include <getopt.h>
- #include <stddef.h>
- #if defined(__GLIBC__) && __GLIBC__ == 2
- #include <net/ethernet.h>
- #else
- #include <linux/if_ether.h>
- #endif
- #include <xtables.h>
- #include <linux/netfilter_ipv4/ipt_CLUSTERIP.h>
- enum {
- O_NEW = 0,
- O_HASHMODE,
- O_CLUSTERMAC,
- O_TOTAL_NODES,
- O_LOCAL_NODE,
- O_HASH_INIT,
- F_NEW = 1 << O_NEW,
- F_HASHMODE = 1 << O_HASHMODE,
- F_CLUSTERMAC = 1 << O_CLUSTERMAC,
- F_TOTAL_NODES = 1 << O_TOTAL_NODES,
- F_LOCAL_NODE = 1 << O_LOCAL_NODE,
- F_FULL = F_NEW | F_HASHMODE | F_CLUSTERMAC |
- F_TOTAL_NODES | F_LOCAL_NODE,
- };
- static void CLUSTERIP_help(void)
- {
- printf(
- "CLUSTERIP target options:\n"
- " --new Create a new ClusterIP\n"
- " --hashmode <mode> Specify hashing mode\n"
- " sourceip\n"
- " sourceip-sourceport\n"
- " sourceip-sourceport-destport\n"
- " --clustermac <mac> Set clusterIP MAC address\n"
- " --total-nodes <num> Set number of total nodes in cluster\n"
- " --local-node <num> Set the local node number\n"
- " --hash-init <num> Set init value of the Jenkins hash\n");
- }
- #define s struct ipt_clusterip_tgt_info
- static const struct xt_option_entry CLUSTERIP_opts[] = {
- {.name = "new", .id = O_NEW, .type = XTTYPE_NONE},
- {.name = "hashmode", .id = O_HASHMODE, .type = XTTYPE_STRING,
- .also = O_NEW},
- {.name = "clustermac", .id = O_CLUSTERMAC, .type = XTTYPE_ETHERMAC,
- .also = O_NEW, .flags = XTOPT_PUT, XTOPT_POINTER(s, clustermac)},
- {.name = "total-nodes", .id = O_TOTAL_NODES, .type = XTTYPE_UINT16,
- .flags = XTOPT_PUT, XTOPT_POINTER(s, num_total_nodes),
- .also = O_NEW, .max = CLUSTERIP_MAX_NODES},
- {.name = "local-node", .id = O_LOCAL_NODE, .type = XTTYPE_UINT16,
- .flags = XTOPT_PUT, XTOPT_POINTER(s, local_nodes[0]),
- .also = O_NEW, .max = CLUSTERIP_MAX_NODES},
- {.name = "hash-init", .id = O_HASH_INIT, .type = XTTYPE_UINT32,
- .flags = XTOPT_PUT, XTOPT_POINTER(s, hash_initval),
- .also = O_NEW, .max = UINT_MAX},
- XTOPT_TABLEEND,
- };
- #undef s
- static void CLUSTERIP_parse(struct xt_option_call *cb)
- {
- struct ipt_clusterip_tgt_info *cipinfo = cb->data;
- xtables_option_parse(cb);
- switch (cb->entry->id) {
- case O_NEW:
- cipinfo->flags |= CLUSTERIP_FLAG_NEW;
- break;
- case O_HASHMODE:
- if (strcmp(cb->arg, "sourceip") == 0)
- cipinfo->hash_mode = CLUSTERIP_HASHMODE_SIP;
- else if (strcmp(cb->arg, "sourceip-sourceport") == 0)
- cipinfo->hash_mode = CLUSTERIP_HASHMODE_SIP_SPT;
- else if (strcmp(cb->arg, "sourceip-sourceport-destport") == 0)
- cipinfo->hash_mode = CLUSTERIP_HASHMODE_SIP_SPT_DPT;
- else
- xtables_error(PARAMETER_PROBLEM, "Unknown hashmode \"%s\"\n",
- cb->arg);
- break;
- case O_CLUSTERMAC:
- if (!(cipinfo->clustermac[0] & 0x01))
- xtables_error(PARAMETER_PROBLEM, "MAC has to be a multicast ethernet address\n");
- break;
- case O_LOCAL_NODE:
- cipinfo->num_local_nodes = 1;
- break;
- }
- }
- static void CLUSTERIP_check(struct xt_fcheck_call *cb)
- {
- if (cb->xflags == 0)
- return;
- if ((cb->xflags & F_FULL) == F_FULL)
- return;
- xtables_error(PARAMETER_PROBLEM, "CLUSTERIP target: Invalid parameter combination\n");
- }
- static const char *hashmode2str(enum clusterip_hashmode mode)
- {
- const char *retstr;
- switch (mode) {
- case CLUSTERIP_HASHMODE_SIP:
- retstr = "sourceip";
- break;
- case CLUSTERIP_HASHMODE_SIP_SPT:
- retstr = "sourceip-sourceport";
- break;
- case CLUSTERIP_HASHMODE_SIP_SPT_DPT:
- retstr = "sourceip-sourceport-destport";
- break;
- default:
- retstr = "unknown-error";
- break;
- }
- return retstr;
- }
- static const char *mac2str(const uint8_t mac[ETH_ALEN])
- {
- static char buf[ETH_ALEN*3];
- sprintf(buf, "%02X:%02X:%02X:%02X:%02X:%02X",
- mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
- return buf;
- }
- static void CLUSTERIP_print(const void *ip,
- const struct xt_entry_target *target, int numeric)
- {
- const struct ipt_clusterip_tgt_info *cipinfo =
- (const struct ipt_clusterip_tgt_info *)target->data;
-
- if (!(cipinfo->flags & CLUSTERIP_FLAG_NEW)) {
- printf(" CLUSTERIP");
- return;
- }
- printf(" CLUSTERIP hashmode=%s clustermac=%s total_nodes=%u local_node=%u hash_init=%u",
- hashmode2str(cipinfo->hash_mode),
- mac2str(cipinfo->clustermac),
- cipinfo->num_total_nodes,
- cipinfo->local_nodes[0],
- cipinfo->hash_initval);
- }
- static void CLUSTERIP_save(const void *ip, const struct xt_entry_target *target)
- {
- const struct ipt_clusterip_tgt_info *cipinfo =
- (const struct ipt_clusterip_tgt_info *)target->data;
- /* if this is not a new entry, we don't need to save target
- * parameters */
- if (!(cipinfo->flags & CLUSTERIP_FLAG_NEW))
- return;
- printf(" --new --hashmode %s --clustermac %s --total-nodes %d --local-node %d --hash-init %u",
- hashmode2str(cipinfo->hash_mode),
- mac2str(cipinfo->clustermac),
- cipinfo->num_total_nodes,
- cipinfo->local_nodes[0],
- cipinfo->hash_initval);
- }
- static struct xtables_target clusterip_tg_reg = {
- .name = "CLUSTERIP",
- .version = XTABLES_VERSION,
- .family = NFPROTO_IPV4,
- .size = XT_ALIGN(sizeof(struct ipt_clusterip_tgt_info)),
- .userspacesize = offsetof(struct ipt_clusterip_tgt_info, config),
- .help = CLUSTERIP_help,
- .x6_parse = CLUSTERIP_parse,
- .x6_fcheck = CLUSTERIP_check,
- .print = CLUSTERIP_print,
- .save = CLUSTERIP_save,
- .x6_options = CLUSTERIP_opts,
- };
- void _init(void)
- {
- xtables_register_target(&clusterip_tg_reg);
- }
|