mirror of
https://git.haproxy.org/git/haproxy.git/
synced 2025-08-07 15:47:01 +02:00
MEDIUM: sock: also restore effective unix family in get_{src,dst}()
As in previous commit, let's push the logic a bit further in order to properly restore the effective UNIX socket type when leveraging get_src() and get_dst() sock functions, since they rely on getpeername() and getsockname() under the hood, both of which will actually loose the effective family and return AF_UNIX for all our custom UNIX sockets. To do this, add sock_restore_unix_family() helper function from the logic implemented in the previous commit, and call this function from get_src() and get_dst() in case of unix socket prior to returning.
This commit is contained in:
parent
ae64444303
commit
d879bf6600
60
src/sock.c
60
src/sock.c
@ -385,6 +385,28 @@ void sock_unbind(struct receiver *rx)
|
||||
rx->fd = -1;
|
||||
}
|
||||
|
||||
/* restore effective family for UNIX type sockets if needed. Indeed since
|
||||
* kernel doesn't know about custom UNIX families (internal to HAproxy),
|
||||
* they lost when leveraging syscalls such as getsockname() or getpeername().
|
||||
*
|
||||
* This function guesses the effective family by analyzing address and address
|
||||
* length as returned by getsockname() and getpeername() calls.
|
||||
*/
|
||||
static void sock_restore_unix_family(struct sockaddr_un *un, socklen_t socklen)
|
||||
{
|
||||
BUG_ON(un->sun_family != AF_UNIX);
|
||||
|
||||
if (un->sun_path[0]); // regular UNIX socket, not a custom family
|
||||
else if (socklen == sizeof(*un))
|
||||
un->sun_family = AF_CUST_ABNS;
|
||||
else {
|
||||
/* not all struct sockaddr_un space is used..
|
||||
* (sun_path is partially filled)
|
||||
*/
|
||||
un->sun_family = AF_CUST_ABNSZ;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Retrieves the source address for the socket <fd>, with <dir> indicating
|
||||
* if we're a listener (=0) or an initiator (!=0). It returns 0 in case of
|
||||
@ -393,10 +415,19 @@ void sock_unbind(struct receiver *rx)
|
||||
*/
|
||||
int sock_get_src(int fd, struct sockaddr *sa, socklen_t salen, int dir)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (dir)
|
||||
return getsockname(fd, sa, &salen);
|
||||
ret = getsockname(fd, sa, &salen);
|
||||
else
|
||||
return getpeername(fd, sa, &salen);
|
||||
ret = getpeername(fd, sa, &salen);
|
||||
|
||||
if (ret)
|
||||
return ret;
|
||||
if (sa->sa_family == AF_UNIX)
|
||||
sock_restore_unix_family((struct sockaddr_un *)sa, salen);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -407,10 +438,19 @@ int sock_get_src(int fd, struct sockaddr *sa, socklen_t salen, int dir)
|
||||
*/
|
||||
int sock_get_dst(int fd, struct sockaddr *sa, socklen_t salen, int dir)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (dir)
|
||||
return getpeername(fd, sa, &salen);
|
||||
ret = getpeername(fd, sa, &salen);
|
||||
else
|
||||
return getsockname(fd, sa, &salen);
|
||||
ret = getsockname(fd, sa, &salen);
|
||||
|
||||
if (ret)
|
||||
return ret;
|
||||
if (sa->sa_family == AF_UNIX)
|
||||
sock_restore_unix_family((struct sockaddr_un *)sa, salen);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Try to retrieve exported sockets from worker at CLI <unixsocket>. These
|
||||
@ -601,20 +641,10 @@ int sock_get_old_sockets(const char *unixsocket)
|
||||
continue;
|
||||
}
|
||||
if (xfer_sock->addr.ss_family == AF_UNIX) {
|
||||
const struct sockaddr_un *un = (const struct sockaddr_un *)&xfer_sock->addr;
|
||||
|
||||
/* restore effective family if needed, because getsockname()
|
||||
* only knows about real families:
|
||||
*/
|
||||
if (un->sun_path[0]); // regular UNIX socket, not a custom family
|
||||
else if (socklen == sizeof(*un))
|
||||
xfer_sock->addr.ss_family = AF_CUST_ABNS;
|
||||
else {
|
||||
/* not all struct sockaddr_un space is used..
|
||||
* (sun_path is partially filled)
|
||||
*/
|
||||
xfer_sock->addr.ss_family = AF_CUST_ABNSZ;
|
||||
}
|
||||
sock_restore_unix_family((struct sockaddr_un *)&xfer_sock->addr, socklen);
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user