mirror of
https://git.haproxy.org/git/haproxy.git/
synced 2025-08-06 23:27:04 +02:00
MINOR: sock_inet: implement sock_inet_get_dst()
This one is common to the TCPv4 and UDPv4 code, it retrieves the destination address of a socket, taking care of the possiblity that for an incoming connection the traffic was possibly redirected. The TCP and UDP definitions were updated to rely on it and remove duplicated code.
This commit is contained in:
parent
f172558b27
commit
c5a94c936b
@ -31,7 +31,6 @@
|
||||
int tcp_bind_socket(int fd, int flags, struct sockaddr_storage *local, struct sockaddr_storage *remote);
|
||||
int tcp_pause_listener(struct listener *l);
|
||||
int tcp_connect_server(struct connection *conn, int flags);
|
||||
int tcp_get_dst(int fd, struct sockaddr *sa, socklen_t salen, int dir);
|
||||
int tcp_is_foreign(int fd, sa_family_t family);
|
||||
|
||||
#endif /* _HAPROXY_PROTO_TCP_H */
|
||||
|
@ -29,6 +29,7 @@ int udp_pause_listener(struct listener *l);
|
||||
int udp_get_src(int fd, struct sockaddr *sa, socklen_t salen, int dir);
|
||||
int udp6_get_src(int fd, struct sockaddr *sa, socklen_t salen, int dir);
|
||||
int udp_get_dst(int fd, struct sockaddr *sa, socklen_t salen, int dir);
|
||||
int udp6_get_dst(int fd, struct sockaddr *sa, socklen_t salen, int dir);
|
||||
|
||||
#endif /* _PROTO_PROTO_UDP_H */
|
||||
|
||||
|
@ -29,5 +29,6 @@
|
||||
|
||||
int sock_inet4_addrcmp(const struct sockaddr_storage *a, const struct sockaddr_storage *b);
|
||||
int sock_inet6_addrcmp(const struct sockaddr_storage *a, const struct sockaddr_storage *b);
|
||||
int sock_inet_get_dst(int fd, struct sockaddr *sa, socklen_t salen, int dir);
|
||||
|
||||
#endif /* _HAPROXY_SOCK_INET_H */
|
||||
|
@ -65,7 +65,7 @@ static struct protocol proto_tcpv4 = {
|
||||
.unbind_all = unbind_all_listeners,
|
||||
.enable_all = enable_all_listeners,
|
||||
.get_src = sock_get_src,
|
||||
.get_dst = tcp_get_dst,
|
||||
.get_dst = sock_inet_get_dst,
|
||||
.pause = tcp_pause_listener,
|
||||
.add = tcpv4_add_listener,
|
||||
.addrcmp = sock_inet4_addrcmp,
|
||||
@ -91,7 +91,7 @@ static struct protocol proto_tcpv6 = {
|
||||
.unbind_all = unbind_all_listeners,
|
||||
.enable_all = enable_all_listeners,
|
||||
.get_src = sock_get_src,
|
||||
.get_dst = tcp_get_dst,
|
||||
.get_dst = sock_get_dst,
|
||||
.pause = tcp_pause_listener,
|
||||
.add = tcpv6_add_listener,
|
||||
.addrcmp = sock_inet6_addrcmp,
|
||||
@ -581,38 +581,6 @@ int tcp_connect_server(struct connection *conn, int flags)
|
||||
return SF_ERR_NONE; /* connection is OK */
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Retrieves the original destination address for the socket <fd>, with <dir>
|
||||
* indicating if we're a listener (=0) or an initiator (!=0). In the case of a
|
||||
* listener, if the original destination address was translated, the original
|
||||
* address is retrieved. It returns 0 in case of success, -1 in case of error.
|
||||
* The socket's source address is stored in <sa> for <salen> bytes.
|
||||
*/
|
||||
int tcp_get_dst(int fd, struct sockaddr *sa, socklen_t salen, int dir)
|
||||
{
|
||||
if (dir)
|
||||
return getpeername(fd, sa, &salen);
|
||||
else {
|
||||
int ret = getsockname(fd, sa, &salen);
|
||||
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
#if defined(USE_TPROXY) && defined(SO_ORIGINAL_DST)
|
||||
/* For TPROXY and Netfilter's NAT, we can retrieve the original
|
||||
* IPv4 address before DNAT/REDIRECT. We must not do that with
|
||||
* other families because v6-mapped IPv4 addresses are still
|
||||
* reported as v4.
|
||||
*/
|
||||
if (((struct sockaddr_storage *)sa)->ss_family == AF_INET
|
||||
&& getsockopt(fd, SOL_IP, SO_ORIGINAL_DST, sa, &salen) == 0)
|
||||
return 0;
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
/* 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>.
|
||||
|
@ -87,7 +87,7 @@ static struct protocol proto_udp6 = {
|
||||
.unbind_all = unbind_all_listeners,
|
||||
.enable_all = enable_all_listeners,
|
||||
.get_src = udp6_get_src,
|
||||
.get_dst = udp_get_dst,
|
||||
.get_dst = udp6_get_dst,
|
||||
.pause = udp_pause_listener,
|
||||
.add = udp6_add_listener,
|
||||
.addrcmp = sock_inet6_addrcmp,
|
||||
@ -142,34 +142,27 @@ int udp_get_dst(int fd, struct sockaddr *sa, socklen_t salen, int dir)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (dir)
|
||||
ret = getpeername(fd, sa, &salen);
|
||||
else {
|
||||
ret = getsockname(fd, sa, &salen);
|
||||
ret = sock_inet_get_dst(fd, sa, salen, dir);
|
||||
if (!ret)
|
||||
sa->sa_family = AF_CUST_UDP4;
|
||||
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
#if defined(USE_TPROXY) && defined(SO_ORIGINAL_DST)
|
||||
/* For TPROXY and Netfilter's NAT, we can retrieve the original
|
||||
* IPv4 address before DNAT/REDIRECT. We must not do that with
|
||||
* other families because v6-mapped IPv4 addresses are still
|
||||
* reported as v4.
|
||||
*/
|
||||
if (((struct sockaddr_storage *)sa)->ss_family == AF_INET
|
||||
&& getsockopt(fd, SOL_IP, SO_ORIGINAL_DST, sa, &salen) == 0) {
|
||||
sa->sa_family = AF_CUST_UDP4;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
/*
|
||||
* Retrieves the original destination address for the socket <fd>, with <dir>
|
||||
* indicating if we're a listener (=0) or an initiator (!=0). In the case of a
|
||||
* listener, if the original destination address was translated, the original
|
||||
* address is retrieved. It returns 0 in case of success, -1 in case of error.
|
||||
* The socket's source address is stored in <sa> for <salen> bytes.
|
||||
*/
|
||||
int udp6_get_dst(int fd, struct sockaddr *sa, socklen_t salen, int dir)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (!ret) {
|
||||
if (sa->sa_family == AF_INET)
|
||||
sa->sa_family = AF_CUST_UDP4;
|
||||
else if (sa->sa_family == AF_INET6)
|
||||
sa->sa_family = AF_CUST_UDP6;
|
||||
}
|
||||
ret = sock_get_dst(fd, sa, salen, dir);
|
||||
if (!ret)
|
||||
sa->sa_family = AF_CUST_UDP6;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -75,3 +75,34 @@ int sock_inet6_addrcmp(const struct sockaddr_storage *a, const struct sockaddr_s
|
||||
|
||||
return memcmp(&a6->sin6_addr, &b6->sin6_addr, sizeof(a6->sin6_addr));
|
||||
}
|
||||
|
||||
/*
|
||||
* Retrieves the original destination address for the socket <fd> which must be
|
||||
* of family AF_INET (not AF_INET6), with <dir> indicating if we're a listener
|
||||
* (=0) or an initiator (!=0). In the case of a listener, if the original
|
||||
* destination address was translated, the original address is retrieved. It
|
||||
* returns 0 in case of success, -1 in case of error. The socket's source
|
||||
* address is stored in <sa> for <salen> bytes.
|
||||
*/
|
||||
int sock_inet_get_dst(int fd, struct sockaddr *sa, socklen_t salen, int dir)
|
||||
{
|
||||
if (dir)
|
||||
return getpeername(fd, sa, &salen);
|
||||
else {
|
||||
int ret = getsockname(fd, sa, &salen);
|
||||
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
#if defined(USE_TPROXY) && defined(SO_ORIGINAL_DST)
|
||||
/* For TPROXY and Netfilter's NAT, we can retrieve the original
|
||||
* IPv4 address before DNAT/REDIRECT. We must not do that with
|
||||
* other families because v6-mapped IPv4 addresses are still
|
||||
* reported as v4.
|
||||
*/
|
||||
if (getsockopt(fd, SOL_IP, SO_ORIGINAL_DST, sa, &salen) == 0)
|
||||
return 0;
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user