From 2f2cb6d08253f036557036d22df41be155e2f091 Mon Sep 17 00:00:00 2001 From: Aurelien DARRAGON Date: Thu, 9 Nov 2023 16:57:01 +0100 Subject: [PATCH] MEDIUM: log/balance: support FQDN for UDP log servers 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 | 1 + src/log.c | 37 ++++++++++++++++++++++++------------- src/server.c | 10 +++++++++- 3 files changed, 34 insertions(+), 14 deletions(-) diff --git a/include/haproxy/log.h b/include/haproxy/log.h index 497b486ee..d36e1840f 100644 --- a/include/haproxy/log.h +++ b/include/haproxy/log.h @@ -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); diff --git a/src/log.c b/src/log.c index d77f462ee..96f53bc49 100644 --- 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; diff --git a/src/server.c b/src/server.c index 8ff084a9d..c854fc1b7 100644 --- a/src/server.c +++ b/src/server.c @@ -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);