]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MEDIUM: server: support track keyword for dynamic servers
authorAmaury Denoyelle <adenoyelle@haproxy.com>
Tue, 13 Jul 2021 08:36:03 +0000 (10:36 +0200)
committerAmaury Denoyelle <adenoyelle@haproxy.com>
Fri, 16 Jul 2021 08:22:58 +0000 (10:22 +0200)
Allow the usage of the 'track' keyword for dynamic servers. On server
deletion, the server is properly removed from the tracking chain to
prevents NULL pointer dereferencing.

doc/management.txt
src/server.c

index 7abfc85fb253bf4bbd0c496732fe070ce8df03f2..4b01ddcb42346f5885cda2c3ecf9cdb44dba9db6 100644 (file)
@@ -1470,6 +1470,11 @@ add server <backend>/<server> [args]*
   init-addr method. This means that no resolution will be undertaken if a FQDN
   is specified as an address, even if the server creation will be validated.
 
+  A dynamic server may use the "track" keyword to follow the check status of
+  another server from the configuration. However, it is not possible to track
+  another dynamic server. This is to ensure that the tracking chain is kept
+  consistent even in the case of dynamic servers deletion.
+
   Here is the list of the currently supported keywords :
 
   - allow-0rtt
@@ -1507,6 +1512,7 @@ add server <backend>/<server> [args]*
   - ssl-min-ver
   - tfo
   - tls-tickets
+  - track
   - usesrc
   - verify
   - verifyhost
index 664e2f4ec563e8453c05e4ca420e8288be34c9fd..5fa3946662b4405211036710a5fe66f4807fa9b9 100644 (file)
@@ -1678,7 +1678,7 @@ static struct srv_kw_list srv_kws = { "ALL", { }, {
        { "source",              srv_parse_source,             -1,  1,  1 }, /* Set the source address to be used to connect to the server */
        { "stick",               srv_parse_stick,               0,  1,  0 }, /* Enable stick-table persistence */
        { "tfo",                 srv_parse_tfo,                 0,  1,  1 }, /* enable TCP Fast Open of server */
-       { "track",               srv_parse_track,               1,  1,  0 }, /* Set the current state of the server, tracking another one */
+       { "track",               srv_parse_track,               1,  1,  1 }, /* Set the current state of the server, tracking another one */
        { "socks4",              srv_parse_socks4,              1,  1,  0 }, /* Set the socks4 proxy of the server*/
        { "usesrc",              srv_parse_usesrc,              0,  1,  1 }, /* safe-guard against usesrc without preceding <source> keyword */
        { "weight",              srv_parse_weight,              1,  1,  1 }, /* Set the load-balancing weight */
@@ -2228,6 +2228,31 @@ void free_server(struct server *srv)
        srv = NULL;
 }
 
+/* Remove a server <srv> from a tracking list if <srv> is tracking another
+ * server. No special care is taken if <srv> is tracked itself by another one :
+ * this situation should be avoided by the caller.
+ *
+ * Not thread-safe.
+ */
+static void release_server_track(struct server *srv)
+{
+       struct server *strack = srv->track;
+       struct server **base;
+
+       if (!strack)
+               return;
+
+       for (base = &strack->trackers; *base; base = &((*base)->tracknext)) {
+               if (*base == srv) {
+                       *base = srv->tracknext;
+                       return;
+               }
+       }
+
+       /* srv not found on the tracking list, this should never happen */
+       BUG_ON(!*base);
+}
+
 /*
  * Parse as much as possible such a range string argument: low[-high]
  * Set <nb_low> and <nb_high> values so that they may be reused by this loop
@@ -4503,6 +4528,11 @@ static int cli_parse_add_server(char **args, char *payload, struct appctx *appct
                }
        }
 
+       if (srv->trackit) {
+               if (srv_apply_track(srv, be))
+                       goto out;
+       }
+
        /* Attach the server to the end of the proxy linked list. Note that this
         * operation is not thread-safe so this is executed under thread
         * isolation.
@@ -4564,8 +4594,11 @@ out:
        if (!usermsgs_empty())
                cli_err(appctx, usermsgs_str());
 
-       if (srv)
+       if (srv) {
+               release_server_track(srv);
                free_server(srv);
+       }
+
        return 1;
 }
 
@@ -4650,6 +4683,10 @@ static int cli_parse_delete_server(char **args, char *payload, struct appctx *ap
                goto out;
        }
 
+       /* remove srv from tracking list */
+       if (srv->track)
+               release_server_track(srv);
+
        /* TODO remove server for check list once 'check' will be implemented for
         * dynamic servers
         */