diff --git a/README.md b/README.md index 45caeefb..3726753a 100644 --- a/README.md +++ b/README.md @@ -50,8 +50,8 @@ External dependencies are linked outside the getdns API build tree (we rely on c * [libevent](http://libevent.org) version 2.0.21 stable Sometimes called libevent2 -* [libldns from NL](https://www.nlnetlabs.nl/projects/ldns/) version 1.6.16 (ldns may require openssl headers and libraries) -* [libunbound from NL](http://www.nlnetlabs.nl/projects/unbound/) svn revision 3012, configure must be run with the --with-libevent option (recommended to also use --with-libunbound-only). +* [libldns from NL](https://www.nlnetlabs.nl/projects/ldns/) version 1.6.17 (ldns requires openssl headers and libraries) +* [libunbound from NL](http://www.nlnetlabs.nl/projects/unbound/) svn revision 3069, configure must be run with the --with-libevent and the --enable-event-api option (recommended to also use --with-libunbound-only). * [libexpat](http://expat.sourceforge.net/) for libunbound. * [libidn from the FSF](http://www.gnu.org/software/libidn/) version 1. * Doxygen is used to generate documentation, while this is not technically necessary for the build it makes things a lot more pleasant. diff --git a/spec/getdns-0.379.tgz b/spec/getdns-0.379.tgz deleted file mode 100644 index 351c128e..00000000 Binary files a/spec/getdns-0.379.tgz and /dev/null differ diff --git a/spec/getdns-0.380.tgz b/spec/getdns-0.380.tgz new file mode 100644 index 00000000..0c70a3d7 Binary files /dev/null and b/spec/getdns-0.380.tgz differ diff --git a/spec/getdns_core_only.h b/spec/getdns_core_only.h index 87e57d08..70c417c7 100644 --- a/spec/getdns_core_only.h +++ b/spec/getdns_core_only.h @@ -1,4 +1,4 @@ -/* Created at 2014-01-22-10-48-59*/ +/* Created at 2014-02-03-16-52-47*/ #ifndef GETDNS_H #define GETDNS_H diff --git a/spec/index.html b/spec/index.html index 32fd5f16..e55de930 100644 --- a/spec/index.html +++ b/spec/index.html @@ -645,7 +645,7 @@ getdns_dict_destroy(this_extensions);
  • dnssec_return_only_secure
  • -
  • dnssec_return_supporting_responses
  • +
  • dnssec_return_validation_chain
  • return_both_v4_and_v6
  • @@ -692,15 +692,81 @@ are determined to be secure, the error code at the top level of the response obj GETDNS_RESPSTATUS_NO_SECURE_ANSWERS.

    Applications that want to do their own validation will want to have the DNSSEC-related records -for a particular response. Use the dnssec_return_supporting_responses extension. The +for a particular response. Use the dnssec_return_validation_chain extension. The extension's value (an int) is set to GETDNS_EXTENSION_TRUE to cause a set of additional DNSSEC-related records needed for validation to be returned in the response object. -This set comes as additional_dnssec (a list) at the top level of the response object. -This list includes any trust anchors needed for the validation. Thus, a reply might look like:

    +This set comes as validation_chain (a list) at the top level of the response object. +This list includes all resource record dicts for all the resource records (DS, DNSKEY and their RRSIGs) that are needed to perform the validation from the root up. Thus, a reply might look like:

     {     # This is the response object
    -  "additional_dnssec": [ <bindata of the first DNSSEC record>, <bindata of the second DNSSEC record> ... ],
    +  "validation_chain":
    +  [ { "name": ,
    +      "type": GETDNS_RRTYPE_DNSKEY,
    +      "rdata": { "flags": 256, . . . },
    +      . . . 
    +    },
    +    { "name": ,
    +      "type": GETDNS_RRTYPE_DNSKEY,
    +      "rdata": { "flags": 257, . . . },
    +      . . .
    +    },
    +    { "name": ,
    +      "type": GETDNS_RRTYPE_RRSIG,
    +      "rdata": { "signers_name": ,
    +                 "type_covered": GETDNS_RRTYPE_DNSKEY,
    +                 . . .
    +               },
    +    },
    +    { "name": ,
    +      "type": GETDNS_RRTYPE_DS,
    +      . . .
    +    },
    +    { "name": ,
    +      "type": GETDNS_RRTYPE_RRSIG
    +      "rdata": { "signers_name": ,
    +                 "type_covered": GETDNS_RRTYPE_DS,
    +                 . . .
    +               },
    +      . . .
    +    },
    +    { "name": ,
    +      "type": GETDNS_RRTYPE_DNSKEY
    +      "rdata": { "flags": 256, . . . },
    +      . . .
    +    },
    +    { "name": ,
    +      "type": GETDNS_RRTYPE_DNSKEY
    +      "rdata": { "flags": 257, . . . },
    +      . . .
    +    },
    +    { "name": ,
    +      "type": GETDNS_RRTYPE_RRSIG
    +      "rdata": { "signers_name": ,
    +                 "type_covered": GETDNS_RRTYPE_DNSKEY,
    +                 . . .
    +               },
    +      . . .
    +    },
    +    { "name": ,
    +      "type": GETDNS_RRTYPE_DS,
    +      . . .
    +    },
    +    { "name": ,
    +      "type": GETDNS_RRTYPE_RRSIG
    +      "rdata": { "signers_name": ,
    +                 "type_covered": GETDNS_RRTYPE_DS,
    +                 . . .
    +               },
    +      . . .
    +    },
    +    { "name": ,
    +      "type": GETDNS_RRTYPE_DNSKEY
    +      "rdata": { "flags": 257, ... },
    +      . . .
    +    },
    +    . . .
    +  ]
       "replies_tree":
       [
       . . .
    @@ -708,7 +774,7 @@ This list includes any trust anchors needed for the validation. Thus, a reply mi
     
     

    If a request is using a context in which stub resolution is set, and that request also has any of the dnssec_return_status, dnssec_return_only_secure, or -dnssec_return_supporting_responses extensions specified, the API will not perform +dnssec_return_validation_chain extensions specified, the API will not perform the request and will instead return an error of GETDNS_RETURN_DNSSEC_WITH_STUB_DISALLOWED.

    3.2 Returning Both IPv4 and IPv6 Responses

    @@ -2210,7 +2276,7 @@ The response dicts inherit the custom memory management functions and the value

    9. The Generated Files

    -

    There is a tarball that includes the .h files, +

    There is a tarball that includes the .h files, the examples, and so on. The examples all make, even though there is no API implementation, based on a pseudo-implementation in the tarball; see make-examples-PLATFORM.sh. Note that this currently builds fine on the Macintosh and Ubuntu; help is definitely appreciated on making the build process diff --git a/src/context.c b/src/context.c index 7b9e164e..842be909 100644 --- a/src/context.c +++ b/src/context.c @@ -3,7 +3,7 @@ * \file context.c * @brief getdns context management functions * - * Originally taken from the getdns API description pseudo implementation. + * Declarations taken from the getdns API description pseudo implementation. * */ @@ -189,6 +189,7 @@ create_from_ldns_list(struct getdns_context *context, ldns_rdf ** ldns_list, return result; } +/*---------------------------------------- set_os_defaults */ static getdns_return_t set_os_defaults(struct getdns_context *context) { @@ -210,8 +211,9 @@ set_os_defaults(struct getdns_context *context) } /** cleanup **/ ldns_resolver_deep_free(lr); + return GETDNS_RETURN_GOOD; -} +} /* set_os_defaults */ /* compare of transaction ids in DESCENDING order so that 0 comes last @@ -351,7 +353,7 @@ getdns_context_create_with_extended_memory_functions( GETDNS_CONTEXT_UDP_FIRST_AND_FALL_BACK_TO_TCP); return GETDNS_RETURN_GOOD; -} /* getdns_context_create */ +} /* getdns_context_create */ /* * getdns_context_create diff --git a/src/example/example-simple-answers.c b/src/example/example-simple-answers.c index e9d75608..a2a3b375 100644 --- a/src/example/example-simple-answers.c +++ b/src/example/example-simple-answers.c @@ -1,3 +1,39 @@ +/** + * + * \file example-simple-answers.c + * @brief example using getdns to resolve a simple query + * + * Originally taken from the getdns API description pseudo implementation. + * + */ + +/* + * Copyright (c) 2013, Versign, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL Verisign, Inc. BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + #include #include #include @@ -14,62 +50,118 @@ void this_callbackfn(struct getdns_context *this_context, void *this_userarg, getdns_transaction_t this_transaction_id) { - UNUSED_PARAM(this_userarg); /* Not looking at the userarg for this example */ - UNUSED_PARAM(this_context); /* Not looking at the context for this example */ - getdns_return_t this_ret; /* Holder for all function returns */ + getdns_return_t this_ret; + uint32_t this_error; + size_t num_addresses; + struct getdns_list *just_the_addresses_ptr; + struct getdns_dict *this_address; + struct getdns_bindata *this_address_data; + size_t rec_count; + char *this_address_str; + + UNUSED_PARAM(this_userarg); + UNUSED_PARAM(this_context); + if (this_callback_type == GETDNS_CALLBACK_COMPLETE) /* This is a callback with data */ { /* Be sure the search returned something */ - uint32_t this_error; - this_ret = getdns_dict_get_int(this_response, "status", &this_error); // Ignore any error - if (this_error != GETDNS_RESPSTATUS_GOOD) // If the search didn't return "good" + + this_ret = getdns_dict_get_int(this_response, "status", &this_error); + if (this_ret != GETDNS_RETURN_GOOD) + { + fprintf(stderr, "The dictionary does not contain \"status\" (this shouldn't have happened). Exiting\n"); + getdns_dict_destroy(this_response); + return; + } + + if (this_error != GETDNS_RESPSTATUS_GOOD) { fprintf(stderr, "The search had no results, and a return value of %d. Exiting.\n", this_error); getdns_dict_destroy(this_response); return; } - struct getdns_list * just_the_addresses_ptr; + this_ret = getdns_dict_get_list(this_response, "just_address_answers", &just_the_addresses_ptr); - if (this_ret != GETDNS_RETURN_GOOD) // This check is really not needed, but prevents a compiler error under "pedantic" + if (this_ret != GETDNS_RETURN_GOOD) { - fprintf(stderr, "Trying to get the answers failed: %d\n", this_ret); + fprintf(stderr, "The dict does not contain \"just_address_answers\" (this shouldn't have happened), and returned %d. Exiting.\n", this_ret); getdns_dict_destroy(this_response); return; } - size_t num_addresses; - this_ret = getdns_list_get_length(just_the_addresses_ptr, &num_addresses); // Ignore any error - /* Go through each record */ - for ( size_t rec_count = 0; rec_count < num_addresses; ++rec_count ) + + this_ret = getdns_list_get_length(just_the_addresses_ptr, &num_addresses); + if (this_ret != GETDNS_RETURN_GOOD) { - struct getdns_dict * this_address; - this_ret = getdns_list_get_dict(just_the_addresses_ptr, rec_count, &this_address); // Ignore any error + fprintf(stderr, "The address list is invalid (this shouldn't have happened). Exiting\n"); + getdns_dict_destroy(this_response); + return; + } + + if (num_addresses == 0) + fprintf(stderr, "The address list has 0 records. Exiting\n"); + + /* Go through each record */ + for (rec_count = 0; rec_count < num_addresses; ++rec_count) + { + this_ret = getdns_list_get_dict(just_the_addresses_ptr, rec_count, &this_address); + if(this_ret != GETDNS_RETURN_GOOD) + { + fprintf(stderr, "Record %d is invalid (this shouldn't have happened). skipping.\n", (int) rec_count); + continue; + } + /* Just print the address */ - struct getdns_bindata * this_address_data; - this_ret = getdns_dict_get_bindata(this_address, "address_data", &this_address_data); // Ignore any error - char *this_address_str = getdns_display_ip_address(this_address_data); - printf("The address is %s\n", this_address_str); - free(this_address_str); + this_ret = getdns_dict_get_bindata(this_address, "address_data", &this_address_data); + if(this_ret != GETDNS_RETURN_GOOD) + { + fprintf(stderr, "Record %d does not contain \"address_data\" (this shouldn't happen), skipping\n", (int) rec_count); + } + else + { + this_address_str = getdns_display_ip_address(this_address_data); + printf("The address is %s\n", this_address_str); + free(this_address_str); + } } } else if (this_callback_type == GETDNS_CALLBACK_CANCEL) fprintf(stderr, "The callback with ID %"PRIu64" was cancelled. Exiting.\n", this_transaction_id); else fprintf(stderr, "The callback got a callback_type of %d. Exiting.\n", this_callback_type); - getdns_dict_destroy(this_response); -} -int main() + getdns_dict_destroy(this_response); +} /* this_callbackfn */ + +/*---------------------------------------- main */ +int +main(int argc, char *argv[]) { - /* Create the DNS context for this call */ + char *this_name = "www.example.com"; + char *this_userarg = "somestring"; + int dispatch_return; + int exitval = EXIT_SUCCESS; struct getdns_context *this_context = NULL; - getdns_return_t context_create_return = getdns_context_create(&this_context, 1); + struct event_base *this_event_base; + getdns_return_t dns_request_return; + getdns_transaction_t this_transaction_id; + getdns_return_t context_create_return; + + if(argc > 1) + this_name = argv[1]; + + printf("resolving %s\n", this_name); + + /* Create the DNS context for this call, use OS configs such as resolv.conf */ + + context_create_return = getdns_context_create(&this_context, 1); if (context_create_return != GETDNS_RETURN_GOOD) { fprintf(stderr, "Trying to create the context failed: %d", context_create_return); return(GETDNS_RETURN_GENERIC_ERROR); } + /* Create an event base and put it in the context using the unknown function name */ - struct event_base *this_event_base; + this_event_base = event_base_new(); if (this_event_base == NULL) { @@ -77,32 +169,37 @@ int main() getdns_context_destroy(this_context); return(GETDNS_RETURN_GENERIC_ERROR); } - (void)getdns_extension_set_libevent_base(this_context, this_event_base); + getdns_extension_set_libevent_base(this_context, this_event_base); + /* Set up the getdns call */ - const char * this_name = "www.example.com"; - char* this_userarg = "somestring"; // Could add things here to help identify this call - getdns_transaction_t this_transaction_id = 0; + + this_transaction_id = 0; /* Make the call */ - getdns_return_t dns_request_return = getdns_address(this_context, this_name, + + dns_request_return = getdns_address(this_context, this_name, NULL, this_userarg, &this_transaction_id, this_callbackfn); if (dns_request_return == GETDNS_RETURN_BAD_DOMAIN_NAME) { fprintf(stderr, "A bad domain name was used: %s. Exiting.\n", this_name); - event_base_free(this_event_base); - getdns_context_destroy(this_context); - return(GETDNS_RETURN_GENERIC_ERROR); + exitval = GETDNS_RETURN_GENERIC_ERROR; } else { /* Call the event loop */ - int dispatch_return = event_base_dispatch(this_event_base); + + dispatch_return = event_base_dispatch(this_event_base); + UNUSED_PARAM(dispatch_return); // TODO: check the return value above } + /* Clean up */ + event_base_free(this_event_base); getdns_context_destroy(this_context); - /* Assuming we get here, leave gracefully */ - exit(EXIT_SUCCESS); -} + + return exitval; +} /* main */ + +/* example-simple-answers.c */ diff --git a/src/general.c b/src/general.c index be497431..f117edc4 100644 --- a/src/general.c +++ b/src/general.c @@ -48,9 +48,8 @@ /* declarations */ static void ub_resolve_callback(void* mydata, int err, struct ub_result* result); -// static void ub_resolve_timeout(evutil_socket_t fd, short what, void *arg); -// static void ub_local_resolve_timeout(evutil_socket_t fd, short what, -// void *arg); +static void ub_resolve_timeout(void *arg); +static void ub_local_resolve_timeout(void *arg); static void handle_network_request_error(getdns_network_req * netreq, int err); static void handle_dns_request_complete(getdns_dns_req * dns_req); @@ -60,9 +59,7 @@ typedef struct netreq_cb_data { getdns_network_req *netreq; int err; - ldns_buffer *result; - int sec; - char *bogus; + struct ub_result* ub_res; } netreq_cb_data; /* cancel, cleanup and send timeout to callback */ @@ -84,29 +81,26 @@ ub_resolve_timeout(void *arg) cb(context, GETDNS_CALLBACK_TIMEOUT, NULL, user_arg, trans_id); } -// static void -// ub_local_resolve_timeout(evutil_socket_t fd, short what, void *arg) -// { -// netreq_cb_data *cb_data = (netreq_cb_data *) arg; +static void +ub_local_resolve_timeout(void *arg) +{ + netreq_cb_data *cb_data = (netreq_cb_data *) arg; -// /* cleanup the local timer here since the memory may be -// * invalid after calling ub_resolve_callback -// */ -// getdns_dns_req *dnsreq = cb_data->netreq->owner; -// event_free(dnsreq->local_cb_timer); -// dnsreq->local_cb_timer = NULL; + /* cleanup the local timer here since the memory may be + * invalid after calling ub_resolve_callback + */ + getdns_dns_req *dnsreq = cb_data->netreq->owner; + /* clear the timeout */ -// /* just call ub_resolve_callback */ -// ub_resolve_callback(cb_data->netreq, cb_data->err, cb_data->result, -// cb_data->sec, cb_data->bogus); + getdns_context_clear_timeout(dnsreq->context, dnsreq->local_timeout_id); + dnsreq->local_timeout_id = 0; -// /* cleanup the state */ -// ldns_buffer_free(cb_data->result); -// if (cb_data->bogus) { -// free(cb_data->bogus); -// } -// free(cb_data); -// } + /* just call ub_resolve_callback */ + ub_resolve_callback(cb_data->netreq, cb_data->err, cb_data->ub_res); + + /* cleanup the state */ + free(cb_data); +} static void call_user_callback(getdns_dns_req *dns_req, struct getdns_dict *response) @@ -212,6 +206,7 @@ ub_supporting_callback(void* arg, int err, struct ub_result* ub_res) ldns_rr_list_free(keys); ldns_pkt_free(p); + ub_resolve_free(ub_res); done: if (response->err == 0 && response->result == NULL) response->err = -1; @@ -247,19 +242,22 @@ static void submit_link(struct validation_chain *chain, char *name) link->DS.unbound_id = -1; ldns_rbtree_insert(&(chain->root), (ldns_rbnode_t *)link); - /* fprintf(stderr, "submitting for: %s\n", name); */ + chain->todo++; r = ub_resolve_async(chain->dns_req->context->unbound_ctx, - name, LDNS_RR_TYPE_DNSKEY, LDNS_RR_CLASS_IN, &link->DNSKEY, - ub_supporting_callback, &link->DNSKEY.unbound_id); - if (r != 0) - link->DNSKEY.err = r; + name, LDNS_RR_TYPE_DNSKEY, LDNS_RR_CLASS_IN, &link->DNSKEY, + ub_supporting_callback, &link->DNSKEY.unbound_id); + if (r != 0) + link->DNSKEY.err = r; - r = ub_resolve_async(chain->dns_req->context->unbound_ctx, - name, LDNS_RR_TYPE_DS, LDNS_RR_CLASS_IN, &link->DS, - ub_supporting_callback, &link->DS.unbound_id); - if (r != 0) - link->DS.err = r; + if (name[0] != '.' || name[1] != '\0') { + r = ub_resolve_async(chain->dns_req->context->unbound_ctx, + name, LDNS_RR_TYPE_DS, LDNS_RR_CLASS_IN, &link->DS, + ub_supporting_callback, &link->DS.unbound_id); + if (r != 0) + link->DS.err = r; + } + chain->todo--; } void destroy_chain_link(ldns_rbnode_t * node, void *arg) @@ -299,7 +297,6 @@ static void callback_on_complete_chain(struct validation_chain *chain) ((const char *)link->node.key)[1] != '\0' )) todo++; } - /* fprintf(stderr, "todo until validation: %d\n", (int)todo); */ if (todo == 0) { getdns_dns_req *dns_req = chain->dns_req; response = create_getdns_response(chain->dns_req); @@ -334,7 +331,7 @@ static void get_validation_chain(getdns_dns_req *dns_req) chain->mf.mf.ext.realloc = dns_req->context->mf.mf.ext.realloc; chain->mf.mf.ext.free = dns_req->context->mf.mf.ext.free; chain->dns_req = dns_req; - chain->todo = 1; + chain->todo = 0; while (netreq) { size_t i; @@ -347,7 +344,6 @@ static void get_validation_chain(getdns_dns_req *dns_req) } netreq = netreq->next; } - chain->todo--; callback_on_complete_chain(chain); } @@ -396,39 +392,21 @@ ub_resolve_callback(void* arg, int err, struct ub_result* ub_res) * This most likely means that getdns_general has not returned */ if (netreq->state == NET_REQ_NOT_SENT) { - /* TODO!!!! */ /* just do a very short timer since this was called immediately. * we can make this less hacky, but it gets interesting when multiple * netreqs need to be issued and some resolve immediately vs. not. */ - // struct timeval tv; - // getdns_dns_req *dnsreq = netreq->owner; - // netreq_cb_data *cb_data = - // (netreq_cb_data *) malloc(sizeof(netreq_cb_data)); + getdns_dns_req *dnsreq = netreq->owner; + netreq_cb_data *cb_data = + (netreq_cb_data *) malloc(sizeof(netreq_cb_data)); + cb_data->netreq = netreq; + cb_data->err = err; + cb_data->ub_res = ub_res; - // cb_data->netreq = netreq; - // cb_data->err = err; - // cb_data->sec = sec; - // cb_data->result = NULL; - // cb_data->bogus = NULL; /* unused but here in case we need it */ - // if (result) { - // cb_data->result = - // ldns_buffer_new(ldns_buffer_limit(result)); - // if (!cb_data->result) { - // cb_data->err = GETDNS_RETURN_GENERIC_ERROR; - // } else { - // /* copy */ - // ldns_buffer_copy(cb_data->result, result); - // } - // } - // /* schedule the timeout */ - // dnsreq->local_cb_timer = - // evtimer_new(dnsreq->ev_base, ub_local_resolve_timeout, - // cb_data); - // tv.tv_sec = 0; - // /* half ms */ - // tv.tv_usec = 500; - // evtimer_add(dnsreq->local_cb_timer, &tv); + dnsreq->local_timeout_id = ldns_get_random(); + + getdns_context_schedule_timeout(dnsreq->context, + dnsreq->local_timeout_id, 1, ub_local_resolve_timeout, cb_data); return; } netreq->state = NET_REQ_FINISHED; diff --git a/src/request-internal.c b/src/request-internal.c index ea88ba45..3ad976f3 100644 --- a/src/request-internal.c +++ b/src/request-internal.c @@ -96,6 +96,10 @@ dns_req_free(getdns_dns_req * req) net_req = next; } + if (req->local_timeout_id != 0) { + getdns_context_clear_timeout(context, req->local_timeout_id); + } + getdns_context_clear_timeout(context, req->trans_id); /* free strduped name */ @@ -132,6 +136,7 @@ dns_req_new(struct getdns_context *context, /* will be set by caller */ result->user_pointer = NULL; result->user_callback = NULL; + result->local_timeout_id = 0; /* create the requests */ req = network_req_new(result, diff --git a/src/test/check_getdns.c b/src/test/check_getdns.c index 6d8703d3..62d980e7 100644 --- a/src/test/check_getdns.c +++ b/src/test/check_getdns.c @@ -10,11 +10,13 @@ #include "check_getdns_common.h" #include "check_getdns_general.h" #include "check_getdns_general_sync.h" +#include "check_getdns_address.h" +#include "check_getdns_address_sync.h" +#include "check_getdns_hostname.h" +#include "check_getdns_hostname_sync.h" #include "check_getdns_context_create.h" #include "check_getdns_context_destroy.h" #include "check_getdns_cancel_callback.h" -#include "check_getdns_address.h" -#include "check_getdns_address_sync.h" #include "check_getdns_list_get_length.h" #include "check_getdns_list_get_data_type.h" #include "check_getdns_list_get_dict.h" @@ -52,6 +54,8 @@ main (int argc, char** argv) Suite *getdns_general_sync_suite(void); Suite *getdns_address_suite(void); Suite *getdns_address_sync_suite(void); + Suite *getdns_hostname_suite(void); + Suite *getdns_hostname_sync_suite(void); Suite *getdns_context_create_suite(void); Suite *getdns_context_destroy_suite(void); Suite *getdns_cancel_callback_suite(void); @@ -83,6 +87,8 @@ main (int argc, char** argv) srunner_add_suite(sr, getdns_general_sync_suite()); srunner_add_suite(sr, getdns_address_suite()); srunner_add_suite(sr, getdns_address_sync_suite()); + srunner_add_suite(sr, getdns_hostname_suite()); + srunner_add_suite(sr, getdns_hostname_sync_suite()); srunner_add_suite(sr, getdns_context_create_suite()); srunner_add_suite(sr, getdns_context_destroy_suite()); srunner_add_suite(sr, getdns_cancel_callback_suite()); diff --git a/src/test/check_getdns_hostname.h b/src/test/check_getdns_hostname.h new file mode 100644 index 00000000..bf496049 --- /dev/null +++ b/src/test/check_getdns_hostname.h @@ -0,0 +1,480 @@ +#ifndef _check_getdns_hostname_h_ +#define _check_getdns_hostname_h_ + + /* + ************************************************************************** + * * + * T E S T S F O R G E T D N S _ H O S T N A M E * + * * + ************************************************************************** + */ + + START_TEST (getdns_hostname_1) + { + /* + * context = NULL + * expect: GETDNS_RETURN_BAD_CONTEXT + */ + struct getdns_context *context = NULL; + struct getdns_dict *address = NULL; + struct getdns_bindata address_type = { 5, (void *)"IPv4" }; + struct getdns_bindata address_data = { 4, (void *)"\x08\x08\x08\x08" }; + getdns_transaction_t transaction_id = 0; + + DICT_CREATE(address); + ASSERT_RC(getdns_dict_set_bindata(address, "address_type", &address_type), + GETDNS_RETURN_GOOD, "Return code from getdns_dict_set_bindata()"); + ASSERT_RC(getdns_dict_set_bindata(address, "address_data", &address_data), + GETDNS_RETURN_GOOD, "Return code from getdns_dict_set_bindata()"); + + ASSERT_RC(getdns_hostname(context, address, NULL, + NULL, &transaction_id, callbackfn), + GETDNS_RETURN_BAD_CONTEXT, "Return code from getdns_hostname()"); + + DICT_DESTROY(address); + } + END_TEST + + START_TEST (getdns_hostname_2) + { + /* + * address = NULL + * expect: GETDNS_RETURN_INVALID_PARAMETER + */ + struct getdns_context *context = NULL; + struct event_base *event_base = NULL; + getdns_transaction_t transaction_id = 0; + + CONTEXT_CREATE(TRUE); + EVENT_BASE_CREATE; + + ASSERT_RC(getdns_hostname(context, NULL, NULL, + NULL, &transaction_id, callbackfn), + GETDNS_RETURN_INVALID_PARAMETER, "Return code from getdns_hostname()"); + + RUN_EVENT_LOOP; + CONTEXT_DESTROY; + } + END_TEST + + START_TEST (getdns_hostname_3) + { + /* + * dict in address does not contain getdns_bindata + * expect: GETDNS_RETURN_NO_SUCH_DICT_NAME + */ + struct getdns_context *context = NULL; + struct getdns_dict *address = NULL; + struct event_base *event_base = NULL; + getdns_transaction_t transaction_id = 0; + + CONTEXT_CREATE(TRUE); + DICT_CREATE(address); + EVENT_BASE_CREATE; + + ASSERT_RC(getdns_hostname(context, address, NULL, + NULL, &transaction_id, callbackfn), + GETDNS_RETURN_NO_SUCH_DICT_NAME, "Return code from getdns_hostname()"); + + RUN_EVENT_LOOP; + DICT_DESTROY(address); + CONTEXT_DESTROY; + } + END_TEST + + START_TEST (getdns_hostname_4) + { + /* + * dict in address does not contain two names + * expect: GETDNS_RETURN_NO_SUCH_DICT_NAME + */ + struct getdns_context *context = NULL; + struct getdns_dict *address = NULL; + struct getdns_bindata address_type = { 5, (void *) "IPv4" }; + struct event_base *event_base = NULL; + getdns_transaction_t transaction_id = 0; + + CONTEXT_CREATE(TRUE); + + DICT_CREATE(address); + ASSERT_RC(getdns_dict_set_bindata(address, "address_type", &address_type), + GETDNS_RETURN_GOOD, "Return code from getdns_dict_set_bindata()"); + + EVENT_BASE_CREATE; + + ASSERT_RC(getdns_hostname(context, address, NULL, + NULL, &transaction_id, callbackfn), + GETDNS_RETURN_NO_SUCH_DICT_NAME, "Return code from getdns_hostname()"); + + RUN_EVENT_LOOP; + + DICT_DESTROY(address); + CONTEXT_DESTROY; + } + END_TEST + + START_TEST (getdns_hostname_5) + { + /* + * dict in address contains names other than adddress_type + * and address_data. + * expect: GETDNS_RETURN_NO_SUCH_DICT_NAME + */ + struct getdns_context *context = NULL; + struct getdns_dict *address = NULL; + struct getdns_bindata address_data = { 4, (void *)"\x08\x08\x08\x08" }; + struct event_base *event_base = NULL; + getdns_transaction_t transaction_id = 0; + + CONTEXT_CREATE(TRUE); + + DICT_CREATE(address); + ASSERT_RC(getdns_dict_set_int(address, "not_address_type", 100), + GETDNS_RETURN_GOOD, "Return code from getdns_dict_set_int()"); + ASSERT_RC(getdns_dict_set_bindata(address, "not_address_data", &address_data), + GETDNS_RETURN_GOOD, "Return code from getdns_dict_set_bindata()"); + + EVENT_BASE_CREATE; + + ASSERT_RC(getdns_hostname(context, address, NULL, + NULL, &transaction_id, callbackfn), + GETDNS_RETURN_NO_SUCH_DICT_NAME, "Return code from getdns_hostname()"); + + RUN_EVENT_LOOP; + + DICT_DESTROY(address); + CONTEXT_DESTROY; + } + END_TEST + + START_TEST (getdns_hostname_6) + { + /* + * dict in address contains names address_type + * and address_data but data type is not bindata + * expect: GETDNS_RETURN_WRONG_TYPE_REQUESTED + */ + struct getdns_context *context = NULL; + struct getdns_dict *address = NULL; + struct event_base *event_base = NULL; + getdns_transaction_t transaction_id = 0; + + CONTEXT_CREATE(TRUE); + + DICT_CREATE(address); + ASSERT_RC(getdns_dict_set_int(address, "address_type", 100), + GETDNS_RETURN_GOOD, "Return code from getdns_dict_set_int()"); + ASSERT_RC(getdns_dict_set_int(address, "address_data", 200), + GETDNS_RETURN_GOOD, "Return code from getdns_dict_set_int()"); + + EVENT_BASE_CREATE; + + ASSERT_RC(getdns_hostname(context, address, NULL, + NULL, &transaction_id, callbackfn), + GETDNS_RETURN_WRONG_TYPE_REQUESTED, "Return code from getdns_hostname()"); + + RUN_EVENT_LOOP; + + DICT_DESTROY(address); + CONTEXT_DESTROY; + } + END_TEST + + START_TEST (getdns_hostname_7) + { + /* + * dict in address contains invalid address_type + * expect: GETDNS_RETURN_GENERIC_ERROR + */ + struct getdns_context *context = NULL; + struct getdns_dict *address = NULL; + struct getdns_bindata address_type = { 5, (void *)"IPv5" }; + struct getdns_bindata address_data = { 4, (void *)"\x08\x08\x08\x08" }; + struct event_base *event_base = NULL; + getdns_transaction_t transaction_id = 0; + + CONTEXT_CREATE(TRUE); + + DICT_CREATE(address); + ASSERT_RC(getdns_dict_set_bindata(address, "address_type", &address_type), + GETDNS_RETURN_GOOD, "Return code from getdns_dict_set_bindata()"); + ASSERT_RC(getdns_dict_set_bindata(address, "address_data", &address_data), + GETDNS_RETURN_GOOD, "Return code from getdns_dict_set_bindata()"); + + EVENT_BASE_CREATE; + + ASSERT_RC(getdns_hostname(context, address, NULL, + NULL, &transaction_id, callbackfn), + GETDNS_RETURN_GENERIC_ERROR, "Return code from getdns_hostname()"); + + RUN_EVENT_LOOP; + + DICT_DESTROY(address); + CONTEXT_DESTROY; + } + END_TEST + + START_TEST (getdns_hostname_8) + { + /* + * dict in address contains invalid address_data + * expect: GETDNS_RETURN_GENERIC_ERROR + */ + struct getdns_context *context = NULL; + struct getdns_dict *address = NULL; + struct getdns_bindata address_type = { 5, (void *)"IPv4" }; + struct getdns_bindata address_data = { 5, (void *)"\x08\x08\x08\x08\x08" }; + struct event_base *event_base = NULL; + getdns_transaction_t transaction_id = 0; + + CONTEXT_CREATE(TRUE); + + DICT_CREATE(address); + ASSERT_RC(getdns_dict_set_bindata(address, "address_type", &address_type), + GETDNS_RETURN_GOOD, "Return code from getdns_dict_set_bindata()"); + ASSERT_RC(getdns_dict_set_bindata(address, "address_data", &address_data), + GETDNS_RETURN_GOOD, "Return code from getdns_dict_set_bindata()"); + + EVENT_BASE_CREATE; + + ASSERT_RC(getdns_hostname(context, address, NULL, + NULL, &transaction_id, callbackfn), + GETDNS_RETURN_GENERIC_ERROR, "Return code from getdns_hostname()"); + + RUN_EVENT_LOOP; + + DICT_DESTROY(address); + CONTEXT_DESTROY; + } + END_TEST + + START_TEST (getdns_hostname_9) + { + /* + * callbackfn = NULL + * expect: GETDNS_RETURN_INVALID_PARAMETER + */ + struct getdns_context *context = NULL; + struct getdns_dict *address = NULL; + struct getdns_bindata address_type = { 5, (void *)"IPv4" }; + struct getdns_bindata address_data = { 4, (void *)"\x08\x08\x08\x08" }; + struct event_base *event_base = NULL; + getdns_transaction_t transaction_id = 0; + + CONTEXT_CREATE(TRUE); + + DICT_CREATE(address); + ASSERT_RC(getdns_dict_set_bindata(address, "address_type", &address_type), + GETDNS_RETURN_GOOD, "Return code from getdns_dict_set_bindata()"); + ASSERT_RC(getdns_dict_set_bindata(address, "address_data", &address_data), + GETDNS_RETURN_GOOD, "Return code from getdns_dict_set_bindata()"); + + EVENT_BASE_CREATE; + + ASSERT_RC(getdns_hostname(context, address, NULL, + NULL, &transaction_id, NULL), + GETDNS_RETURN_INVALID_PARAMETER, "Return code from getdns_hostname()"); + + RUN_EVENT_LOOP; + + DICT_DESTROY(address); + CONTEXT_DESTROY; + } + END_TEST + + START_TEST (getdns_hostname_10) + { + /* + * dict in address has resolvable IPv4 address + * expect: response with correct hostname + */ + void verify_getdns_hostname_10(struct extracted_response *ex_response); + struct getdns_context *context = NULL; + struct getdns_dict *address = NULL; + struct getdns_bindata address_type = { 5, (void *)"IPv4" }; + struct getdns_bindata address_data = { 4, (void *)"\x08\x08\x08\x08" }; + struct event_base *event_base = NULL; + getdns_transaction_t transaction_id = 0; + + CONTEXT_CREATE(TRUE); + + DICT_CREATE(address); + ASSERT_RC(getdns_dict_set_bindata(address, "address_type", &address_type), + GETDNS_RETURN_GOOD, "Return code from getdns_dict_set_bindata()"); + ASSERT_RC(getdns_dict_set_bindata(address, "address_data", &address_data), + GETDNS_RETURN_GOOD, "Return code from getdns_dict_set_bindata()"); + + EVENT_BASE_CREATE; + + ASSERT_RC(getdns_hostname(context, address, NULL, + verify_getdns_hostname_10, &transaction_id, callbackfn), + GETDNS_RETURN_GOOD, "Return code from getdns_hostname()"); + + RUN_EVENT_LOOP; + + DICT_DESTROY(address); + CONTEXT_DESTROY; + } + END_TEST + + void verify_getdns_hostname_10(struct extracted_response *ex_response) + { + assert_noerror(ex_response); + assert_ptr_in_answer(ex_response); + } + + START_TEST (getdns_hostname_11) + { + /* + * dict in address has unresolvable IPv4 address + * expect: response with no hostname + */ + void verify_getdns_hostname_11(struct extracted_response *ex_response); + struct getdns_context *context = NULL; + struct getdns_dict *address = NULL; + struct getdns_bindata address_type = { 5, (void *)"IPv4" }; + struct getdns_bindata address_data = { 4, (void *)"\x01\x01\x01\x01" }; + struct event_base *event_base = NULL; + getdns_transaction_t transaction_id = 0; + + CONTEXT_CREATE(TRUE); + + DICT_CREATE(address); + ASSERT_RC(getdns_dict_set_bindata(address, "address_type", &address_type), + GETDNS_RETURN_GOOD, "Return code from getdns_dict_set_bindata()"); + ASSERT_RC(getdns_dict_set_bindata(address, "address_data", &address_data), + GETDNS_RETURN_GOOD, "Return code from getdns_dict_set_bindata()"); + + EVENT_BASE_CREATE; + + ASSERT_RC(getdns_hostname(context, address, NULL, + verify_getdns_hostname_11, &transaction_id, callbackfn), + GETDNS_RETURN_GOOD, "Return code from getdns_hostname()"); + + RUN_EVENT_LOOP; + + DICT_DESTROY(address); + CONTEXT_DESTROY; + } + END_TEST + + void verify_getdns_hostname_11(struct extracted_response *ex_response) + { + assert_nxdomain(ex_response); + assert_nodata(ex_response); + assert_soa_in_authority(ex_response); + } + + START_TEST (getdns_hostname_12) + { + /* + * dict in address has resolvable IPv6 address + * expect: response with correct hostname + */ + void verify_getdns_hostname_12(struct extracted_response *ex_response); + struct getdns_context *context = NULL; + struct getdns_dict *address = NULL; + struct getdns_bindata address_type = { 5, (void *)"IPv6" }; + struct getdns_bindata address_data = { 16, (void *)"\x26\x07\xf8\xb0\x40\x06\x08\x02\x00\x00\x00\x00\x00\x00\x10\x04" }; + struct event_base *event_base = NULL; + getdns_transaction_t transaction_id = 0; + + CONTEXT_CREATE(TRUE); + + DICT_CREATE(address); + ASSERT_RC(getdns_dict_set_bindata(address, "address_type", &address_type), + GETDNS_RETURN_GOOD, "Return code from getdns_dict_set_bindata()"); + ASSERT_RC(getdns_dict_set_bindata(address, "address_data", &address_data), + GETDNS_RETURN_GOOD, "Return code from getdns_dict_set_bindata()"); + + EVENT_BASE_CREATE; + + ASSERT_RC(getdns_hostname(context, address, NULL, + verify_getdns_hostname_12, &transaction_id, callbackfn), + GETDNS_RETURN_GOOD, "Return code from getdns_hostname()"); + + RUN_EVENT_LOOP; + + DICT_DESTROY(address); + CONTEXT_DESTROY; + } + END_TEST + + void verify_getdns_hostname_12(struct extracted_response *ex_response) + { + assert_noerror(ex_response); + assert_ptr_in_answer(ex_response); + } + + START_TEST (getdns_hostname_13) + { + /* + * dict in address has unresolvable IPv4 address + * expect: response with no hostname + */ + void verify_getdns_hostname_13(struct extracted_response *ex_response); + struct getdns_context *context = NULL; + struct getdns_dict *address = NULL; + struct getdns_bindata address_type = { 5, (void *)"IPv6" }; + struct getdns_bindata address_data = { 16, (void *)"\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" }; + struct event_base *event_base = NULL; + getdns_transaction_t transaction_id = 0; + + CONTEXT_CREATE(TRUE); + + DICT_CREATE(address); + ASSERT_RC(getdns_dict_set_bindata(address, "address_type", &address_type), + GETDNS_RETURN_GOOD, "Return code from getdns_dict_set_bindata()"); + ASSERT_RC(getdns_dict_set_bindata(address, "address_data", &address_data), + GETDNS_RETURN_GOOD, "Return code from getdns_dict_set_bindata()"); + + EVENT_BASE_CREATE; + + ASSERT_RC(getdns_hostname(context, address, NULL, + verify_getdns_hostname_13, &transaction_id, callbackfn), + GETDNS_RETURN_GOOD, "Return code from getdns_hostname()"); + + RUN_EVENT_LOOP; + + DICT_DESTROY(address); + CONTEXT_DESTROY; + } + END_TEST + + void verify_getdns_hostname_13(struct extracted_response *ex_response) + { + assert_nxdomain(ex_response); + assert_nodata(ex_response); + assert_soa_in_authority(ex_response); + } + + Suite * + getdns_hostname_suite (void) + { + Suite *s = suite_create ("getdns_hostname()"); + + /* Negative test caseis */ + TCase *tc_neg = tcase_create("Negative"); + tcase_add_test(tc_neg, getdns_hostname_1); + tcase_add_test(tc_neg, getdns_hostname_2); + tcase_add_test(tc_neg, getdns_hostname_3); + tcase_add_test(tc_neg, getdns_hostname_4); + tcase_add_test(tc_neg, getdns_hostname_5); + tcase_add_test(tc_neg, getdns_hostname_6); + tcase_add_test(tc_neg, getdns_hostname_7); + tcase_add_test(tc_neg, getdns_hostname_8); + tcase_add_test(tc_neg, getdns_hostname_9); + suite_add_tcase(s, tc_neg); + + /* Positive test cases */ + TCase *tc_pos = tcase_create("Positive"); + tcase_add_test(tc_pos, getdns_hostname_10); + tcase_add_test(tc_pos, getdns_hostname_11); + tcase_add_test(tc_pos, getdns_hostname_12); + tcase_add_test(tc_pos, getdns_hostname_13); + suite_add_tcase(s, tc_pos); + + return s; + } + +#endif diff --git a/src/test/check_getdns_hostname_sync.h b/src/test/check_getdns_hostname_sync.h new file mode 100644 index 00000000..c984987f --- /dev/null +++ b/src/test/check_getdns_hostname_sync.h @@ -0,0 +1,402 @@ +#ifndef _check_getdns_hostname_sync_h_ +#define _check_getdns_hostname_sync_h_ + + /* + ************************************************************************** + * * + * T E S T S F O R G E T D N S _ H O S T N A M E _ S Y N C * + * * + ************************************************************************** + */ + + START_TEST (getdns_hostname_sync_1) + { + /* + * context = NULL + * expect: GETDNS_RETURN_BAD_CONTEXT + */ + struct getdns_context *context = NULL; + struct getdns_dict *address = NULL; + struct getdns_bindata address_type = { 5, (void *)"IPv4" }; + struct getdns_bindata address_data = { 4, (void *)"\x08\x08\x08\x08" }; + struct getdns_dict *response = NULL; + + DICT_CREATE(address); + ASSERT_RC(getdns_dict_set_bindata(address, "address_type", &address_type), + GETDNS_RETURN_GOOD, "Return code from getdns_dict_set_bindata()"); + ASSERT_RC(getdns_dict_set_bindata(address, "address_data", &address_data), + GETDNS_RETURN_GOOD, "Return code from getdns_dict_set_bindata()"); + + ASSERT_RC(getdns_hostname_sync(context, address, NULL, &response), + GETDNS_RETURN_BAD_CONTEXT, "Return code from getdns_hostname_sync()"); + + DICT_DESTROY(address); + } + END_TEST + + START_TEST (getdns_hostname_sync_2) + { + /* + * address = NULL + * expect: GETDNS_RETURN_INVALID_PARAMETER + */ + struct getdns_context *context = NULL; + struct getdns_dict *response = NULL; + + CONTEXT_CREATE(TRUE); + + ASSERT_RC(getdns_hostname_sync(context, NULL, NULL, &response), + GETDNS_RETURN_INVALID_PARAMETER, "Return code from getdns_hostname_sync()"); + + CONTEXT_DESTROY; + } + END_TEST + + START_TEST (getdns_hostname_sync_3) + { + /* + * response = NULL + * expect: GETDNS_RETURN_INVALID_PARAMETER + */ + struct getdns_context *context = NULL; + struct getdns_dict *address = NULL; + struct getdns_bindata address_type = { 5, (void *)"IPv4" }; + struct getdns_bindata address_data = { 4, (void *)"\x08\x08\x08\x08" }; + + CONTEXT_CREATE(TRUE); + + DICT_CREATE(address); + ASSERT_RC(getdns_dict_set_bindata(address, "address_type", &address_type), + GETDNS_RETURN_GOOD, "Return code from getdns_dict_set_bindata()"); + ASSERT_RC(getdns_dict_set_bindata(address, "address_data", &address_data), + GETDNS_RETURN_GOOD, "Return code from getdns_dict_set_bindata()"); + + ASSERT_RC(getdns_hostname_sync(context, address, NULL, NULL), + GETDNS_RETURN_INVALID_PARAMETER, "Return code from getdns_hostname_sync()"); + + DICT_DESTROY(address); + CONTEXT_DESTROY; + } + END_TEST + + START_TEST (getdns_hostname_sync_4) + { + /* + * dict in address does not contain getdns_bindata + * expect: GETDNS_RETURN_NO_SUCH_DICT_NAME + */ + struct getdns_context *context = NULL; + struct getdns_dict *address = NULL; + struct getdns_dict *response = NULL; + + CONTEXT_CREATE(TRUE); + DICT_CREATE(address); + + ASSERT_RC(getdns_hostname_sync(context, address, NULL, &response), + GETDNS_RETURN_NO_SUCH_DICT_NAME, "Return code from getdns_hostname_sync()"); + + DICT_DESTROY(address); + CONTEXT_DESTROY; + } + END_TEST + + START_TEST (getdns_hostname_sync_5) + { + /* + * dict in address does not contain two names + * expect: GETDNS_RETURN_NO_SUCH_DICT_NAME + */ + struct getdns_context *context = NULL; + struct getdns_dict *address = NULL; + struct getdns_bindata address_type = { 5, (void *) "IPv4" }; + struct getdns_dict *response = NULL; + + CONTEXT_CREATE(TRUE); + + DICT_CREATE(address); + ASSERT_RC(getdns_dict_set_bindata(address, "address_type", &address_type), + GETDNS_RETURN_GOOD, "Return code from getdns_dict_set_bindata()"); + + ASSERT_RC(getdns_hostname_sync(context, address, NULL, &response), + GETDNS_RETURN_NO_SUCH_DICT_NAME, "Return code from getdns_hostname_sync()"); + + DICT_DESTROY(address); + CONTEXT_DESTROY; + } + END_TEST + + START_TEST (getdns_hostname_sync_6) + { + /* + * dict in address contains names other than adddress_type + * and address_data. + * expect: GETDNS_RETURN_NO_SUCH_DICT_NAME + */ + struct getdns_context *context = NULL; + struct getdns_dict *address = NULL; + struct getdns_bindata address_data = { 4, (void *)"\x08\x08\x08\x08" }; + struct getdns_dict *response = NULL; + + CONTEXT_CREATE(TRUE); + + DICT_CREATE(address); + ASSERT_RC(getdns_dict_set_int(address, "not_address_type", 100), + GETDNS_RETURN_GOOD, "Return code from getdns_dict_set_int()"); + ASSERT_RC(getdns_dict_set_bindata(address, "not_address_data", &address_data), + GETDNS_RETURN_GOOD, "Return code from getdns_dict_set_bindata()"); + + ASSERT_RC(getdns_hostname_sync(context, address, NULL, &response), + GETDNS_RETURN_NO_SUCH_DICT_NAME, "Return code from getdns_hostname_sync()"); + + DICT_DESTROY(address); + CONTEXT_DESTROY; + } + END_TEST + + START_TEST (getdns_hostname_sync_7) + { + /* + * dict in address contains names address_type + * and address_data but data type is not bindata + * expect: GETDNS_RETURN_WRONG_TYPE_REQUESTED + */ + struct getdns_context *context = NULL; + struct getdns_dict *address = NULL; + struct getdns_dict *response = NULL; + + CONTEXT_CREATE(TRUE); + + DICT_CREATE(address); + ASSERT_RC(getdns_dict_set_int(address, "address_type", 100), + GETDNS_RETURN_GOOD, "Return code from getdns_dict_set_int()"); + ASSERT_RC(getdns_dict_set_int(address, "address_data", 200), + GETDNS_RETURN_GOOD, "Return code from getdns_dict_set_int()"); + + ASSERT_RC(getdns_hostname_sync(context, address, NULL, &response), + GETDNS_RETURN_WRONG_TYPE_REQUESTED, "Return code from getdns_hostname_sync()"); + + DICT_DESTROY(address); + CONTEXT_DESTROY; + } + END_TEST + + START_TEST (getdns_hostname_sync_8) + { + /* + * dict in address contains invalid address_type + * expect: GETDNS_RETURN_WRONG_TYPE_REQUESTED + */ + struct getdns_context *context = NULL; + struct getdns_dict *address = NULL; + struct getdns_bindata address_type = { 5, (void *)"IPv5" }; + struct getdns_bindata address_data = { 4, (void *)"\x08\x08\x08\x08" }; + struct getdns_dict *response = NULL; + + CONTEXT_CREATE(TRUE); + + DICT_CREATE(address); + ASSERT_RC(getdns_dict_set_bindata(address, "address_type", &address_type), + GETDNS_RETURN_GOOD, "Return code from getdns_dict_set_bindata()"); + ASSERT_RC(getdns_dict_set_bindata(address, "address_data", &address_data), + GETDNS_RETURN_GOOD, "Return code from getdns_dict_set_bindata()"); + + ASSERT_RC(getdns_hostname_sync(context, address, NULL, &response), + GETDNS_RETURN_GENERIC_ERROR, "Return code from getdns_hostname_sync()"); + + DICT_DESTROY(address); + CONTEXT_DESTROY; + } + END_TEST + + START_TEST (getdns_hostname_sync_9) + { + /* + * dict in address contains invalid address_data + * expect: GETDNS_RETURN_GENERIC_ERROR + */ + struct getdns_context *context = NULL; + struct getdns_dict *address = NULL; + struct getdns_bindata address_type = { 5, (void *)"IPv4" }; + struct getdns_bindata address_data = { 5, (void *)"\x08\x08\x08\x08\x08" }; + struct getdns_dict *response = NULL; + + CONTEXT_CREATE(TRUE); + + DICT_CREATE(address); + ASSERT_RC(getdns_dict_set_bindata(address, "address_type", &address_type), + GETDNS_RETURN_GOOD, "Return code from getdns_dict_set_bindata()"); + ASSERT_RC(getdns_dict_set_bindata(address, "address_data", &address_data), + GETDNS_RETURN_GOOD, "Return code from getdns_dict_set_bindata()"); + + ASSERT_RC(getdns_hostname_sync(context, address, NULL, &response), + GETDNS_RETURN_GENERIC_ERROR, "Return code from getdns_hostname_sync()"); + + DICT_DESTROY(address); + CONTEXT_DESTROY; + } + END_TEST + + START_TEST (getdns_hostname_sync_10) + { + /* + * dict in address has resolvable IPv4 address + * expect: response with correct hostnam + */ + struct getdns_context *context = NULL; + struct getdns_dict *address = NULL; + struct getdns_bindata address_type = { 5, (void *)"IPv4" }; + struct getdns_bindata address_data = { 4, (void *)"\x08\x08\x08\x08" }; + struct getdns_dict *response = NULL; + + CONTEXT_CREATE(TRUE); + + DICT_CREATE(address); + ASSERT_RC(getdns_dict_set_bindata(address, "address_type", &address_type), + GETDNS_RETURN_GOOD, "Return code from getdns_dict_set_bindata()"); + ASSERT_RC(getdns_dict_set_bindata(address, "address_data", &address_data), + GETDNS_RETURN_GOOD, "Return code from getdns_dict_set_bindata()"); + + ASSERT_RC(getdns_hostname_sync(context, address, NULL, &response), + GETDNS_RETURN_GOOD, "Return code from getdns_hostname_sync()"); + + EXTRACT_RESPONSE; + + assert_noerror(&ex_response); + assert_ptr_in_answer(&ex_response); + + DICT_DESTROY(address); + CONTEXT_DESTROY; + } + END_TEST + + START_TEST (getdns_hostname_sync_11) + { + /* + * dict in address has unresolvable IPv4 address + * expect: response with no hostname + */ + struct getdns_context *context = NULL; + struct getdns_dict *address = NULL; + struct getdns_bindata address_type = { 5, (void *)"IPv4" }; + struct getdns_bindata address_data = { 4, (void *)"\x01\x01\x01\x01" }; + struct getdns_dict *response = NULL; + + CONTEXT_CREATE(TRUE); + + DICT_CREATE(address); + ASSERT_RC(getdns_dict_set_bindata(address, "address_type", &address_type), + GETDNS_RETURN_GOOD, "Return code from getdns_dict_set_bindata()"); + ASSERT_RC(getdns_dict_set_bindata(address, "address_data", &address_data), + GETDNS_RETURN_GOOD, "Return code from getdns_dict_set_bindata()"); + + ASSERT_RC(getdns_hostname_sync(context, address, NULL, &response), + GETDNS_RETURN_GOOD, "Return code from getdns_hostname_sync()"); + + EXTRACT_RESPONSE; + + assert_nxdomain(&ex_response); + assert_nodata(&ex_response); + assert_soa_in_authority(&ex_response); + + DICT_DESTROY(address); + CONTEXT_DESTROY; + } + END_TEST + + START_TEST (getdns_hostname_sync_12) + { + /* + * dict in address has resolvable IPv6 address + * expect: response with correct hostnam + */ + struct getdns_context *context = NULL; + struct getdns_dict *address = NULL; + struct getdns_bindata address_type = { 5, (void *)"IPv6" }; + struct getdns_bindata address_data = { 16, (void *)"\x26\x07\xf8\xb0\x40\x06\x08\x02\x00\x00\x00\x00\x00\x00\x10\x04" }; + struct getdns_dict *response = NULL; + + CONTEXT_CREATE(TRUE); + + DICT_CREATE(address); + ASSERT_RC(getdns_dict_set_bindata(address, "address_type", &address_type), + GETDNS_RETURN_GOOD, "Return code from getdns_dict_set_bindata()"); + ASSERT_RC(getdns_dict_set_bindata(address, "address_data", &address_data), + GETDNS_RETURN_GOOD, "Return code from getdns_dict_set_bindata()"); + + ASSERT_RC(getdns_hostname_sync(context, address, NULL, &response), + GETDNS_RETURN_GOOD, "Return code from getdns_hostname_sync()"); + + EXTRACT_RESPONSE; + + assert_noerror(&ex_response); + assert_ptr_in_answer(&ex_response); + + DICT_DESTROY(address); + CONTEXT_DESTROY; + } + END_TEST + + START_TEST (getdns_hostname_sync_13) + { + /* + * dict in address has unresolvable IPv6 address + * expect: response with no hostname + */ + struct getdns_context *context = NULL; + struct getdns_dict *address = NULL; + struct getdns_bindata address_type = { 5, (void *)"IPv6" }; + struct getdns_bindata address_data = { 16, (void *)"\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff" }; + struct getdns_dict *response = NULL; + + CONTEXT_CREATE(TRUE); + + DICT_CREATE(address); + ASSERT_RC(getdns_dict_set_bindata(address, "address_type", &address_type), + GETDNS_RETURN_GOOD, "Return code from getdns_dict_set_bindata()"); + ASSERT_RC(getdns_dict_set_bindata(address, "address_data", &address_data), + GETDNS_RETURN_GOOD, "Return code from getdns_dict_set_bindata()"); + + ASSERT_RC(getdns_hostname_sync(context, address, NULL, &response), + GETDNS_RETURN_GOOD, "Return code from getdns_hostname_sync()"); + + EXTRACT_RESPONSE; + + assert_nxdomain(&ex_response); + assert_nodata(&ex_response); + assert_soa_in_authority(&ex_response); + + DICT_DESTROY(address); + CONTEXT_DESTROY; + } + END_TEST + + Suite * + getdns_hostname_sync_suite (void) + { + Suite *s = suite_create ("getdns_hostname_sync()"); + + /* Negative test caseis */ + TCase *tc_neg = tcase_create("Negative"); + tcase_add_test(tc_neg, getdns_hostname_sync_1); + tcase_add_test(tc_neg, getdns_hostname_sync_2); + tcase_add_test(tc_neg, getdns_hostname_sync_3); + tcase_add_test(tc_neg, getdns_hostname_sync_4); + tcase_add_test(tc_neg, getdns_hostname_sync_5); + tcase_add_test(tc_neg, getdns_hostname_sync_6); + tcase_add_test(tc_neg, getdns_hostname_sync_7); + tcase_add_test(tc_neg, getdns_hostname_sync_8); + tcase_add_test(tc_neg, getdns_hostname_sync_9); + suite_add_tcase(s, tc_neg); + /* Positive test cases */ + + TCase *tc_pos = tcase_create("Positive"); + tcase_add_test(tc_pos, getdns_hostname_sync_10); + tcase_add_test(tc_pos, getdns_hostname_sync_11); + tcase_add_test(tc_pos, getdns_hostname_sync_12); + tcase_add_test(tc_pos, getdns_hostname_sync_13); + suite_add_tcase(s, tc_pos); + + return s; + } + +#endif diff --git a/src/test/check_getdns_libevent.h b/src/test/check_getdns_libevent.h index 3dbcaf75..f9e519c9 100644 --- a/src/test/check_getdns_libevent.h +++ b/src/test/check_getdns_libevent.h @@ -1,3 +1,4 @@ +#include "config.h" #ifdef HAVE_EVENT2_EVENT_H #include #else diff --git a/src/types-internal.h b/src/types-internal.h index 47963716..36d90e9e 100644 --- a/src/types-internal.h +++ b/src/types-internal.h @@ -175,6 +175,9 @@ typedef struct getdns_dns_req /* the transaction id */ getdns_transaction_t trans_id; + /* local timeout id */ + getdns_transaction_t local_timeout_id; + } getdns_dns_req; #define MF_PLAIN ((void *)&plain_mem_funcs_user_arg)