]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MEDIUM: log/balance: support FQDN for UDP log servers
authorAurelien DARRAGON <adarragon@haproxy.com>
Thu, 9 Nov 2023 15:57:01 +0000 (16:57 +0100)
committerChristopher Faulet <cfaulet@haproxy.com>
Wed, 29 Nov 2023 07:59:27 +0000 (08:59 +0100)
In previous log backend implementation, we created a pseudo log target
for each declared log server, and we made the log target's address point
to the actual server address to save some time and prevent unecessary
copies.

But this was done without knowing that when FQDN is involved (more broadly
when dns/resolution is involved), the "port" part of server addr should
not be relied upon, and we should explicitly use ->svc_port for that
purpose.

With that in mind and thanks to the previous commit, some changes were
required: we allocate a dedicated addr within the log target when target
is in DGRAM mode. The addr is first initialized with known values and it
is then updated automatically by _srv_set_inetaddr() during runtime.
(the change is atomic so readers don't need to worry about it)

addr from server "log target" (INET/DGRAM mode) is made of the combination
of server's address (lacking the port part) and server's svc_port.

include/haproxy/log.h
src/log.c
src/server.c

index 497b486eeb67c476014df3c64f6ae4bd06411e18..d36e1840f618c5ae7947f8382be018fb53059dde 100644 (file)
@@ -91,6 +91,7 @@ int postresolve_logger_list(struct list *loggers, const char *section, const cha
 
 struct logger *dup_logger(struct logger *def);
 void free_logger(struct logger *logger);
+void deinit_log_target(struct log_target *target);
 
 /* Parse "log" keyword and update the linked list. */
 int parse_logger(char **args, struct list *loggers, int do_del, const char *file, int linenum, char **err);
index d77f462ee04c32d7fd2406eefeb6e9f108cd980a..96f53bc49378697ec1afaafafe34fd0e0ec920c9 100644 (file)
--- a/src/log.c
+++ b/src/log.c
@@ -745,7 +745,7 @@ static inline void init_log_target(struct log_target *target)
        target->resolv_name = NULL;
 }
 
-static void deinit_log_target(struct log_target *target)
+void deinit_log_target(struct log_target *target)
 {
        ha_free(&target->addr);
        if (!(target->flags & LOG_TARGET_FL_RESOLVED))
@@ -1054,15 +1054,33 @@ static int postcheck_log_backend(struct proxy *be)
                        err_code |= ERR_ALERT | ERR_FATAL;
                        goto end;
                }
-               srv->log_target->addr = &srv->addr;
-               if (srv->addr_type.proto_type == PROTO_TYPE_DGRAM)
+               init_log_target(srv->log_target);
+               if (srv->addr_type.proto_type == PROTO_TYPE_DGRAM) {
                        srv->log_target->type = LOG_TARGET_DGRAM;
+                       /* Try to allocate log target addr (only used in DGRAM mode) */
+                       srv->log_target->addr = calloc(1, sizeof(*srv->log_target->addr));
+                       if (!srv->log_target->addr) {
+                               memprintf(&msg, "memory error when allocating log server '%s'\n", srv->id);
+                               err_code |= ERR_ALERT | ERR_FATAL;
+                               goto end;
+                       }
+                       /* We must initialize it with known addr:svc_port, it will then
+                        * be updated automatically by the server API for runtime changes
+                        */
+                       ipcpy(&srv->addr, srv->log_target->addr);
+                       set_host_port(srv->log_target->addr, srv->svc_port);
+               }
                else {
                        /* for now BUFFER type only supports TCP server to it's almost
-                        * explicit. This will require ring buffer creation during log
-                        * postresolving step.
+                        * explicit
                         */
                        srv->log_target->type = LOG_TARGET_BUFFER;
+                       srv->log_target->sink = sink_new_from_srv(srv, "log backend");
+                       if (!srv->log_target->sink) {
+                               memprintf(&msg, "error when creating sink from '%s' log server", srv->id);
+                               err_code |= ERR_ALERT | ERR_FATAL;
+                               goto end;
+                       }
                }
 
                if (target_type == -1)
@@ -1073,14 +1091,7 @@ static int postcheck_log_backend(struct proxy *be)
                        err_code |= ERR_ALERT | ERR_FATAL;
                        goto end;
                }
-               if (target_type == LOG_TARGET_BUFFER) {
-                       srv->log_target->sink = sink_new_from_srv(srv, "log backend");
-                       if (!srv->log_target->sink) {
-                               memprintf(&msg, "error when creating sink from '%s' log server", srv->id);
-                               err_code |= ERR_ALERT | ERR_FATAL;
-                               goto end;
-                       }
-               }
+               srv->log_target->flags |= LOG_TARGET_FL_RESOLVED;
                srv->cur_eweight = 1; /* ignore weights, all servers have the same weight */
                _log_backend_srv_queue(srv);
                srv = srv->next;
index 8ff084a9d4aa75b688f2d6099bd4c6ecb4e91679..c854fc1b7d526b5cddd61da3f16e82b19adba5e6 100644 (file)
@@ -177,6 +177,11 @@ void _srv_set_inetaddr(struct server *srv, const struct sockaddr_storage *addr,
 {
        ipcpy(addr, &srv->addr);
        srv->svc_port = svc_port;
+       if (srv->log_target && srv->log_target->type == LOG_TARGET_DGRAM) {
+               /* server is used as a log target, manually update log target addr for DGRAM */
+               ipcpy(addr, srv->log_target->addr);
+               set_host_port(srv->log_target->addr, svc_port);
+       }
 }
 
 /*
@@ -2819,7 +2824,10 @@ void srv_free_params(struct server *srv)
        free(srv->resolvers_id);
        free(srv->addr_node.key);
        free(srv->lb_nodes);
-       free(srv->log_target);
+       if (srv->log_target) {
+               deinit_log_target(srv->log_target);
+               free(srv->log_target);
+       }
 
        if (xprt_get(XPRT_SSL) && xprt_get(XPRT_SSL)->destroy_srv)
                xprt_get(XPRT_SSL)->destroy_srv(srv);