]> git.kaiwu.me - haproxy.git/commitdiff
MINOR: event_hdl/proxy: publish EVENT_HDL_SUB_PROXY_{ADD,DEL,PUB,UNPUB} events
authorAurelien DARRAGON <adarragon@haproxy.com>
Tue, 6 Oct 2026 19:26:35 +0000 (21:26 +0200)
committerAurelien DARRAGON <adarragon@haproxy.com>
Mon, 12 Oct 2026 07:50:06 +0000 (09:50 +0200)
Proxy events are published in the per-proxy subscription list as well as
global one. EVENT_HDL_SUB_PROXY_ADD is published when proxy is created
(ie: "add backend"), EVENT_HDL_SUB_PROXY_DEL when backend is removed,
EVENT_HDL_SUB_PROXY_PUB when backend is published and
EVENT_HDL_SUB_PROXY_UNPUB when backend is unpublished.

All events provide event_hdl_cb_data_proxy struct, which contains info
about the proxy that triggered the event.

include/haproxy/proxy-t.h
src/proxy.c

index 51c0f3eadfcfefae6a0498d8a3f37ef3e5d7cd18..f9db0482be51983215d0d25e9909e2fed3bc5295 100644 (file)
@@ -549,6 +549,35 @@ struct proxy {
        int totpend;                            /* total number of pending connections on this instance (for stats) */
 };
 
+/* data provided to EVENT_HDL_SUB_PROXY handlers through event_hdl facility */
+struct event_hdl_cb_data_proxy {
+       /* provided by:
+        *   EVENT_HDL_SUB_PROXY_ADD
+        *   EVENT_HDL_SUB_PROXY_DEL
+        */
+       struct {
+               /* safe data can be safely used from both
+                * sync and async handlers
+                * data consistency is guaranteed
+                */
+               char cap;                   /* supported capabilities (PR_CAP_*) */
+               int uuid;                   /* uuid of the proxy */
+               char name[64];              /* id of proxy */
+               char guid[GUID_MAX_LEN + 1];/* GUID global tree node */
+       } safe;
+       struct {
+               /* unsafe data may only be used from sync handlers:
+                * in async mode, data consistency cannot be guaranteed
+                * and unsafe data may already be stale, thus using
+                * it is highly discouraged because it
+                * could lead to undefined behavior (UAF, null dereference...)
+                */
+
+               /* not use yet */
+       } unsafe;
+};
+
+
 struct switching_rule {
        struct list list;                       /* list linked to from the proxy */
        struct acl_cond *cond;                  /* acl condition to meet */
index c70fc9cea88427f557d4733aa378db101b482927..9c4fb5d0ced77b7558317ed77b135ca466d14658 100644 (file)
@@ -566,6 +566,30 @@ enum pr_mode str_to_proxy_mode(const char *mode)
        return PR_MODES;
 }
 
+/* proxy event publishing helper: publish in both global and
+ * proxy dedicated subscription list.
+ */
+#define _proxy_event_hdl_publish(e, d, px)                               \
+        ({                                                               \
+                /* publish in proxy dedicated sub list */                \
+                event_hdl_publish(&px->e_subs, e, EVENT_HDL_CB_DATA(&d));\
+                /* publish in global subscription list */                \
+                event_hdl_publish(NULL, e, EVENT_HDL_CB_DATA(&d)) ;      \
+        })
+
+/* fill common proxy event data members struct
+ * must be called with server lock or under thread isolate
+ */
+static inline void _proxy_event_hdl_prepare(struct event_hdl_cb_data_proxy *cb_data,
+                                            struct proxy *proxy)
+{
+       /* safe data assignments */
+       cb_data->safe.cap = proxy->cap;
+       cb_data->safe.uuid = proxy->uuid;
+       snprintf(cb_data->safe.name, sizeof(cb_data->safe.name), "%s", proxy->id);
+       snprintf(cb_data->safe.guid, sizeof(cb_data->safe.guid), "%s", proxy->guid.key);
+}
+
 /* try to find among known options the one that looks closest to <word> by
  * counting transitions between letters, digits and other characters. Will
  * return the best matching word if found, otherwise NULL. An optional array
@@ -5041,6 +5065,7 @@ static int cli_parse_add_backend(char **args, char *payload, struct appctx *appc
 {
        struct proxy *px, *defpx;
        struct post_proxy_check_fct *ppcf;
+       struct event_hdl_cb_data_proxy e_cb_data;
        const char *be_name, *def_name, *guid = NULL, *err;
        char *msg = NULL;
        enum pr_mode mode = 0;
@@ -5198,6 +5223,11 @@ static int cli_parse_add_backend(char **args, char *payload, struct appctx *appc
         * setup_new_proxy() via alloc_new_proxy().
         */
        main_proxies_register(px);
+
+       /* backend creation cannot fail anymore, time to publish the PROXY_ADD event */
+       _proxy_event_hdl_prepare(&e_cb_data, px);
+       _proxy_event_hdl_publish(EVENT_HDL_SUB_PROXY_ADD, e_cb_data, px);
+
        thread_release();
 
        if (unlikely(!be_supports_dynamic_srv(px, &msg)))
@@ -5302,6 +5332,7 @@ int be_check_for_deletion(const char *bename, struct proxy **pb, const char **pm
 /* Handler for "delete backend". Runs under thread isolation. Always returns 1. */
 static int cli_parse_delete_backend(char **args, char *payload, struct appctx *appctx, void *private)
 {
+       struct event_hdl_cb_data_proxy e_cb_data;
        struct watcher *px_watch;
        struct proxy *px;
        const char *msg;
@@ -5343,6 +5374,10 @@ static int cli_parse_delete_backend(char **args, char *payload, struct appctx *a
         */
        flt_deinit_new_proxy(px);
 
+       /* backend deletion cannot fail anymore, time to publish the PROXY_DEL event */
+       _proxy_event_hdl_prepare(&e_cb_data, px);
+       _proxy_event_hdl_publish(EVENT_HDL_SUB_PROXY_DEL, e_cb_data, px);
+
        thread_release();
 
        ha_notice("Backend deleted.\n");
@@ -5419,6 +5454,7 @@ static int cli_parse_enable_frontend(char **args, char *payload, struct appctx *
 
 static int cli_parse_publish_backend(char **args, char *payload, struct appctx *appctx, void *private)
 {
+       struct event_hdl_cb_data_proxy e_cb_data;
        struct proxy *px;
 
        usermsgs_clr("CLI");
@@ -5435,6 +5471,11 @@ static int cli_parse_publish_backend(char **args, char *payload, struct appctx *
 
        thread_isolate();
        px->flags &= ~PR_FL_BE_UNPUBLISHED;
+
+       /* backend publish cannot fail anymore, time to publish the PROXY_PUB event */
+       _proxy_event_hdl_prepare(&e_cb_data, px);
+       _proxy_event_hdl_publish(EVENT_HDL_SUB_PROXY_PUB, e_cb_data, px);
+
        thread_release();
 
        ha_notice("Backend published.\n");
@@ -5443,6 +5484,7 @@ static int cli_parse_publish_backend(char **args, char *payload, struct appctx *
 
 static int cli_parse_unpublish_backend(char **args, char *payload, struct appctx *appctx, void *private)
 {
+       struct event_hdl_cb_data_proxy e_cb_data;
        struct proxy *px;
 
        usermsgs_clr("CLI");
@@ -5459,6 +5501,11 @@ static int cli_parse_unpublish_backend(char **args, char *payload, struct appctx
 
        thread_isolate();
        px->flags |= PR_FL_BE_UNPUBLISHED;
+
+       /* backend unpublish cannot fail anymore, time to publish the PROXY_UNPUB event */
+       _proxy_event_hdl_prepare(&e_cb_data, px);
+       _proxy_event_hdl_publish(EVENT_HDL_SUB_PROXY_UNPUB, e_cb_data, px);
+
        thread_release();
 
        ha_notice("Backend unpublished.\n");