11cb0ef41Sopenharmony_ci/* 21cb0ef41Sopenharmony_ci * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") 31cb0ef41Sopenharmony_ci * Copyright (c) 1996-1999 by Internet Software Consortium. 41cb0ef41Sopenharmony_ci * 51cb0ef41Sopenharmony_ci * Permission to use, copy, modify, and distribute this software for any 61cb0ef41Sopenharmony_ci * purpose with or without fee is hereby granted, provided that the above 71cb0ef41Sopenharmony_ci * copyright notice and this permission notice appear in all copies. 81cb0ef41Sopenharmony_ci * 91cb0ef41Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES 101cb0ef41Sopenharmony_ci * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 111cb0ef41Sopenharmony_ci * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR 121cb0ef41Sopenharmony_ci * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 131cb0ef41Sopenharmony_ci * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 141cb0ef41Sopenharmony_ci * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 151cb0ef41Sopenharmony_ci * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 161cb0ef41Sopenharmony_ci * 171cb0ef41Sopenharmony_ci * SPDX-License-Identifier: MIT 181cb0ef41Sopenharmony_ci */ 191cb0ef41Sopenharmony_ci 201cb0ef41Sopenharmony_ci#include "ares_setup.h" 211cb0ef41Sopenharmony_ci 221cb0ef41Sopenharmony_ci#ifdef HAVE_NETINET_IN_H 231cb0ef41Sopenharmony_ci# include <netinet/in.h> 241cb0ef41Sopenharmony_ci#endif 251cb0ef41Sopenharmony_ci#ifdef HAVE_ARPA_INET_H 261cb0ef41Sopenharmony_ci# include <arpa/inet.h> 271cb0ef41Sopenharmony_ci#endif 281cb0ef41Sopenharmony_ci 291cb0ef41Sopenharmony_ci#include "ares_nameser.h" 301cb0ef41Sopenharmony_ci 311cb0ef41Sopenharmony_ci#include "ares.h" 321cb0ef41Sopenharmony_ci#include "ares_ipv6.h" 331cb0ef41Sopenharmony_ci#include "ares_private.h" 341cb0ef41Sopenharmony_ci 351cb0ef41Sopenharmony_ci#ifndef HAVE_INET_NTOP 361cb0ef41Sopenharmony_ci 371cb0ef41Sopenharmony_ci/* 381cb0ef41Sopenharmony_ci * WARNING: Don't even consider trying to compile this on a system where 391cb0ef41Sopenharmony_ci * sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX. 401cb0ef41Sopenharmony_ci */ 411cb0ef41Sopenharmony_ci 421cb0ef41Sopenharmony_cistatic const char *inet_ntop4(const unsigned char *src, char *dst, size_t size); 431cb0ef41Sopenharmony_cistatic const char *inet_ntop6(const unsigned char *src, char *dst, size_t size); 441cb0ef41Sopenharmony_ci 451cb0ef41Sopenharmony_ci/* char * 461cb0ef41Sopenharmony_ci * inet_ntop(af, src, dst, size) 471cb0ef41Sopenharmony_ci * convert a network format address to presentation format. 481cb0ef41Sopenharmony_ci * return: 491cb0ef41Sopenharmony_ci * pointer to presentation format address (`dst'), or NULL (see errno). 501cb0ef41Sopenharmony_ci * note: 511cb0ef41Sopenharmony_ci * On Windows we store the error in the thread errno, not 521cb0ef41Sopenharmony_ci * in the winsock error code. This is to avoid losing the 531cb0ef41Sopenharmony_ci * actual last winsock error. So use macro ERRNO to fetch the 541cb0ef41Sopenharmony_ci * errno this function sets when returning NULL, not SOCKERRNO. 551cb0ef41Sopenharmony_ci * author: 561cb0ef41Sopenharmony_ci * Paul Vixie, 1996. 571cb0ef41Sopenharmony_ci */ 581cb0ef41Sopenharmony_ciconst char *ares_inet_ntop(int af, const void *src, char *dst, 591cb0ef41Sopenharmony_ci ares_socklen_t size) 601cb0ef41Sopenharmony_ci{ 611cb0ef41Sopenharmony_ci switch (af) { 621cb0ef41Sopenharmony_ci case AF_INET: 631cb0ef41Sopenharmony_ci return (inet_ntop4(src, dst, (size_t)size)); 641cb0ef41Sopenharmony_ci case AF_INET6: 651cb0ef41Sopenharmony_ci return (inet_ntop6(src, dst, (size_t)size)); 661cb0ef41Sopenharmony_ci default: 671cb0ef41Sopenharmony_ci SET_ERRNO(EAFNOSUPPORT); 681cb0ef41Sopenharmony_ci return (NULL); 691cb0ef41Sopenharmony_ci } 701cb0ef41Sopenharmony_ci /* NOTREACHED */ 711cb0ef41Sopenharmony_ci} 721cb0ef41Sopenharmony_ci 731cb0ef41Sopenharmony_ci/* const char * 741cb0ef41Sopenharmony_ci * inet_ntop4(src, dst, size) 751cb0ef41Sopenharmony_ci * format an IPv4 address 761cb0ef41Sopenharmony_ci * return: 771cb0ef41Sopenharmony_ci * `dst' (as a const) 781cb0ef41Sopenharmony_ci * notes: 791cb0ef41Sopenharmony_ci * (1) uses no statics 801cb0ef41Sopenharmony_ci * (2) takes a unsigned char* not an in_addr as input 811cb0ef41Sopenharmony_ci * author: 821cb0ef41Sopenharmony_ci * Paul Vixie, 1996. 831cb0ef41Sopenharmony_ci */ 841cb0ef41Sopenharmony_cistatic const char *inet_ntop4(const unsigned char *src, char *dst, size_t size) 851cb0ef41Sopenharmony_ci{ 861cb0ef41Sopenharmony_ci static const char fmt[] = "%u.%u.%u.%u"; 871cb0ef41Sopenharmony_ci char tmp[sizeof("255.255.255.255")]; 881cb0ef41Sopenharmony_ci 891cb0ef41Sopenharmony_ci if ((size_t)snprintf(tmp, sizeof(tmp), fmt, src[0], src[1], src[2], src[3]) >= 901cb0ef41Sopenharmony_ci size) { 911cb0ef41Sopenharmony_ci SET_ERRNO(ENOSPC); 921cb0ef41Sopenharmony_ci return (NULL); 931cb0ef41Sopenharmony_ci } 941cb0ef41Sopenharmony_ci ares_strcpy(dst, tmp, size); 951cb0ef41Sopenharmony_ci return (dst); 961cb0ef41Sopenharmony_ci} 971cb0ef41Sopenharmony_ci 981cb0ef41Sopenharmony_ci/* const char * 991cb0ef41Sopenharmony_ci * inet_ntop6(src, dst, size) 1001cb0ef41Sopenharmony_ci * convert IPv6 binary address into presentation (printable) format 1011cb0ef41Sopenharmony_ci * author: 1021cb0ef41Sopenharmony_ci * Paul Vixie, 1996. 1031cb0ef41Sopenharmony_ci */ 1041cb0ef41Sopenharmony_cistatic const char *inet_ntop6(const unsigned char *src, char *dst, size_t size) 1051cb0ef41Sopenharmony_ci{ 1061cb0ef41Sopenharmony_ci /* 1071cb0ef41Sopenharmony_ci * Note that int32_t and int16_t need only be "at least" large enough 1081cb0ef41Sopenharmony_ci * to contain a value of the specified size. On some systems, like 1091cb0ef41Sopenharmony_ci * Crays, there is no such thing as an integer variable with 16 bits. 1101cb0ef41Sopenharmony_ci * Keep this in mind if you think this function should have been coded 1111cb0ef41Sopenharmony_ci * to use pointer overlays. All the world's not a VAX. 1121cb0ef41Sopenharmony_ci */ 1131cb0ef41Sopenharmony_ci char tmp[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")]; 1141cb0ef41Sopenharmony_ci char *tp; 1151cb0ef41Sopenharmony_ci 1161cb0ef41Sopenharmony_ci struct { 1171cb0ef41Sopenharmony_ci int base, len; 1181cb0ef41Sopenharmony_ci } best, cur; 1191cb0ef41Sopenharmony_ci 1201cb0ef41Sopenharmony_ci unsigned int words[NS_IN6ADDRSZ / NS_INT16SZ]; 1211cb0ef41Sopenharmony_ci int i; 1221cb0ef41Sopenharmony_ci 1231cb0ef41Sopenharmony_ci /* 1241cb0ef41Sopenharmony_ci * Preprocess: 1251cb0ef41Sopenharmony_ci * Copy the input (bytewise) array into a wordwise array. 1261cb0ef41Sopenharmony_ci * Find the longest run of 0x00's in src[] for :: shorthanding. 1271cb0ef41Sopenharmony_ci */ 1281cb0ef41Sopenharmony_ci memset(words, '\0', sizeof(words)); 1291cb0ef41Sopenharmony_ci for (i = 0; i < NS_IN6ADDRSZ; i++) { 1301cb0ef41Sopenharmony_ci words[i / 2] |= (unsigned int)(src[i] << ((1 - (i % 2)) << 3)); 1311cb0ef41Sopenharmony_ci } 1321cb0ef41Sopenharmony_ci best.base = -1; 1331cb0ef41Sopenharmony_ci best.len = 0; 1341cb0ef41Sopenharmony_ci cur.base = -1; 1351cb0ef41Sopenharmony_ci cur.len = 0; 1361cb0ef41Sopenharmony_ci for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++) { 1371cb0ef41Sopenharmony_ci if (words[i] == 0) { 1381cb0ef41Sopenharmony_ci if (cur.base == -1) { 1391cb0ef41Sopenharmony_ci cur.base = i, cur.len = 1; 1401cb0ef41Sopenharmony_ci } else { 1411cb0ef41Sopenharmony_ci cur.len++; 1421cb0ef41Sopenharmony_ci } 1431cb0ef41Sopenharmony_ci } else { 1441cb0ef41Sopenharmony_ci if (cur.base != -1) { 1451cb0ef41Sopenharmony_ci if (best.base == -1 || cur.len > best.len) { 1461cb0ef41Sopenharmony_ci best = cur; 1471cb0ef41Sopenharmony_ci } 1481cb0ef41Sopenharmony_ci cur.base = -1; 1491cb0ef41Sopenharmony_ci } 1501cb0ef41Sopenharmony_ci } 1511cb0ef41Sopenharmony_ci } 1521cb0ef41Sopenharmony_ci if (cur.base != -1) { 1531cb0ef41Sopenharmony_ci if (best.base == -1 || cur.len > best.len) { 1541cb0ef41Sopenharmony_ci best = cur; 1551cb0ef41Sopenharmony_ci } 1561cb0ef41Sopenharmony_ci } 1571cb0ef41Sopenharmony_ci if (best.base != -1 && best.len < 2) { 1581cb0ef41Sopenharmony_ci best.base = -1; 1591cb0ef41Sopenharmony_ci } 1601cb0ef41Sopenharmony_ci 1611cb0ef41Sopenharmony_ci /* 1621cb0ef41Sopenharmony_ci * Format the result. 1631cb0ef41Sopenharmony_ci */ 1641cb0ef41Sopenharmony_ci tp = tmp; 1651cb0ef41Sopenharmony_ci for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++) { 1661cb0ef41Sopenharmony_ci /* Are we inside the best run of 0x00's? */ 1671cb0ef41Sopenharmony_ci if (best.base != -1 && i >= best.base && i < (best.base + best.len)) { 1681cb0ef41Sopenharmony_ci if (i == best.base) { 1691cb0ef41Sopenharmony_ci *tp++ = ':'; 1701cb0ef41Sopenharmony_ci } 1711cb0ef41Sopenharmony_ci continue; 1721cb0ef41Sopenharmony_ci } 1731cb0ef41Sopenharmony_ci /* Are we following an initial run of 0x00s or any real hex? */ 1741cb0ef41Sopenharmony_ci if (i != 0) { 1751cb0ef41Sopenharmony_ci *tp++ = ':'; 1761cb0ef41Sopenharmony_ci } 1771cb0ef41Sopenharmony_ci /* Is this address an encapsulated IPv4? */ 1781cb0ef41Sopenharmony_ci if (i == 6 && best.base == 0 && 1791cb0ef41Sopenharmony_ci (best.len == 6 || (best.len == 7 && words[7] != 0x0001) || 1801cb0ef41Sopenharmony_ci (best.len == 5 && words[5] == 0xffff))) { 1811cb0ef41Sopenharmony_ci if (!inet_ntop4(src + 12, tp, sizeof(tmp) - (size_t)(tp - tmp))) { 1821cb0ef41Sopenharmony_ci return (NULL); 1831cb0ef41Sopenharmony_ci } 1841cb0ef41Sopenharmony_ci tp += ares_strlen(tp); 1851cb0ef41Sopenharmony_ci break; 1861cb0ef41Sopenharmony_ci } 1871cb0ef41Sopenharmony_ci tp += snprintf(tp, sizeof(tmp) - (size_t)(tp - tmp), "%x", words[i]); 1881cb0ef41Sopenharmony_ci } 1891cb0ef41Sopenharmony_ci /* Was it a trailing run of 0x00's? */ 1901cb0ef41Sopenharmony_ci if (best.base != -1 && 1911cb0ef41Sopenharmony_ci (best.base + best.len) == (NS_IN6ADDRSZ / NS_INT16SZ)) { 1921cb0ef41Sopenharmony_ci *tp++ = ':'; 1931cb0ef41Sopenharmony_ci } 1941cb0ef41Sopenharmony_ci *tp++ = '\0'; 1951cb0ef41Sopenharmony_ci 1961cb0ef41Sopenharmony_ci /* 1971cb0ef41Sopenharmony_ci * Check for overflow, copy, and we're done. 1981cb0ef41Sopenharmony_ci */ 1991cb0ef41Sopenharmony_ci if ((size_t)(tp - tmp) > size) { 2001cb0ef41Sopenharmony_ci SET_ERRNO(ENOSPC); 2011cb0ef41Sopenharmony_ci return (NULL); 2021cb0ef41Sopenharmony_ci } 2031cb0ef41Sopenharmony_ci ares_strcpy(dst, tmp, size); 2041cb0ef41Sopenharmony_ci return (dst); 2051cb0ef41Sopenharmony_ci} 2061cb0ef41Sopenharmony_ci 2071cb0ef41Sopenharmony_ci#else /* HAVE_INET_NTOP */ 2081cb0ef41Sopenharmony_ci 2091cb0ef41Sopenharmony_ciconst char *ares_inet_ntop(int af, const void *src, char *dst, 2101cb0ef41Sopenharmony_ci ares_socklen_t size) 2111cb0ef41Sopenharmony_ci{ 2121cb0ef41Sopenharmony_ci /* just relay this to the underlying function */ 2131cb0ef41Sopenharmony_ci return inet_ntop(af, src, dst, size); 2141cb0ef41Sopenharmony_ci} 2151cb0ef41Sopenharmony_ci 2161cb0ef41Sopenharmony_ci#endif /* HAVE_INET_NTOP */ 217