Compare commits

..
8 Commits
Author SHA1 Message Date
Simon Kelley ea28d0ef8a Scale the DNS random scket pool on the value of dns-forward-max. 2021-03-26 22:02:04 +00:00
Simon Kelley 4a8c098840 Change the method of allocation of random source ports for DNS.
Previously, without min-port or max-port configured, dnsmasq would
default to the compiled in defaults for those, which are 1024 and
65535. Now, when neither are configured, it defaults instead to
the kernel's ephemeral port range, which is typically
32768 to 60999 on Linux systems. This change eliminates the
possibility that dnsmasq may be using a registered port > 1024
when a long-running daemon starts up and wishes to claim it.

This change does likely slighly reduce the number of random ports
and therefore the protection from reply spoofing. The older
behaviour can be restored using the min-port and max-port config
switches should that be a concern.
2021-03-26 21:19:39 +00:00
黎醒聪 ffa4628faa Fix thinko in 51f7bc924c 2021-03-22 22:00:26 +00:00
Petr Menšík e10a9239e1 Move repeated test pattern to server_test_type
Use static function to test similar checks in multiple places.
2021-03-21 22:57:02 +00:00
Petr Menšík 51f7bc924c Create common function for forward dump, log and send
One part in dnssec retry path did not dump sent retry into dump file.
Make sure it is dumped all times it is sent by common function shared on
multiple places. Reduce a bit also server sending.
2021-03-21 22:56:05 +00:00
Petr Menšík 6c0bf79078 Reduce few repetitions in forward code 2021-03-21 22:54:12 +00:00
Matthias Andree 4b03170920 Update German translation for 2.85rc1.
Signed-off-by: Matthias Andree <matthias.andree@gmx.de>
2021-03-21 22:41:58 +00:00
Simon Kelley 1de6bbc108 Fix FTBS on FreeBSD due to Linux-specific optimisation of if_nametoindex() 2021-03-19 22:24:08 +00:00
8 changed files with 488 additions and 519 deletions

No files matched your search

+16
View File
@@ -49,7 +49,23 @@ version 2.85
source address errors from fatal to run-time. The error will be
logged and communiction with the server not possible.
Change the method of allocation of random source ports for DNS.
Previously, without min-port or max-port configured, dnsmasq would
default to the compiled in defaults for those, which are 1024 and
65535. Now, when neither are configured, it defaults instead to
the kernel's ephemeral port range, which is typically
32768 to 60999 on Linux systems. This change eliminates the
possibility that dnsmasq may be using a registered port > 1024
when a long-running daemon starts up and wishes to claim it.
This change does likely slighly reduce the number of random ports
and therefore the protection from reply spoofing. The older
behaviour can be restored using the min-port and max-port config
switches should that be a concern.
Scale the size of the DNS random-port pool based on the
value of the --dns-forward-max configuration.
version 2.84
Fix a problem, introduced in 2.83, which could see DNS replies
being sent via the wrong socket. On machines running both
+324 -372
View File
File diff suppressed because it is too large. Load diff
-1
View File
@@ -29,7 +29,6 @@
#define UDP_TEST_TIME 60 /* How often to reset our idea of max packet size. */
#define SERVERS_LOGGED 30 /* Only log this many servers when logging state */
#define LOCALS_LOGGED 8 /* Only log this many local addresses when logging state */
#define RANDOM_SOCKS 64 /* max simultaneous random ports */
#define LEASE_RETRY 60 /* on error, retry writing leasefile after LEASE_RETRY seconds */
#define CACHESIZ 150 /* default cache size */
#define TTL_FLOOR_LIMIT 3600 /* don't allow --min-cache-ttl to raise TTL above this under any circumstances */
+19 -4
View File
@@ -237,9 +237,16 @@ int main (int argc, char **argv)
die(_("Ubus not available: set HAVE_UBUS in src/config.h"), NULL, EC_BADCONF);
#endif
/* Handle only one of min_port/max_port being set. */
if (daemon->min_port != 0 && daemon->max_port == 0)
daemon->max_port = MAX_PORT;
if (daemon->max_port != 0 && daemon->min_port == 0)
daemon->min_port = MIN_PORT;
if (daemon->max_port < daemon->min_port)
die(_("max_port cannot be smaller than min_port"), NULL, EC_BADCONF);
now = dnsmasq_time();
if (daemon->auth_zones)
@@ -392,6 +399,14 @@ int main (int argc, char **argv)
cache_init();
blockdata_init();
hash_questions_init();
/* Scale random socket pool by ftabsize, but
limit it based on available fds. */
daemon->numrrand = daemon->ftabsize/2;
if (daemon->numrrand > max_fd/3)
daemon->numrrand = max_fd/3;
/* safe_malloc returns zero'd memory */
daemon->randomsocks = safe_malloc(daemon->numrrand * sizeof(struct randfd));
}
#ifdef HAVE_INOTIFY
@@ -980,7 +995,7 @@ int main (int argc, char **argv)
a single file will be sent to may clients (the file only needs
one fd). */
max_fd -= 30; /* use other than TFTP */
max_fd -= 30 + daemon->numrrand; /* use other than TFTP */
if (max_fd < 0)
max_fd = 5;
@@ -1693,7 +1708,7 @@ static int set_dns_listeners(time_t now)
for (serverfdp = daemon->sfds; serverfdp; serverfdp = serverfdp->next)
poll_listen(serverfdp->fd, POLLIN);
for (i = 0; i < RANDOM_SOCKS; i++)
for (i = 0; i < daemon->numrrand; i++)
if (daemon->randomsocks[i].refcount != 0)
poll_listen(daemon->randomsocks[i].fd, POLLIN);
@@ -1745,7 +1760,7 @@ static void check_dns_listeners(time_t now)
if (poll_check(serverfdp->fd, POLLIN))
reply_query(serverfdp->fd, now);
for (i = 0; i < RANDOM_SOCKS; i++)
for (i = 0; i < daemon->numrrand; i++)
if (daemon->randomsocks[i].refcount != 0 &&
poll_check(daemon->randomsocks[i].fd, POLLIN))
reply_query(daemon->randomsocks[i].fd, now);
+2 -1
View File
@@ -1130,7 +1130,8 @@ extern struct daemon {
pid_t tcp_pids[MAX_PROCS];
int tcp_pipes[MAX_PROCS];
int pipe_to_parent;
struct randfd randomsocks[RANDOM_SOCKS];
int numrrand;
struct randfd *randomsocks;
struct randfd_list *rfl_spare, *rfl_poll;
int v6pktinfo;
struct addrlist *interface_addrs; /* list of all addresses/prefix lengths associated with all local interfaces */
+87 -112
View File
@@ -245,6 +245,53 @@ static unsigned int search_servers(time_t now, union all_addr **addrpp, unsigned
return flags;
}
#ifdef HAVE_CONNTRACK
static void set_outgoing_mark(struct frec *forward, int fd)
{
/* Copy connection mark of incoming query to outgoing connection. */
unsigned int mark;
if (get_incoming_mark(&forward->frec_src.source, &forward->frec_src.dest, 0, &mark))
setsockopt(fd, SOL_SOCKET, SO_MARK, &mark, sizeof(unsigned int));
}
#endif
static void log_query_mysockaddr(unsigned int flags, char *name, union mysockaddr *addr, char *arg)
{
if (addr->sa.sa_family == AF_INET)
log_query(flags | F_IPV4, name, (union all_addr *)&addr->in.sin_addr, arg);
else
log_query(flags | F_IPV6, name, (union all_addr *)&addr->in6.sin6_addr, arg);
}
static void server_send(struct server *server, int fd,
const void *header, size_t plen, int flags)
{
while (retry_send(sendto(fd, header, plen, flags,
&server->addr.sa,
sa_len(&server->addr))));
}
#ifdef HAVE_DNSSEC
static void server_send_log(struct server *server, int fd,
const void *header, size_t plen, int dumpflags,
unsigned int logflags, char *name, char *arg)
{
#ifdef HAVE_DUMPFILE
dump_packet(dumpflags, (void *)header, (size_t)plen, NULL, &server->addr);
#endif
log_query_mysockaddr(logflags, name, &server->addr, arg);
server_send(server, fd, header, plen, 0);
}
#endif
static int server_test_type(const struct server *server,
const char *domain, int type, int extratype)
{
return (type == (server->flags & (SERV_TYPE | extratype)) &&
(type != SERV_HAS_DOMAIN || hostname_isequal(domain, server->domain)) &&
!(server->flags & (SERV_LITERAL_ADDRESS | SERV_LOOP)));
}
static int forward_query(int udpfd, union mysockaddr *udpaddr,
union all_addr *dst_addr, unsigned int dst_iface,
struct dns_header *header, size_t plen, time_t now,
@@ -345,17 +392,10 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
PUTSHORT(SAFE_PKTSZ, pheader);
if ((fd = allocate_rfd(&forward->rfds, forward->sentto)) != -1)
{
if (forward->sentto->addr.sa.sa_family == AF_INET)
log_query(F_NOEXTRA | F_DNSSEC | F_IPV4, "retry", (union all_addr *)&forward->sentto->addr.in.sin_addr, "dnssec");
else
log_query(F_NOEXTRA | F_DNSSEC | F_IPV6, "retry", (union all_addr *)&forward->sentto->addr.in6.sin6_addr, "dnssec");
while (retry_send(sendto(fd, (char *)header, plen, 0,
&forward->sentto->addr.sa,
sa_len(&forward->sentto->addr))));
}
server_send_log(forward->sentto, fd, header, plen,
DUMP_SEC_QUERY,
F_NOEXTRA | F_DNSSEC, "retry", "dnssec");
return 1;
}
#endif
@@ -506,20 +546,14 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
domain may be NULL, in which case server->domain
must be NULL also. */
if (type == (start->flags & SERV_TYPE) &&
(type != SERV_HAS_DOMAIN || hostname_isequal(domain, start->domain)) &&
!(start->flags & (SERV_LITERAL_ADDRESS | SERV_LOOP)) &&
if (server_test_type(start, domain, type, 0) &&
((fd = allocate_rfd(&forward->rfds, start)) != -1))
{
#ifdef HAVE_CONNTRACK
/* Copy connection mark of incoming query to outgoing connection. */
if (option_bool(OPT_CONNTRACK))
{
unsigned int mark;
if (get_incoming_mark(&forward->frec_src.source, &forward->frec_src.dest, 0, &mark))
setsockopt(fd, SOL_SOCKET, SO_MARK, &mark, sizeof(unsigned int));
}
set_outgoing_mark(forward, fd);
#endif
#ifdef HAVE_DNSSEC
@@ -556,12 +590,8 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
if (!gotname)
strcpy(daemon->namebuff, "query");
if (start->addr.sa.sa_family == AF_INET)
log_query(F_SERVER | F_IPV4 | F_FORWARD, daemon->namebuff,
(union all_addr *)&start->addr.in.sin_addr, NULL);
else
log_query(F_SERVER | F_IPV6 | F_FORWARD, daemon->namebuff,
(union all_addr *)&start->addr.in6.sin6_addr, NULL);
log_query_mysockaddr(F_SERVER | F_FORWARD, daemon->namebuff,
&start->addr, NULL);
start->queries++;
forwarded = 1;
forward->sentto = start;
@@ -878,22 +908,10 @@ void reply_query(int fd, time_t now)
}
if ((fd = allocate_rfd(&forward->rfds, start)) == -1)
return;
#ifdef HAVE_DUMPFILE
dump_packet(DUMP_SEC_QUERY, (void *)header, (size_t)plen, NULL, &start->addr);
#endif
while (retry_send(sendto(fd, (char *)header, plen, 0,
&start->addr.sa,
sa_len(&start->addr))));
if (start->addr.sa.sa_family == AF_INET)
log_query(F_NOEXTRA | F_DNSSEC | F_IPV4, "retry", (union all_addr *)&start->addr.in.sin_addr, "dnssec");
else
log_query(F_NOEXTRA | F_DNSSEC | F_IPV6, "retry", (union all_addr *)&start->addr.in6.sin6_addr, "dnssec");
if ((fd = allocate_rfd(&forward->rfds, start)) != -1)
server_send_log(start, fd, header, plen,
DUMP_SEC_QUERY,
F_NOEXTRA | F_DNSSEC, "retry", "dnssec");
return;
}
#endif
@@ -1064,9 +1082,7 @@ void reply_query(int fd, time_t now)
while (1)
{
if (type == (start->flags & (SERV_TYPE | SERV_DO_DNSSEC)) &&
((type & SERV_TYPE) != SERV_HAS_DOMAIN || hostname_isequal(domain, start->domain)) &&
!(start->flags & (SERV_LITERAL_ADDRESS | SERV_LOOP)))
if (server_test_type(start, domain, type, 0))
{
new_server = start;
if (server == start)
@@ -1109,13 +1125,6 @@ void reply_query(int fd, time_t now)
nn = dnssec_generate_query(header,((unsigned char *) header) + server->edns_pktsz,
daemon->keyname, forward->class, querytype, server->edns_pktsz);
if (server->addr.sa.sa_family == AF_INET)
log_query(F_NOEXTRA | F_DNSSEC | F_IPV4, daemon->keyname, (union all_addr *)&(server->addr.in.sin_addr),
querystr("dnssec-query", querytype));
else
log_query(F_NOEXTRA | F_DNSSEC | F_IPV6, daemon->keyname, (union all_addr *)&(server->addr.in6.sin6_addr),
querystr("dnssec-query", querytype));
memcpy(new->hash, hash_questions(header, nn, daemon->namebuff), HASH_SIZE);
new->new_id = get_id();
header->id = htons(new->new_id);
@@ -1129,22 +1138,12 @@ void reply_query(int fd, time_t now)
if ((fd = allocate_rfd(&new->rfds, server)) != -1)
{
#ifdef HAVE_CONNTRACK
/* Copy connection mark of incoming query to outgoing connection. */
if (option_bool(OPT_CONNTRACK))
{
unsigned int mark;
if (get_incoming_mark(&orig->frec_src.source, &orig->frec_src.dest, 0, &mark))
setsockopt(fd, SOL_SOCKET, SO_MARK, &mark, sizeof(unsigned int));
}
set_outgoing_mark(orig, fd);
#endif
#ifdef HAVE_DUMPFILE
dump_packet(DUMP_SEC_QUERY, (void *)header, (size_t)nn, NULL, &server->addr);
#endif
while (retry_send(sendto(fd, (char *)header, nn, 0,
&server->addr.sa,
sa_len(&server->addr))));
server_send_log(server, fd, header, nn, DUMP_SEC_QUERY,
F_NOEXTRA | F_DNSSEC, daemon->keyname,
querystr("dnssec-query", querytype));
server->queries++;
}
}
@@ -1503,13 +1502,9 @@ void receive_query(struct listener *listen, time_t now)
struct auth_zone *zone;
#endif
char *types = querystr(auth_dns ? "auth" : "query", type);
if (family == AF_INET)
log_query(F_QUERY | F_IPV4 | F_FORWARD, daemon->namebuff,
(union all_addr *)&source_addr.in.sin_addr, types);
else
log_query(F_QUERY | F_IPV6 | F_FORWARD, daemon->namebuff,
(union all_addr *)&source_addr.in6.sin6_addr, types);
log_query_mysockaddr(F_QUERY | F_FORWARD, daemon->namebuff,
&source_addr, types);
#ifdef HAVE_AUTH
/* find queries for zones we're authoritative for, and answer them directly */
@@ -1671,9 +1666,7 @@ static int tcp_key_recurse(time_t now, int status, struct dns_header *header, si
}
}
if (type != (server->flags & (SERV_TYPE | SERV_DO_DNSSEC)) ||
(type == SERV_HAS_DOMAIN && !hostname_isequal(domain, server->domain)) ||
(server->flags & (SERV_LITERAL_ADDRESS | SERV_LOOP)))
if (!server_test_type(server, domain, type, SERV_DO_DNSSEC))
continue;
retry:
@@ -1697,9 +1690,8 @@ static int tcp_key_recurse(time_t now, int status, struct dns_header *header, si
}
#ifdef MSG_FASTOPEN
while(retry_send(sendto(server->tcpfd, packet, m + sizeof(u16),
MSG_FASTOPEN, &server->addr.sa, sa_len(&server->addr))));
server_send(server, server->tcpfd, packet, m + sizeof(u16), MSG_FASTOPEN);
if (errno == 0)
data_sent = 1;
#endif
@@ -1730,14 +1722,9 @@ static int tcp_key_recurse(time_t now, int status, struct dns_header *header, si
continue;
}
log_query_mysockaddr(F_NOEXTRA | F_DNSSEC, keyname, &server->addr,
querystr("dnssec-query", new_status == STAT_NEED_KEY ? T_DNSKEY : T_DS));
if (server->addr.sa.sa_family == AF_INET)
log_query(F_NOEXTRA | F_DNSSEC | F_IPV4, keyname, (union all_addr *)&(server->addr.in.sin_addr),
querystr("dnssec-query", new_status == STAT_NEED_KEY ? T_DNSKEY : T_DS));
else
log_query(F_NOEXTRA | F_DNSSEC | F_IPV6, keyname, (union all_addr *)&(server->addr.in6.sin6_addr),
querystr("dnssec-query", new_status == STAT_NEED_KEY ? T_DNSKEY : T_DS));
server->flags |= SERV_GOT_TCP;
m = (c1 << 8) | c2;
@@ -1875,12 +1862,8 @@ unsigned char *tcp_request(int confd, time_t now,
#endif
char *types = querystr(auth_dns ? "auth" : "query", qtype);
if (peer_addr.sa.sa_family == AF_INET)
log_query(F_QUERY | F_IPV4 | F_FORWARD, daemon->namebuff,
(union all_addr *)&peer_addr.in.sin_addr, types);
else
log_query(F_QUERY | F_IPV6 | F_FORWARD, daemon->namebuff,
(union all_addr *)&peer_addr.in6.sin6_addr, types);
log_query_mysockaddr(F_QUERY | F_FORWARD, daemon->namebuff,
&peer_addr, types);
#ifdef HAVE_AUTH
/* find queries for zones we're authoritative for, and answer them directly */
@@ -1995,9 +1978,7 @@ unsigned char *tcp_request(int confd, time_t now,
}
/* server for wrong domain */
if (type != (last_server->flags & SERV_TYPE) ||
(type == SERV_HAS_DOMAIN && !hostname_isequal(domain, last_server->domain)) ||
(last_server->flags & (SERV_LITERAL_ADDRESS | SERV_LOOP)))
if (!server_test_type(last_server, domain, type, 0))
continue;
retry:
@@ -2022,9 +2003,8 @@ unsigned char *tcp_request(int confd, time_t now,
}
#ifdef MSG_FASTOPEN
while(retry_send(sendto(last_server->tcpfd, packet, size + sizeof(u16),
MSG_FASTOPEN, &last_server->addr.sa, sa_len(&last_server->addr))));
server_send(last_server, last_server->tcpfd, packet, size + sizeof(u16), MSG_FASTOPEN);
if (errno == 0)
data_sent = 1;
#endif
@@ -2062,13 +2042,9 @@ unsigned char *tcp_request(int confd, time_t now,
last_server->flags |= SERV_GOT_TCP;
m = (c1 << 8) | c2;
if (last_server->addr.sa.sa_family == AF_INET)
log_query(F_SERVER | F_IPV4 | F_FORWARD, daemon->namebuff,
(union all_addr *)&last_server->addr.in.sin_addr, NULL);
else
log_query(F_SERVER | F_IPV6 | F_FORWARD, daemon->namebuff,
(union all_addr *)&last_server->addr.in6.sin6_addr, NULL);
log_query_mysockaddr(F_SERVER | F_FORWARD, daemon->namebuff,
&last_server->addr, NULL);
#ifdef HAVE_DNSSEC
if (option_bool(OPT_DNSSEC_VALID) && !checking_disabled && (last_server->flags & SERV_DO_DNSSEC))
@@ -2242,7 +2218,7 @@ int allocate_rfd(struct randfd_list **fdlp, struct server *serv)
/* limit the number of sockets we have open to avoid starvation of
(eg) TFTP. Once we have a reasonable number, randomness should be OK */
for (i = 0; i < RANDOM_SOCKS; i++)
for (i = 0; i < daemon->numrrand; i++)
if (daemon->randomsocks[i].refcount == 0)
{
if ((fd = random_sock(serv)) != -1)
@@ -2257,9 +2233,9 @@ int allocate_rfd(struct randfd_list **fdlp, struct server *serv)
/* No free ones or cannot get new socket, grab an existing one */
if (!rfd)
for (j = 0; j < RANDOM_SOCKS; j++)
for (j = 0; j < daemon->numrrand; j++)
{
i = (j + finger) % RANDOM_SOCKS;
i = (j + finger) % daemon->numrrand;
if (daemon->randomsocks[i].refcount != 0 &&
server_isequal(serv, daemon->randomsocks[i].serv) &&
daemon->randomsocks[i].refcount != 0xfffe)
@@ -2271,7 +2247,7 @@ int allocate_rfd(struct randfd_list **fdlp, struct server *serv)
}
}
if (j == RANDOM_SOCKS)
if (j == daemon->numrrand)
{
struct randfd_list *rfl_poll;
@@ -2546,9 +2522,8 @@ static struct frec *lookup_frec_by_query(void *hash, unsigned int flags)
void resend_query()
{
if (daemon->srv_save)
while(retry_send(sendto(daemon->fd_save, daemon->packet, daemon->packet_len, 0,
&daemon->srv_save->addr.sa,
sa_len(&daemon->srv_save->addr))));
server_send(daemon->srv_save, daemon->fd_save,
daemon->packet, daemon->packet_len, 0);
}
/* A server record is going away, remove references to it */
@@ -2563,7 +2538,7 @@ void server_gone(struct server *server)
/* If any random socket refers to this server, NULL the reference.
No more references to the socket will be created in the future. */
for (i = 0; i < RANDOM_SOCKS; i++)
for (i = 0; i < daemon->numrrand; i++)
if (daemon->randomsocks[i].refcount != 0 && daemon->randomsocks[i].serv == server)
daemon->randomsocks[i].serv = NULL;
+39 -26
View File
@@ -720,13 +720,17 @@ int enumerate_interfaces(int reset)
to a server is specified by an interface, so cache them.
Update the cache here. */
for (serv = daemon->servers; serv; serv = serv->next)
if (strlen(serv->interface) != 0)
if (serv->interface[0] != 0)
{
struct ifreq ifr;
safe_strncpy(ifr.ifr_name, serv->interface, IF_NAMESIZE);
if (ioctl(param.fd, SIOCGIFINDEX, &ifr) != -1)
serv->ifindex = ifr.ifr_ifindex;
#ifdef HAVE_LINUX_NETWORK
struct ifreq ifr;
safe_strncpy(ifr.ifr_name, serv->interface, IF_NAMESIZE);
if (ioctl(param.fd, SIOCGIFINDEX, &ifr) != -1)
serv->ifindex = ifr.ifr_ifindex;
#else
serv->ifindex = if_nametoindex(serv->interface);
#endif
}
again:
@@ -1306,9 +1310,9 @@ int local_bind(int fd, union mysockaddr *addr, char *intname, unsigned int ifind
{
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;
int tries = 1;
unsigned short ports_avail = 1;
if (addr_copy.sa.sa_family == AF_INET)
port = addr_copy.in.sin_port;
else
@@ -1317,34 +1321,43 @@ int local_bind(int fd, union mysockaddr *addr, char *intname, unsigned int ifind
/* cannot set source _port_ for TCP connections. */
if (is_tcp)
port = 0;
else if (port == 0)
else if (port == 0 && daemon->max_port != 0)
{
/* Bind a random port within the range given by min-port and max-port */
/* Bind a random port within the range given by min-port and max-port if either
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;
port = htons(daemon->min_port + (rand16() % ((unsigned short)ports_avail)));
port = htons(daemon->min_port + (rand16() % ports_avail));
}
while (tries--)
while (1)
{
/* elide bind() call if it's to port 0, address 0 */
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 (port == 0 && addr_copy.in.sin_addr.s_addr == 0)
break;
addr_copy.in.sin_port = port;
}
else
{
if (port == 0 && IN6_IS_ADDR_UNSPECIFIED(&addr_copy.in6.sin6_addr))
break;
addr_copy.in6.sin6_port = port;
}
if (errno != EADDRINUSE && errno != EACCES)
return 0;
if (bind(fd, (struct sockaddr *)&addr_copy, sa_len(&addr_copy)) != -1)
break;
port = htons(daemon->min_port + (rand16() % ((unsigned short)ports_avail)));
}
if (errno != EADDRINUSE && errno != EACCES)
return 0;
if (!done)
return 0;
if (--tries == 0)
return 0;
port = htons(daemon->min_port + (rand16() % ports_avail));
}
if (!is_tcp && ifindex > 0)
{
+1 -3
View File
@@ -5076,9 +5076,7 @@ void read_opts(int argc, char **argv, char *compile_opts)
daemon->soa_refresh = SOA_REFRESH;
daemon->soa_retry = SOA_RETRY;
daemon->soa_expiry = SOA_EXPIRY;
daemon->max_port = MAX_PORT;
daemon->min_port = MIN_PORT;
#ifndef NO_ID
add_txt("version.bind", "dnsmasq-" VERSION, 0 );
add_txt("authors.bind", "Simon Kelley", 0);