[Dnsmasq-discuss] Patch to cache SRV records - version (#4)
Jeremy Allison
jra at google.com
Fri Dec 21 20:37:45 GMT 2018
Last version before Christmas, I promise :-).
Changes from version #3.
1). Use memset(&srv, '\0', sizeof(srv) to fully clean out SRV records
instead of setting 'src' and 'target' to NULL.
2). As requested by Donald Muller, add an option (I called it --srv-cache
but feel free to change if you want !) that turns on SRV record caching.
Note this is off by default.
Hope this works for everyone ! I've been testing this for
a while locally under valgrind and it seems robust.
Cheers,
Jeremy.
-------------- next part --------------
From e7b23f09804de982e8a19e38158011288c475260 Mon Sep 17 00:00:00 2001
From: Jeremy Allison <jra at google.com>
Date: Tue, 18 Dec 2018 10:44:08 -0800
Subject: [PATCH 1/7] Widen 'flags' field in cache to unsigned int from
unsigned short.
Ensure we still only cache unsigned short bits (0xFFFF).
Signed-off-by: Jeremy Allison <jra at google.com>
---
src/cache.c | 23 ++++++++++++++---------
src/dnsmasq.h | 6 ++++--
src/rfc1035.c | 2 +-
3 files changed, 19 insertions(+), 12 deletions(-)
diff --git a/src/cache.c b/src/cache.c
index 8662f54..cd72a0c 100644
--- a/src/cache.c
+++ b/src/cache.c
@@ -27,7 +27,7 @@ static int bignames_left, hash_size;
static void make_non_terminals(struct crec *source);
static struct crec *really_insert(char *name, struct all_addr *addr,
- 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. */
static const struct {
@@ -330,7 +330,7 @@ static int is_expired(time_t now, struct crec *crecp)
return 1;
}
-static struct crec *cache_scan_free(char *name, struct all_addr *addr, time_t now, unsigned short flags,
+static struct crec *cache_scan_free(char *name, struct all_addr *addr, time_t now, unsigned int flags,
struct crec **target_crec, unsigned int *target_uid)
{
/* Scan and remove old entries.
@@ -465,7 +465,7 @@ void cache_start_insert(void)
}
struct crec *cache_insert(char *name, struct all_addr *addr,
- 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 */
if (flags & (F_IPV4 | F_IPV6 | F_CNAME))
@@ -483,7 +483,7 @@ struct crec *cache_insert(char *name, struct all_addr *addr,
static struct crec *really_insert(char *name, struct all_addr *addr,
- time_t now, unsigned long ttl, unsigned short flags)
+ time_t now, unsigned long ttl, unsigned int flags)
{
struct crec *new, *target_crec = NULL;
union bigname *big_name = NULL;
@@ -495,6 +495,11 @@ static struct crec *really_insert(char *name, struct all_addr *addr,
if (insert_error)
return NULL;
+ /*
+ * Ensure we only cache unsigned short bits.
+ */
+ flags &= DNSMASQ_CACHE_MASK;
+
/* First remove any expired entries and entries for the name/address we
are currently inserting. */
if ((new = cache_scan_free(name, addr, now, flags, &target_crec, &target_uid)))
@@ -656,7 +661,7 @@ void cache_end_insert(void)
{
char *name = cache_get_name(new_chain);
ssize_t m = strlen(name);
- unsigned short flags = new_chain->flags;
+ unsigned int flags = new_chain->flags;
#ifdef HAVE_DNSSEC
u16 class = new_chain->uid;
#endif
@@ -717,7 +722,7 @@ int cache_recv_insert(time_t now, int fd)
struct all_addr addr;
unsigned long ttl;
time_t ttd;
- unsigned short flags;
+ unsigned int flags;
struct crec *crecp = NULL;
cache_start_insert();
@@ -856,7 +861,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
also free anything which has expired */
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)
{
@@ -1140,7 +1145,7 @@ int read_hostsfile(char *filename, unsigned int index, int cache_size, struct cr
FILE *f = fopen(filename, "r");
char *token = daemon->namebuff, *domain_suffix = NULL;
int addr_count = 0, name_count = cache_size, lineno = 0;
- unsigned short flags = 0;
+ unsigned int flags = 0;
struct all_addr addr;
int atnl, addrlen = 0;
@@ -1435,7 +1440,7 @@ void cache_add_dhcp_entry(char *host_name, int prot,
struct all_addr *host_address, time_t ttd)
{
struct crec *crec = NULL, *fail_crec = NULL;
- unsigned short flags = F_IPV4;
+ unsigned int flags = F_IPV4;
int in_hosts = 0;
size_t addrlen = sizeof(struct in_addr);
diff --git a/src/dnsmasq.h b/src/dnsmasq.h
index f8803f5..43f1974 100644
--- a/src/dnsmasq.h
+++ b/src/dnsmasq.h
@@ -433,7 +433,7 @@ struct crec {
time_t ttd; /* time to die */
/* used as class if DNSKEY/DS, index to source for F_HOSTS */
unsigned int uid;
- unsigned short flags;
+ unsigned int flags;
union {
char sname[SMALLDNAME];
union bigname *bname;
@@ -461,6 +461,8 @@ struct crec {
#define F_DS (1u<<14)
#define F_DNSSECOK (1u<<15)
+#define DNSMASQ_CACHE_MASK (0xFFFF)
+
/* below here are only valid as args to log_query: cache
entries are limited to 16 bits */
#define F_UPSTREAM (1u<<16)
@@ -1149,7 +1151,7 @@ void cache_end_insert(void);
void cache_start_insert(void);
int cache_recv_insert(time_t now, int fd);
struct crec *cache_insert(char *name, struct all_addr *addr,
- time_t now, unsigned long ttl, unsigned short flags);
+ time_t now, unsigned long ttl, unsigned int flags);
void cache_reload(void);
void cache_add_dhcp_entry(char *host_name, int prot, struct all_addr *host_address, time_t ttd);
struct in_addr a_record_from_hosts(char *name, time_t now);
diff --git a/src/rfc1035.c b/src/rfc1035.c
index bcdbef2..b419795 100644
--- a/src/rfc1035.c
+++ b/src/rfc1035.c
@@ -1279,7 +1279,7 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
unsigned int qtype, qclass;
struct all_addr addr;
int nameoffset;
- unsigned short flag;
+ unsigned int flag;
int q, ans, anscount = 0, addncount = 0;
int dryrun = 0;
struct crec *crecp;
--
2.19.1
From 9411455da1a671e5f750ea524589f77c7c1841d8 Mon Sep 17 00:00:00 2001
From: Jeremy Allison <jra at google.com>
Date: Tue, 18 Dec 2018 10:52:26 -0800
Subject: [PATCH 2/7] Change cache_XXX() interface to take a 'void *' parameter
instead of 'struct all_addr *'.
This allows us to pass in a different type when caching SRV records later.
Signed-off-by: Jeremy Allison <jra at google.com>
---
src/cache.c | 37 +++++++++++++++++++++++--------------
src/dnsmasq.h | 2 +-
2 files changed, 24 insertions(+), 15 deletions(-)
diff --git a/src/cache.c b/src/cache.c
index cd72a0c..32fc1ec 100644
--- a/src/cache.c
+++ b/src/cache.c
@@ -26,7 +26,7 @@ static union bigname *big_free = NULL;
static int bignames_left, hash_size;
static void make_non_terminals(struct crec *source);
-static struct crec *really_insert(char *name, struct all_addr *addr,
+static struct crec *really_insert(char *name, void *vaddr,
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. */
@@ -330,7 +330,7 @@ static int is_expired(time_t now, struct crec *crecp)
return 1;
}
-static struct crec *cache_scan_free(char *name, struct all_addr *addr, time_t now, unsigned int flags,
+static struct crec *cache_scan_free(char *name, void *vaddr, time_t now, unsigned int flags,
struct crec **target_crec, unsigned int *target_uid)
{
/* Scan and remove old entries.
@@ -381,14 +381,19 @@ static struct crec *cache_scan_free(char *name, struct all_addr *addr, time_t no
#ifdef HAVE_DNSSEC
/* Deletion has to be class-sensitive for DS and DNSKEY */
- if ((flags & crecp->flags & (F_DNSKEY | F_DS)) && crecp->uid == addr->addr.dnssec.class)
+ if (flags & crecp->flags & (F_DNSKEY | F_DS))
{
- if (crecp->flags & F_CONFIG)
- return crecp;
- *up = crecp->hash_next;
- cache_unlink(crecp);
- cache_free(crecp);
- continue;
+ struct all_addr *addr = (struct all_addr *)vaddr;
+ /* Deletion has to be class-sensitive for DS and DNSKEY */
+ if (crecp->uid == addr->addr.dnssec.class)
+ {
+ if (crecp->flags & F_CONFIG)
+ return crecp;
+ *up = crecp->hash_next;
+ cache_unlink(crecp);
+ cache_free(crecp);
+ continue;
+ }
}
#endif
}
@@ -428,7 +433,7 @@ static struct crec *cache_scan_free(char *name, struct all_addr *addr, time_t no
else if (!(crecp->flags & (F_HOSTS | F_DHCP | F_CONFIG)) &&
(flags & crecp->flags & F_REVERSE) &&
(flags & crecp->flags & (F_IPV4 | F_IPV6)) &&
- memcmp(&crecp->addr.addr, addr, addrlen) == 0)
+ memcmp(&crecp->addr.addr, vaddr, addrlen) == 0)
{
*up = crecp->hash_next;
cache_unlink(crecp);
@@ -464,12 +469,13 @@ void cache_start_insert(void)
insert_error = 0;
}
-struct crec *cache_insert(char *name, struct all_addr *addr,
+struct crec *cache_insert(char *name, void *vaddr,
time_t now, unsigned long ttl, unsigned int flags)
{
/* Don't log DNSSEC records here, done elsewhere */
if (flags & (F_IPV4 | F_IPV6 | F_CNAME))
{
+ struct all_addr *addr = (struct all_addr *)vaddr;
log_query(flags | F_UPSTREAM, name, addr, NULL);
/* Don't mess with TTL for DNSSEC records. */
if (daemon->max_cache_ttl != 0 && daemon->max_cache_ttl < ttl)
@@ -478,13 +484,14 @@ struct crec *cache_insert(char *name, struct all_addr *addr,
ttl = daemon->min_cache_ttl;
}
- return really_insert(name, addr, now, ttl, flags);
+ return really_insert(name, vaddr, now, ttl, flags);
}
-static struct crec *really_insert(char *name, struct all_addr *addr,
+static struct crec *really_insert(char *name, void *vaddr,
time_t now, unsigned long ttl, unsigned int flags)
{
+ struct all_addr *addr = NULL;
struct crec *new, *target_crec = NULL;
union bigname *big_name = NULL;
int freed_all = flags & F_REVERSE;
@@ -500,9 +507,11 @@ static struct crec *really_insert(char *name, struct all_addr *addr,
*/
flags &= DNSMASQ_CACHE_MASK;
+ addr = (struct all_addr *)vaddr;
+
/* First remove any expired entries and entries for the name/address we
are currently inserting. */
- if ((new = cache_scan_free(name, addr, now, flags, &target_crec, &target_uid)))
+ if ((new = cache_scan_free(name, vaddr, now, flags, &target_crec, &target_uid)))
{
/* We're trying to insert a record over one from
/etc/hosts or DHCP, or other config. If the
diff --git a/src/dnsmasq.h b/src/dnsmasq.h
index 43f1974..172af2e 100644
--- a/src/dnsmasq.h
+++ b/src/dnsmasq.h
@@ -1150,7 +1150,7 @@ struct crec *cache_find_by_name(struct crec *crecp,
void cache_end_insert(void);
void cache_start_insert(void);
int cache_recv_insert(time_t now, int fd);
-struct crec *cache_insert(char *name, struct all_addr *addr,
+struct crec *cache_insert(char *name, void *vaddr,
time_t now, unsigned long ttl, unsigned int flags);
void cache_reload(void);
void cache_add_dhcp_entry(char *host_name, int prot, struct all_addr *host_address, time_t ttd);
--
2.19.1
From 6d937cf88329a996c0cec56360f2f5b40a57b8d6 Mon Sep 17 00:00:00 2001
From: Jeremy Allison <jra at google.com>
Date: Tue, 18 Dec 2018 11:04:07 -0800
Subject: [PATCH 3/7] Add utility function free_mx_srv_record().
Not yet used.
Signed-off-by: Jeremy Allison <jra at google.com>
---
src/dnsmasq.h | 1 +
src/util.c | 9 +++++++++
2 files changed, 10 insertions(+)
diff --git a/src/dnsmasq.h b/src/dnsmasq.h
index 172af2e..232521f 100644
--- a/src/dnsmasq.h
+++ b/src/dnsmasq.h
@@ -1279,6 +1279,7 @@ int read_write(int fd, unsigned char *packet, int size, int rw);
int wildcard_match(const char* wildcard, const char* match);
int wildcard_matchn(const char* wildcard, const char* match, int num);
+void free_mx_srv_record(struct mx_srv_record *rec);
/* log.c */
void die(char *message, char *arg1, int exit_code) ATTRIBUTE_NORETURN;
diff --git a/src/util.c b/src/util.c
index 079fe44..a885836 100644
--- a/src/util.c
+++ b/src/util.c
@@ -741,3 +741,12 @@ int wildcard_matchn(const char* wildcard, const char* match, int num)
return (!num) || (*wildcard == *match);
}
+
+void free_mx_srv_record(struct mx_srv_record *rec)
+{
+ if (rec->name != NULL)
+ free(rec->name);
+ if (rec->target != NULL)
+ free(rec->target);
+ memset(rec, '\0', sizeof(*rec));
+}
--
2.19.1
From 101e465d5a1d21ec3449f6ee92121b1d45ec257f Mon Sep 17 00:00:00 2001
From: Jeremy Allison <jra at google.com>
Date: Tue, 18 Dec 2018 11:12:09 -0800
Subject: [PATCH 4/7] Add the ability to cache SRV records.
Not yet used.
Signed-off-by: Jeremy Allison <jra at google.com>
---
src/cache.c | 24 +++++++++++++++++++++---
src/dnsmasq.h | 8 +++++---
2 files changed, 26 insertions(+), 6 deletions(-)
diff --git a/src/cache.c b/src/cache.c
index 32fc1ec..f2b954c 100644
--- a/src/cache.c
+++ b/src/cache.c
@@ -230,6 +230,12 @@ static void cache_free(struct crec *crecp)
crecp->flags &= ~F_BIGNAME;
}
+ if (crecp->flags & F_SRV)
+ {
+ free_mx_srv_record(&crecp->addr.srv);
+ crecp->flags &= ~F_SRV;
+ }
+
#ifdef HAVE_DNSSEC
cache_blockdata_free(crecp);
#endif
@@ -492,6 +498,7 @@ static struct crec *really_insert(char *name, void *vaddr,
time_t now, unsigned long ttl, unsigned int flags)
{
struct all_addr *addr = NULL;
+ struct mx_srv_record *srv = NULL;
struct crec *new, *target_crec = NULL;
union bigname *big_name = NULL;
int freed_all = flags & F_REVERSE;
@@ -503,11 +510,15 @@ static struct crec *really_insert(char *name, void *vaddr,
return NULL;
/*
- * Ensure we only cache unsigned short bits.
+ * Ensure we only cache unsigned short bits
+ * plus F_SRV.
*/
flags &= DNSMASQ_CACHE_MASK;
- addr = (struct all_addr *)vaddr;
+ if (flags & F_SRV)
+ srv = (struct mx_srv_record *)vaddr;
+ else
+ addr = (struct all_addr *)vaddr;
/* First remove any expired entries and entries for the name/address we
are currently inserting. */
@@ -629,7 +640,14 @@ static struct crec *really_insert(char *name, void *vaddr,
else
*cache_get_name(new) = 0;
- if (addr)
+ if (flags & F_SRV)
+ {
+ if (srv)
+ new->addr.srv = *srv;
+ else
+ memset(&new->addr.srv, '\0', sizeof(new->addr.srv));
+ }
+ else if (addr)
{
#ifdef HAVE_DNSSEC
if (flags & (F_DS | F_DNSKEY))
diff --git a/src/dnsmasq.h b/src/dnsmasq.h
index 232521f..742e40a 100644
--- a/src/dnsmasq.h
+++ b/src/dnsmasq.h
@@ -429,6 +429,7 @@ struct crec {
unsigned char algo;
unsigned char digest;
} ds;
+ struct mx_srv_record srv; /* For SRV record caching. */
} addr;
time_t ttd; /* time to die */
/* used as class if DNSKEY/DS, index to source for F_HOSTS */
@@ -461,10 +462,11 @@ struct crec {
#define F_DS (1u<<14)
#define F_DNSSECOK (1u<<15)
-#define DNSMASQ_CACHE_MASK (0xFFFF)
+#define F_SRV (1u<<30)
-/* below here are only valid as args to log_query: cache
- entries are limited to 16 bits */
+#define DNSMASQ_CACHE_MASK (0xFFFF|F_SRV)
+
+/* below here are only valid as args to log_query */
#define F_UPSTREAM (1u<<16)
#define F_RRNAME (1u<<17)
#define F_SERVER (1u<<18)
--
2.19.1
From 480a2773342ede26dd5af1ee8f0aba4f8d8054c1 Mon Sep 17 00:00:00 2001
From: Jeremy Allison <jra at google.com>
Date: Tue, 18 Dec 2018 11:19:53 -0800
Subject: [PATCH 5/7] Add positive and negative SRV record return insertion
into cache.
Not yet looked up.
Signed-off-by: Jeremy Allison <jra at google.com>
---
src/rfc1035.c | 83 +++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 83 insertions(+)
diff --git a/src/rfc1035.c b/src/rfc1035.c
index b419795..fba6c2f 100644
--- a/src/rfc1035.c
+++ b/src/rfc1035.c
@@ -722,6 +722,89 @@ int extract_addresses(struct dns_header *header, size_t qlen, char *name, time_t
cache_insert(NULL, &addr, now, ttl, name_encoding | F_REVERSE | F_NEG | flags | (secure ? F_DNSSECOK : 0));
}
}
+ else if (qtype == T_SRV)
+ {
+ /* SRV records */
+ if (!(flags & F_NXDOMAIN))
+ {
+ if (!(p1 = skip_questions(header, qlen)))
+ return 0;
+
+ for (j = 0; j < ntohs(header->ancount); j++)
+ {
+ /*
+ * Get the name from the answer. This is
+ * the name we'll use as the name to cache.
+ */
+ if (!extract_name(header, qlen, &p1, name, 1, 0))
+ return 0;
+
+ GETSHORT(aqtype, p1);
+ GETSHORT(aqclass, p1);
+ GETLONG(attl, p1);
+
+ if ((daemon->max_ttl != 0) && (attl > daemon->max_ttl) && !is_sign)
+ {
+ (p1) -= 4;
+ PUTLONG(daemon->max_ttl, p1);
+ }
+
+ GETSHORT(ardlen, p1);
+ endrr = p1+ardlen;
+
+ if (aqclass == C_IN && aqtype == T_SRV)
+ {
+ struct mx_srv_record srv;
+
+ memset(&srv, '\0', sizeof(srv));
+
+ GETSHORT(srv.priority, p1);
+ GETSHORT(srv.weight, p1);
+ GETSHORT(srv.srvport, p1);
+
+ srv.name = strdup(name);
+ if (srv.name == NULL)
+ return 0;
+
+ /*
+ * Now get the target name to cache.
+ */
+ if (!extract_name(header, qlen, &p1, name, 1, 0))
+ {
+ free_mx_srv_record(&srv);
+ return 0;
+ }
+ srv.target = strdup(name);
+ if (srv.target == NULL)
+ {
+ free_mx_srv_record(&srv);
+ return 0;
+ }
+
+ srv.offset = 0;
+ srv.next = NULL;
+ srv.issrv = 1;
+ cache_insert(srv.name, &srv, now, attl, flags | F_SRV | F_FORWARD);
+ }
+
+ p1 = endrr;
+ if (!CHECK_LEN(header, p1, qlen, 0))
+ return 0; /* bad packet */
+ }
+ }
+
+ /* Negative SRV caching. */
+ if ((flags & F_NXDOMAIN) && !option_bool(OPT_NO_NEG))
+ {
+ if (!searched_soa)
+ {
+ searched_soa = 1;
+ ttl = find_soa(header, qlen, NULL, doctored);
+ }
+ if (ttl)
+ cache_insert(name, NULL, now, ttl, F_SRV | F_FORWARD | F_NEG | flags | (secure ? F_DNSSECOK : 0));
+ }
+ }
else
{
/* everything other than PTR */
--
2.19.1
From 1a0baccc0bc8a39232c768db4ef891491e68c045 Mon Sep 17 00:00:00 2001
From: Jeremy Allison <jra at google.com>
Date: Tue, 18 Dec 2018 11:31:51 -0800
Subject: [PATCH 6/7] Add looking up of positive and negative SRV records from
the cache.
Signed-off-by: Jeremy Allison <jra at google.com>
---
src/rfc1035.c | 56 +++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 56 insertions(+)
diff --git a/src/rfc1035.c b/src/rfc1035.c
index fba6c2f..c6fd960 100644
--- a/src/rfc1035.c
+++ b/src/rfc1035.c
@@ -1927,6 +1927,62 @@ size_t answer_request(struct dns_header *header, char *limit, size_t qlen,
*up = move;
move->next = NULL;
}
+
+ if (!found)
+ {
+ /* Look for SRV records in the cache. */
+ crecp = NULL;
+ while (1)
+ {
+ struct mx_srv_record *srv = NULL;
+
+ crecp = cache_find_by_name(crecp,
+ name,
+ now,
+ flag | F_SRV);
+ if (!crecp)
+ break;
+
+ if (crecp->flags & F_NEG)
+ {
+ /* Found a negative SRV cache entry. */
+ ans = 1;
+ auth = 0;
+ found = 1;
+ if (crecp->flags & F_NXDOMAIN)
+ nxdomain = 1;
+ if (!dryrun)
+ log_query(crecp->flags, name, NULL, NULL);
+ break;
+ }
+
+ srv = &crecp->addr.srv;
+
+ if (add_resource_record(header,
+ limit,
+ &trunc,
+ nameoffset,
+ &ansp,
+ crec_ttl(crecp, now),
+ &nameoffset,
+ T_SRV,
+ C_IN,
+ "sssd",
+ srv->priority,
+ srv->weight,
+ srv->srvport,
+ srv->target))
+ {
+ ans = 1;
+ anscount++;
+ found = 1;
+ log_query((crecp->flags & ~F_FORWARD) | F_RRNAME,
+ cache_get_name(crecp),
+ NULL,
+ srv->target);
+ }
+ }
+ }
if (!found && option_bool(OPT_FILTER) && (qtype == T_SRV || (qtype == T_ANY && strchr(name, '_'))))
{
--
2.19.1
From 717d04424e9e24d745bacb0f312e5897e93bc382 Mon Sep 17 00:00:00 2001
From: Jeremy Allison <jra at samba.org>
Date: Fri, 21 Dec 2018 12:12:33 -0800
Subject: [PATCH 7/7] Add --srv-cache option. Controls whether SRV records are
cached or not.
Signed-off-by: Jeremy Allison <jra at google.com>
---
man/dnsmasq.8 | 5 +++++
src/dnsmasq.h | 3 ++-
src/option.c | 3 +++
src/rfc1035.c | 4 ++--
4 files changed, 12 insertions(+), 3 deletions(-)
diff --git a/man/dnsmasq.8 b/man/dnsmasq.8
index f01a5ba..a342f5c 100644
--- a/man/dnsmasq.8
+++ b/man/dnsmasq.8
@@ -1942,6 +1942,11 @@ A special case of
which differs in two respects. Firstly, only \fB--server\fP and \fB--rev-server\fP are allowed
in the configuration file included. Secondly, the file is re-read and the configuration
therein is updated when dnsmasq receives SIGHUP.
+.TP
+.B --srv-cache
+Cache SRV record lookups, both positively and negatively unless
+\fB--no-negcache\fP, or \fB-N\P options are set.
+
.SH CONFIG FILE
At startup, dnsmasq reads
.I /etc/dnsmasq.conf,
diff --git a/src/dnsmasq.h b/src/dnsmasq.h
index 742e40a..b7eb817 100644
--- a/src/dnsmasq.h
+++ b/src/dnsmasq.h
@@ -259,7 +259,8 @@ struct event_desc {
#define OPT_TFTP_APREF_MAC 56
#define OPT_RAPID_COMMIT 57
#define OPT_UBUS 58
-#define OPT_LAST 59
+#define OPT_SRV_CACHE 59
+#define OPT_LAST 60
#define OPTION_BITS (sizeof(unsigned int)*8)
#define OPTION_SIZE ( (OPT_LAST/OPTION_BITS)+((OPT_LAST%OPTION_BITS)!=0) )
diff --git a/src/option.c b/src/option.c
index 6fbd486..ccaa015 100644
--- a/src/option.c
+++ b/src/option.c
@@ -166,6 +166,7 @@ struct myoption {
#define LOPT_UBUS 354
#define LOPT_NAME_MATCH 355
#define LOPT_CAA 356
+#define LOPT_SRV_CACHE 357
#ifdef HAVE_GETOPT_LONG
static const struct option opts[] =
@@ -337,6 +338,7 @@ static const struct myoption opts[] =
{ "dhcp-rapid-commit", 0, 0, LOPT_RAPID_COMMIT },
{ "dumpfile", 1, 0, LOPT_DUMPFILE },
{ "dumpmask", 1, 0, LOPT_DUMPMASK },
+ { "srv-cache", 0, 0, LOPT_SRV_CACHE },
{ NULL, 0, 0, 0 }
};
@@ -515,6 +517,7 @@ static struct {
{ LOPT_RAPID_COMMIT, OPT_RAPID_COMMIT, NULL, gettext_noop("Enables DHCPv4 Rapid Commit option."), NULL },
{ LOPT_DUMPFILE, ARG_ONE, "<path>", gettext_noop("Path to debug packet dump file"), NULL },
{ LOPT_DUMPMASK, ARG_ONE, "<hex>", gettext_noop("Mask which packets to dump"), NULL },
+ { LOPT_SRV_CACHE, OPT_SRV_CACHE, NULL, gettext_noop("Cache SRV records."), NULL },
{ 0, 0, NULL, NULL, NULL }
};
diff --git a/src/rfc1035.c b/src/rfc1035.c
index c6fd960..1095875 100644
--- a/src/rfc1035.c
+++ b/src/rfc1035.c
@@ -725,7 +725,7 @@ int extract_addresses(struct dns_header *header, size_t qlen, char *name, time_t
else if (qtype == T_SRV)
{
/* SRV records */
- if (!(flags & F_NXDOMAIN))
+ if (!(flags & F_NXDOMAIN) && option_bool(OPT_SRV_CACHE))
{
if (!(p1 = skip_questions(header, qlen)))
return 0;
@@ -794,7 +794,7 @@ int extract_addresses(struct dns_header *header, size_t qlen, char *name, time_t
}
/* Negative SRV caching. */
- if ((flags & F_NXDOMAIN) && !option_bool(OPT_NO_NEG))
+ if ((flags & F_NXDOMAIN) && option_bool(OPT_SRV_CACHE) && !option_bool(OPT_NO_NEG))
{
if (!searched_soa)
{
--
2.19.1
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 488 bytes
Desc: OpenPGP digital signature
URL: <http://lists.thekelleys.org.uk/pipermail/dnsmasq-discuss/attachments/20181221/074dd9c8/attachment-0001.sig>
More information about the Dnsmasq-discuss
mailing list