diff --git a/README.md b/README.md index dacf291a..65d68676 100644 --- a/README.md +++ b/README.md @@ -40,6 +40,8 @@ External dependencies are linked outside the getdns API build tree (we rely on c The project relies on [libldns from NL](https://www.nlnetlabs.nl/projects/ldns/) for parsing and constructing DNS packets. Version 1.6.16 (note that building ldns may require openssl headers and libraries) +The project also relies on [libunbound from NL](http://www.nlnetlabs.nl/projects/unbound/). Currently it relies on svn revision 2985. The unbound.2985.patch must be applied to the source tree as well. The ./configure must be run with the --with-libevent option (recommended to also use --with-libunbound-only) + Although [libevent](http://libevent.org) is used initially to implement the asynchronous model, future work may include a move to other mechanisms (epoll based etc.). Version 2.0.21 stable 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/configure.ac b/configure.ac index 798fa3a1..938fd88e 100644 --- a/configure.ac +++ b/configure.ac @@ -26,10 +26,11 @@ AC_PROG_CPP # Checks for libraries. found_all_libs=1 -AC_MSG_NOTICE([Checking for dependencies ldns and libevent]) +AC_MSG_NOTICE([Checking for dependencies libevent, ldns, pthread, and unbound]) AC_CHECK_LIB([event_core], [event_base_new], [], [found_all_libs=0]) AC_CHECK_LIB([ldns], [ldns_dname_new_frm_str], [], [found_all_libs=0]) AC_CHECK_LIB([pthread], [pthread_create], [], [found_all_libs=0]) +AC_CHECK_LIB([unbound], [ub_ctx_set_event], [], [found_all_libs=0]) if test $found_all_libs == 0 then AC_MSG_ERROR([One more dependencies is missing]) diff --git a/src/Makefile.in b/src/Makefile.in index 19500e9c..5bc65d2e 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -17,8 +17,7 @@ VPATH = @srcdir@ CC=gcc CFLAGS=-Wall -g -fPIC -I$(srcdir)/ -I /usr/local/include -std=c99 -# LDFLAGS=-L. -L/usr/local/lib -# LDLIBS=-levent_core -lldns -lgetdns +LDFLAGS=-levent_core -lldns -lunbound # PROGRAMS=example-simple-answers example-tree example-all-functions example-synchronous .SUFFIXES: .c .o .a .lo .h @@ -33,8 +32,8 @@ all: libgetdns cd example && $(MAKE) $@ libgetdns: sync.o context.o list.o dict.o convert.o general.o hostname.o service.o \ - validate_dnssec.o nameserver-internal.o request-internal.o util-internal.o getdns_error.o - $(CC) $(CFLAGS) -shared -o libgetdns.so $? + validate_dnssec.o util-internal.o getdns_error.o + $(CC) $(CFLAGS) $(LDFLAGS) -shared -o libgetdns.so $? clean: rm -f *.o $(PROGRAMS) libgetdns.so diff --git a/src/context.c b/src/context.c index 55492176..f9fad1ce 100644 --- a/src/context.c +++ b/src/context.c @@ -29,9 +29,14 @@ */ #include +#include +#include #include "context.h" #include "util-internal.h" #include +#include +#include +#include /* stuff to make it compile pedantically */ #define UNUSED_PARAM(x) ((void)(x)) @@ -143,17 +148,26 @@ getdns_return_t getdns_context_create( return GETDNS_RETURN_GENERIC_ERROR; } - getdns_dict *outbound_reqs = getdns_dict_create(); - if (outbound_reqs == NULL) { + /** default init **/ + result = malloc(sizeof(struct getdns_context_t)); + if (!result) { return GETDNS_RETURN_GENERIC_ERROR; } - /** default init **/ - result = malloc(sizeof(struct getdns_context_t)); + result->update_callback = NULL; + result->memory_allocator = malloc; + result->memory_deallocator = free; + result->memory_reallocator = realloc; + + result->event_base_sync = event_base_new(); + result->unbound_sync = ub_ctx_create_event(result->event_base_sync); + /* create the async one also so options are kept up to date */ + result->unbound_async = ub_ctx_create_event(result->event_base_sync); + result->async_set = 0; + result->resolution_type = GETDNS_CONTEXT_RECURSING; result->namespaces = create_default_namespaces(); - result->dns_transport = GETDNS_CONTEXT_UDP_FIRST_AND_FALL_BACK_TO_TCP; - result->limit_outstanding_queries = 0; + result->timeout = 5000; result->follow_redirects = GETDNS_CONTEXT_FOLLOW_REDIRECTS; result->dns_root_servers = create_default_root_servers(); @@ -161,22 +175,12 @@ getdns_return_t getdns_context_create( result->suffix = NULL; result->dnssec_trust_anchors = NULL; - result->dnssec_allow_skew = 0; result->upstream_list = NULL; - result->edns_maximum_udp_payload_size = 512; + result->edns_extended_rcode = 0; result->edns_version = 0; result->edns_do_bit = 0; - result->event_base = NULL; - result->resolver_socket = 0; - result->outbound_reqs = outbound_reqs; - - result->update_callback = NULL; - result->memory_allocator = malloc; - result->memory_deallocator = free; - result->memory_reallocator = realloc; - if (set_from_os) { if (GETDNS_RETURN_GOOD != set_os_defaults(result)) { getdns_context_destroy(result); @@ -186,6 +190,12 @@ getdns_return_t getdns_context_create( *context = result; + /* other opts */ + getdns_context_set_dnssec_allowed_skew(result, 0); + getdns_context_set_edns_maximum_udp_payload_size(result, 512); + getdns_context_set_dns_transport(result, GETDNS_CONTEXT_UDP_FIRST_AND_FALL_BACK_TO_TCP); + + return GETDNS_RETURN_GOOD; } /* getdns_context_create */ @@ -211,13 +221,12 @@ getdns_context_destroy( getdns_list_destroy(context->dnssec_trust_anchors); getdns_list_destroy(context->upstream_list); - getdns_dict_destroy(context->outbound_reqs); - - /* TODO: cancel all events */ - - if (context->resolver_socket != 0) { - evutil_closesocket(context->resolver_socket); - } + /* destroy the ub context */ + ub_ctx_delete(context->unbound_async); + ub_ctx_delete(context->unbound_sync); + + event_base_free(context->event_base_sync); + free(context); return; @@ -237,6 +246,21 @@ getdns_context_set_context_update_callback( return GETDNS_RETURN_GOOD; } /* getdns_context_set_context_update_callback */ +/* + * Helpers to set options on the unbound ctx + */ + +static void set_ub_string_opt(getdns_context_t ctx, char* opt, char* value) { + ub_ctx_set_option(ctx->unbound_sync, opt, value); + ub_ctx_set_option(ctx->unbound_async, opt, value); +} + +static void set_ub_number_opt(getdns_context_t ctx, char* opt, uint16_t value) { + char buffer[64]; + snprintf(buffer, 64, "%hu", value); + set_ub_string_opt(ctx, opt, buffer); +} + /* * getdns_context_set_context_update * @@ -323,14 +347,24 @@ getdns_context_set_dns_transport( uint16_t value ) { - if (value != GETDNS_CONTEXT_UDP_FIRST_AND_FALL_BACK_TO_TCP && - value != GETDNS_CONTEXT_UDP_ONLY && - value != GETDNS_CONTEXT_TCP_ONLY && - value != GETDNS_CONTEXT_TCP_ONLY_KEEP_CONNECTIONS_OPEN) { - return GETDNS_RETURN_CONTEXT_UPDATE_FAIL; + + switch (value) { + case GETDNS_CONTEXT_UDP_FIRST_AND_FALL_BACK_TO_TCP: + set_ub_string_opt(context, "do-udp", "yes"); + set_ub_string_opt(context, "do-tcp", "yes"); + break; + case GETDNS_CONTEXT_UDP_ONLY: + set_ub_string_opt(context, "do-udp", "yes"); + set_ub_string_opt(context, "do-tcp", "no"); + break; + case GETDNS_CONTEXT_TCP_ONLY: + set_ub_string_opt(context, "do-udp", "no"); + set_ub_string_opt(context, "do-tcp", "yes"); + break; + default: + /* TODO GETDNS_CONTEXT_TCP_ONLY_KEEP_CONNECTIONS_OPEN */ + return GETDNS_RETURN_CONTEXT_UPDATE_FAIL; } - - context->dns_transport = value; dispatch_updated(context, GETDNS_CONTEXT_CODE_DNS_TRANSPORT); @@ -347,8 +381,9 @@ getdns_context_set_limit_outstanding_queries( uint16_t limit ) { - context->limit_outstanding_queries = limit; - + /* num-queries-per-thread */ + set_ub_number_opt(context, "num-queries-per-thread", limit); + dispatch_updated(context, GETDNS_CONTEXT_CODE_LIMIT_OUTSTANDING_QUERIES); return GETDNS_RETURN_GOOD; @@ -427,7 +462,6 @@ getdns_context_set_append_name( value != GETDNS_CONTEXT_APPEND_NAME_ONLY_TO_SINGLE_LABEL_AFTER_FAILURE && value != GETDNS_CONTEXT_APPEND_NAME_ONLY_TO_MULTIPLE_LABEL_NAME_AFTER_FAILURE && value != GETDNS_CONTEXT_DO_NOT_APPEND_NAMES) { - return GETDNS_RETURN_CONTEXT_UPDATE_FAIL; } @@ -498,8 +532,8 @@ getdns_context_set_dnssec_allowed_skew( uint16_t value ) { - context->dnssec_allow_skew = value; - + set_ub_number_opt(context, "val-sig-skew-min", value); + set_ub_number_opt(context, "val-sig-skew-max", value); dispatch_updated(context, GETDNS_CONTEXT_CODE_DNSSEC_ALLOWED_SKEW); return GETDNS_RETURN_GOOD; @@ -549,7 +583,8 @@ getdns_context_set_edns_maximum_udp_payload_size( return GETDNS_RETURN_CONTEXT_UPDATE_FAIL; } - context->edns_maximum_udp_payload_size = value; + /* max-udp-size */ + set_ub_number_opt(context, "max-udp-size", value); dispatch_updated(context, GETDNS_CONTEXT_CODE_EDNS_MAXIMUM_UDP_PAYLOAD_SIZE); @@ -667,9 +702,13 @@ getdns_extension_set_libevent_base( struct event_base *this_event_base ) { - /* TODO: cancel anything on an existing event base */ - context->event_base = this_event_base; - + if (this_event_base) { + ub_ctx_set_event(context->unbound_async, this_event_base); + context->async_set = 1; + } else { + context->async_set = 0; + ub_ctx_set_event(context->unbound_async, context->event_base_sync); + } return GETDNS_RETURN_GOOD; } /* getdns_extension_set_libevent_base */ diff --git a/src/context.h b/src/context.h index e9c513b5..d6991a0c 100644 --- a/src/context.h +++ b/src/context.h @@ -32,6 +32,9 @@ #include +struct event_base; +struct ub_ctx; + /** function pointer typedefs */ typedef void (*getdns_update_callback)(getdns_context_t context, uint16_t changed_item); typedef void* (*getdns_memory_allocator)(size_t size); @@ -43,17 +46,14 @@ struct getdns_context_t { /* Context values */ uint16_t resolution_type; uint16_t *namespaces; - uint16_t dns_transport; - uint16_t limit_outstanding_queries; uint16_t timeout; uint16_t follow_redirects; struct getdns_list *dns_root_servers; uint16_t append_name; struct getdns_list *suffix; struct getdns_list *dnssec_trust_anchors; - uint16_t dnssec_allow_skew; struct getdns_list *upstream_list; - uint16_t edns_maximum_udp_payload_size; + uint8_t edns_extended_rcode; uint8_t edns_version; uint8_t edns_do_bit; @@ -63,14 +63,15 @@ struct getdns_context_t { getdns_memory_deallocator memory_deallocator; getdns_memory_reallocator memory_reallocator; - /* Event loop */ - struct event_base* event_base; + /* Event loop for sync requests */ + struct event_base* event_base_sync; + + /* The underlying unbound contexts that do + the real work */ + struct ub_ctx *unbound_sync; + struct ub_ctx *unbound_async; + uint8_t async_set; - /* outbound request dict (transaction -> req struct) */ - getdns_dict *outbound_reqs; - - /* socket */ - evutil_socket_t resolver_socket; } ; #endif diff --git a/src/example/Makefile.in b/src/example/Makefile.in index 1a5c2cf2..2bbf3ad6 100644 --- a/src/example/Makefile.in +++ b/src/example/Makefile.in @@ -17,7 +17,7 @@ VPATH = @srcdir@ CC=gcc CFLAGS=-Wall -g -fPIC -I$(srcdir)/ -I$(srcdir)/../ -I/usr/local/include -std=c99 LDFLAGS=-L. -L$(srcdir)/.. -L/usr/local/lib -LDLIBS=-lgetdns -lldns -levent_core +LDLIBS=-lgetdns -lldns -levent_core -lunbound PROGRAMS=example_simple_answers example_tree example_all_functions example_synchronous .SUFFIXES: .c .o .a .lo .h diff --git a/src/example/example_simple_answers.c b/src/example/example_simple_answers.c index a4c038ef..0d78d7f0 100644 --- a/src/example/example_simple_answers.c +++ b/src/example/example_simple_answers.c @@ -32,6 +32,7 @@ #include #include #include +#include #define UNUSED_PARAM(x) ((void)(x)) diff --git a/src/example/example_tree.c b/src/example/example_tree.c index 6769baad..e51c5755 100644 --- a/src/example/example_tree.c +++ b/src/example/example_tree.c @@ -4,6 +4,7 @@ #include #include #include +#include #define UNUSED_PARAM(x) ((void)(x)) diff --git a/src/general.c b/src/general.c index f0c3eae0..7a6f3f55 100644 --- a/src/general.c +++ b/src/general.c @@ -58,94 +58,108 @@ * Version: 0.1b */ -#include "types-internal.h" +#include +#include +#include +#include +#include "context.h" #include "util-internal.h" /* stuff to make it compile pedantically */ #define UNUSED_PARAM(x) ((void)(x)) -/* libevent callback for a network request */ -static void dns_req_callback(int fd, short events, void *arg) { - getdns_dns_req *request = (getdns_dns_req*) arg; - uint8_t data[1500]; - if (events & EV_READ) { - while (1) { - ssize_t r = recv(fd, data, sizeof(data), MSG_DONTWAIT); - if (r < 0) { - if (errno == EAGAIN) return; - /* otherwise failed */ - request->user_callback(request->context, - GETDNS_CALLBACK_ERROR, - NULL, request->user_pointer, - request->trans_id); - } - /* parse a packet */ - ldns_pkt* pkt = NULL; - ldns_wire2pkt(&pkt, data, r); - if (pkt == NULL) { - /* otherwise failed */ - request->user_callback(request->context, - GETDNS_CALLBACK_ERROR, - NULL, request->user_pointer, - request->trans_id); - } else { - /* success */ - getdns_dict* response = create_getdns_response(pkt); - ldns_pkt_free(pkt); - request->user_callback(request->context, GETDNS_CALLBACK_COMPLETE, - response, request->user_pointer, - request->trans_id); - } - } - } else if (events & EV_TIMEOUT) { - request->user_callback(request->context, GETDNS_CALLBACK_TIMEOUT, - NULL, request->user_pointer, request->trans_id); - } - /* clean up ns since right now it's 1:1 with the request */ - nameserver_free(request->current_req->ns); - /* cleanup the request */ - dns_req_free(request); +typedef struct getdns_ub_req { + struct ub_ctx *unbound; + getdns_context_t context; + char* name; + void* userarg; + getdns_callback_t callback; + getdns_transaction_t transaction_id; +} getdns_ub_req; + +static void getdns_ub_req_free(getdns_ub_req* req) { + free(req->name); + free(req); } -/* submit a new request to the event loop */ -static getdns_return_t submit_new_dns_req(getdns_dns_req *request) { - getdns_dict *ip_dict = NULL; - getdns_context_t context = request->context; - uint8_t* data = NULL; - size_t data_len = 0; - struct timeval timeout = { 5, 0 }; - - /* get first upstream server */ - getdns_list_get_dict(context->upstream_list, 0, &ip_dict); - if (!ip_dict) { - return GETDNS_RETURN_GENERIC_ERROR; +void ub_resolve_callback(void* arg, int err, ldns_buffer* result, int sec, char* bogus) { + getdns_ub_req* req = (getdns_ub_req*) arg; + ldns_pkt* pkt = NULL; + if (err) { + req->callback(req->context, + GETDNS_CALLBACK_ERROR, + NULL, + req->userarg, + req->transaction_id); + } else { + /* parse */ + ldns_status r = ldns_buffer2pkt_wire(&pkt, result); + if (r != LDNS_STATUS_OK) { + req->callback(req->context, + GETDNS_CALLBACK_ERROR, + NULL, + req->userarg, + req->transaction_id); + } else { + getdns_dict* response = create_getdns_response(pkt); + ldns_pkt_free(pkt); + req->callback(req->context, + GETDNS_CALLBACK_COMPLETE, + response, + req->userarg, + req->transaction_id); } - - /* get the nameserver */ - getdns_nameserver *ns = nameserver_new_from_ip_dict(context, ip_dict); - if (!ns) { - return GETDNS_RETURN_GENERIC_ERROR; - } - - request->current_req->ns = ns; + } + /* cleanup */ + getdns_ub_req_free(req); +} - /* schedule on the loop */ - ns->event = event_new(context->event_base, request->current_req->ns->socket, - EV_READ | EV_TIMEOUT, - dns_req_callback, request); - - event_add(ns->event, &timeout); - - /* send data */ - ldns_pkt *pkt = request->current_req->pkt; - ldns_pkt2wire(&data, pkt, &data_len); - send(ns->socket, data, data_len, MSG_DONTWAIT); - free(data); - +getdns_return_t +getdns_general_ub( + struct ub_ctx* unbound, + getdns_context_t context, + const char *name, + uint16_t request_type, + struct getdns_dict *extensions, + void *userarg, + getdns_transaction_t *transaction_id, + getdns_callback_t callbackfn +) { + + int r; + int async_id = 0; + + /* request state */ + getdns_ub_req* req = (getdns_ub_req*) malloc(sizeof(getdns_ub_req)); + req->unbound = unbound; + req->context = context; + req->name = strdup(name); + req->userarg = userarg; + req->callback = callbackfn; + + /* TODO: + setup root or stub + handle immediate callback + A + AAAA + */ + + r = ub_resolve_event(unbound, req->name, request_type, + LDNS_RR_CLASS_IN, req, ub_resolve_callback, + &async_id); + + if (transaction_id) { + *transaction_id = async_id; + } + req->transaction_id = async_id; + + + if (r != 0) { + getdns_ub_req_free(req); + return GETDNS_RETURN_GENERIC_ERROR; + } return GETDNS_RETURN_GOOD; } - /* * getdns_general */ @@ -160,36 +174,24 @@ getdns_general( getdns_callback_t callback ) { - /* Default to zero */ - if (transaction_id != NULL) { - *transaction_id = 0; - } - if (!context || context->event_base == NULL || - callback == NULL || - context->resolution_type != GETDNS_CONTEXT_STUB) { + + if (!context || context->async_set == 0 || + callback == NULL) { /* Can't do async without an event loop - * or callback - * - * Only supports stub right now. + * or callback */ return GETDNS_RETURN_BAD_CONTEXT; } + return getdns_general_ub(context->unbound_async, + context, + name, + request_type, + extensions, + userarg, + transaction_id, + callback); - /* create a req */ - getdns_dns_req *dns_req = dns_req_new(context, name, request_type, - extensions, transaction_id); - if (dns_req == NULL) { - return GETDNS_RETURN_GENERIC_ERROR; - } - - dns_req->user_callback = callback; - dns_req->user_pointer = userarg; - - /* submit it */ - submit_new_dns_req(dns_req); - - return GETDNS_RETURN_GOOD; } /* getdns_general */ diff --git a/src/general.h b/src/general.h new file mode 100644 index 00000000..ee3bd84b --- /dev/null +++ b/src/general.h @@ -0,0 +1,49 @@ +/** + * + * /brief getdns contect management functions + * + * This is the meat of the API + * Originally taken from the getdns API description pseudo implementation. + * + */ +/* The MIT License (MIT) + * Copyright (c) 2013 Verisign, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#ifndef _GETDNS_GENERAL_H_ +#define _GETDNS_GENERAL_H_ + +#include + +struct ub_ctx; + +getdns_return_t +getdns_general_ub( + struct ub_ctx* unbound, + getdns_context_t context, + const char *name, + uint16_t request_type, + struct getdns_dict *extensions, + void *userarg, + getdns_transaction_t *transaction_id, + getdns_callback_t callbackfn +); + +#endif diff --git a/src/getdns/getdns.h b/src/getdns/getdns.h index 046c9558..0152bbf9 100644 --- a/src/getdns/getdns.h +++ b/src/getdns/getdns.h @@ -34,7 +34,8 @@ #include #include #include -#include + +struct event_base; #define GETDNS_COMPILATION_COMMENT The API implementation should fill in something here, such as a compilation version string and date, and change it each time the API is compiled. diff --git a/src/sync.c b/src/sync.c index 6f029286..041de7f6 100644 --- a/src/sync.c +++ b/src/sync.c @@ -29,7 +29,10 @@ #include #include -#include "types-internal.h" +#include +#include +#include "context.h" +#include "general.h" /* stuff to make it compile pedantically */ #define UNUSED_PARAM(x) ((void)(x)) @@ -55,18 +58,17 @@ static void sync_callback_func(getdns_context_t context, static void * request_thread_start(void *arg) { struct sync_request_data *req_data = arg; - struct event_base *event_base = event_base_new(); - getdns_extension_set_libevent_base(req_data->context, event_base); - req_data->response_status = getdns_general(req_data->context, - req_data->name, - req_data->request_type, - req_data->extensions, - req_data, - NULL, - sync_callback_func); + req_data->response_status = getdns_general_ub(req_data->context->unbound_sync, + req_data->context, + req_data->name, + req_data->request_type, + req_data->extensions, + req_data, + NULL, + sync_callback_func); - event_base_dispatch(event_base); + event_base_dispatch(req_data->context->event_base_sync); return NULL; } @@ -82,8 +84,8 @@ getdns_general_sync( ) { /* we will cheat and spawn a thread */ - /* get the old event base */ - struct event_base* orig_base = context->event_base; + /* set up for sync resolution */ + pthread_t thread; pthread_attr_t attr; sync_request_data req_data = { @@ -110,10 +112,7 @@ getdns_general_sync( if (ret != 0) { return GETDNS_RETURN_GENERIC_ERROR; } - - /* set the old event loop */ - getdns_extension_set_libevent_base(context, orig_base); - + return req_data.response_status; } diff --git a/src/test/tests_stub_async.c b/src/test/tests_stub_async.c index 71728c23..b5f6933f 100644 --- a/src/test/tests_stub_async.c +++ b/src/test/tests_stub_async.c @@ -31,6 +31,7 @@ #include #include "testmessages.h" #include +#include /* Set up the callback function, which will also do the processing of the results */ void this_callbackfn(struct getdns_context_t *this_context, diff --git a/src/util-internal.h b/src/util-internal.h index 5e144d56..740358f4 100644 --- a/src/util-internal.h +++ b/src/util-internal.h @@ -28,7 +28,13 @@ * THE SOFTWARE. */ +/* #include "types-internal.h" +*/ + +#include +#include "context.h" + /* convert an ip address dict to a sock storage */ getdns_return_t dict_to_sockaddr(getdns_dict* ns, struct sockaddr_storage* output); diff --git a/unbound.2985.patch b/unbound.2985.patch new file mode 100644 index 00000000..ed3875c1 --- /dev/null +++ b/unbound.2985.patch @@ -0,0 +1,118 @@ +Index: Makefile.in +=================================================================== +--- Makefile.in (revision 2985) ++++ Makefile.in (working copy) +@@ -280,7 +280,7 @@ + longtest: tests + if test -x "`which bash`"; then bash testcode/do-tests.sh; else sh testcode/do-tests.sh; fi + +-lib: libunbound.la unbound.h ++lib: libunbound.la unbound.h unbound-event.h + + libunbound.la: $(LIBUNBOUND_OBJ_LINK) + $(LINK_LIB) $(UBSYMS) -o $@ $(LIBUNBOUND_OBJ_LINK) -rpath $(libdir) -lssl $(LIBS) +@@ -348,6 +348,9 @@ + unbound.h: $(srcdir)/libunbound/unbound.h + sed -e 's/@''UNBOUND_VERSION_MAJOR@/$(UNBOUND_VERSION_MAJOR)/' -e 's/@''UNBOUND_VERSION_MINOR@/$(UNBOUND_VERSION_MINOR)/' -e 's/@''UNBOUND_VERSION_MICRO@/$(UNBOUND_VERSION_MICRO)/' < $(srcdir)/libunbound/unbound.h > $@ + ++unbound-event.h: $(srcdir)/libunbound/unbound-event.h ++ sed -e 's/@''UNBOUND_VERSION_MAJOR@/$(UNBOUND_VERSION_MAJOR)/' -e 's/@''UNBOUND_VERSION_MINOR@/$(UNBOUND_VERSION_MINOR)/' -e 's/@''UNBOUND_VERSION_MICRO@/$(UNBOUND_VERSION_MICRO)/' < $(srcdir)/libunbound/unbound-event.h > $@ ++ + unbound-control-setup: $(srcdir)/smallapp/unbound-control-setup.sh + sed -e 's:^DESTDIR=.*$$:DESTDIR=$(UNBOUND_RUN_DIR):' < $(srcdir)/smallapp/unbound-control-setup.sh > $@ + -chmod +x $@ +@@ -496,6 +499,7 @@ + $(INSTALL) -c -m 755 unbound-control-setup $(DESTDIR)$(sbindir)/unbound-control-setup + if test ! -e $(DESTDIR)$(configfile); then $(INSTALL) -d `dirname $(DESTDIR)$(configfile)`; $(INSTALL) -c -m 644 doc/example.conf $(DESTDIR)$(configfile); fi + $(LIBTOOL) --mode=install cp unbound.h $(DESTDIR)$(includedir)/unbound.h ++ $(LIBTOOL) --mode=install cp unbound-event.h $(DESTDIR)$(includedir)/unbound-event.h + $(LIBTOOL) --mode=install cp libunbound.la $(DESTDIR)$(libdir) + $(LIBTOOL) --mode=finish $(DESTDIR)$(libdir) + +Index: libunbound/ubsyms.def +=================================================================== +--- libunbound/ubsyms.def (revision 2985) ++++ libunbound/ubsyms.def (working copy) +@@ -29,3 +29,4 @@ + ub_ctx_data_add + ub_ctx_data_remove + ub_version ++ub_ctx_set_event +Index: libunbound/unbound-event.h +=================================================================== +--- libunbound/unbound-event.h (revision 2985) ++++ libunbound/unbound-event.h (working copy) +@@ -63,9 +63,9 @@ + struct ub_ctx; + struct ub_result; + struct event_base; +-struct ldns_buffer; ++struct ldns_struct_buffer; + +-typedef void (*ub_event_callback_t)(void*, int, struct ldns_buffer*, int, char*); ++typedef void (*ub_event_callback_t)(void*, int, struct ldns_struct_buffer*, int, char*); + + /** + * Create a resolving and validation context. +@@ -82,6 +82,15 @@ + struct ub_ctx* ub_ctx_create_event(struct event_base* base); + + /** ++ * Set a new event_base on a context created with ub_ctx_create_event. ++ * Any outbound queries will be canceled. ++ * @param ctx the ub_ctx to update. Must have been created with ub_ctx_create_event ++ * @param base the new event_base to attach to the ctx ++ * @return 0 if OK, else error ++ */ ++int ub_ctx_set_event(struct ub_ctx* ctx, struct event_base* base); ++ ++/** + * Perform resolution and validation of the target name. + * Asynchronous, after a while, the callback will be called with your + * data and the result. Uses the event_base user installed by creating the +Index: libunbound/libunbound.c +=================================================================== +--- libunbound/libunbound.c (revision 2985) ++++ libunbound/libunbound.c (working copy) +@@ -656,15 +656,14 @@ + return r; + } + } ++ lock_basic_unlock(&ctx->cfglock); + if(!ctx->event_worker) { + ctx->event_worker = libworker_create_event(ctx, + ctx->event_base); + if(!ctx->event_worker) { +- lock_basic_unlock(&ctx->cfglock); + return UB_INITFAIL; + } + } +- lock_basic_unlock(&ctx->cfglock); + + /* create new ctx_query and attempt to add to the list */ + q = context_new(ctx, name, rrtype, rrclass, (ub_callback_t)callback, +@@ -1212,3 +1211,24 @@ + { + return PACKAGE_VERSION; + } ++ ++int ++ub_ctx_set_event(struct ub_ctx* ctx, struct event_base* base) { ++ if (!ctx || !ctx->event_base || !base) { ++ return UB_INITFAIL; ++ } ++ if (ctx->event_base == base) { ++ /* already set */ ++ return UB_NOERROR; ++ } ++ ++ lock_basic_lock(&ctx->cfglock); ++ /* destroy the current worker - safe to pass in NULL */ ++ libworker_delete_event(ctx->event_worker); ++ ctx->event_worker = NULL; ++ ctx->event_base = base; ++ ctx->created_bg = 0; ++ ctx->dothread = 1; ++ lock_basic_unlock(&ctx->cfglock); ++ return UB_NOERROR; ++}