diff --git a/CHANGES b/CHANGES index b619125c9f..d066845439 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,27 @@ +3707. [bug] irs_resconf_load now returns ISC_R_FILENOTFOUND + on a missing resolv.conf file and initializes the + structure as if it had been configured with: + + nameserver ::1 + nameserver 127.0.0.1 + + Note: Callers will need to be updated to treat + ISC_R_FILENOTFOUND as a qualified success or else + they will leak memory. The following code fragment + will work with both only and new versions without + changing the behaviour of the existing code. + + resconf = NULL; + result = irs_resconf_load(mctx, "/etc/resolv.conf", + &resconf); + if (result != ISC_SUCCESS) { + if (resconf != NULL) + irs_resconf_destroy(&resconf); + .... + } + + [RT #35194] + 3706. [contrib] queryperf: Fixed a possible integer overflow when printing results. [RT #35182] diff --git a/lib/irs/include/irs/resconf.h b/lib/irs/include/irs/resconf.h index 78c87d5166..c6c6e851bc 100644 --- a/lib/irs/include/irs/resconf.h +++ b/lib/irs/include/irs/resconf.h @@ -46,7 +46,12 @@ isc_result_t irs_resconf_load(isc_mem_t *mctx, const char *filename, irs_resconf_t **confp); /*%< * Load the resolver configuration file 'filename' in the "resolv.conf" format, - * and create a new irs_resconf_t object from the configuration. + * and create a new irs_resconf_t object from the configuration. If the file + * is not found ISC_R_FILENOTFOUND is returned with the structure initialized + * as if file contained only: + * + * nameserver ::1 + * nameserver 127.0.0.1 * * Notes: * @@ -55,6 +60,11 @@ irs_resconf_load(isc_mem_t *mctx, const char *filename, irs_resconf_t **confp); * In addition, 'sortlist' is not actually effective; it's parsed, but * the application cannot use the configuration. * + * Returns: + * \li ISC_R_SUCCESS on success + * \li ISC_R_FILENOTFOUND if the file was not found. *confp will be valid. + * \li other on error. + * * Requires: * *\li 'mctx' is a valid memory context. diff --git a/lib/irs/resconf.c b/lib/irs/resconf.c index 15a46baf3f..29cfb75fef 100644 --- a/lib/irs/resconf.c +++ b/lib/irs/resconf.c @@ -507,45 +507,50 @@ irs_resconf_load(isc_mem_t *mctx, const char *filename, irs_resconf_t **confp) conf->search[i] = NULL; errno = 0; - if ((fp = fopen(filename, "r")) == NULL) { - isc_mem_put(mctx, conf, sizeof(*conf)); - return (ISC_R_INVALIDFILE); - } - - ret = ISC_R_SUCCESS; - do { - stopchar = getword(fp, word, sizeof(word)); - if (stopchar == EOF) { - rval = ISC_R_SUCCESS; - POST(rval); - break; - } - - if (strlen(word) == 0U) - rval = ISC_R_SUCCESS; - else if (strcmp(word, "nameserver") == 0) - rval = resconf_parsenameserver(conf, fp); - else if (strcmp(word, "domain") == 0) - rval = resconf_parsedomain(conf, fp); - else if (strcmp(word, "search") == 0) - rval = resconf_parsesearch(conf, fp); - else if (strcmp(word, "sortlist") == 0) - rval = resconf_parsesortlist(conf, fp); - else if (strcmp(word, "options") == 0) - rval = resconf_parseoption(conf, fp); - else { - /* unrecognised word. Ignore entire line */ - rval = ISC_R_SUCCESS; - stopchar = eatline(fp); + if ((fp = fopen(filename, "r")) != NULL) { + ret = ISC_R_SUCCESS; + do { + stopchar = getword(fp, word, sizeof(word)); if (stopchar == EOF) { + rval = ISC_R_SUCCESS; + POST(rval); break; } - } - if (ret == ISC_R_SUCCESS && rval != ISC_R_SUCCESS) - ret = rval; - } while (1); - fclose(fp); + if (strlen(word) == 0U) + rval = ISC_R_SUCCESS; + else if (strcmp(word, "nameserver") == 0) + rval = resconf_parsenameserver(conf, fp); + else if (strcmp(word, "domain") == 0) + rval = resconf_parsedomain(conf, fp); + else if (strcmp(word, "search") == 0) + rval = resconf_parsesearch(conf, fp); + else if (strcmp(word, "sortlist") == 0) + rval = resconf_parsesortlist(conf, fp); + else if (strcmp(word, "options") == 0) + rval = resconf_parseoption(conf, fp); + else { + /* unrecognised word. Ignore entire line */ + rval = ISC_R_SUCCESS; + stopchar = eatline(fp); + if (stopchar == EOF) { + break; + } + } + if (ret == ISC_R_SUCCESS && rval != ISC_R_SUCCESS) + ret = rval; + } while (1); + + fclose(fp); + } else { + switch (errno) { + case ENOENT: + break; + default: + isc_mem_put(mctx, conf, sizeof(*conf)); + return (ISC_R_INVALIDFILE); + } + } /* If we don't find a nameserver fall back to localhost */ if (conf->numns == 0) { @@ -575,8 +580,11 @@ irs_resconf_load(isc_mem_t *mctx, const char *filename, irs_resconf_t **confp) if (ret != ISC_R_SUCCESS) irs_resconf_destroy(&conf); - else + else { + if (fp == NULL) + ret = ISC_R_FILENOTFOUND; *confp = conf; + } return (ret); } diff --git a/lib/samples/resolve.c b/lib/samples/resolve.c index 95475ebb21..278e0e292d 100644 --- a/lib/samples/resolve.c +++ b/lib/samples/resolve.c @@ -401,7 +401,7 @@ main(int argc, char *argv[]) { isc_sockaddrlist_t *nameservers; result = irs_resconf_load(mctx, "/etc/resolv.conf", &resconf); - if (result != ISC_R_SUCCESS) { + if (result != ISC_R_SUCCESS && result != ISC_R_FILENOTFOUND) { fprintf(stderr, "irs_resconf_load failed: %d\n", result); exit(1);