]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: diag: diag if servers use the same cookie value
authorAmaury Denoyelle <adenoyelle@haproxy.com>
Tue, 30 Mar 2021 15:35:19 +0000 (17:35 +0200)
committerAmaury Denoyelle <adenoyelle@haproxy.com>
Thu, 1 Apr 2021 16:03:37 +0000 (18:03 +0200)
Add a diagnostic to check that two servers of the same backend does not
use the same cookie value. Ignore backup servers as it is quite common
for them to share a cookie value with a primary one.

src/cfgdiag.c

index 35c8e67d9598d2e43786332d37e9751c7273448b..a06ae0fe9217fe66aa6fb8b63910c9e9e69e36a8 100644 (file)
@@ -1,8 +1,12 @@
 #include <stdarg.h>
 #include <stdlib.h>
 
+#include <import/ebistree.h>
+
 #include <haproxy/cfgdiag.h>
 #include <haproxy/log.h>
+#include <haproxy/proxy.h>
+#include <haproxy/server.h>
 
 /* Use this fonction to emit diagnostic.
  * This can be used as a shortcut to set value pointed by <ret> to 1 at the
@@ -33,6 +37,51 @@ static inline void *diag_alloc(size_t size)
        return out;
 }
 
+/* Checks that two servers from the same backend does not share the same cookie
+ * value. Backup servers are not taken into account as it can be quite common to
+ * share cookie values in this case.
+ */
+static void check_server_cookies(int *ret)
+{
+       struct cookie_entry {
+               struct ebpt_node node;
+       };
+
+       struct proxy  *px;
+       struct server *srv;
+
+       struct eb_root cookies_tree = EB_ROOT_UNIQUE;
+       struct ebpt_node *cookie_node;
+       struct cookie_entry *cookie_entry;
+       struct ebpt_node *node;
+
+       for (px = proxies_list; px; px = px->next) {
+               for (srv = px->srv; srv; srv = srv->next) {
+                       /* do not take into account backup servers */
+                       if (!srv->cookie || (srv->flags & SRV_F_BACKUP))
+                               continue;
+
+                       cookie_node = ebis_lookup(&cookies_tree, srv->cookie);
+                       if (cookie_node) {
+                               diag_warning(ret, "parsing [%s:%d] : 'server %s' : same cookie value is set for a previous non-backup server in the same backend, it may break connection persistence\n",
+                                            srv->conf.file, srv->conf.line, srv->id);
+                               continue;
+                       }
+
+                       cookie_entry = diag_alloc(sizeof(*cookie_entry));
+                       cookie_entry->node.key = srv->cookie;
+                       ebis_insert(&cookies_tree, &cookie_entry->node);
+               }
+
+               /* clear the tree and free its entries */
+               while ((node = ebpt_first(&cookies_tree))) {
+                       cookie_entry = ebpt_entry(node, struct cookie_entry, node);
+                       eb_delete(&node->node);
+                       free(cookie_entry);
+               }
+       }
+}
+
 /* Placeholder to execute various diagnostic checks after the configuration file
  * has been fully parsed. It will output a warning for each diagnostic found.
  *
@@ -41,5 +90,8 @@ static inline void *diag_alloc(size_t size)
 int cfg_run_diagnostics()
 {
        int ret = 0;
+
+       check_server_cookies(&ret);
+
        return ret;
 }