struct ctx_query* context_deserialize_new_query(struct ub_ctx* ctx, uint8_t* p, uint32_t len) { struct ctx_query* q = (struct ctx_query*)calloc(1, sizeof(*q)); if(!q) return NULL; if(len < 4*sizeof(uint32_t)+1) { free(q); return NULL; } log_assert( ldns_read_uint32(p) == UB_LIBCMD_NEWQUERY); q->querynum = (int)ldns_read_uint32(p+sizeof(uint32_t)); q->node.key = &q->querynum; q->async = 1; q->res = (struct ub_result*)calloc(1, sizeof(*q->res)); if(!q->res) { free(q); return NULL; } q->res->qtype = (int)ldns_read_uint32(p+2*sizeof(uint32_t)); q->res->qclass = (int)ldns_read_uint32(p+3*sizeof(uint32_t)); q->res->qname = strdup((char*)(p+4*sizeof(uint32_t))); if(!q->res->qname) { free(q->res); free(q); return NULL; } /** add to query list */ ctx->num_async++; (void)rbtree_insert(&ctx->queries, &q->node); return q; }
struct ctx_query* context_deserialize_cancel(struct ub_ctx* ctx, uint8_t* p, uint32_t len) { struct ctx_query* q; int id; if(len != 2*sizeof(uint32_t)) return NULL; log_assert( ldns_read_uint32(p) == UB_LIBCMD_CANCEL); id = (int)ldns_read_uint32(p+sizeof(uint32_t)); q = (struct ctx_query*)rbtree_search(&ctx->queries, &id); return q; }
enum ub_ctx_cmd context_serial_getcmd(uint8_t* p, uint32_t len) { uint32_t v; if((size_t)len < sizeof(v)) return UB_LIBCMD_QUIT; v = ldns_read_uint32(p); return v; }
struct ctx_query* context_lookup_new_query(struct ub_ctx* ctx, uint8_t* p, uint32_t len) { struct ctx_query* q; int querynum; if(len < 4*sizeof(uint32_t)+1) { return NULL; } log_assert( ldns_read_uint32(p) == UB_LIBCMD_NEWQUERY); querynum = (int)ldns_read_uint32(p+sizeof(uint32_t)); q = (struct ctx_query*)rbtree_search(&ctx->queries, &querynum); if(!q) { return NULL; } log_assert(q->async); return q; }
struct ctx_query* context_deserialize_answer(struct ub_ctx* ctx, uint8_t* p, uint32_t len, int* err) { struct ctx_query* q = NULL ; int id; size_t wlen; if(len < 5*sizeof(uint32_t)) return NULL; log_assert( ldns_read_uint32(p) == UB_LIBCMD_ANSWER); id = (int)ldns_read_uint32(p+sizeof(uint32_t)); q = (struct ctx_query*)rbtree_search(&ctx->queries, &id); if(!q) return NULL; *err = (int)ldns_read_uint32(p+2*sizeof(uint32_t)); q->msg_security = ldns_read_uint32(p+3*sizeof(uint32_t)); wlen = (size_t)ldns_read_uint32(p+4*sizeof(uint32_t)); if(len > 5*sizeof(uint32_t) && wlen > 0) { if(len >= 5*sizeof(uint32_t)+wlen) q->res->why_bogus = (char*)memdup( p+5*sizeof(uint32_t), wlen); if(!q->res->why_bogus) { /* pass malloc failure to the user callback */ q->msg_len = 0; *err = UB_NOMEM; return q; } q->res->why_bogus[wlen-1] = 0; /* zero terminated for sure */ } if(len > 5*sizeof(uint32_t)+wlen) { q->msg_len = len - 5*sizeof(uint32_t) - wlen; q->msg = (uint8_t*)memdup(p+5*sizeof(uint32_t)+wlen, q->msg_len); if(!q->msg) { /* pass malloc failure to the user callback */ q->msg_len = 0; *err = UB_NOMEM; return q; } } return q; }
void worker_handle_control_cmd(struct tube* ATTR_UNUSED(tube), uint8_t* msg, size_t len, int error, void* arg) { struct worker* worker = (struct worker*)arg; enum worker_commands cmd; if(error != NETEVENT_NOERROR) { free(msg); if(error == NETEVENT_CLOSED) comm_base_exit(worker->base); else log_info("control event: %d", error); return; } if(len != sizeof(uint32_t)) { fatal_exit("bad control msg length %d", (int)len); } cmd = ldns_read_uint32(msg); free(msg); switch(cmd) { case worker_cmd_quit: verbose(VERB_ALGO, "got control cmd quit"); comm_base_exit(worker->base); break; case worker_cmd_stats: verbose(VERB_ALGO, "got control cmd stats"); server_stats_reply(worker, 1); break; case worker_cmd_stats_noreset: verbose(VERB_ALGO, "got control cmd stats_noreset"); server_stats_reply(worker, 0); break; case worker_cmd_remote: verbose(VERB_ALGO, "got control cmd remote"); daemon_remote_exec(worker); break; default: log_err("bad command %d", (int)cmd); break; } }
ldns_status ldns_pkt2buffer_wire(ldns_buffer *buffer, const ldns_pkt *packet) { ldns_rr_list *rr_list; uint16_t i; /* edns tmp vars */ ldns_rr *edns_rr; uint8_t edata[4]; (void) ldns_hdr2buffer_wire(buffer, packet); rr_list = ldns_pkt_question(packet); if (rr_list) { for (i = 0; i < ldns_rr_list_rr_count(rr_list); i++) { (void) ldns_rr2buffer_wire(buffer, ldns_rr_list_rr(rr_list, i), LDNS_SECTION_QUESTION); } } rr_list = ldns_pkt_answer(packet); if (rr_list) { for (i = 0; i < ldns_rr_list_rr_count(rr_list); i++) { (void) ldns_rr2buffer_wire(buffer, ldns_rr_list_rr(rr_list, i), LDNS_SECTION_ANSWER); } } rr_list = ldns_pkt_authority(packet); if (rr_list) { for (i = 0; i < ldns_rr_list_rr_count(rr_list); i++) { (void) ldns_rr2buffer_wire(buffer, ldns_rr_list_rr(rr_list, i), LDNS_SECTION_AUTHORITY); } } rr_list = ldns_pkt_additional(packet); if (rr_list) { for (i = 0; i < ldns_rr_list_rr_count(rr_list); i++) { (void) ldns_rr2buffer_wire(buffer, ldns_rr_list_rr(rr_list, i), LDNS_SECTION_ADDITIONAL); } } /* add EDNS to additional if it is needed */ if (ldns_pkt_edns(packet)) { edns_rr = ldns_rr_new(); ldns_rr_set_owner(edns_rr, ldns_rdf_new_frm_str(LDNS_RDF_TYPE_DNAME, ".")); ldns_rr_set_type(edns_rr, LDNS_RR_TYPE_OPT); ldns_rr_set_class(edns_rr, ldns_pkt_edns_udp_size(packet)); edata[0] = ldns_pkt_edns_extended_rcode(packet); edata[1] = ldns_pkt_edns_version(packet); ldns_write_uint16(&edata[2], ldns_pkt_edns_z(packet)); ldns_rr_set_ttl(edns_rr, ldns_read_uint32(edata)); (void)ldns_rr2buffer_wire(buffer, edns_rr, LDNS_SECTION_ADDITIONAL); ldns_rr_free(edns_rr); } /* add TSIG to additional if it is there */ if (ldns_pkt_tsig(packet)) { (void) ldns_rr2buffer_wire(buffer, ldns_pkt_tsig(packet), LDNS_SECTION_ADDITIONAL); } return LDNS_STATUS_OK; }
/** do the rdata copy */ static int rdata_copy(ldns_buffer* pkt, struct packed_rrset_data* data, uint8_t* to, struct rr_parse* rr, uint32_t* rr_ttl, uint16_t type) { uint16_t pkt_len; const ldns_rr_descriptor* desc; *rr_ttl = ldns_read_uint32(rr->ttl_data); /* RFC 2181 Section 8. if msb of ttl is set treat as if zero. */ if(*rr_ttl & 0x80000000U) *rr_ttl = 0; if(*rr_ttl < MIN_TTL) *rr_ttl = MIN_TTL; if(*rr_ttl < data->ttl) data->ttl = *rr_ttl; if(rr->outside_packet) { /* uncompressed already, only needs copy */ memmove(to, rr->ttl_data+sizeof(uint32_t), rr->size); return 1; } ldns_buffer_set_position(pkt, (size_t) (rr->ttl_data - ldns_buffer_begin(pkt) + sizeof(uint32_t))); /* insert decompressed size into rdata len stored in memory */ /* -2 because rdatalen bytes are not included. */ pkt_len = htons(rr->size - 2); memmove(to, &pkt_len, sizeof(uint16_t)); to += 2; /* read packet rdata len */ pkt_len = ldns_buffer_read_u16(pkt); if(ldns_buffer_remaining(pkt) < pkt_len) return 0; desc = ldns_rr_descript(type); if(pkt_len > 0 && desc && desc->_dname_count > 0) { int count = (int)desc->_dname_count; int rdf = 0; size_t len; size_t oldpos; /* decompress dnames. */ while(pkt_len > 0 && count) { switch(desc->_wireformat[rdf]) { case LDNS_RDF_TYPE_DNAME: oldpos = ldns_buffer_position(pkt); dname_pkt_copy(pkt, to, ldns_buffer_current(pkt)); to += pkt_dname_len(pkt); pkt_len -= ldns_buffer_position(pkt)-oldpos; count--; len = 0; break; case LDNS_RDF_TYPE_STR: len = ldns_buffer_current(pkt)[0] + 1; break; default: len = get_rdf_size(desc->_wireformat[rdf]); break; } if(len) { memmove(to, ldns_buffer_current(pkt), len); to += len; ldns_buffer_skip(pkt, (ssize_t)len); log_assert(len <= pkt_len); pkt_len -= len; } rdf++; } } /* copy remaining rdata */ if(pkt_len > 0) memmove(to, ldns_buffer_current(pkt), pkt_len); return 1; }