]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Remove artificial search limit from libirs
authorPetr Menšík <pemensik@redhat.com>
Fri, 4 Oct 2019 22:20:54 +0000 (00:20 +0200)
committerMark Andrews <marka@isc.org>
Tue, 10 Dec 2024 00:51:56 +0000 (00:51 +0000)
Search directive from resolv.conf had a maximum of 8 domains. Any
more were ignored. Do not ignore them anymore; iterate over any
number of domains.

Test resolv.conf support by checking the first and last domain in
the search list. Ignore the domains between; just ensure that the
last domain in the configuration is the last domain parsed.

lib/dns/resconf.c
tests/irs/testdata/search.conf

index d1d660e60a31ee416b634ab85a0fce1ea2a3a761..c21df4a51150e14135bd7907e1e57547a7b0fe76 100644 (file)
@@ -72,7 +72,6 @@
  */
 
 #define RESCONFMAXNAMESERVERS 3U   /*%< max 3 "nameserver" entries */
-#define RESCONFMAXSEARCH      8U   /*%< max 8 domains in "search" entry */
 #define RESCONFMAXLINELEN     256U /*%< max size of a line */
 #define RESCONFMAXSORTLIST    10U  /*%< max 10 */
 
@@ -99,7 +98,6 @@ struct irs_resconf {
        unsigned int numns; /*%< number of configured servers */
 
        char *domainname;
-       char *search[RESCONFMAXSEARCH];
        uint8_t searchnxt; /*%< index for next free slot */
 
        irs_resconf_searchlist_t searchlist;
@@ -139,10 +137,9 @@ static int
 eatline(FILE *fp) {
        int ch;
 
-       ch = fgetc(fp);
-       while (ch != '\n' && ch != EOF) {
+       do {
                ch = fgetc(fp);
-       }
+       } while (ch != '\n' && ch != EOF);
 
        return ch;
 }
@@ -156,10 +153,9 @@ static int
 eatwhite(FILE *fp) {
        int ch;
 
-       ch = fgetc(fp);
-       while (ch != '\n' && ch != EOF && isspace((unsigned char)ch)) {
+       do {
                ch = fgetc(fp);
-       }
+       } while (ch != EOF && ch != '\n' && isspace((unsigned char)ch));
 
        if (ch == ';' || ch == '#') {
                ch = eatline(fp);
@@ -186,7 +182,6 @@ getword(FILE *fp, char *buffer, size_t size) {
        *p = '\0';
 
        ch = eatwhite(fp);
-
        if (ch == EOF) {
                return EOF;
        }
@@ -194,7 +189,7 @@ getword(FILE *fp, char *buffer, size_t size) {
        do {
                *p = '\0';
 
-               if (ch == EOF || isspace((unsigned char)ch)) {
+               if (isspace((unsigned char)ch)) {
                        break;
                } else if ((size_t)(p - buffer) == size - 1) {
                        return EOF; /* Not enough space. */
@@ -202,7 +197,7 @@ getword(FILE *fp, char *buffer, size_t size) {
 
                *p++ = (char)ch;
                ch = fgetc(fp);
-       } while (1);
+       } while (ch != EOF);
 
        return ch;
 }
@@ -298,7 +293,7 @@ resconf_parsenameserver(irs_resconf_t *conf, FILE *fp) {
        isc_result_t result;
 
        cp = getword(fp, word, sizeof(word));
-       if (strlen(word) == 0U) {
+       if (cp == EOF || strlen(word) == 0U) {
                return ISC_R_UNEXPECTEDEND; /* Nothing on line. */
        } else if (cp == ' ' || cp == '\t') {
                cp = eatwhite(fp);
@@ -325,10 +320,9 @@ static isc_result_t
 resconf_parsedomain(irs_resconf_t *conf, FILE *fp) {
        char word[RESCONFMAXLINELEN];
        int res;
-       unsigned int i;
 
        res = getword(fp, word, sizeof(word));
-       if (strlen(word) == 0U) {
+       if (res == EOF || strlen(word) == 0U) {
                return ISC_R_UNEXPECTEDEND; /* Nothing else on line. */
        } else if (res == ' ' || res == '\t') {
                res = eatwhite(fp);
@@ -344,25 +338,50 @@ resconf_parsedomain(irs_resconf_t *conf, FILE *fp) {
 
        /*
         * Search and domain are mutually exclusive.
+        * Search is cleared later.
         */
-       for (i = 0; i < RESCONFMAXSEARCH; i++) {
-               if (conf->search[i] != NULL) {
-                       isc_mem_free(conf->mctx, conf->search[i]);
-                       conf->search[i] = NULL;
-               }
-       }
-       conf->searchnxt = 0;
 
        conf->domainname = isc_mem_strdup(conf->mctx, word);
 
        return ISC_R_SUCCESS;
 }
 
+static void
+free_search(irs_resconf_t *conf) {
+       irs_resconf_search_t *searchentry;
+
+       while ((searchentry = ISC_LIST_HEAD(conf->searchlist)) != NULL) {
+               ISC_LIST_UNLINK(conf->searchlist, searchentry, link);
+               isc_mem_free(conf->mctx, searchentry->domain);
+               isc_mem_put(conf->mctx, searchentry, sizeof(*searchentry));
+       }
+}
+
+/*!
+ * Append new search entry to searchlist.
+ *
+ * Always copy domain name passed.
+ */
+static isc_result_t
+add_search(irs_resconf_t *conf, char *domain) {
+       irs_resconf_search_t *entry = NULL;
+
+       entry = isc_mem_get(conf->mctx, sizeof(*entry));
+       *entry = (irs_resconf_search_t){
+               .domain = isc_mem_strdup(conf->mctx, domain),
+               .link = ISC_LINK_INITIALIZER,
+       };
+
+       ISC_LIST_APPEND(conf->searchlist, entry, link);
+
+       return ISC_R_SUCCESS;
+}
+
 static isc_result_t
 resconf_parsesearch(irs_resconf_t *conf, FILE *fp) {
        int delim;
-       unsigned int idx;
        char word[RESCONFMAXLINELEN];
+       isc_result_t result;
 
        if (conf->domainname != NULL) {
                /*
@@ -375,37 +394,27 @@ resconf_parsesearch(irs_resconf_t *conf, FILE *fp) {
        /*
         * Remove any previous search definitions.
         */
-       for (idx = 0; idx < RESCONFMAXSEARCH; idx++) {
-               if (conf->search[idx] != NULL) {
-                       isc_mem_free(conf->mctx, conf->search[idx]);
-                       conf->search[idx] = NULL;
-               }
-       }
-       conf->searchnxt = 0;
+       free_search(conf);
 
        delim = getword(fp, word, sizeof(word));
-       if (strlen(word) == 0U) {
+       if (delim == EOF || strlen(word) == 0U) {
                return ISC_R_UNEXPECTEDEND; /* Nothing else on line. */
        }
-
-       idx = 0;
-       while (strlen(word) > 0U) {
-               if (conf->searchnxt == RESCONFMAXSEARCH) {
-                       goto ignore; /* Too many domains. */
+       do {
+               result = add_search(conf, word);
+               if (result != ISC_R_SUCCESS) {
+                       return result;
                }
 
-               INSIST(idx < sizeof(conf->search) / sizeof(conf->search[0]));
-               conf->search[idx] = isc_mem_strdup(conf->mctx, word);
-               idx++;
-               conf->searchnxt++;
-
-       ignore:
-               if (delim == EOF || delim == '\n') {
+               if (delim == '\n') {
                        break;
-               } else {
-                       delim = getword(fp, word, sizeof(word));
                }
-       }
+
+               delim = getword(fp, word, sizeof(word));
+               if (delim == EOF) {
+                       return ISC_R_UNEXPECTEDEND;
+               }
+       } while (strlen(word) > 0U);
 
        return ISC_R_SUCCESS;
 }
@@ -418,11 +427,11 @@ resconf_parsesortlist(irs_resconf_t *conf, FILE *fp) {
        char *p;
 
        delim = getword(fp, word, sizeof(word));
-       if (strlen(word) == 0U) {
+       if (delim == EOF || strlen(word) == 0U) {
                return ISC_R_UNEXPECTEDEND; /* Empty line after keyword. */
        }
 
-       while (strlen(word) > 0U) {
+       while (delim != EOF && strlen(word) > 0U) {
                if (conf->sortlistnxt == RESCONFMAXSORTLIST) {
                        return ISC_R_QUOTA; /* Too many values. */
                }
@@ -515,19 +524,6 @@ cleanup:
        return result;
 }
 
-static isc_result_t
-add_search(irs_resconf_t *conf, char *domain) {
-       irs_resconf_search_t *entry;
-
-       entry = isc_mem_get(conf->mctx, sizeof(*entry));
-
-       entry->domain = domain;
-       ISC_LINK_INIT(entry, link);
-       ISC_LIST_APPEND(conf->searchlist, entry, link);
-
-       return ISC_R_SUCCESS;
-}
-
 /*% parses a file and fills in the data structure. */
 isc_result_t
 irs_resconf_load(isc_mem_t *mctx, const char *filename, irs_resconf_t **confp) {
@@ -535,8 +531,7 @@ irs_resconf_load(isc_mem_t *mctx, const char *filename, irs_resconf_t **confp) {
        char word[256];
        isc_result_t rval, ret = ISC_R_SUCCESS;
        irs_resconf_t *conf;
-       unsigned int i;
-       int stopchar;
+       int stopchar = EOF;
 
        REQUIRE(mctx != NULL);
        REQUIRE(filename != NULL);
@@ -544,29 +539,24 @@ irs_resconf_load(isc_mem_t *mctx, const char *filename, irs_resconf_t **confp) {
        REQUIRE(confp != NULL && *confp == NULL);
 
        conf = isc_mem_get(mctx, sizeof(*conf));
-
-       conf->mctx = mctx;
-       ISC_LIST_INIT(conf->nameservers);
-       ISC_LIST_INIT(conf->searchlist);
-       conf->numns = 0;
-       conf->domainname = NULL;
-       conf->searchnxt = 0;
-       conf->sortlistnxt = 0;
-       conf->resdebug = 0;
-       conf->ndots = 1;
-       conf->attempts = 3;
-       conf->timeout = 0;
-       for (i = 0; i < RESCONFMAXSEARCH; i++) {
-               conf->search[i] = NULL;
-       }
+       *conf = (irs_resconf_t){
+               .mctx = mctx,
+               .nameservers = ISC_LIST_INITIALIZER,
+               .searchlist = ISC_LIST_INITIALIZER,
+               .ndots = 1,
+               .attempts = 3,
+       };
 
        errno = 0;
        if ((fp = fopen(filename, "r")) != NULL) {
-               do {
+               while (!feof(fp) && !ferror(fp)) {
                        stopchar = getword(fp, word, sizeof(word));
                        if (stopchar == EOF) {
-                               rval = ISC_R_SUCCESS;
-                               POST(rval);
+                               if (strlen(word) != 0) {
+                                       if (ret == ISC_R_SUCCESS) {
+                                               ret = ISC_R_UNEXPECTEDEND;
+                                       }
+                               }
                                break;
                        }
 
@@ -583,11 +573,10 @@ irs_resconf_load(isc_mem_t *mctx, const char *filename, irs_resconf_t **confp) {
                        } else if (strcmp(word, "options") == 0) {
                                rval = resconf_parseoption(conf, fp);
                        } else {
-                               /* unrecognised word. Ignore entire line */
+                               /* Unrecognised word. Ignore entire line. */
                                rval = ISC_R_SUCCESS;
                                if (stopchar != '\n') {
-                                       stopchar = eatline(fp);
-                                       if (stopchar == EOF) {
+                                       if (eatline(fp) == EOF) {
                                                break;
                                        }
                                }
@@ -595,7 +584,7 @@ irs_resconf_load(isc_mem_t *mctx, const char *filename, irs_resconf_t **confp) {
                        if (ret == ISC_R_SUCCESS && rval != ISC_R_SUCCESS) {
                                ret = rval;
                        }
-               } while (1);
+               }
 
                fclose(fp);
        } else {
@@ -614,17 +603,11 @@ irs_resconf_load(isc_mem_t *mctx, const char *filename, irs_resconf_t **confp) {
 
        /*
         * Construct unified search list from domain or configured
-        * search list
+        * search list. Last specified is used.
         */
        if (conf->domainname != NULL) {
+               free_search(conf);
                ret = add_search(conf, conf->domainname);
-       } else if (conf->searchnxt > 0) {
-               for (i = 0; i < conf->searchnxt; i++) {
-                       ret = add_search(conf, conf->search[i]);
-                       if (ret != ISC_R_SUCCESS) {
-                               break;
-                       }
-               }
        }
 
        /* If we don't find a nameserver fall back to localhost */
@@ -655,18 +638,13 @@ void
 irs_resconf_destroy(irs_resconf_t **confp) {
        irs_resconf_t *conf;
        isc_sockaddr_t *address;
-       irs_resconf_search_t *searchentry;
-       unsigned int i;
 
        REQUIRE(confp != NULL);
        conf = *confp;
        *confp = NULL;
        REQUIRE(IRS_RESCONF_VALID(conf));
 
-       while ((searchentry = ISC_LIST_HEAD(conf->searchlist)) != NULL) {
-               ISC_LIST_UNLINK(conf->searchlist, searchentry, link);
-               isc_mem_put(conf->mctx, searchentry, sizeof(*searchentry));
-       }
+       free_search(conf);
 
        while ((address = ISC_LIST_HEAD(conf->nameservers)) != NULL) {
                ISC_LIST_UNLINK(conf->nameservers, address, link);
@@ -677,12 +655,6 @@ irs_resconf_destroy(irs_resconf_t **confp) {
                isc_mem_free(conf->mctx, conf->domainname);
        }
 
-       for (i = 0; i < RESCONFMAXSEARCH; i++) {
-               if (conf->search[i] != NULL) {
-                       isc_mem_free(conf->mctx, conf->search[i]);
-               }
-       }
-
        isc_mem_put(conf->mctx, conf, sizeof(*conf));
 }
 
index f019ab9817de58edaf2a6c2cac2d75f2fcb7b67d..a507fefb5bc3c0197a0e3c8218a6e8033a03d0d1 100644 (file)
@@ -9,4 +9,4 @@
 # See the COPYRIGHT file distributed with this work for additional
 # information regarding copyright ownership.
 
-search example.com example.net
+search example.com n1.example.org n2.example.org n3.example.org n4.example.org n5.example.org n6.example.org n7.example.org n8.example.org example.net