diff options
Diffstat (limited to 'external/unbound/libunbound/libunbound.c')
-rw-r--r-- | external/unbound/libunbound/libunbound.c | 143 |
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; } |