From: Baptiste Assmann Date: Wed, 21 Sep 2016 18:26:16 +0000 (+0200) Subject: MEDIUM: server: add a new init-addr server line setting X-Git-Tag: v1.7-dev6~26 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=25938278b76179a46af79fbdcd51714b2ed54777;p=thirdparty%2Fhaproxy.git MEDIUM: server: add a new init-addr server line setting This new setting supports a comma-delimited list of methods used to resolve the server's FQDN to an IP address. Currently supported methods are "libc" (use the regular libc's resolver) and "last" (use the last known valid address found in the state file). The list is implemented in a 32-bit integer, because each init-addr method only requires 3 bits. The last one must always be SRV_IADDR_END (0), allowing to store up to 10 methods in a single 32 bit integer. Note: the doc is provided at the end of this series. --- diff --git a/include/proto/server.h b/include/proto/server.h index 64ae696f09..f2cca94c11 100644 --- a/include/proto/server.h +++ b/include/proto/server.h @@ -229,6 +229,21 @@ static inline void srv_adm_set_ready(struct server *s) srv_clr_admin_flag(s, SRV_ADMF_FMAINT); } +/* appends an initaddr method to the existing list. Returns 0 on failure. */ +static inline int srv_append_initaddr(unsigned int *list, enum srv_initaddr addr) +{ + int shift = 0; + + while (shift + 3 < 32 && (*list >> shift)) + shift += 3; + + if (shift + 3 > 32) + return 0; + + *list |= addr << shift; + return 1; +} + #endif /* _PROTO_SERVER_H */ /* diff --git a/include/types/server.h b/include/types/server.h index 57971a2eb2..f5aebb11bc 100644 --- a/include/types/server.h +++ b/include/types/server.h @@ -84,6 +84,20 @@ enum srv_admin { SRV_ADMF_RMAINT = 0x20, /* the server is down because of an IP address resolution failure */ }; +/* options for servers' "init-addr" parameter + * this parameter may be used to drive HAProxy's behavior when parsing a server + * address at start up time. + * These values are stored as a list into an integer ordered from first to last + * starting with the lowest to highest bits. SRV_IADDR_END (0) is used to + * indicate the end of the list. 3 bits are enough to store each value. + */ +enum srv_initaddr { + SRV_IADDR_END = 0, /* end of the list */ + SRV_IADDR_NONE = 1, /* the server won't have any address at start up */ + SRV_IADDR_LIBC = 2, /* address set using the libc DNS resolver */ + SRV_IADDR_LAST = 3, /* we set the IP address found in state-file for this server */ +}; + /* server-state-file version */ #define SRV_STATE_FILE_VERSION 1 #define SRV_STATE_FILE_VERSION_MIN 1 @@ -231,6 +245,7 @@ struct server { char *lastaddr; /* the address string provided by the server-state file */ struct dns_resolution *resolution; /* server name resolution */ struct dns_options dns_opts; + unsigned int init_addr_methods; /* initial address setting, 3-bit per method, ends at 0, enough to store 10 entries */ #ifdef USE_OPENSSL int use_ssl; /* ssl enabled */ diff --git a/src/server.c b/src/server.c index f2e419daec..9da8b27a37 100644 --- a/src/server.c +++ b/src/server.c @@ -1113,6 +1113,8 @@ int parse_server(const char *file, int linenum, char **args, struct proxy *curpr curproxy->defsrv.dns_opts.pref_net, sizeof(newsrv->dns_opts.pref_net)); newsrv->dns_opts.pref_net_nb = curproxy->defsrv.dns_opts.pref_net_nb; + newsrv->init_addr_methods = curproxy->defsrv.init_addr_methods; + newsrv->init_addr = curproxy->defsrv.init_addr; cur_arg = 3; } else { @@ -1161,6 +1163,40 @@ int parse_server(const char *file, int linenum, char **args, struct proxy *curpr newsrv->cklen = strlen(args[cur_arg + 1]); cur_arg += 2; } + else if (!strcmp(args[cur_arg], "init-addr")) { + char *p, *end; + int done; + + newsrv->init_addr_methods = 0; + memset(&newsrv->init_addr, 0, sizeof(newsrv->init_addr)); + + for (p = args[cur_arg + 1]; *p; p = end) { + /* cut on next comma */ + for (end = p; *end && *end != ','; end++); + if (*end) + *(end++) = 0; + + if (!strcmp(p, "libc")) { + done = srv_append_initaddr(&newsrv->init_addr_methods, SRV_IADDR_LIBC); + } + else if (!strcmp(p, "last")) { + done = srv_append_initaddr(&newsrv->init_addr_methods, SRV_IADDR_LAST); + } + else { + Alert("parsing [%s:%d]: '%s' : unknown init-addr method '%s', supported methods are 'libc', 'last'.\n", + file, linenum, args[cur_arg], p); + err_code |= ERR_ALERT | ERR_FATAL; + goto out; + } + if (!done) { + Alert("parsing [%s:%d]: '%s' : too many init-addr methods when trying to add '%s'\n", + file, linenum, args[cur_arg], p); + err_code |= ERR_ALERT | ERR_FATAL; + goto out; + } + } + cur_arg += 2; + } else if (!defsrv && !strcmp(args[cur_arg], "redir")) { newsrv->rdr_pfx = strdup(args[cur_arg + 1]); newsrv->rdr_len = strlen(args[cur_arg + 1]);