mirror of
https://github.com/pi-hole/dnsmasq.git
synced 2025-12-24 12:48:32 +00:00
Cache SRV records.
Inpsired by a patch from Jeremy Allison, but completely re-rolled by srk. All bugs are mine.
This commit is contained in:
@@ -129,7 +129,7 @@ size_t answer_auth(struct dns_header *header, char *limit, size_t qlen, time_t n
|
|||||||
|
|
||||||
for (q = ntohs(header->qdcount); q != 0; q--)
|
for (q = ntohs(header->qdcount); q != 0; q--)
|
||||||
{
|
{
|
||||||
unsigned short flag = 0;
|
unsigned int flag = 0;
|
||||||
int found = 0;
|
int found = 0;
|
||||||
int cname_wildcard = 0;
|
int cname_wildcard = 0;
|
||||||
|
|
||||||
|
|||||||
@@ -16,8 +16,6 @@
|
|||||||
|
|
||||||
#include "dnsmasq.h"
|
#include "dnsmasq.h"
|
||||||
|
|
||||||
#ifdef HAVE_DNSSEC
|
|
||||||
|
|
||||||
static struct blockdata *keyblock_free;
|
static struct blockdata *keyblock_free;
|
||||||
static unsigned int blockdata_count, blockdata_hwm, blockdata_alloced;
|
static unsigned int blockdata_count, blockdata_hwm, blockdata_alloced;
|
||||||
|
|
||||||
@@ -54,8 +52,7 @@ void blockdata_init(void)
|
|||||||
|
|
||||||
void blockdata_report(void)
|
void blockdata_report(void)
|
||||||
{
|
{
|
||||||
if (option_bool(OPT_DNSSEC_VALID))
|
my_syslog(LOG_INFO, _("pool memory in use %u, max %u, allocated %u"),
|
||||||
my_syslog(LOG_INFO, _("DNSSEC memory in use %u, max %u, allocated %u"),
|
|
||||||
blockdata_count * sizeof(struct blockdata),
|
blockdata_count * sizeof(struct blockdata),
|
||||||
blockdata_hwm * sizeof(struct blockdata),
|
blockdata_hwm * sizeof(struct blockdata),
|
||||||
blockdata_alloced * sizeof(struct blockdata));
|
blockdata_alloced * sizeof(struct blockdata));
|
||||||
@@ -178,4 +175,3 @@ struct blockdata *blockdata_read(int fd, size_t len)
|
|||||||
return blockdata_alloc_real(fd, NULL, len);
|
return blockdata_alloc_real(fd, NULL, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|||||||
62
src/cache.c
62
src/cache.c
@@ -27,7 +27,7 @@ static int bignames_left, hash_size;
|
|||||||
|
|
||||||
static void make_non_terminals(struct crec *source);
|
static void make_non_terminals(struct crec *source);
|
||||||
static struct crec *really_insert(char *name, union all_addr *addr, unsigned short class,
|
static struct crec *really_insert(char *name, union all_addr *addr, unsigned short class,
|
||||||
time_t now, unsigned long ttl, unsigned short flags);
|
time_t now, unsigned long ttl, unsigned int flags);
|
||||||
|
|
||||||
/* type->string mapping: this is also used by the name-hash function as a mixing table. */
|
/* type->string mapping: this is also used by the name-hash function as a mixing table. */
|
||||||
static const struct {
|
static const struct {
|
||||||
@@ -198,15 +198,17 @@ static void cache_hash(struct crec *crecp)
|
|||||||
*up = crecp;
|
*up = crecp;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_DNSSEC
|
|
||||||
static void cache_blockdata_free(struct crec *crecp)
|
static void cache_blockdata_free(struct crec *crecp)
|
||||||
{
|
{
|
||||||
if (crecp->flags & F_DNSKEY)
|
if (crecp->flags & F_SRV)
|
||||||
|
blockdata_free(crecp->addr.srv.target);
|
||||||
|
#ifdef HAVE_DNSSEC
|
||||||
|
else if (crecp->flags & F_DNSKEY)
|
||||||
blockdata_free(crecp->addr.key.keydata);
|
blockdata_free(crecp->addr.key.keydata);
|
||||||
else if ((crecp->flags & F_DS) && !(crecp->flags & F_NEG))
|
else if ((crecp->flags & F_DS) && !(crecp->flags & F_NEG))
|
||||||
blockdata_free(crecp->addr.ds.keydata);
|
blockdata_free(crecp->addr.ds.keydata);
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
static void cache_free(struct crec *crecp)
|
static void cache_free(struct crec *crecp)
|
||||||
{
|
{
|
||||||
@@ -230,9 +232,7 @@ static void cache_free(struct crec *crecp)
|
|||||||
crecp->flags &= ~F_BIGNAME;
|
crecp->flags &= ~F_BIGNAME;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_DNSSEC
|
|
||||||
cache_blockdata_free(crecp);
|
cache_blockdata_free(crecp);
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* insert a new cache entry at the head of the list (youngest entry) */
|
/* insert a new cache entry at the head of the list (youngest entry) */
|
||||||
@@ -331,7 +331,7 @@ static int is_expired(time_t now, struct crec *crecp)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static struct crec *cache_scan_free(char *name, union all_addr *addr, unsigned short class, time_t now,
|
static struct crec *cache_scan_free(char *name, union all_addr *addr, unsigned short class, time_t now,
|
||||||
unsigned short flags, struct crec **target_crec, unsigned int *target_uid)
|
unsigned int flags, struct crec **target_crec, unsigned int *target_uid)
|
||||||
{
|
{
|
||||||
/* Scan and remove old entries.
|
/* Scan and remove old entries.
|
||||||
If (flags & F_FORWARD) then remove any forward entries for name and any expired
|
If (flags & F_FORWARD) then remove any forward entries for name and any expired
|
||||||
@@ -360,7 +360,7 @@ static struct crec *cache_scan_free(char *name, union all_addr *addr, unsigned s
|
|||||||
if ((crecp->flags & F_FORWARD) && hostname_isequal(cache_get_name(crecp), name))
|
if ((crecp->flags & F_FORWARD) && hostname_isequal(cache_get_name(crecp), name))
|
||||||
{
|
{
|
||||||
/* Don't delete DNSSEC in favour of a CNAME, they can co-exist */
|
/* Don't delete DNSSEC in favour of a CNAME, they can co-exist */
|
||||||
if ((flags & crecp->flags & (F_IPV4 | F_IPV6)) ||
|
if ((flags & crecp->flags & (F_IPV4 | F_IPV6 | F_SRV)) ||
|
||||||
(((crecp->flags | flags) & F_CNAME) && !(crecp->flags & (F_DNSKEY | F_DS))))
|
(((crecp->flags | flags) & F_CNAME) && !(crecp->flags & (F_DNSKEY | F_DS))))
|
||||||
{
|
{
|
||||||
if (crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG))
|
if (crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG))
|
||||||
@@ -467,10 +467,10 @@ void cache_start_insert(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct crec *cache_insert(char *name, union all_addr *addr, unsigned short class,
|
struct crec *cache_insert(char *name, union all_addr *addr, unsigned short class,
|
||||||
time_t now, unsigned long ttl, unsigned short flags)
|
time_t now, unsigned long ttl, unsigned int flags)
|
||||||
{
|
{
|
||||||
/* Don't log DNSSEC records here, done elsewhere */
|
/* Don't log DNSSEC records here, done elsewhere */
|
||||||
if (flags & (F_IPV4 | F_IPV6 | F_CNAME))
|
if (flags & (F_IPV4 | F_IPV6 | F_CNAME | F_SRV))
|
||||||
{
|
{
|
||||||
log_query(flags | F_UPSTREAM, name, addr, NULL);
|
log_query(flags | F_UPSTREAM, name, addr, NULL);
|
||||||
/* Don't mess with TTL for DNSSEC records. */
|
/* Don't mess with TTL for DNSSEC records. */
|
||||||
@@ -485,7 +485,7 @@ struct crec *cache_insert(char *name, union all_addr *addr, unsigned short class
|
|||||||
|
|
||||||
|
|
||||||
static struct crec *really_insert(char *name, union all_addr *addr, unsigned short class,
|
static struct crec *really_insert(char *name, union all_addr *addr, unsigned short class,
|
||||||
time_t now, unsigned long ttl, unsigned short flags)
|
time_t now, unsigned long ttl, unsigned int flags)
|
||||||
{
|
{
|
||||||
struct crec *new, *target_crec = NULL;
|
struct crec *new, *target_crec = NULL;
|
||||||
union bigname *big_name = NULL;
|
union bigname *big_name = NULL;
|
||||||
@@ -649,7 +649,7 @@ void cache_end_insert(void)
|
|||||||
{
|
{
|
||||||
char *name = cache_get_name(new_chain);
|
char *name = cache_get_name(new_chain);
|
||||||
ssize_t m = strlen(name);
|
ssize_t m = strlen(name);
|
||||||
unsigned short flags = new_chain->flags;
|
unsigned int flags = new_chain->flags;
|
||||||
#ifdef HAVE_DNSSEC
|
#ifdef HAVE_DNSSEC
|
||||||
u16 class = new_chain->uid;
|
u16 class = new_chain->uid;
|
||||||
#endif
|
#endif
|
||||||
@@ -659,8 +659,10 @@ void cache_end_insert(void)
|
|||||||
read_write(daemon->pipe_to_parent, (unsigned char *)&new_chain->ttd, sizeof(new_chain->ttd), 0);
|
read_write(daemon->pipe_to_parent, (unsigned char *)&new_chain->ttd, sizeof(new_chain->ttd), 0);
|
||||||
read_write(daemon->pipe_to_parent, (unsigned char *)&flags, sizeof(flags), 0);
|
read_write(daemon->pipe_to_parent, (unsigned char *)&flags, sizeof(flags), 0);
|
||||||
|
|
||||||
if (flags & (F_IPV4 | F_IPV6 | F_DNSKEY | F_DS))
|
if (flags & (F_IPV4 | F_IPV6 | F_DNSKEY | F_DS | F_SRV))
|
||||||
read_write(daemon->pipe_to_parent, (unsigned char *)&new_chain->addr, sizeof(new_chain->addr), 0);
|
read_write(daemon->pipe_to_parent, (unsigned char *)&new_chain->addr, sizeof(new_chain->addr), 0);
|
||||||
|
if (flags & F_SRV)
|
||||||
|
blockdata_write(new_chain->addr.srv.target, new_chain->addr.srv.targetlen, daemon->pipe_to_parent);
|
||||||
#ifdef HAVE_DNSSEC
|
#ifdef HAVE_DNSSEC
|
||||||
if (flags & F_DNSKEY)
|
if (flags & F_DNSKEY)
|
||||||
{
|
{
|
||||||
@@ -699,7 +701,7 @@ int cache_recv_insert(time_t now, int fd)
|
|||||||
union all_addr addr;
|
union all_addr addr;
|
||||||
unsigned long ttl;
|
unsigned long ttl;
|
||||||
time_t ttd;
|
time_t ttd;
|
||||||
unsigned short flags;
|
unsigned int flags;
|
||||||
struct crec *crecp = NULL;
|
struct crec *crecp = NULL;
|
||||||
|
|
||||||
cache_start_insert();
|
cache_start_insert();
|
||||||
@@ -725,13 +727,16 @@ int cache_recv_insert(time_t now, int fd)
|
|||||||
|
|
||||||
ttl = difftime(ttd, now);
|
ttl = difftime(ttd, now);
|
||||||
|
|
||||||
if (flags & (F_IPV4 | F_IPV6 | F_DNSKEY | F_DS))
|
if (flags & (F_IPV4 | F_IPV6 | F_DNSKEY | F_DS | F_SRV))
|
||||||
{
|
{
|
||||||
unsigned short class = C_IN;
|
unsigned short class = C_IN;
|
||||||
|
|
||||||
if (!read_write(fd, (unsigned char *)&addr, sizeof(addr), 1))
|
if (!read_write(fd, (unsigned char *)&addr, sizeof(addr), 1))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
if (flags & F_SRV && !(addr.srv.target = blockdata_read(fd, addr.srv.targetlen)))
|
||||||
|
return 0;
|
||||||
|
|
||||||
#ifdef HAVE_DNSSEC
|
#ifdef HAVE_DNSSEC
|
||||||
if (flags & F_DNSKEY)
|
if (flags & F_DNSKEY)
|
||||||
{
|
{
|
||||||
@@ -802,7 +807,7 @@ struct crec *cache_find_by_name(struct crec *crecp, char *name, time_t now, unsi
|
|||||||
/* first search, look for relevant entries and push to top of list
|
/* first search, look for relevant entries and push to top of list
|
||||||
also free anything which has expired */
|
also free anything which has expired */
|
||||||
struct crec *next, **up, **insert = NULL, **chainp = &ans;
|
struct crec *next, **up, **insert = NULL, **chainp = &ans;
|
||||||
unsigned short ins_flags = 0;
|
unsigned int ins_flags = 0;
|
||||||
|
|
||||||
for (up = hash_bucket(name), crecp = *up; crecp; crecp = next)
|
for (up = hash_bucket(name), crecp = *up; crecp; crecp = next)
|
||||||
{
|
{
|
||||||
@@ -1086,7 +1091,7 @@ int read_hostsfile(char *filename, unsigned int index, int cache_size, struct cr
|
|||||||
FILE *f = fopen(filename, "r");
|
FILE *f = fopen(filename, "r");
|
||||||
char *token = daemon->namebuff, *domain_suffix = NULL;
|
char *token = daemon->namebuff, *domain_suffix = NULL;
|
||||||
int addr_count = 0, name_count = cache_size, lineno = 0;
|
int addr_count = 0, name_count = cache_size, lineno = 0;
|
||||||
unsigned short flags = 0;
|
unsigned int flags = 0;
|
||||||
union all_addr addr;
|
union all_addr addr;
|
||||||
int atnl, addrlen = 0;
|
int atnl, addrlen = 0;
|
||||||
|
|
||||||
@@ -1201,9 +1206,8 @@ void cache_reload(void)
|
|||||||
for (i=0; i<hash_size; i++)
|
for (i=0; i<hash_size; i++)
|
||||||
for (cache = hash_table[i], up = &hash_table[i]; cache; cache = tmp)
|
for (cache = hash_table[i], up = &hash_table[i]; cache; cache = tmp)
|
||||||
{
|
{
|
||||||
#ifdef HAVE_DNSSEC
|
|
||||||
cache_blockdata_free(cache);
|
cache_blockdata_free(cache);
|
||||||
#endif
|
|
||||||
tmp = cache->hash_next;
|
tmp = cache->hash_next;
|
||||||
if (cache->flags & (F_HOSTS | F_CONFIG))
|
if (cache->flags & (F_HOSTS | F_CONFIG))
|
||||||
{
|
{
|
||||||
@@ -1381,7 +1385,7 @@ void cache_add_dhcp_entry(char *host_name, int prot,
|
|||||||
union all_addr *host_address, time_t ttd)
|
union all_addr *host_address, time_t ttd)
|
||||||
{
|
{
|
||||||
struct crec *crec = NULL, *fail_crec = NULL;
|
struct crec *crec = NULL, *fail_crec = NULL;
|
||||||
unsigned short flags = F_IPV4;
|
unsigned int flags = F_IPV4;
|
||||||
int in_hosts = 0;
|
int in_hosts = 0;
|
||||||
size_t addrlen = sizeof(struct in_addr);
|
size_t addrlen = sizeof(struct in_addr);
|
||||||
|
|
||||||
@@ -1682,9 +1686,8 @@ void dump_cache(time_t now)
|
|||||||
#ifdef HAVE_AUTH
|
#ifdef HAVE_AUTH
|
||||||
my_syslog(LOG_INFO, _("queries for authoritative zones %u"), daemon->metrics[METRIC_DNS_AUTH_ANSWERED]);
|
my_syslog(LOG_INFO, _("queries for authoritative zones %u"), daemon->metrics[METRIC_DNS_AUTH_ANSWERED]);
|
||||||
#endif
|
#endif
|
||||||
#ifdef HAVE_DNSSEC
|
|
||||||
blockdata_report();
|
blockdata_report();
|
||||||
#endif
|
|
||||||
|
|
||||||
/* sum counts from different records for same server */
|
/* sum counts from different records for same server */
|
||||||
for (serv = daemon->servers; serv; serv = serv->next)
|
for (serv = daemon->servers; serv; serv = serv->next)
|
||||||
@@ -1726,6 +1729,17 @@ void dump_cache(time_t now)
|
|||||||
p += sprintf(p, "%-30.30s ", sanitise(n));
|
p += sprintf(p, "%-30.30s ", sanitise(n));
|
||||||
if ((cache->flags & F_CNAME) && !is_outdated_cname_pointer(cache))
|
if ((cache->flags & F_CNAME) && !is_outdated_cname_pointer(cache))
|
||||||
a = sanitise(cache_get_cname_target(cache));
|
a = sanitise(cache_get_cname_target(cache));
|
||||||
|
else if ((cache->flags & F_SRV) && !(cache->flags & F_NEG))
|
||||||
|
{
|
||||||
|
int targetlen = cache->addr.srv.targetlen;
|
||||||
|
ssize_t len = sprintf(a, "%u %u %u ", cache->addr.srv.priority,
|
||||||
|
cache->addr.srv.weight, cache->addr.srv.srvport);
|
||||||
|
|
||||||
|
if (targetlen > (40 - len))
|
||||||
|
targetlen = 40 - len;
|
||||||
|
blockdata_retrieve(cache->addr.srv.target, targetlen, a + len);
|
||||||
|
a[len + targetlen] = 0;
|
||||||
|
}
|
||||||
#ifdef HAVE_DNSSEC
|
#ifdef HAVE_DNSSEC
|
||||||
else if (cache->flags & F_DS)
|
else if (cache->flags & F_DS)
|
||||||
{
|
{
|
||||||
@@ -1752,6 +1766,8 @@ void dump_cache(time_t now)
|
|||||||
t = "6";
|
t = "6";
|
||||||
else if (cache->flags & F_CNAME)
|
else if (cache->flags & F_CNAME)
|
||||||
t = "C";
|
t = "C";
|
||||||
|
else if (cache->flags & F_SRV)
|
||||||
|
t = "V";
|
||||||
#ifdef HAVE_DNSSEC
|
#ifdef HAVE_DNSSEC
|
||||||
else if (cache->flags & F_DS)
|
else if (cache->flags & F_DS)
|
||||||
t = "S";
|
t = "S";
|
||||||
@@ -1913,6 +1929,8 @@ void log_query(unsigned int flags, char *name, union all_addr *addr, char *arg)
|
|||||||
}
|
}
|
||||||
else if (flags & F_CNAME)
|
else if (flags & F_CNAME)
|
||||||
dest = "<CNAME>";
|
dest = "<CNAME>";
|
||||||
|
else if (flags & F_SRV)
|
||||||
|
dest = "<SRV>";
|
||||||
else if (flags & F_RRNAME)
|
else if (flags & F_RRNAME)
|
||||||
dest = arg;
|
dest = arg;
|
||||||
|
|
||||||
|
|||||||
@@ -366,9 +366,7 @@ int main (int argc, char **argv)
|
|||||||
{
|
{
|
||||||
cache_init();
|
cache_init();
|
||||||
|
|
||||||
#ifdef HAVE_DNSSEC
|
|
||||||
blockdata_init();
|
blockdata_init();
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_INOTIFY
|
#ifdef HAVE_INOTIFY
|
||||||
|
|||||||
@@ -299,6 +299,10 @@ union all_addr {
|
|||||||
unsigned char algo;
|
unsigned char algo;
|
||||||
unsigned char digest;
|
unsigned char digest;
|
||||||
} ds;
|
} ds;
|
||||||
|
struct {
|
||||||
|
struct blockdata *target;
|
||||||
|
unsigned short targetlen, srvport, priority, weight;
|
||||||
|
} srv;
|
||||||
/* for log_query */
|
/* for log_query */
|
||||||
struct {
|
struct {
|
||||||
unsigned short keytag, algo, digest, rcode;
|
unsigned short keytag, algo, digest, rcode;
|
||||||
@@ -426,7 +430,7 @@ struct crec {
|
|||||||
time_t ttd; /* time to die */
|
time_t ttd; /* time to die */
|
||||||
/* used as class if DNSKEY/DS, index to source for F_HOSTS */
|
/* used as class if DNSKEY/DS, index to source for F_HOSTS */
|
||||||
unsigned int uid;
|
unsigned int uid;
|
||||||
unsigned short flags;
|
unsigned int flags;
|
||||||
union {
|
union {
|
||||||
char sname[SMALLDNAME];
|
char sname[SMALLDNAME];
|
||||||
union bigname *bname;
|
union bigname *bname;
|
||||||
@@ -470,6 +474,7 @@ struct crec {
|
|||||||
#define F_NOEXTRA (1u<<27)
|
#define F_NOEXTRA (1u<<27)
|
||||||
#define F_SERVFAIL (1u<<28)
|
#define F_SERVFAIL (1u<<28)
|
||||||
#define F_RCODE (1u<<29)
|
#define F_RCODE (1u<<29)
|
||||||
|
#define F_SRV (1u<<30)
|
||||||
|
|
||||||
#define UID_NONE 0
|
#define UID_NONE 0
|
||||||
/* Values of uid in crecs with F_CONFIG bit set. */
|
/* Values of uid in crecs with F_CONFIG bit set. */
|
||||||
@@ -1142,7 +1147,7 @@ void cache_end_insert(void);
|
|||||||
void cache_start_insert(void);
|
void cache_start_insert(void);
|
||||||
int cache_recv_insert(time_t now, int fd);
|
int cache_recv_insert(time_t now, int fd);
|
||||||
struct crec *cache_insert(char *name, union all_addr *addr, unsigned short class,
|
struct crec *cache_insert(char *name, union all_addr *addr, unsigned short class,
|
||||||
time_t now, unsigned long ttl, unsigned short flags);
|
time_t now, unsigned long ttl, unsigned int flags);
|
||||||
void cache_reload(void);
|
void cache_reload(void);
|
||||||
void cache_add_dhcp_entry(char *host_name, int prot, union all_addr *host_address, time_t ttd);
|
void cache_add_dhcp_entry(char *host_name, int prot, union all_addr *host_address, time_t ttd);
|
||||||
struct in_addr a_record_from_hosts(char *name, time_t now);
|
struct in_addr a_record_from_hosts(char *name, time_t now);
|
||||||
@@ -1158,7 +1163,6 @@ int read_hostsfile(char *filename, unsigned int index, int cache_size,
|
|||||||
struct crec **rhash, int hashsz);
|
struct crec **rhash, int hashsz);
|
||||||
|
|
||||||
/* blockdata.c */
|
/* blockdata.c */
|
||||||
#ifdef HAVE_DNSSEC
|
|
||||||
void blockdata_init(void);
|
void blockdata_init(void);
|
||||||
void blockdata_report(void);
|
void blockdata_report(void);
|
||||||
struct blockdata *blockdata_alloc(char *data, size_t len);
|
struct blockdata *blockdata_alloc(char *data, size_t len);
|
||||||
@@ -1166,7 +1170,6 @@ void *blockdata_retrieve(struct blockdata *block, size_t len, void *data);
|
|||||||
struct blockdata *blockdata_read(int fd, size_t len);
|
struct blockdata *blockdata_read(int fd, size_t len);
|
||||||
void blockdata_write(struct blockdata *block, size_t len, int fd);
|
void blockdata_write(struct blockdata *block, size_t len, int fd);
|
||||||
void blockdata_free(struct blockdata *blocks);
|
void blockdata_free(struct blockdata *blocks);
|
||||||
#endif
|
|
||||||
|
|
||||||
/* domain.c */
|
/* domain.c */
|
||||||
char *get_domain(struct in_addr addr);
|
char *get_domain(struct in_addr addr);
|
||||||
|
|||||||
@@ -726,7 +726,7 @@ int extract_addresses(struct dns_header *header, size_t qlen, char *name, time_t
|
|||||||
{
|
{
|
||||||
/* everything other than PTR */
|
/* everything other than PTR */
|
||||||
struct crec *newc;
|
struct crec *newc;
|
||||||
int addrlen;
|
int addrlen = 0;
|
||||||
|
|
||||||
if (qtype == T_A)
|
if (qtype == T_A)
|
||||||
{
|
{
|
||||||
@@ -738,6 +738,8 @@ int extract_addresses(struct dns_header *header, size_t qlen, char *name, time_t
|
|||||||
addrlen = IN6ADDRSZ;
|
addrlen = IN6ADDRSZ;
|
||||||
flags |= F_IPV6;
|
flags |= F_IPV6;
|
||||||
}
|
}
|
||||||
|
else if (qtype == T_SRV)
|
||||||
|
flags |= F_SRV;
|
||||||
else
|
else
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@@ -799,6 +801,27 @@ int extract_addresses(struct dns_header *header, size_t qlen, char *name, time_t
|
|||||||
{
|
{
|
||||||
found = 1;
|
found = 1;
|
||||||
|
|
||||||
|
if (flags & F_SRV)
|
||||||
|
{
|
||||||
|
unsigned char *tmp = namep;
|
||||||
|
|
||||||
|
if (!CHECK_LEN(header, p1, qlen, 6))
|
||||||
|
return 0; /* bad packet */
|
||||||
|
GETSHORT(addr.srv.priority, p1);
|
||||||
|
GETSHORT(addr.srv.weight, p1);
|
||||||
|
GETSHORT(addr.srv.srvport, p1);
|
||||||
|
if (!extract_name(header, qlen, &p1, name, 1, 0))
|
||||||
|
return 0;
|
||||||
|
addr.srv.targetlen = strlen(name) + 1; /* include terminating zero */
|
||||||
|
if (!(addr.srv.target = blockdata_alloc(name, addr.srv.targetlen)))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* we overwrote the original name, so get it back here. */
|
||||||
|
if (!extract_name(header, qlen, &tmp, name, 1, 0))
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
/* copy address into aligned storage */
|
/* copy address into aligned storage */
|
||||||
if (!CHECK_LEN(header, p1, qlen, addrlen))
|
if (!CHECK_LEN(header, p1, qlen, addrlen))
|
||||||
return 0; /* bad packet */
|
return 0; /* bad packet */
|
||||||
@@ -832,6 +855,7 @@ int extract_addresses(struct dns_header *header, size_t qlen, char *name, time_t
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
newc = cache_insert(name, &addr, C_IN, now, attl, flags | F_FORWARD | secflag);
|
newc = cache_insert(name, &addr, C_IN, now, attl, flags | F_FORWARD | secflag);
|
||||||
if (newc && cpp)
|
if (newc && cpp)
|
||||||
@@ -1845,6 +1869,67 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
|
|||||||
move->next = NULL;
|
move->next = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!found)
|
||||||
|
{
|
||||||
|
cname_srv_restart:
|
||||||
|
if ((crecp = cache_find_by_name(NULL, name, now, F_CNAME | F_SRV | (dryrun ? F_NO_RR : 0))) &&
|
||||||
|
(!do_bit || (option_bool(OPT_DNSSEC_VALID) && !(crecp->flags & F_DNSSECOK))))
|
||||||
|
{
|
||||||
|
if (!(crecp->flags & F_DNSSECOK))
|
||||||
|
sec_data = 0;
|
||||||
|
|
||||||
|
auth = 0;
|
||||||
|
found = ans = 1;
|
||||||
|
|
||||||
|
do {
|
||||||
|
if (crecp->flags & F_CNAME)
|
||||||
|
{
|
||||||
|
char *cname_target = cache_get_cname_target(crecp);
|
||||||
|
|
||||||
|
if (!dryrun)
|
||||||
|
{
|
||||||
|
log_query(crecp->flags, name, NULL, record_source(crecp->uid));
|
||||||
|
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
|
||||||
|
crec_ttl(crecp, now), &nameoffset,
|
||||||
|
T_CNAME, C_IN, "d", cname_target))
|
||||||
|
anscount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
strcpy(name, cname_target);
|
||||||
|
goto cname_srv_restart;
|
||||||
|
}
|
||||||
|
else if (crecp->flags & F_NEG)
|
||||||
|
{
|
||||||
|
if (crecp->flags & F_NXDOMAIN)
|
||||||
|
nxdomain = 1;
|
||||||
|
if (!dryrun)
|
||||||
|
log_query(crecp->flags, name, NULL, NULL);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
unsigned char *p1 = ((unsigned char *)header) + nameoffset;
|
||||||
|
|
||||||
|
if (!dryrun)
|
||||||
|
{
|
||||||
|
log_query(crecp->flags, name, NULL, 0);
|
||||||
|
|
||||||
|
blockdata_retrieve(crecp->addr.srv.target, crecp->addr.srv.targetlen, name);
|
||||||
|
if (add_resource_record(header, limit, &trunc, nameoffset, &ansp,
|
||||||
|
crec_ttl(crecp, now), NULL, T_SRV, C_IN, "sssd",
|
||||||
|
crecp->addr.srv.priority, crecp->addr.srv.weight, crecp->addr.srv.srvport,
|
||||||
|
name))
|
||||||
|
anscount++;
|
||||||
|
|
||||||
|
|
||||||
|
/* restore name we overwrote */
|
||||||
|
if (!extract_name(header, qlen, &p1, name, 1, 0))
|
||||||
|
return 0; /* bad packet */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} while ((crecp = cache_find_by_name(crecp, name, now, F_SRV | F_CNAME)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!found && option_bool(OPT_FILTER) && (qtype == T_SRV || (qtype == T_ANY && strchr(name, '_'))))
|
if (!found && option_bool(OPT_FILTER) && (qtype == T_SRV || (qtype == T_ANY && strchr(name, '_'))))
|
||||||
{
|
{
|
||||||
ans = 1;
|
ans = 1;
|
||||||
|
|||||||
Reference in New Issue
Block a user