/** dump one rrset zonefile line */
static int
dump_rrset_line(SSL* ssl, struct ub_packed_rrset_key* k,
- struct packed_rrset_data* d, uint32_t now, int i, uint16_t type)
+ struct packed_rrset_data* d, uint32_t now, size_t i, uint16_t type)
{
char* s;
ldns_rr* rr = to_rr(k, d, now, i, type);
return 1;
}
+/** read qinfo from next three words */
+static char*
+load_qinfo(char* str, struct query_info* qinfo, ldns_buffer* buf,
+ struct regional* region, SSL* ssl)
+{
+ /* s is part of the buf */
+ char* s = str;
+ ldns_rr* rr;
+ ldns_status status;
+
+ /* skip three words */
+ s = strchr(str, ' ');
+ if(s) s = strchr(s+1, ' ');
+ if(s) s = strchr(s+1, ' ');
+ if(!s) {
+ (void)ssl_printf(ssl, "error line too short, %s\n", str);
+ return NULL;
+ }
+ s[0] = 0;
+ s++;
+
+ /* parse them */
+ status = ldns_rr_new_question_frm_str(&rr, str, NULL, NULL);
+ if(status != LDNS_STATUS_OK) {
+ (void)ssl_printf(ssl, "error cannot parse: %s %s\n",
+ ldns_get_errorstr_by_id(status), str);
+ return NULL;
+ }
+ qinfo->qtype = ldns_rr_get_type(rr);
+ qinfo->qclass = ldns_rr_get_class(rr);
+ ldns_buffer_clear(buf);
+ status = ldns_dname2buffer_wire(buf, ldns_rr_owner(rr));
+ if(status != LDNS_STATUS_OK) {
+ (void)ssl_printf(ssl, "error cannot dname2wire: %s\n",
+ ldns_get_errorstr_by_id(status));
+ ldns_rr_free(rr);
+ return NULL;
+ }
+ ldns_rr_free(rr);
+ ldns_buffer_flip(buf);
+ qinfo->qname_len = ldns_buffer_limit(buf);
+ qinfo->qname = (uint8_t*)regional_alloc_init(region,
+ ldns_buffer_begin(buf), ldns_buffer_limit(buf));
+ if(!qinfo->qname) {
+ (void)ssl_printf(ssl, "error out of memory\n");
+ return NULL;
+ }
+
+ return s;
+}
+
/** load a msg rrset reference */
static int
load_ref(SSL* ssl, ldns_buffer* buf, struct worker* worker,
struct regional *region, struct ub_packed_rrset_key** rrset,
int* go_on)
{
- ldns_rr* rr;
- ldns_status status;
char* s = (char*)ldns_buffer_begin(buf);
+ struct query_info qinfo;
+ unsigned int flags;
+ struct ub_packed_rrset_key* k;
/* read line */
if(!ssl_read_buf(ssl, buf))
return 0;
+ if(strncmp(s, "BADREF", 6) == 0) {
+ *go_on = 0; /* its bad, skip it and skip message */
+ return 1;
+ }
- s += 4;
- /* skip three words */
- s = strchr(s, ' ');
- if(s) s = strchr(s+1, ' ');
- if(s) s = strchr(s+1, ' ');
+ s = load_qinfo(s, &qinfo, buf, region, ssl);
if(!s) {
- (void)ssl_printf(ssl, "error ref line too short, %s\n", s);
return 0;
}
- s[0] = 0;
-
- status = ldns_rr_new_question_frm_str(&rr,
- (char*)ldns_buffer_begin(buf), NULL, NULL);
- if(status != LDNS_STATUS_OK) {
- (void)ssl_printf(ssl, "error cannot parse ref: %s %s\n",
- ldns_get_errorstr_by_id(status), s);
- ldns_rr_free(rr);
+ if(sscanf(s, " %u", &flags) != 1) {
+ (void)ssl_printf(ssl, "error cannot parse flags: %s\n", s);
return 0;
}
- ldns_rr_free(rr);
-
/* lookup in cache */
+ k = rrset_cache_lookup(worker->env.rrset_cache, qinfo.qname,
+ qinfo.qname_len, qinfo.qtype, qinfo.qclass,
+ (uint32_t)flags, *worker->env.now, 0);
+ if(!k) {
+ /* not found or expired */
+ *go_on = 0;
+ return 1;
+ }
+
/* store in result */
- return 1;
+ *rrset = packed_rrset_copy_region(k, region, *worker->env.now);
+ lock_rw_unlock(&k->entry.lock);
+
+ return (*rrset != NULL);
}
/** load a msg entry */
struct query_info qinf;
struct reply_info rep;
char* s = (char*)ldns_buffer_begin(buf);
- ldns_rr* rr;
- ldns_status status;
unsigned int flags, qdcount, ttl, security, an, ns, ar;
size_t i;
int go_on = 1;
return 0;
}
s += 4;
- /* skip three words */
- s = strchr(s, ' ');
- if(s) s = strchr(s+1, ' ');
- if(s) s = strchr(s+1, ' ');
+ s = load_qinfo(s, &qinf, buf, region, ssl);
if(!s) {
- (void)ssl_printf(ssl, "error msg line too short, %s\n", s);
- return 0;
- }
- s[0] = 0;
-
- status = ldns_rr_new_question_frm_str(&rr,
- (char*)ldns_buffer_at(buf, 4), NULL, NULL);
- if(status != LDNS_STATUS_OK) {
- (void)ssl_printf(ssl, "error cannot parse query: %s %s\n",
- ldns_get_errorstr_by_id(status), s);
- ldns_rr_free(rr);
return 0;
}
/* read remainder of line */
- if(sscanf(s+1, " %u %u %u %u %u %u %u", &flags, &qdcount, &ttl,
+ if(sscanf(s, " %u %u %u %u %u %u %u", &flags, &qdcount, &ttl,
&security, &an, &ns, &ar) != 7) {
- (void)ssl_printf(ssl, "error cannot parse numbers: %s\n", s+1);
- ldns_rr_free(rr);
- return 0;
- }
-
- /* fill qinfo and repinfo */
- qinf.qtype = ldns_rr_get_type(rr);
- qinf.qclass = ldns_rr_get_class(rr);
- ldns_buffer_clear(buf);
- status = ldns_dname2buffer_wire(buf, ldns_rr_owner(rr));
- if(status != LDNS_STATUS_OK) {
- (void)ssl_printf(ssl, "error cannot dname2wire: %s\n",
- ldns_get_errorstr_by_id(status));
- ldns_rr_free(rr);
- return 0;
- }
- ldns_rr_free(rr);
- ldns_buffer_flip(buf);
- qinf.qname_len = ldns_buffer_limit(buf);
- qinf.qname = (uint8_t*)regional_alloc_init(region,
- ldns_buffer_begin(buf), ldns_buffer_limit(buf));
- if(!qinf.qname) {
- (void)ssl_printf(ssl, "error out of memory\n");
+ (void)ssl_printf(ssl, "error cannot parse numbers: %s\n", s);
return 0;
}
rep.flags = (uint16_t)flags;
slabhash_insert(env->msg_cache, hash, &e->entry, rep, env->alloc);
}
-/** allocate rrset in region - no more locks needed */
-static struct ub_packed_rrset_key*
-copy_rrset(struct ub_packed_rrset_key* key, struct regional* region,
- uint32_t now)
-{
- struct ub_packed_rrset_key* ck = regional_alloc(region,
- sizeof(struct ub_packed_rrset_key));
- struct packed_rrset_data* d;
- struct packed_rrset_data* data = (struct packed_rrset_data*)
- key->entry.data;
- size_t dsize, i;
- if(!ck)
- return NULL;
- ck->id = key->id;
- memset(&ck->entry, 0, sizeof(ck->entry));
- ck->entry.hash = key->entry.hash;
- ck->entry.key = ck;
- ck->rk = key->rk;
- ck->rk.dname = regional_alloc_init(region, key->rk.dname,
- key->rk.dname_len);
- if(!ck->rk.dname)
- return NULL;
- dsize = packed_rrset_sizeof(data);
- d = (struct packed_rrset_data*)regional_alloc_init(region, data, dsize);
- if(!d)
- return NULL;
- ck->entry.data = d;
- packed_rrset_ptr_fixup(d);
- /* make TTLs relative - once per rrset */
- for(i=0; i<d->count + d->rrsig_count; i++)
- d->rr_ttl[i] -= now;
- d->ttl -= now;
- return ck;
-}
-
/** find closest NS or DNAME and returns the rrset (locked) */
static struct ub_packed_rrset_key*
find_closest_of_type(struct module_env* env, uint8_t* qname, size_t qnamelen,
struct dns_msg* msg, uint32_t now)
{
if((msg->rep->rrsets[msg->rep->rrset_count] =
- copy_rrset(rrset, region, now))) {
+ packed_rrset_copy_region(rrset, region, now))) {
msg->rep->ar_numrrsets++;
msg->rep->rrset_count++;
}
if(rrset) {
/* add it to auth section. This is the second rrset. */
if((msg->rep->rrsets[msg->rep->rrset_count] =
- copy_rrset(rrset, region, now))) {
+ packed_rrset_copy_region(rrset, region, now))) {
msg->rep->ns_numrrsets++;
msg->rep->rrset_count++;
}
(2 + nsdata->count*2)*sizeof(struct ub_packed_rrset_key*));
if(!msg->rep->rrsets)
return NULL;
- msg->rep->rrsets[0] = copy_rrset(nskey, region, now);
+ msg->rep->rrsets[0] = packed_rrset_copy_region(nskey, region, now);
if(!msg->rep->rrsets[0])
return NULL;
msg->rep->ns_numrrsets++;
if(!rrset_array_lock(r->ref, r->rrset_count, now))
return NULL;
for(i=0; i<msg->rep->rrset_count; i++) {
- msg->rep->rrsets[i] = copy_rrset(r->rrsets[i], region, now);
+ msg->rep->rrsets[i] = packed_rrset_copy_region(r->rrsets[i],
+ region, now);
if(!msg->rep->rrsets[i]) {
rrset_array_unlock(r->ref, r->rrset_count);
return NULL;
msg->rep->ns_numrrsets = 0;
msg->rep->ar_numrrsets = 0;
msg->rep->rrset_count = 1;
- msg->rep->rrsets[0] = copy_rrset(rrset, region, now);
+ msg->rep->rrsets[0] = packed_rrset_copy_region(rrset, region, now);
if(!msg->rep->rrsets[0]) /* copy CNAME */
return NULL;
return msg;
msg->rep->ns_numrrsets = 0;
msg->rep->ar_numrrsets = 0;
msg->rep->rrset_count = 1;
- msg->rep->rrsets[0] = copy_rrset(rrset, region, now);
+ msg->rep->rrsets[0] = packed_rrset_copy_region(rrset, region, now);
if(!msg->rep->rrsets[0]) /* copy DNAME */
return NULL;
/* synth CNAME rrset */