void dname_test(void) { sldns_buffer* loopbuf = sldns_buffer_new(14); sldns_buffer* boundbuf = sldns_buffer_new(16); sldns_buffer* buff = sldns_buffer_new(65800); unit_assert(loopbuf && boundbuf && buff); sldns_buffer_flip(buff); dname_setup_bufs(loopbuf, boundbuf); dname_test_qdl(buff); dname_test_qdtl(buff); dname_test_pdtl(loopbuf, boundbuf); dname_test_query_dname_compare(); dname_test_count_labels(); dname_test_count_size_labels(); dname_test_dname_lab_cmp(); dname_test_pkt_dname_len(buff); dname_test_strict_subdomain(); dname_test_subdomain(); dname_test_isroot(); dname_test_removelabel(); dname_test_sigcount(); dname_test_iswild(); dname_test_canoncmp(); dname_test_topdomain(); dname_test_valid(); sldns_buffer_free(buff); sldns_buffer_free(loopbuf); sldns_buffer_free(boundbuf); }
/** * Perform range entry on pending message. * @param runtime: runtime buffer size preference. * @param entry: entry that codes for the reply to do. * @param pend: pending query that is answered, callback called. */ static void answer_callback_from_entry(struct replay_runtime* runtime, struct entry* entry, struct fake_pending* pend) { struct comm_point c; struct comm_reply repinfo; void* cb_arg = pend->cb_arg; comm_point_callback_t* cb = pend->callback; memset(&c, 0, sizeof(c)); c.fd = -1; c.buffer = sldns_buffer_new(runtime->bufsize); c.type = comm_udp; if(pend->transport == transport_tcp) c.type = comm_tcp; fill_buffer_with_reply(c.buffer, entry, pend->pkt, pend->pkt_len); repinfo.c = &c; repinfo.addrlen = pend->addrlen; memcpy(&repinfo.addr, &pend->addr, pend->addrlen); if(!pend->serviced) pending_list_delete(runtime, pend); if((*cb)(&c, cb_arg, NETEVENT_NOERROR, &repinfo)) { fatal_exit("testbound: unexpected: callback returned 1"); } sldns_buffer_free(c.buffer); }
/** * Perform callback for fake pending message. */ static void fake_pending_callback(struct replay_runtime* runtime, struct replay_moment* todo, int error) { struct fake_pending* p = runtime->pending_list; struct comm_reply repinfo; struct comm_point c; void* cb_arg; comm_point_callback_t* cb; memset(&c, 0, sizeof(c)); if(!p) fatal_exit("No pending queries."); cb_arg = p->cb_arg; cb = p->callback; c.buffer = sldns_buffer_new(runtime->bufsize); c.type = comm_udp; if(p->transport == transport_tcp) c.type = comm_tcp; if(todo->evt_type == repevt_back_reply && todo->match) { fill_buffer_with_reply(c.buffer, todo->match, p->pkt, p->pkt_len); } repinfo.c = &c; repinfo.addrlen = p->addrlen; memcpy(&repinfo.addr, &p->addr, p->addrlen); if(!p->serviced) pending_list_delete(runtime, p); if((*cb)(&c, cb_arg, error, &repinfo)) { fatal_exit("unexpected: pending callback returned 1"); } /* delete the pending item. */ sldns_buffer_free(c.buffer); }
/** 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; sldns_buffer* buf = sldns_buffer_new(65535); struct entry* e; struct entry* list = read_datafile(fname, 1); 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); sldns_buffer_free(buf); }
void outside_network_delete(struct outside_network* outnet) { if(!outnet) return; sldns_buffer_free(outnet->udp_buff); free(outnet); }
void listen_delete(struct listen_dnsport* listen) { if(!listen) return; sldns_buffer_free(listen->udp_buff); free(listen); }
void listen_delete(struct listen_dnsport* front) { if(!front) return; listen_list_delete(front->cps); sldns_buffer_free(front->udp_buff); free(front); }
/** send the TCP queries and print answers */ static void send_em(const char* svr, int udp, int usessl, int noanswer, int num, char** qs) { sldns_buffer* buf = sldns_buffer_new(65553); int fd = open_svr(svr, udp); int i; SSL_CTX* ctx = NULL; SSL* ssl = NULL; if(!buf) fatal_exit("out of memory"); if(usessl) { ctx = connect_sslctx_create(NULL, NULL, NULL); if(!ctx) fatal_exit("cannot create ssl ctx"); ssl = outgoing_ssl_fd(ctx, fd); if(!ssl) fatal_exit("cannot create ssl"); while(1) { int r; ERR_clear_error(); if( (r=SSL_do_handshake(ssl)) == 1) break; r = SSL_get_error(ssl, r); if(r != SSL_ERROR_WANT_READ && r != SSL_ERROR_WANT_WRITE) { log_crypto_err("could not ssl_handshake"); exit(1); } } if(1) { X509* x = SSL_get_peer_certificate(ssl); if(!x) printf("SSL: no peer certificate\n"); else { X509_print_fp(stdout, x); X509_free(x); } } } for(i=0; i<num; i+=3) { printf("\nNext query is %s %s %s\n", qs[i], qs[i+1], qs[i+2]); write_q(fd, udp, ssl, buf, (uint16_t)get_random(), qs[i], qs[i+1], qs[i+2]); /* print at least one result */ if(!noanswer) recv_one(fd, udp, ssl, buf); } if(usessl) { SSL_shutdown(ssl); SSL_free(ssl); SSL_CTX_free(ctx); } #ifndef USE_WINSOCK close(fd); #else closesocket(fd); #endif sldns_buffer_free(buf); printf("orderly exit\n"); }
void comm_point_drop_reply(struct comm_reply* repinfo) { log_info("comm_point_drop_reply fake"); if(repinfo->c) { sldns_buffer_free(repinfo->c->buffer); free(repinfo->c); } }
/** delete a fake pending */ static void delete_fake_pending(struct fake_pending* pend) { if(!pend) return; free(pend->zone); sldns_buffer_free(pend->buffer); free(pend->pkt); free(pend); }
void msgparse_test(void) { sldns_buffer* pkt = sldns_buffer_new(65553); sldns_buffer* out = sldns_buffer_new(65553); struct alloc_cache super_a, alloc; /* init */ alloc_init(&super_a, NULL, 0); alloc_init(&alloc, &super_a, 2); unit_show_feature("message parse"); simpletest(pkt, &alloc, out); /* plain hex dumps, like pcat */ testfromfile(pkt, &alloc, out, "testdata/test_packets.1"); testfromfile(pkt, &alloc, out, "testdata/test_packets.2"); testfromfile(pkt, &alloc, out, "testdata/test_packets.3"); /* like from drill -w - */ testfromdrillfile(pkt, &alloc, out, "testdata/test_packets.4"); testfromdrillfile(pkt, &alloc, out, "testdata/test_packets.5"); matches_nolocation = 1; /* RR order not important for the next test */ testfromdrillfile(pkt, &alloc, out, "testdata/test_packets.6"); check_rrsigs = 1; testfromdrillfile(pkt, &alloc, out, "testdata/test_packets.7"); check_rrsigs = 0; matches_nolocation = 0; check_formerr_gone = 1; testfromdrillfile(pkt, &alloc, out, "testdata/test_packets.8"); check_formerr_gone = 0; check_rrsigs = 1; check_nosameness = 1; testfromdrillfile(pkt, &alloc, out, "testdata/test_packets.9"); check_nosameness = 0; check_rrsigs = 0; /* cleanup */ alloc_clear(&alloc); alloc_clear(&super_a); sldns_buffer_free(pkt); sldns_buffer_free(out); }
/** delete a replay answer */ static void delete_replay_answer(struct replay_answer* a) { if(!a) return; if(a->repinfo.c) { sldns_buffer_free(a->repinfo.c->buffer); free(a->repinfo.c); } free(a->pkt); free(a); }
void anchors_test(void) { sldns_buffer* buff = sldns_buffer_new(65800); struct val_anchors* a; unit_show_feature("trust anchor store"); unit_assert(a = anchors_create()); sldns_buffer_flip(buff); test_anchor_empty(a); test_anchor_one(buff, a); test_anchors(buff, a); anchors_delete(a); sldns_buffer_free(buff); }
/** main program for pktview */ int main(int argc, char* argv[]) { sldns_buffer* pkt = sldns_buffer_new(65553); if(argc != 1) { usage(argv); } if(!pkt) fatal_exit("out of memory"); read_input(pkt, stdin); analyze(pkt); sldns_buffer_free(pkt); return 0; }
/** 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; sldns_buffer* buf = sldns_buffer_new(65535); struct entry* e; struct entry* list = read_datafile(fname, 1); struct module_env env; struct val_env ve; time_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); sldns_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); }
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_type ct; struct regional* region = regional_create(); struct alloc_cache alloc; sldns_buffer* buf = sldns_buffer_new(65535); struct entry* e; struct entry* list = read_datafile(fname, 1); 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); sldns_buffer_free(buf); }
void outnet_serviced_query_stop(struct serviced_query* sq, void* cb_arg) { struct fake_pending* pend = (struct fake_pending*)sq; struct replay_runtime* runtime = pend->runtime; /* delete from the list */ struct fake_pending* p = runtime->pending_list, *prev=NULL; while(p) { if(p == pend) { log_assert(p->cb_arg == cb_arg); log_info("serviced pending delete"); if(prev) prev->next = p->next; else runtime->pending_list = p->next; sldns_buffer_free(p->buffer); free(p->pkt); free(p->zone); free(p); return; } prev = p; p = p->next; } log_info("double delete of pending serviced query"); }
/** 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 */ sldns_buffer* buf = sldns_buffer_new(q->msg_len); struct regional* region = regional_create(); *res = q->res; (*res)->rcode = LDNS_RCODE_SERVFAIL; if(region && buf) { sldns_buffer_clear(buf); sldns_buffer_write(buf, q->msg, q->msg_len); sldns_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; sldns_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; }
/** main program for perf */ int main(int argc, char* argv[]) { char* nm = argv[0]; int c; struct perfinfo info; #ifdef USE_WINSOCK int r; WSADATA wsa_data; #endif /* defaults */ memset(&info, 0, sizeof(info)); info.io_num = 16; log_init(NULL, 0, NULL); log_ident_set("perf"); checklock_start(); #ifdef USE_WINSOCK if((r = WSAStartup(MAKEWORD(2,2), &wsa_data)) != 0) fatal_exit("WSAStartup failed: %s", wsa_strerror(r)); #endif info.buf = sldns_buffer_new(65553); if(!info.buf) fatal_exit("out of memory"); /* parse the options */ while( (c=getopt(argc, argv, "d:ha:f:q")) != -1) { switch(c) { case 'q': info.quiet = 1; break; case 'd': if(atoi(optarg)==0 && strcmp(optarg, "0")!=0) { printf("-d not a number %s", optarg); return 1; } info.duration = atoi(optarg); break; case 'a': qlist_add_line(&info, optarg, 0); break; case 'f': qlist_read_file(&info, optarg); break; case '?': case 'h': default: usage(nm); } } argc -= optind; argv += optind; if(argc != 1) { printf("error: pass server IP address on commandline.\n"); usage(nm); } if(!extstrtoaddr(argv[0], &info.dest, &info.destlen)) { printf("Could not parse ip: %s\n", argv[0]); return 1; } if(info.qlist_size == 0) { printf("No queries to make, use -f or -a.\n"); return 1; } /* do the performance test */ perfmain(&info); sldns_buffer_free(info.buf); #ifdef USE_WINSOCK WSACleanup(); #endif checklock_stop(); return 0; }
/** delayer main service routine */ static void service(const char* bind_str, int bindport, const char* serv_str, size_t memsize, int delay_msec) { struct sockaddr_storage bind_addr, srv_addr; socklen_t bind_len, srv_len; struct ringbuf* ring = ring_create(memsize); struct timeval delay, reuse; sldns_buffer* pkt; int i, s, listen_s; #ifndef S_SPLINT_S delay.tv_sec = delay_msec / 1000; delay.tv_usec = (delay_msec % 1000)*1000; #endif reuse = delay; /* reuse is max(4*delay, 1 second) */ dl_tv_add(&reuse, &delay); dl_tv_add(&reuse, &delay); dl_tv_add(&reuse, &delay); if(reuse.tv_sec == 0) reuse.tv_sec = 1; if(!extstrtoaddr(serv_str, &srv_addr, &srv_len)) { printf("cannot parse forward address: %s\n", serv_str); exit(1); } pkt = sldns_buffer_new(65535); if(!pkt) fatal_exit("out of memory"); if( signal(SIGINT, delayer_sigh) == SIG_ERR || #ifdef SIGHUP signal(SIGHUP, delayer_sigh) == SIG_ERR || #endif #ifdef SIGQUIT signal(SIGQUIT, delayer_sigh) == SIG_ERR || #endif #ifdef SIGBREAK signal(SIGBREAK, delayer_sigh) == SIG_ERR || #endif #ifdef SIGALRM signal(SIGALRM, delayer_sigh) == SIG_ERR || #endif signal(SIGTERM, delayer_sigh) == SIG_ERR) fatal_exit("could not bind to signal"); /* bind UDP port */ if((s = socket(str_is_ip6(bind_str)?AF_INET6:AF_INET, SOCK_DGRAM, 0)) == -1) { #ifndef USE_WINSOCK fatal_exit("socket: %s", strerror(errno)); #else fatal_exit("socket: %s", wsa_strerror(WSAGetLastError())); #endif } i=0; if(bindport == 0) { bindport = 1024 + random()%64000; i = 100; } while(1) { if(!ipstrtoaddr(bind_str, bindport, &bind_addr, &bind_len)) { printf("cannot parse listen address: %s\n", bind_str); exit(1); } if(bind(s, (struct sockaddr*)&bind_addr, bind_len) == -1) { #ifndef USE_WINSOCK log_err("bind: %s", strerror(errno)); #else log_err("bind: %s", wsa_strerror(WSAGetLastError())); #endif if(i--==0) fatal_exit("cannot bind any port"); bindport = 1024 + random()%64000; } else break; } fd_set_nonblock(s); /* and TCP port */ if((listen_s = socket(str_is_ip6(bind_str)?AF_INET6:AF_INET, SOCK_STREAM, 0)) == -1) { #ifndef USE_WINSOCK fatal_exit("tcp socket: %s", strerror(errno)); #else fatal_exit("tcp socket: %s", wsa_strerror(WSAGetLastError())); #endif } #ifdef SO_REUSEADDR if(1) { int on = 1; if(setsockopt(listen_s, SOL_SOCKET, SO_REUSEADDR, (void*)&on, (socklen_t)sizeof(on)) < 0) #ifndef USE_WINSOCK fatal_exit("setsockopt(.. SO_REUSEADDR ..) failed: %s", strerror(errno)); #else fatal_exit("setsockopt(.. SO_REUSEADDR ..) failed: %s", wsa_strerror(WSAGetLastError())); #endif } #endif if(bind(listen_s, (struct sockaddr*)&bind_addr, bind_len) == -1) { #ifndef USE_WINSOCK fatal_exit("tcp bind: %s", strerror(errno)); #else fatal_exit("tcp bind: %s", wsa_strerror(WSAGetLastError())); #endif } if(listen(listen_s, 5) == -1) { #ifndef USE_WINSOCK fatal_exit("tcp listen: %s", strerror(errno)); #else fatal_exit("tcp listen: %s", wsa_strerror(WSAGetLastError())); #endif } fd_set_nonblock(listen_s); printf("listening on port: %d\n", bindport); /* process loop */ do_quit = 0; service_loop(s, listen_s, ring, &delay, &reuse, &srv_addr, srv_len, pkt); /* cleanup */ verbose(1, "cleanup"); #ifndef USE_WINSOCK close(s); close(listen_s); #else closesocket(s); closesocket(listen_s); #endif sldns_buffer_free(pkt); ring_delete(ring); }
int anchors_apply_cfg(struct val_anchors* anchors, struct config_file* cfg) { struct config_strlist* f; char* nm; sldns_buffer* parsebuf = sldns_buffer_new(65535); for(f = cfg->domain_insecure; f; f = f->next) { if(!f->str || f->str[0] == 0) /* empty "" */ continue; if(!anchor_insert_insecure(anchors, f->str)) { log_err("error in domain-insecure: %s", f->str); sldns_buffer_free(parsebuf); return 0; } } for(f = cfg->trust_anchor_file_list; f; f = f->next) { if(!f->str || f->str[0] == 0) /* empty "" */ continue; nm = f->str; if(cfg->chrootdir && cfg->chrootdir[0] && strncmp(nm, cfg->chrootdir, strlen(cfg->chrootdir)) == 0) nm += strlen(cfg->chrootdir); if(!anchor_read_file(anchors, parsebuf, nm, 0)) { log_err("error reading trust-anchor-file: %s", f->str); sldns_buffer_free(parsebuf); return 0; } } for(f = cfg->trusted_keys_file_list; f; f = f->next) { if(!f->str || f->str[0] == 0) /* empty "" */ continue; nm = f->str; if(cfg->chrootdir && cfg->chrootdir[0] && strncmp(nm, cfg->chrootdir, strlen(cfg->chrootdir)) == 0) nm += strlen(cfg->chrootdir); if(!anchor_read_bind_file_wild(anchors, parsebuf, nm)) { log_err("error reading trusted-keys-file: %s", f->str); sldns_buffer_free(parsebuf); return 0; } } for(f = cfg->trust_anchor_list; f; f = f->next) { if(!f->str || f->str[0] == 0) /* empty "" */ continue; if(!anchor_store_str(anchors, parsebuf, f->str)) { log_err("error in trust-anchor: \"%s\"", f->str); sldns_buffer_free(parsebuf); return 0; } } if(cfg->dlv_anchor_file && cfg->dlv_anchor_file[0] != 0) { struct trust_anchor* dlva; nm = cfg->dlv_anchor_file; if(cfg->chrootdir && cfg->chrootdir[0] && strncmp(nm, cfg->chrootdir, strlen(cfg->chrootdir)) == 0) nm += strlen(cfg->chrootdir); if(!(dlva = anchor_read_file(anchors, parsebuf, nm, 1))) { log_err("error reading dlv-anchor-file: %s", cfg->dlv_anchor_file); sldns_buffer_free(parsebuf); return 0; } lock_basic_lock(&anchors->lock); anchors->dlv_anchor = dlva; lock_basic_unlock(&anchors->lock); } for(f = cfg->dlv_anchor_list; f; f = f->next) { struct trust_anchor* dlva; if(!f->str || f->str[0] == 0) /* empty "" */ continue; if(!(dlva = anchor_store_str( anchors, parsebuf, f->str))) { log_err("error in dlv-anchor: \"%s\"", f->str); sldns_buffer_free(parsebuf); return 0; } lock_basic_lock(&anchors->lock); anchors->dlv_anchor = dlva; lock_basic_unlock(&anchors->lock); } /* do autr last, so that it sees what anchors are filled by other * means can can print errors about double config for the name */ for(f = cfg->auto_trust_anchor_file_list; f; f = f->next) { if(!f->str || f->str[0] == 0) /* empty "" */ continue; nm = f->str; if(cfg->chrootdir && cfg->chrootdir[0] && strncmp(nm, cfg->chrootdir, strlen(cfg->chrootdir)) == 0) nm += strlen(cfg->chrootdir); if(!autr_read_file(anchors, nm)) { log_err("error reading auto-trust-anchor-file: %s", f->str); sldns_buffer_free(parsebuf); return 0; } } /* first assemble, since it may delete useless anchors */ anchors_assemble_rrsets(anchors); init_parents(anchors); sldns_buffer_free(parsebuf); if(verbosity >= VERB_ALGO) autr_debug_print(anchors); return 1; }