diff options
-rw-r--r-- | src/dnsmasq.h | 1 | ||||
-rw-r--r-- | src/forward.c | 46 | ||||
-rw-r--r-- | src/network.c | 13 | ||||
-rw-r--r-- | src/util.c | 13 |
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) @@ -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 |