/** load an RR into rrset */ static int load_rr(SSL* ssl, sldns_buffer* buf, struct regional* region, struct ub_packed_rrset_key* rk, struct packed_rrset_data* d, unsigned int i, int is_rrsig, int* go_on, time_t now) { uint8_t rr[LDNS_RR_BUF_SIZE]; size_t rr_len = sizeof(rr), dname_len = 0; int status; /* read the line */ if(!ssl_read_buf(ssl, buf)) return 0; if(strncmp((char*)sldns_buffer_begin(buf), "BADRR\n", 6) == 0) { *go_on = 0; return 1; } status = sldns_str2wire_rr_buf((char*)sldns_buffer_begin(buf), rr, &rr_len, &dname_len, 3600, NULL, 0, NULL, 0); if(status != 0) { log_warn("error cannot parse rr: %s: %s", sldns_get_errorstr_parse(status), (char*)sldns_buffer_begin(buf)); return 0; } if(is_rrsig && sldns_wirerr_get_type(rr, rr_len, dname_len) != LDNS_RR_TYPE_RRSIG) { log_warn("error expected rrsig but got %s", (char*)sldns_buffer_begin(buf)); return 0; } /* convert ldns rr into packed_rr */ d->rr_ttl[i] = (time_t)sldns_wirerr_get_ttl(rr, rr_len, dname_len) + now; sldns_buffer_clear(buf); d->rr_len[i] = sldns_wirerr_get_rdatalen(rr, rr_len, dname_len)+2; d->rr_data[i] = (uint8_t*)regional_alloc_init(region, sldns_wirerr_get_rdatawl(rr, rr_len, dname_len), d->rr_len[i]); if(!d->rr_data[i]) { log_warn("error out of memory"); return 0; } /* if first entry, fill the key structure */ if(i==0) { rk->rk.type = htons(sldns_wirerr_get_type(rr, rr_len, dname_len)); rk->rk.rrset_class = htons(sldns_wirerr_get_class(rr, rr_len, dname_len)); rk->rk.dname_len = dname_len; rk->rk.dname = regional_alloc_init(region, rr, dname_len); if(!rk->rk.dname) { log_warn("error out of memory"); return 0; } } return 1; }
/** load msg cache */ static int load_msg_cache(SSL* ssl, struct worker* worker) { sldns_buffer* buf = worker->env.scratch_buffer; if(!read_fixed(ssl, buf, "START_MSG_CACHE")) return 0; while(ssl_read_buf(ssl, buf) && strcmp((char*)sldns_buffer_begin(buf), "END_MSG_CACHE")!=0) { if(!load_msg(ssl, buf, worker)) return 0; } return 1; }
/** load a msg rrset reference */ static int load_ref(SSL* ssl, sldns_buffer* buf, struct worker* worker, struct regional *region, struct ub_packed_rrset_key** rrset, int* go_on) { char* s = (char*)sldns_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 = load_qinfo(s, &qinfo, region); if(!s) { return 0; } if(sscanf(s, " %u", &flags) != 1) { log_warn("error cannot parse flags: %s", s); return 0; } /* 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 */ *rrset = packed_rrset_copy_region(k, region, *worker->env.now); lock_rw_unlock(&k->entry.lock); return (*rrset != NULL); }
/** check fixed text on line */ static int read_fixed(SSL* ssl, sldns_buffer* buf, const char* str) { if(!ssl_read_buf(ssl, buf)) return 0; return (strcmp((char*)sldns_buffer_begin(buf), str) == 0); }
/** load an RR into rrset */ static int load_rr(SSL* ssl, ldns_buffer* buf, struct regional* region, struct ub_packed_rrset_key* rk, struct packed_rrset_data* d, unsigned int i, int is_rrsig, int* go_on, uint32_t now) { ldns_rr* rr; ldns_status status; /* read the line */ if(!ssl_read_buf(ssl, buf)) return 0; if(strncmp((char*)ldns_buffer_begin(buf), "BADRR\n", 6) == 0) { *go_on = 0; return 1; } status = ldns_rr_new_frm_str(&rr, (char*)ldns_buffer_begin(buf), LDNS_DEFAULT_TTL, NULL, NULL); if(status != LDNS_STATUS_OK) { log_warn("error cannot parse rr: %s: %s", ldns_get_errorstr_by_id(status), (char*)ldns_buffer_begin(buf)); return 0; } if(is_rrsig && ldns_rr_get_type(rr) != LDNS_RR_TYPE_RRSIG) { log_warn("error expected rrsig but got %s", (char*)ldns_buffer_begin(buf)); return 0; } /* convert ldns rr into packed_rr */ d->rr_ttl[i] = ldns_rr_ttl(rr) + now; ldns_buffer_clear(buf); ldns_buffer_skip(buf, 2); status = ldns_rr_rdata2buffer_wire(buf, rr); if(status != LDNS_STATUS_OK) { log_warn("error cannot rr2wire: %s", ldns_get_errorstr_by_id(status)); ldns_rr_free(rr); return 0; } ldns_buffer_flip(buf); ldns_buffer_write_u16_at(buf, 0, ldns_buffer_limit(buf) - 2); d->rr_len[i] = ldns_buffer_limit(buf); d->rr_data[i] = (uint8_t*)regional_alloc_init(region, ldns_buffer_begin(buf), ldns_buffer_limit(buf)); if(!d->rr_data[i]) { ldns_rr_free(rr); log_warn("error out of memory"); return 0; } /* if first entry, fill the key structure */ if(i==0) { rk->rk.type = htons(ldns_rr_get_type(rr)); rk->rk.rrset_class = htons(ldns_rr_get_class(rr)); ldns_buffer_clear(buf); status = ldns_dname2buffer_wire(buf, ldns_rr_owner(rr)); if(status != LDNS_STATUS_OK) { log_warn("error cannot dname2buffer: %s", ldns_get_errorstr_by_id(status)); ldns_rr_free(rr); return 0; } ldns_buffer_flip(buf); rk->rk.dname_len = ldns_buffer_limit(buf); rk->rk.dname = regional_alloc_init(region, ldns_buffer_begin(buf), ldns_buffer_limit(buf)); if(!rk->rk.dname) { log_warn("error out of memory"); ldns_rr_free(rr); return 0; } } ldns_rr_free(rr); return 1; }