#include "daemon/daemon.h"
#include "util/netevent.h"
#include "util/config_file.h"
+#include "util/region-allocator.h"
#include "util/storage/slabhash.h"
#include "services/listen_dnsport.h"
#include "services/outside_network.h"
slabhash_insert(worker->daemon->rrset_cache,
rep->rrsets[i]->entry.hash, &rep->rrsets[i]->entry,
rep->rrsets[i]->entry.data, &worker->alloc);
- /* TODO store correct key and id */
+ if(e) rep->rrsets[i] = rep->ref[i].key;
}
}
if(LDNS_QDCOUNT(ldns_buffer_begin(c->buffer)) > 1)
return 0; /* too much in the query section */
/* woohoo a reply! */
- if((r=reply_info_parse(c->buffer, &w->worker->alloc, &qinf, &rep))!=0) {
+ if((r=reply_info_parse(c->buffer, &w->worker->alloc, &qinf, &rep,
+ w->worker->scratchpad))!=0) {
if(r == LDNS_RCODE_SERVFAIL)
log_err("reply_info_parse: out of memory");
/* formerr on my parse gives servfail to my client */
replyerror(LDNS_RCODE_SERVFAIL, w);
+ region_free_all(w->worker->scratchpad);
return 0;
}
if(!reply_info_answer_encode(&qinf, rep, w->query_id, w->query_flags,
- w->query_reply.c->buffer, 0, 0)) {
+ w->query_reply.c->buffer, 0, 0, w->worker->scratchpad)) {
replyerror(LDNS_RCODE_SERVFAIL, w);
query_info_clear(&qinf);
reply_info_parsedelete(rep, &w->worker->alloc);
+ region_free_all(w->worker->scratchpad);
return 0;
}
comm_point_send_reply(&w->query_reply);
+ region_free_all(w->worker->scratchpad);
req_release(w);
query_info_clear(&w->qinfo);
if(rep->ttl == 0) {
/** answer query from the cache */
static int
-answer_from_cache(struct lruhash_entry* e, uint16_t id,
+answer_from_cache(struct worker* worker, struct lruhash_entry* e, uint16_t id,
uint16_t flags, struct comm_reply* repinfo)
{
struct msgreply_entry* mrentry = (struct msgreply_entry*)e->key;
}
/* locked and ids and ttls are OK. */
if(!reply_info_answer_encode(&mrentry->key, rep, id, flags,
- repinfo->c->buffer, timenow, 1)) {
+ repinfo->c->buffer, timenow, 1, worker->scratchpad)) {
replyerror_fillbuf(LDNS_RCODE_SERVFAIL, repinfo, id,
flags, &mrentry->key);
}
/* unlock */
for(i=0; i<rep->rrset_count; i++)
lock_rw_unlock(&rep->ref[i].key->entry.lock);
+ region_free_all(worker->scratchpad);
/* go and return this buffer to the client */
return 1;
}
if((e=slabhash_lookup(worker->daemon->msg_cache, h, &qinfo, 0))) {
/* answer from cache - we have acquired a readlock on it */
log_info("answer from the cache");
- if(answer_from_cache(e,
+ if(answer_from_cache(worker, e,
*(uint16_t*)ldns_buffer_begin(c->buffer),
ldns_buffer_read_u16_at(c->buffer, 2), repinfo)) {
lock_rw_unlock(&e->lock);
server_stats_init(&worker->stats);
alloc_init(&worker->alloc, &worker->daemon->superalloc,
worker->thread_num);
+ worker->scratchpad = region_create_custom(malloc, free,
+ 65536, 8192, 32, 1);
return 1;
}
close(worker->cmd_recv_fd);
worker->cmd_recv_fd = -1;
alloc_clear(&worker->alloc);
+ region_destroy(worker->scratchpad);
free(worker);
}
}
int reply_info_parse(ldns_buffer* pkt, struct alloc_cache* alloc,
- struct query_info* qinf, struct reply_info** rep)
+ struct query_info* qinf, struct reply_info** rep, struct region* region)
{
/* use scratch pad region-allocator during parsing. */
- region_type* region = region_create(malloc, free);
struct msg_parse* msg;
int ret;
qinf->qname = NULL;
*rep = NULL;
if(!(msg = region_alloc(region, sizeof(*msg)))) {
- region_free_all(region);
- region_destroy(region);
return LDNS_RCODE_SERVFAIL;
}
memset(msg, 0, sizeof(*msg));
log_assert(ldns_buffer_position(pkt) == 0);
if((ret = parse_packet(pkt, msg, region)) != 0) {
- region_free_all(region);
- region_destroy(region);
return ret;
}
query_info_clear(qinf);
reply_info_parsedelete(*rep, alloc);
*rep = NULL;
- region_free_all(region);
- region_destroy(region);
return ret;
}
-
- /* exit and cleanup */
- region_free_all(region);
- region_destroy(region);
return 0;
}
int
reply_info_answer_encode(struct query_info* qinf, struct reply_info* rep,
uint16_t id, uint16_t qflags, ldns_buffer* pkt, uint32_t timenow,
- int cached)
+ int cached, struct region* region)
{
uint16_t flags;
- region_type* region = region_create(malloc, free);
if(!cached) {
/* original flags, copy RD bit from query. */
log_err("reply encode: out of memory");
return 0;
}
- region_destroy(region);
return 1;
}
* @param alloc: creates packed rrset key structures.
* @param rep: allocated reply_info is returned (only on no error).
* @param qinf: query_info is returned (only on no error).
+ * @param region: where to store temporary data (for parsing).
* @return: zero is OK, or DNS error code in case of error
* o FORMERR for parse errors.
* o SERVFAIL for memory allocation errors.
*/
int reply_info_parse(ldns_buffer* pkt, struct alloc_cache* alloc,
- struct query_info* qinf, struct reply_info** rep);
+ struct query_info* qinf, struct reply_info** rep,
+ struct region* region);
/**
* Sorts the ref array.
* @param timenow: time to subtract.
* @param cached: set true if a cached reply (so no AA bit).
* set false for the first reply.
+ * @param region: where to allocate temp variables (for compression).
* @return: 0 on error (server failure).
*/
int reply_info_answer_encode(struct query_info* qinf, struct reply_info* rep,
uint16_t id, uint16_t qflags, ldns_buffer* dest, uint32_t timenow,
- int cached);
+ int cached, struct region* region);
/**
* Regenerate the wireformat from the stored msg reply.