static void dns_set_srch_internal(struct dns_ctx *ctx, char *srch) { dns_add_srch(ctx, NULL); for(srch = strtok(srch, space); srch; srch = strtok(NULL, space)) dns_add_srch(ctx, srch); }
static int dns_init_resolvconf(struct dns_ctx *ctx) { char *v; char buf[4097]; /* this buffer is used to hold /etc/resolv.conf */ int has_srch = 0; /* read resolv.conf... */ { int fd = open("/etc/resolv.conf", O_RDONLY); if (fd >= 0) { int l = read(fd, buf, sizeof(buf) - 1); close(fd); buf[l < 0 ? 0 : l] = '\0'; } else buf[0] = '\0'; } if (buf[0]) { /* ...and parse it */ char *line, *nextline; line = buf; do { nextline = strchr(line, '\n'); if (nextline) *nextline++ = '\0'; v = line; while(*v && !ISSPACE(*v)) ++v; if (!*v) continue; *v++ = '\0'; while(ISSPACE(*v)) ++v; if (!*v) continue; if (strcmp(line, "domain") == 0) { dns_set_srch_internal(ctx, strtok(v, space)); has_srch = 1; } else if (strcmp(line, "search") == 0) { dns_set_srch_internal(ctx, v); has_srch = 1; } else if (strcmp(line, "nameserver") == 0) dns_add_serv(ctx, strtok(v, space)); else if (strcmp(line, "options") == 0) dns_set_opts(ctx, v); } while((line = nextline) != NULL); } buf[sizeof(buf)-1] = '\0'; #if TARGET_OS_IPHONE // SOLUTION FOUND: // http://iphone.galloway.me.uk/2009/11/iphone-dns-servers/ // ORIGINAL CODE EXAMPLE: // // #if TARGET_OS_IPHONE // #include <resolv.h> // #endif // // ... // // #if TARGET_OS_IPHONE // // XXX: On the iPhone we need to get the DNS servers using resolv.h magic // if ((_res.options & RES_INIT) == 0) res_init(); // channel->nservers = _res.nscount; // channel->servers = malloc(channel->nservers * sizeof(struct server_state)); // memset(channel->servers, '\0', channel->nservers * sizeof(struct server_state)); // // int i; // for (i = 0; i < channel->nservers; i++) // { // memcpy(&channel->servers[i].addr, &_res.nsaddr_list[i].sin_addr, sizeof(struct in_addr)); // } // #endif if ((_res.options & RES_INIT) == 0) res_init(); int i; for (i = 0; i < _res.nscount; i++) { struct sockaddr_in address; memset(&address, 0, sizeof(address)); address.sin_family = AF_INET; address.sin_addr = _res.nsaddr_list[i].sin_addr; // loopback is a special case since it could be stored as ::1 in IPv6 dns_add_serv_s(ctx, (struct sockaddr *)&address); } #endif //TARGET_OS_IPHONE /* get list of nameservers from env. vars. */ if ((v = getenv("NSCACHEIP")) != NULL || (v = getenv("NAMESERVERS")) != NULL) { strncpy(buf, v, sizeof(buf) - 1); dns_set_serv_internal(ctx, buf); } /* if $LOCALDOMAIN is set, use it for search list */ if ((v = getenv("LOCALDOMAIN")) != NULL) { strncpy(buf, v, sizeof(buf) - 1); dns_set_srch_internal(ctx, buf); has_srch = 1; } if ((v = getenv("RES_OPTIONS")) != NULL) dns_set_opts(ctx, v); /* if still no search list, use local domain name */ if (has_srch && gethostname(buf, sizeof(buf) - 1) == 0 && (v = strchr(buf, '.')) != NULL && *++v != '\0') dns_add_srch(ctx, v); return 0; }
static int dns_init_resolvconf(struct dns_ctx *ctx) { char *v; char buf[2049]; /* this buffer is used to hold /etc/resolv.conf */ int has_srch = 0; /* read resolv.conf... */ { int fd = open("/etc/resolv.conf", O_RDONLY); if (fd >= 0) { int l = read(fd, buf, sizeof(buf) - 1); close(fd); buf[l < 0 ? 0 : l] = '\0'; } else buf[0] = '\0'; } if (buf[0]) { /* ...and parse it */ char *line, *nextline; line = buf; do { nextline = strchr(line, '\n'); if (nextline) *nextline++ = '\0'; v = line; while(*v && !ISSPACE(*v)) ++v; if (!*v) continue; *v++ = '\0'; while(ISSPACE(*v)) ++v; if (!*v) continue; if (strcmp(line, "domain") == 0) { dns_set_srch_internal(ctx, strtok(v, space)); has_srch = 1; } else if (strcmp(line, "search") == 0) { dns_set_srch_internal(ctx, v); has_srch = 1; } else if (strcmp(line, "nameserver") == 0) dns_add_serv(ctx, strtok(v, space)); else if (strcmp(line, "options") == 0) dns_set_opts(ctx, v); } while((line = nextline) != NULL); } buf[sizeof(buf)-1] = '\0'; /* get list of nameservers from env. vars. */ if ((v = getenv("NSCACHEIP")) != NULL || (v = getenv("NAMESERVERS")) != NULL) { strncpy(buf, v, sizeof(buf) - 1); dns_set_serv_internal(ctx, buf); } /* if $LOCALDOMAIN is set, use it for search list */ if ((v = getenv("LOCALDOMAIN")) != NULL) { strncpy(buf, v, sizeof(buf) - 1); dns_set_srch_internal(ctx, buf); has_srch = 1; } if ((v = getenv("RES_OPTIONS")) != NULL) dns_set_opts(ctx, v); /* if still no search list, use local domain name */ if (has_srch && gethostname(buf, sizeof(buf) - 1) == 0 && (v = strchr(buf, '.')) != NULL && *++v != '\0') dns_add_srch(ctx, v); return 0; }
void noit_check_resolver_init() { int cnt; mtev_conf_section_t *servers, *searchdomains; eventer_t e; if(dns_init(NULL, 0) < 0) mtevL(noit_error, "dns initialization failed.\n"); dns_ctx = dns_new(NULL); if(dns_init(dns_ctx, 0) != 0) { mtevL(noit_error, "dns initialization failed.\n"); exit(-1); } /* Optional servers */ servers = mtev_conf_get_sections(NULL, "//resolver//server", &cnt); if(cnt) { int i; char server[128]; dns_add_serv(dns_ctx, NULL); /* reset */ for(i=0;i<cnt;i++) { if(mtev_conf_get_stringbuf(servers[i], "self::node()", server, sizeof(server))) { if(dns_add_serv(dns_ctx, server) < 0) { mtevL(noit_error, "Failed adding DNS server: %s\n", server); } } } free(servers); } searchdomains = mtev_conf_get_sections(NULL, "//resolver//search", &cnt); if(cnt) { int i; char search[128]; dns_add_srch(dns_ctx, NULL); /* reset */ for(i=0;i<cnt;i++) { if(mtev_conf_get_stringbuf(searchdomains[i], "self::node()", search, sizeof(search))) { if(dns_add_srch(dns_ctx, search) < 0) { mtevL(noit_error, "Failed adding DNS search path: %s\n", search); } else if(dns_search_flag) dns_search_flag = 0; /* enable search */ } } free(searchdomains); } if(mtev_conf_get_int(NULL, "//resolver/@ndots", &cnt)) dns_set_opt(dns_ctx, DNS_OPT_NDOTS, cnt); if(mtev_conf_get_int(NULL, "//resolver/@ntries", &cnt)) dns_set_opt(dns_ctx, DNS_OPT_NTRIES, cnt); if(mtev_conf_get_int(NULL, "//resolver/@timeout", &cnt)) dns_set_opt(dns_ctx, DNS_OPT_TIMEOUT, cnt); if(dns_open(dns_ctx) < 0) { mtevL(noit_error, "dns open failed.\n"); exit(-1); } eventer_name_callback("dns_cache_callback", dns_cache_callback); dns_set_tmcbck(dns_ctx, dns_cache_utm_fn, dns_ctx); e = eventer_alloc(); e->mask = EVENTER_READ | EVENTER_EXCEPTION; e->closure = dns_ctx; e->callback = dns_cache_callback; e->fd = dns_sock(dns_ctx); eventer_add(e); mtev_skiplist_init(&nc_dns_cache); mtev_skiplist_set_compare(&nc_dns_cache, name_lookup, name_lookup_k); mtev_skiplist_add_index(&nc_dns_cache, refresh_idx, refresh_idx_k); /* maybe load it from cache */ if(noit_resolver_cache_load_hook_exists()) { struct timeval now; char *key; void *data; int len; gettimeofday(&now, NULL); while(noit_resolver_cache_load_hook_invoke(&key, &data, &len) == MTEV_HOOK_CONTINUE) { dns_cache_node *n; n = calloc(1, sizeof(*n)); if(dns_cache_node_deserialize(n, data, len) >= 0) { n->target = strdup(key); /* if the TTL indicates that it will expire in less than 60 seconds * (including stuff that should have already expired), then fudge * the last_updated time to make it expire some random time within * the next 60 seconds. */ if(n->last_needed > now.tv_sec || n->last_updated > now.tv_sec) break; /* impossible */ n->last_needed = now.tv_sec; if(n->last_updated + n->ttl < now.tv_sec + 60) { int fudge = MIN(60, n->ttl) + 1; n->last_updated = now.tv_sec - n->ttl + (lrand48() % fudge); } DCLOCK(); mtev_skiplist_insert(&nc_dns_cache, n); DCUNLOCK(); n = NULL; } else { mtevL(noit_error, "Failed to deserialize resolver cache record.\n"); } if(n) dns_cache_node_free(n); if(key) free(key); if(data) free(data); } } noit_check_resolver_loop(NULL, 0, NULL, NULL); register_console_dns_cache_commands(); mtev_hash_init(&etc_hosts_cache); noit_check_etc_hosts_cache_refresh(NULL, 0, NULL, NULL); }