aboutsummaryrefslogtreecommitdiff
path: root/external/unbound/libunbound/libunbound.c
diff options
context:
space:
mode:
Diffstat (limited to 'external/unbound/libunbound/libunbound.c')
-rw-r--r--external/unbound/libunbound/libunbound.c143
1 files changed, 132 insertions, 11 deletions
diff --git a/external/unbound/libunbound/libunbound.c b/external/unbound/libunbound/libunbound.c
index 17f50e8e8..eaa31c71c 100644
--- a/external/unbound/libunbound/libunbound.c
+++ b/external/unbound/libunbound/libunbound.c
@@ -57,6 +57,7 @@
#include "util/random.h"
#include "util/net_help.h"
#include "util/tube.h"
+#include "util/ub_event.h"
#include "services/modstack.h"
#include "services/localzone.h"
#include "services/cache/infra.h"
@@ -131,6 +132,15 @@ static struct ub_ctx* ub_ctx_create_nopipe(void)
errno = ENOMEM;
return NULL;
}
+ /* init edns_known_options */
+ if(!edns_known_options_init(ctx->env)) {
+ config_delete(ctx->env->cfg);
+ free(ctx->env);
+ ub_randfree(ctx->seed_rnd);
+ free(ctx);
+ errno = ENOMEM;
+ return NULL;
+ }
ctx->env->alloc = &ctx->superalloc;
ctx->env->worker = NULL;
ctx->env->need_to_validate = 0;
@@ -150,6 +160,7 @@ ub_ctx_create(void)
ub_randfree(ctx->seed_rnd);
config_delete(ctx->env->cfg);
modstack_desetup(&ctx->mods, ctx->env);
+ edns_known_options_delete(ctx->env);
free(ctx->env);
free(ctx);
errno = e;
@@ -161,6 +172,7 @@ ub_ctx_create(void)
ub_randfree(ctx->seed_rnd);
config_delete(ctx->env->cfg);
modstack_desetup(&ctx->mods, ctx->env);
+ edns_known_options_delete(ctx->env);
free(ctx->env);
free(ctx);
errno = e;
@@ -170,6 +182,20 @@ ub_ctx_create(void)
}
struct ub_ctx*
+ub_ctx_create_ub_event(struct ub_event_base* ueb)
+{
+ struct ub_ctx* ctx = ub_ctx_create_nopipe();
+ if(!ctx)
+ return NULL;
+ /* no pipes, but we have the locks to make sure everything works */
+ ctx->created_bg = 0;
+ ctx->dothread = 1; /* the processing is in the same process,
+ makes ub_cancel and ub_ctx_delete do the right thing */
+ ctx->event_base = ueb;
+ return ctx;
+}
+
+struct ub_ctx*
ub_ctx_create_event(struct event_base* eb)
{
struct ub_ctx* ctx = ub_ctx_create_nopipe();
@@ -179,13 +205,17 @@ ub_ctx_create_event(struct event_base* eb)
ctx->created_bg = 0;
ctx->dothread = 1; /* the processing is in the same process,
makes ub_cancel and ub_ctx_delete do the right thing */
- ctx->event_base = eb;
+ ctx->event_base = ub_libevent_event_base(eb);
+ if (!ctx->event_base) {
+ ub_ctx_delete(ctx);
+ return NULL;
+ }
return ctx;
}
/** delete q */
static void
-delq(rbnode_t* n, void* ATTR_UNUSED(arg))
+delq(rbnode_type* n, void* ATTR_UNUSED(arg))
{
struct ctx_query* q = (struct ctx_query*)n;
context_query_delete(q);
@@ -279,6 +309,7 @@ ub_ctx_delete(struct ub_ctx* ctx)
rrset_cache_delete(ctx->env->rrset_cache);
infra_delete(ctx->env->infra_cache);
config_delete(ctx->env->cfg);
+ edns_known_options_delete(ctx->env);
free(ctx->env);
}
ub_randfree(ctx->seed_rnd);
@@ -468,7 +499,7 @@ ub_fd(struct ub_ctx* ctx)
/** process answer from bg worker */
static int
process_answer_detail(struct ub_ctx* ctx, uint8_t* msg, uint32_t len,
- ub_callback_t* cb, void** cbarg, int* err,
+ ub_callback_type* cb, void** cbarg, int* err,
struct ub_result** res)
{
struct ctx_query* q;
@@ -535,7 +566,7 @@ static int
process_answer(struct ub_ctx* ctx, uint8_t* msg, uint32_t len)
{
int err;
- ub_callback_t cb;
+ ub_callback_type cb;
void* cbarg;
struct ub_result* res;
int r;
@@ -578,7 +609,7 @@ int
ub_wait(struct ub_ctx* ctx)
{
int err;
- ub_callback_t cb;
+ ub_callback_type cb;
void* cbarg;
struct ub_result* res;
int r;
@@ -674,7 +705,8 @@ ub_resolve(struct ub_ctx* ctx, const char* name, int rrtype,
int
ub_resolve_event(struct ub_ctx* ctx, const char* name, int rrtype,
- int rrclass, void* mydata, ub_event_callback_t callback, int* async_id)
+ int rrclass, void* mydata, ub_event_callback_type callback,
+ int* async_id)
{
struct ctx_query* q;
int r;
@@ -698,8 +730,11 @@ ub_resolve_event(struct ub_ctx* ctx, const char* name, int rrtype,
}
}
+ /* set time in case answer comes from cache */
+ ub_comm_base_now(ctx->event_worker->base);
+
/* create new ctx_query and attempt to add to the list */
- q = context_new(ctx, name, rrtype, rrclass, (ub_callback_t)callback,
+ q = context_new(ctx, name, rrtype, rrclass, (ub_callback_type)callback,
mydata);
if(!q)
return UB_NOMEM;
@@ -713,7 +748,7 @@ ub_resolve_event(struct ub_ctx* ctx, const char* name, int rrtype,
int
ub_resolve_async(struct ub_ctx* ctx, const char* name, int rrtype,
- int rrclass, void* mydata, ub_callback_t callback, int* async_id)
+ int rrclass, void* mydata, ub_callback_type callback, int* async_id)
{
struct ctx_query* q;
uint8_t* msg = NULL;
@@ -924,6 +959,88 @@ ub_ctx_set_fwd(struct ub_ctx* ctx, const char* addr)
return UB_NOERROR;
}
+int ub_ctx_set_stub(struct ub_ctx* ctx, const char* zone, const char* addr,
+ int isprime)
+{
+ char* a;
+ struct config_stub **prev, *elem;
+
+ /* check syntax for zone name */
+ if(zone) {
+ uint8_t* nm;
+ int nmlabs;
+ size_t nmlen;
+ if(!parse_dname(zone, &nm, &nmlen, &nmlabs)) {
+ errno=EINVAL;
+ return UB_SYNTAX;
+ }
+ free(nm);
+ } else {
+ zone = ".";
+ }
+
+ /* check syntax for addr (if not NULL) */
+ if(addr) {
+ struct sockaddr_storage storage;
+ socklen_t stlen;
+ if(!extstrtoaddr(addr, &storage, &stlen)) {
+ errno=EINVAL;
+ return UB_SYNTAX;
+ }
+ }
+
+ lock_basic_lock(&ctx->cfglock);
+ if(ctx->finalized) {
+ lock_basic_unlock(&ctx->cfglock);
+ errno=EINVAL;
+ return UB_AFTERFINAL;
+ }
+
+ /* arguments all right, now find or add the stub */
+ prev = &ctx->env->cfg->stubs;
+ elem = cfg_stub_find(&prev, zone);
+ if(!elem && !addr) {
+ /* not found and we want to delete, nothing to do */
+ lock_basic_unlock(&ctx->cfglock);
+ return UB_NOERROR;
+ } else if(elem && !addr) {
+ /* found, and we want to delete */
+ *prev = elem->next;
+ config_delstub(elem);
+ lock_basic_unlock(&ctx->cfglock);
+ return UB_NOERROR;
+ } else if(!elem) {
+ /* not found, create the stub entry */
+ elem=(struct config_stub*)calloc(1, sizeof(struct config_stub));
+ if(elem) elem->name = strdup(zone);
+ if(!elem || !elem->name) {
+ free(elem);
+ lock_basic_unlock(&ctx->cfglock);
+ errno = ENOMEM;
+ return UB_NOMEM;
+ }
+ elem->next = ctx->env->cfg->stubs;
+ ctx->env->cfg->stubs = elem;
+ }
+
+ /* add the address to the list and set settings */
+ elem->isprime = isprime;
+ a = strdup(addr);
+ if(!a) {
+ lock_basic_unlock(&ctx->cfglock);
+ errno = ENOMEM;
+ return UB_NOMEM;
+ }
+ if(!cfg_strlist_insert(&elem->addrs, a)) {
+ lock_basic_unlock(&ctx->cfglock);
+ free(a);
+ errno = ENOMEM;
+ return UB_NOMEM;
+ }
+ lock_basic_unlock(&ctx->cfglock);
+ return UB_NOERROR;
+}
+
int
ub_ctx_resolvconf(struct ub_ctx* ctx, const char* fname)
{
@@ -1241,10 +1358,12 @@ const char* ub_version(void)
int
ub_ctx_set_event(struct ub_ctx* ctx, struct event_base* base) {
+ struct ub_event_base* new_base;
+
if (!ctx || !ctx->event_base || !base) {
return UB_INITFAIL;
}
- if (ctx->event_base == base) {
+ if (ub_libevent_get_event_base(ctx->event_base) == base) {
/* already set */
return UB_NOERROR;
}
@@ -1253,9 +1372,11 @@ ub_ctx_set_event(struct ub_ctx* ctx, struct event_base* base) {
/* destroy the current worker - safe to pass in NULL */
libworker_delete_event(ctx->event_worker);
ctx->event_worker = NULL;
- ctx->event_base = base;
+ new_base = ub_libevent_event_base(base);
+ if (new_base)
+ ctx->event_base = new_base;
ctx->created_bg = 0;
ctx->dothread = 1;
lock_basic_unlock(&ctx->cfglock);
- return UB_NOERROR;
+ return new_base ? UB_NOERROR : UB_INITFAIL;
}