mirror of
http://thekelleys.org.uk/git/dnsmasq.git
synced 2026-11-06 15:51:41 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ea28d0ef8a | ||
|
|
4a8c098840 | ||
|
|
ffa4628faa | ||
|
|
e10a9239e1 | ||
|
|
51f7bc924c | ||
|
|
6c0bf79078 | ||
|
|
4b03170920 | ||
|
|
1de6bbc108 |
No files matched your search
@@ -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
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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);
|
||||
|
||||
Reference in new issue
Block a user