summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/dnsmasq.h1
-rw-r--r--src/forward.c46
-rw-r--r--src/network.c13
-rw-r--r--src/util.c13
4 files changed, 50 insertions, 23 deletions
diff --git a/src/dnsmasq.h b/src/dnsmasq.h
index 1bfb965..6f02368 100644
--- a/src/dnsmasq.h
+++ b/src/dnsmasq.h
@@ -1405,6 +1405,7 @@ void *whine_malloc(size_t size);
void *whine_realloc(void *ptr, size_t size);
int sa_len(union mysockaddr *addr);
int sockaddr_isequal(const union mysockaddr *s1, const union mysockaddr *s2);
+int sockaddr_isnull(const union mysockaddr *s);
int hostname_order(const char *a, const char *b);
int hostname_isequal(const char *a, const char *b);
int hostname_issubdomain(char *a, char *b);
diff --git a/src/forward.c b/src/forward.c
index 9d1f005..681ee90 100644
--- a/src/forward.c
+++ b/src/forward.c
@@ -2438,13 +2438,18 @@ static int random_sock(struct server *s)
if (local_bind(fd, &s->source_addr, s->interface, s->ifindex, 0))
return fd;
- if (s->interface[0] == 0)
- (void)prettyprint_addr(&s->source_addr, daemon->addrbuff);
- else
- safe_strncpy(daemon->addrbuff, s->interface, ADDRSTRLEN);
-
- my_syslog(LOG_ERR, _("failed to bind server socket to %s: %s"),
- daemon->addrbuff, strerror(errno));
+ /* don't log errors due to running out of available ports, we handle those. */
+ if (!sockaddr_isnull(&s->source_addr) || errno != EADDRINUSE)
+ {
+ if (s->interface[0] == 0)
+ (void)prettyprint_addr(&s->source_addr, daemon->addrbuff);
+ else
+ safe_strncpy(daemon->addrbuff, s->interface, ADDRSTRLEN);
+
+ my_syslog(LOG_ERR, _("failed to bind server socket to %s: %s"),
+ daemon->addrbuff, strerror(errno));
+ }
+
close(fd);
}
@@ -2518,16 +2523,6 @@ int allocate_rfd(struct randfd_list **fdlp, struct server *serv)
break;
}
- /* We've hit the global limit on sockets before hitting the query limit,
- use an exsiting socket as source in that case. */
- if (!rfd && found)
- {
- *found_link = found->next;
- found->next = *fdlp;
- *fdlp = found;
- return found->rfd->fd;
- }
-
/* No good existing. Need new link. */
if ((rfl = daemon->rfl_spare))
daemon->rfl_spare = rfl->next;
@@ -2552,10 +2547,19 @@ int allocate_rfd(struct randfd_list **fdlp, struct server *serv)
server_isequal(serv, daemon->randomsocks[i].serv) &&
daemon->randomsocks[i].refcount != 0xfffe)
{
- finger = i + 1;
- rfd = &daemon->randomsocks[i];
- rfd->refcount++;
- break;
+ struct randfd_list *rl;
+ /* Don't pick one we already have. */
+ for (rl = *fdlp; rl; rl = rl->next)
+ if (rl->rfd == &daemon->randomsocks[i])
+ break;
+
+ if (!rl)
+ {
+ finger = i + 1;
+ rfd = &daemon->randomsocks[i];
+ rfd->refcount++;
+ break;
+ }
}
}
diff --git a/src/network.c b/src/network.c
index 6166484..9ecb9c0 100644
--- a/src/network.c
+++ b/src/network.c
@@ -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
leaving port == 0 and tries == 1 */
ports_avail = daemon->max_port - daemon->min_port + 1;
- tries = ports_avail < 30 ? 3 * ports_avail : 100;
+ tries = (ports_avail < 30) ? ports_avail : 100;
port = htons(daemon->min_port + (rand16() % ports_avail));
}
@@ -1400,7 +1400,16 @@ int local_bind(int fd, union mysockaddr *addr, char *intname, unsigned int ifind
if (--tries == 0)
return 0;
- port = htons(daemon->min_port + (rand16() % ports_avail));
+ /* For small ranges, do a systematic search, not a random one. */
+ if (ports_avail < 30)
+ {
+ unsigned short hport = ntohs(port);
+ if (hport++ == daemon->max_port)
+ hport = daemon->min_port;
+ port = htons(hport);
+ }
+ else
+ port = htons(daemon->min_port + (rand16() % ports_avail));
}
if (!is_tcp && ifindex > 0)
diff --git a/src/util.c b/src/util.c
index 5165fd6..e0ce67d 100644
--- a/src/util.c
+++ b/src/util.c
@@ -364,6 +364,19 @@ int sockaddr_isequal(const union mysockaddr *s1, const union mysockaddr *s2)
return 0;
}
+int sockaddr_isnull(const union mysockaddr *s)
+{
+ if (s->sa.sa_family == AF_INET &&
+ s->in.sin_addr.s_addr == 0)
+ return 1;
+
+ if (s->sa.sa_family == AF_INET6 &&
+ IN6_IS_ADDR_UNSPECIFIED(&s->in6.sin6_addr))
+ return 1;
+
+ return 0;
+}
+
int sa_len(union mysockaddr *addr)
{
#ifdef HAVE_SOCKADDR_SA_LEN