diff --git a/include/proto/server.h b/include/proto/server.h index 64ae696f0..f2cca94c1 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 57971a2eb..f5aebb11b 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 f2e419dae..9da8b27a3 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]);