11cb0ef41Sopenharmony_ci/* MIT License 21cb0ef41Sopenharmony_ci * 31cb0ef41Sopenharmony_ci * Copyright (c) 2005, 2013 Dominick Meglio 41cb0ef41Sopenharmony_ci * 51cb0ef41Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a copy 61cb0ef41Sopenharmony_ci * of this software and associated documentation files (the "Software"), to deal 71cb0ef41Sopenharmony_ci * in the Software without restriction, including without limitation the rights 81cb0ef41Sopenharmony_ci * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 91cb0ef41Sopenharmony_ci * copies of the Software, and to permit persons to whom the Software is 101cb0ef41Sopenharmony_ci * furnished to do so, subject to the following conditions: 111cb0ef41Sopenharmony_ci * 121cb0ef41Sopenharmony_ci * The above copyright notice and this permission notice (including the next 131cb0ef41Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the 141cb0ef41Sopenharmony_ci * Software. 151cb0ef41Sopenharmony_ci * 161cb0ef41Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 171cb0ef41Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 181cb0ef41Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 191cb0ef41Sopenharmony_ci * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 201cb0ef41Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 211cb0ef41Sopenharmony_ci * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 221cb0ef41Sopenharmony_ci * SOFTWARE. 231cb0ef41Sopenharmony_ci * 241cb0ef41Sopenharmony_ci * SPDX-License-Identifier: MIT 251cb0ef41Sopenharmony_ci */ 261cb0ef41Sopenharmony_ci#include "ares_setup.h" 271cb0ef41Sopenharmony_ci 281cb0ef41Sopenharmony_ci#ifdef HAVE_GETSERVBYPORT_R 291cb0ef41Sopenharmony_ci# if !defined(GETSERVBYPORT_R_ARGS) || (GETSERVBYPORT_R_ARGS < 4) || \ 301cb0ef41Sopenharmony_ci (GETSERVBYPORT_R_ARGS > 6) 311cb0ef41Sopenharmony_ci# error "you MUST specify a valid number of arguments for getservbyport_r" 321cb0ef41Sopenharmony_ci# endif 331cb0ef41Sopenharmony_ci#endif 341cb0ef41Sopenharmony_ci 351cb0ef41Sopenharmony_ci#ifdef HAVE_NETINET_IN_H 361cb0ef41Sopenharmony_ci# include <netinet/in.h> 371cb0ef41Sopenharmony_ci#endif 381cb0ef41Sopenharmony_ci#ifdef HAVE_NETDB_H 391cb0ef41Sopenharmony_ci# include <netdb.h> 401cb0ef41Sopenharmony_ci#endif 411cb0ef41Sopenharmony_ci#ifdef HAVE_ARPA_INET_H 421cb0ef41Sopenharmony_ci# include <arpa/inet.h> 431cb0ef41Sopenharmony_ci#endif 441cb0ef41Sopenharmony_ci 451cb0ef41Sopenharmony_ci#include "ares_nameser.h" 461cb0ef41Sopenharmony_ci 471cb0ef41Sopenharmony_ci#ifdef HAVE_NET_IF_H 481cb0ef41Sopenharmony_ci# include <net/if.h> 491cb0ef41Sopenharmony_ci#endif 501cb0ef41Sopenharmony_ci#if defined(USE_WINSOCK) && defined(HAVE_IPHLPAPI_H) 511cb0ef41Sopenharmony_ci# include <iphlpapi.h> 521cb0ef41Sopenharmony_ci#endif 531cb0ef41Sopenharmony_ci 541cb0ef41Sopenharmony_ci#include "ares.h" 551cb0ef41Sopenharmony_ci#include "ares_ipv6.h" 561cb0ef41Sopenharmony_ci#include "ares_private.h" 571cb0ef41Sopenharmony_ci 581cb0ef41Sopenharmony_cistruct nameinfo_query { 591cb0ef41Sopenharmony_ci ares_nameinfo_callback callback; 601cb0ef41Sopenharmony_ci void *arg; 611cb0ef41Sopenharmony_ci 621cb0ef41Sopenharmony_ci union { 631cb0ef41Sopenharmony_ci struct sockaddr_in addr4; 641cb0ef41Sopenharmony_ci struct sockaddr_in6 addr6; 651cb0ef41Sopenharmony_ci } addr; 661cb0ef41Sopenharmony_ci 671cb0ef41Sopenharmony_ci int family; 681cb0ef41Sopenharmony_ci unsigned int flags; 691cb0ef41Sopenharmony_ci size_t timeouts; 701cb0ef41Sopenharmony_ci}; 711cb0ef41Sopenharmony_ci 721cb0ef41Sopenharmony_ci#ifdef HAVE_STRUCT_SOCKADDR_IN6_SIN6_SCOPE_ID 731cb0ef41Sopenharmony_ci# define IPBUFSIZ \ 741cb0ef41Sopenharmony_ci (sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255") + IF_NAMESIZE) 751cb0ef41Sopenharmony_ci#else 761cb0ef41Sopenharmony_ci# define IPBUFSIZ (sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")) 771cb0ef41Sopenharmony_ci#endif 781cb0ef41Sopenharmony_ci 791cb0ef41Sopenharmony_cistatic void nameinfo_callback(void *arg, int status, int timeouts, 801cb0ef41Sopenharmony_ci struct hostent *host); 811cb0ef41Sopenharmony_cistatic char *lookup_service(unsigned short port, unsigned int flags, char *buf, 821cb0ef41Sopenharmony_ci size_t buflen); 831cb0ef41Sopenharmony_ci#ifdef HAVE_STRUCT_SOCKADDR_IN6_SIN6_SCOPE_ID 841cb0ef41Sopenharmony_cistatic void append_scopeid(const struct sockaddr_in6 *addr6, 851cb0ef41Sopenharmony_ci unsigned int scopeid, char *buf, size_t buflen); 861cb0ef41Sopenharmony_ci#endif 871cb0ef41Sopenharmony_cistatic char *ares_striendstr(const char *s1, const char *s2); 881cb0ef41Sopenharmony_ci 891cb0ef41Sopenharmony_cistatic void ares_getnameinfo_int(ares_channel_t *channel, 901cb0ef41Sopenharmony_ci const struct sockaddr *sa, 911cb0ef41Sopenharmony_ci ares_socklen_t salen, int flags_int, 921cb0ef41Sopenharmony_ci ares_nameinfo_callback callback, void *arg) 931cb0ef41Sopenharmony_ci{ 941cb0ef41Sopenharmony_ci const struct sockaddr_in *addr = NULL; 951cb0ef41Sopenharmony_ci const struct sockaddr_in6 *addr6 = NULL; 961cb0ef41Sopenharmony_ci struct nameinfo_query *niquery; 971cb0ef41Sopenharmony_ci unsigned short port = 0; 981cb0ef41Sopenharmony_ci unsigned int flags = (unsigned int)flags_int; 991cb0ef41Sopenharmony_ci 1001cb0ef41Sopenharmony_ci /* Validate socket address family and length */ 1011cb0ef41Sopenharmony_ci if ((sa->sa_family == AF_INET) && (salen == sizeof(struct sockaddr_in))) { 1021cb0ef41Sopenharmony_ci addr = CARES_INADDR_CAST(struct sockaddr_in *, sa); 1031cb0ef41Sopenharmony_ci port = addr->sin_port; 1041cb0ef41Sopenharmony_ci } else if ((sa->sa_family == AF_INET6) && 1051cb0ef41Sopenharmony_ci (salen == sizeof(struct sockaddr_in6))) { 1061cb0ef41Sopenharmony_ci addr6 = CARES_INADDR_CAST(struct sockaddr_in6 *, sa); 1071cb0ef41Sopenharmony_ci port = addr6->sin6_port; 1081cb0ef41Sopenharmony_ci } else { 1091cb0ef41Sopenharmony_ci callback(arg, ARES_ENOTIMP, 0, NULL, NULL); 1101cb0ef41Sopenharmony_ci return; 1111cb0ef41Sopenharmony_ci } 1121cb0ef41Sopenharmony_ci 1131cb0ef41Sopenharmony_ci /* If neither, assume they want a host */ 1141cb0ef41Sopenharmony_ci if (!(flags & ARES_NI_LOOKUPSERVICE) && !(flags & ARES_NI_LOOKUPHOST)) { 1151cb0ef41Sopenharmony_ci flags |= ARES_NI_LOOKUPHOST; 1161cb0ef41Sopenharmony_ci } 1171cb0ef41Sopenharmony_ci 1181cb0ef41Sopenharmony_ci /* All they want is a service, no need for DNS */ 1191cb0ef41Sopenharmony_ci if ((flags & ARES_NI_LOOKUPSERVICE) && !(flags & ARES_NI_LOOKUPHOST)) { 1201cb0ef41Sopenharmony_ci char buf[33]; 1211cb0ef41Sopenharmony_ci char *service; 1221cb0ef41Sopenharmony_ci 1231cb0ef41Sopenharmony_ci service = 1241cb0ef41Sopenharmony_ci lookup_service((unsigned short)(port & 0xffff), flags, buf, sizeof(buf)); 1251cb0ef41Sopenharmony_ci callback(arg, ARES_SUCCESS, 0, NULL, service); 1261cb0ef41Sopenharmony_ci return; 1271cb0ef41Sopenharmony_ci } 1281cb0ef41Sopenharmony_ci 1291cb0ef41Sopenharmony_ci /* They want a host lookup */ 1301cb0ef41Sopenharmony_ci if (flags & ARES_NI_LOOKUPHOST) { 1311cb0ef41Sopenharmony_ci /* A numeric host can be handled without DNS */ 1321cb0ef41Sopenharmony_ci if (flags & ARES_NI_NUMERICHOST) { 1331cb0ef41Sopenharmony_ci char ipbuf[IPBUFSIZ]; 1341cb0ef41Sopenharmony_ci char srvbuf[33]; 1351cb0ef41Sopenharmony_ci char *service = NULL; 1361cb0ef41Sopenharmony_ci ipbuf[0] = 0; 1371cb0ef41Sopenharmony_ci 1381cb0ef41Sopenharmony_ci /* Specifying not to lookup a host, but then saying a host 1391cb0ef41Sopenharmony_ci * is required has to be illegal. 1401cb0ef41Sopenharmony_ci */ 1411cb0ef41Sopenharmony_ci if (flags & ARES_NI_NAMEREQD) { 1421cb0ef41Sopenharmony_ci callback(arg, ARES_EBADFLAGS, 0, NULL, NULL); 1431cb0ef41Sopenharmony_ci return; 1441cb0ef41Sopenharmony_ci } 1451cb0ef41Sopenharmony_ci if (salen == sizeof(struct sockaddr_in6)) { 1461cb0ef41Sopenharmony_ci ares_inet_ntop(AF_INET6, &addr6->sin6_addr, ipbuf, IPBUFSIZ); 1471cb0ef41Sopenharmony_ci /* If the system supports scope IDs, use it */ 1481cb0ef41Sopenharmony_ci#ifdef HAVE_STRUCT_SOCKADDR_IN6_SIN6_SCOPE_ID 1491cb0ef41Sopenharmony_ci append_scopeid(addr6, flags, ipbuf, sizeof(ipbuf)); 1501cb0ef41Sopenharmony_ci#endif 1511cb0ef41Sopenharmony_ci } else { 1521cb0ef41Sopenharmony_ci ares_inet_ntop(AF_INET, &addr->sin_addr, ipbuf, IPBUFSIZ); 1531cb0ef41Sopenharmony_ci } 1541cb0ef41Sopenharmony_ci /* They also want a service */ 1551cb0ef41Sopenharmony_ci if (flags & ARES_NI_LOOKUPSERVICE) { 1561cb0ef41Sopenharmony_ci service = lookup_service((unsigned short)(port & 0xffff), flags, srvbuf, 1571cb0ef41Sopenharmony_ci sizeof(srvbuf)); 1581cb0ef41Sopenharmony_ci } 1591cb0ef41Sopenharmony_ci callback(arg, ARES_SUCCESS, 0, ipbuf, service); 1601cb0ef41Sopenharmony_ci return; 1611cb0ef41Sopenharmony_ci } 1621cb0ef41Sopenharmony_ci /* This is where a DNS lookup becomes necessary */ 1631cb0ef41Sopenharmony_ci else { 1641cb0ef41Sopenharmony_ci niquery = ares_malloc(sizeof(struct nameinfo_query)); 1651cb0ef41Sopenharmony_ci if (!niquery) { 1661cb0ef41Sopenharmony_ci callback(arg, ARES_ENOMEM, 0, NULL, NULL); 1671cb0ef41Sopenharmony_ci return; 1681cb0ef41Sopenharmony_ci } 1691cb0ef41Sopenharmony_ci niquery->callback = callback; 1701cb0ef41Sopenharmony_ci niquery->arg = arg; 1711cb0ef41Sopenharmony_ci niquery->flags = flags; 1721cb0ef41Sopenharmony_ci niquery->timeouts = 0; 1731cb0ef41Sopenharmony_ci if (sa->sa_family == AF_INET) { 1741cb0ef41Sopenharmony_ci niquery->family = AF_INET; 1751cb0ef41Sopenharmony_ci memcpy(&niquery->addr.addr4, addr, sizeof(niquery->addr.addr4)); 1761cb0ef41Sopenharmony_ci ares_gethostbyaddr(channel, &addr->sin_addr, sizeof(struct in_addr), 1771cb0ef41Sopenharmony_ci AF_INET, nameinfo_callback, niquery); 1781cb0ef41Sopenharmony_ci } else { 1791cb0ef41Sopenharmony_ci niquery->family = AF_INET6; 1801cb0ef41Sopenharmony_ci memcpy(&niquery->addr.addr6, addr6, sizeof(niquery->addr.addr6)); 1811cb0ef41Sopenharmony_ci ares_gethostbyaddr(channel, &addr6->sin6_addr, 1821cb0ef41Sopenharmony_ci sizeof(struct ares_in6_addr), AF_INET6, 1831cb0ef41Sopenharmony_ci nameinfo_callback, niquery); 1841cb0ef41Sopenharmony_ci } 1851cb0ef41Sopenharmony_ci } 1861cb0ef41Sopenharmony_ci } 1871cb0ef41Sopenharmony_ci} 1881cb0ef41Sopenharmony_ci 1891cb0ef41Sopenharmony_civoid ares_getnameinfo(ares_channel_t *channel, const struct sockaddr *sa, 1901cb0ef41Sopenharmony_ci ares_socklen_t salen, int flags_int, 1911cb0ef41Sopenharmony_ci ares_nameinfo_callback callback, void *arg) 1921cb0ef41Sopenharmony_ci{ 1931cb0ef41Sopenharmony_ci if (channel == NULL) { 1941cb0ef41Sopenharmony_ci return; 1951cb0ef41Sopenharmony_ci } 1961cb0ef41Sopenharmony_ci 1971cb0ef41Sopenharmony_ci ares__channel_lock(channel); 1981cb0ef41Sopenharmony_ci ares_getnameinfo_int(channel, sa, salen, flags_int, callback, arg); 1991cb0ef41Sopenharmony_ci ares__channel_unlock(channel); 2001cb0ef41Sopenharmony_ci} 2011cb0ef41Sopenharmony_ci 2021cb0ef41Sopenharmony_cistatic void nameinfo_callback(void *arg, int status, int timeouts, 2031cb0ef41Sopenharmony_ci struct hostent *host) 2041cb0ef41Sopenharmony_ci{ 2051cb0ef41Sopenharmony_ci struct nameinfo_query *niquery = (struct nameinfo_query *)arg; 2061cb0ef41Sopenharmony_ci char srvbuf[33]; 2071cb0ef41Sopenharmony_ci char *service = NULL; 2081cb0ef41Sopenharmony_ci 2091cb0ef41Sopenharmony_ci niquery->timeouts += (size_t)timeouts; 2101cb0ef41Sopenharmony_ci if (status == ARES_SUCCESS) { 2111cb0ef41Sopenharmony_ci /* They want a service too */ 2121cb0ef41Sopenharmony_ci if (niquery->flags & ARES_NI_LOOKUPSERVICE) { 2131cb0ef41Sopenharmony_ci if (niquery->family == AF_INET) { 2141cb0ef41Sopenharmony_ci service = lookup_service(niquery->addr.addr4.sin_port, niquery->flags, 2151cb0ef41Sopenharmony_ci srvbuf, sizeof(srvbuf)); 2161cb0ef41Sopenharmony_ci } else { 2171cb0ef41Sopenharmony_ci service = lookup_service(niquery->addr.addr6.sin6_port, niquery->flags, 2181cb0ef41Sopenharmony_ci srvbuf, sizeof(srvbuf)); 2191cb0ef41Sopenharmony_ci } 2201cb0ef41Sopenharmony_ci } 2211cb0ef41Sopenharmony_ci /* NOFQDN means we have to strip off the domain name portion. We do 2221cb0ef41Sopenharmony_ci this by determining our own domain name, then searching the string 2231cb0ef41Sopenharmony_ci for this domain name and removing it. 2241cb0ef41Sopenharmony_ci */ 2251cb0ef41Sopenharmony_ci#ifdef HAVE_GETHOSTNAME 2261cb0ef41Sopenharmony_ci if (niquery->flags & ARES_NI_NOFQDN) { 2271cb0ef41Sopenharmony_ci char buf[255]; 2281cb0ef41Sopenharmony_ci const char *domain; 2291cb0ef41Sopenharmony_ci gethostname(buf, 255); 2301cb0ef41Sopenharmony_ci if ((domain = strchr(buf, '.')) != NULL) { 2311cb0ef41Sopenharmony_ci char *end = ares_striendstr(host->h_name, domain); 2321cb0ef41Sopenharmony_ci if (end) { 2331cb0ef41Sopenharmony_ci *end = 0; 2341cb0ef41Sopenharmony_ci } 2351cb0ef41Sopenharmony_ci } 2361cb0ef41Sopenharmony_ci } 2371cb0ef41Sopenharmony_ci#endif 2381cb0ef41Sopenharmony_ci niquery->callback(niquery->arg, ARES_SUCCESS, (int)niquery->timeouts, 2391cb0ef41Sopenharmony_ci host->h_name, service); 2401cb0ef41Sopenharmony_ci ares_free(niquery); 2411cb0ef41Sopenharmony_ci return; 2421cb0ef41Sopenharmony_ci } 2431cb0ef41Sopenharmony_ci /* We couldn't find the host, but it's OK, we can use the IP */ 2441cb0ef41Sopenharmony_ci else if (status == ARES_ENOTFOUND && !(niquery->flags & ARES_NI_NAMEREQD)) { 2451cb0ef41Sopenharmony_ci char ipbuf[IPBUFSIZ]; 2461cb0ef41Sopenharmony_ci if (niquery->family == AF_INET) { 2471cb0ef41Sopenharmony_ci ares_inet_ntop(AF_INET, &niquery->addr.addr4.sin_addr, ipbuf, IPBUFSIZ); 2481cb0ef41Sopenharmony_ci } else { 2491cb0ef41Sopenharmony_ci ares_inet_ntop(AF_INET6, &niquery->addr.addr6.sin6_addr, ipbuf, IPBUFSIZ); 2501cb0ef41Sopenharmony_ci#ifdef HAVE_STRUCT_SOCKADDR_IN6_SIN6_SCOPE_ID 2511cb0ef41Sopenharmony_ci append_scopeid(&niquery->addr.addr6, niquery->flags, ipbuf, 2521cb0ef41Sopenharmony_ci sizeof(ipbuf)); 2531cb0ef41Sopenharmony_ci#endif 2541cb0ef41Sopenharmony_ci } 2551cb0ef41Sopenharmony_ci /* They want a service too */ 2561cb0ef41Sopenharmony_ci if (niquery->flags & ARES_NI_LOOKUPSERVICE) { 2571cb0ef41Sopenharmony_ci if (niquery->family == AF_INET) { 2581cb0ef41Sopenharmony_ci service = lookup_service(niquery->addr.addr4.sin_port, niquery->flags, 2591cb0ef41Sopenharmony_ci srvbuf, sizeof(srvbuf)); 2601cb0ef41Sopenharmony_ci } else { 2611cb0ef41Sopenharmony_ci service = lookup_service(niquery->addr.addr6.sin6_port, niquery->flags, 2621cb0ef41Sopenharmony_ci srvbuf, sizeof(srvbuf)); 2631cb0ef41Sopenharmony_ci } 2641cb0ef41Sopenharmony_ci } 2651cb0ef41Sopenharmony_ci niquery->callback(niquery->arg, ARES_SUCCESS, (int)niquery->timeouts, ipbuf, 2661cb0ef41Sopenharmony_ci service); 2671cb0ef41Sopenharmony_ci ares_free(niquery); 2681cb0ef41Sopenharmony_ci return; 2691cb0ef41Sopenharmony_ci } 2701cb0ef41Sopenharmony_ci niquery->callback(niquery->arg, status, (int)niquery->timeouts, NULL, NULL); 2711cb0ef41Sopenharmony_ci ares_free(niquery); 2721cb0ef41Sopenharmony_ci} 2731cb0ef41Sopenharmony_ci 2741cb0ef41Sopenharmony_cistatic char *lookup_service(unsigned short port, unsigned int flags, char *buf, 2751cb0ef41Sopenharmony_ci size_t buflen) 2761cb0ef41Sopenharmony_ci{ 2771cb0ef41Sopenharmony_ci const char *proto; 2781cb0ef41Sopenharmony_ci struct servent *sep; 2791cb0ef41Sopenharmony_ci#ifdef HAVE_GETSERVBYPORT_R 2801cb0ef41Sopenharmony_ci struct servent se; 2811cb0ef41Sopenharmony_ci#endif 2821cb0ef41Sopenharmony_ci char tmpbuf[4096]; 2831cb0ef41Sopenharmony_ci const char *name; 2841cb0ef41Sopenharmony_ci size_t name_len; 2851cb0ef41Sopenharmony_ci 2861cb0ef41Sopenharmony_ci if (port) { 2871cb0ef41Sopenharmony_ci if (flags & ARES_NI_NUMERICSERV) { 2881cb0ef41Sopenharmony_ci sep = NULL; 2891cb0ef41Sopenharmony_ci } else { 2901cb0ef41Sopenharmony_ci if (flags & ARES_NI_UDP) { 2911cb0ef41Sopenharmony_ci proto = "udp"; 2921cb0ef41Sopenharmony_ci } else if (flags & ARES_NI_SCTP) { 2931cb0ef41Sopenharmony_ci proto = "sctp"; 2941cb0ef41Sopenharmony_ci } else if (flags & ARES_NI_DCCP) { 2951cb0ef41Sopenharmony_ci proto = "dccp"; 2961cb0ef41Sopenharmony_ci } else { 2971cb0ef41Sopenharmony_ci proto = "tcp"; 2981cb0ef41Sopenharmony_ci } 2991cb0ef41Sopenharmony_ci#ifdef HAVE_GETSERVBYPORT_R 3001cb0ef41Sopenharmony_ci memset(&se, 0, sizeof(se)); 3011cb0ef41Sopenharmony_ci sep = &se; 3021cb0ef41Sopenharmony_ci memset(tmpbuf, 0, sizeof(tmpbuf)); 3031cb0ef41Sopenharmony_ci# if GETSERVBYPORT_R_ARGS == 6 3041cb0ef41Sopenharmony_ci if (getservbyport_r(port, proto, &se, (void *)tmpbuf, sizeof(tmpbuf), 3051cb0ef41Sopenharmony_ci &sep) != 0) { 3061cb0ef41Sopenharmony_ci sep = NULL; /* LCOV_EXCL_LINE: buffer large so this never fails */ 3071cb0ef41Sopenharmony_ci } 3081cb0ef41Sopenharmony_ci# elif GETSERVBYPORT_R_ARGS == 5 3091cb0ef41Sopenharmony_ci sep = getservbyport_r(port, proto, &se, (void *)tmpbuf, sizeof(tmpbuf)); 3101cb0ef41Sopenharmony_ci# elif GETSERVBYPORT_R_ARGS == 4 3111cb0ef41Sopenharmony_ci if (getservbyport_r(port, proto, &se, (void *)tmpbuf) != 0) { 3121cb0ef41Sopenharmony_ci sep = NULL; 3131cb0ef41Sopenharmony_ci } 3141cb0ef41Sopenharmony_ci# else 3151cb0ef41Sopenharmony_ci /* Lets just hope the OS uses TLS! */ 3161cb0ef41Sopenharmony_ci sep = getservbyport(port, proto); 3171cb0ef41Sopenharmony_ci# endif 3181cb0ef41Sopenharmony_ci#else 3191cb0ef41Sopenharmony_ci /* Lets just hope the OS uses TLS! */ 3201cb0ef41Sopenharmony_ci# if (defined(NETWARE) && !defined(__NOVELL_LIBC__)) 3211cb0ef41Sopenharmony_ci sep = getservbyport(port, (char *)proto); 3221cb0ef41Sopenharmony_ci# else 3231cb0ef41Sopenharmony_ci sep = getservbyport(port, proto); 3241cb0ef41Sopenharmony_ci# endif 3251cb0ef41Sopenharmony_ci#endif 3261cb0ef41Sopenharmony_ci } 3271cb0ef41Sopenharmony_ci if (sep && sep->s_name) { 3281cb0ef41Sopenharmony_ci /* get service name */ 3291cb0ef41Sopenharmony_ci name = sep->s_name; 3301cb0ef41Sopenharmony_ci } else { 3311cb0ef41Sopenharmony_ci /* get port as a string */ 3321cb0ef41Sopenharmony_ci snprintf(tmpbuf, sizeof(tmpbuf), "%u", (unsigned int)ntohs(port)); 3331cb0ef41Sopenharmony_ci name = tmpbuf; 3341cb0ef41Sopenharmony_ci } 3351cb0ef41Sopenharmony_ci name_len = ares_strlen(name); 3361cb0ef41Sopenharmony_ci if (name_len < buflen) { 3371cb0ef41Sopenharmony_ci /* return it if buffer big enough */ 3381cb0ef41Sopenharmony_ci memcpy(buf, name, name_len + 1); 3391cb0ef41Sopenharmony_ci } else { 3401cb0ef41Sopenharmony_ci /* avoid reusing previous one */ 3411cb0ef41Sopenharmony_ci buf[0] = '\0'; /* LCOV_EXCL_LINE: no real service names are too big */ 3421cb0ef41Sopenharmony_ci } 3431cb0ef41Sopenharmony_ci return buf; 3441cb0ef41Sopenharmony_ci } 3451cb0ef41Sopenharmony_ci buf[0] = '\0'; 3461cb0ef41Sopenharmony_ci return NULL; 3471cb0ef41Sopenharmony_ci} 3481cb0ef41Sopenharmony_ci 3491cb0ef41Sopenharmony_ci#ifdef HAVE_STRUCT_SOCKADDR_IN6_SIN6_SCOPE_ID 3501cb0ef41Sopenharmony_cistatic void append_scopeid(const struct sockaddr_in6 *addr6, unsigned int flags, 3511cb0ef41Sopenharmony_ci char *buf, size_t buflen) 3521cb0ef41Sopenharmony_ci{ 3531cb0ef41Sopenharmony_ci# ifdef HAVE_IF_INDEXTONAME 3541cb0ef41Sopenharmony_ci int is_ll; 3551cb0ef41Sopenharmony_ci int is_mcll; 3561cb0ef41Sopenharmony_ci# endif 3571cb0ef41Sopenharmony_ci char tmpbuf[IF_NAMESIZE + 2]; 3581cb0ef41Sopenharmony_ci size_t bufl; 3591cb0ef41Sopenharmony_ci 3601cb0ef41Sopenharmony_ci tmpbuf[0] = '%'; 3611cb0ef41Sopenharmony_ci 3621cb0ef41Sopenharmony_ci# ifdef HAVE_IF_INDEXTONAME 3631cb0ef41Sopenharmony_ci is_ll = IN6_IS_ADDR_LINKLOCAL(&addr6->sin6_addr); 3641cb0ef41Sopenharmony_ci is_mcll = IN6_IS_ADDR_MC_LINKLOCAL(&addr6->sin6_addr); 3651cb0ef41Sopenharmony_ci if ((flags & ARES_NI_NUMERICSCOPE) || (!is_ll && !is_mcll)) { 3661cb0ef41Sopenharmony_ci snprintf(&tmpbuf[1], sizeof(tmpbuf) - 1, "%lu", 3671cb0ef41Sopenharmony_ci (unsigned long)addr6->sin6_scope_id); 3681cb0ef41Sopenharmony_ci } else { 3691cb0ef41Sopenharmony_ci if (if_indextoname(addr6->sin6_scope_id, &tmpbuf[1]) == NULL) { 3701cb0ef41Sopenharmony_ci snprintf(&tmpbuf[1], sizeof(tmpbuf) - 1, "%lu", 3711cb0ef41Sopenharmony_ci (unsigned long)addr6->sin6_scope_id); 3721cb0ef41Sopenharmony_ci } 3731cb0ef41Sopenharmony_ci } 3741cb0ef41Sopenharmony_ci# else 3751cb0ef41Sopenharmony_ci snprintf(&tmpbuf[1], sizeof(tmpbuf) - 1, "%lu", 3761cb0ef41Sopenharmony_ci (unsigned long)addr6->sin6_scope_id); 3771cb0ef41Sopenharmony_ci (void)flags; 3781cb0ef41Sopenharmony_ci# endif 3791cb0ef41Sopenharmony_ci tmpbuf[IF_NAMESIZE + 1] = '\0'; 3801cb0ef41Sopenharmony_ci bufl = ares_strlen(buf); 3811cb0ef41Sopenharmony_ci 3821cb0ef41Sopenharmony_ci if (bufl + ares_strlen(tmpbuf) < buflen) { 3831cb0ef41Sopenharmony_ci /* only append the scopeid string if it fits in the target buffer */ 3841cb0ef41Sopenharmony_ci ares_strcpy(&buf[bufl], tmpbuf, buflen - bufl); 3851cb0ef41Sopenharmony_ci } 3861cb0ef41Sopenharmony_ci} 3871cb0ef41Sopenharmony_ci#endif 3881cb0ef41Sopenharmony_ci 3891cb0ef41Sopenharmony_ci/* Determines if s1 ends with the string in s2 (case-insensitive) */ 3901cb0ef41Sopenharmony_cistatic char *ares_striendstr(const char *s1, const char *s2) 3911cb0ef41Sopenharmony_ci{ 3921cb0ef41Sopenharmony_ci const char *c1; 3931cb0ef41Sopenharmony_ci const char *c2; 3941cb0ef41Sopenharmony_ci const char *c1_begin; 3951cb0ef41Sopenharmony_ci int lo1; 3961cb0ef41Sopenharmony_ci int lo2; 3971cb0ef41Sopenharmony_ci size_t s1_len = ares_strlen(s1); 3981cb0ef41Sopenharmony_ci size_t s2_len = ares_strlen(s2); 3991cb0ef41Sopenharmony_ci 4001cb0ef41Sopenharmony_ci if (s1 == NULL || s2 == NULL) { 4011cb0ef41Sopenharmony_ci return NULL; 4021cb0ef41Sopenharmony_ci } 4031cb0ef41Sopenharmony_ci 4041cb0ef41Sopenharmony_ci /* If the substr is longer than the full str, it can't match */ 4051cb0ef41Sopenharmony_ci if (s2_len > s1_len) { 4061cb0ef41Sopenharmony_ci return NULL; 4071cb0ef41Sopenharmony_ci } 4081cb0ef41Sopenharmony_ci 4091cb0ef41Sopenharmony_ci /* Jump to the end of s1 minus the length of s2 */ 4101cb0ef41Sopenharmony_ci c1_begin = s1 + s1_len - s2_len; 4111cb0ef41Sopenharmony_ci c1 = c1_begin; 4121cb0ef41Sopenharmony_ci c2 = s2; 4131cb0ef41Sopenharmony_ci while (c2 < s2 + s2_len) { 4141cb0ef41Sopenharmony_ci lo1 = TOLOWER(*c1); 4151cb0ef41Sopenharmony_ci lo2 = TOLOWER(*c2); 4161cb0ef41Sopenharmony_ci if (lo1 != lo2) { 4171cb0ef41Sopenharmony_ci return NULL; 4181cb0ef41Sopenharmony_ci } else { 4191cb0ef41Sopenharmony_ci c1++; 4201cb0ef41Sopenharmony_ci c2++; 4211cb0ef41Sopenharmony_ci } 4221cb0ef41Sopenharmony_ci } 4231cb0ef41Sopenharmony_ci /* Cast off const */ 4241cb0ef41Sopenharmony_ci return (char *)((size_t)c1_begin); 4251cb0ef41Sopenharmony_ci} 4261cb0ef41Sopenharmony_ci 4271cb0ef41Sopenharmony_ciares_bool_t ares__is_onion_domain(const char *name) 4281cb0ef41Sopenharmony_ci{ 4291cb0ef41Sopenharmony_ci if (ares_striendstr(name, ".onion")) { 4301cb0ef41Sopenharmony_ci return ARES_TRUE; 4311cb0ef41Sopenharmony_ci } 4321cb0ef41Sopenharmony_ci 4331cb0ef41Sopenharmony_ci if (ares_striendstr(name, ".onion.")) { 4341cb0ef41Sopenharmony_ci return ARES_TRUE; 4351cb0ef41Sopenharmony_ci } 4361cb0ef41Sopenharmony_ci 4371cb0ef41Sopenharmony_ci return ARES_FALSE; 4381cb0ef41Sopenharmony_ci} 439