/** setup qinfo and edns */ static int setup_qinfo_edns(struct libworker* w, struct ctx_query* q, struct query_info* qinfo, struct edns_data* edns) { ldns_rdf* rdf; qinfo->qtype = (uint16_t)q->res->qtype; qinfo->qclass = (uint16_t)q->res->qclass; rdf = ldns_dname_new_frm_str(q->res->qname); if(!rdf) { return 0; } #ifdef UNBOUND_ALLOC_LITE qinfo->qname = memdup(ldns_rdf_data(rdf), ldns_rdf_size(rdf)); qinfo->qname_len = ldns_rdf_size(rdf); ldns_rdf_deep_free(rdf); rdf = 0; #else qinfo->qname = ldns_rdf_data(rdf); qinfo->qname_len = ldns_rdf_size(rdf); #endif edns->edns_present = 1; edns->ext_rcode = 0; edns->edns_version = 0; edns->bits = EDNS_DO; if(ldns_buffer_capacity(w->back->udp_buff) < 65535) edns->udp_size = (uint16_t)ldns_buffer_capacity( w->back->udp_buff); else edns->udp_size = 65535; ldns_rdf_free(rdf); return 1; }
void ldns_buffer_copy(ldns_buffer* result, ldns_buffer* from) { size_t tocopy = ldns_buffer_limit(from); if(tocopy > ldns_buffer_capacity(result)) tocopy = ldns_buffer_capacity(result); ldns_buffer_clear(result); ldns_buffer_write(result, ldns_buffer_begin(from), tocopy); ldns_buffer_flip(result); }
static int l_pkt2string(lua_State *L) { ldns_buffer *b; luaL_Buffer lua_b; ldns_pkt *p = (ldns_pkt *)lua_touserdata(L, 1); if (!p) { return 0; } b = ldns_buffer_new(LDNS_MAX_PACKETLEN); luaL_buffinit(L,&lua_b); if (ldns_pkt2buffer_wire(b, p) != LDNS_STATUS_OK) { ldns_buffer_free(b); return 0; } /* this is a memcpy??? */ luaL_addlstring(&lua_b, (char*)ldns_buffer_begin(b), ldns_buffer_capacity(b) ); /* I hope so */ ldns_buffer_free(b); luaL_pushresult(&lua_b); return 1; }
size_t listen_get_mem(struct listen_dnsport* listen) { size_t s = sizeof(*listen) + sizeof(*listen->base) + sizeof(*listen->udp_buff) + ldns_buffer_capacity(listen->udp_buff); struct listen_list* p; for(p = listen->cps; p; p = p->next) { s += sizeof(*p); s += comm_point_get_mem(p->com); } return s; }
size_t mesh_get_mem(struct mesh_area* mesh) { struct mesh_state* m; size_t s = sizeof(*mesh) + sizeof(struct timehist) + sizeof(struct th_buck)*mesh->histogram->num + sizeof(ldns_buffer) + ldns_buffer_capacity(mesh->qbuf_bak); RBTREE_FOR(m, struct mesh_state*, &mesh->all) { /* all, including m itself allocated in qstate region */ s += regional_get_mem(m->s.region); } return s; }
static int l_buf_info(lua_State *L) { ldns_buffer *b = (ldns_buffer *)lua_touserdata(L, 1); if (!b) { return 0; } printf("capacity %d; position %d; limit %d\n", ldns_buffer_capacity(b), ldns_buffer_position(b), ldns_buffer_limit(b)); return 0; }
struct waiting_tcp* pending_tcp_query(struct outside_network* outnet, ldns_buffer* packet, struct sockaddr_storage* addr, socklen_t addrlen, int timeout, comm_point_callback_t* callback, void* callback_arg) { struct replay_runtime* runtime = (struct replay_runtime*)outnet->base; struct fake_pending* pend = (struct fake_pending*)calloc(1, sizeof(struct fake_pending)); ldns_status status; log_assert(pend); pend->buffer = ldns_buffer_new(ldns_buffer_capacity(packet)); log_assert(pend->buffer); ldns_buffer_write(pend->buffer, ldns_buffer_begin(packet), ldns_buffer_limit(packet)); ldns_buffer_flip(pend->buffer); memcpy(&pend->addr, addr, addrlen); pend->addrlen = addrlen; pend->callback = callback; pend->cb_arg = callback_arg; pend->timeout = timeout; pend->transport = transport_tcp; pend->pkt = NULL; pend->runtime = runtime; pend->serviced = 0; status = ldns_buffer2pkt_wire(&pend->pkt, packet); if(status != LDNS_STATUS_OK) { log_err("ldns error parsing tcp output packet: %s", ldns_get_errorstr_by_id(status)); fatal_exit("Sending unparseable DNS packets to servers!"); } log_pkt("pending tcp pkt: ", pend->pkt); /* see if it matches the current moment */ if(runtime->now && runtime->now->evt_type == repevt_back_query && (runtime->now->addrlen == 0 || sockaddr_cmp( &runtime->now->addr, runtime->now->addrlen, &pend->addr, pend->addrlen) == 0) && find_match(runtime->now->match, pend->pkt, pend->transport)) { log_info("testbound: matched pending to event. " "advance time between events."); log_info("testbound: do STEP %d %s", runtime->now->time_step, repevt_string(runtime->now->evt_type)); advance_moment(runtime); /* still create the pending, because we need it to callback */ } log_info("testbound: created fake pending"); /* add to list */ pend->next = runtime->pending_list; runtime->pending_list = pend; return (struct waiting_tcp*)pend; }
ldns_buffer * read_hex_buffer(char *filename) { uint8_t *wire; size_t wiresize; ldns_buffer *result_buffer = NULL; wire = xmalloc(LDNS_MAX_PACKETLEN); wiresize = packetbuffromfile(filename, wire); result_buffer = LDNS_MALLOC(ldns_buffer); ldns_buffer_new_frm_data(result_buffer, wire, wiresize); ldns_buffer_set_position(result_buffer, ldns_buffer_capacity(result_buffer)); xfree(wire); return result_buffer; }
/** Report on memory usage by this thread and global */ static void worker_mem_report(struct worker* ATTR_UNUSED(worker), struct serviced_query* ATTR_UNUSED(cur_serv)) { #ifdef UNBOUND_ALLOC_STATS /* debug func in validator module */ size_t total, front, back, mesh, msg, rrset, infra, ac, superac; size_t me, iter, val, anch; int i; if(verbosity < VERB_ALGO) return; front = listen_get_mem(worker->front); back = outnet_get_mem(worker->back); msg = slabhash_get_mem(worker->env.msg_cache); rrset = slabhash_get_mem(&worker->env.rrset_cache->table); infra = infra_get_mem(worker->env.infra_cache); mesh = mesh_get_mem(worker->env.mesh); ac = alloc_get_mem(&worker->alloc); superac = alloc_get_mem(&worker->daemon->superalloc); anch = anchors_get_mem(worker->env.anchors); iter = 0; val = 0; for(i=0; i<worker->env.mesh->mods.num; i++) { fptr_ok(fptr_whitelist_mod_get_mem(worker->env.mesh-> mods.mod[i]->get_mem)); if(strcmp(worker->env.mesh->mods.mod[i]->name, "validator")==0) val += (*worker->env.mesh->mods.mod[i]->get_mem) (&worker->env, i); else iter += (*worker->env.mesh->mods.mod[i]->get_mem) (&worker->env, i); } me = sizeof(*worker) + sizeof(*worker->base) + sizeof(*worker->comsig) + comm_point_get_mem(worker->cmd_com) + sizeof(worker->rndstate) + regional_get_mem(worker->scratchpad) + sizeof(*worker->env.scratch_buffer) + ldns_buffer_capacity(worker->env.scratch_buffer) + forwards_get_mem(worker->env.fwds) + hints_get_mem(worker->env.hints); if(worker->thread_num == 0) me += acl_list_get_mem(worker->daemon->acl); if(cur_serv) { me += serviced_get_mem(cur_serv); } total = front+back+mesh+msg+rrset+infra+iter+val+ac+superac+me; log_info("Memory conditions: %u front=%u back=%u mesh=%u msg=%u " "rrset=%u infra=%u iter=%u val=%u anchors=%u " "alloccache=%u globalalloccache=%u me=%u", (unsigned)total, (unsigned)front, (unsigned)back, (unsigned)mesh, (unsigned)msg, (unsigned)rrset, (unsigned)infra, (unsigned)iter, (unsigned)val, (unsigned)anch, (unsigned)ac, (unsigned)superac, (unsigned)me); debug_total_mem(total); #else /* no UNBOUND_ALLOC_STATS */ size_t val = 0; int i; if(verbosity < VERB_QUERY) return; for(i=0; i<worker->env.mesh->mods.num; i++) { fptr_ok(fptr_whitelist_mod_get_mem(worker->env.mesh-> mods.mod[i]->get_mem)); if(strcmp(worker->env.mesh->mods.mod[i]->name, "validator")==0) val += (*worker->env.mesh->mods.mod[i]->get_mem) (&worker->env, i); } verbose(VERB_QUERY, "cache memory msg=%u rrset=%u infra=%u val=%u", (unsigned)slabhash_get_mem(worker->env.msg_cache), (unsigned)slabhash_get_mem(&worker->env.rrset_cache->table), (unsigned)infra_get_mem(worker->env.infra_cache), (unsigned)val); #endif /* UNBOUND_ALLOC_STATS */ }
/** read a line from ssl into buffer */ static int ssl_read_buf(SSL* ssl, ldns_buffer* buf) { return ssl_read_line(ssl, (char*)ldns_buffer_begin(buf), ldns_buffer_capacity(buf)); }
/* * Parses data buffer to a query, finds the correct answer * and calls the given function for every packet to send. */ void handle_query(uint8_t* inbuf, ssize_t inlen, struct entry* entries, int* count, enum transport_type transport, void (*sendfunc)(uint8_t*, size_t, void*), void* userdata, FILE* verbose_out) { ldns_status status; ldns_pkt *query_pkt = NULL; ldns_pkt *answer_pkt = NULL; struct reply_packet *p; ldns_rr *query_rr = NULL; uint8_t *outbuf = NULL; size_t answer_size = 0; struct entry* entry = NULL; ldns_rdf *stop_command = ldns_dname_new_frm_str("server.stop."); status = ldns_wire2pkt(&query_pkt, inbuf, (size_t)inlen); if (status != LDNS_STATUS_OK) { verbose(1, "Got bad packet: %s\n", ldns_get_errorstr_by_id(status)); ldns_rdf_free(stop_command); return; } query_rr = ldns_rr_list_rr(ldns_pkt_question(query_pkt), 0); verbose(1, "query %d: id %d: %s %d bytes: ", ++(*count), (int)ldns_pkt_id(query_pkt), (transport==transport_tcp)?"TCP":"UDP", (int)inlen); if(verbose_out) ldns_rr_print(verbose_out, query_rr); if(verbose_out) ldns_pkt_print(verbose_out, query_pkt); if (ldns_rr_get_type(query_rr) == LDNS_RR_TYPE_TXT && ldns_rr_get_class(query_rr) == LDNS_RR_CLASS_CH && ldns_dname_compare(ldns_rr_owner(query_rr), stop_command) == 0) { exit(0); } /* fill up answer packet */ entry = find_match(entries, query_pkt, transport); if(!entry || !entry->reply_list) { verbose(1, "no answer packet for this query, no reply.\n"); ldns_pkt_free(query_pkt); ldns_rdf_free(stop_command); return; } for(p = entry->reply_list; p; p = p->next) { verbose(3, "Answer pkt:\n"); if (p->reply_from_hex) { /* try to parse the hex packet, if it can be * parsed, we can use adjust rules. if not, * send packet literally */ status = ldns_buffer2pkt_wire(&answer_pkt, p->reply_from_hex); if (status == LDNS_STATUS_OK) { adjust_packet(entry, answer_pkt, query_pkt); if(verbose_out) ldns_pkt_print(verbose_out, answer_pkt); status = ldns_pkt2wire(&outbuf, answer_pkt, &answer_size); verbose(2, "Answer packet size: %u bytes.\n", (unsigned int)answer_size); if (status != LDNS_STATUS_OK) { verbose(1, "Error creating answer: %s\n", ldns_get_errorstr_by_id(status)); ldns_pkt_free(query_pkt); ldns_rdf_free(stop_command); return; } ldns_pkt_free(answer_pkt); answer_pkt = NULL; } else { verbose(3, "Could not parse hex data (%s), sending hex data directly.\n", ldns_get_errorstr_by_id(status)); /* still try to adjust ID */ answer_size = ldns_buffer_capacity(p->reply_from_hex); outbuf = LDNS_XMALLOC(uint8_t, answer_size); memcpy(outbuf, ldns_buffer_export(p->reply_from_hex), answer_size); if(entry->copy_id) { ldns_write_uint16(outbuf, ldns_pkt_id(query_pkt)); } } } else { answer_pkt = ldns_pkt_clone(p->reply); adjust_packet(entry, answer_pkt, query_pkt); if(verbose_out) ldns_pkt_print(verbose_out, answer_pkt); status = ldns_pkt2wire(&outbuf, answer_pkt, &answer_size); verbose(1, "Answer packet size: %u bytes.\n", (unsigned int)answer_size); if (status != LDNS_STATUS_OK) { verbose(1, "Error creating answer: %s\n", ldns_get_errorstr_by_id(status)); ldns_pkt_free(query_pkt); ldns_rdf_free(stop_command); return; } ldns_pkt_free(answer_pkt); answer_pkt = NULL; } if(p->packet_sleep) { verbose(3, "sleeping for next packet %d secs\n", p->packet_sleep); #ifdef HAVE_SLEEP sleep(p->packet_sleep); #else Sleep(p->packet_sleep * 1000); #endif verbose(3, "wakeup for next packet " "(slept %d secs)\n", p->packet_sleep); } sendfunc(outbuf, answer_size, userdata); LDNS_FREE(outbuf); outbuf = NULL; answer_size = 0; } ldns_pkt_free(query_pkt); ldns_rdf_free(stop_command); }