static void nss_ubdns_load_resolvconf(void) { struct stat sb; if (stat(NSS_UBDNS_RESOLVCONF, &sb) == 0) { ub_ctx_resolvconf(ctx, NSS_UBDNS_RESOLVCONF); } else { ub_ctx_set_fwd(ctx, "127.0.0.1"); } }
DNSResolver::DNSResolver() : m_data(new DNSResolverData()) { int use_dns_public = 0; const char* dns_public_addr = "8.8.4.4"; if (auto res = getenv("DNS_PUBLIC")) { std::string dns_public(res); // TODO: could allow parsing of IP and protocol: e.g. DNS_PUBLIC=tcp:8.8.8.8 if (dns_public == "tcp") { LOG_PRINT_L0("Using public DNS server: " << dns_public_addr << " (TCP)"); use_dns_public = 1; } } // init libunbound context m_data->m_ub_context = ub_ctx_create(); if (use_dns_public) { ub_ctx_set_fwd(m_data->m_ub_context, dns_public_addr); ub_ctx_set_option(m_data->m_ub_context, "do-udp:", "no"); ub_ctx_set_option(m_data->m_ub_context, "do-tcp:", "yes"); } else { // look for "/etc/resolv.conf" and "/etc/hosts" or platform equivalent ub_ctx_resolvconf(m_data->m_ub_context, NULL); ub_ctx_hosts(m_data->m_ub_context, NULL); } #ifdef DEVELOPER_LIBUNBOUND_OLD #pragma message "Using the work around for old libunbound" { // work around for bug https://www.nlnetlabs.nl/bugs-script/show_bug.cgi?id=515 needed for it to compile on e.g. Debian 7 char * ds_copy = NULL; // this will be the writable copy of string that bugged version of libunbound requires try { char * ds_copy = strdup( ::get_builtin_ds() ); ub_ctx_add_ta(m_data->m_ub_context, ds_copy); } catch(...) { // probably not needed but to work correctly in every case... if (ds_copy) { free(ds_copy); ds_copy=NULL; } // for the strdup throw ; } if (ds_copy) { free(ds_copy); ds_copy=NULL; } // for the strdup } #else // normal version for fixed libunbound ub_ctx_add_ta(m_data->m_ub_context, ::get_builtin_ds() ); #endif }
DNSResolver::DNSResolver() : m_data(new DNSResolverData()) { int use_dns_public = 0; std::vector<std::string> dns_public_addr; if (auto res = getenv("DNS_PUBLIC")) { dns_public_addr = tools::dns_utils::parse_dns_public(res); if (!dns_public_addr.empty()) { MGINFO("Using public DNS server(s): " << boost::join(dns_public_addr, ", ") << " (TCP)"); use_dns_public = 1; } else { MERROR("Failed to parse DNS_PUBLIC"); } } // init libunbound context m_data->m_ub_context = ub_ctx_create(); if (use_dns_public) { for (const auto &ip: dns_public_addr) ub_ctx_set_fwd(m_data->m_ub_context, string_copy(ip.c_str())); ub_ctx_set_option(m_data->m_ub_context, string_copy("do-udp:"), string_copy("no")); ub_ctx_set_option(m_data->m_ub_context, string_copy("do-tcp:"), string_copy("yes")); } else { // look for "/etc/resolv.conf" and "/etc/hosts" or platform equivalent ub_ctx_resolvconf(m_data->m_ub_context, NULL); ub_ctx_hosts(m_data->m_ub_context, NULL); } const char * const *ds = ::get_builtin_ds(); while (*ds) { MINFO("adding trust anchor: " << *ds); ub_ctx_add_ta(m_data->m_ub_context, string_copy(*ds++)); } }
int ub_ctx_resolvconf(struct ub_ctx* ctx, char* fname) { FILE* in; int numserv = 0; char buf[1024]; char* parse, *addr; int r; if(fname == NULL) { #if !defined(UB_ON_WINDOWS) || !defined(HAVE_WINDOWS_H) fname = "/etc/resolv.conf"; #else FIXED_INFO *info; ULONG buflen = sizeof(*info); IP_ADDR_STRING *ptr; info = (FIXED_INFO *) malloc(sizeof (FIXED_INFO)); if (info == NULL) return UB_READFILE; if (GetNetworkParams(info, &buflen) == ERROR_BUFFER_OVERFLOW) { free(info); info = (FIXED_INFO *) malloc(buflen); if (info == NULL) return UB_READFILE; } if (GetNetworkParams(info, &buflen) == NO_ERROR) { int retval=0; ptr = &(info->DnsServerList); while (ptr) { numserv++; if((retval=ub_ctx_set_fwd(ctx, ptr->IpAddress.String)!=0)) { free(info); return retval; } ptr = ptr->Next; } free(info); if (numserv==0) return UB_READFILE; return UB_NOERROR; } free(info); return UB_READFILE; #endif /* WINDOWS */ } in = fopen(fname, "r"); if(!in) { /* error in errno! perror(fname) */ return UB_READFILE; } while(fgets(buf, (int)sizeof(buf), in)) { buf[sizeof(buf)-1] = 0; parse=buf; while(*parse == ' ' || *parse == '\t') parse++; if(strncmp(parse, "nameserver", 10) == 0) { numserv++; parse += 10; /* skip 'nameserver' */ /* skip whitespace */ while(*parse == ' ' || *parse == '\t') parse++; addr = parse; /* skip [0-9a-fA-F.:]*, i.e. IP4 and IP6 address */ while(isxdigit(*parse) || *parse=='.' || *parse==':') parse++; /* terminate after the address, remove newline */ *parse = 0; if((r = ub_ctx_set_fwd(ctx, addr)) != UB_NOERROR) { fclose(in); return r; } } } fclose(in); if(numserv == 0) { /* from resolv.conf(5) if none given, use localhost */ return ub_ctx_set_fwd(ctx, "127.0.0.1"); } return UB_NOERROR; }
/** 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; }