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;
|
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
|
* 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
|
* 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 sock_get_src(int fd, struct sockaddr *sa, socklen_t salen, int dir)
|
||||||
{
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
if (dir)
|
if (dir)
|
||||||
return getsockname(fd, sa, &salen);
|
ret = getsockname(fd, sa, &salen);
|
||||||
else
|
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 sock_get_dst(int fd, struct sockaddr *sa, socklen_t salen, int dir)
|
||||||
{
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
if (dir)
|
if (dir)
|
||||||
return getpeername(fd, sa, &salen);
|
ret = getpeername(fd, sa, &salen);
|
||||||
else
|
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
|
/* Try to retrieve exported sockets from worker at CLI <unixsocket>. These
|
||||||
@ -601,20 +641,10 @@ int sock_get_old_sockets(const char *unixsocket)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (xfer_sock->addr.ss_family == AF_UNIX) {
|
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()
|
/* restore effective family if needed, because getsockname()
|
||||||
* only knows about real families:
|
* only knows about real families:
|
||||||
*/
|
*/
|
||||||
if (un->sun_path[0]); // regular UNIX socket, not a custom family
|
sock_restore_unix_family((struct sockaddr_un *)&xfer_sock->addr, socklen);
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user