11cb0ef41Sopenharmony_ci/* MIT License
21cb0ef41Sopenharmony_ci *
31cb0ef41Sopenharmony_ci * Copyright (c) 1998 Massachusetts Institute of Technology
41cb0ef41Sopenharmony_ci * Copyright (c) The c-ares project and its contributors
51cb0ef41Sopenharmony_ci *
61cb0ef41Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a copy
71cb0ef41Sopenharmony_ci * of this software and associated documentation files (the "Software"), to deal
81cb0ef41Sopenharmony_ci * in the Software without restriction, including without limitation the rights
91cb0ef41Sopenharmony_ci * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
101cb0ef41Sopenharmony_ci * copies of the Software, and to permit persons to whom the Software is
111cb0ef41Sopenharmony_ci * furnished to do so, subject to the following conditions:
121cb0ef41Sopenharmony_ci *
131cb0ef41Sopenharmony_ci * The above copyright notice and this permission notice (including the next
141cb0ef41Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the
151cb0ef41Sopenharmony_ci * Software.
161cb0ef41Sopenharmony_ci *
171cb0ef41Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
181cb0ef41Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
191cb0ef41Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
201cb0ef41Sopenharmony_ci * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
211cb0ef41Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
221cb0ef41Sopenharmony_ci * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
231cb0ef41Sopenharmony_ci * SOFTWARE.
241cb0ef41Sopenharmony_ci *
251cb0ef41Sopenharmony_ci * SPDX-License-Identifier: MIT
261cb0ef41Sopenharmony_ci */
271cb0ef41Sopenharmony_ci
281cb0ef41Sopenharmony_ci#include "ares_setup.h"
291cb0ef41Sopenharmony_ci
301cb0ef41Sopenharmony_ci#ifdef HAVE_STRINGS_H
311cb0ef41Sopenharmony_ci#  include <strings.h>
321cb0ef41Sopenharmony_ci#endif
331cb0ef41Sopenharmony_ci
341cb0ef41Sopenharmony_ci#include "ares.h"
351cb0ef41Sopenharmony_ci#include "ares_private.h"
361cb0ef41Sopenharmony_ci
371cb0ef41Sopenharmony_cistruct search_query {
381cb0ef41Sopenharmony_ci  /* Arguments passed to ares_search */
391cb0ef41Sopenharmony_ci  ares_channel_t *channel;
401cb0ef41Sopenharmony_ci  char           *name; /* copied into an allocated buffer */
411cb0ef41Sopenharmony_ci  int             dnsclass;
421cb0ef41Sopenharmony_ci  int             type;
431cb0ef41Sopenharmony_ci  ares_callback   callback;
441cb0ef41Sopenharmony_ci  void           *arg;
451cb0ef41Sopenharmony_ci  char          **domains; /* duplicate for ares_reinit() safety */
461cb0ef41Sopenharmony_ci  size_t          ndomains;
471cb0ef41Sopenharmony_ci
481cb0ef41Sopenharmony_ci  int             status_as_is; /* error status from trying as-is */
491cb0ef41Sopenharmony_ci  size_t          next_domain;  /* next search domain to try */
501cb0ef41Sopenharmony_ci  ares_bool_t     trying_as_is; /* current query is for name as-is */
511cb0ef41Sopenharmony_ci  size_t          timeouts;     /* number of timeouts we saw for this request */
521cb0ef41Sopenharmony_ci  ares_bool_t ever_got_nodata; /* did we ever get ARES_ENODATA along the way? */
531cb0ef41Sopenharmony_ci};
541cb0ef41Sopenharmony_ci
551cb0ef41Sopenharmony_cistatic void search_callback(void *arg, int status, int timeouts,
561cb0ef41Sopenharmony_ci                            unsigned char *abuf, int alen);
571cb0ef41Sopenharmony_cistatic void end_squery(struct search_query *squery, ares_status_t status,
581cb0ef41Sopenharmony_ci                       unsigned char *abuf, size_t alen);
591cb0ef41Sopenharmony_ci
601cb0ef41Sopenharmony_cistatic void ares_search_int(ares_channel_t *channel, const char *name,
611cb0ef41Sopenharmony_ci                            int dnsclass, int type, ares_callback callback,
621cb0ef41Sopenharmony_ci                            void *arg)
631cb0ef41Sopenharmony_ci{
641cb0ef41Sopenharmony_ci  struct search_query *squery;
651cb0ef41Sopenharmony_ci  char                *s;
661cb0ef41Sopenharmony_ci  const char          *p;
671cb0ef41Sopenharmony_ci  ares_status_t        status;
681cb0ef41Sopenharmony_ci  size_t               ndots;
691cb0ef41Sopenharmony_ci
701cb0ef41Sopenharmony_ci  /* Per RFC 7686, reject queries for ".onion" domain names with NXDOMAIN. */
711cb0ef41Sopenharmony_ci  if (ares__is_onion_domain(name)) {
721cb0ef41Sopenharmony_ci    callback(arg, ARES_ENOTFOUND, 0, NULL, 0);
731cb0ef41Sopenharmony_ci    return;
741cb0ef41Sopenharmony_ci  }
751cb0ef41Sopenharmony_ci
761cb0ef41Sopenharmony_ci  /* If name only yields one domain to search, then we don't have
771cb0ef41Sopenharmony_ci   * to keep extra state, so just do an ares_query().
781cb0ef41Sopenharmony_ci   */
791cb0ef41Sopenharmony_ci  status = ares__single_domain(channel, name, &s);
801cb0ef41Sopenharmony_ci  if (status != ARES_SUCCESS) {
811cb0ef41Sopenharmony_ci    callback(arg, (int)status, 0, NULL, 0);
821cb0ef41Sopenharmony_ci    return;
831cb0ef41Sopenharmony_ci  }
841cb0ef41Sopenharmony_ci  if (s) {
851cb0ef41Sopenharmony_ci    ares_query(channel, s, dnsclass, type, callback, arg);
861cb0ef41Sopenharmony_ci    ares_free(s);
871cb0ef41Sopenharmony_ci    return;
881cb0ef41Sopenharmony_ci  }
891cb0ef41Sopenharmony_ci
901cb0ef41Sopenharmony_ci  /* Allocate a search_query structure to hold the state necessary for
911cb0ef41Sopenharmony_ci   * doing multiple lookups.
921cb0ef41Sopenharmony_ci   */
931cb0ef41Sopenharmony_ci  squery = ares_malloc_zero(sizeof(*squery));
941cb0ef41Sopenharmony_ci  if (!squery) {
951cb0ef41Sopenharmony_ci    callback(arg, ARES_ENOMEM, 0, NULL, 0);
961cb0ef41Sopenharmony_ci    return;
971cb0ef41Sopenharmony_ci  }
981cb0ef41Sopenharmony_ci  squery->channel = channel;
991cb0ef41Sopenharmony_ci  squery->name    = ares_strdup(name);
1001cb0ef41Sopenharmony_ci  if (!squery->name) {
1011cb0ef41Sopenharmony_ci    ares_free(squery);
1021cb0ef41Sopenharmony_ci    callback(arg, ARES_ENOMEM, 0, NULL, 0);
1031cb0ef41Sopenharmony_ci    return;
1041cb0ef41Sopenharmony_ci  }
1051cb0ef41Sopenharmony_ci
1061cb0ef41Sopenharmony_ci  /* Duplicate domains for safety during ares_reinit() */
1071cb0ef41Sopenharmony_ci  if (channel->ndomains) {
1081cb0ef41Sopenharmony_ci    squery->domains =
1091cb0ef41Sopenharmony_ci      ares__strsplit_duplicate(channel->domains, channel->ndomains);
1101cb0ef41Sopenharmony_ci    if (squery->domains == NULL) {
1111cb0ef41Sopenharmony_ci      ares_free(squery->name);
1121cb0ef41Sopenharmony_ci      ares_free(squery);
1131cb0ef41Sopenharmony_ci      callback(arg, ARES_ENOMEM, 0, NULL, 0);
1141cb0ef41Sopenharmony_ci      return;
1151cb0ef41Sopenharmony_ci    }
1161cb0ef41Sopenharmony_ci    squery->ndomains = channel->ndomains;
1171cb0ef41Sopenharmony_ci  }
1181cb0ef41Sopenharmony_ci
1191cb0ef41Sopenharmony_ci  squery->dnsclass        = dnsclass;
1201cb0ef41Sopenharmony_ci  squery->type            = type;
1211cb0ef41Sopenharmony_ci  squery->status_as_is    = -1;
1221cb0ef41Sopenharmony_ci  squery->callback        = callback;
1231cb0ef41Sopenharmony_ci  squery->arg             = arg;
1241cb0ef41Sopenharmony_ci  squery->timeouts        = 0;
1251cb0ef41Sopenharmony_ci  squery->ever_got_nodata = ARES_FALSE;
1261cb0ef41Sopenharmony_ci
1271cb0ef41Sopenharmony_ci  /* Count the number of dots in name. */
1281cb0ef41Sopenharmony_ci  ndots = 0;
1291cb0ef41Sopenharmony_ci  for (p = name; *p; p++) {
1301cb0ef41Sopenharmony_ci    if (*p == '.') {
1311cb0ef41Sopenharmony_ci      ndots++;
1321cb0ef41Sopenharmony_ci    }
1331cb0ef41Sopenharmony_ci  }
1341cb0ef41Sopenharmony_ci
1351cb0ef41Sopenharmony_ci  /* If ndots is at least the channel ndots threshold (usually 1),
1361cb0ef41Sopenharmony_ci   * then we try the name as-is first.  Otherwise, we try the name
1371cb0ef41Sopenharmony_ci   * as-is last.
1381cb0ef41Sopenharmony_ci   */
1391cb0ef41Sopenharmony_ci  if (ndots >= channel->ndots || squery->ndomains == 0) {
1401cb0ef41Sopenharmony_ci    /* Try the name as-is first. */
1411cb0ef41Sopenharmony_ci    squery->next_domain  = 0;
1421cb0ef41Sopenharmony_ci    squery->trying_as_is = ARES_TRUE;
1431cb0ef41Sopenharmony_ci    ares_query(channel, name, dnsclass, type, search_callback, squery);
1441cb0ef41Sopenharmony_ci  } else {
1451cb0ef41Sopenharmony_ci    /* Try the name as-is last; start with the first search domain. */
1461cb0ef41Sopenharmony_ci    squery->next_domain  = 1;
1471cb0ef41Sopenharmony_ci    squery->trying_as_is = ARES_FALSE;
1481cb0ef41Sopenharmony_ci    status               = ares__cat_domain(name, squery->domains[0], &s);
1491cb0ef41Sopenharmony_ci    if (status == ARES_SUCCESS) {
1501cb0ef41Sopenharmony_ci      ares_query(channel, s, dnsclass, type, search_callback, squery);
1511cb0ef41Sopenharmony_ci      ares_free(s);
1521cb0ef41Sopenharmony_ci    } else {
1531cb0ef41Sopenharmony_ci      /* failed, free the malloc()ed memory */
1541cb0ef41Sopenharmony_ci      ares_free(squery->name);
1551cb0ef41Sopenharmony_ci      ares_free(squery);
1561cb0ef41Sopenharmony_ci      callback(arg, (int)status, 0, NULL, 0);
1571cb0ef41Sopenharmony_ci    }
1581cb0ef41Sopenharmony_ci  }
1591cb0ef41Sopenharmony_ci}
1601cb0ef41Sopenharmony_ci
1611cb0ef41Sopenharmony_civoid ares_search(ares_channel_t *channel, const char *name, int dnsclass,
1621cb0ef41Sopenharmony_ci                 int type, ares_callback callback, void *arg)
1631cb0ef41Sopenharmony_ci{
1641cb0ef41Sopenharmony_ci  if (channel == NULL) {
1651cb0ef41Sopenharmony_ci    return;
1661cb0ef41Sopenharmony_ci  }
1671cb0ef41Sopenharmony_ci  ares__channel_lock(channel);
1681cb0ef41Sopenharmony_ci  ares_search_int(channel, name, dnsclass, type, callback, arg);
1691cb0ef41Sopenharmony_ci  ares__channel_unlock(channel);
1701cb0ef41Sopenharmony_ci}
1711cb0ef41Sopenharmony_ci
1721cb0ef41Sopenharmony_cistatic void search_callback(void *arg, int status, int timeouts,
1731cb0ef41Sopenharmony_ci                            unsigned char *abuf, int alen)
1741cb0ef41Sopenharmony_ci{
1751cb0ef41Sopenharmony_ci  struct search_query *squery  = (struct search_query *)arg;
1761cb0ef41Sopenharmony_ci  ares_channel_t      *channel = squery->channel;
1771cb0ef41Sopenharmony_ci  char                *s;
1781cb0ef41Sopenharmony_ci
1791cb0ef41Sopenharmony_ci  squery->timeouts += (size_t)timeouts;
1801cb0ef41Sopenharmony_ci
1811cb0ef41Sopenharmony_ci  /* Stop searching unless we got a non-fatal error. */
1821cb0ef41Sopenharmony_ci  if (status != ARES_ENODATA && status != ARES_ESERVFAIL &&
1831cb0ef41Sopenharmony_ci      status != ARES_ENOTFOUND) {
1841cb0ef41Sopenharmony_ci    end_squery(squery, (ares_status_t)status, abuf, (size_t)alen);
1851cb0ef41Sopenharmony_ci  } else {
1861cb0ef41Sopenharmony_ci    /* Save the status if we were trying as-is. */
1871cb0ef41Sopenharmony_ci    if (squery->trying_as_is) {
1881cb0ef41Sopenharmony_ci      squery->status_as_is = status;
1891cb0ef41Sopenharmony_ci    }
1901cb0ef41Sopenharmony_ci
1911cb0ef41Sopenharmony_ci    /*
1921cb0ef41Sopenharmony_ci     * If we ever get ARES_ENODATA along the way, record that; if the search
1931cb0ef41Sopenharmony_ci     * should run to the very end and we got at least one ARES_ENODATA,
1941cb0ef41Sopenharmony_ci     * then callers like ares_gethostbyname() may want to try a T_A search
1951cb0ef41Sopenharmony_ci     * even if the last domain we queried for T_AAAA resource records
1961cb0ef41Sopenharmony_ci     * returned ARES_ENOTFOUND.
1971cb0ef41Sopenharmony_ci     */
1981cb0ef41Sopenharmony_ci    if (status == ARES_ENODATA) {
1991cb0ef41Sopenharmony_ci      squery->ever_got_nodata = ARES_TRUE;
2001cb0ef41Sopenharmony_ci    }
2011cb0ef41Sopenharmony_ci
2021cb0ef41Sopenharmony_ci    if (squery->next_domain < squery->ndomains) {
2031cb0ef41Sopenharmony_ci      ares_status_t mystatus;
2041cb0ef41Sopenharmony_ci      /* Try the next domain. */
2051cb0ef41Sopenharmony_ci      mystatus = ares__cat_domain(squery->name,
2061cb0ef41Sopenharmony_ci                                  squery->domains[squery->next_domain], &s);
2071cb0ef41Sopenharmony_ci      if (mystatus != ARES_SUCCESS) {
2081cb0ef41Sopenharmony_ci        end_squery(squery, mystatus, NULL, 0);
2091cb0ef41Sopenharmony_ci      } else {
2101cb0ef41Sopenharmony_ci        squery->trying_as_is = ARES_FALSE;
2111cb0ef41Sopenharmony_ci        squery->next_domain++;
2121cb0ef41Sopenharmony_ci        ares_query(channel, s, squery->dnsclass, squery->type, search_callback,
2131cb0ef41Sopenharmony_ci                   squery);
2141cb0ef41Sopenharmony_ci        ares_free(s);
2151cb0ef41Sopenharmony_ci      }
2161cb0ef41Sopenharmony_ci    } else if (squery->status_as_is == -1) {
2171cb0ef41Sopenharmony_ci      /* Try the name as-is at the end. */
2181cb0ef41Sopenharmony_ci      squery->trying_as_is = ARES_TRUE;
2191cb0ef41Sopenharmony_ci      ares_query(channel, squery->name, squery->dnsclass, squery->type,
2201cb0ef41Sopenharmony_ci                 search_callback, squery);
2211cb0ef41Sopenharmony_ci    } else {
2221cb0ef41Sopenharmony_ci      if (squery->status_as_is == ARES_ENOTFOUND && squery->ever_got_nodata) {
2231cb0ef41Sopenharmony_ci        end_squery(squery, ARES_ENODATA, NULL, 0);
2241cb0ef41Sopenharmony_ci      } else {
2251cb0ef41Sopenharmony_ci        end_squery(squery, (ares_status_t)squery->status_as_is, NULL, 0);
2261cb0ef41Sopenharmony_ci      }
2271cb0ef41Sopenharmony_ci    }
2281cb0ef41Sopenharmony_ci  }
2291cb0ef41Sopenharmony_ci}
2301cb0ef41Sopenharmony_ci
2311cb0ef41Sopenharmony_cistatic void end_squery(struct search_query *squery, ares_status_t status,
2321cb0ef41Sopenharmony_ci                       unsigned char *abuf, size_t alen)
2331cb0ef41Sopenharmony_ci{
2341cb0ef41Sopenharmony_ci  squery->callback(squery->arg, (int)status, (int)squery->timeouts, abuf,
2351cb0ef41Sopenharmony_ci                   (int)alen);
2361cb0ef41Sopenharmony_ci  ares__strsplit_free(squery->domains, squery->ndomains);
2371cb0ef41Sopenharmony_ci  ares_free(squery->name);
2381cb0ef41Sopenharmony_ci  ares_free(squery);
2391cb0ef41Sopenharmony_ci}
2401cb0ef41Sopenharmony_ci
2411cb0ef41Sopenharmony_ci/* Concatenate two domains. */
2421cb0ef41Sopenharmony_ciares_status_t ares__cat_domain(const char *name, const char *domain, char **s)
2431cb0ef41Sopenharmony_ci{
2441cb0ef41Sopenharmony_ci  size_t nlen = ares_strlen(name);
2451cb0ef41Sopenharmony_ci  size_t dlen = ares_strlen(domain);
2461cb0ef41Sopenharmony_ci
2471cb0ef41Sopenharmony_ci  *s = ares_malloc(nlen + 1 + dlen + 1);
2481cb0ef41Sopenharmony_ci  if (!*s) {
2491cb0ef41Sopenharmony_ci    return ARES_ENOMEM;
2501cb0ef41Sopenharmony_ci  }
2511cb0ef41Sopenharmony_ci  memcpy(*s, name, nlen);
2521cb0ef41Sopenharmony_ci  (*s)[nlen] = '.';
2531cb0ef41Sopenharmony_ci  if (strcmp(domain, ".") == 0) {
2541cb0ef41Sopenharmony_ci    /* Avoid appending the root domain to the separator, which would set *s to
2551cb0ef41Sopenharmony_ci       an ill-formed value (ending in two consecutive dots). */
2561cb0ef41Sopenharmony_ci    dlen = 0;
2571cb0ef41Sopenharmony_ci  }
2581cb0ef41Sopenharmony_ci  memcpy(*s + nlen + 1, domain, dlen);
2591cb0ef41Sopenharmony_ci  (*s)[nlen + 1 + dlen] = 0;
2601cb0ef41Sopenharmony_ci  return ARES_SUCCESS;
2611cb0ef41Sopenharmony_ci}
2621cb0ef41Sopenharmony_ci
2631cb0ef41Sopenharmony_ci/* Determine if this name only yields one query.  If it does, set *s to
2641cb0ef41Sopenharmony_ci * the string we should query, in an allocated buffer.  If not, set *s
2651cb0ef41Sopenharmony_ci * to NULL.
2661cb0ef41Sopenharmony_ci */
2671cb0ef41Sopenharmony_ciares_status_t ares__single_domain(const ares_channel_t *channel,
2681cb0ef41Sopenharmony_ci                                  const char *name, char **s)
2691cb0ef41Sopenharmony_ci{
2701cb0ef41Sopenharmony_ci  size_t        len = ares_strlen(name);
2711cb0ef41Sopenharmony_ci  const char   *hostaliases;
2721cb0ef41Sopenharmony_ci  FILE         *fp;
2731cb0ef41Sopenharmony_ci  char         *line = NULL;
2741cb0ef41Sopenharmony_ci  ares_status_t status;
2751cb0ef41Sopenharmony_ci  size_t        linesize;
2761cb0ef41Sopenharmony_ci  const char   *p;
2771cb0ef41Sopenharmony_ci  const char   *q;
2781cb0ef41Sopenharmony_ci  int           error;
2791cb0ef41Sopenharmony_ci
2801cb0ef41Sopenharmony_ci  /* If the name contains a trailing dot, then the single query is the name
2811cb0ef41Sopenharmony_ci   * sans the trailing dot.
2821cb0ef41Sopenharmony_ci   */
2831cb0ef41Sopenharmony_ci  if ((len > 0) && (name[len - 1] == '.')) {
2841cb0ef41Sopenharmony_ci    *s = ares_strdup(name);
2851cb0ef41Sopenharmony_ci    return (*s) ? ARES_SUCCESS : ARES_ENOMEM;
2861cb0ef41Sopenharmony_ci  }
2871cb0ef41Sopenharmony_ci
2881cb0ef41Sopenharmony_ci  if (!(channel->flags & ARES_FLAG_NOALIASES) && !strchr(name, '.')) {
2891cb0ef41Sopenharmony_ci    /* The name might be a host alias. */
2901cb0ef41Sopenharmony_ci    hostaliases = getenv("HOSTALIASES");
2911cb0ef41Sopenharmony_ci    if (hostaliases) {
2921cb0ef41Sopenharmony_ci      fp = fopen(hostaliases, "r");
2931cb0ef41Sopenharmony_ci      if (fp) {
2941cb0ef41Sopenharmony_ci        while ((status = ares__read_line(fp, &line, &linesize)) ==
2951cb0ef41Sopenharmony_ci               ARES_SUCCESS) {
2961cb0ef41Sopenharmony_ci          if (strncasecmp(line, name, len) != 0 || !ISSPACE(line[len])) {
2971cb0ef41Sopenharmony_ci            continue;
2981cb0ef41Sopenharmony_ci          }
2991cb0ef41Sopenharmony_ci          p = line + len;
3001cb0ef41Sopenharmony_ci          while (ISSPACE(*p)) {
3011cb0ef41Sopenharmony_ci            p++;
3021cb0ef41Sopenharmony_ci          }
3031cb0ef41Sopenharmony_ci          if (*p) {
3041cb0ef41Sopenharmony_ci            q = p + 1;
3051cb0ef41Sopenharmony_ci            while (*q && !ISSPACE(*q)) {
3061cb0ef41Sopenharmony_ci              q++;
3071cb0ef41Sopenharmony_ci            }
3081cb0ef41Sopenharmony_ci            *s = ares_malloc((size_t)(q - p + 1));
3091cb0ef41Sopenharmony_ci            if (*s) {
3101cb0ef41Sopenharmony_ci              memcpy(*s, p, (size_t)(q - p));
3111cb0ef41Sopenharmony_ci              (*s)[q - p] = 0;
3121cb0ef41Sopenharmony_ci            }
3131cb0ef41Sopenharmony_ci            ares_free(line);
3141cb0ef41Sopenharmony_ci            fclose(fp);
3151cb0ef41Sopenharmony_ci            return (*s) ? ARES_SUCCESS : ARES_ENOMEM;
3161cb0ef41Sopenharmony_ci          }
3171cb0ef41Sopenharmony_ci        }
3181cb0ef41Sopenharmony_ci        ares_free(line);
3191cb0ef41Sopenharmony_ci        fclose(fp);
3201cb0ef41Sopenharmony_ci        if (status != ARES_SUCCESS && status != ARES_EOF) {
3211cb0ef41Sopenharmony_ci          return status;
3221cb0ef41Sopenharmony_ci        }
3231cb0ef41Sopenharmony_ci      } else {
3241cb0ef41Sopenharmony_ci        error = ERRNO;
3251cb0ef41Sopenharmony_ci        switch (error) {
3261cb0ef41Sopenharmony_ci          case ENOENT:
3271cb0ef41Sopenharmony_ci          case ESRCH:
3281cb0ef41Sopenharmony_ci            break;
3291cb0ef41Sopenharmony_ci          default:
3301cb0ef41Sopenharmony_ci            DEBUGF(fprintf(stderr, "fopen() failed with error: %d %s\n", error,
3311cb0ef41Sopenharmony_ci                           strerror(error)));
3321cb0ef41Sopenharmony_ci            DEBUGF(fprintf(stderr, "Error opening file: %s\n", hostaliases));
3331cb0ef41Sopenharmony_ci            *s = NULL;
3341cb0ef41Sopenharmony_ci            return ARES_EFILE;
3351cb0ef41Sopenharmony_ci        }
3361cb0ef41Sopenharmony_ci      }
3371cb0ef41Sopenharmony_ci    }
3381cb0ef41Sopenharmony_ci  }
3391cb0ef41Sopenharmony_ci
3401cb0ef41Sopenharmony_ci  if (channel->flags & ARES_FLAG_NOSEARCH || channel->ndomains == 0) {
3411cb0ef41Sopenharmony_ci    /* No domain search to do; just try the name as-is. */
3421cb0ef41Sopenharmony_ci    *s = ares_strdup(name);
3431cb0ef41Sopenharmony_ci    return (*s) ? ARES_SUCCESS : ARES_ENOMEM;
3441cb0ef41Sopenharmony_ci  }
3451cb0ef41Sopenharmony_ci
3461cb0ef41Sopenharmony_ci  *s = NULL;
3471cb0ef41Sopenharmony_ci  return ARES_SUCCESS;
3481cb0ef41Sopenharmony_ci}
349