From: Willy Tarreau Date: Wed, 26 Aug 2020 08:30:09 +0000 (+0200) Subject: MEDIUM: reload: stop passing listener options along with FDs X-Git-Tag: v2.3-dev4~74 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=cf1f193624acb9d5a52f40375bb445e5438dd89e;p=thirdparty%2Fhaproxy.git MEDIUM: reload: stop passing listener options along with FDs During a reload operation, we used to send listener options associated with each passed file descriptor. These were passed as binary contents for the size of the "options" field in the struct listener. This means that any flag value change or field size change would be problematic, the former failing to properly grab certain options, the latter possibly causing permanent failures during this operation. Since these two previous commits: MINOR: reload: determine the foreing binding status from the socket BUG/MINOR: reload: detect the OS's v6only status before choosing an old socket we don't need this anymore as the values are determined from the file descriptor itself. Let's just turn the previous 32 bits to vestigal space, send them as zeroes and ignore them on receipt. The only possible side effect is if someone would want to roll back from a 2.3 to 2.2 or earlier, such options might be ignored during this reload. But other forthcoming changes might make this fail as well anyway so that's not a reason for keeping this behavior. --- diff --git a/src/cli.c b/src/cli.c index da6932f138..3783bd6eae 100644 --- a/src/cli.c +++ b/src/cli.c @@ -1639,9 +1639,10 @@ inline static int _getsocks_gen_send(struct proxy *px, int sendfd, int *tmpfd, s curoff += len; } else tmpbuf[curoff++] = 0; - memcpy(tmpbuf + curoff, &l->options, - sizeof(l->options)); - curoff += sizeof(l->options); + + /* we used to send the listener options here before 2.3 */ + memset(tmpbuf + curoff, 0, sizeof(int)); + curoff += sizeof(int); i++; } else @@ -1785,7 +1786,7 @@ static int _getsocks(char **args, char *payload, struct appctx *appctx, void *pr * The namespace name, if any * Size of the interface name (or 0 if none), as an unsigned char * The interface name, if any - * Listener options, as an int. + * 32 bits of zeroes (used to be listener options). */ /* We will send sockets MAX_SEND_FD per MAX_SEND_FD, allocate a * buffer big enough to store the socket information. diff --git a/src/haproxy.c b/src/haproxy.c index 5b3252256c..a8d27f84e1 100644 --- a/src/haproxy.c +++ b/src/haproxy.c @@ -1295,34 +1295,30 @@ static int get_old_sockets(const char *unixsocket) ha_warning("Inconsistency while transferring sockets\n"); goto out; } - memcpy(&xfer_sock->options, &tmpbuf[curoff], - sizeof(xfer_sock->options)); - curoff += sizeof(xfer_sock->options); + + /* we used to have 32 bits of listener options here but we don't + * use them anymore. + */ + curoff += sizeof(int); /* determine the foreign status directly from the socket itself */ - xfer_sock->options &= ~LI_O_FOREIGN; if (tcp_is_foreign(fd, xfer_sock->addr.ss_family)) xfer_sock->options |= LI_O_FOREIGN; /* keep only the v6only flag depending on what's currently * active on the socket, and always drop the v4v6 one. */ +#if defined(IPV6_V6ONLY) { int val = 0; -#if defined(IPV6_V6ONLY) socklen_t len = sizeof(val); if (xfer_sock->addr.ss_family == AF_INET6 && - getsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &val, &len) != 0) - val = 0; -#endif - - if (val) + getsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &val, &len) == 0 && + val > 0) xfer_sock->options |= LI_O_V6ONLY; - else - xfer_sock->options &= ~LI_O_V6ONLY; - xfer_sock->options &= ~LI_O_V4V6; } +#endif xfer_sock->fd = fd; if (xfer_sock_list)