]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MEDIUM: server: add a new init-addr server line setting
authorBaptiste Assmann <bedis9@gmail.com>
Wed, 21 Sep 2016 18:26:16 +0000 (20:26 +0200)
committerWilly Tarreau <w@1wt.eu>
Wed, 9 Nov 2016 14:30:47 +0000 (15:30 +0100)
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.

include/proto/server.h
include/types/server.h
src/server.c

index 64ae696f093d64c9c3e9ca274abfe53841f0d842..f2cca94c11f3ebcdeb9a03ca1748a646a1ad76c8 100644 (file)
@@ -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 */
 
 /*
index 57971a2eb2a5c38d094e1e8e599bccbc03689e69..f5aebb11bce506f791342e08bd38b72b0f4cd564 100644 (file)
@@ -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 */
index f2e419daec99c271f1a81bce942556129e62e990..9da8b27a37e420928524e7b3a42dfbd56bf87f91 100644 (file)
@@ -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]);