mirror of
https://github.com/pi-hole/dnsmasq.git
synced 2025-12-20 02:38:32 +00:00
Further optimisation of --port-limit.
No longer try and fail to open every port when the port range is in complete use; go straight to re-using an existing socket. Die at startup if port range is smaller than --port-limit, since the code behaves badly in this case.
This commit is contained in:
@@ -24,6 +24,7 @@
|
|||||||
#define KEYBLOCK_LEN 40 /* choose to minimise fragmentation when storing DNSSEC keys */
|
#define KEYBLOCK_LEN 40 /* choose to minimise fragmentation when storing DNSSEC keys */
|
||||||
#define DNSSEC_WORK 50 /* Max number of queries to validate one question */
|
#define DNSSEC_WORK 50 /* Max number of queries to validate one question */
|
||||||
#define TIMEOUT 10 /* drop UDP queries after TIMEOUT seconds */
|
#define TIMEOUT 10 /* drop UDP queries after TIMEOUT seconds */
|
||||||
|
#define SMALL_PORT_RANGE 30 /* If DNS port range is smaller than this, use different allocation. */
|
||||||
#define FORWARD_TEST 50 /* try all servers every 50 queries */
|
#define FORWARD_TEST 50 /* try all servers every 50 queries */
|
||||||
#define FORWARD_TIME 20 /* or 20 seconds */
|
#define FORWARD_TIME 20 /* or 20 seconds */
|
||||||
#define UDP_TEST_TIME 60 /* How often to reset our idea of max packet size. */
|
#define UDP_TEST_TIME 60 /* How often to reset our idea of max packet size. */
|
||||||
|
|||||||
@@ -266,6 +266,10 @@ int main (int argc, char **argv)
|
|||||||
if (daemon->max_port < daemon->min_port)
|
if (daemon->max_port < daemon->min_port)
|
||||||
die(_("max_port cannot be smaller than min_port"), NULL, EC_BADCONF);
|
die(_("max_port cannot be smaller than min_port"), NULL, EC_BADCONF);
|
||||||
|
|
||||||
|
if (daemon->max_port != 0 &&
|
||||||
|
daemon->max_port - daemon->min_port + 1 < daemon->randport_limit)
|
||||||
|
die(_("port_limit must not be larger than available port range"), NULL, EC_BADCONF);
|
||||||
|
|
||||||
now = dnsmasq_time();
|
now = dnsmasq_time();
|
||||||
|
|
||||||
if (daemon->auth_zones)
|
if (daemon->auth_zones)
|
||||||
|
|||||||
@@ -2435,6 +2435,21 @@ static int random_sock(struct server *s)
|
|||||||
|
|
||||||
if ((fd = socket(s->source_addr.sa.sa_family, SOCK_DGRAM, 0)) != -1)
|
if ((fd = socket(s->source_addr.sa.sa_family, SOCK_DGRAM, 0)) != -1)
|
||||||
{
|
{
|
||||||
|
/* We need to set IPV6ONLY so we can use the same ports
|
||||||
|
for IPv4 and IPV6, otherwise, in restriced port situations,
|
||||||
|
we can end up with all our available ports in use for
|
||||||
|
one address family, and the other address family cannot be used. */
|
||||||
|
if (s->source_addr.sa.sa_family == AF_INET6)
|
||||||
|
{
|
||||||
|
int opt = 1;
|
||||||
|
|
||||||
|
if (setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &opt, sizeof(opt)) == -1)
|
||||||
|
{
|
||||||
|
close(fd);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (local_bind(fd, &s->source_addr, s->interface, s->ifindex, 0))
|
if (local_bind(fd, &s->source_addr, s->interface, s->ifindex, 0))
|
||||||
return fd;
|
return fd;
|
||||||
|
|
||||||
@@ -2479,9 +2494,22 @@ int allocate_rfd(struct randfd_list **fdlp, struct server *serv)
|
|||||||
{
|
{
|
||||||
static int finger = 0;
|
static int finger = 0;
|
||||||
int i, j = 0;
|
int i, j = 0;
|
||||||
|
int ports_full = 0;
|
||||||
struct randfd_list **up, *rfl, *found, **found_link;
|
struct randfd_list **up, *rfl, *found, **found_link;
|
||||||
struct randfd *rfd = NULL;
|
struct randfd *rfd = NULL;
|
||||||
int fd = 0;
|
int fd = 0;
|
||||||
|
int ports_avail = 0;
|
||||||
|
|
||||||
|
/* We can't have more randomsocks for this AF available than ports in our port range,
|
||||||
|
so check that here, to avoid trying and failing to bind every port
|
||||||
|
in local_bind(), called from random_sock(). The actual check is below when
|
||||||
|
ports_avail != 0 */
|
||||||
|
if (daemon->max_port != 0)
|
||||||
|
{
|
||||||
|
ports_avail = daemon->max_port - daemon->min_port + 1;
|
||||||
|
if (ports_avail >= SMALL_PORT_RANGE)
|
||||||
|
ports_avail = 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* If server has a pre-allocated fd, use that. */
|
/* If server has a pre-allocated fd, use that. */
|
||||||
if (serv->sfd)
|
if (serv->sfd)
|
||||||
@@ -2508,8 +2536,24 @@ int allocate_rfd(struct randfd_list **fdlp, struct server *serv)
|
|||||||
return found->rfd->fd;
|
return found->rfd->fd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* check for all available ports in use. */
|
||||||
|
if (ports_avail != 0)
|
||||||
|
{
|
||||||
|
int ports_inuse;
|
||||||
|
|
||||||
|
for (ports_inuse = 0, i = 0; i < daemon->numrrand; i++)
|
||||||
|
if (daemon->randomsocks[i].refcount != 0 &&
|
||||||
|
daemon->randomsocks[i].serv->source_addr.sa.sa_family == serv->source_addr.sa.sa_family &&
|
||||||
|
++ports_inuse >= ports_avail)
|
||||||
|
{
|
||||||
|
ports_full = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* limit the number of sockets we have open to avoid starvation of
|
/* limit the number of sockets we have open to avoid starvation of
|
||||||
(eg) TFTP. Once we have a reasonable number, randomness should be OK */
|
(eg) TFTP. Once we have a reasonable number, randomness should be OK */
|
||||||
|
if (!ports_full)
|
||||||
for (i = 0; i < daemon->numrrand; i++)
|
for (i = 0; i < daemon->numrrand; i++)
|
||||||
if (daemon->randomsocks[i].refcount == 0)
|
if (daemon->randomsocks[i].refcount == 0)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1371,7 +1371,7 @@ int local_bind(int fd, union mysockaddr *addr, char *intname, unsigned int ifind
|
|||||||
or both are set. Otherwise use the OS's random ephemeral port allocation by
|
or both are set. Otherwise use the OS's random ephemeral port allocation by
|
||||||
leaving port == 0 and tries == 1 */
|
leaving port == 0 and tries == 1 */
|
||||||
ports_avail = daemon->max_port - daemon->min_port + 1;
|
ports_avail = daemon->max_port - daemon->min_port + 1;
|
||||||
tries = (ports_avail < 30) ? ports_avail : 100;
|
tries = (ports_avail < SMALL_PORT_RANGE) ? ports_avail : 100;
|
||||||
port = htons(daemon->min_port + (rand16() % ports_avail));
|
port = htons(daemon->min_port + (rand16() % ports_avail));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1401,7 +1401,7 @@ int local_bind(int fd, union mysockaddr *addr, char *intname, unsigned int ifind
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* For small ranges, do a systematic search, not a random one. */
|
/* For small ranges, do a systematic search, not a random one. */
|
||||||
if (ports_avail < 30)
|
if (ports_avail < SMALL_PORT_RANGE)
|
||||||
{
|
{
|
||||||
unsigned short hport = ntohs(port);
|
unsigned short hport = ntohs(port);
|
||||||
if (hport++ == daemon->max_port)
|
if (hport++ == daemon->max_port)
|
||||||
|
|||||||
Reference in New Issue
Block a user