From: Wouter Wijngaards Date: Thu, 28 Feb 2008 12:29:00 +0000 (+0000) Subject: + - fixed memory leaks in libunbound (during cancellation and wait). X-Git-Tag: release-0.10~12 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=2b95664a66edde8509dd841db41b9a8c66823c9c;p=thirdparty%2Funbound.git + - fixed memory leaks in libunbound (during cancellation and wait). + - libunbound returns the answer packet in full. + - snprintf compat update. + - harvest performs lookup. + - ldns-tarball update with fix for ldns_dname_label. git-svn-id: file:///svn/unbound/trunk@998 be551aaa-1e26-0410-a405-d3ace91eadb9 --- diff --git a/compat/snprintf.c b/compat/snprintf.c index 766c11930..72fb2eb94 100644 --- a/compat/snprintf.c +++ b/compat/snprintf.c @@ -528,7 +528,7 @@ static long double abs_val (long double value) return result; } -static long double pow10 (int exp) +static long double compat_pow10 (int exp) { long double result = 1; @@ -541,7 +541,7 @@ static long double pow10 (int exp) return result; } -static long round (long double value) +static long compat_round (long double value) { long intpart; @@ -602,12 +602,12 @@ static void fmtfp (char *buffer, size_t *currlen, size_t maxlen, /* We "cheat" by converting the fractional part to integer by * multiplying by a factor of 10 */ - fracpart = round ((pow10 (max)) * (ufvalue - intpart)); + fracpart = compat_round ((compat_pow10 (max)) * (ufvalue - intpart)); - if (fracpart >= pow10 (max)) + if (fracpart >= compat_pow10 (max)) { intpart++; - fracpart -= pow10 (max); + fracpart -= compat_pow10 (max); } #ifdef DEBUG_SNPRINTF diff --git a/configure b/configure index f1bd3c3f6..703e9d98d 100755 --- a/configure +++ b/configure @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.61 for unbound 1.0. +# Generated by GNU Autoconf 2.61 for unbound 0.10. # # Report bugs to . # @@ -724,8 +724,8 @@ SHELL=${CONFIG_SHELL-/bin/sh} # Identity of this package. PACKAGE_NAME='unbound' PACKAGE_TARNAME='unbound' -PACKAGE_VERSION='1.0' -PACKAGE_STRING='unbound 1.0' +PACKAGE_VERSION='0.10' +PACKAGE_STRING='unbound 0.10' PACKAGE_BUGREPORT='unbound-bugs@nlnetlabs.nl' # Factoring default headers for most tests. @@ -1359,7 +1359,7 @@ if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures unbound 1.0 to adapt to many kinds of systems. +\`configure' configures unbound 0.10 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1424,7 +1424,7 @@ fi if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of unbound 1.0:";; + short | recursive ) echo "Configuration of unbound 0.10:";; esac cat <<\_ACEOF @@ -1549,7 +1549,7 @@ fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -unbound configure 1.0 +unbound configure 0.10 generated by GNU Autoconf 2.61 Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, @@ -1563,7 +1563,7 @@ cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by unbound $as_me 1.0, which was +It was created by unbound $as_me 0.10, which was generated by GNU Autoconf 2.61. Invocation command line was $ $0 $@ @@ -25213,7 +25213,7 @@ exec 6>&1 # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by unbound $as_me 1.0, which was +This file was extended by unbound $as_me 0.10, which was generated by GNU Autoconf 2.61. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -25262,7 +25262,7 @@ Report bugs to ." _ACEOF cat >>$CONFIG_STATUS <<_ACEOF ac_cs_version="\\ -unbound config.status 1.0 +unbound config.status 0.10 configured by $0, generated by GNU Autoconf 2.61, with options \\"`echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\" diff --git a/configure.ac b/configure.ac index 264d8e91e..95a7ee480 100644 --- a/configure.ac +++ b/configure.ac @@ -2,7 +2,7 @@ # Process this file with autoconf to produce a configure script. AC_PREREQ(2.57) -AC_INIT(unbound, 1.0, unbound-bugs@nlnetlabs.nl, unbound) +AC_INIT(unbound, 0.10, unbound-bugs@nlnetlabs.nl, unbound) CFLAGS= AC_AIX diff --git a/doc/Changelog b/doc/Changelog index 003945675..2c913de05 100644 --- a/doc/Changelog +++ b/doc/Changelog @@ -1,3 +1,10 @@ +28 February 2008: Wouter + - fixed memory leaks in libunbound (during cancellation and wait). + - libunbound returns the answer packet in full. + - snprintf compat update. + - harvest performs lookup. + - ldns-tarball update with fix for ldns_dname_label. + 27 February 2008: Wouter - option to use caps for id randomness. - config file option use-caps-for-id: yes diff --git a/doc/libunbound.3 b/doc/libunbound.3 index 81e8de1ca..96fd854b0 100644 --- a/doc/libunbound.3 +++ b/doc/libunbound.3 @@ -303,6 +303,8 @@ The result of the DNS resolution and validation is returned as int* len; /* array with lengths of rdata items */ char* canonname; /* canonical name of result */ int rcode; /* additional error code in case of no data */ + void* answer_packet; /* full network format answer packet */ + int answer_len; /* length of packet in octets */ int havedata; /* true if there is data */ int nxdomain; /* true if nodata because name does not exist */ int secure; /* true if result is secure */ diff --git a/ldns-src.tar.gz b/ldns-src.tar.gz index 6eedacbdd..5debe05e5 100644 Binary files a/ldns-src.tar.gz and b/ldns-src.tar.gz differ diff --git a/libunbound/libunbound.c b/libunbound/libunbound.c index 0e7d70256..2280e4f7d 100644 --- a/libunbound/libunbound.c +++ b/libunbound/libunbound.c @@ -437,6 +437,9 @@ process_answer_detail(struct ub_ctx* ctx, uint8_t* msg, uint32_t len, libworker_enter_result(*res, buf, region, q->msg_security); } + (*res)->answer_packet = q->msg; + (*res)->answer_len = q->msg_len; + q->msg = NULL; ldns_buffer_free(buf); regional_destroy(region); } @@ -448,6 +451,7 @@ process_answer_detail(struct ub_ctx* ctx, uint8_t* msg, uint32_t len, lock_basic_unlock(&ctx->cfglock); if(*cb) return 2; + ub_resolve_free(*res); return 1; } @@ -537,6 +541,7 @@ ub_wait(struct ub_ctx* ctx) r = process_answer_detail(ctx, msg, len, &cb, &cbarg, &err, &res); lock_basic_unlock(&ctx->rrpipe_lock); + free(msg); if(r == 0) return UB_PIPE; if(r == 2) @@ -579,6 +584,9 @@ ub_resolve(struct ub_ctx* ctx, char* name, int rrtype, lock_basic_unlock(&ctx->cfglock); return r; } + q->res->answer_packet = q->msg; + q->res->answer_len = q->msg_len; + q->msg = NULL; *result = q->res; q->res = NULL; @@ -672,8 +680,8 @@ ub_cancel(struct ub_ctx* ctx, int async_id) if(!ctx->dothread) { /* if forked */ (void)rbtree_delete(&ctx->queries, q->node.key); ctx->num_async--; - context_query_delete(q); msg = context_serialize_cancel(q, &len); + context_query_delete(q); lock_basic_unlock(&ctx->cfglock); if(!msg) { return UB_NOMEM; @@ -706,6 +714,7 @@ ub_resolve_free(struct ub_result* result) free(*p); free(result->data); free(result->len); + free(result->answer_packet); free(result); } diff --git a/libunbound/libworker.c b/libunbound/libworker.c index 446071cff..a152b62af 100644 --- a/libunbound/libworker.c +++ b/libunbound/libworker.c @@ -935,14 +935,18 @@ libworker_read_msg(int fd, uint8_t** buf, uint32_t* len, int nonblock) if((r=read(fd, *buf, *len)) == -1) { log_err("msg read failed: %s", strerror(errno)); (void)fd_set_nonblock(fd); + free(*buf); return 0; } if(r == 0) { /* EOF */ (void)fd_set_nonblock(fd); + free(*buf); return 0; } - if(!fd_set_nonblock(fd)) + if(!fd_set_nonblock(fd)) { + free(*buf); return 0; + } return 1; } diff --git a/libunbound/unbound.h b/libunbound/unbound.h index 9ee32b9c0..8e52e47e8 100644 --- a/libunbound/unbound.h +++ b/libunbound/unbound.h @@ -139,6 +139,13 @@ struct ub_result { */ int rcode; + /** + * The DNS answer packet. Network formatted. Can contain DNSSEC types. + */ + void* answer_packet; + /** length of the answer packet in octets. */ + int answer_len; + /** * If there is any data, this is true. * If false, there was no data (nxdomain may be true, rcode can be set). diff --git a/testcode/asynclook.c b/testcode/asynclook.c index 4a5a61960..ae7466eb1 100644 --- a/testcode/asynclook.c +++ b/testcode/asynclook.c @@ -216,6 +216,16 @@ ext_check_result(const char* desc, int err, struct ub_result* result) "wrong.\n", desc); exit(1); } + if(result->answer_packet == NULL) { + printf("%s: error result->answer_packet is NULL.\n", + desc); + exit(1); + } + if(result->answer_len != 54) { + printf("%s: error result->answer_len is wrong.\n", + desc); + exit(1); + } } } @@ -288,6 +298,7 @@ ext_thread(void* arg) r = ub_resolve(inf->ctx, inf->argv[i%inf->argc], LDNS_RR_TYPE_A, LDNS_RR_CLASS_IN, &result); ext_check_result("ub_resolve", r, result); + ub_resolve_free(result); } } if(inf->thread_num > NUMTHR/2) { diff --git a/testcode/harvest.c b/testcode/harvest.c index 637af47c8..c80df6f34 100644 --- a/testcode/harvest.c +++ b/testcode/harvest.c @@ -232,6 +232,7 @@ lab_create(char* name) if(!lab) error_exit("out of memory"); lab->label = ldns_dname_new_frm_str(name); if(!lab->label) error_exit("out of memory"); + printf("labcount %d\n", ldns_dname_label_count(lab->label)); lab->name = ldns_dname_new_frm_str(name); if(!lab->name) error_exit("out of memory"); lab->node.key = lab->label; @@ -264,8 +265,12 @@ find_create_lab(struct harvest_data* data, ldns_rdf* name) /* create it */ nextlab = (struct labdata*)calloc(1, sizeof(*lab)); if(!nextlab) error_exit("out of memory"); + printf("nextcount %d len %d\n", + ldns_dname_label_count(next), + ldns_rdf_size(next)); nextlab->label = ldns_rdf_clone(next); if(!nextlab->label) error_exit("out of memory"); + printf("labcount %d\n", ldns_dname_label_count(nextlab->label)); nextlab->node.key = nextlab->label; nextlab->node.data = nextlab; nextlab->sublabels = ldns_rbtree_create(lab_cmp); @@ -342,6 +347,10 @@ new_todo_infra(struct harvest_data* data, struct todo_item* it) LDNS_RR_CLASS_IN, it->depth); new_todo_item(data, lab->name, LDNS_RR_TYPE_DS, LDNS_RR_CLASS_IN, it->depth); + new_todo_item(data, lab->name, LDNS_RR_TYPE_A, + LDNS_RR_CLASS_IN, it->depth); + new_todo_item(data, lab->name, LDNS_RR_TYPE_AAAA, + LDNS_RR_CLASS_IN, it->depth); lab->done = 1; } } @@ -359,10 +368,63 @@ make_todo(struct harvest_data* data) } } -/** get result and store it */ +/** store RR and make new work items for it if needed */ +static void +process_rr(struct harvest_data* data, ldns_rr* rr, int depth) +{ + /* must free or store rr */ + struct labdata* lab = find_create_lab(data, ldns_rr_owner(rr)); + if(!lab) error_exit("cannot find/create label"); + /* generate extra queries */ + if(ldns_rr_get_type(rr) == LDNS_RR_TYPE_NS) { + new_todo_item(data, ldns_rr_ns_nsdname(rr), LDNS_RR_TYPE_A, + LDNS_RR_CLASS_IN, depth+1); + new_todo_item(data, ldns_rr_ns_nsdname(rr), LDNS_RR_TYPE_AAAA, + LDNS_RR_CLASS_IN, depth+1); + } else if(ldns_rr_get_type(rr) == LDNS_RR_TYPE_MX) { + new_todo_item(data, ldns_rr_mx_exchange(rr), LDNS_RR_TYPE_A, + LDNS_RR_CLASS_IN, depth+1); + new_todo_item(data, ldns_rr_mx_exchange(rr), LDNS_RR_TYPE_AAAA, + LDNS_RR_CLASS_IN, depth+1); + } else if(ldns_rr_get_type(rr) == LDNS_RR_TYPE_SOA) { + new_todo_item(data, ldns_rr_rdf(rr, 0), LDNS_RR_TYPE_A, + LDNS_RR_CLASS_IN, depth+1); + new_todo_item(data, ldns_rr_rdf(rr, 0), LDNS_RR_TYPE_AAAA, + LDNS_RR_CLASS_IN, depth+1); + } + /* store it */ + if(!ldns_rr_list_contains_rr(lab->rrlist, rr)) { + if(hverb) printf("store RR\n"); + if(!ldns_rr_list_push_rr(lab->rrlist, rr)) + error_exit("outofmem ldns_rr_list_push_rr"); + } else { + if(hverb) printf("duplicate RR\n"); + ldns_rr_free(rr); + } +} + +/** store RRs and make new work items if needed */ +static void +process_pkt(struct harvest_data* data, ldns_pkt* pkt, int depth) +{ + size_t i; + ldns_rr_list* list; + list = ldns_pkt_get_section_clone(pkt, LDNS_SECTION_ANY_NOQUESTION); + if(!list) error_exit("outofmemory"); + for(i=0; iqname); @@ -377,11 +439,36 @@ process(struct harvest_data* data, struct todo_item* it) printf("\n"); } /* do lookup */ - + nm = ldns_rdf2str(it->qname); + if(!nm) error_exit("ldns_rdf2str"); + r = ub_resolve(data->ctx, nm, it->qtype, it->qclass, &result); + if(r != 0) { + printf("ub_resolve(%s, %d, %d): %s\n", nm, it->qtype, + it->qclass, ub_strerror(r)); + free(nm); + return; + } + /* even if result is a negative, try to store resulting SOA/NSEC */ /* create ldns pkt */ - /* create recursive todo items */ - /* store results */ + s = ldns_wire2pkt(&pkt, result->answer_packet, result->answer_len); + if(s != LDNS_STATUS_OK) { + printf("ldns_wire2pkt failed! %s %d %d %s", nm, + it->qtype, it->qclass, ldns_get_errorstr_by_id(s)); + free(nm); + return; + } + if(hverb >= 2) { + printf("answer: "); + ldns_pkt_print(stdout, pkt); + printf("\n"); + } + /* process results */ + process_pkt(data, pkt, it->depth); + + ldns_pkt_free(pkt); + free(nm); + ub_resolve_free(result); } /** perform main harvesting */ @@ -404,6 +491,7 @@ harvest_main(struct harvest_data* data) } data->numtodo--; process(data, it); + exit(1); } } @@ -417,11 +505,11 @@ int main(int argc, char* argv[]) { struct harvest_data data; char* nm = argv[0]; - struct ub_ctx* ctx = ub_ctx_create(); int c; /* defaults */ memset(&data, 0, sizeof(data)); + data.ctx = ub_ctx_create(); data.resultdir = strdup("harvested_zones"); if(!data.resultdir) error_exit("out of memory"); data.maxdepth = 10; @@ -451,6 +539,6 @@ int main(int argc, char* argv[]) harvest_main(&data); /* no cleanup except the context (to close open sockets) */ - ub_ctx_delete(ctx); + ub_ctx_delete(data.ctx); return 0; }