Initial pass at using unbound stock

This commit is contained in:
Neel Goyal 2014-01-21 15:31:22 -05:00
parent d9e3485f8b
commit 2bcfedcf78
15 changed files with 282 additions and 8861 deletions

8601
aclocal.m4 vendored

File diff suppressed because it is too large Load Diff

26
configure vendored
View File

@ -7103,6 +7103,10 @@ _lt_linker_boilerplate=`cat conftest.err`
$RM -r conftest*
## CAVEAT EMPTOR:
## There is no encapsulation within the following macros, do not change
## the running order or otherwise move them around unless you know exactly
## what you are doing...
if test -n "$compiler"; then
lt_prog_compiler_no_builtin_flag=
@ -11014,9 +11018,9 @@ fi
found_libunbound=1
{ $as_echo "$as_me:${as_lineno-$LINENO}: Checking for dependency libunbound" >&5
$as_echo "$as_me: Checking for dependency libunbound" >&6;}
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ub_ctx_set_event in -lunbound" >&5
$as_echo_n "checking for ub_ctx_set_event in -lunbound... " >&6; }
if ${ac_cv_lib_unbound_ub_ctx_set_event+:} false; then :
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ub_fd in -lunbound" >&5
$as_echo_n "checking for ub_fd in -lunbound... " >&6; }
if ${ac_cv_lib_unbound_ub_fd+:} false; then :
$as_echo_n "(cached) " >&6
else
ac_check_lib_save_LIBS=$LIBS
@ -11030,27 +11034,27 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
#ifdef __cplusplus
extern "C"
#endif
char ub_ctx_set_event ();
char ub_fd ();
int
main ()
{
return ub_ctx_set_event ();
return ub_fd ();
;
return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :
ac_cv_lib_unbound_ub_ctx_set_event=yes
ac_cv_lib_unbound_ub_fd=yes
else
ac_cv_lib_unbound_ub_ctx_set_event=no
ac_cv_lib_unbound_ub_fd=no
fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_unbound_ub_ctx_set_event" >&5
$as_echo "$ac_cv_lib_unbound_ub_ctx_set_event" >&6; }
if test "x$ac_cv_lib_unbound_ub_ctx_set_event" = xyes; then :
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_unbound_ub_fd" >&5
$as_echo "$ac_cv_lib_unbound_ub_fd" >&6; }
if test "x$ac_cv_lib_unbound_ub_fd" = xyes; then :
cat >>confdefs.h <<_ACEOF
#define HAVE_LIBUNBOUND 1
_ACEOF
@ -11063,7 +11067,7 @@ fi
if test $found_libunbound == 0
then
as_fn_error $? "libunbound is missing or does not incude event code, you may need to patch your libunbound sources and rebuild. See the getdns build instructions" "$LINENO" 5
as_fn_error $? "libunbound is missing." "$LINENO" 5
fi
for ac_prog in doxygen

View File

@ -138,14 +138,14 @@ then
AC_MSG_ERROR([One more dependencies is missing])
fi
# break out libunbound from other libraries since we are currently using a
# break out libunbound from other libraries since we are currently using a
# patch to the sources
found_libunbound=1
AC_MSG_NOTICE([Checking for dependency libunbound])
AC_CHECK_LIB([unbound], [ub_ctx_set_event], [], [found_libunbound=0])
AC_CHECK_LIB([unbound], [ub_fd], [], [found_libunbound=0])
if test $found_libunbound == 0
then
AC_MSG_ERROR([libunbound is missing or does not incude event code, you may need to patch your libunbound sources and rebuild. See the getdns build instructions])
AC_MSG_ERROR([libunbound is missing.])
fi
AC_CHECK_PROGS([DOXYGEN], [doxygen])

View File

@ -33,7 +33,7 @@ CFLAGS=@CFLAGS@ -Wall -I$(srcdir)/ -I/usr/local/include -std=c99
LDFLAGS=@LDFLAGS@ @LIBS@
GETDNS_OBJ=sync.lo context.lo list.lo dict.lo convert.lo general.lo \
hostname.lo service.lo request-internal.lo validate_dnssec.lo \
util-internal.lo getdns_error.lo
util-internal.lo getdns_error.lo extension_libevent.lo
.SUFFIXES: .c .o .a .lo .h

View File

@ -29,17 +29,11 @@
*/
#include "config.h"
#ifdef HAVE_EVENT2_EVENT_H
# include <event2/event.h>
#else
# include <event.h>
#endif
#include <arpa/inet.h>
#include <ldns/ldns.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <unbound-event.h>
#include <unbound.h>
#include "context.h"
@ -275,11 +269,7 @@ getdns_context_create_with_extended_memory_functions(
result->mf.mf.ext.realloc = realloc;
result->mf.mf.ext.free = free;
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->event_base_async = NULL;
result->unbound_ctx = ub_ctx_create();
result->resolution_type_set = 0;
@ -375,10 +365,7 @@ getdns_context_destroy(struct getdns_context *context)
getdns_list_destroy(context->upstream_list);
/* destroy the ub context */
ub_ctx_delete(context->unbound_async);
ub_ctx_delete(context->unbound_sync);
event_base_free(context->event_base_sync);
ub_ctx_delete(context->unbound_ctx);
ldns_rbtree_free(context->outbound_requests);
@ -407,8 +394,7 @@ getdns_context_set_context_update_callback(struct getdns_context *context,
static void
set_ub_string_opt(struct getdns_context *ctx, char *opt, char *value)
{
ub_ctx_set_option(ctx->unbound_sync, opt, value);
ub_ctx_set_option(ctx->unbound_async, opt, value);
ub_ctx_set_option(ctx->unbound_ctx, opt, value);
}
static void
@ -883,27 +869,6 @@ getdns_context_set_memory_functions(struct getdns_context *context,
context, MF_PLAIN, mf.ext.malloc, mf.ext.realloc, mf.ext.free);
} /* getdns_context_set_memory_functions*/
/*
* getdns_extension_set_libevent_base
*
*/
getdns_return_t
getdns_extension_set_libevent_base(struct getdns_context *context,
struct event_base * this_event_base)
{
RETURN_IF_NULL(context, GETDNS_RETURN_BAD_CONTEXT);
if (this_event_base) {
ub_ctx_set_event(context->unbound_async, this_event_base);
context->event_base_async = this_event_base;
} else {
ub_ctx_set_event(context->unbound_async,
context->event_base_sync);
context->event_base_async = NULL;
}
return GETDNS_RETURN_GOOD;
} /* getdns_extension_set_libevent_base */
/* cancel the request */
static void
cancel_dns_req(getdns_dns_req * req)
@ -913,7 +878,7 @@ cancel_dns_req(getdns_dns_req * req)
if (netreq->state == NET_REQ_IN_FLIGHT) {
/* for ev based ub, this should always prevent
* the callback from firing */
ub_cancel(req->unbound, netreq->unbound_id);
ub_cancel(req->context->unbound_ctx, netreq->unbound_id);
netreq->state = NET_REQ_CANCELED;
} else if (netreq->state == NET_REQ_NOT_SENT) {
netreq->state = NET_REQ_CANCELED;
@ -1063,19 +1028,15 @@ getdns_context_prepare_for_resolution(struct getdns_context *context)
return GETDNS_RETURN_BAD_CONTEXT;
}
/* set upstreams */
ub_setup_stub(context->unbound_async, context->upstream_list,
upstream_len);
ub_setup_stub(context->unbound_sync, context->upstream_list,
ub_setup_stub(context->unbound_ctx, context->upstream_list,
upstream_len);
/* use /etc/hosts */
ub_ctx_hosts(context->unbound_sync, NULL);
ub_ctx_hosts(context->unbound_async, NULL);
ub_ctx_hosts(context->unbound_ctx, NULL);
} else if (context->resolution_type == GETDNS_CONTEXT_RECURSING) {
/* set recursive */
/* TODO: use the root servers via root hints file */
ub_ctx_set_fwd(context->unbound_async, NULL);
ub_ctx_set_fwd(context->unbound_sync, NULL);
ub_ctx_set_fwd(context->unbound_ctx, NULL);
} else {
/* bogus? */
@ -1121,6 +1082,23 @@ getdns_context_clear_outbound_request(getdns_dns_req * req)
return GETDNS_RETURN_GOOD;
}
/* get the fd */
int getdns_context_fd(struct getdns_context* context) {
RETURN_IF_NULL(context, -1);
return ub_fd(context->unbound_ctx);
}
/* process async reqs */
getdns_return_t getdns_context_process_async(struct getdns_context* context) {
RETURN_IF_NULL(context, GETDNS_RETURN_BAD_CONTEXT);
if (ub_process(context->unbound_ctx) != 0) {
/* need an async return code? */
return GETDNS_RETURN_GENERIC_ERROR;
}
return GETDNS_RETURN_GOOD;
}
char *
getdns_strdup(const struct mem_funcs *mfs, const char *s)
{

View File

@ -33,7 +33,6 @@
#include <getdns/getdns.h>
#include "types-internal.h"
struct event_base;
struct getdns_dns_req;
struct ldns_rbtree_t;
struct ub_ctx;
@ -63,15 +62,9 @@ struct getdns_context {
struct mem_funcs mf;
struct mem_funcs my_mf;
/* Event loop for sync requests */
struct event_base *event_base_sync;
/* Event loop for async requests */
struct event_base *event_base_async;
/* The underlying unbound contexts that do
* the real work */
struct ub_ctx *unbound_sync;
struct ub_ctx *unbound_async;
struct ub_ctx *unbound_ctx;
/* which resolution type the contexts are configured for
* 0 means nothing set

47
src/extension_libevent.c Normal file
View File

@ -0,0 +1,47 @@
#include "config.h"
#include "context.h"
#ifdef HAVE_EVENT2_EVENT_H
# include <event2/event.h>
#else
# include <event.h>
# define evutil_socket_t int
# define event_free free
# define evtimer_new(b, cb, arg) event_new((b), -1, 0, (cb), (arg))
#endif
#define RETURN_IF_NULL(ptr, code) if(ptr == NULL) return code;
#ifndef HAVE_EVENT2_EVENT_H
static struct event *
event_new(struct event_base *b, evutil_socket_t fd, short ev, void* cb, void *arg)
{
struct event* e = (struct event*)calloc(1, sizeof(struct event));
if(!e) return NULL;
event_set(e, fd, ev, cb, arg);
event_base_set(b, e);
return e;
}
#endif /* no event2 */
void getdns_libevent_cb(evutil_socket_t fd, short what, void *userarg) {
struct getdns_context* context = (struct getdns_context*) userarg;
getdns_context_process_async(context);
}
/*
* getdns_extension_set_libevent_base
*
*/
getdns_return_t
getdns_extension_set_libevent_base(struct getdns_context *context,
struct event_base * this_event_base)
{
RETURN_IF_NULL(context, GETDNS_RETURN_BAD_CONTEXT);
RETURN_IF_NULL(this_event_base, GETDNS_RETURN_INVALID_PARAMETER);
/* TODO: cleanup current extension base */
int fd = getdns_context_fd(context);
struct event *getdns_event = event_new(this_event_base, fd, EV_READ | EV_PERSIST, getdns_libevent_cb, context);
event_add(getdns_event, NULL);
return GETDNS_RETURN_GOOD;
} /* getdns_extension_set_libevent_base */

View File

@ -35,17 +35,8 @@
*/
#include "config.h"
#ifdef HAVE_EVENT2_EVENT_H
# include <event2/event.h>
#else
# include <event.h>
# define evutil_socket_t int
# define event_free free
# define evtimer_new(b, cb, arg) event_new((b), -1, 0, (cb), (arg))
#endif
#include <string.h>
#include <unbound.h>
#include <unbound-event.h>
#include <ldns/ldns.h>
#include "context.h"
#include "types-internal.h"
@ -56,11 +47,10 @@
#define UNUSED_PARAM(x) ((void)(x))
/* declarations */
static void ub_resolve_callback(void *arg, int err, ldns_buffer * result,
int sec, char *bogus);
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_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 handle_network_request_error(getdns_network_req * netreq, int err);
static void handle_dns_request_complete(getdns_dns_req * dns_req);
@ -75,60 +65,48 @@ typedef struct netreq_cb_data
char *bogus;
} netreq_cb_data;
#ifndef HAVE_EVENT2_EVENT_H
static struct event *
event_new(struct event_base *b, evutil_socket_t fd, short ev, void* cb, void *arg)
{
struct event* e = (struct event*)calloc(1, sizeof(struct event));
if(!e) return NULL;
event_set(e, fd, ev, cb, arg);
event_base_set(b, e);
return e;
}
#endif /* no event2 */
// /* cancel, cleanup and send timeout to callback */
// static void
// ub_resolve_timeout(evutil_socket_t fd, short what, void *arg)
// {
// getdns_dns_req *dns_req = (getdns_dns_req *) arg;
// struct getdns_context *context = dns_req->context;
// getdns_transaction_t trans_id = dns_req->trans_id;
// getdns_callback_t cb = dns_req->user_callback;
// void *user_arg = dns_req->user_pointer;
/* cancel, cleanup and send timeout to callback */
static void
ub_resolve_timeout(evutil_socket_t fd, short what, void *arg)
{
getdns_dns_req *dns_req = (getdns_dns_req *) arg;
struct getdns_context *context = dns_req->context;
getdns_transaction_t trans_id = dns_req->trans_id;
getdns_callback_t cb = dns_req->user_callback;
void *user_arg = dns_req->user_pointer;
// /* cancel the req - also clears it from outbound */
// getdns_context_cancel_request(context, trans_id, 0);
/* cancel the req - also clears it from outbound */
getdns_context_cancel_request(context, trans_id, 0);
// /* cleanup */
// dns_req_free(dns_req);
/* cleanup */
dns_req_free(dns_req);
// cb(context, GETDNS_CALLBACK_TIMEOUT, NULL, user_arg, trans_id);
// }
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(evutil_socket_t fd, short what, 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;
event_free(dnsreq->local_cb_timer);
dnsreq->local_cb_timer = NULL;
// /* just call ub_resolve_callback */
// ub_resolve_callback(cb_data->netreq, cb_data->err, cb_data->result,
// cb_data->sec, cb_data->bogus);
/* just call ub_resolve_callback */
ub_resolve_callback(cb_data->netreq, cb_data->err, cb_data->result,
cb_data->sec, cb_data->bogus);
/* cleanup the state */
ldns_buffer_free(cb_data->result);
if (cb_data->bogus) {
free(cb_data->bogus);
}
free(cb_data);
}
// /* cleanup the state */
// ldns_buffer_free(cb_data->result);
// if (cb_data->bogus) {
// free(cb_data->bogus);
// }
// free(cb_data);
// }
/* cleanup and send an error to the user callback */
static void
@ -174,7 +152,7 @@ static int
submit_network_request(getdns_network_req * netreq)
{
getdns_dns_req *dns_req = netreq->owner;
int r = ub_resolve_event(dns_req->unbound,
int r = ub_resolve_async(dns_req->context->unbound_ctx,
dns_req->name,
netreq->request_type,
netreq->request_class,
@ -186,82 +164,84 @@ submit_network_request(getdns_network_req * netreq)
}
static void
ub_resolve_callback(void *arg, int err, ldns_buffer * result, int sec,
char *bogus)
ub_resolve_callback(void* arg, int err, struct ub_result* ub_res)
// ub_resolve_callback(void *arg, int err, ldns_buffer * result, int sec,
// char *bogus)
{
getdns_network_req *netreq = (getdns_network_req *) arg;
getdns_network_req *netreq = (getdns_network_req *) arg;
if (err != 0) {
handle_network_request_error(netreq, err);
return;
}
/* if netreq->state == NET_REQ_NOT_SENT here, that implies
* that ub called us back immediately - probably from a local file.
* 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));
// struct timeval tv;
// 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->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);
// 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);
return;
}
netreq->state = NET_REQ_FINISHED;
if (err) {
handle_network_request_error(netreq, err);
} else {
/* parse */
ldns_status r =
ldns_buffer2pkt_wire(&(netreq->result), result);
if (r != LDNS_STATUS_OK) {
handle_network_request_error(netreq, r);
/* parse */
/* TODO: optimize */
getdns_return_t r = getdns_apply_network_result(netreq, ub_res);
ub_resolve_free(ub_res);
if (r != GETDNS_RETURN_GOOD) {
handle_network_request_error(netreq, err);
} else {
/* is this the last request */
if (!netreq->next) {
/* finished */
handle_dns_request_complete(netreq->owner);
} else {
/* is this the last request */
if (!netreq->next) {
/* finished */
handle_dns_request_complete(netreq->owner);
} else {
/* not finished - update to next request and ship it */
getdns_dns_req *dns_req = netreq->owner;
dns_req->current_req = netreq->next;
submit_network_request(netreq->next);
}
/* not finished - update to next request and ship it */
getdns_dns_req *dns_req = netreq->owner;
dns_req->current_req = netreq->next;
submit_network_request(netreq->next);
}
}
}
getdns_return_t
getdns_general_ub(struct ub_ctx *unbound,
struct event_base *ev_base,
struct getdns_context *context,
getdns_general_ub(struct getdns_context *context,
const char *name,
uint16_t request_type,
struct getdns_dict *extensions,
void *userarg,
getdns_transaction_t * transaction_id, getdns_callback_t callbackfn)
getdns_transaction_t * transaction_id,
getdns_callback_t callbackfn)
{
/* timeout */
struct timeval tv;
@ -279,7 +259,6 @@ getdns_general_ub(struct ub_ctx *unbound,
/* request state */
getdns_dns_req *req = dns_req_new(context,
unbound,
name,
request_type,
extensions);
@ -296,12 +275,13 @@ getdns_general_ub(struct ub_ctx *unbound,
getdns_context_track_outbound_request(req);
/* assign a timeout */
req->ev_base = ev_base;
req->timeout = evtimer_new(ev_base, ub_resolve_timeout, req);
tv.tv_sec = context->timeout / 1000;
tv.tv_usec = (context->timeout % 1000) * 1000;
evtimer_add(req->timeout, &tv);
/* TODO: timeout.. */
// /* assign a timeout */
// req->ev_base = ev_base;
// req->timeout = evtimer_new(ev_base, ub_resolve_timeout, req);
// tv.tv_sec = context->timeout / 1000;
// tv.tv_usec = (context->timeout % 1000) * 1000;
// evtimer_add(req->timeout, &tv);
/* issue the first network req */
@ -329,7 +309,7 @@ getdns_general(struct getdns_context *context,
{
int extcheck = GETDNS_RETURN_GOOD;
if (!context || !context->event_base_async) {
if (!context) {
/* Can't do async without an event loop
* or callback
*/
@ -345,9 +325,7 @@ getdns_general(struct getdns_context *context,
if (extcheck != GETDNS_RETURN_GOOD)
return extcheck;
return getdns_general_ub(context->unbound_async,
context->event_base_async,
context,
return getdns_general_ub(context,
name, request_type, extensions, userarg, transaction_id, callback);
} /* getdns_general */

View File

@ -9,7 +9,7 @@
/*
* 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
@ -40,13 +40,8 @@
/* private inner helper used by sync and async */
struct ub_ctx;
struct event_base;
getdns_return_t
getdns_general_ub(struct ub_ctx *unbound,
struct event_base *ev_base,
struct getdns_context *context,
getdns_general_ub(struct getdns_context *context,
const char *name,
uint16_t request_type,
struct getdns_dict *extensions,

View File

@ -884,4 +884,11 @@ getdns_return_t
getdns_extension_set_libevent_base(struct getdns_context *context,
struct event_base *this_event_base);
/* get the fd */
int getdns_context_fd(struct getdns_context* context);
/* process async reqs */
getdns_return_t getdns_context_process_async(struct getdns_context* context);
#endif /* GETDNS_H */

View File

@ -9,7 +9,7 @@
/*
* 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
@ -34,15 +34,8 @@
*/
#include "config.h"
#ifdef HAVE_EVENT2_EVENT_H
# include <event2/event.h>
#else
# include <event.h>
# define event_free free
#endif
#include "types-internal.h"
#include "util-internal.h"
#include <unbound.h>
void
network_req_free(getdns_network_req * net_req)
@ -103,17 +96,6 @@ dns_req_free(getdns_dns_req * req)
net_req = next;
}
/* cleanup timeout */
if (req->timeout) {
event_del(req->timeout);
event_free(req->timeout);
}
if (req->local_cb_timer) {
event_del(req->local_cb_timer);
event_free(req->local_cb_timer);
}
/* free strduped name */
free(req->name);
@ -123,7 +105,6 @@ dns_req_free(getdns_dns_req * req)
/* create a new dns req to be submitted */
getdns_dns_req *
dns_req_new(struct getdns_context *context,
struct ub_ctx *unbound,
const char *name, uint16_t request_type, struct getdns_dict *extensions)
{
@ -139,14 +120,13 @@ dns_req_new(struct getdns_context *context,
result->name = strdup(name);
result->context = context;
result->unbound = unbound;
result->canceled = 0;
result->current_req = NULL;
result->first_req = NULL;
result->trans_id = ldns_get_random();
result->timeout = NULL;
result->local_cb_timer = NULL;
result->ev_base = NULL;
// result->timeout = NULL;
// result->local_cb_timer = NULL;
// result->ev_base = NULL;
getdns_dict_copy(extensions, &result->extensions);

View File

@ -34,13 +34,8 @@
*/
#include "config.h"
#ifdef HAVE_EVENT2_EVENT_H
# include <event2/event.h>
#else
# include <event.h>
#endif
#include <getdns/getdns.h>
#include <unbound-event.h>
#include <unbound.h>
#include "context.h"
#include "general.h"
#include "types-internal.h"
@ -51,14 +46,28 @@
#define UNUSED_PARAM(x) ((void)(x))
#define RETURN_IF_NULL(ptr, code) if(ptr == NULL) return code;
static void
sync_callback_func(struct getdns_context *context,
uint16_t callback_type,
struct getdns_dict *response,
void *userarg, getdns_transaction_t transaction_id)
{
*((struct getdns_dict **) userarg) = response;
getdns_return_t submit_request_sync(getdns_dns_req* req) {
struct ub_result* ub_res = NULL;
getdns_return_t gr = GETDNS_RETURN_GOOD;
getdns_network_req *netreq = req->first_req;
while (netreq) {
int r = ub_resolve(req->context->unbound_ctx,
req->name,
netreq->request_type,
netreq->request_class,
&ub_res);
if (r != 0) {
return GETDNS_RETURN_GENERIC_ERROR;
}
gr = getdns_apply_network_result(netreq, ub_res);
ub_resolve_free(ub_res);
ub_res = NULL;
if (gr != GETDNS_RETURN_GOOD) {
return gr;
}
netreq = netreq->next;
}
return gr;
}
getdns_return_t
@ -73,12 +82,22 @@ getdns_general_sync(struct getdns_context *context,
RETURN_IF_NULL(response, GETDNS_RETURN_INVALID_PARAMETER);
response_status = validate_extensions(extensions);
if (response_status == GETDNS_RETURN_GOOD) {
response_status = getdns_general_ub(context->unbound_sync,
context->event_base_sync,
context, name, request_type,
extensions, (void *) response, NULL, sync_callback_func);
event_base_dispatch(context->event_base_sync);
/* for each netreq we call ub_ctx_resolve */
/* request state */
getdns_dns_req *req = dns_req_new(context,
name,
request_type,
extensions);
if (!req) {
return GETDNS_RETURN_GENERIC_ERROR;
}
response_status = submit_request_sync(req);
if (response_status != GETDNS_RETURN_GOOD) {
dns_req_free(req);
return response_status;
}
*response = create_getdns_response(req);
dns_req_free(req);
}
return response_status;
}

View File

@ -9,7 +9,7 @@
/*
* 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
@ -99,9 +99,6 @@ struct getdns_context;
/* declarations */
struct getdns_dns_req;
struct getdns_network_req;
struct ub_ctx;
struct event;
struct event_base;
typedef enum network_req_state_enum
{
@ -164,21 +161,9 @@ typedef struct getdns_dns_req
/* first request in list */
struct getdns_network_req *first_req;
/* request timeout event */
struct event *timeout;
/* local callback timer */
struct event *local_cb_timer;
/* event base this req is scheduled on */
struct event_base *ev_base;
/* context that owns the request */
struct getdns_context *context;
/* ub_ctx issuing the request */
struct ub_ctx *unbound;
/* request extensions */
struct getdns_dict *extensions;
@ -246,7 +231,6 @@ getdns_network_req *network_req_new(getdns_dns_req * owner,
/* dns request utils */
getdns_dns_req *dns_req_new(struct getdns_context *context,
struct ub_ctx *unbound,
const char *name, uint16_t request_type, struct getdns_dict *extensions);
void dns_req_free(getdns_dns_req * req);

View File

@ -11,7 +11,7 @@
/*
* 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
@ -41,6 +41,7 @@
#include "list.h"
#include "util-internal.h"
#include "types-internal.h"
#include <unbound.h>
/**
* this is a comprehensive list of extensions and their data types
@ -374,7 +375,7 @@ add_only_addresses(struct getdns_list * addrs, ldns_rr_list * rr_list)
int r = GETDNS_RETURN_GOOD;
size_t i = 0;
size_t item_idx = 0;
r = getdns_list_get_length(addrs, &item_idx);
for (i = 0; r == GETDNS_RETURN_GOOD &&
i < ldns_rr_list_rr_count(rr_list); ++i) {
@ -405,7 +406,7 @@ add_only_addresses(struct getdns_list * addrs, ldns_rr_list * rr_list)
? &IPv4_str_bindata : &IPv6_str_bindata));
r |= getdns_dict_set_bindata(this_address,
GETDNS_STR_ADDRESS_DATA, &rbin);
r |= getdns_list_set_dict(addrs, item_idx++,
r |= getdns_list_set_dict(addrs, item_idx++,
this_address);
getdns_dict_destroy(this_address);
}
@ -418,7 +419,7 @@ create_reply_dict(struct getdns_context *context, getdns_network_req * req,
struct getdns_list * just_addrs)
{
/* turn a packet into this glorious structure
*
*
* { # This is the first reply
* "header": { "id": 23456, "qr": 1, "opcode": 0, ... },
* "question": { "qname": <bindata for "www.example.com">, "qtype": 1, "qclass": 1 },
@ -454,7 +455,7 @@ create_reply_dict(struct getdns_context *context, getdns_network_req * req,
* "canonical_name": <bindata for "www.example.com">,
* "answer_type": GETDNS_NAMETYPE_DNS
* }
*
*
*/
int r = 0;
ldns_pkt *reply = req->result;
@ -677,4 +678,20 @@ validate_extensions(struct getdns_dict * extensions)
return GETDNS_RETURN_GOOD;
} /* validate_extensions */
getdns_return_t getdns_apply_network_result(getdns_network_req* netreq,
struct ub_result* ub_res) {
ldns_buffer *result = ldns_buffer_new(ub_res->answer_len);
if (!result) {
return GETDNS_RETURN_GENERIC_ERROR;
}
ldns_buffer_new_frm_data(result, ub_res->answer_packet, ub_res->answer_len);
ldns_status r =
ldns_buffer2pkt_wire(&(netreq->result), result);
ldns_buffer_free(result);
if (r != LDNS_STATUS_OK) {
return GETDNS_RETURN_GENERIC_ERROR;
}
return GETDNS_RETURN_GOOD;
}
/* util-internal.c */

View File

@ -10,7 +10,7 @@
/*
* 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
@ -41,6 +41,10 @@
#include <ldns/ldns.h>
#include "context.h"
struct ub_result;
struct getdns_network_req;
getdns_return_t getdns_apply_network_result(getdns_network_req* netreq, struct ub_result* result);
/**
* add an item to the tail of a list - note that this was not in the getdns API
* description but the list_set functions seem to be designed to modify an existing