]> git.ipfire.org Git - thirdparty/glibc.git/blobdiff - resolv/res_query.c
Consistency about byte vs character in string.texi
[thirdparty/glibc.git] / resolv / res_query.c
index abccd4a92105d4bc105b2b04307c7d03440bea38..4a9b3b3f27288f1c6926082ba5aadcd0427b142e 100644 (file)
@@ -98,7 +98,7 @@ static int
 __libc_res_nquerydomain(res_state statp, const char *name, const char *domain,
                        int class, int type, u_char *answer, int anslen,
                        u_char **answerp, u_char **answerp2, int *nanswerp2,
-                       int *resplen2);
+                       int *resplen2, int *answerp2_malloced);
 
 /*
  * Formulate a normal query, send, and await answer.
@@ -119,9 +119,11 @@ __libc_res_nquery(res_state statp,
                  u_char **answerp,     /* if buffer needs to be enlarged */
                  u_char **answerp2,
                  int *nanswerp2,
-                 int *resplen2)
+                 int *resplen2,
+                 int *answerp2_malloced)
 {
        HEADER *hp = (HEADER *) answer;
+       HEADER *hp2;
        int n, use_malloc = 0;
        u_int oflags = statp->_flags;
 
@@ -201,7 +203,7 @@ __libc_res_nquery(res_state statp,
                        goto again;
                }
        }
-       if (__builtin_expect (n <= 0, 0)) {
+       if (__glibc_unlikely (n <= 0))       {
                /* If the query choked with EDNS0, retry without EDNS0.  */
                if ((statp->options & (RES_USE_EDNS0|RES_USE_DNSSEC)) != 0
                    && ((oflags ^ statp->_flags) & RES_F_EDNS0ERR) != 0) {
@@ -223,7 +225,8 @@ __libc_res_nquery(res_state statp,
        }
        assert (answerp == NULL || (void *) *answerp == (void *) answer);
        n = __libc_res_nsend(statp, query1, nquery1, query2, nquery2, answer,
-                            anslen, answerp, answerp2, nanswerp2, resplen2);
+                            anslen, answerp, answerp2, nanswerp2, resplen2,
+                            answerp2_malloced);
        if (use_malloc)
                free (buf);
        if (n < 0) {
@@ -239,26 +242,25 @@ __libc_res_nquery(res_state statp,
          /* __libc_res_nsend might have reallocated the buffer.  */
          hp = (HEADER *) *answerp;
 
-       /* We simplify the following tests by assigning HP to HP2.  It
-          is easy to verify that this is the same as ignoring all
-          tests of HP2.  */
-       HEADER *hp2 = answerp2 ? (HEADER *) *answerp2 : hp;
-
-       if (n < (int) sizeof (HEADER) && answerp2 != NULL
-           && *resplen2 > (int) sizeof (HEADER))
+       /* We simplify the following tests by assigning HP to HP2 or
+          vice versa.  It is easy to verify that this is the same as
+          ignoring all tests of HP or HP2.  */
+       if (answerp2 == NULL || *resplen2 < (int) sizeof (HEADER))
          {
-           /* Special case of partial answer.  */
-           assert (hp != hp2);
-           hp = hp2;
+           hp2 = hp;
          }
-       else if (answerp2 != NULL && *resplen2 < (int) sizeof (HEADER)
-                && n > (int) sizeof (HEADER))
+       else
          {
-           /* Special case of partial answer.  */
-           assert (hp != hp2);
-           hp2 = hp;
+           hp2 = (HEADER *) *answerp2;
+           if (n < (int) sizeof (HEADER))
+             {
+               hp = hp2;
+             }
          }
 
+       /* Make sure both hp and hp2 are defined */
+       assert((hp != NULL) && (hp2 != NULL));
+
        if ((hp->rcode != NOERROR || ntohs(hp->ancount) == 0)
            && (hp2->rcode != NOERROR || ntohs(hp2->ancount) == 0)) {
 #ifdef DEBUG
@@ -316,7 +318,7 @@ res_nquery(res_state statp,
           int anslen)          /* size of answer buffer */
 {
        return __libc_res_nquery(statp, name, class, type, answer, anslen,
-                                NULL, NULL, NULL, NULL);
+                                NULL, NULL, NULL, NULL, NULL);
 }
 libresolv_hidden_def (res_nquery)
 
@@ -335,7 +337,8 @@ __libc_res_nsearch(res_state statp,
                   u_char **answerp,
                   u_char **answerp2,
                   int *nanswerp2,
-                  int *resplen2)
+                  int *resplen2,
+                  int *answerp2_malloced)
 {
        const char *cp, * const *domain;
        HEADER *hp = (HEADER *) answer;
@@ -360,7 +363,7 @@ __libc_res_nsearch(res_state statp,
        if (!dots && (cp = res_hostalias(statp, name, tmp, sizeof tmp))!= NULL)
                return (__libc_res_nquery(statp, cp, class, type, answer,
                                          anslen, answerp, answerp2,
-                                         nanswerp2, resplen2));
+                                         nanswerp2, resplen2, answerp2_malloced));
 
 #ifdef DEBUG
        if (statp->options & RES_DEBUG)
@@ -377,8 +380,11 @@ __libc_res_nsearch(res_state statp,
        if (dots >= statp->ndots || trailing_dot) {
                ret = __libc_res_nquerydomain(statp, name, NULL, class, type,
                                              answer, anslen, answerp,
-                                             answerp2, nanswerp2, resplen2);
-               if (ret > 0 || trailing_dot)
+                                             answerp2, nanswerp2, resplen2,
+                                             answerp2_malloced);
+               if (ret > 0 || trailing_dot
+                   /* If the second response is valid then we use that.  */
+                   || (ret == 0 && resplen2 != NULL && *resplen2 > 0))
                        return (ret);
                saved_herrno = h_errno;
                tried_as_is++;
@@ -386,11 +392,11 @@ __libc_res_nsearch(res_state statp,
                        answer = *answerp;
                        anslen = MAXPACKET;
                }
-               if (answerp2
-                   && (*answerp2 < answer || *answerp2 >= answer + anslen))
+               if (answerp2 && *answerp2_malloced)
                  {
                    free (*answerp2);
                    *answerp2 = NULL;
+                   *answerp2_malloced = 0;
                  }
        }
 
@@ -407,30 +413,41 @@ __libc_res_nsearch(res_state statp,
                for (domain = (const char * const *)statp->dnsrch;
                     *domain && !done;
                     domain++) {
+                       const char *dname = domain[0];
                        searched = 1;
 
-                       if (domain[0][0] == '\0' ||
-                           (domain[0][0] == '.' && domain[0][1] == '\0'))
+                       /* __libc_res_nquerydoman concatenates name
+                          with dname with a "." in between.  If we
+                          pass it in dname the "." we got from the
+                          configured default search path, we'll end
+                          up with "name..", which won't resolve.
+                          OTOH, passing it "" will result in "name.",
+                          which has the intended effect for both
+                          possible representations of the root
+                          domain.  */
+                       if (dname[0] == '.')
+                               dname++;
+                       if (dname[0] == '\0')
                                root_on_list++;
 
-                       ret = __libc_res_nquerydomain(statp, name, *domain,
+                       ret = __libc_res_nquerydomain(statp, name, dname,
                                                      class, type,
                                                      answer, anslen, answerp,
                                                      answerp2, nanswerp2,
-                                                     resplen2);
-                       if (ret > 0)
+                                                     resplen2, answerp2_malloced);
+                       if (ret > 0 || (ret == 0 && resplen2 != NULL
+                                       && *resplen2 > 0))
                                return (ret);
 
                        if (answerp && *answerp != answer) {
                                answer = *answerp;
                                anslen = MAXPACKET;
                        }
-                       if (answerp2
-                           && (*answerp2 < answer
-                               || *answerp2 >= answer + anslen))
+                       if (answerp2 && *answerp2_malloced)
                          {
                            free (*answerp2);
                            *answerp2 = NULL;
+                           *answerp2_malloced = 0;
                          }
 
                        /*
@@ -479,15 +496,17 @@ __libc_res_nsearch(res_state statp,
        }
 
        /*
-        * f the query has not already been tried as is then try it
+        * If the query has not already been tried as is then try it
         * unless RES_NOTLDQUERY is set and there were no dots.
         */
        if ((dots || !searched || (statp->options & RES_NOTLDQUERY) == 0)
            && !(tried_as_is || root_on_list)) {
                ret = __libc_res_nquerydomain(statp, name, NULL, class, type,
                                              answer, anslen, answerp,
-                                             answerp2, nanswerp2, resplen2);
-               if (ret > 0)
+                                             answerp2, nanswerp2, resplen2,
+                                             answerp2_malloced);
+               if (ret > 0 || (ret == 0 && resplen2 != NULL
+                               && *resplen2 > 0))
                        return (ret);
        }
 
@@ -498,10 +517,11 @@ __libc_res_nsearch(res_state statp,
         * else send back meaningless H_ERRNO, that being the one from
         * the last DNSRCH we did.
         */
-       if (answerp2 && (*answerp2 < answer || *answerp2 >= answer + anslen))
+       if (answerp2 && *answerp2_malloced)
          {
            free (*answerp2);
            *answerp2 = NULL;
+           *answerp2_malloced = 0;
          }
        if (saved_herrno != -1)
                RES_SET_H_ERRNO(statp, saved_herrno);
@@ -521,13 +541,12 @@ res_nsearch(res_state statp,
            int anslen)         /* size of answer */
 {
        return __libc_res_nsearch(statp, name, class, type, answer,
-                                 anslen, NULL, NULL, NULL, NULL);
+                                 anslen, NULL, NULL, NULL, NULL, NULL);
 }
 libresolv_hidden_def (res_nsearch)
 
 /*
- * Perform a call on res_query on the concatenation of name and domain,
- * removing a trailing dot from name if domain is NULL.
+ * Perform a call on res_query on the concatenation of name and domain.
  */
 static int
 __libc_res_nquerydomain(res_state statp,
@@ -539,7 +558,8 @@ __libc_res_nquerydomain(res_state statp,
                        u_char **answerp,
                        u_char **answerp2,
                        int *nanswerp2,
-                       int *resplen2)
+                       int *resplen2,
+                       int *answerp2_malloced)
 {
        char nbuf[MAXDNAME];
        const char *longname = nbuf;
@@ -551,10 +571,6 @@ __libc_res_nquerydomain(res_state statp,
                       name, domain?domain:"<Nil>", class, type);
 #endif
        if (domain == NULL) {
-               /*
-                * Check for trailing '.';
-                * copy without '.' if present.
-                */
                n = strlen(name);
 
                /* Decrement N prior to checking it against MAXDNAME
@@ -565,11 +581,7 @@ __libc_res_nquerydomain(res_state statp,
                        RES_SET_H_ERRNO(statp, NO_RECOVERY);
                        return (-1);
                }
-               if (name[n] == '.') {
-                       strncpy(nbuf, name, n);
-                       nbuf[n] = '\0';
-               } else
-                       longname = name;
+               longname = name;
        } else {
                n = strlen(name);
                d = strlen(domain);
@@ -581,7 +593,7 @@ __libc_res_nquerydomain(res_state statp,
        }
        return (__libc_res_nquery(statp, longname, class, type, answer,
                                  anslen, answerp, answerp2, nanswerp2,
-                                 resplen2));
+                                 resplen2, answerp2_malloced));
 }
 
 int
@@ -593,7 +605,8 @@ res_nquerydomain(res_state statp,
            int anslen)         /* size of answer */
 {
        return __libc_res_nquerydomain(statp, name, domain, class, type,
-                                      answer, anslen, NULL, NULL, NULL, NULL);
+                                      answer, anslen, NULL, NULL, NULL, NULL,
+                                      NULL);
 }
 libresolv_hidden_def (res_nquerydomain)