mirror of
http://git.haproxy.org/git/haproxy.git/
synced 2024-12-19 01:54:37 +00:00
MINOR: reload: determine the foreing binding status from the socket
Let's not look at the listener options passed by the original process and determine from the socket itself whether it is configured for transparent mode or not. This is cleaner and safer, and doesn't rely on flag values that could possibly change between versions.
This commit is contained in:
parent
bca5a4e0a8
commit
bf3b06b03d
@ -33,6 +33,7 @@ int tcp_pause_listener(struct listener *l);
|
||||
int tcp_connect_server(struct connection *conn, int flags);
|
||||
int tcp_get_src(int fd, struct sockaddr *sa, socklen_t salen, int dir);
|
||||
int tcp_get_dst(int fd, struct sockaddr *sa, socklen_t salen, int dir);
|
||||
int tcp_is_foreign(int fd, sa_family_t family);
|
||||
|
||||
/* Export some samples. */
|
||||
int smp_fetch_src(const struct arg *args, struct sample *smp, const char *kw, void *private);
|
||||
|
@ -110,6 +110,7 @@
|
||||
#include <haproxy/peers.h>
|
||||
#include <haproxy/pool.h>
|
||||
#include <haproxy/protocol.h>
|
||||
#include <haproxy/proto_tcp.h>
|
||||
#include <haproxy/proxy.h>
|
||||
#include <haproxy/regex.h>
|
||||
#include <haproxy/sample.h>
|
||||
@ -1298,6 +1299,11 @@ static int get_old_sockets(const char *unixsocket)
|
||||
sizeof(xfer_sock->options));
|
||||
curoff += sizeof(xfer_sock->options);
|
||||
|
||||
/* 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.
|
||||
*/
|
||||
|
@ -681,6 +681,65 @@ static int compare_sockaddr(struct sockaddr_storage *a, struct sockaddr_storage
|
||||
|
||||
}
|
||||
|
||||
/* Returns true if the passed FD corresponds to a socket bound with LI_O_FOREIGN
|
||||
* according to the various supported socket options. The socket's address family
|
||||
* must be passed in <family>.
|
||||
*/
|
||||
int tcp_is_foreign(int fd, sa_family_t family)
|
||||
{
|
||||
int val __maybe_unused;
|
||||
socklen_t len __maybe_unused;
|
||||
|
||||
switch (family) {
|
||||
case AF_INET:
|
||||
#if defined(IP_TRANSPARENT)
|
||||
val = 0; len = sizeof(val);
|
||||
if (getsockopt(fd, SOL_IP, IP_TRANSPARENT, &val, &len) == 0 && val)
|
||||
return 1;
|
||||
#endif
|
||||
#if defined(IP_FREEBIND)
|
||||
val = 0; len = sizeof(val);
|
||||
if (getsockopt(fd, SOL_IP, IP_FREEBIND, &val, &len) == 0 && val)
|
||||
return 1;
|
||||
#endif
|
||||
#if defined(IP_BINDANY)
|
||||
val = 0; len = sizeof(val);
|
||||
if (getsockopt(fd, IPPROTO_IP, IP_BINDANY, &val, &len) == 0 && val)
|
||||
return 1;
|
||||
#endif
|
||||
#if defined(SO_BINDANY)
|
||||
val = 0; len = sizeof(val);
|
||||
if (getsockopt(fd, SOL_SOCKET, SO_BINDANY, &val, &len) == 0 && val)
|
||||
return 1;
|
||||
#endif
|
||||
break;
|
||||
|
||||
case AF_INET6:
|
||||
#if defined(IPV6_TRANSPARENT) && defined(SOL_IPV6)
|
||||
val = 0; len = sizeof(val);
|
||||
if (getsockopt(fd, SOL_IPV6, IPV6_TRANSPARENT, &val, &len) == 0 && val)
|
||||
return 1;
|
||||
#endif
|
||||
#if defined(IP_FREEBIND)
|
||||
val = 0; len = sizeof(val);
|
||||
if (getsockopt(fd, SOL_IP, IP_FREEBIND, &val, &len) == 0 && val)
|
||||
return 1;
|
||||
#endif
|
||||
#if defined(IPV6_BINDANY)
|
||||
val = 0; len = sizeof(val);
|
||||
if (getsockopt(fd, IPPROTO_IPV6, IPV6_BINDANY, &val, &len) == 0 && val)
|
||||
return 1;
|
||||
#endif
|
||||
#if defined(SO_BINDANY)
|
||||
val = 0; len = sizeof(val);
|
||||
if (getsockopt(fd, SOL_SOCKET, SO_BINDANY, &val, &len) == 0 && val)
|
||||
return 1;
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* sets the v6only_default flag according to the OS' default settings; for
|
||||
* simplicity it's set to zero if not supported.
|
||||
*/
|
||||
|
Loading…
Reference in New Issue
Block a user