/** read forwards config */ static int read_forwards(struct iter_forwards* fwd, struct config_file* cfg) { struct config_stub* s; for(s = cfg->forwards; s; s = s->next) { struct delegpt* dp; if(!(dp=read_fwds_name(s))) return 0; if(!read_fwds_host(s, dp) || !read_fwds_addr(s, dp)) { delegpt_free_mlc(dp); return 0; } /* set flag that parent side NS information is included. * Asking a (higher up) server on the internet is not useful */ /* the flag is turned off for 'forward-first' so that the * last resort will ask for parent-side NS record and thus * fallback to the internet name servers on a failure */ dp->has_parent_side_NS = (uint8_t)!s->isfirst; verbose(VERB_QUERY, "Forward zone server list:"); delegpt_log(VERB_QUERY, dp); if(!forwards_insert(fwd, LDNS_RR_CLASS_IN, dp)) return 0; } return 1; }
/** read stubs config */ static int read_stubs(struct iter_hints* hints, struct config_file* cfg) { struct config_stub* s; struct delegpt* dp; for(s = cfg->stubs; s; s = s->next) { if(!(dp=read_stubs_name(s)) || !read_stubs_host(s, dp) || !read_stubs_addr(s, dp)) return 0; /* the flag is turned off for 'stub-first' so that the * last resort will ask for parent-side NS record and thus * fallback to the internet name servers on a failure */ dp->has_parent_side_NS = (uint8_t)!s->isfirst; if(!hints_insert(hints, LDNS_RR_CLASS_IN, dp, !s->isprime)) return 0; delegpt_log(VERB_QUERY, dp); } return 1; }
/** read root hints from file */ static int read_root_hints(struct iter_hints* hints, char* fname) { struct sldns_file_parse_state pstate; struct delegpt* dp; uint8_t rr[LDNS_RR_BUF_SIZE]; size_t rr_len, dname_len; int status; uint16_t c = LDNS_RR_CLASS_IN; FILE* f = fopen(fname, "r"); if(!f) { log_err("could not read root hints %s: %s", fname, strerror(errno)); return 0; } dp = delegpt_create_mlc(NULL); if(!dp) { log_err("out of memory reading root hints"); fclose(f); return 0; } verbose(VERB_QUERY, "Reading root hints from %s", fname); memset(&pstate, 0, sizeof(pstate)); pstate.lineno = 1; dp->has_parent_side_NS = 1; while(!feof(f)) { rr_len = sizeof(rr); dname_len = 0; status = sldns_fp2wire_rr_buf(f, rr, &rr_len, &dname_len, &pstate); if(status != 0) { log_err("reading root hints %s %d:%d: %s", fname, pstate.lineno, LDNS_WIREPARSE_OFFSET(status), sldns_get_errorstr_parse(status)); goto stop_read; } if(rr_len == 0) continue; /* EMPTY line, TTL or ORIGIN */ if(sldns_wirerr_get_type(rr, rr_len, dname_len) == LDNS_RR_TYPE_NS) { if(!delegpt_add_ns_mlc(dp, sldns_wirerr_get_rdata(rr, rr_len, dname_len), 0)) { log_err("out of memory reading root hints"); goto stop_read; } c = sldns_wirerr_get_class(rr, rr_len, dname_len); if(!dp->name) { if(!delegpt_set_name_mlc(dp, rr)) { log_err("out of memory."); goto stop_read; } } } else if(sldns_wirerr_get_type(rr, rr_len, dname_len) == LDNS_RR_TYPE_A && sldns_wirerr_get_rdatalen(rr, rr_len, dname_len) == INET_SIZE) { struct sockaddr_in sa; socklen_t len = (socklen_t)sizeof(sa); memset(&sa, 0, len); sa.sin_family = AF_INET; sa.sin_port = (in_port_t)htons(UNBOUND_DNS_PORT); memmove(&sa.sin_addr, sldns_wirerr_get_rdata(rr, rr_len, dname_len), INET_SIZE); if(!delegpt_add_target_mlc(dp, rr, dname_len, (struct sockaddr_storage*)&sa, len, 0, 0)) { log_err("out of memory reading root hints"); goto stop_read; } } else if(sldns_wirerr_get_type(rr, rr_len, dname_len) == LDNS_RR_TYPE_AAAA && sldns_wirerr_get_rdatalen(rr, rr_len, dname_len) == INET6_SIZE) { struct sockaddr_in6 sa; socklen_t len = (socklen_t)sizeof(sa); memset(&sa, 0, len); sa.sin6_family = AF_INET6; sa.sin6_port = (in_port_t)htons(UNBOUND_DNS_PORT); memmove(&sa.sin6_addr, sldns_wirerr_get_rdata(rr, rr_len, dname_len), INET6_SIZE); if(!delegpt_add_target_mlc(dp, rr, dname_len, (struct sockaddr_storage*)&sa, len, 0, 0)) { log_err("out of memory reading root hints"); goto stop_read; } } else { char buf[17]; sldns_wire2str_type_buf(sldns_wirerr_get_type(rr, rr_len, dname_len), buf, sizeof(buf)); log_warn("root hints %s:%d skipping type %s", fname, pstate.lineno, buf); } } fclose(f); if(!dp->name) { log_warn("root hints %s: no NS content", fname); delegpt_free_mlc(dp); return 1; } if(!hints_insert(hints, c, dp, 0)) { return 0; } delegpt_log(VERB_QUERY, dp); return 1; stop_read: delegpt_free_mlc(dp); fclose(f); return 0; }
/** read root hints from file */ static int read_root_hints(struct iter_hints* hints, char* fname) { int lineno = 0; uint32_t default_ttl = 0; ldns_rdf* origin = NULL; ldns_rdf* prev_rr = NULL; struct delegpt* dp; ldns_rr* rr = NULL; ldns_status status; uint16_t c = LDNS_RR_CLASS_IN; FILE* f = fopen(fname, "r"); if(!f) { log_err("could not read root hints %s: %s", fname, strerror(errno)); return 0; } dp = delegpt_create_mlc(NULL); if(!dp) { log_err("out of memory reading root hints"); fclose(f); return 0; } verbose(VERB_QUERY, "Reading root hints from %s", fname); dp->has_parent_side_NS = 1; while(!feof(f)) { status = ldns_rr_new_frm_fp_l(&rr, f, &default_ttl, &origin, &prev_rr, &lineno); if(status == LDNS_STATUS_SYNTAX_EMPTY || status == LDNS_STATUS_SYNTAX_TTL || status == LDNS_STATUS_SYNTAX_ORIGIN) continue; if(status != LDNS_STATUS_OK) { log_err("reading root hints %s %d: %s", fname, lineno, ldns_get_errorstr_by_id(status)); goto stop_read; } if(ldns_rr_get_type(rr) == LDNS_RR_TYPE_NS) { if(!delegpt_add_ns_mlc(dp, ldns_rdf_data(ldns_rr_rdf(rr, 0)), 0)) { log_err("out of memory reading root hints"); goto stop_read; } c = ldns_rr_get_class(rr); if(!dp->name) { if(!delegpt_set_name_mlc(dp, ldns_rdf_data(ldns_rr_owner(rr)))){ log_err("out of memory."); goto stop_read; } } } else if(ldns_rr_get_type(rr) == LDNS_RR_TYPE_A) { struct sockaddr_in sa; socklen_t len = (socklen_t)sizeof(sa); memset(&sa, 0, len); sa.sin_family = AF_INET; sa.sin_port = (in_port_t)htons(UNBOUND_DNS_PORT); memmove(&sa.sin_addr, ldns_rdf_data(ldns_rr_rdf(rr, 0)), INET_SIZE); if(!delegpt_add_target_mlc(dp, ldns_rdf_data(ldns_rr_owner(rr)), ldns_rdf_size(ldns_rr_owner(rr)), (struct sockaddr_storage*)&sa, len, 0, 0)) { log_err("out of memory reading root hints"); goto stop_read; } } else if(ldns_rr_get_type(rr) == LDNS_RR_TYPE_AAAA) { struct sockaddr_in6 sa; socklen_t len = (socklen_t)sizeof(sa); memset(&sa, 0, len); sa.sin6_family = AF_INET6; sa.sin6_port = (in_port_t)htons(UNBOUND_DNS_PORT); memmove(&sa.sin6_addr, ldns_rdf_data(ldns_rr_rdf(rr, 0)), INET6_SIZE); if(!delegpt_add_target_mlc(dp, ldns_rdf_data(ldns_rr_owner(rr)), ldns_rdf_size(ldns_rr_owner(rr)), (struct sockaddr_storage*)&sa, len, 0, 0)) { log_err("out of memory reading root hints"); goto stop_read; } } else { log_warn("root hints %s:%d skipping type %d", fname, lineno, ldns_rr_get_type(rr)); } ldns_rr_free(rr); } if (origin) ldns_rdf_deep_free(origin); if (prev_rr) ldns_rdf_deep_free(prev_rr); fclose(f); if(!dp->name) { log_warn("root hints %s: no NS content", fname); delegpt_free_mlc(dp); return 1; } if(!hints_insert(hints, c, dp, 0)) { return 0; } delegpt_log(VERB_QUERY, dp); return 1; stop_read: if (origin) ldns_rdf_deep_free(origin); if (prev_rr) ldns_rdf_deep_free(prev_rr); delegpt_free_mlc(dp); fclose(f); return 0; }