summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimon Kelley <simon@thekelleys.org.uk>2013-12-31 13:57:21 +0000
committerSimon Kelley <simon@thekelleys.org.uk>2013-12-31 13:57:21 +0000
commit91dff77ee080ec76461ce17b81355ebb23fbe604 (patch)
treee4177a7d3f1f4be2d29664e695525d9a40848154
parentf5d4a4a169cf30f11c7d44096c664ddfa45a132d (diff)
parentc3e0b9b6e75001ea2d24a4f67537ed77d0f0210c (diff)
downloaddnsmasq-dnssec.tar.gz
Merge branch 'dnssec' of ssh://thekelleys.org.uk/var/cache/git/dnsmasq into dnssecdnssec
Conflicts: src/forward.c
-rw-r--r--CHANGELOG3
-rw-r--r--src/cache.c20
-rw-r--r--src/dhcp-common.c14
-rw-r--r--src/dns-protocol.h6
-rw-r--r--src/dnsmasq.c6
-rw-r--r--src/dnsmasq.h16
-rw-r--r--src/dnssec.c359
-rw-r--r--src/forward.c14
-rw-r--r--src/option.c10
-rw-r--r--src/rfc1035.c9
-rw-r--r--src/slaac.c1
11 files changed, 419 insertions, 39 deletions
diff --git a/CHANGELOG b/CHANGELOG
index 39dbe17..785eea4 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -4,6 +4,9 @@ version 2.69
on the BSD platform. Thanks to Matthias Andree for
valuable research on how to implement this.
+ Fix infinite loop associated with some --bogus-nxdomain
+ configs. Thanks fogobogo for the bug report.
+
version 2.68
Use random addresses for DHCPv6 temporary address
diff --git a/src/cache.c b/src/cache.c
index 1338681..cfbeae3 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 int uid = 1;
#ifdef HAVE_DNSSEC
-static struct keydata *keyblock_free = NULL;
+static struct blockdata *keyblock_free = NULL;
#endif
/* type->string mapping: this is also used by the name-hash function as a mixing table. */
@@ -198,7 +198,7 @@ static void cache_free(struct crec *crecp)
}
#ifdef HAVE_DNSSEC
else if (crecp->flags & (F_DNSKEY | F_DS))
- keydata_free(crecp->addr.key.keydata);
+ blockdata_free(crecp->addr.key.keydata);
#endif
}
@@ -1361,10 +1361,10 @@ void log_query(unsigned int flags, char *name, struct all_addr *addr, char *arg)
}
#ifdef HAVE_DNSSEC
-struct keydata *keydata_alloc(char *data, size_t len)
+struct blockdata *blockdata_alloc(char *data, size_t len)
{
- struct keydata *block, *ret = NULL;
- struct keydata **prev = &ret;
+ struct blockdata *block, *ret = NULL;
+ struct blockdata **prev = &ret;
size_t blen;
while (len > 0)
@@ -1375,12 +1375,12 @@ struct keydata *keydata_alloc(char *data, size_t len)
keyblock_free = block->next;
}
else
- block = whine_malloc(sizeof(struct keydata));
+ block = whine_malloc(sizeof(struct blockdata));
if (!block)
{
/* failed to alloc, free partial chain */
- keydata_free(ret);
+ blockdata_free(ret);
return NULL;
}
@@ -1396,7 +1396,7 @@ struct keydata *keydata_alloc(char *data, size_t len)
return ret;
}
-size_t keydata_walk(struct keydata **key, unsigned char **p, size_t cnt)
+size_t blockdata_walk(struct blockdata **key, unsigned char **p, size_t cnt)
{
if (*p == NULL)
*p = (*key)->key;
@@ -1411,9 +1411,9 @@ size_t keydata_walk(struct keydata **key, unsigned char **p, size_t cnt)
return MIN(cnt, (*key)->key + KEYBLOCK_LEN - (*p));
}
-void keydata_free(struct keydata *blocks)
+void blockdata_free(struct blockdata *blocks)
{
- struct keydata *tmp;
+ struct blockdata *tmp;
if (blocks)
{
diff --git a/src/dhcp-common.c b/src/dhcp-common.c
index a92d728..3f9979e 100644
--- a/src/dhcp-common.c
+++ b/src/dhcp-common.c
@@ -399,13 +399,13 @@ void dhcp_update_configs(struct dhcp_config *configs)
if (cache_find_by_name(crec, config->hostname, 0, cacheflags))
{
/* use primary (first) address */
- while (crec && !(crec->flags & F_REVERSE))
- crec = cache_find_by_name(crec, config->hostname, 0, cacheflags);
- if (!crec)
- continue; /* should be never */
- inet_ntop(prot, &crec->addr.addr, daemon->addrbuff, ADDRSTRLEN);
- my_syslog(MS_DHCP | LOG_WARNING, _("%s has more than one address in hostsfile, using %s for DHCP"),
- config->hostname, daemon->addrbuff);
+ while (crec && !(crec->flags & F_REVERSE))
+ crec = cache_find_by_name(crec, config->hostname, 0, cacheflags);
+ if (!crec)
+ continue; /* should be never */
+ inet_ntop(prot, &crec->addr.addr, daemon->addrbuff, ADDRSTRLEN);
+ my_syslog(MS_DHCP | LOG_WARNING, _("%s has more than one address in hostsfile, using %s for DHCP"),
+ config->hostname, daemon->addrbuff);
}
if (prot == AF_INET &&
diff --git a/src/dns-protocol.h b/src/dns-protocol.h
index 07cc768..efecb1c 100644
--- a/src/dns-protocol.h
+++ b/src/dns-protocol.h
@@ -140,3 +140,9 @@ struct dns_header {
GETLONG(var, ptr); \
(len) -= 4; \
} while (0)
+
+#define CHECK_LEN(header, pp, plen, len) \
+ ((size_t)((pp) - (unsigned char *)(header) + (len)) <= (plen))
+
+#define ADD_RDLEN(header, pp, plen, len) \
+ (!CHECK_LEN(header, pp, plen, len) ? 0 : (((pp) += (len)), 1))
diff --git a/src/dnsmasq.c b/src/dnsmasq.c
index f5ce7df..3e5f51e 100644
--- a/src/dnsmasq.c
+++ b/src/dnsmasq.c
@@ -81,8 +81,14 @@ int main (int argc, char **argv)
umask(022); /* known umask, create leases and pid files as 0644 */
read_opts(argc, argv, compile_opts);
+
+#ifdef HAVE_DNSSEC
if (option_bool(OPT_DNSSEC_VALID))
if (daemon->doctors) exit(1); /* TODO */
+
+ daemon->keyname = safe_malloc(MAXDNAME);
+#endif
+
if (daemon->edns_pktsz < PACKETSZ)
daemon->edns_pktsz = option_bool(OPT_DNSSEC_VALID) ? EDNS_PKTSZ : PACKETSZ;
daemon->packet_buff_sz = daemon->edns_pktsz > DNSMASQ_PACKETSZ ?
diff --git a/src/dnsmasq.h b/src/dnsmasq.h
index bde72e2..8a3541a 100644
--- a/src/dnsmasq.h
+++ b/src/dnsmasq.h
@@ -335,8 +335,8 @@ union bigname {
union bigname *next; /* freelist */
};
-struct keydata {
- struct keydata *next;
+struct blockdata {
+ struct blockdata *next;
unsigned char key[KEYBLOCK_LEN];
};
@@ -528,6 +528,7 @@ struct frec {
unsigned int crc;
time_t time;
#ifdef HAVE_DNSSEC
+ int class;
struct blockdata *stash; /* Saved reply, whilst we validate */
size_t stash_len;
struct frec *dependent; /* Query awaiting internally-generated DNSKEY or DS query */
@@ -581,7 +582,7 @@ struct dhcp_lease {
struct in6_addr addr6;
int iaid;
struct slaac_address {
- struct in6_addr addr, local;
+ struct in6_addr addr;
time_t ping_time;
int backoff; /* zero -> confirmed */
struct slaac_address *next;
@@ -900,6 +901,9 @@ extern struct daemon {
char *packet; /* packet buffer */
int packet_buff_sz; /* size of above */
char *namebuff; /* MAXDNAME size buffer */
+#ifdef HAVE_DNSSEC
+ char *keyname; /* MAXDNAME size buffer */
+#endif
unsigned int local_answer, queries_forwarded, auth_answer;
struct frec *frec_list;
struct serverfd *sfds;
@@ -1030,7 +1034,11 @@ int in_zone(struct auth_zone *zone, char *name, char **cut);
#endif
/* dnssec.c */
-int dnssec_validate(int flags, struct dns_header *header, size_t plen);
+size_t dnssec_generate_query(struct dns_header *header, char *name, int class, int type);
+int dnssec_validate_by_ds(time_t now, struct dns_header *header, size_t n, 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);
+int validate_rrset(time_t now, struct dns_header *header, size_t plen, int class, int type, char *name, char *keyname);
+int dnssec_validate_reply(struct dns_header *header, size_t plen, char *name, char *keyname, int *class);
/* util.c */
void rand_init(void);
diff --git a/src/dnssec.c b/src/dnssec.c
index a1f7856..4a91137 100644
--- a/src/dnssec.c
+++ b/src/dnssec.c
@@ -21,11 +21,15 @@
/* Maximum length in octects of a domain name, in wire format */
#define MAXCDNAME 256
+#define MAXRRSET 16
+
#define SERIAL_UNDEF -100
#define SERIAL_EQ 0
#define SERIAL_LT -1
#define SERIAL_GT 1
+static int dnskey_keytag(int alg, unsigned char *rdata, int rdlen);
+
/* Implement RFC1982 wrapped compare for 32-bit numbers */
static int serial_compare_32(unsigned long s1, unsigned long s2)
{
@@ -494,7 +498,359 @@ static int digestalg_add_rdata(int sigtype, struct dns_header *header, size_t pk
return 1;
}
+size_t dnssec_generate_query(struct dns_header *header, char *name, int class, int type)
+{
+ unsigned char *p;
+
+ header->qdcount = htons(1);
+ header->ancount = htons(0);
+ header->nscount = htons(0);
+ header->arcount = htons(0);
+
+ header->hb3 = HB3_RD;
+ SET_OPCODE(header, QUERY);
+ header->hb4 = 0;
+
+ /* ID filled in later */
+
+ p = (unsigned char *)(header+1);
+
+ p = do_rfc1035_name(p, name);
+ PUTSHORT(type, p);
+ PUTSHORT(class, p);
+
+ return add_do_bit(header, p - (unsigned char *)header, ((char *) header) + PACKETSZ);
+}
+
+/* The DNS packet is expected to contain the answer to a DNSKEY query
+ Put all DNSKEYs in the answer which are valid into the cache.
+ return codes:
+ STAT_INSECURE bad packet, no DNSKEYs in reply.
+ STAT_SECURE At least one valid DNSKEY found and in cache.
+ STAT_BOGUS At least one DNSKEY found, which fails validation.
+ STAT_NEED_DS DS records to validate a key not found, name in namebuff
+*/
+int dnssec_validate_by_ds(time_t now, struct dns_header *header, size_t plen, char *name, char *keyname, int class)
+{
+ unsigned char *p;
+ struct crec *crecp, *recp1;
+ int j, qtype, qclass, ttl, rdlen, flags, protocol, algo, gotone;
+ struct blockdata *key;
+
+ if (ntohs(header->qdcount) != 1)
+ return STAT_INSECURE;
+
+ if (!extract_name(header, plen, &p, name, 1, 4))
+ return STAT_INSECURE;
+
+ GETSHORT(qtype, p);
+ GETSHORT(qclass, p);
+
+ if (qtype != T_DNSKEY || qclass != class)
+ return STAT_INSECURE;
+
+ cache_start_insert();
+
+ for (gotone = 0, j = ntohs(header->ancount); j != 0; j--)
+ {
+ /* Ensure we have type, class TTL and length */
+ if (!extract_name(header, plen, &p, name, 1, 10))
+ return STAT_INSECURE; /* bad packet */
+
+ GETSHORT(qtype, p);
+ GETSHORT(qclass, p);
+ GETLONG(ttl, p);
+ GETSHORT(rdlen, p);
+
+ if (qclass != class || qtype != T_DNSKEY || rdlen < 4)
+ {
+ /* skip all records other than DNSKEY */
+ p += rdlen;
+ continue;
+ }
+
+ crecp = cache_find_by_name(NULL, name, now, F_DS);
+
+ /* length at least covers flags, protocol and algo now. */
+ GETSHORT(flags, p);
+ protocol = *p++;
+ algo = *p++;
+
+ /* See if we have cached a DS record which validates this key */
+ for (recp1 = crecp; recp1; recp1 = cache_find_by_name(recp1, name, now, F_DS))
+ if (recp1->addr.key.algo == algo && is_supported_digest(recp1->addr.key.digest))
+ break;
+
+ /* DS record needed to validate key is missing, return name of DS in namebuff */
+ if (!recp1)
+ return STAT_NEED_DS;
+ else
+ {
+ int valid = 1;
+ /* calculate digest of canonicalised DNSKEY data using digest in (recp1->addr.key.digest)
+ and see if it equals digest stored in recp1
+ */
+
+ if (!valid)
+ return STAT_BOGUS;
+ }
+
+ if ((key = blockdata_alloc((char*)p, rdlen)))
+ {
+
+ /* We've proved that the KEY is OK, store it in the cache */
+ if ((crecp = cache_insert(name, NULL, now, ttl, F_FORWARD | F_DNSKEY)))
+ {
+ crecp->uid = rdlen;
+ crecp->addr.key.keydata = key;
+ crecp->addr.key.algo = algo;
+ crecp->addr.key.keytag = dnskey_keytag(algo, (char*)p, rdlen);
+ gotone = 1;
+ }
+ }
+
+ }
+
+ cache_end_insert();
+
+
+ return gotone ? STAT_SECURE : STAT_INSECURE;
+}
+/* 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.
+ return codes:
+ STAT_INSECURE bad packet, no DNSKEYs in reply.
+ STAT_SECURE At least one valid DS found and in cache.
+ STAT_BOGUS At least one DS found, which fails validation.
+ STAT_NEED_DNSKEY DNSKEY records to validate a DS not found, name in keyname
+*/
+
+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);
+ struct crec *crecp, *recp1;
+ int qtype, qclass, val, j, gotone;
+ struct blockdata *key;
+
+ if (ntohs(header->qdcount) != 1)
+ return STAT_INSECURE;
+
+ if (!extract_name(header, plen, &p, name, 1, 4))
+ return STAT_INSECURE;
+
+ GETSHORT(qtype, p);
+ GETSHORT(qclass, p);
+
+ if (qtype != T_DS || qclass != class)
+ return STAT_INSECURE;
+
+ val = validate_rrset(header, plen, class, T_DS, name, keyname);
+
+ /* failed to validate or missing key. */
+ if (val != STAT_SECURE)
+ return val;
+
+ cache_start_insert();
+
+ for (gotone = 0, j = ntohs(header->ancount); j != 0; j--)
+ {
+ int ttl, rdlen, rc, algo;
+
+ /* Ensure we have type, class TTL and length */
+ if (!(rc = extract_name(header, plen, &p, name, 0, 10)))
+ return STAT_INSECURE; /* bad packet */
+
+ GETSHORT(qtype, p);
+ GETSHORT(qclass, p);
+ GETLONG(ttl, p);
+ GETSHORT(rdlen, p);
+
+ /* check type, class and name, skip if not in DS rrset */
+ if (qclass != class || qtype != T_DS || rc == 2)
+ {
+ p += rdlen;
+ continue;
+ }
+
+ if ((key = blockdata_alloc((char*)p, rdlen)))
+ {
+
+ /* We've proved that the DS is OK, store it in the cache */
+ if ((crecp = cache_insert(name, NULL, now, ttl, F_FORWARD | F_DS)))
+ {
+ crecp->uid = rdlen;
+ crecp->addr.key.keydata = key;
+ crecp->addr.key.algo = algo;
+ crecp->addr.key.keytag = dnskey_keytag(algo, (char*)p, rdlen);
+ gotone = 1;
+ }
+ }
+
+ }
+
+ cache_end_insert();
+
+
+ return gotone ? STAT_SECURE : STAT_INSECURE;
+}
+
+
+/* Validate a single RRset (class, type, name) in the supplied DNS reply
+ Return code:
+ STAT_SECURE if it validates.
+ STAT_INSECURE can't validate (no RRSIG, bad packet).
+ STAT_BOGUS signature is wrong.
+ STAT_NEED_KEY need DNSKEY to complete validation (name is returned in keyname)
+*/
+int validate_rrset(time_t now, struct dns_header *header, size_t plen, int class, int type, char *name, char *keyname)
+{
+ unsigned char *p, *psav, *sig;
+ int rrsetidx, res, sigttl, sig_data_len, j;
+ struct crec *crecp;
+ void *rrset[MAXRRSET]; /* TODO: max RRset size? */
+ int type_covered, algo, labels, orig_ttl, sig_expiration, sig_inception, key_tag;
+
+ if (!(p = skip_questions(header, plen)))
+ return STAT_INSECURE;
+
+ /* look for an RRSIG record for this RRset and get pointers to each record */
+ for (rrsetidx = 0, sig = NULL, j = ntohs(header->ancount) + ntohs(header->nscount);
+ j != 0; j--)
+ {
+ unsigned char *pstart = p;
+ int stype, sclass, sttl, rdlen;
+
+ if (!(res = extract_name(header, plen, &p, name, 0, 10)))
+ return STAT_INSECURE; /* bad packet */
+
+ GETSHORT(stype, p);
+ GETSHORT(sclass, p);
+ GETLONG(sttl, p);
+ GETSHORT(rdlen, p);
+
+ if (!CHECK_LEN(header, p, plen, rdlen))
+ return STAT_INSECURE; /* bad packet */
+
+ if (res == 2 || htons(stype) != T_RRSIG || htons(sclass) != class)
+ continue;
+
+ if (htons(stype) == type)
+ {
+ rrset[rrsetidx++] = pstart;
+ if (rrsetidx == MAXRRSET)
+ return STAT_INSECURE; /* RRSET too big TODO */
+ }
+
+ if (htons(stype) == T_RRSIG)
+ {
+ /* name matches, RRSIG for correct class */
+ /* enough data? */
+ if (rdlen < 18)
+ return STAT_INSECURE;
+
+ GETSHORT(type_covered, p);
+ algo = *p++;
+ labels = *p++;
+ GETLONG(orig_ttl, p);
+ GETLONG(sig_expiration, p);
+ GETLONG(sig_inception, p);
+ GETSHORT(key_tag, p);
+
+ if (type_covered != type ||
+ !check_date_range(sig_inception, sig_expiration))
+ {
+ /* covers wrong type or out of date - skip */
+ p = psav;
+ if (!ADD_RDLEN(header, p, plen, rdlen))
+ return STAT_INSECURE;
+ continue;
+ }
+
+ if (!extract_name(header, plen, &p, keyname, 1, 0))
+ return STAT_INSECURE;
+
+ /* OK, we have the signature record, see if the
+ relevant DNSKEY is in the cache. */
+ for (crecp = cache_find_by_name(NULL, keyname, now, F_DNSKEY);
+ crecp;
+ crecp = cache_find_by_name(crecp, keyname, now, F_DNSKEY))
+ if (crecp->addr.key.algo == algo && crecp->addr.key.keytag == key_tag)
+ break;
+
+ /* No, abort for now whilst we get it */
+ if (!crecp)
+ return STAT_NEED_KEY;
+
+ /* Save point to signature data */
+ sig = p;
+ sig_data_len = rdlen - (p - psav);
+ sigttl = sttl;
+
+ /* next record */
+ p = psav;
+ if (!ADD_RDLEN(header, p, plen, rdlen))
+ return STAT_INSECURE;
+ }
+ }
+
+ /* Didn't find RRSIG or RRset is empty */
+ if (!sig || rrsetidx == 0)
+ return STAT_INSECURE;
+
+ /* OK, we have an RRSIG and an RRset and we have a the DNSKEY that validates them. */
+
+ /* Sort RRset records in canonical order. */
+ rrset_canonical_order_ctx.header = header;
+ rrset_canonical_order_ctx.pktlen = plen;
+ qsort(rrset, rrsetidx, sizeof(void*), rrset_canonical_order);
+
+ /* Now initialize the signature verification algorithm and process the whole
+ RRset */
+ VerifyAlgCtx *alg = verifyalg_alloc(algo);
+ if (!alg)
+ return STAT_INSECURE;
+
+ alg->sig = sig;
+ alg->siglen = sig_data_len;
+
+ u16 ntype = htons(type);
+ u16 nclass = htons(class);
+ u32 nsigttl = htonl(sigttl);
+
+ /* TODO: we shouldn't need to convert this to wire here. Best solution would be:
+ - Use process_name() instead of extract_name() everywhere in dnssec code
+ - Convert from wire format to representation format only for querying/storing cache
+ */
+ unsigned char owner_wire[MAXCDNAME];
+ int owner_wire_len = convert_domain_to_wire(name, owner_wire);
+
+ digestalg_begin(alg->vtbl->digest_algo);
+ digestalg_add_data(sigrdata, 18+signer_name_rdlen);
+ for (i = 0; i < rrsetidx; ++i)
+ {
+ p = (unsigned char*)(rrset[i]);
+
+ digestalg_add_data(owner_wire, owner_wire_len);
+ digestalg_add_data(&ntype, 2);
+ digestalg_add_data(&nclass, 2);
+ digestalg_add_data(&nsigttl, 4);
+
+ p += 8;
+ if (!digestalg_add_rdata(ntohs(sigtype), header, pktlen, p))
+ return 0;
+ }
+ int digest_len = digestalg_len();
+ memcpy(alg->digest, digestalg_final(), digest_len);
+
+ if (alg->vtbl->verify(alg, crecp->addr.key.keydata, crecp_uid))
+ return STAT_SECURE;
+
+ return STAT_INSECURE;
+}
+
+
+#if 0
static int begin_rrsig_validation(struct dns_header *header, size_t pktlen,
unsigned char *reply, int count, char *owner,
int sigclass, int sigrdlen, unsigned char *sig,
@@ -624,6 +980,7 @@ static int end_rrsig_validation(PendingRRSIGValidation *val, struct crec *crec_d
return val->alg->vtbl->verify(val->alg, crec_dnskey->addr.key.keydata, crec_dnskey->uid);
}
+
static void dnssec_parserrsig(struct dns_header *header, size_t pktlen,
unsigned char *reply, int count, char *owner,
int sigclass, int sigrdlen, unsigned char *sig)
@@ -663,6 +1020,8 @@ static void dnssec_parserrsig(struct dns_header *header, size_t pktlen,
}
}
+#endif /* comment out */
+
/* Compute keytag (checksum to quickly index a key). See RFC4034 */
static int dnskey_keytag(int alg, unsigned char *rdata, int rdlen)
{
diff --git a/src/forward.c b/src/forward.c
index a549727..ad50783 100644
--- a/src/forward.c
+++ b/src/forward.c
@@ -678,15 +678,19 @@ void reply_query(int fd, int family, time_t now)
if (option_bool(OPT_DNSSEC_VALID) && !(forward->flags & FREC_CHECKING_DISABLED))
{
int status;
- char rrbitmap[256/8];
int class;
if (forward->flags & FREC_DNSKEY_QUERY)
+<<<<<<< HEAD
status = dnssec_validate_by_ds(header, n, daemon->namebuff, &class);
else if (forward->flags & FREC_DS_QUERY)
status = dnssec_validate_dnskey(header, n, daemon->namebuff, &class);
+=======
+ status = dnssec_validate_by_ds(now, header, n, daemon->namebuff, daemon->keyname, forward->class);
+ else if (forward->flags & FREC_DS_QUERY)
+ status = dnssec_validate_ds(now, header, n, daemon->namebuff, daemon->keyname, forward->class);
else
- status = dnssec_validate_reply(&rrbitmap, header, n, daemon->namebuff, &class);
+ status = dnssec_validate_reply(header, n, daemon->namebuff, daemon->keyname, &forward->class);
/* Can't validate, as we're missing key data. Put this
answer aside, whilst we get that. */
@@ -761,9 +765,9 @@ void reply_query(int fd, int family, time_t now)
if (status == STAT_SECURE)
{
if (forward->flags & FREC_DNSKEY_QUERY)
- status = dnssec_validate_by_ds(header, n, daemon->namebuff, &class);
+ status = dnssec_validate_by_ds(now, header, n, daemon->namebuff, daemon->keyname, forward->class);
else if (forward->flags & FREC_DS_QUERY)
- status = dnssec_validate_dnskey(header, n, daemon->namebuff, &class);
+ status = dnssec_validate_dnskey(now, header, n, daemon->namebuff, daemon->keyname, forward->class);
if (status == STAT_NEED_DS || status == STAT_NEED_KEY)
my_syslog(LOG_ERR, _("Unexpected missing data for DNSSEC validation"));
@@ -773,7 +777,7 @@ void reply_query(int fd, int family, time_t now)
/* All DNSKEY and DS records done and in cache, now finally validate original
answer, provided last DNSKEY is OK. */
if (status == STAT_SECURE)
- status = dnssec_validate_reply(&rrbitmap, header, n, daemon->namebuff, &class);
+ status = dnssec_validate_reply(header, n, daemon->namebuff, daemon->keyname, &forward->class);
if (status == STAT_SECURE)
cache_secure = 1;
diff --git a/src/option.c b/src/option.c
index edc3ae4..cadabd5 100644
--- a/src/option.c
+++ b/src/option.c
@@ -2737,7 +2737,7 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
else
{
char *cp, *lastp = NULL, last = 0;
- int fac = 1;
+ int fac = 1, isdig = 0;
if (strlen(a[j]) > 1)
{
@@ -2768,9 +2768,11 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
}
for (cp = a[j]; *cp; cp++)
- if (!isdigit((unsigned char)*cp) && *cp != ' ')
+ if (isdigit((unsigned char)*cp))
+ isdig = 1;
+ else if (*cp != ' ')
break;
-
+
if (*cp)
{
if (lastp)
@@ -2792,7 +2794,7 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma
new->domain = strip_hostname(new->hostname);
}
}
- else
+ else if (isdig)
{
new->lease_time = atoi(a[j]) * fac;
/* Leases of a minute or less confuse
diff --git a/src/rfc1035.c b/src/rfc1035.c
index 7321d96..e547782 100644
--- a/src/rfc1035.c
+++ b/src/rfc1035.c
@@ -16,13 +16,6 @@
#include "dnsmasq.h"
-
-#define CHECK_LEN(header, pp, plen, len) \
- ((size_t)((pp) - (unsigned char *)(header) + (len)) <= (plen))
-
-#define ADD_RDLEN(header, pp, plen, len) \
- (!CHECK_LEN(header, pp, plen, len) ? 0 : (((pp) += (len)), 1))
-
int extract_name(struct dns_header *header, size_t plen, unsigned char **pp,
char *name, int isExtract, int extrabytes)
{
@@ -1299,7 +1292,7 @@ int check_for_bogus_wildcard(struct dns_header *header, size_t qlen, char *name,
/* Found a bogus address. Insert that info here, since there no SOA record
to get the ttl from in the normal processing */
cache_start_insert();
- cache_insert(name, NULL, now, ttl, F_IPV4 | F_FORWARD | F_NEG | F_NXDOMAIN | F_CONFIG);
+ cache_insert(name, NULL, now, ttl, F_IPV4 | F_FORWARD | F_NEG | F_NXDOMAIN);
cache_end_insert();
return 1;
diff --git a/src/slaac.c b/src/slaac.c
index 43c2c38..7eb4236 100644
--- a/src/slaac.c
+++ b/src/slaac.c
@@ -93,7 +93,6 @@ void slaac_add_addrs(struct dhcp_lease *lease, time_t now, int force)
slaac->ping_time = now;
slaac->backoff = 1;
slaac->addr = addr;
- slaac->local = context->local6;
/* Do RA's to prod it */
ra_start_unsolicted(now, context);
}