Use the values of --min-port and --max-port in TCP connections.

Rather that letting the kernel pick source ports, do it ourselves
so that the --min-port and --max-port parameters are be obeyed.
This commit is contained in:
Simon Kelley
2020-12-12 23:26:45 +00:00
parent 4ded96209e
commit a2a7e040b1
2 changed files with 39 additions and 5 deletions

View File

@@ -1,3 +1,8 @@
version 2.83
Use the values of --min-port and --max-port in outgoing
TCP connections to upstream DNS servers.
version 2.82
Improve behaviour in the face of network interfaces which come
and go and change index. Thanks to Petr Mensik for the patch.

View File

@@ -1262,17 +1262,46 @@ int random_sock(int family)
int local_bind(int fd, union mysockaddr *addr, char *intname, unsigned int ifindex, int is_tcp)
{
union mysockaddr addr_copy = *addr;
unsigned short port;
int tries = 1, done = 0;
unsigned int ports_avail = ((unsigned short)daemon->max_port - (unsigned short)daemon->min_port) + 1;
if (addr_copy.sa.sa_family == AF_INET)
port = addr_copy.in.sin_port;
else
port = addr_copy.in6.sin6_port;
/* cannot set source _port_ for TCP connections. */
if (is_tcp)
port = 0;
/* Bind a random port within the range given by min-port and max-port */
if (port == 0)
{
if (addr_copy.sa.sa_family == AF_INET)
addr_copy.in.sin_port = 0;
else
addr_copy.in6.sin6_port = 0;
tries = ports_avail < 30 ? 3 * ports_avail : 100;
port = htons(daemon->min_port + (rand16() % ((unsigned short)ports_avail)));
}
if (bind(fd, (struct sockaddr *)&addr_copy, sa_len(&addr_copy)) == -1)
while (tries--)
{
if (addr_copy.sa.sa_family == AF_INET)
addr_copy.in.sin_port = port;
else
addr_copy.in6.sin6_port = port;
if (bind(fd, (struct sockaddr *)&addr_copy, sa_len(&addr_copy)) != -1)
{
done = 1;
break;
}
if (errno != EADDRINUSE && errno != EACCES)
return 0;
port = htons(daemon->min_port + (rand16() % ((unsigned short)ports_avail)));
}
if (!done)
return 0;
if (!is_tcp && ifindex > 0)