diff options
Diffstat (limited to 'contrib/ldns/resolver.c')
-rw-r--r-- | contrib/ldns/resolver.c | 182 |
1 files changed, 120 insertions, 62 deletions
diff --git a/contrib/ldns/resolver.c b/contrib/ldns/resolver.c index 20d4e6d..16efc90 100644 --- a/contrib/ldns/resolver.c +++ b/contrib/ldns/resolver.c @@ -26,6 +26,12 @@ ldns_resolver_port(const ldns_resolver *r) return r->_port; } +ldns_rdf * +ldns_resolver_source(const ldns_resolver *r) +{ + return r->_source; +} + uint16_t ldns_resolver_edns_udp_size(const ldns_resolver *r) { @@ -234,6 +240,12 @@ ldns_resolver_set_port(ldns_resolver *r, uint16_t p) r->_port = p; } +void +ldns_resolver_set_source(ldns_resolver *r, ldns_rdf *s) +{ + r->_source = s; +} + ldns_rdf * ldns_resolver_pop_nameserver(ldns_resolver *r) { @@ -625,6 +637,7 @@ ldns_resolver_new(void) ldns_resolver_set_igntc(r, false); ldns_resolver_set_recursive(r, false); ldns_resolver_set_dnsrch(r, true); + ldns_resolver_set_source(r, NULL); /* randomize the nameserver to be queried * when there are multiple @@ -670,8 +683,15 @@ ldns_resolver_new_frm_fp_l(ldns_resolver **res, FILE *fp, int *line_nr) ssize_t gtr, bgtr; ldns_buffer *b; int lnr = 0, oldline; + FILE* myfp = fp; if(!line_nr) line_nr = &lnr; + if(!fp) { + myfp = fopen("/etc/resolv.conf", "r"); + if(!myfp) + return LDNS_STATUS_FILE_ERR; + } + /* do this better * expect = * 0: keyword @@ -691,6 +711,7 @@ ldns_resolver_new_frm_fp_l(ldns_resolver **res, FILE *fp, int *line_nr) r = ldns_resolver_new(); if (!r) { + if(!fp) fclose(myfp); return LDNS_STATUS_MEM_ERR; } @@ -706,9 +727,9 @@ ldns_resolver_new_frm_fp_l(ldns_resolver **res, FILE *fp, int *line_nr) /* skip until end of line */ int c; do { - c = fgetc(fp); + c = fgetc(myfp); } while(c != EOF && c != '\n'); - if(c=='\n' && line_nr) (*line_nr)++; + if(c=='\n') (*line_nr)++; } /* and read next to prepare for further parsing */ oldline = *line_nr; @@ -718,7 +739,7 @@ ldns_resolver_new_frm_fp_l(ldns_resolver **res, FILE *fp, int *line_nr) switch(expect) { case LDNS_RESOLV_KEYWORD: /* keyword */ - gtr = ldns_fget_token_l(fp, word, LDNS_PARSE_NORMAL, 0, line_nr); + gtr = ldns_fget_token_l(myfp, word, LDNS_PARSE_NORMAL, 0, line_nr); if (gtr != 0) { if(word[0] == '#') continue; for(i = 0; i < LDNS_RESOLV_KEYWORDS; i++) { @@ -735,6 +756,7 @@ ldns_resolver_new_frm_fp_l(ldns_resolver **res, FILE *fp, int *line_nr) /* skip line */ /* ldns_resolver_deep_free(r); + if(!fp) fclose(myfp); return LDNS_STATUS_SYNTAX_KEYWORD_ERR; */ } @@ -742,8 +764,9 @@ ldns_resolver_new_frm_fp_l(ldns_resolver **res, FILE *fp, int *line_nr) break; case LDNS_RESOLV_DEFDOMAIN: /* default domain dname */ - gtr = ldns_fget_token_l(fp, word, LDNS_PARSE_NORMAL, 0, line_nr); + gtr = ldns_fget_token_l(myfp, word, LDNS_PARSE_NORMAL, 0, line_nr); if (gtr == 0) { + if(!fp) fclose(myfp); return LDNS_STATUS_SYNTAX_MISSING_VALUE_ERR; } if(word[0] == '#') { @@ -753,6 +776,7 @@ ldns_resolver_new_frm_fp_l(ldns_resolver **res, FILE *fp, int *line_nr) tmp = ldns_rdf_new_frm_str(LDNS_RDF_TYPE_DNAME, word); if (!tmp) { ldns_resolver_deep_free(r); + if(!fp) fclose(myfp); return LDNS_STATUS_SYNTAX_DNAME_ERR; } @@ -762,8 +786,9 @@ ldns_resolver_new_frm_fp_l(ldns_resolver **res, FILE *fp, int *line_nr) break; case LDNS_RESOLV_NAMESERVER: /* NS aaaa or a record */ - gtr = ldns_fget_token_l(fp, word, LDNS_PARSE_NORMAL, 0, line_nr); + gtr = ldns_fget_token_l(myfp, word, LDNS_PARSE_NORMAL, 0, line_nr); if (gtr == 0) { + if(!fp) fclose(myfp); return LDNS_STATUS_SYNTAX_MISSING_VALUE_ERR; } if(word[0] == '#') { @@ -783,6 +808,7 @@ ldns_resolver_new_frm_fp_l(ldns_resolver **res, FILE *fp, int *line_nr) /* could not parse it, exit */ if (!tmp) { ldns_resolver_deep_free(r); + if(!fp) fclose(myfp); return LDNS_STATUS_SYNTAX_ERR; } (void)ldns_resolver_push_nameserver(r, tmp); @@ -791,10 +817,11 @@ ldns_resolver_new_frm_fp_l(ldns_resolver **res, FILE *fp, int *line_nr) break; case LDNS_RESOLV_SEARCH: /* search list domain dname */ - gtr = ldns_fget_token_l(fp, word, LDNS_PARSE_SKIP_SPACE, 0, line_nr); + gtr = ldns_fget_token_l(myfp, word, LDNS_PARSE_SKIP_SPACE, 0, line_nr); b = LDNS_MALLOC(ldns_buffer); if(!b) { ldns_resolver_deep_free(r); + if(!fp) fclose(myfp); return LDNS_STATUS_MEM_ERR; } @@ -802,6 +829,7 @@ ldns_resolver_new_frm_fp_l(ldns_resolver **res, FILE *fp, int *line_nr) if(ldns_buffer_status(b) != LDNS_STATUS_OK) { LDNS_FREE(b); ldns_resolver_deep_free(r); + if(!fp) fclose(myfp); return LDNS_STATUS_MEM_ERR; } bgtr = ldns_bget_token(b, word, LDNS_PARSE_NORMAL, (size_t) gtr + 1); @@ -815,6 +843,7 @@ ldns_resolver_new_frm_fp_l(ldns_resolver **res, FILE *fp, int *line_nr) if (!tmp) { ldns_resolver_deep_free(r); ldns_buffer_free(b); + if(!fp) fclose(myfp); return LDNS_STATUS_SYNTAX_DNAME_ERR; } @@ -831,20 +860,21 @@ ldns_resolver_new_frm_fp_l(ldns_resolver **res, FILE *fp, int *line_nr) } break; case LDNS_RESOLV_SORTLIST: - gtr = ldns_fget_token_l(fp, word, LDNS_PARSE_SKIP_SPACE, 0, line_nr); + gtr = ldns_fget_token_l(myfp, word, LDNS_PARSE_SKIP_SPACE, 0, line_nr); /* sortlist not implemented atm */ expect = LDNS_RESOLV_KEYWORD; break; case LDNS_RESOLV_OPTIONS: - gtr = ldns_fget_token_l(fp, word, LDNS_PARSE_SKIP_SPACE, 0, line_nr); + gtr = ldns_fget_token_l(myfp, word, LDNS_PARSE_SKIP_SPACE, 0, line_nr); /* options not implemented atm */ expect = LDNS_RESOLV_KEYWORD; break; case LDNS_RESOLV_ANCHOR: /* a file containing a DNSSEC trust anchor */ - gtr = ldns_fget_token_l(fp, word, LDNS_PARSE_NORMAL, 0, line_nr); + gtr = ldns_fget_token_l(myfp, word, LDNS_PARSE_NORMAL, 0, line_nr); if (gtr == 0) { ldns_resolver_deep_free(r); + if(!fp) fclose(myfp); return LDNS_STATUS_SYNTAX_MISSING_VALUE_ERR; } if(word[0] == '#') { @@ -862,6 +892,9 @@ ldns_resolver_new_frm_fp_l(ldns_resolver **res, FILE *fp, int *line_nr) } } + if(!fp) + fclose(myfp); + if (res) { *res = r; return LDNS_STATUS_OK; @@ -953,86 +986,82 @@ ldns_resolver_deep_free(ldns_resolver *res) } } -ldns_pkt * -ldns_resolver_search(const ldns_resolver *r,const ldns_rdf *name, - ldns_rr_type t, ldns_rr_class c, uint16_t flags) +ldns_status +ldns_resolver_search_status(ldns_pkt** pkt, + ldns_resolver *r, const ldns_rdf *name, + ldns_rr_type t, ldns_rr_class c, uint16_t flags) { - ldns_rdf *new_name; ldns_rdf **search_list; size_t i; - ldns_pkt *p; + ldns_status s = LDNS_STATUS_OK; if (ldns_dname_absolute(name)) { /* query as-is */ - return ldns_resolver_query(r, name, t, c, flags); + return ldns_resolver_query_status(pkt, r, name, t, c, flags); } else if (ldns_resolver_dnsrch(r)) { search_list = ldns_resolver_searchlist(r); for (i = 0; i < ldns_resolver_searchlist_count(r); i++) { new_name = ldns_dname_cat_clone(name, search_list[i]); - p = ldns_resolver_query(r, new_name, t, c, flags); + s = ldns_resolver_query_status(pkt, r, + new_name, t, c, flags); ldns_rdf_free(new_name); - if (p) { - if (ldns_pkt_get_rcode(p) == LDNS_RCODE_NOERROR) { - return p; - } else { - ldns_pkt_free(p); - p = NULL; + if (pkt) { + if (s == LDNS_STATUS_OK && *pkt && + ldns_pkt_get_rcode(*pkt) == + LDNS_RCODE_NOERROR) { + return LDNS_STATUS_OK; } + ldns_pkt_free(*pkt); } } } - return NULL; + return s; } ldns_pkt * -ldns_resolver_query(const ldns_resolver *r, const ldns_rdf *name, +ldns_resolver_search(const ldns_resolver *r,const ldns_rdf *name, ldns_rr_type t, ldns_rr_class c, uint16_t flags) { + ldns_pkt* pkt = NULL; + if (ldns_resolver_search_status(&pkt, (ldns_resolver *)r, + name, t, c, flags) != LDNS_STATUS_OK) { + ldns_pkt_free(pkt); + } + return pkt; +} + +ldns_status +ldns_resolver_query_status(ldns_pkt** pkt, + ldns_resolver *r, const ldns_rdf *name, + ldns_rr_type t, ldns_rr_class c, uint16_t flags) +{ ldns_rdf *newname; - ldns_pkt *pkt; ldns_status status; - pkt = NULL; - - if (!ldns_resolver_defnames(r)) { - status = ldns_resolver_send(&pkt, (ldns_resolver *)r, name, - t, c, flags); - if (status == LDNS_STATUS_OK) { - return pkt; - } else { - if (pkt) { - ldns_pkt_free(pkt); - } - return NULL; - } - } - - if (!ldns_resolver_domain(r)) { - /* _defnames is set, but the domain is not....?? */ - status = ldns_resolver_send(&pkt, (ldns_resolver *)r, name, - t, c, flags); - if (status == LDNS_STATUS_OK) { - return pkt; - } else { - if (pkt) { - ldns_pkt_free(pkt); - } - return NULL; - } + if (!ldns_resolver_defnames(r) || !ldns_resolver_domain(r)) { + return ldns_resolver_send(pkt, r, name, t, c, flags); } - newname = ldns_dname_cat_clone((const ldns_rdf*)name, ldns_resolver_domain(r)); + newname = ldns_dname_cat_clone(name, ldns_resolver_domain(r)); if (!newname) { - return NULL; + return LDNS_STATUS_MEM_ERR; } - - (void)ldns_resolver_send(&pkt, (ldns_resolver *)r, newname, t, c, - flags); - + status = ldns_resolver_send(pkt, r, newname, t, c, flags); ldns_rdf_free(newname); + return status; +} +ldns_pkt * +ldns_resolver_query(const ldns_resolver *r, const ldns_rdf *name, + ldns_rr_type t, ldns_rr_class c, uint16_t flags) +{ + ldns_pkt* pkt = NULL; + if (ldns_resolver_query_status(&pkt, (ldns_resolver *)r, + name, t, c, flags) != LDNS_STATUS_OK) { + ldns_pkt_free(pkt); + } return pkt; } @@ -1129,7 +1158,12 @@ ldns_resolver_prepare_query_pkt(ldns_pkt **query_pkt, ldns_resolver *r, /* prepare a question pkt from the parameters * and then send this */ - *query_pkt = ldns_pkt_query_new(ldns_rdf_clone(name), t, c, flags); + if (t == LDNS_RR_TYPE_IXFR) { + *query_pkt = ldns_pkt_ixfr_request_new(ldns_rdf_clone(name), + c, flags, NULL); + } else { + *query_pkt = ldns_pkt_query_new(ldns_rdf_clone(name), t, c, flags); + } if (!*query_pkt) { return LDNS_STATUS_ERR; } @@ -1206,7 +1240,7 @@ ldns_resolver_send(ldns_pkt **answer, ldns_resolver *r, const ldns_rdf *name, /* if tsig values are set, tsign it */ /* TODO: make last 3 arguments optional too? maybe make complete - rr instead of seperate values in resolver (and packet) + rr instead of separate values in resolver (and packet) Jelte should this go in pkt_prepare? */ @@ -1286,9 +1320,11 @@ ldns_axfr_next(ldns_resolver *resolver) resolver->_axfr_i = 0; if (status != LDNS_STATUS_OK) { /* TODO: make status return type of this function (...api change) */ +#ifdef STDERR_MSGS fprintf(stderr, "Error parsing rr during AXFR: %s\n", ldns_get_errorstr_by_id(status)); +#endif - /* RoRi: we must now also close the socket, otherwise subsequent uses of the + /* we must now also close the socket, otherwise subsequent uses of the same resolver structure will fail because the link is still open or in an undefined state */ #ifndef USE_WINSOCK @@ -1301,6 +1337,7 @@ ldns_axfr_next(ldns_resolver *resolver) return NULL; } else if (ldns_pkt_get_rcode(resolver->_cur_axfr_pkt) != 0) { rcode = ldns_lookup_by_id(ldns_rcodes, (int) ldns_pkt_get_rcode(resolver->_cur_axfr_pkt)); +#ifdef STDERR_MSGS if (rcode) { fprintf(stderr, "Error in AXFR: %s\n", rcode->name); @@ -1309,8 +1346,9 @@ ldns_axfr_next(ldns_resolver *resolver) (int) ldns_pkt_get_rcode( resolver->_cur_axfr_pkt)); } +#endif - /* RoRi: we must now also close the socket, otherwise subsequent uses of the + /* we must now also close the socket, otherwise subsequent uses of the same resolver structure will fail because the link is still open or in an undefined state */ #ifndef USE_WINSOCK @@ -1329,6 +1367,26 @@ ldns_axfr_next(ldns_resolver *resolver) } +/* this function is needed to abort a transfer that is in progress; + * without it an aborted transfer will lead to the AXFR code in the + * library staying in an indetermined state because the socket for the + * AXFR is never closed + */ +void +ldns_axfr_abort(ldns_resolver *resolver) +{ + /* Only abort if an actual AXFR is in progress */ + if (resolver->_socket != 0) + { +#ifndef USE_WINSOCK + close(resolver->_socket); +#else + closesocket(resolver->_socket); +#endif + resolver->_socket = 0; + } +} + bool ldns_axfr_complete(const ldns_resolver *res) { |