From a2a7e040b128a8ec369ba8f22beca2705435b85b Mon Sep 17 00:00:00 2001 From: Simon Kelley Date: Sat, 12 Dec 2020 23:26:45 +0000 Subject: [PATCH] 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. --- CHANGELOG | 5 +++++ src/network.c | 37 +++++++++++++++++++++++++++++++++---- 2 files changed, 38 insertions(+), 4 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index e6a2231..34ad22e 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -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. diff --git a/src/network.c b/src/network.c index c7d002b..7cf2546 100644 --- a/src/network.c +++ b/src/network.c @@ -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) + { + tries = ports_avail < 30 ? 3 * ports_avail : 100; + port = htons(daemon->min_port + (rand16() % ((unsigned short)ports_avail))); + } + + while (tries--) { if (addr_copy.sa.sa_family == AF_INET) - addr_copy.in.sin_port = 0; + addr_copy.in.sin_port = port; else - addr_copy.in6.sin6_port = 0; + 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 (bind(fd, (struct sockaddr *)&addr_copy, sa_len(&addr_copy)) == -1) + + if (!done) return 0; if (!is_tcp && ifindex > 0) -- 1.8.3.1