int unbound_init(struct ub_ctx *dnsctx) { int ugh; /* create unbound resolver context */ dnsctx = ub_ctx_create(); if(!dnsctx) { libreswan_log("error: could not create unbound context\n"); return 0; } DBG(DBG_DNS, ub_ctx_debuglevel(dnsctx,5); DBG_log("unbound context created - setting debug level to 5\n")); /* lookup from /etc/hosts before DNS lookups as people expect that */ if( (ugh=ub_ctx_hosts(dnsctx, "/etc/hosts")) != 0) { libreswan_log("error reading hosts: %s: %s\n", ub_strerror(ugh), strerror(errno)); return 0; } DBG(DBG_DNS, DBG_log("/etc/hosts lookups activated\n")); /* * Use /etc/resolv.conf as forwarding cache - we expect people to reconfigure this * file if they need to work around DHCP DNS obtained servers */ if( (ugh=ub_ctx_resolvconf(dnsctx, "/etc/resolv.conf")) != 0) { libreswan_log("error reading resolv.conf: %s: %s\n", ub_strerror(ugh), strerror(errno)); return 0; } DBG(DBG_DNS, DBG_log("/etc/resolv.conf usage activated\n")); /* add trust anchors to libunbound context - make this configurable later */ DBG(DBG_DNS, DBG_log("Loading root key:%s\n",rootanchor)); ugh = ub_ctx_add_ta(dnsctx, rootanchor); if(ugh != 0) { libreswan_log("error adding the DNSSEC root key: %s: %s\n", ub_strerror(ugh), strerror(errno)); return 0; } /* Enable DLV */ DBG(DBG_DNS, DBG_log("Loading dlv key:%s\n",dlvanchor)); ugh = ub_ctx_set_option(dnsctx, "dlv-anchor:",dlvanchor); if(ugh != 0) { libreswan_log("error adding the DLV key: %s: %s\n", ub_strerror(ugh), strerror(errno)); return 0; } return 1; }
bool unbound_init(struct ub_ctx *dnsctx) { int ugh; /* create unbound resolver context */ dnsctx = ub_ctx_create(); if (!dnsctx) { libreswan_log("error: could not create unbound context"); return FALSE; } DBG(DBG_DNS, ub_ctx_debuglevel(dnsctx, 5); DBG_log("unbound context created - setting debug level to 5"); );
static void unbound_ctx_config(bool do_dnssec, const char *rootfile, const char *trusted) { int ugh; if (DBGP(DBG_DNS)) { ub_ctx_debuglevel(dns_ctx, 5); DBG_log("unbound context created - setting debug level to 5"); }; /* lookup from /etc/hosts before DNS lookups as people expect that */ ugh = ub_ctx_hosts(dns_ctx, "/etc/hosts"); if (ugh != 0) { loglog(RC_LOG_SERIOUS, "error reading hosts: %s: %s", ub_strerror(ugh), strerror(errno)); } else { DBG(DBG_DNS, DBG_log("/etc/hosts lookups activated")); } /* * Use /etc/resolv.conf as forwarding cache - we expect people * to reconfigure this file if they need to work around DHCP DNS * obtained servers. */ /* * ??? ub_ctx_resolvconf is not currently documented to set errno. * Private communications with W.C.A. Wijngaards 2017 October: * "Is errno is meaningful after a failed call to libunbound?" * "Yes it is. Specifically for the error-to-read-file case. * Not other cases (eg. socket errors happen too far away in the code)." */ errno = 0; ugh = ub_ctx_resolvconf(dns_ctx, "/etc/resolv.conf"); if (ugh != 0) { int e = errno; /* protect value from ub_strerror */ loglog(RC_LOG_SERIOUS, "error reading /etc/resolv.conf: %s: [errno: %s]", ub_strerror(ugh), strerror(e)); } else { DBG(DBG_DNS, DBG_log("/etc/resolv.conf usage activated")); } if (!do_dnssec) { /* No DNSSEC - nothing more to configure */ DBG(DBG_DNS, DBG_log("dnssec validation disabled by configuration")); } if (rootfile == NULL) { if (trusted != NULL) { loglog(RC_LOG_SERIOUS, "dnssec-enable=yes but no dnssec-rootkey-file or trust anchors specified."); loglog(RC_LOG_SERIOUS, "WARNING: DNSSEC validation disabled"); } } else { DBG(DBG_DNS, DBG_log("Loading dnssec root key from:%s", rootfile)); /* the cast is there for unbound < 1.4.12 */ /* ??? ub_ctx_add_ta_autr is not documented to set errno */ errno = 0; ugh = ub_ctx_add_ta_autr(dns_ctx, (char *) rootfile); if (ugh != 0) { int e = errno; /* protect value from ub_strerror */ loglog(RC_LOG_SERIOUS, "error adding dnssec root key: %s [errno: %s]", ub_strerror(ugh), strerror(e)); loglog(RC_LOG_SERIOUS, "WARNING: DNSSEC validation likely broken!"); } } if (trusted == NULL) { DBG(DBG_DNS,DBG_log("No additional dnssec trust anchors defined via dnssec-trusted= option")); } else { glob_t globbuf; char **fnp; int r = glob(trusted, GLOB_ERR, globugh_ta, &globbuf); switch (r) { case 0: /* success */ for (fnp = globbuf.gl_pathv; fnp != NULL && *fnp != NULL; fnp++) { ugh = ub_ctx_add_ta_file(dns_ctx, *fnp); if (ugh != 0) { loglog(RC_LOG_SERIOUS, "Ignored trusted key file %s: %s", *fnp, ub_strerror(ugh)); } else { DBG(DBG_DNS, DBG_log("Added contents of trusted key file %s to unbound resolver context", *fnp)); } } break; case GLOB_NOSPACE: loglog(RC_LOG_SERIOUS, "out of space processing dnssec-trusted= argument: %s", trusted); break; case GLOB_ABORTED: /* already logged by globugh_ta */ break; case GLOB_NOMATCH: loglog(RC_LOG_SERIOUS, "no trust anchor files matched '%s'", trusted); break; default: loglog(RC_LOG_SERIOUS, "trusted key file '%s': unknown glob error %d", trusted, r); break; } globfree(&globbuf); } }
/** Main routine for checkconf */ int main(int argc, char* argv[]) { int c; char* qclass = NULL; char* qtype = NULL; struct ub_ctx* ctx = NULL; int debuglevel = 0; ctx = ub_ctx_create(); if(!ctx) { fprintf(stderr, "error: out of memory\n"); exit(1); } /* parse the options */ while( (c=getopt(argc, argv, "46F:c:df:hrt:vy:C:")) != -1) { switch(c) { case '4': check_ub_res(ub_ctx_set_option(ctx, "do-ip6:", "no")); break; case '6': check_ub_res(ub_ctx_set_option(ctx, "do-ip4:", "no")); break; case 'c': qclass = optarg; break; case 'C': check_ub_res(ub_ctx_config(ctx, optarg)); break; case 'd': debuglevel++; if(debuglevel < 2) debuglevel = 2; /* at least VERB_DETAIL */ break; case 'r': check_ub_res(ub_ctx_resolvconf(ctx, "/etc/resolv.conf")); break; case 't': qtype = optarg; break; case 'v': verb++; break; case 'y': check_ub_res(ub_ctx_add_ta(ctx, optarg)); break; case 'f': check_ub_res(ub_ctx_add_ta_file(ctx, optarg)); break; case 'F': check_ub_res(ub_ctx_trustedkeys(ctx, optarg)); break; case '?': case 'h': default: usage(); } } if(debuglevel != 0) /* set after possible -C options */ check_ub_res(ub_ctx_debuglevel(ctx, debuglevel)); if(ub_ctx_get_option(ctx, "use-syslog", &optarg) == 0) { if(strcmp(optarg, "yes") == 0) /* disable use-syslog */ check_ub_res(ub_ctx_set_option(ctx, "use-syslog:", "no")); free(optarg); } argc -= optind; argv += optind; if(argc != 1) usage(); #ifdef HAVE_NSS if(NSS_NoDB_Init(".") != SECSuccess) { fprintf(stderr, "could not init NSS\n"); return 1; } #endif lookup(ctx, argv[0], qtype, qclass); return 0; }
/** main program for asynclook */ int main(int argc, char** argv) { int c; struct ub_ctx* ctx; struct lookinfo* lookups; int i, r, cancel=0, blocking=0, ext=0; /* init log now because solaris thr_key_create() is not threadsafe */ log_init(0,0,0); /* lock debug start (if any) */ checklock_start(); /* create context */ ctx = ub_ctx_create(); if(!ctx) { printf("could not create context, %s\n", strerror(errno)); return 1; } /* command line options */ if(argc == 1) { usage(argv); } while( (c=getopt(argc, argv, "bcdf:hH:r:tx")) != -1) { switch(c) { case 'd': r = ub_ctx_debuglevel(ctx, 3); checkerr("ub_ctx_debuglevel", r); break; case 't': r = ub_ctx_async(ctx, 1); checkerr("ub_ctx_async", r); break; case 'c': cancel = 1; break; case 'b': blocking = 1; break; case 'r': r = ub_ctx_resolvconf(ctx, optarg); if(r != 0) { printf("ub_ctx_resolvconf " "error: %s : %s\n", ub_strerror(r), strerror(errno)); return 1; } break; case 'H': r = ub_ctx_hosts(ctx, optarg); if(r != 0) { printf("ub_ctx_hosts " "error: %s : %s\n", ub_strerror(r), strerror(errno)); return 1; } break; case 'f': r = ub_ctx_set_fwd(ctx, optarg); checkerr("ub_ctx_set_fwd", r); break; case 'x': ext = 1; break; case 'h': case '?': default: usage(argv); } } argc -= optind; argv += optind; if(ext) return ext_test(ctx, argc, argv); /* allocate array for results. */ lookups = (struct lookinfo*)calloc((size_t)argc, sizeof(struct lookinfo)); if(!lookups) { printf("out of memory\n"); return 1; } /* perform asynchronous calls */ num_wait = argc; for(i=0; i<argc; i++) { lookups[i].name = argv[i]; if(blocking) { fprintf(stderr, "lookup %s\n", argv[i]); r = ub_resolve(ctx, argv[i], LDNS_RR_TYPE_A, LDNS_RR_CLASS_IN, &lookups[i].result); checkerr("ub_resolve", r); } else { fprintf(stderr, "start async lookup %s\n", argv[i]); r = ub_resolve_async(ctx, argv[i], LDNS_RR_TYPE_A, LDNS_RR_CLASS_IN, &lookups[i], &lookup_is_done, &lookups[i].async_id); checkerr("ub_resolve_async", r); } } if(blocking) num_wait = 0; else if(cancel) { for(i=0; i<argc; i++) { fprintf(stderr, "cancel %s\n", argv[i]); r = ub_cancel(ctx, lookups[i].async_id); if(r != UB_NOID) checkerr("ub_cancel", r); } num_wait = 0; } /* wait while the hostnames are looked up. Do something useful here */ if(num_wait > 0) for(i=0; i<1000; i++) { usleep(100000); fprintf(stderr, "%g seconds passed\n", 0.1*(double)i); r = ub_process(ctx); checkerr("ub_process", r); if(num_wait == 0) break; } if(i>=999) { printf("timed out\n"); return 0; } printf("lookup complete\n"); /* print lookup results */ for(i=0; i<argc; i++) { print_result(&lookups[i]); ub_resolve_free(lookups[i].result); } ub_ctx_delete(ctx); free(lookups); checklock_stop(); return 0; }
static int mod_instantiate(void *instance, CONF_SECTION *conf) { rlm_unbound_t *inst = instance; int res; char *optval; fr_log_dst_t log_dst; int log_level; int log_fd = -1; char k[64]; /* To silence const warns until newer unbound in distros */ /* * @todo - move this to the thread-instantiate function */ inst->el = fr_global_event_list(); inst->log_pipe_stream[0] = NULL; inst->log_pipe_stream[1] = NULL; inst->log_fd = -1; inst->log_pipe_in_use = false; inst->ub = ub_ctx_create(); if (!inst->ub) { cf_log_err(conf, "ub_ctx_create failed"); return -1; } /* * Note unbound threads WILL happen with -s option, if it matters. * We cannot tell from here whether that option is in effect. */ res = ub_ctx_async(inst->ub, 1); if (res) goto error; /* Glean some default settings to match the main server. */ /* TODO: debug_level can be changed at runtime. */ /* TODO: log until fork when stdout or stderr and !rad_debug_lvl. */ log_level = 0; if (rad_debug_lvl > 0) { log_level = rad_debug_lvl; } else if (main_config->debug_level > 0) { log_level = main_config->debug_level; } switch (log_level) { /* TODO: This will need some tweaking */ case 0: case 1: break; case 2: log_level = 1; break; case 3: case 4: log_level = 2; /* mid-to-heavy levels of output */ break; case 5: case 6: case 7: case 8: log_level = 3; /* Pretty crazy amounts of output */ break; default: log_level = 4; /* Insane amounts of output including crypts */ break; } res = ub_ctx_debuglevel(inst->ub, log_level); if (res) goto error; switch (default_log.dst) { case L_DST_STDOUT: if (!rad_debug_lvl) { log_dst = L_DST_NULL; break; } log_dst = L_DST_STDOUT; log_fd = dup(STDOUT_FILENO); break; case L_DST_STDERR: if (!rad_debug_lvl) { log_dst = L_DST_NULL; break; } log_dst = L_DST_STDOUT; log_fd = dup(STDERR_FILENO); break; case L_DST_FILES: if (main_config->log_file) { char *log_file; strcpy(k, "logfile:"); /* 3rd argument isn't const'd in libunbounds API */ memcpy(&log_file, &main_config->log_file, sizeof(log_file)); res = ub_ctx_set_option(inst->ub, k, log_file); if (res) { goto error; } log_dst = L_DST_FILES; break; } /* FALL-THROUGH */ case L_DST_NULL: log_dst = L_DST_NULL; break; default: log_dst = L_DST_SYSLOG; break; } /* Now load the config file, which can override gleaned settings. */ { char *file; memcpy(&file, &inst->filename, sizeof(file)); res = ub_ctx_config(inst->ub, file); if (res) goto error; } /* * Check if the config file tried to use syslog. Unbound * does not share syslog gracefully. */ strcpy(k, "use-syslog"); res = ub_ctx_get_option(inst->ub, k, &optval); if (res || !optval) goto error; if (!strcmp(optval, "yes")) { char v[3]; free(optval); WARN("Overriding syslog settings"); strcpy(k, "use-syslog:"); strcpy(v, "no"); res = ub_ctx_set_option(inst->ub, k, v); if (res) goto error; if (log_dst == L_DST_FILES) { char *log_file; /* Reinstate the log file name JIC */ strcpy(k, "logfile:"); /* 3rd argument isn't const'd in libunbounds API */ memcpy(&log_file, &main_config->log_file, sizeof(log_file)); res = ub_ctx_set_option(inst->ub, k, log_file); if (res) goto error; } } else { if (optval) free(optval); strcpy(k, "logfile"); res = ub_ctx_get_option(inst->ub, k, &optval); if (res) goto error; if (optval && strlen(optval)) { log_dst = L_DST_FILES; /* * We open log_fd early in the process, * so that libunbound doesn't close * stdout / stderr on us (grrr, stupid * software). But if the config say to * use files, we now have to close the * dup'd FD. */ if (log_fd >= 0) { close(log_fd); log_fd = -1; } } else if (!rad_debug_lvl) { log_dst = L_DST_NULL; } if (optval) free(optval); } switch (log_dst) { case L_DST_STDOUT: /* * We have an fd to log to. And we've already attempted to * dup it so libunbound doesn't close it on us. */ if (log_fd == -1) { cf_log_err(conf, "Could not dup fd"); goto error_nores; } inst->log_stream = fdopen(log_fd, "w"); if (!inst->log_stream) { cf_log_err(conf, "error setting up log stream"); goto error_nores; } res = ub_ctx_debugout(inst->ub, inst->log_stream); if (res) goto error; break; case L_DST_FILES: /* We gave libunbound a filename. It is on its own now. */ break; case L_DST_NULL: /* We tell libunbound not to log at all. */ res = ub_ctx_debugout(inst->ub, NULL); if (res) goto error; break; case L_DST_SYSLOG: /* * Currently this wreaks havoc when running threaded, so just * turn logging off until that gets figured out. */ res = ub_ctx_debugout(inst->ub, NULL); if (res) goto error; break; default: break; } /* * Now we need to finalize the context. * * There's no clean API to just finalize the context made public * in libunbound. But we can trick it by trying to delete data * which as it happens fails quickly and quietly even though the * data did not exist. */ strcpy(k, "notar33lsite.foo123.nottld A 127.0.0.1"); ub_ctx_data_remove(inst->ub, k); inst->log_fd = ub_fd(inst->ub); if (inst->log_fd >= 0) { if (fr_event_fd_insert(inst, inst->el, inst->log_fd, ub_fd_handler, NULL, NULL, inst) < 0) { cf_log_err(conf, "could not insert async fd"); inst->log_fd = -1; goto error_nores; } } return 0; error: cf_log_err(conf, "%s", ub_strerror(res)); error_nores: if (log_fd > -1) close(log_fd); return -1; }