summaryrefslogtreecommitdiff
path: root/util/data
diff options
context:
space:
mode:
Diffstat (limited to 'util/data')
-rw-r--r--util/data/dname.c58
-rw-r--r--util/data/dname.h9
-rw-r--r--util/data/msgencode.c6
-rw-r--r--util/data/msgparse.c6
-rw-r--r--util/data/msgparse.h4
-rw-r--r--util/data/msgreply.c4
-rw-r--r--util/data/packed_rrset.c21
-rw-r--r--util/data/packed_rrset.h13
8 files changed, 116 insertions, 5 deletions
diff --git a/util/data/dname.c b/util/data/dname.c
index 9f25e1efe204..76b2ec7d6d8a 100644
--- a/util/data/dname.c
+++ b/util/data/dname.c
@@ -233,17 +233,28 @@ int
dname_pkt_compare(sldns_buffer* pkt, uint8_t* d1, uint8_t* d2)
{
uint8_t len1, len2;
+ int count1 = 0, count2 = 0;
log_assert(pkt && d1 && d2);
len1 = *d1++;
len2 = *d2++;
while( len1 != 0 || len2 != 0 ) {
/* resolve ptrs */
if(LABEL_IS_PTR(len1)) {
+ if((size_t)PTR_OFFSET(len1, *d1)
+ >= sldns_buffer_limit(pkt))
+ return -1;
+ if(count1++ > MAX_COMPRESS_PTRS)
+ return -1;
d1 = sldns_buffer_at(pkt, PTR_OFFSET(len1, *d1));
len1 = *d1++;
continue;
}
if(LABEL_IS_PTR(len2)) {
+ if((size_t)PTR_OFFSET(len2, *d2)
+ >= sldns_buffer_limit(pkt))
+ return 1;
+ if(count2++ > MAX_COMPRESS_PTRS)
+ return 1;
d2 = sldns_buffer_at(pkt, PTR_OFFSET(len2, *d2));
len2 = *d2++;
continue;
@@ -302,12 +313,18 @@ dname_pkt_hash(sldns_buffer* pkt, uint8_t* dname, hashvalue_type h)
uint8_t labuf[LDNS_MAX_LABELLEN+1];
uint8_t lablen;
int i;
+ int count = 0;
/* preserve case of query, make hash label by label */
lablen = *dname++;
while(lablen) {
if(LABEL_IS_PTR(lablen)) {
/* follow pointer */
+ if((size_t)PTR_OFFSET(lablen, *dname)
+ >= sldns_buffer_limit(pkt))
+ return h;
+ if(count++ > MAX_COMPRESS_PTRS)
+ return h;
dname = sldns_buffer_at(pkt, PTR_OFFSET(lablen, *dname));
lablen = *dname++;
continue;
@@ -341,6 +358,9 @@ void dname_pkt_copy(sldns_buffer* pkt, uint8_t* to, uint8_t* dname)
return;
}
/* follow pointer */
+ if((size_t)PTR_OFFSET(lablen, *dname)
+ >= sldns_buffer_limit(pkt))
+ return;
dname = sldns_buffer_at(pkt, PTR_OFFSET(lablen, *dname));
lablen = *dname++;
continue;
@@ -369,6 +389,7 @@ void dname_pkt_copy(sldns_buffer* pkt, uint8_t* to, uint8_t* dname)
void dname_print(FILE* out, struct sldns_buffer* pkt, uint8_t* dname)
{
uint8_t lablen;
+ int count = 0;
if(!out) out = stdout;
if(!dname) return;
@@ -382,6 +403,15 @@ void dname_print(FILE* out, struct sldns_buffer* pkt, uint8_t* dname)
fputs("??compressionptr??", out);
return;
}
+ if((size_t)PTR_OFFSET(lablen, *dname)
+ >= sldns_buffer_limit(pkt)) {
+ fputs("??compressionptr??", out);
+ return;
+ }
+ if(count++ > MAX_COMPRESS_PTRS) {
+ fputs("??compressionptr??", out);
+ return;
+ }
dname = sldns_buffer_at(pkt, PTR_OFFSET(lablen, *dname));
lablen = *dname++;
continue;
@@ -558,6 +588,34 @@ dname_lab_startswith(uint8_t* label, char* prefix, char** endptr)
return 1;
}
+int
+dname_has_label(uint8_t* dname, size_t dnamelen, uint8_t* label)
+{
+ size_t len;
+
+ /* 1 byte needed for the label length */
+ if(dnamelen < 1)
+ return 0;
+
+ len = *dname;
+ while(len <= dnamelen) {
+ if(!(*dname)) {
+ if(*dname == *label)
+ return 1; /* empty label match */
+ /* termination label found, stop iterating */
+ return 0;
+ }
+ if(*dname == *label && *label &&
+ memlowercmp(dname+1, label+1, *dname) == 0)
+ return 1;
+ len += *dname;
+ dname += *dname;
+ dname++;
+ len++;
+ }
+ return 0;
+}
+
int
dname_buffer_write(sldns_buffer* pkt, uint8_t* dname)
{
diff --git a/util/data/dname.h b/util/data/dname.h
index 53a33c689bc0..e37c11822b36 100644
--- a/util/data/dname.h
+++ b/util/data/dname.h
@@ -197,6 +197,15 @@ int dname_lab_cmp(uint8_t* d1, int labs1, uint8_t* d2, int labs2, int* mlabs);
int dname_lab_startswith(uint8_t* label, char* prefix, char** endptr);
/**
+ * Check if dname contains label
+ * @param dname: dname
+ * @param dnamelen: length of dname
+ * @param label: label to be checked for presence in dname
+ * @return: 1 if dname has this label, 0 otherwise
+ */
+int dname_has_label(uint8_t* dname, size_t dnamelen, uint8_t* label);
+
+/**
* See if domain name d1 is a strict subdomain of d2.
* That is a subdomain, but not equal.
* @param d1: domain name, uncompressed wireformat
diff --git a/util/data/msgencode.c b/util/data/msgencode.c
index a51a4b9b85d8..be69f628a507 100644
--- a/util/data/msgencode.c
+++ b/util/data/msgencode.c
@@ -480,7 +480,8 @@ packed_rrset_encode(struct ub_packed_rrset_key* key, sldns_buffer* pkt,
sldns_buffer_write(pkt, &key->rk.type, 2);
sldns_buffer_write(pkt, &key->rk.rrset_class, 2);
if(data->rr_ttl[j] < timenow)
- sldns_buffer_write_u32(pkt, 0);
+ sldns_buffer_write_u32(pkt,
+ SERVE_EXPIRED?SERVE_EXPIRED_REPLY_TTL:0);
else sldns_buffer_write_u32(pkt,
data->rr_ttl[j]-timenow);
if(c) {
@@ -517,7 +518,8 @@ packed_rrset_encode(struct ub_packed_rrset_key* key, sldns_buffer* pkt,
sldns_buffer_write_u16(pkt, LDNS_RR_TYPE_RRSIG);
sldns_buffer_write(pkt, &key->rk.rrset_class, 2);
if(data->rr_ttl[i] < timenow)
- sldns_buffer_write_u32(pkt, 0);
+ sldns_buffer_write_u32(pkt,
+ SERVE_EXPIRED?SERVE_EXPIRED_REPLY_TTL:0);
else sldns_buffer_write_u32(pkt,
data->rr_ttl[i]-timenow);
/* rrsig rdata cannot be compressed, perform 100+ byte
diff --git a/util/data/msgparse.c b/util/data/msgparse.c
index fb312370366d..7c32618a3015 100644
--- a/util/data/msgparse.c
+++ b/util/data/msgparse.c
@@ -55,7 +55,11 @@ smart_compare(sldns_buffer* pkt, uint8_t* dnow,
{
if(LABEL_IS_PTR(*dnow)) {
/* ptr points to a previous dname */
- uint8_t* p = sldns_buffer_at(pkt, PTR_OFFSET(dnow[0], dnow[1]));
+ uint8_t* p;
+ if((size_t)PTR_OFFSET(dnow[0], dnow[1])
+ >= sldns_buffer_limit(pkt))
+ return -1;
+ p = sldns_buffer_at(pkt, PTR_OFFSET(dnow[0], dnow[1]));
if( p == dprfirst || p == dprlast )
return 0;
/* prev dname is also a ptr, both ptrs are the same. */
diff --git a/util/data/msgparse.h b/util/data/msgparse.h
index c0c6ff5fd09f..fd04f9f6f071 100644
--- a/util/data/msgparse.h
+++ b/util/data/msgparse.h
@@ -79,8 +79,12 @@ extern time_t MAX_TTL;
extern time_t MIN_TTL;
/** Maximum Negative TTL that is allowed */
extern time_t MAX_NEG_TTL;
+/** If we serve expired entries and prefetch them */
+extern int SERVE_EXPIRED;
/** Time to serve records after expiration */
extern time_t SERVE_EXPIRED_TTL;
+/** TTL to use for expired records */
+extern time_t SERVE_EXPIRED_REPLY_TTL;
/** Negative cache time (for entries without any RRs.) */
#define NORR_TTL 5 /* seconds */
diff --git a/util/data/msgreply.c b/util/data/msgreply.c
index 4320f312d6f3..927bf09a29d8 100644
--- a/util/data/msgreply.c
+++ b/util/data/msgreply.c
@@ -61,8 +61,12 @@ time_t MAX_TTL = 3600 * 24 * 10; /* ten days */
time_t MIN_TTL = 0;
/** MAX Negative TTL, for SOA records in authority section */
time_t MAX_NEG_TTL = 3600; /* one hour */
+/** If we serve expired entries and prefetch them */
+int SERVE_EXPIRED = 0;
/** Time to serve records after expiration */
time_t SERVE_EXPIRED_TTL = 0;
+/** TTL to use for expired records */
+time_t SERVE_EXPIRED_REPLY_TTL = 30;
/** allocate qinfo, return 0 on error */
static int
diff --git a/util/data/packed_rrset.c b/util/data/packed_rrset.c
index 7b9d5494d960..4b0294f9724b 100644
--- a/util/data/packed_rrset.c
+++ b/util/data/packed_rrset.c
@@ -40,6 +40,7 @@
*/
#include "config.h"
+#include "util/data/msgparse.h"
#include "util/data/packed_rrset.h"
#include "util/data/dname.h"
#include "util/storage/lookup3.h"
@@ -351,11 +352,11 @@ packed_rrset_copy_region(struct ub_packed_rrset_key* key,
/* make TTLs relative - once per rrset */
for(i=0; i<d->count + d->rrsig_count; i++) {
if(d->rr_ttl[i] < now)
- d->rr_ttl[i] = 0;
+ d->rr_ttl[i] = SERVE_EXPIRED?SERVE_EXPIRED_REPLY_TTL:0;
else d->rr_ttl[i] -= now;
}
if(d->ttl < now)
- d->ttl = 0;
+ d->ttl = SERVE_EXPIRED?SERVE_EXPIRED_REPLY_TTL:0;
else d->ttl -= now;
return ck;
}
@@ -386,3 +387,19 @@ packed_rrset_copy_alloc(struct ub_packed_rrset_key* key,
packed_rrset_ttl_add(dd, now);
return dk;
}
+
+int
+packed_rrset_find_rr(struct packed_rrset_data* d, uint8_t* rdata, size_t len,
+ size_t* index)
+{
+ size_t i;
+ for(i=0; i<d->count; i++) {
+ if(d->rr_len[i] != len)
+ continue;
+ if(memcmp(d->rr_data[i], rdata, len) == 0) {
+ *index = i;
+ return 1;
+ }
+ }
+ return 0;
+}
diff --git a/util/data/packed_rrset.h b/util/data/packed_rrset.h
index 3a5335ddfa59..729877bab5ec 100644
--- a/util/data/packed_rrset.h
+++ b/util/data/packed_rrset.h
@@ -446,4 +446,17 @@ struct ub_packed_rrset_key* packed_rrset_copy_alloc(
struct ub_packed_rrset_key* key, struct alloc_cache* alloc,
time_t now);
+/**
+ * Find RR index in packed rrset
+ * Raw comparison, does not canonicalize RDATA
+ * @param d: packed rrset
+ * @param rdata: RDATA of RR to find
+ * @param len: length of rdata
+ * @param index: pointer to int to store index of found RR
+ * @return 1 if RR found, 0 otherwise
+ */
+int
+packed_rrset_find_rr(struct packed_rrset_data* d, uint8_t* rdata, size_t len,
+ size_t* index);
+
#endif /* UTIL_DATA_PACKED_RRSET_H */