/** fillup fg results */ static void libworker_fillup_fg(struct ctx_query* q, int rcode, sldns_buffer* buf, enum sec_status s, char* why_bogus) { if(why_bogus) q->res->why_bogus = strdup(why_bogus); if(rcode != 0) { q->res->rcode = rcode; q->msg_security = s; return; } q->res->rcode = LDNS_RCODE_SERVFAIL; q->msg_security = 0; q->msg = memdup(sldns_buffer_begin(buf), sldns_buffer_limit(buf)); q->msg_len = sldns_buffer_limit(buf); if(!q->msg) { return; /* the error is in the rcode */ } /* canonname and results */ q->msg_security = s; libworker_enter_result(q->res, buf, q->w->env->scratch, s); }
/** process answer from bg worker */ static int process_answer_detail(struct ub_ctx* ctx, uint8_t* msg, uint32_t len, ub_callback_t* cb, void** cbarg, int* err, struct ub_result** res) { struct ctx_query* q; if(context_serial_getcmd(msg, len) != UB_LIBCMD_ANSWER) { log_err("error: bad data from bg worker %d", (int)context_serial_getcmd(msg, len)); return 0; } lock_basic_lock(&ctx->cfglock); q = context_deserialize_answer(ctx, msg, len, err); if(!q) { lock_basic_unlock(&ctx->cfglock); /* probably simply the lookup that failed, i.e. * response returned before cancel was sent out, so noerror */ return 1; } log_assert(q->async); /* grab cb while locked */ if(q->cancelled) { *cb = NULL; *cbarg = NULL; } else { *cb = q->cb; *cbarg = q->cb_arg; } if(*err) { *res = NULL; ub_resolve_free(q->res); } else { /* parse the message, extract rcode, fill result */ ldns_buffer* buf = ldns_buffer_new(q->msg_len); struct regional* region = regional_create(); *res = q->res; (*res)->rcode = LDNS_RCODE_SERVFAIL; if(region && buf) { ldns_buffer_clear(buf); ldns_buffer_write(buf, q->msg, q->msg_len); ldns_buffer_flip(buf); libworker_enter_result(*res, buf, region, q->msg_security); } (*res)->answer_packet = q->msg; (*res)->answer_len = (int)q->msg_len; q->msg = NULL; ldns_buffer_free(buf); regional_destroy(region); } q->res = NULL; /* delete the q from list */ (void)rbtree_delete(&ctx->queries, q->node.key); ctx->num_async--; context_query_delete(q); lock_basic_unlock(&ctx->cfglock); if(*cb) return 2; ub_resolve_free(*res); return 1; }