diff options
Diffstat (limited to 'util/data')
| -rw-r--r-- | util/data/dname.c | 58 | ||||
| -rw-r--r-- | util/data/dname.h | 9 | ||||
| -rw-r--r-- | util/data/msgencode.c | 6 | ||||
| -rw-r--r-- | util/data/msgparse.c | 6 | ||||
| -rw-r--r-- | util/data/msgparse.h | 4 | ||||
| -rw-r--r-- | util/data/msgreply.c | 4 | ||||
| -rw-r--r-- | util/data/packed_rrset.c | 21 | ||||
| -rw-r--r-- | util/data/packed_rrset.h | 13 |
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 */ |
