/** update domain to file */ static int do_update(char* domain, char* file) { struct ub_ctx* ctx; struct ub_result* result; int r; printf("updating %s to %s\n", domain, file); ctx = ub_ctx_create(); if(!ctx) fatal("ub_ctx_create failed"); if((r=ub_ctx_add_ta_file(ctx, file))) { printf("%s\n", ub_strerror(r)); fatal("ub_ctx_add_ta_file failed"); } if(!(result=do_lookup(ctx, domain))) { ub_ctx_delete(ctx); return 1; } ub_ctx_delete(ctx); do_print(result, file); ub_resolve_free(result); return 0; }
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; }
int main(int argc, char **argv) { struct ub_ctx* ctx; struct ub_result* result; int retval; int i; struct timeval starttime, endtime; int number = 100000; if (argc > 1) { number = atoi(argv[1]); } /* create context */ ctx = ub_ctx_create(); if(!ctx) { printf("error: could not create unbound context\n"); return 1; } /* read /etc/resolv.conf for DNS proxy settings (from DHCP) */ if( (retval=ub_ctx_resolvconf(ctx, "resolv.conf")) != 0) { printf("error reading resolv.conf: %s. errno says: %s\n", ub_strerror(retval), strerror(errno)); return 1; } /* read /etc/hosts for locally supplied host addresses */ if( (retval=ub_ctx_hosts(ctx, "hosts")) != 0) { printf("error reading hosts: %s. errno says: %s\n", ub_strerror(retval), strerror(errno)); return 1; } /* read public keys for DNSSEC verification */ if( (retval=ub_ctx_add_ta_file(ctx, "keys")) != 0) { printf("error adding keys: %s\n", ub_strerror(retval)); return 1; } /* query for webserver */ retval = ub_resolve(ctx, LOOKUP_NAME, 1, 1, &result); if(retval != 0) { printf("resolve error: %s\n", ub_strerror(retval)); return 1; } /* show first result */ if(result->havedata) printf("The address is %s\n", inet_ntoa(*(struct in_addr*)result->data[0])); /* show security status */ if(!result->secure) { fprintf(stderr, "something very wrong; not validated response returned\n"); exit(1); } fprintf(stderr, "validated response returned\n"); // Note: this is without proper memory freeing fprintf(stderr, "starting %d queries without context....\n", number); gettimeofday(&starttime, NULL); for (i = 0; i < number; i++) { retval = ub_resolve(ctx, LOOKUP_NAME, 1, 1, &result); } gettimeofday(&endtime, NULL); fprintf(stderr, "time elapsed (ms) for %d queries: %d\n", number, timeofday_diff(&starttime, &endtime)); ub_resolve_free(result); ub_ctx_delete(ctx); return 0; }