From ae2b16665b422222c3c1c4b501ece9c65a918ff4 Mon Sep 17 00:00:00 2001 From: Willem Toorop Date: Tue, 19 Jan 2016 16:52:11 +0100 Subject: [PATCH] Setup getdns eventloop in libunbound When unbound supports this --- configure.ac | 15 +++++++++++++-- src/context.c | 40 +++++++++++++++++++++++++++++++++------- src/context.h | 3 +++ src/general.c | 40 +++++++++++++++++++++++++++++++++++----- src/sync.c | 20 +++++++++++++++----- src/test/getdns_query.c | 6 ++++-- src/util-internal.c | 28 +++++++++++----------------- src/util-internal.h | 3 ++- 8 files changed, 116 insertions(+), 39 deletions(-) diff --git a/configure.ac b/configure.ac index ab0d917b..df56589c 100644 --- a/configure.ac +++ b/configure.ac @@ -526,7 +526,15 @@ fi if test $my_with_libunbound = 1 then AC_MSG_NOTICE([Checking for dependency libunbound]) - AC_CHECK_LIB([unbound], [ub_fd], [], [found_all_libs=0]) + AC_CHECK_LIB([unbound], [ub_fd], [ + AC_DEFINE_UNQUOTED([HAVE_LIBUNBOUND], [1], [Define to 1 if you have the `unbound' library (-lunbound).]) + LIBS="$LIBS -lunbound" + AC_CHECK_HEADER([unbound-event.h],[ + AC_CHECK_FUNC([ub_event_get_version], [ + AC_DEFINE_UNQUOTED([HAVE_UNBOUND_EVENT_API], [1], [Define this when libunbound is compiled with the --enable-event-api option.]) + ]) + ],,[AC_INCLUDES_DEFAULT]) + ], [found_all_libs=0]) fi if test $found_all_libs = 0 @@ -1192,7 +1200,10 @@ const char *inet_ntop(int af, const void *src, char *dst, size_t size); #endif #ifdef HAVE_LIBUNBOUND -#include +# include +# ifdef HAVE_UNBOUND_EVENT_API +# include +# endif #endif ]) diff --git a/src/context.c b/src/context.c index 8ddf2c9a..3ea960e6 100644 --- a/src/context.c +++ b/src/context.c @@ -1281,9 +1281,12 @@ getdns_context_request_count_changed(getdns_context *context) "-> ub schedule(el_ev = %p, el_ev->ev = %p)\n", &context->ub_event, context->ub_event.ev); #ifndef USE_WINSOCK - context->extension->vmt->schedule( - context->extension, ub_fd(context->unbound_ctx), - TIMEOUT_FOREVER, &context->ub_event); +#ifdef HAVE_UNBOUND_EVENT_API + if (!context->unbound_event_api) +#endif + context->extension->vmt->schedule( + context->extension, ub_fd(context->unbound_ctx), + TIMEOUT_FOREVER, &context->ub_event); #endif } else if (context->ub_event.ev) /* Only test if count == 0! */ { @@ -1292,8 +1295,11 @@ getdns_context_request_count_changed(getdns_context *context) &context->ub_event, context->ub_event.ev); #ifndef USE_WINSOCK - context->extension->vmt->clear( - context->extension, &context->ub_event); +#ifdef HAVE_UNBOUND_EVENT_API + if (!context->unbound_event_api) +#endif + context->extension->vmt->clear( + context->extension, &context->ub_event); #endif } } @@ -1324,8 +1330,18 @@ rebuild_ub_ctx(struct getdns_context* context) { context->unbound_ctx = NULL; } /* setup */ - context->unbound_ctx = ub_ctx_create(); - (void) ub_ctx_async(context->unbound_ctx, 1); +#ifdef HAVE_UNBOUND_EVENT_API + context->unbound_event_api = + strncmp(ub_event_get_version(), "getdns-event", 12) == 0; + if (context->unbound_event_api) { + context->unbound_ctx = ub_ctx_create_event((void *)context->extension); + } else { +#endif + context->unbound_ctx = ub_ctx_create(); + (void) ub_ctx_async(context->unbound_ctx, 1); +#ifdef HAVE_UNBOUND_EVENT_API + } +#endif context->unbound_ta_set = 0; if (!context->unbound_ctx) { return GETDNS_RETURN_MEMORY_ERROR; @@ -2891,6 +2907,11 @@ getdns_context_detach_eventloop(struct getdns_context* context) context->extension->vmt->cleanup(context->extension); context->extension = &context->default_eventloop.loop; _getdns_default_eventloop_init(&context->default_eventloop); +#ifdef HAVE_UNBOUND_EVENT_API + if (context->unbound_event_api) + (void) ub_ctx_set_event( + context->unbound_ctx, (void *)context->extension); +#endif return GETDNS_RETURN_GOOD; } @@ -2905,6 +2926,11 @@ getdns_context_set_eventloop(getdns_context* context, getdns_eventloop* loop) context->extension->vmt->cleanup(context->extension); } context->extension = loop; +#ifdef HAVE_UNBOUND_EVENT_API + if (context->unbound_event_api) + (void) ub_ctx_set_event( + context->unbound_ctx, (void *)context->extension); +#endif return GETDNS_RETURN_GOOD; } diff --git a/src/context.h b/src/context.h index 8547673c..2ba134f9 100644 --- a/src/context.h +++ b/src/context.h @@ -220,6 +220,9 @@ struct getdns_context { /* The underlying contexts that do the real work */ struct ub_ctx *unbound_ctx; int unbound_ta_set; +#ifdef HAVE_UNBOUND_EVENT_API + int unbound_event_api; +#endif #endif /* A tree to hold local host information*/ diff --git a/src/general.c b/src/general.c index 777774e6..af156c05 100644 --- a/src/general.c +++ b/src/general.c @@ -256,6 +256,26 @@ _getdns_check_dns_req_complete(getdns_dns_req *dns_req) } #ifdef HAVE_LIBUNBOUND +#ifdef HAVE_UNBOUND_EVENT_API +static void +ub_resolve_event_callback(void* arg, int rcode, void *pkt, int pkt_len, + int sec, char* why_bogus) +{ + getdns_network_req *netreq = (getdns_network_req *) arg; + getdns_dns_req *dns_req = netreq->owner; + + netreq->state = NET_REQ_FINISHED; + /* parse */ + if (getdns_apply_network_result( + netreq, rcode, pkt, pkt_len, sec, why_bogus)) { + _getdns_call_user_callback(dns_req, NULL); + return; + } + _getdns_check_dns_req_complete(dns_req); + +} /* ub_resolve_event_callback */ +#endif + static void ub_resolve_callback(void* arg, int err, struct ub_result* ub_res) { @@ -268,7 +288,9 @@ ub_resolve_callback(void* arg, int err, struct ub_result* ub_res) return; } /* parse */ - if (getdns_apply_network_result(netreq, ub_res)) { + if (getdns_apply_network_result(netreq, ub_res->rcode, + ub_res->answer_packet, ub_res->answer_len, + (ub_res->secure ? 2 : ub_res->bogus ? 1 : 0), ub_res->why_bogus)) { ub_resolve_free(ub_res); _getdns_call_user_callback(dns_req, NULL); return; @@ -319,10 +341,18 @@ _getdns_submit_netreq(getdns_network_req *netreq) dns_req->name_len, name, sizeof(name)); #ifdef HAVE_LIBUNBOUND - return ub_resolve_async(dns_req->context->unbound_ctx, - name, netreq->request_type, netreq->owner->request_class, - netreq, ub_resolve_callback, &(netreq->unbound_id)) ? - GETDNS_RETURN_GENERIC_ERROR : GETDNS_RETURN_GOOD; +#ifdef HAVE_UNBOUND_EVENT_API + if (dns_req->context->unbound_event_api) + return ub_resolve_event(dns_req->context->unbound_ctx, + name, netreq->request_type, netreq->owner->request_class, + netreq, ub_resolve_event_callback, &(netreq->unbound_id)) ? + GETDNS_RETURN_GENERIC_ERROR : GETDNS_RETURN_GOOD; + else +#endif + return ub_resolve_async(dns_req->context->unbound_ctx, + name, netreq->request_type, netreq->owner->request_class, + netreq, ub_resolve_callback, &(netreq->unbound_id)) ? + GETDNS_RETURN_GENERIC_ERROR : GETDNS_RETURN_GOOD; #else return GETDNS_RETURN_NOT_IMPLEMENTED; #endif diff --git a/src/sync.c b/src/sync.c index 714a6b87..dffff203 100644 --- a/src/sync.c +++ b/src/sync.c @@ -75,11 +75,15 @@ getdns_sync_loop_init(getdns_context *context, getdns_sync_loop *loop) loop->ub_event.timeout_cb = NULL; loop->ub_event.ev = NULL; - return ext->vmt->schedule(ext, ub_fd(context->unbound_ctx), - TIMEOUT_FOREVER, &loop->ub_event); -#else - return GETDNS_RETURN_GOOD; +# ifdef HAVE_UNBOUND_EVENT_API + if (context->unbound_event_api) { + (void) ub_ctx_set_event(context->unbound_ctx, (void *)ext); + } else +# endif + return ext->vmt->schedule(ext, ub_fd(context->unbound_ctx), + TIMEOUT_FOREVER, &loop->ub_event); #endif + return GETDNS_RETURN_GOOD; } static void @@ -88,7 +92,13 @@ getdns_sync_loop_cleanup(getdns_sync_loop *loop) getdns_eventloop *ext = &loop->loop.loop; #if defined(HAVE_LIBUNBOUND) && !defined(USE_WINSOCK) - ext->vmt->clear(ext, &loop->ub_event); +# ifdef HAVE_UNBOUND_EVENT_API + if (loop->context->unbound_event_api) { + (void) ub_ctx_set_event(loop->context->unbound_ctx, + (void *)loop->context->extension); + } else +# endif + ext->vmt->clear(ext, &loop->ub_event); #endif ext->vmt->cleanup(ext); } diff --git a/src/test/getdns_query.c b/src/test/getdns_query.c index 2e665cef..a17a4bec 100644 --- a/src/test/getdns_query.c +++ b/src/test/getdns_query.c @@ -1305,8 +1305,6 @@ main(int argc, char **argv) return r; } my_eventloop_init(&my_loop); - if ((r = getdns_context_set_eventloop(context, &my_loop.base))) - goto done_destroy_context; if ((r = getdns_context_set_use_threads(context, 1))) goto done_destroy_context; extensions = getdns_dict_create(); @@ -1329,10 +1327,14 @@ main(int argc, char **argv) /* Make the call */ if (interactive) { + getdns_eventloop_event read_line_ev = { &read_line_ev, read_line_cb, NULL, NULL, NULL }; (void) my_eventloop_schedule( &my_loop.base, fileno(fp), -1, &read_line_ev); + if ((r = getdns_context_set_eventloop(context, &my_loop.base))) + goto done_destroy_context; + if (!query_file) { printf("> "); fflush(stdout); diff --git a/src/util-internal.c b/src/util-internal.c index fe41bea6..2498306b 100644 --- a/src/util-internal.c +++ b/src/util-internal.c @@ -1020,30 +1020,24 @@ error_free_result: #ifdef HAVE_LIBUNBOUND getdns_return_t getdns_apply_network_result(getdns_network_req* netreq, - struct ub_result* ub_res) + int rcode, void *pkt, int pkt_len, int sec, char* why_bogus) { - if (ub_res->bogus) - netreq->dnssec_status = GETDNS_DNSSEC_BOGUS; - else if (ub_res->secure) - netreq->dnssec_status = GETDNS_DNSSEC_SECURE; - else if (netreq->owner->context->trust_anchors) - netreq->dnssec_status = GETDNS_DNSSEC_INSECURE; + netreq->dnssec_status = sec == 0 ? GETDNS_DNSSEC_INSECURE + : sec == 2 ? GETDNS_DNSSEC_SECURE + : GETDNS_DNSSEC_BOGUS; - if (ub_res == NULL) /* Timeout */ - return GETDNS_RETURN_GOOD; - - if (ub_res->answer_packet) { - if (netreq->max_udp_payload_size < ub_res->answer_len) + if (pkt) { + if (netreq->max_udp_payload_size < pkt_len) netreq->response = GETDNS_XMALLOC( netreq->owner->context->mf, - uint8_t, ub_res->answer_len + uint8_t, pkt_len ); - (void) memcpy(netreq->response, ub_res->answer_packet, - (netreq->response_len = ub_res->answer_len)); + (void) memcpy(netreq->response, pkt, + (netreq->response_len = pkt_len)); return GETDNS_RETURN_GOOD; } - if (ub_res->rcode == GETDNS_RCODE_SERVFAIL) { + if (rcode == GETDNS_RCODE_SERVFAIL) { /* Likely to be caused by timeout from a synchronous * lookup. Don't forge a packet. */ @@ -1064,7 +1058,7 @@ getdns_apply_network_result(getdns_network_req* netreq, GLDNS_QR_SET(netreq->response); GLDNS_RD_SET(netreq->response); GLDNS_RA_SET(netreq->response); - GLDNS_RCODE_SET(netreq->response, ub_res->rcode); + GLDNS_RCODE_SET(netreq->response, rcode); (void) memcpy( netreq->response + GLDNS_HEADER_SIZE , netreq->owner->name, netreq->owner->name_len); diff --git a/src/util-internal.h b/src/util-internal.h index 7a826b95..8aeeb397 100644 --- a/src/util-internal.h +++ b/src/util-internal.h @@ -56,7 +56,8 @@ struct ub_result; struct getdns_network_req; -getdns_return_t getdns_apply_network_result(getdns_network_req* netreq, struct ub_result* result); +getdns_return_t getdns_apply_network_result(getdns_network_req* netreq, + int rcode, void *pkt, int pkt_len, int sec, char* why_bogus); #define GETDNS_MAX_DNAME_LEN 255 #define GETDNS_MAX_LABEL_LEN 63