mirror of
https://github.com/yrutschle/sslh.git
synced 2025-04-14 08:07:14 +03:00
fix memory leak when using transparent proxying
This commit is contained in:
parent
b8e63a4d9d
commit
7acf9627ee
78
common.c
78
common.c
@ -161,6 +161,48 @@ int start_listen_sockets(int *sockfd[], struct addrinfo *addr_list)
|
||||
return num_addr;
|
||||
}
|
||||
|
||||
|
||||
/* returns 1 if given address is on the local machine: iterate through all
|
||||
* network interfaces and check their addresses */
|
||||
int is_same_machine(struct addrinfo* from)
|
||||
{
|
||||
struct ifaddrs *ifaddrs_p = NULL, *ifa;
|
||||
int match = 0;
|
||||
|
||||
getifaddrs(&ifaddrs_p);
|
||||
|
||||
for (ifa = ifaddrs_p; ifa != NULL; ifa = ifa->ifa_next)
|
||||
{
|
||||
if (!ifa->ifa_addr)
|
||||
continue;
|
||||
if (from->ai_addr->sa_family == ifa->ifa_addr->sa_family)
|
||||
{
|
||||
int family = ifa->ifa_addr->sa_family;
|
||||
if (family == AF_INET)
|
||||
{
|
||||
struct sockaddr_in *from_addr = (struct sockaddr_in*)from->ai_addr;
|
||||
struct sockaddr_in *ifa_addr = (struct sockaddr_in*)ifa->ifa_addr;
|
||||
if (from_addr->sin_addr.s_addr == ifa_addr->sin_addr.s_addr) {
|
||||
match = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (family == AF_INET6)
|
||||
{
|
||||
struct sockaddr_in6 *from_addr = (struct sockaddr_in6*)from->ai_addr;
|
||||
struct sockaddr_in6 *ifa_addr = (struct sockaddr_in6*)ifa->ifa_addr;
|
||||
if (!memcmp(from_addr->sin6_addr.s6_addr, ifa_addr->sin6_addr.s6_addr, 16)) {
|
||||
match = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
freeifaddrs(ifaddrs_p);
|
||||
return match;
|
||||
}
|
||||
|
||||
|
||||
/* Transparent proxying: bind the peer address of fd to the peer address of
|
||||
* fd_from */
|
||||
#define IP_TRANSPARENT 19
|
||||
@ -178,39 +220,11 @@ int bind_peer(int fd, int fd_from)
|
||||
* got here */
|
||||
res = getpeername(fd_from, from.ai_addr, &from.ai_addrlen);
|
||||
CHECK_RES_RETURN(res, "getpeername");
|
||||
|
||||
|
||||
/* if the destination is the same machine, there's no need to do bind */
|
||||
struct ifaddrs *ifaddrs_p = NULL, *ifa;
|
||||
|
||||
getifaddrs(&ifaddrs_p);
|
||||
|
||||
for (ifa = ifaddrs_p; ifa != NULL; ifa = ifa->ifa_next)
|
||||
{
|
||||
if (!ifa->ifa_addr)
|
||||
continue;
|
||||
int match = 0;
|
||||
if (from.ai_addr->sa_family == ifa->ifa_addr->sa_family)
|
||||
{
|
||||
int family = ifa->ifa_addr->sa_family;
|
||||
if (family == AF_INET)
|
||||
{
|
||||
struct sockaddr_in *from_addr = (struct sockaddr_in*)from.ai_addr;
|
||||
struct sockaddr_in *ifa_addr = (struct sockaddr_in*)ifa->ifa_addr;
|
||||
if (from_addr->sin_addr.s_addr == ifa_addr->sin_addr.s_addr)
|
||||
match = 1;
|
||||
}
|
||||
else if (family == AF_INET6)
|
||||
{
|
||||
struct sockaddr_in6 *from_addr = (struct sockaddr_in6*)from.ai_addr;
|
||||
struct sockaddr_in6 *ifa_addr = (struct sockaddr_in6*)ifa->ifa_addr;
|
||||
if (!memcmp(from_addr->sin6_addr.s6_addr, ifa_addr->sin6_addr.s6_addr, 16))
|
||||
match = 1;
|
||||
}
|
||||
}
|
||||
if (match) /* the destination is the same as the source, should not create a transparent bind */
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (is_same_machine(&from))
|
||||
return 0;
|
||||
|
||||
#ifndef IP_BINDANY /* use IP_TRANSPARENT */
|
||||
res = setsockopt(fd, IPPROTO_IP, IP_TRANSPARENT, &trans, sizeof(trans));
|
||||
CHECK_RES_DIE(res, "setsockopt");
|
||||
|
Loading…
x
Reference in New Issue
Block a user