From a5b325f92c909f9976fcae2b2890eccde244dd40 Mon Sep 17 00:00:00 2001 From: Willy Tarreau Date: Fri, 4 Sep 2020 16:44:20 +0200 Subject: [PATCH] MINOR: protocol: add a real family for existing FDs At some places (log fd@XXX, bind fd@XXX) we support using an explicit file descriptor number, that is placed into the sockaddr for later use. The problem is that till now it was done with an AF_UNSPEC family, which is also used for other situations like missing info or rings (for logs). Let's create an "official" family AF_CUST_EXISTING_FD for this case so that we are certain the FD can be found in the address when it is set. --- include/haproxy/protocol-t.h | 9 +++++---- src/cfgparse.c | 2 +- src/log.c | 27 ++++++++++++++++----------- src/tools.c | 7 ++++--- 4 files changed, 26 insertions(+), 19 deletions(-) diff --git a/include/haproxy/protocol-t.h b/include/haproxy/protocol-t.h index 4f5aac221e..cacd3fc316 100644 --- a/include/haproxy/protocol-t.h +++ b/include/haproxy/protocol-t.h @@ -37,10 +37,11 @@ struct connection; * Custom network family for str2sa parsing. Should be ok to do this since * sa_family_t is standardized as an unsigned integer */ -#define AF_CUST_SOCKPAIR (AF_MAX + 1) -#define AF_CUST_UDP4 (AF_MAX + 2) -#define AF_CUST_UDP6 (AF_MAX + 3) -#define AF_CUST_MAX (AF_MAX + 4) +#define AF_CUST_EXISTING_FD (AF_MAX + 1) +#define AF_CUST_SOCKPAIR (AF_MAX + 2) +#define AF_CUST_UDP4 (AF_MAX + 3) +#define AF_CUST_UDP6 (AF_MAX + 4) +#define AF_CUST_MAX (AF_MAX + 5) /* * Test in case AF_CUST_MAX overflows the sa_family_t (unsigned int) diff --git a/src/cfgparse.c b/src/cfgparse.c index cc5f9f76ec..8effc83110 100644 --- a/src/cfgparse.c +++ b/src/cfgparse.c @@ -156,7 +156,7 @@ int str2listener(char *str, struct proxy *curproxy, struct bind_conf *bind_conf, goto fail; } } - else if (ss2->ss_family == AF_UNSPEC) { + else if (ss2->ss_family == AF_CUST_EXISTING_FD) { socklen_t addr_len; inherited = 1; diff --git a/src/log.c b/src/log.c index 702f443d97..e1257132aa 100644 --- a/src/log.c +++ b/src/log.c @@ -1754,14 +1754,14 @@ static inline void __do_send_log(struct logsrv *logsrv, int nblogger, int level, while (size && (message[size-1] == '\n' || (message[size-1] == 0))) size--; - if (logsrv->type == LOG_TARGET_FD) { - /* the socket's address is a file descriptor */ - plogfd = (int *)&((struct sockaddr_in *)&logsrv->addr)->sin_addr.s_addr; - } - else if (logsrv->type == LOG_TARGET_BUFFER) { + if (logsrv->type == LOG_TARGET_BUFFER) { plogfd = NULL; goto send; } + else if (logsrv->addr.ss_family == AF_CUST_EXISTING_FD) { + /* the socket's address is a file descriptor */ + plogfd = (int *)&((struct sockaddr_in *)&logsrv->addr)->sin_addr.s_addr; + } else if (logsrv->addr.ss_family == AF_UNIX) plogfd = &logfdunix; else @@ -1790,18 +1790,23 @@ static inline void __do_send_log(struct logsrv *logsrv, int nblogger, int level, msg_header = build_log_header(logsrv->format, level, facility, metadata, &nbelem); send: - if (logsrv->addr.ss_family == AF_UNSPEC) { + if (logsrv->type == LOG_TARGET_BUFFER) { struct ist msg; msg = ist2(message, size); if (msg.len > logsrv->maxlen) msg.len = logsrv->maxlen; - if (logsrv->type == LOG_TARGET_BUFFER) { - sent = sink_write(logsrv->sink, &msg, 1, level, logsrv->facility, metadata); - } - else /* LOG_TARGET_FD */ - sent = fd_write_frag_line(*plogfd, logsrv->maxlen, msg_header, nbelem, &msg, 1, 1); + sent = sink_write(logsrv->sink, &msg, 1, level, logsrv->facility, metadata); + } + else if (logsrv->addr.ss_family == AF_CUST_EXISTING_FD) { + struct ist msg; + + msg = ist2(message, size); + if (msg.len > logsrv->maxlen) + msg.len = logsrv->maxlen; + + sent = fd_write_frag_line(*plogfd, logsrv->maxlen, msg_header, nbelem, &msg, 1, 1); } else { int i = 0; diff --git a/src/tools.c b/src/tools.c index 803afab9e9..d948993b25 100644 --- a/src/tools.c +++ b/src/tools.c @@ -861,7 +861,8 @@ struct sockaddr_storage *str2ip2(const char *str, struct sockaddr_storage *sa, i * was filled, indicating the need for a resolution. * * When a file descriptor is passed, its value is put into the s_addr part of - * the address when cast to sockaddr_in and the address family is AF_UNSPEC. + * the address when cast to sockaddr_in and the address family is + * AF_CUST_EXISTING_FD. */ struct sockaddr_storage *str2sa_range(const char *str, int *port, int *low, int *high, char **err, const char *pfx, char **fqdn, int resolve) { @@ -957,8 +958,8 @@ struct sockaddr_storage *str2sa_range(const char *str, int *port, int *low, int goto out; } - /* we return AF_UNSPEC if we use a file descriptor number */ - ss.ss_family = AF_UNSPEC; + /* we return AF_CUST_EXISTING_FD if we use a file descriptor number */ + ss.ss_family = AF_CUST_EXISTING_FD; } else if (ss.ss_family == AF_UNIX) { struct sockaddr_un *un = (struct sockaddr_un *)&ss; -- 2.39.5