/** performance test message encoding */ static void perf_encode(struct query_info* qi, struct reply_info* rep, uint16_t id, uint16_t flags, sldns_buffer* out, time_t timenow, struct edns_data* edns) { static int num = 0; int ret; size_t max = 10000; size_t i; struct timeval start, end; double dt; struct regional* r2 = regional_create(); if(gettimeofday(&start, NULL) < 0) fatal_exit("gettimeofday: %s", strerror(errno)); /* encode a couple times */ for(i=0; i<max; i++) { ret = reply_info_encode(qi, rep, id, flags, out, timenow, r2, 65535, (int)(edns->bits & EDNS_DO) ); unit_assert(ret != 0); /* udp packets should fit */ attach_edns_record(out, edns); regional_free_all(r2); } if(gettimeofday(&end, NULL) < 0) fatal_exit("gettimeofday: %s", strerror(errno)); /* time in millisec */ dt = (double)(end.tv_sec - start.tv_sec)*1000. + ((double)end.tv_usec - (double)start.tv_usec)/1000.; printf("[%d] did %u in %g msec for %f encode/sec size %d\n", num++, (unsigned)max, dt, (double)max / (dt/1000.), (int)sldns_buffer_limit(out)); regional_destroy(r2); }
void log_dns_msg(const char* str, struct query_info* qinfo, struct reply_info* rep) { /* not particularly fast but flexible, make wireformat and print */ ldns_buffer* buf = ldns_buffer_new(65535); struct regional* region = regional_create(); if(!reply_info_encode(qinfo, rep, 0, rep->flags, buf, 0, region, 65535, 1)) { log_info("%s: log_dns_msg: out of memory", str); } else { ldns_status s; ldns_pkt* pkt = NULL; s = ldns_buffer2pkt_wire(&pkt, buf); if(s != LDNS_STATUS_OK) { log_info("%s: log_dns_msg: ldns parse gave: %s", str, ldns_get_errorstr_by_id(s)); } else { ldns_buffer_clear(buf); s = ldns_pkt2buffer_str(buf, pkt); if(s != LDNS_STATUS_OK) { log_info("%s: log_dns_msg: ldns tostr gave: %s", str, ldns_get_errorstr_by_id(s)); } else { log_info("%s %s", str, (char*)ldns_buffer_begin(buf)); } } ldns_pkt_free(pkt); } ldns_buffer_free(buf); regional_destroy(region); }
/** perf test a packet */ static void perftestpkt(sldns_buffer* pkt, struct alloc_cache* alloc, sldns_buffer* out, const char* hex) { struct query_info qi; struct reply_info* rep = 0; int ret; uint16_t id; uint16_t flags; time_t timenow = 0; struct regional* region = regional_create(); struct edns_data edns; hex_to_buf(pkt, hex); memmove(&id, sldns_buffer_begin(pkt), sizeof(id)); if(sldns_buffer_limit(pkt) < 2) flags = 0; else memmove(&flags, sldns_buffer_at(pkt, 2), sizeof(flags)); flags = ntohs(flags); ret = reply_info_parse(pkt, alloc, &qi, &rep, region, &edns); if(ret != 0) { char rbuf[16]; sldns_wire2str_rcode_buf(ret, rbuf, sizeof(rbuf)); if(vbmp) printf("parse code %d: %s\n", ret, rbuf); if(ret == LDNS_RCODE_FORMERR) checkformerr(pkt); unit_assert(ret != LDNS_RCODE_SERVFAIL); } else { perf_encode(&qi, rep, id, flags, out, timenow, &edns); } query_info_clear(&qi); reply_info_parsedelete(rep, alloc); regional_destroy(region); }
/** verify DS matches DNSKEY from a file */ static void dstest_file(const char* fname) { /* * The file contains a list of ldns-testpkts entries. * The first entry must be a query for DNSKEY. * The answer rrset is the keyset that will be used for verification */ struct regional* region = regional_create(); struct alloc_cache alloc; ldns_buffer* buf = ldns_buffer_new(65535); struct entry* e; struct entry* list = read_datafile(fname); struct module_env env; if(!list) fatal_exit("could not read %s: %s", fname, strerror(errno)); alloc_init(&alloc, NULL, 1); memset(&env, 0, sizeof(env)); env.scratch = region; env.scratch_buffer = buf; unit_assert(region && buf); /* ready to go! */ for(e = list; e; e = e->next) { dstest_entry(e, &alloc, region, buf, &env); } delete_entry(list); regional_destroy(region); alloc_clear(&alloc); ldns_buffer_free(buf); }
void acl_list_delete(struct acl_list* acl) { if(!acl) return; regional_destroy(acl->region); free(acl); }
void respip_set_delete(struct respip_set* set) { if(!set) return; regional_destroy(set->region); free(set); }
void local_zone_delete(struct local_zone* z) { if(!z) return; lock_rw_destroy(&z->lock); regional_destroy(z->region); free(z->name); free(z->taglist); free(z); }
void alloc_reg_release(struct alloc_cache* alloc, struct regional* r) { if(alloc->num_reg_blocks >= alloc->max_reg_blocks) { regional_destroy(r); return; } if(!r) return; regional_free_all(r); log_assert(r->next == NULL); r->next = (char*)alloc->reg_list; alloc->reg_list = r; alloc->num_reg_blocks++; }
void anchors_delete(struct val_anchors* anchors) { if(!anchors) return; lock_unprotect(&anchors->lock, anchors->autr); lock_unprotect(&anchors->lock, anchors); lock_basic_destroy(&anchors->lock); traverse_postorder(anchors->tree, anchors_delfunc, NULL); free(anchors->tree); regional_destroy(anchors->region); autr_global_delete(anchors->autr); free(anchors); }
/** check if module works with config */ static void check_mod(struct config_file* cfg, struct module_func_block* fb) { struct module_env env; memset(&env, 0, sizeof(env)); env.cfg = cfg; env.scratch = regional_create(); env.scratch_buffer = ldns_buffer_new(BUFSIZ); if(!env.scratch || !env.scratch_buffer) fatal_exit("out of memory"); if(!(*fb->init)(&env, 0)) { fatal_exit("bad config for %s module", fb->name); } (*fb->deinit)(&env, 0); ldns_buffer_free(env.scratch_buffer); regional_destroy(env.scratch); }
/** verify from a file */ static void verifytest_file(const char* fname, const char* at_date) { /* * The file contains a list of ldns-testpkts entries. * The first entry must be a query for DNSKEY. * The answer rrset is the keyset that will be used for verification */ struct ub_packed_rrset_key* dnskey; struct regional* region = regional_create(); struct alloc_cache alloc; ldns_buffer* buf = ldns_buffer_new(65535); struct entry* e; struct entry* list = read_datafile(fname); struct module_env env; struct val_env ve; uint32_t now = time(NULL); if(!list) fatal_exit("could not read %s: %s", fname, strerror(errno)); alloc_init(&alloc, NULL, 1); memset(&env, 0, sizeof(env)); memset(&ve, 0, sizeof(ve)); env.scratch = region; env.scratch_buffer = buf; env.now = &now; ve.date_override = cfg_convert_timeval(at_date); unit_assert(region && buf); dnskey = extract_keys(list, &alloc, region, buf); if(vsig) log_nametypeclass(VERB_QUERY, "test dnskey", dnskey->rk.dname, ntohs(dnskey->rk.type), ntohs(dnskey->rk.rrset_class)); /* ready to go! */ for(e = list->next; e; e = e->next) { verifytest_entry(e, &alloc, region, buf, dnskey, &env, &ve); } ub_packed_rrset_parsedelete(dnskey, &alloc); delete_entry(list); regional_destroy(region); alloc_clear(&alloc); ldns_buffer_free(buf); }
/** delete libworker env */ static void libworker_delete_env(struct libworker* w) { if(w->env) { outside_network_quit_prepare(w->back); mesh_delete(w->env->mesh); context_release_alloc(w->ctx, w->env->alloc, !w->is_bg || w->is_bg_thread); sldns_buffer_free(w->env->scratch_buffer); regional_destroy(w->env->scratch); forwards_delete(w->env->fwds); hints_delete(w->env->hints); ub_randfree(w->env->rnd); free(w->env); } #ifdef HAVE_SSL SSL_CTX_free(w->sslctx); #endif outside_network_delete(w->back); }
/** delete libworker struct */ static void libworker_delete(struct libworker* w) { if(!w) return; if(w->env) { outside_network_quit_prepare(w->back); mesh_delete(w->env->mesh); context_release_alloc(w->ctx, w->env->alloc, !w->is_bg || w->is_bg_thread); ldns_buffer_free(w->env->scratch_buffer); regional_destroy(w->env->scratch); forwards_delete(w->env->fwds); ub_randfree(w->env->rnd); free(w->env); } SSL_CTX_free(w->sslctx); outside_network_delete(w->back); comm_base_delete(w->base); free(w); }
void log_dns_msg(const char* str, struct query_info* qinfo, struct reply_info* rep) { /* not particularly fast but flexible, make wireformat and print */ sldns_buffer* buf = sldns_buffer_new(65535); struct regional* region = regional_create(); if(!reply_info_encode(qinfo, rep, 0, rep->flags, buf, 0, region, 65535, 1)) { log_info("%s: log_dns_msg: out of memory", str); } else { char* s = sldns_wire2str_pkt(sldns_buffer_begin(buf), sldns_buffer_limit(buf)); if(!s) { log_info("%s: log_dns_msg: ldns tostr failed", str); } else { log_info("%s %s", str, s); } free(s); } sldns_buffer_free(buf); regional_destroy(region); }
/** Read file to test NSEC3 hash algo */ static void nsec3_hash_test(const char* fname) { /* * The list contains a list of ldns-testpkts entries. * Every entry is a test. * The qname is hashed. * The answer section AAAA RR name is the required result. * The auth section NSEC3 is used to get hash parameters. * The hash cache is maintained per file. * * The test does not perform canonicalization during the compare. */ rbtree_t ct; struct regional* region = regional_create(); struct alloc_cache alloc; ldns_buffer* buf = ldns_buffer_new(65535); struct entry* e; struct entry* list = read_datafile(fname); if(!list) fatal_exit("could not read %s: %s", fname, strerror(errno)); rbtree_init(&ct, &nsec3_hash_cmp); alloc_init(&alloc, NULL, 1); unit_assert(region && buf); /* ready to go! */ for(e = list; e; e = e->next) { nsec3_hash_test_entry(e, &ct, &alloc, region, buf); } delete_entry(list); regional_destroy(region); alloc_clear(&alloc); ldns_buffer_free(buf); }
/** 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; }
/** test a packet */ static void testpkt(sldns_buffer* pkt, struct alloc_cache* alloc, sldns_buffer* out, const char* hex) { struct query_info qi; struct reply_info* rep = 0; int ret; uint16_t id; uint16_t flags; uint32_t timenow = 0; struct regional* region = regional_create(); struct edns_data edns; hex_to_buf(pkt, hex); memmove(&id, sldns_buffer_begin(pkt), sizeof(id)); if(sldns_buffer_limit(pkt) < 2) flags = 0; else memmove(&flags, sldns_buffer_at(pkt, 2), sizeof(flags)); flags = ntohs(flags); ret = reply_info_parse(pkt, alloc, &qi, &rep, region, &edns); if(ret != 0) { char rbuf[16]; sldns_wire2str_rcode_buf(ret, rbuf, sizeof(rbuf)); if(vbmp) printf("parse code %d: %s\n", ret, rbuf); if(ret == LDNS_RCODE_FORMERR) { unit_assert(!check_formerr_gone); checkformerr(pkt); } unit_assert(ret != LDNS_RCODE_SERVFAIL); } else if(!check_formerr_gone) { const size_t lim = 512; ret = reply_info_encode(&qi, rep, id, flags, out, timenow, region, 65535, (int)(edns.bits & EDNS_DO) ); unit_assert(ret != 0); /* udp packets should fit */ attach_edns_record(out, &edns); if(vbmp) printf("inlen %u outlen %u\n", (unsigned)sldns_buffer_limit(pkt), (unsigned)sldns_buffer_limit(out)); if(!check_nosameness) test_buffers(pkt, out); if(check_rrsigs) check_the_rrsigs(&qi, rep); if(sldns_buffer_limit(out) > lim) { ret = reply_info_encode(&qi, rep, id, flags, out, timenow, region, lim - calc_edns_field_size(&edns), (int)(edns.bits & EDNS_DO)); unit_assert(ret != 0); /* should fit, but with TC */ attach_edns_record(out, &edns); if( LDNS_QDCOUNT(sldns_buffer_begin(out)) != LDNS_QDCOUNT(sldns_buffer_begin(pkt)) || LDNS_ANCOUNT(sldns_buffer_begin(out)) != LDNS_ANCOUNT(sldns_buffer_begin(pkt)) || LDNS_NSCOUNT(sldns_buffer_begin(out)) != LDNS_NSCOUNT(sldns_buffer_begin(pkt))) unit_assert( LDNS_TC_WIRE(sldns_buffer_begin(out))); /* must set TC bit if shortened */ unit_assert(sldns_buffer_limit(out) <= lim); } } query_info_clear(&qi); reply_info_parsedelete(rep, alloc); regional_destroy(region); }