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_NETINET_IN_H
311cb0ef41Sopenharmony_ci#  include <netinet/in.h>
321cb0ef41Sopenharmony_ci#endif
331cb0ef41Sopenharmony_ci#ifdef HAVE_NETDB_H
341cb0ef41Sopenharmony_ci#  include <netdb.h>
351cb0ef41Sopenharmony_ci#endif
361cb0ef41Sopenharmony_ci#ifdef HAVE_ARPA_INET_H
371cb0ef41Sopenharmony_ci#  include <arpa/inet.h>
381cb0ef41Sopenharmony_ci#endif
391cb0ef41Sopenharmony_ci
401cb0ef41Sopenharmony_ci#include "ares_nameser.h"
411cb0ef41Sopenharmony_ci
421cb0ef41Sopenharmony_ci#include "ares.h"
431cb0ef41Sopenharmony_ci#include "ares_inet_net_pton.h"
441cb0ef41Sopenharmony_ci#include "ares_platform.h"
451cb0ef41Sopenharmony_ci#include "ares_private.h"
461cb0ef41Sopenharmony_ci
471cb0ef41Sopenharmony_ci#ifdef WATT32
481cb0ef41Sopenharmony_ci#  undef WIN32
491cb0ef41Sopenharmony_ci#endif
501cb0ef41Sopenharmony_ci
511cb0ef41Sopenharmony_cistruct addr_query {
521cb0ef41Sopenharmony_ci  /* Arguments passed to ares_gethostbyaddr() */
531cb0ef41Sopenharmony_ci  ares_channel_t    *channel;
541cb0ef41Sopenharmony_ci  struct ares_addr   addr;
551cb0ef41Sopenharmony_ci  ares_host_callback callback;
561cb0ef41Sopenharmony_ci  void              *arg;
571cb0ef41Sopenharmony_ci  char       *lookups; /* duplicate memory from channel for ares_reinit() */
581cb0ef41Sopenharmony_ci  const char *remaining_lookups;
591cb0ef41Sopenharmony_ci  size_t      timeouts;
601cb0ef41Sopenharmony_ci};
611cb0ef41Sopenharmony_ci
621cb0ef41Sopenharmony_cistatic void          next_lookup(struct addr_query *aquery);
631cb0ef41Sopenharmony_cistatic void          addr_callback(void *arg, int status, int timeouts,
641cb0ef41Sopenharmony_ci                                   unsigned char *abuf, int alen);
651cb0ef41Sopenharmony_cistatic void          end_aquery(struct addr_query *aquery, ares_status_t status,
661cb0ef41Sopenharmony_ci                                struct hostent *host);
671cb0ef41Sopenharmony_cistatic ares_status_t file_lookup(ares_channel_t         *channel,
681cb0ef41Sopenharmony_ci                                 const struct ares_addr *addr,
691cb0ef41Sopenharmony_ci                                 struct hostent        **host);
701cb0ef41Sopenharmony_ci
711cb0ef41Sopenharmony_cistatic void ares_gethostbyaddr_int(ares_channel_t *channel, const void *addr,
721cb0ef41Sopenharmony_ci                                   int addrlen, int family,
731cb0ef41Sopenharmony_ci                                   ares_host_callback callback, void *arg)
741cb0ef41Sopenharmony_ci{
751cb0ef41Sopenharmony_ci  struct addr_query *aquery;
761cb0ef41Sopenharmony_ci
771cb0ef41Sopenharmony_ci  if (family != AF_INET && family != AF_INET6) {
781cb0ef41Sopenharmony_ci    callback(arg, ARES_ENOTIMP, 0, NULL);
791cb0ef41Sopenharmony_ci    return;
801cb0ef41Sopenharmony_ci  }
811cb0ef41Sopenharmony_ci
821cb0ef41Sopenharmony_ci  if ((family == AF_INET && addrlen != sizeof(aquery->addr.addr.addr4)) ||
831cb0ef41Sopenharmony_ci      (family == AF_INET6 && addrlen != sizeof(aquery->addr.addr.addr6))) {
841cb0ef41Sopenharmony_ci    callback(arg, ARES_ENOTIMP, 0, NULL);
851cb0ef41Sopenharmony_ci    return;
861cb0ef41Sopenharmony_ci  }
871cb0ef41Sopenharmony_ci
881cb0ef41Sopenharmony_ci  aquery = ares_malloc(sizeof(struct addr_query));
891cb0ef41Sopenharmony_ci  if (!aquery) {
901cb0ef41Sopenharmony_ci    callback(arg, ARES_ENOMEM, 0, NULL);
911cb0ef41Sopenharmony_ci    return;
921cb0ef41Sopenharmony_ci  }
931cb0ef41Sopenharmony_ci  aquery->lookups = ares_strdup(channel->lookups);
941cb0ef41Sopenharmony_ci  if (aquery->lookups == NULL) {
951cb0ef41Sopenharmony_ci    ares_free(aquery);
961cb0ef41Sopenharmony_ci    callback(arg, ARES_ENOMEM, 0, NULL);
971cb0ef41Sopenharmony_ci    return;
981cb0ef41Sopenharmony_ci  }
991cb0ef41Sopenharmony_ci  aquery->channel = channel;
1001cb0ef41Sopenharmony_ci  if (family == AF_INET) {
1011cb0ef41Sopenharmony_ci    memcpy(&aquery->addr.addr.addr4, addr, sizeof(aquery->addr.addr.addr4));
1021cb0ef41Sopenharmony_ci  } else {
1031cb0ef41Sopenharmony_ci    memcpy(&aquery->addr.addr.addr6, addr, sizeof(aquery->addr.addr.addr6));
1041cb0ef41Sopenharmony_ci  }
1051cb0ef41Sopenharmony_ci  aquery->addr.family       = family;
1061cb0ef41Sopenharmony_ci  aquery->callback          = callback;
1071cb0ef41Sopenharmony_ci  aquery->arg               = arg;
1081cb0ef41Sopenharmony_ci  aquery->remaining_lookups = aquery->lookups;
1091cb0ef41Sopenharmony_ci  aquery->timeouts          = 0;
1101cb0ef41Sopenharmony_ci
1111cb0ef41Sopenharmony_ci  next_lookup(aquery);
1121cb0ef41Sopenharmony_ci}
1131cb0ef41Sopenharmony_ci
1141cb0ef41Sopenharmony_civoid ares_gethostbyaddr(ares_channel_t *channel, const void *addr, int addrlen,
1151cb0ef41Sopenharmony_ci                        int family, ares_host_callback callback, void *arg)
1161cb0ef41Sopenharmony_ci{
1171cb0ef41Sopenharmony_ci  if (channel == NULL) {
1181cb0ef41Sopenharmony_ci    return;
1191cb0ef41Sopenharmony_ci  }
1201cb0ef41Sopenharmony_ci  ares__channel_lock(channel);
1211cb0ef41Sopenharmony_ci  ares_gethostbyaddr_int(channel, addr, addrlen, family, callback, arg);
1221cb0ef41Sopenharmony_ci  ares__channel_unlock(channel);
1231cb0ef41Sopenharmony_ci}
1241cb0ef41Sopenharmony_ci
1251cb0ef41Sopenharmony_cistatic void next_lookup(struct addr_query *aquery)
1261cb0ef41Sopenharmony_ci{
1271cb0ef41Sopenharmony_ci  const char     *p;
1281cb0ef41Sopenharmony_ci  ares_status_t   status;
1291cb0ef41Sopenharmony_ci  struct hostent *host;
1301cb0ef41Sopenharmony_ci  char           *name;
1311cb0ef41Sopenharmony_ci
1321cb0ef41Sopenharmony_ci  for (p = aquery->remaining_lookups; *p; p++) {
1331cb0ef41Sopenharmony_ci    switch (*p) {
1341cb0ef41Sopenharmony_ci      case 'b':
1351cb0ef41Sopenharmony_ci        name = ares_dns_addr_to_ptr(&aquery->addr);
1361cb0ef41Sopenharmony_ci        if (name == NULL) {
1371cb0ef41Sopenharmony_ci          end_aquery(aquery, ARES_ENOMEM, NULL);
1381cb0ef41Sopenharmony_ci          return;
1391cb0ef41Sopenharmony_ci        }
1401cb0ef41Sopenharmony_ci        aquery->remaining_lookups = p + 1;
1411cb0ef41Sopenharmony_ci        ares_query(aquery->channel, name, C_IN, T_PTR, addr_callback, aquery);
1421cb0ef41Sopenharmony_ci        ares_free(name);
1431cb0ef41Sopenharmony_ci        return;
1441cb0ef41Sopenharmony_ci      case 'f':
1451cb0ef41Sopenharmony_ci        status = file_lookup(aquery->channel, &aquery->addr, &host);
1461cb0ef41Sopenharmony_ci
1471cb0ef41Sopenharmony_ci        /* this status check below previously checked for !ARES_ENOTFOUND,
1481cb0ef41Sopenharmony_ci           but we should not assume that this single error code is the one
1491cb0ef41Sopenharmony_ci           that can occur, as that is in fact no longer the case */
1501cb0ef41Sopenharmony_ci        if (status == ARES_SUCCESS) {
1511cb0ef41Sopenharmony_ci          end_aquery(aquery, status, host);
1521cb0ef41Sopenharmony_ci          return;
1531cb0ef41Sopenharmony_ci        }
1541cb0ef41Sopenharmony_ci        break;
1551cb0ef41Sopenharmony_ci      default:
1561cb0ef41Sopenharmony_ci        break;
1571cb0ef41Sopenharmony_ci    }
1581cb0ef41Sopenharmony_ci  }
1591cb0ef41Sopenharmony_ci  end_aquery(aquery, ARES_ENOTFOUND, NULL);
1601cb0ef41Sopenharmony_ci}
1611cb0ef41Sopenharmony_ci
1621cb0ef41Sopenharmony_cistatic void addr_callback(void *arg, int status, int timeouts,
1631cb0ef41Sopenharmony_ci                          unsigned char *abuf, int alen)
1641cb0ef41Sopenharmony_ci{
1651cb0ef41Sopenharmony_ci  struct addr_query *aquery = (struct addr_query *)arg;
1661cb0ef41Sopenharmony_ci  struct hostent    *host;
1671cb0ef41Sopenharmony_ci  size_t             addrlen;
1681cb0ef41Sopenharmony_ci
1691cb0ef41Sopenharmony_ci  aquery->timeouts += (size_t)timeouts;
1701cb0ef41Sopenharmony_ci  if (status == ARES_SUCCESS) {
1711cb0ef41Sopenharmony_ci    if (aquery->addr.family == AF_INET) {
1721cb0ef41Sopenharmony_ci      addrlen = sizeof(aquery->addr.addr.addr4);
1731cb0ef41Sopenharmony_ci      status  = ares_parse_ptr_reply(abuf, alen, &aquery->addr.addr.addr4,
1741cb0ef41Sopenharmony_ci                                     (int)addrlen, AF_INET, &host);
1751cb0ef41Sopenharmony_ci    } else {
1761cb0ef41Sopenharmony_ci      addrlen = sizeof(aquery->addr.addr.addr6);
1771cb0ef41Sopenharmony_ci      status  = ares_parse_ptr_reply(abuf, alen, &aquery->addr.addr.addr6,
1781cb0ef41Sopenharmony_ci                                     (int)addrlen, AF_INET6, &host);
1791cb0ef41Sopenharmony_ci    }
1801cb0ef41Sopenharmony_ci    end_aquery(aquery, (ares_status_t)status, host);
1811cb0ef41Sopenharmony_ci  } else if (status == ARES_EDESTRUCTION || status == ARES_ECANCELLED) {
1821cb0ef41Sopenharmony_ci    end_aquery(aquery, (ares_status_t)status, NULL);
1831cb0ef41Sopenharmony_ci  } else {
1841cb0ef41Sopenharmony_ci    next_lookup(aquery);
1851cb0ef41Sopenharmony_ci  }
1861cb0ef41Sopenharmony_ci}
1871cb0ef41Sopenharmony_ci
1881cb0ef41Sopenharmony_cistatic void end_aquery(struct addr_query *aquery, ares_status_t status,
1891cb0ef41Sopenharmony_ci                       struct hostent *host)
1901cb0ef41Sopenharmony_ci{
1911cb0ef41Sopenharmony_ci  aquery->callback(aquery->arg, (int)status, (int)aquery->timeouts, host);
1921cb0ef41Sopenharmony_ci  if (host) {
1931cb0ef41Sopenharmony_ci    ares_free_hostent(host);
1941cb0ef41Sopenharmony_ci  }
1951cb0ef41Sopenharmony_ci  ares_free(aquery->lookups);
1961cb0ef41Sopenharmony_ci  ares_free(aquery);
1971cb0ef41Sopenharmony_ci}
1981cb0ef41Sopenharmony_ci
1991cb0ef41Sopenharmony_cistatic ares_status_t file_lookup(ares_channel_t         *channel,
2001cb0ef41Sopenharmony_ci                                 const struct ares_addr *addr,
2011cb0ef41Sopenharmony_ci                                 struct hostent        **host)
2021cb0ef41Sopenharmony_ci{
2031cb0ef41Sopenharmony_ci  char                      ipaddr[INET6_ADDRSTRLEN];
2041cb0ef41Sopenharmony_ci  const void               *ptr = NULL;
2051cb0ef41Sopenharmony_ci  const ares_hosts_entry_t *entry;
2061cb0ef41Sopenharmony_ci  ares_status_t             status;
2071cb0ef41Sopenharmony_ci
2081cb0ef41Sopenharmony_ci  if (addr->family == AF_INET) {
2091cb0ef41Sopenharmony_ci    ptr = &addr->addr.addr4;
2101cb0ef41Sopenharmony_ci  } else if (addr->family == AF_INET6) {
2111cb0ef41Sopenharmony_ci    ptr = &addr->addr.addr6;
2121cb0ef41Sopenharmony_ci  }
2131cb0ef41Sopenharmony_ci
2141cb0ef41Sopenharmony_ci  if (ptr == NULL) {
2151cb0ef41Sopenharmony_ci    return ARES_ENOTFOUND;
2161cb0ef41Sopenharmony_ci  }
2171cb0ef41Sopenharmony_ci
2181cb0ef41Sopenharmony_ci  if (!ares_inet_ntop(addr->family, ptr, ipaddr, sizeof(ipaddr))) {
2191cb0ef41Sopenharmony_ci    return ARES_ENOTFOUND;
2201cb0ef41Sopenharmony_ci  }
2211cb0ef41Sopenharmony_ci
2221cb0ef41Sopenharmony_ci  status = ares__hosts_search_ipaddr(channel, ARES_FALSE, ipaddr, &entry);
2231cb0ef41Sopenharmony_ci  if (status != ARES_SUCCESS) {
2241cb0ef41Sopenharmony_ci    return status;
2251cb0ef41Sopenharmony_ci  }
2261cb0ef41Sopenharmony_ci
2271cb0ef41Sopenharmony_ci  status = ares__hosts_entry_to_hostent(entry, addr->family, host);
2281cb0ef41Sopenharmony_ci  if (status != ARES_SUCCESS) {
2291cb0ef41Sopenharmony_ci    return status;
2301cb0ef41Sopenharmony_ci  }
2311cb0ef41Sopenharmony_ci
2321cb0ef41Sopenharmony_ci  return ARES_SUCCESS;
2331cb0ef41Sopenharmony_ci}
234