mirror of
http://thekelleys.org.uk/git/dnsmasq.git
synced 2026-11-06 15:51:41 +00:00
Compare commits
14
Commits
v2.88test2
...
v2.88rc4
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
142456cfd0 | ||
|
|
207ce40db2 | ||
|
|
881eaa4dbc | ||
|
|
d6d7527c95 | ||
|
|
11b4be2036 | ||
|
|
3e306c1202 | ||
|
|
7f227a83f2 | ||
|
|
9ed3ee67ec | ||
|
|
1f9215f5f9 | ||
|
|
f52cfdd8c3 | ||
|
|
2fc904111d | ||
|
|
262dadf50e | ||
|
|
6c596f1cc1 | ||
|
|
dafa16c400 |
No files matched your search
@@ -5,10 +5,10 @@ version 2.88
|
|||||||
Add --fast-dns-retry option. This gives dnsmasq the ability
|
Add --fast-dns-retry option. This gives dnsmasq the ability
|
||||||
to originate retries for upstream DNS queries itself, rather
|
to originate retries for upstream DNS queries itself, rather
|
||||||
than relying on the downstream client. This is most useful
|
than relying on the downstream client. This is most useful
|
||||||
when doing DNSSEC over unreliable upstream network. It comes
|
when doing DNSSEC over unreliable upstream networks. It comes
|
||||||
with some cost in memory usage and network bandwidth.
|
with some cost in memory usage and network bandwidth.
|
||||||
|
|
||||||
Add -use-stale-cache option. When set, if a DNS name exists
|
Add --use-stale-cache option. When set, if a DNS name exists
|
||||||
in the cache, but its time-to-live has expired, dnsmasq will
|
in the cache, but its time-to-live has expired, dnsmasq will
|
||||||
return the data anyway. (It attempts to refresh the
|
return the data anyway. (It attempts to refresh the
|
||||||
data with an upstream query after returning the stale data.)
|
data with an upstream query after returning the stale data.)
|
||||||
@@ -26,26 +26,41 @@ version 2.88
|
|||||||
servers being removed from the configuration when reloading
|
servers being removed from the configuration when reloading
|
||||||
server configuration from DBus, or re-reading /etc/resolv.conf
|
server configuration from DBus, or re-reading /etc/resolv.conf
|
||||||
Only servers from the same source should be replaced, but some
|
Only servers from the same source should be replaced, but some
|
||||||
servers from other sources (ie hard coded or another dynamic source)
|
servers from other sources (i.e., hard coded or another dynamic source)
|
||||||
could mysteriously disappear. Thanks to all reporting this,
|
could mysteriously disappear. Thanks to all reporting this,
|
||||||
but especially Christopher J. Masden who reduced the problem
|
but especially Christopher J. Madsen who reduced the problem
|
||||||
to an easily reproducible case which saved mucg labour in
|
to an easily reproducible case which saved much labour in
|
||||||
finding it.
|
finding it.
|
||||||
|
|
||||||
Add --no-round-robin option.
|
Add --no-round-robin option.
|
||||||
|
|
||||||
Allow domain names as well as IP addresses when specifying
|
Allow domain names as well as IP addresses when specifying
|
||||||
upstream DNS servers. There are some gotchas associated with this,
|
upstream DNS servers. There are some gotchas associated with this
|
||||||
(it will mysteriously fail to work if the dnsmasq instance
|
(it will mysteriously fail to work if the dnsmasq instance
|
||||||
being started is in the path from the system resolver to the DNS)
|
being started is in the path from the system resolver to the DNS),
|
||||||
and a seemingly sensible configuration like
|
and a seemingly sensible configuration like
|
||||||
--server=domain.name@1.2.3.4 is unactionable if domain.name
|
--server=domain.name@1.2.3.4 is unactionable if domain.name
|
||||||
only resolves to an IPv6 address). There are, however,
|
only resolves to an IPv6 address). There are, however,
|
||||||
cases where is can be useful. Thanks to Dominik Derigs for
|
cases where is can be useful. Thanks to Dominik Derigs for
|
||||||
the patch.
|
the patch.
|
||||||
|
|
||||||
|
Handle DS records for unsupported crypto algorithms correctly.
|
||||||
|
Such a DS, as long as it is validated, should allow answers
|
||||||
|
in the domain it attests to be returned as unvalidated, and not
|
||||||
|
as a validation error.
|
||||||
|
|
||||||
|
Optimise reading large numbers of --server options. When re-reading
|
||||||
|
upstream servers from /etc/resolv.conf or other sources that
|
||||||
|
can change dnsmasq tries to avoid memory fragmentation by re-using
|
||||||
|
existing records that are being re-read unchanged. This involves
|
||||||
|
seaching all the server records for each new one installed.
|
||||||
|
During startup this search is pointless, and can cause long
|
||||||
|
start times with thousands of --server options because the work
|
||||||
|
needed is O(n^2). Handle this case more intelligently.
|
||||||
|
Thanks to Ye Zhou for spotting the problem and an initial patch.
|
||||||
|
|
||||||
(version 2.87
|
|
||||||
|
version 2.87
|
||||||
Allow arbitrary prefix lengths in --rev-server and
|
Allow arbitrary prefix lengths in --rev-server and
|
||||||
--domain=....,local
|
--domain=....,local
|
||||||
|
|
||||||
|
|||||||
+2
-1
@@ -1166,7 +1166,8 @@ given in a
|
|||||||
.B --dhcp-host
|
.B --dhcp-host
|
||||||
option, but aliases are possible by using CNAMEs. (See
|
option, but aliases are possible by using CNAMEs. (See
|
||||||
.B --cname
|
.B --cname
|
||||||
).
|
). Note that /etc/hosts is NOT used when the DNS server side of dnsmasq
|
||||||
|
is disabled by setting the DNS server port to zero.
|
||||||
|
|
||||||
More than one
|
More than one
|
||||||
.B --dhcp-host
|
.B --dhcp-host
|
||||||
|
|||||||
+846
-679
File diff suppressed because it is too large.
Load diff
+21
-8
@@ -309,14 +309,14 @@ static int dnsmasq_gostdsa_verify(struct blockdata *key_data, unsigned int key_l
|
|||||||
mpz_init(y);
|
mpz_init(y);
|
||||||
}
|
}
|
||||||
|
|
||||||
mpz_import(x, 32 , 1, 1, 0, 0, p);
|
mpz_import(x, 32, -1, 1, 0, 0, p);
|
||||||
mpz_import(y, 32 , 1, 1, 0, 0, p + 32);
|
mpz_import(y, 32, -1, 1, 0, 0, p + 32);
|
||||||
|
|
||||||
if (!ecc_point_set(gost_key, x, y))
|
if (!ecc_point_set(gost_key, x, y))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
mpz_import(sig_struct->r, 32, 1, 1, 0, 0, sig);
|
mpz_import(sig_struct->s, 32, 1, 1, 0, 0, sig);
|
||||||
mpz_import(sig_struct->s, 32, 1, 1, 0, 0, sig + 32);
|
mpz_import(sig_struct->r, 32, 1, 1, 0, 0, sig + 32);
|
||||||
|
|
||||||
return nettle_gostdsa_verify(gost_key, digest_len, digest, sig_struct);
|
return nettle_gostdsa_verify(gost_key, digest_len, digest, sig_struct);
|
||||||
}
|
}
|
||||||
@@ -390,7 +390,12 @@ static int (*verify_func(int algo))(struct blockdata *key_data, unsigned int key
|
|||||||
return dnsmasq_ecdsa_verify;
|
return dnsmasq_ecdsa_verify;
|
||||||
|
|
||||||
#if MIN_VERSION(3, 1)
|
#if MIN_VERSION(3, 1)
|
||||||
case 15: case 16:
|
case 15:
|
||||||
|
return dnsmasq_eddsa_verify;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if MIN_VERSION(3, 6)
|
||||||
|
case 16:
|
||||||
return dnsmasq_eddsa_verify;
|
return dnsmasq_eddsa_verify;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@@ -425,7 +430,9 @@ char *ds_digest_name(int digest)
|
|||||||
{
|
{
|
||||||
case 1: return "sha1";
|
case 1: return "sha1";
|
||||||
case 2: return "sha256";
|
case 2: return "sha256";
|
||||||
case 3: return "gosthash94";
|
#if MIN_VERSION(3, 6)
|
||||||
|
case 3: return "gosthash94cp";
|
||||||
|
#endif
|
||||||
case 4: return "sha384";
|
case 4: return "sha384";
|
||||||
default: return NULL;
|
default: return NULL;
|
||||||
}
|
}
|
||||||
@@ -444,11 +451,17 @@ char *algo_digest_name(int algo)
|
|||||||
case 7: return "sha1"; /* RSASHA1-NSEC3-SHA1 */
|
case 7: return "sha1"; /* RSASHA1-NSEC3-SHA1 */
|
||||||
case 8: return "sha256"; /* RSA/SHA-256 */
|
case 8: return "sha256"; /* RSA/SHA-256 */
|
||||||
case 10: return "sha512"; /* RSA/SHA-512 */
|
case 10: return "sha512"; /* RSA/SHA-512 */
|
||||||
case 12: return "gosthash94"; /* ECC-GOST */
|
#if MIN_VERSION(3, 6)
|
||||||
|
case 12: return "gosthash94cp"; /* ECC-GOST */
|
||||||
|
#endif
|
||||||
case 13: return "sha256"; /* ECDSAP256SHA256 */
|
case 13: return "sha256"; /* ECDSAP256SHA256 */
|
||||||
case 14: return "sha384"; /* ECDSAP384SHA384 */
|
case 14: return "sha384"; /* ECDSAP384SHA384 */
|
||||||
|
#if MIN_VERSION(3, 1)
|
||||||
case 15: return "null_hash"; /* ED25519 */
|
case 15: return "null_hash"; /* ED25519 */
|
||||||
|
# if MIN_VERSION(3, 6)
|
||||||
case 16: return "null_hash"; /* ED448 */
|
case 16: return "null_hash"; /* ED448 */
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
default: return NULL;
|
default: return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+56
-18
@@ -379,21 +379,6 @@ static DBusMessage* dbus_read_servers_ex(DBusMessage *message, int strings)
|
|||||||
strcpy(str_addr, str);
|
strcpy(str_addr, str);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* parse the IP address */
|
|
||||||
if ((addr_err = parse_server(str_addr, &sdetails)) ||
|
|
||||||
(addr_err = parse_server_addr(&sdetails)))
|
|
||||||
{
|
|
||||||
error = dbus_message_new_error_printf(message, DBUS_ERROR_INVALID_ARGS,
|
|
||||||
"Invalid IP address '%s': %s",
|
|
||||||
str, addr_err);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 0.0.0.0 for server address == NULL, for Dbus */
|
|
||||||
if (addr.in.sin_family == AF_INET &&
|
|
||||||
addr.in.sin_addr.s_addr == 0)
|
|
||||||
flags |= SERV_LITERAL_ADDRESS;
|
|
||||||
|
|
||||||
if (strings)
|
if (strings)
|
||||||
{
|
{
|
||||||
char *p;
|
char *p;
|
||||||
@@ -407,7 +392,31 @@ static DBusMessage* dbus_read_servers_ex(DBusMessage *message, int strings)
|
|||||||
else
|
else
|
||||||
p = NULL;
|
p = NULL;
|
||||||
|
|
||||||
add_update_server(flags | SERV_FROM_DBUS, &addr, &source_addr, interface, str_domain, NULL);
|
if (strings && strlen(str_addr) == 0)
|
||||||
|
add_update_server(SERV_LITERAL_ADDRESS | SERV_FROM_DBUS, &addr, &source_addr, interface, str_domain, NULL);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if ((addr_err = parse_server(str_addr, &sdetails)))
|
||||||
|
{
|
||||||
|
error = dbus_message_new_error_printf(message, DBUS_ERROR_INVALID_ARGS,
|
||||||
|
"Invalid IP address '%s': %s",
|
||||||
|
str, addr_err);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (parse_server_next(&sdetails))
|
||||||
|
{
|
||||||
|
if ((addr_err = parse_server_addr(&sdetails)))
|
||||||
|
{
|
||||||
|
error = dbus_message_new_error_printf(message, DBUS_ERROR_INVALID_ARGS,
|
||||||
|
"Invalid IP address '%s': %s",
|
||||||
|
str, addr_err);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
add_update_server(flags | SERV_FROM_DBUS, &addr, &source_addr, interface, str_domain, NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
} while ((str_domain = p));
|
} while ((str_domain = p));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -421,11 +430,40 @@ static DBusMessage* dbus_read_servers_ex(DBusMessage *message, int strings)
|
|||||||
if (dbus_message_iter_get_arg_type(&string_iter) == DBUS_TYPE_STRING)
|
if (dbus_message_iter_get_arg_type(&string_iter) == DBUS_TYPE_STRING)
|
||||||
dbus_message_iter_get_basic(&string_iter, &str);
|
dbus_message_iter_get_basic(&string_iter, &str);
|
||||||
dbus_message_iter_next (&string_iter);
|
dbus_message_iter_next (&string_iter);
|
||||||
|
|
||||||
|
if ((addr_err = parse_server(str_addr, &sdetails)))
|
||||||
|
{
|
||||||
|
error = dbus_message_new_error_printf(message, DBUS_ERROR_INVALID_ARGS,
|
||||||
|
"Invalid IP address '%s': %s",
|
||||||
|
str, addr_err);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
add_update_server(flags | SERV_FROM_DBUS, &addr, &source_addr, interface, str, NULL);
|
while (parse_server_next(&sdetails))
|
||||||
|
{
|
||||||
|
if ((addr_err = parse_server_addr(&sdetails)))
|
||||||
|
{
|
||||||
|
error = dbus_message_new_error_printf(message, DBUS_ERROR_INVALID_ARGS,
|
||||||
|
"Invalid IP address '%s': %s",
|
||||||
|
str, addr_err);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 0.0.0.0 for server address == NULL, for Dbus */
|
||||||
|
if (addr.in.sin_family == AF_INET &&
|
||||||
|
addr.in.sin_addr.s_addr == 0)
|
||||||
|
flags |= SERV_LITERAL_ADDRESS;
|
||||||
|
else
|
||||||
|
flags &= ~SERV_LITERAL_ADDRESS;
|
||||||
|
|
||||||
|
add_update_server(flags | SERV_FROM_DBUS, &addr, &source_addr, interface, str, NULL);
|
||||||
|
}
|
||||||
} while (dbus_message_iter_get_arg_type(&string_iter) == DBUS_TYPE_STRING);
|
} while (dbus_message_iter_get_arg_type(&string_iter) == DBUS_TYPE_STRING);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (sdetails.orig_hostinfo)
|
||||||
|
freeaddrinfo(sdetails.orig_hostinfo);
|
||||||
|
|
||||||
/* jump to next element in outer array */
|
/* jump to next element in outer array */
|
||||||
dbus_message_iter_next(&array_iter);
|
dbus_message_iter_next(&array_iter);
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-2
@@ -1295,9 +1295,9 @@ extern struct daemon {
|
|||||||
|
|
||||||
struct server_details {
|
struct server_details {
|
||||||
union mysockaddr *addr, *source_addr;
|
union mysockaddr *addr, *source_addr;
|
||||||
struct addrinfo *hostinfo;
|
struct addrinfo *hostinfo, *orig_hostinfo;
|
||||||
char *interface, *source, *scope_id, *interface_opt;
|
char *interface, *source, *scope_id, *interface_opt;
|
||||||
int serv_port, source_port, addr_type, scope_index, valid, resolved;
|
int serv_port, source_port, addr_type, scope_index, valid;
|
||||||
u16 *flags;
|
u16 *flags;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1478,6 +1478,7 @@ void reset_option_bool(unsigned int opt);
|
|||||||
struct hostsfile *expand_filelist(struct hostsfile *list);
|
struct hostsfile *expand_filelist(struct hostsfile *list);
|
||||||
char *parse_server(char *arg, struct server_details *sdetails);
|
char *parse_server(char *arg, struct server_details *sdetails);
|
||||||
char *parse_server_addr(struct server_details *sdetails);
|
char *parse_server_addr(struct server_details *sdetails);
|
||||||
|
int parse_server_next(struct server_details *sdetails);
|
||||||
int option_read_dynfile(char *file, int flags);
|
int option_read_dynfile(char *file, int flags);
|
||||||
|
|
||||||
/* forward.c */
|
/* forward.c */
|
||||||
|
|||||||
+37
-22
@@ -979,10 +979,13 @@ int dnssec_validate_by_ds(time_t now, struct dns_header *header, size_t plen, ch
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* The DNS packet is expected to contain the answer to a DS query
|
/* The DNS packet is expected to contain the answer to a DS query
|
||||||
Put all DSs in the answer which are valid into the cache.
|
Put all DSs in the answer which are valid and have hash and signature algos
|
||||||
|
we support into the cache.
|
||||||
Also handles replies which prove that there's no DS at this location,
|
Also handles replies which prove that there's no DS at this location,
|
||||||
either because the zone is unsigned or this isn't a zone cut. These are
|
either because the zone is unsigned or this isn't a zone cut. These are
|
||||||
cached too.
|
cached too.
|
||||||
|
If none of the DS's are for supported algos, treat the answer as if
|
||||||
|
it's a proof of no DS at this location. RFC4035 para 5.2.
|
||||||
return codes:
|
return codes:
|
||||||
STAT_OK At least one valid DS found and in cache.
|
STAT_OK At least one valid DS found and in cache.
|
||||||
STAT_BOGUS no DS in reply or not signed, fails validation, bad packet.
|
STAT_BOGUS no DS in reply or not signed, fails validation, bad packet.
|
||||||
@@ -993,8 +996,8 @@ int dnssec_validate_by_ds(time_t now, struct dns_header *header, size_t plen, ch
|
|||||||
int dnssec_validate_ds(time_t now, struct dns_header *header, size_t plen, char *name, char *keyname, int class)
|
int dnssec_validate_ds(time_t now, struct dns_header *header, size_t plen, char *name, char *keyname, int class)
|
||||||
{
|
{
|
||||||
unsigned char *p = (unsigned char *)(header+1);
|
unsigned char *p = (unsigned char *)(header+1);
|
||||||
int qtype, qclass, rc, i, neganswer, nons, neg_ttl = 0;
|
int qtype, qclass, rc, i, neganswer, nons, neg_ttl = 0, found_supported = 0;
|
||||||
int aclass, atype, rdlen;
|
int aclass, atype, rdlen, flags;
|
||||||
unsigned long ttl;
|
unsigned long ttl;
|
||||||
union all_addr a;
|
union all_addr a;
|
||||||
|
|
||||||
@@ -1065,14 +1068,22 @@ int dnssec_validate_ds(time_t now, struct dns_header *header, size_t plen, char
|
|||||||
algo = *p++;
|
algo = *p++;
|
||||||
digest = *p++;
|
digest = *p++;
|
||||||
|
|
||||||
if ((key = blockdata_alloc((char*)p, rdlen - 4)))
|
if (!ds_digest_name(digest) || !ds_digest_name(digest))
|
||||||
|
{
|
||||||
|
a.log.keytag = keytag;
|
||||||
|
a.log.algo = algo;
|
||||||
|
a.log.digest = digest;
|
||||||
|
log_query(F_NOEXTRA | F_KEYTAG | F_UPSTREAM, name, &a, "DS keytag %hu, algo %hu, digest %hu (not supported)", 0);
|
||||||
|
neg_ttl = ttl;
|
||||||
|
}
|
||||||
|
else if ((key = blockdata_alloc((char*)p, rdlen - 4)))
|
||||||
{
|
{
|
||||||
a.ds.digest = digest;
|
a.ds.digest = digest;
|
||||||
a.ds.keydata = key;
|
a.ds.keydata = key;
|
||||||
a.ds.algo = algo;
|
a.ds.algo = algo;
|
||||||
a.ds.keytag = keytag;
|
a.ds.keytag = keytag;
|
||||||
a.ds.keylen = rdlen - 4;
|
a.ds.keylen = rdlen - 4;
|
||||||
|
|
||||||
if (!cache_insert(name, &a, class, now, ttl, F_FORWARD | F_DS | F_DNSSECOK))
|
if (!cache_insert(name, &a, class, now, ttl, F_FORWARD | F_DS | F_DNSSECOK))
|
||||||
{
|
{
|
||||||
blockdata_free(key);
|
blockdata_free(key);
|
||||||
@@ -1083,26 +1094,29 @@ int dnssec_validate_ds(time_t now, struct dns_header *header, size_t plen, char
|
|||||||
a.log.keytag = keytag;
|
a.log.keytag = keytag;
|
||||||
a.log.algo = algo;
|
a.log.algo = algo;
|
||||||
a.log.digest = digest;
|
a.log.digest = digest;
|
||||||
if (ds_digest_name(digest) && algo_digest_name(algo))
|
log_query(F_NOEXTRA | F_KEYTAG | F_UPSTREAM, name, &a, "DS keytag %hu, algo %hu, digest %hu", 0);
|
||||||
log_query(F_NOEXTRA | F_KEYTAG | F_UPSTREAM, name, &a, "DS keytag %hu, algo %hu, digest %hu", 0);
|
found_supported = 1;
|
||||||
else
|
|
||||||
log_query(F_NOEXTRA | F_KEYTAG | F_UPSTREAM, name, &a, "DS keytag %hu, algo %hu, digest %hu (not supported)", 0);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
p = psave;
|
p = psave;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ADD_RDLEN(header, p, plen, rdlen))
|
if (!ADD_RDLEN(header, p, plen, rdlen))
|
||||||
return STAT_BOGUS; /* bad packet */
|
return STAT_BOGUS; /* bad packet */
|
||||||
}
|
}
|
||||||
|
|
||||||
cache_end_insert();
|
cache_end_insert();
|
||||||
|
|
||||||
|
/* Fall through if no supported algo DS found. */
|
||||||
|
if (found_supported)
|
||||||
|
return STAT_OK;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
|
flags = F_FORWARD | F_DS | F_NEG | F_DNSSECOK;
|
||||||
|
|
||||||
|
if (neganswer)
|
||||||
{
|
{
|
||||||
int flags = F_FORWARD | F_DS | F_NEG | F_DNSSECOK;
|
|
||||||
|
|
||||||
if (RCODE(header) == NXDOMAIN)
|
if (RCODE(header) == NXDOMAIN)
|
||||||
flags |= F_NXDOMAIN;
|
flags |= F_NXDOMAIN;
|
||||||
|
|
||||||
@@ -1110,17 +1124,18 @@ int dnssec_validate_ds(time_t now, struct dns_header *header, size_t plen, char
|
|||||||
to store presence/absence of NS. */
|
to store presence/absence of NS. */
|
||||||
if (nons)
|
if (nons)
|
||||||
flags &= ~F_DNSSECOK;
|
flags &= ~F_DNSSECOK;
|
||||||
|
|
||||||
cache_start_insert();
|
|
||||||
|
|
||||||
/* Use TTL from NSEC for negative cache entries */
|
|
||||||
if (!cache_insert(name, NULL, class, now, neg_ttl, flags))
|
|
||||||
return STAT_BOGUS;
|
|
||||||
|
|
||||||
cache_end_insert();
|
|
||||||
|
|
||||||
log_query(F_NOEXTRA | F_UPSTREAM, name, NULL, nons ? "no DS/cut" : "no DS", 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cache_start_insert();
|
||||||
|
|
||||||
|
/* Use TTL from NSEC for negative cache entries */
|
||||||
|
if (!cache_insert(name, NULL, class, now, neg_ttl, flags))
|
||||||
|
return STAT_BOGUS;
|
||||||
|
|
||||||
|
cache_end_insert();
|
||||||
|
|
||||||
|
if (neganswer)
|
||||||
|
log_query(F_NOEXTRA | F_UPSTREAM, name, NULL, nons ? "no DS/cut" : "no DS", 0);
|
||||||
|
|
||||||
return STAT_OK;
|
return STAT_OK;
|
||||||
}
|
}
|
||||||
|
|||||||
+35
-20
@@ -546,11 +546,23 @@ static int order_qsort(const void *a, const void *b)
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* When loading large numbers of server=.... lines during startup,
|
||||||
|
there's no possibility that there will be server records that can be reused, but
|
||||||
|
searching a long list for each server added grows as O(n^2) and slows things down.
|
||||||
|
This flag is set only if is known there may be free server records that can be reused.
|
||||||
|
There's a call to mark_servers(0) in read_opts() to reset the flag before
|
||||||
|
main config read. */
|
||||||
|
|
||||||
|
static int maybe_free_servers = 0;
|
||||||
|
|
||||||
/* Must be called before add_update_server() to set daemon->servers_tail */
|
/* Must be called before add_update_server() to set daemon->servers_tail */
|
||||||
void mark_servers(int flag)
|
void mark_servers(int flag)
|
||||||
{
|
{
|
||||||
struct server *serv, **up;
|
struct server *serv, **up;
|
||||||
|
|
||||||
|
maybe_free_servers = !!flag;
|
||||||
|
|
||||||
daemon->servers_tail = NULL;
|
daemon->servers_tail = NULL;
|
||||||
|
|
||||||
/* mark everything with argument flag */
|
/* mark everything with argument flag */
|
||||||
@@ -667,27 +679,30 @@ int add_update_server(int flags,
|
|||||||
and move to the end of the list, for order. The entry found may already
|
and move to the end of the list, for order. The entry found may already
|
||||||
be at the end. */
|
be at the end. */
|
||||||
struct server **up, *tmp;
|
struct server **up, *tmp;
|
||||||
|
|
||||||
for (serv = daemon->servers, up = &daemon->servers; serv; serv = tmp)
|
|
||||||
{
|
|
||||||
tmp = serv->next;
|
|
||||||
if ((serv->flags & SERV_MARK) &&
|
|
||||||
hostname_isequal(alloc_domain, serv->domain))
|
|
||||||
{
|
|
||||||
/* Need to move down? */
|
|
||||||
if (serv->next)
|
|
||||||
{
|
|
||||||
*up = serv->next;
|
|
||||||
daemon->servers_tail->next = serv;
|
|
||||||
daemon->servers_tail = serv;
|
|
||||||
serv->next = NULL;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
up = &serv->next;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
serv = NULL;
|
||||||
|
|
||||||
|
if (maybe_free_servers)
|
||||||
|
for (serv = daemon->servers, up = &daemon->servers; serv; serv = tmp)
|
||||||
|
{
|
||||||
|
tmp = serv->next;
|
||||||
|
if ((serv->flags & SERV_MARK) &&
|
||||||
|
hostname_isequal(alloc_domain, serv->domain))
|
||||||
|
{
|
||||||
|
/* Need to move down? */
|
||||||
|
if (serv->next)
|
||||||
|
{
|
||||||
|
*up = serv->next;
|
||||||
|
daemon->servers_tail->next = serv;
|
||||||
|
daemon->servers_tail = serv;
|
||||||
|
serv->next = NULL;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
up = &serv->next;
|
||||||
|
}
|
||||||
|
|
||||||
if (serv)
|
if (serv)
|
||||||
{
|
{
|
||||||
free(alloc_domain);
|
free(alloc_domain);
|
||||||
|
|||||||
+57
-35
@@ -860,14 +860,18 @@ char *parse_server(char *arg, struct server_details *sdetails)
|
|||||||
sdetails->serv_port = NAMESERVER_PORT;
|
sdetails->serv_port = NAMESERVER_PORT;
|
||||||
char *portno;
|
char *portno;
|
||||||
int ecode = 0;
|
int ecode = 0;
|
||||||
struct addrinfo hints = { 0 };
|
struct addrinfo hints;
|
||||||
|
|
||||||
|
memset(&hints, 0, sizeof(struct addrinfo));
|
||||||
|
|
||||||
*sdetails->interface = 0;
|
*sdetails->interface = 0;
|
||||||
|
sdetails->addr_type = AF_UNSPEC;
|
||||||
|
|
||||||
if (strcmp(arg, "#") == 0)
|
if (strcmp(arg, "#") == 0)
|
||||||
{
|
{
|
||||||
if (sdetails->flags)
|
if (sdetails->flags)
|
||||||
*sdetails->flags |= SERV_USE_RESOLV;
|
*sdetails->flags |= SERV_USE_RESOLV;
|
||||||
|
sdetails->addr_type = AF_LOCAL;
|
||||||
sdetails->valid = 1;
|
sdetails->valid = 1;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -941,7 +945,7 @@ char *parse_server(char *arg, struct server_details *sdetails)
|
|||||||
above, and returns a pointer to the start of the list in <hostinfo>.
|
above, and returns a pointer to the start of the list in <hostinfo>.
|
||||||
The items in the linked list are linked by the <ai_next> field. */
|
The items in the linked list are linked by the <ai_next> field. */
|
||||||
sdetails->valid = 1;
|
sdetails->valid = 1;
|
||||||
sdetails->resolved = 1;
|
sdetails->orig_hostinfo = sdetails->hostinfo;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -965,7 +969,7 @@ char *parse_server_addr(struct server_details *sdetails)
|
|||||||
sdetails->addr->in.sin_port = htons(sdetails->serv_port);
|
sdetails->addr->in.sin_port = htons(sdetails->serv_port);
|
||||||
sdetails->addr->sa.sa_family = sdetails->source_addr->sa.sa_family = AF_INET;
|
sdetails->addr->sa.sa_family = sdetails->source_addr->sa.sa_family = AF_INET;
|
||||||
#ifdef HAVE_SOCKADDR_SA_LEN
|
#ifdef HAVE_SOCKADDR_SA_LEN
|
||||||
source_addr->in.sin_len = addr->in.sin_len = sizeof(struct sockaddr_in);
|
sdetails->source_addr->in.sin_len = sdetails->addr->in.sin_len = sizeof(struct sockaddr_in);
|
||||||
#endif
|
#endif
|
||||||
sdetails->source_addr->in.sin_addr.s_addr = INADDR_ANY;
|
sdetails->source_addr->in.sin_addr.s_addr = INADDR_ANY;
|
||||||
sdetails->source_addr->in.sin_port = htons(daemon->query_port);
|
sdetails->source_addr->in.sin_port = htons(daemon->query_port);
|
||||||
@@ -983,7 +987,7 @@ char *parse_server_addr(struct server_details *sdetails)
|
|||||||
/* When resolving a server IP by hostname, we can simply skip mismatching
|
/* When resolving a server IP by hostname, we can simply skip mismatching
|
||||||
server / source IP pairs. Otherwise, when an IP address is given directly,
|
server / source IP pairs. Otherwise, when an IP address is given directly,
|
||||||
this is a fatal error. */
|
this is a fatal error. */
|
||||||
if (!sdetails->resolved)
|
if (!sdetails->orig_hostinfo)
|
||||||
return _("cannot use IPv4 server address with IPv6 source address");
|
return _("cannot use IPv4 server address with IPv6 source address");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -1014,7 +1018,7 @@ char *parse_server_addr(struct server_details *sdetails)
|
|||||||
sdetails->addr->sa.sa_family = sdetails->source_addr->sa.sa_family = AF_INET6;
|
sdetails->addr->sa.sa_family = sdetails->source_addr->sa.sa_family = AF_INET6;
|
||||||
sdetails->addr->in6.sin6_flowinfo = sdetails->source_addr->in6.sin6_flowinfo = 0;
|
sdetails->addr->in6.sin6_flowinfo = sdetails->source_addr->in6.sin6_flowinfo = 0;
|
||||||
#ifdef HAVE_SOCKADDR_SA_LEN
|
#ifdef HAVE_SOCKADDR_SA_LEN
|
||||||
sdetails->addr->in6.sin6_len = sdetails->source_addr->in6.sin6_len = sizeof(addr->in6);
|
sdetails->addr->in6.sin6_len = sdetails->source_addr->in6.sin6_len = sizeof(sdetails->addr->in6);
|
||||||
#endif
|
#endif
|
||||||
if (sdetails->source)
|
if (sdetails->source)
|
||||||
{
|
{
|
||||||
@@ -1029,7 +1033,7 @@ char *parse_server_addr(struct server_details *sdetails)
|
|||||||
/* When resolving a server IP by hostname, we can simply skip mismatching
|
/* When resolving a server IP by hostname, we can simply skip mismatching
|
||||||
server / source IP pairs. Otherwise, when an IP address is given directly,
|
server / source IP pairs. Otherwise, when an IP address is given directly,
|
||||||
this is a fatal error. */
|
this is a fatal error. */
|
||||||
if(!sdetails->resolved)
|
if(!sdetails->orig_hostinfo)
|
||||||
return _("cannot use IPv6 server address with IPv4 source address");
|
return _("cannot use IPv6 server address with IPv4 source address");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -1047,12 +1051,13 @@ char *parse_server_addr(struct server_details *sdetails)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else if (sdetails->addr_type != AF_LOCAL)
|
||||||
return _("bad address");
|
return _("bad address");
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int parse_server_next(struct server_details *sdetails)
|
int parse_server_next(struct server_details *sdetails)
|
||||||
{
|
{
|
||||||
/* Looping over resolved addresses? */
|
/* Looping over resolved addresses? */
|
||||||
if (sdetails->hostinfo)
|
if (sdetails->hostinfo)
|
||||||
@@ -1095,12 +1100,14 @@ static char *domain_rev4(int from_file, char *server, struct in_addr *addr4, int
|
|||||||
union mysockaddr serv_addr, source_addr;
|
union mysockaddr serv_addr, source_addr;
|
||||||
char interface[IF_NAMESIZE+1];
|
char interface[IF_NAMESIZE+1];
|
||||||
int count = 1, rem, addrbytes, addrbits;
|
int count = 1, rem, addrbytes, addrbits;
|
||||||
struct server_details sdetails = { 0 };
|
struct server_details sdetails;
|
||||||
|
|
||||||
|
memset(&sdetails, 0, sizeof(struct server_details));
|
||||||
sdetails.addr = &serv_addr;
|
sdetails.addr = &serv_addr;
|
||||||
sdetails.source_addr = &source_addr;
|
sdetails.source_addr = &source_addr;
|
||||||
sdetails.interface = interface;
|
sdetails.interface = interface;
|
||||||
sdetails.flags = &flags;
|
sdetails.flags = &flags;
|
||||||
|
|
||||||
if (!server)
|
if (!server)
|
||||||
flags = SERV_LITERAL_ADDRESS;
|
flags = SERV_LITERAL_ADDRESS;
|
||||||
else if ((string = parse_server(server, &sdetails)))
|
else if ((string = parse_server(server, &sdetails)))
|
||||||
@@ -1157,6 +1164,9 @@ static char *domain_rev4(int from_file, char *server, struct in_addr *addr4, int
|
|||||||
if (!add_update_server(flags, &serv_addr, &source_addr, interface, domain, NULL))
|
if (!add_update_server(flags, &serv_addr, &source_addr, interface, domain, NULL))
|
||||||
return _("error");
|
return _("error");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (sdetails.orig_hostinfo)
|
||||||
|
freeaddrinfo(sdetails.orig_hostinfo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1173,12 +1183,14 @@ static char *domain_rev6(int from_file, char *server, struct in6_addr *addr6, in
|
|||||||
union mysockaddr serv_addr, source_addr;
|
union mysockaddr serv_addr, source_addr;
|
||||||
char interface[IF_NAMESIZE+1];
|
char interface[IF_NAMESIZE+1];
|
||||||
int count = 1, rem, addrbytes, addrbits;
|
int count = 1, rem, addrbytes, addrbits;
|
||||||
struct server_details sdetails = { 0 };
|
struct server_details sdetails;
|
||||||
|
|
||||||
|
memset(&sdetails, 0, sizeof(struct server_details));
|
||||||
sdetails.addr = &serv_addr;
|
sdetails.addr = &serv_addr;
|
||||||
sdetails.source_addr = &source_addr;
|
sdetails.source_addr = &source_addr;
|
||||||
sdetails.interface = interface;
|
sdetails.interface = interface;
|
||||||
sdetails.flags = &flags;
|
sdetails.flags = &flags;
|
||||||
|
|
||||||
if (!server)
|
if (!server)
|
||||||
flags = SERV_LITERAL_ADDRESS;
|
flags = SERV_LITERAL_ADDRESS;
|
||||||
else if ((string = parse_server(server, &sdetails)))
|
else if ((string = parse_server(server, &sdetails)))
|
||||||
@@ -1237,6 +1249,9 @@ static char *domain_rev6(int from_file, char *server, struct in6_addr *addr6, in
|
|||||||
if (!add_update_server(flags, &serv_addr, &source_addr, interface, domain, NULL))
|
if (!add_update_server(flags, &serv_addr, &source_addr, interface, domain, NULL))
|
||||||
return _("error");
|
return _("error");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (sdetails.orig_hostinfo)
|
||||||
|
freeaddrinfo(sdetails.orig_hostinfo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2950,19 +2965,20 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
|||||||
case LOPT_LOCAL: /* --local */
|
case LOPT_LOCAL: /* --local */
|
||||||
case 'A': /* --address */
|
case 'A': /* --address */
|
||||||
{
|
{
|
||||||
char *lastdomain = NULL, *domain = "";
|
char *lastdomain = NULL, *domain = "", *cur_domain;
|
||||||
u16 flags = 0;
|
u16 flags = 0;
|
||||||
char *err;
|
char *err;
|
||||||
union all_addr addr;
|
union all_addr addr;
|
||||||
union mysockaddr serv_addr, source_addr;
|
union mysockaddr serv_addr, source_addr;
|
||||||
char interface[IF_NAMESIZE+1];
|
char interface[IF_NAMESIZE+1];
|
||||||
|
struct server_details sdetails;
|
||||||
|
|
||||||
struct server_details sdetails = { 0 };
|
memset(&sdetails, 0, sizeof(struct server_details));
|
||||||
sdetails.addr = &serv_addr;
|
sdetails.addr = &serv_addr;
|
||||||
sdetails.source_addr = &source_addr;
|
sdetails.source_addr = &source_addr;
|
||||||
sdetails.interface = interface;
|
sdetails.interface = interface;
|
||||||
sdetails.flags = &flags;
|
sdetails.flags = &flags;
|
||||||
|
|
||||||
unhide_metas(arg);
|
unhide_metas(arg);
|
||||||
|
|
||||||
/* split the domain args, if any and skip to the end of them. */
|
/* split the domain args, if any and skip to the end of them. */
|
||||||
@@ -3001,9 +3017,12 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
|||||||
|
|
||||||
if (servers_only && option == 'S')
|
if (servers_only && option == 'S')
|
||||||
flags |= SERV_FROM_FILE;
|
flags |= SERV_FROM_FILE;
|
||||||
|
|
||||||
|
cur_domain = domain;
|
||||||
while ((flags & SERV_LITERAL_ADDRESS) || parse_server_next(&sdetails))
|
while ((flags & SERV_LITERAL_ADDRESS) || parse_server_next(&sdetails))
|
||||||
{
|
{
|
||||||
|
cur_domain = domain;
|
||||||
|
|
||||||
if (!(flags & SERV_LITERAL_ADDRESS) && (err = parse_server_addr(&sdetails)))
|
if (!(flags & SERV_LITERAL_ADDRESS) && (err = parse_server_addr(&sdetails)))
|
||||||
ret_err(err);
|
ret_err(err);
|
||||||
|
|
||||||
@@ -3015,32 +3034,32 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
|
|||||||
{
|
{
|
||||||
/* server=//1.2.3.4 is special. */
|
/* server=//1.2.3.4 is special. */
|
||||||
if (lastdomain)
|
if (lastdomain)
|
||||||
{
|
{
|
||||||
if (strlen(domain) == 0)
|
if (strlen(cur_domain) == 0)
|
||||||
flags |= SERV_FOR_NODOTS;
|
flags |= SERV_FOR_NODOTS;
|
||||||
else
|
else
|
||||||
flags &= ~SERV_FOR_NODOTS;
|
flags &= ~SERV_FOR_NODOTS;
|
||||||
|
|
||||||
/* address=/#/ matches the same as without domain */
|
/* address=/#/ matches the same as without domain */
|
||||||
if (option == 'A' && domain[0] == '#' && domain[1] == 0)
|
if (option == 'A' && cur_domain[0] == '#' && cur_domain[1] == 0)
|
||||||
domain[0] = 0;
|
cur_domain[0] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!add_update_server(flags, sdetails.addr, sdetails.source_addr, sdetails.interface, domain, &addr))
|
if (!add_update_server(flags, sdetails.addr, sdetails.source_addr, sdetails.interface, cur_domain, &addr))
|
||||||
ret_err(gen_err);
|
ret_err(gen_err);
|
||||||
|
|
||||||
if (!lastdomain || domain == lastdomain)
|
if (!lastdomain || cur_domain == lastdomain)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
domain += strlen(domain) + 1;
|
cur_domain += strlen(cur_domain) + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (flags & SERV_LITERAL_ADDRESS)
|
if (flags & SERV_LITERAL_ADDRESS)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sdetails.resolved)
|
if (sdetails.orig_hostinfo)
|
||||||
freeaddrinfo(sdetails.hostinfo);
|
freeaddrinfo(sdetails.orig_hostinfo);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -5734,7 +5753,10 @@ void read_opts(int argc, char **argv, char *compile_opts)
|
|||||||
#endif
|
#endif
|
||||||
add_txt("servers.bind", NULL, TXT_STAT_SERVERS);
|
add_txt("servers.bind", NULL, TXT_STAT_SERVERS);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* See comment above make_servers(). Optimises server-read code. */
|
||||||
|
mark_servers(0);
|
||||||
|
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
#ifdef HAVE_GETOPT_LONG
|
#ifdef HAVE_GETOPT_LONG
|
||||||
|
|||||||
Reference in new issue
Block a user