17db96d56Sopenharmony_ci/* 27db96d56Sopenharmony_ci * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. 37db96d56Sopenharmony_ci * All rights reserved. 47db96d56Sopenharmony_ci * 57db96d56Sopenharmony_ci * Redistribution and use in source and binary forms, with or without 67db96d56Sopenharmony_ci * modification, are permitted provided that the following conditions 77db96d56Sopenharmony_ci * are met: 87db96d56Sopenharmony_ci * 1. Redistributions of source code must retain the above copyright 97db96d56Sopenharmony_ci * notice, this list of conditions and the following disclaimer. 107db96d56Sopenharmony_ci * 2. Redistributions in binary form must reproduce the above copyright 117db96d56Sopenharmony_ci * notice, this list of conditions and the following disclaimer in the 127db96d56Sopenharmony_ci * documentation and/or other materials provided with the distribution. 137db96d56Sopenharmony_ci * 3. Neither the name of the project nor the names of its contributors 147db96d56Sopenharmony_ci * may be used to endorse or promote products derived from this software 157db96d56Sopenharmony_ci * without specific prior written permission. 167db96d56Sopenharmony_ci * 177db96d56Sopenharmony_ci * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 187db96d56Sopenharmony_ci * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 197db96d56Sopenharmony_ci * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 207db96d56Sopenharmony_ci * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 217db96d56Sopenharmony_ci * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 227db96d56Sopenharmony_ci * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 237db96d56Sopenharmony_ci * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 247db96d56Sopenharmony_ci * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 257db96d56Sopenharmony_ci * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 267db96d56Sopenharmony_ci * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 277db96d56Sopenharmony_ci * SUCH DAMAGE. 287db96d56Sopenharmony_ci */ 297db96d56Sopenharmony_ci 307db96d56Sopenharmony_ci/* 317db96d56Sopenharmony_ci * Issues to be discussed: 327db96d56Sopenharmony_ci * - Thread safe-ness must be checked 337db96d56Sopenharmony_ci * - Return values. There seems to be no standard for return value (RFC2133) 347db96d56Sopenharmony_ci * but INRIA implementation returns EAI_xxx defined for getaddrinfo(). 357db96d56Sopenharmony_ci */ 367db96d56Sopenharmony_ci 377db96d56Sopenharmony_ci#if 0 387db96d56Sopenharmony_ci#include <sys/types.h> 397db96d56Sopenharmony_ci#include <sys/socket.h> 407db96d56Sopenharmony_ci#include <netinet/in.h> 417db96d56Sopenharmony_ci#include <arpa/inet.h> 427db96d56Sopenharmony_ci#include <arpa/nameser.h> 437db96d56Sopenharmony_ci#include <netdb.h> 447db96d56Sopenharmony_ci#include <resolv.h> 457db96d56Sopenharmony_ci#include <string.h> 467db96d56Sopenharmony_ci#include <stddef.h> 477db96d56Sopenharmony_ci 487db96d56Sopenharmony_ci#include "addrinfo.h" 497db96d56Sopenharmony_ci#endif 507db96d56Sopenharmony_ci 517db96d56Sopenharmony_ci#ifdef HAVE_NETDB_H 527db96d56Sopenharmony_ci#define HAVE_GETNAMEINFO 1 537db96d56Sopenharmony_ci 547db96d56Sopenharmony_ci#define SUCCESS 0 557db96d56Sopenharmony_ci#define YES 1 567db96d56Sopenharmony_ci#define NO 0 577db96d56Sopenharmony_ci 587db96d56Sopenharmony_cistatic struct gni_afd { 597db96d56Sopenharmony_ci int a_af; 607db96d56Sopenharmony_ci int a_addrlen; 617db96d56Sopenharmony_ci int a_socklen; 627db96d56Sopenharmony_ci int a_off; 637db96d56Sopenharmony_ci} gni_afdl [] = { 647db96d56Sopenharmony_ci#ifdef ENABLE_IPV6 657db96d56Sopenharmony_ci {PF_INET6, sizeof(struct in6_addr), sizeof(struct sockaddr_in6), 667db96d56Sopenharmony_ci offsetof(struct sockaddr_in6, sin6_addr)}, 677db96d56Sopenharmony_ci#endif 687db96d56Sopenharmony_ci {PF_INET, sizeof(struct in_addr), sizeof(struct sockaddr_in), 697db96d56Sopenharmony_ci offsetof(struct sockaddr_in, sin_addr)}, 707db96d56Sopenharmony_ci {0, 0, 0}, 717db96d56Sopenharmony_ci}; 727db96d56Sopenharmony_ci 737db96d56Sopenharmony_cistruct gni_sockinet { 747db96d56Sopenharmony_ci u_char si_len; 757db96d56Sopenharmony_ci u_char si_family; 767db96d56Sopenharmony_ci u_short si_port; 777db96d56Sopenharmony_ci}; 787db96d56Sopenharmony_ci 797db96d56Sopenharmony_ci#define ENI_NOSOCKET 0 807db96d56Sopenharmony_ci#define ENI_NOSERVNAME 1 817db96d56Sopenharmony_ci#define ENI_NOHOSTNAME 2 827db96d56Sopenharmony_ci#define ENI_MEMORY 3 837db96d56Sopenharmony_ci#define ENI_SYSTEM 4 847db96d56Sopenharmony_ci#define ENI_FAMILY 5 857db96d56Sopenharmony_ci#define ENI_SALEN 6 867db96d56Sopenharmony_ci 877db96d56Sopenharmony_ci/* forward declaration to make gcc happy */ 887db96d56Sopenharmony_ciint getnameinfo(const struct sockaddr *, size_t, char *, size_t, 897db96d56Sopenharmony_ci char *, size_t, int); 907db96d56Sopenharmony_ci 917db96d56Sopenharmony_ciint 927db96d56Sopenharmony_cigetnameinfo(sa, salen, host, hostlen, serv, servlen, flags) 937db96d56Sopenharmony_ci const struct sockaddr *sa; 947db96d56Sopenharmony_ci size_t salen; 957db96d56Sopenharmony_ci char *host; 967db96d56Sopenharmony_ci size_t hostlen; 977db96d56Sopenharmony_ci char *serv; 987db96d56Sopenharmony_ci size_t servlen; 997db96d56Sopenharmony_ci int flags; 1007db96d56Sopenharmony_ci{ 1017db96d56Sopenharmony_ci struct gni_afd *gni_afd; 1027db96d56Sopenharmony_ci struct servent *sp; 1037db96d56Sopenharmony_ci struct hostent *hp; 1047db96d56Sopenharmony_ci u_short port; 1057db96d56Sopenharmony_ci int family, len, i; 1067db96d56Sopenharmony_ci char *addr, *p; 1077db96d56Sopenharmony_ci u_long v4a; 1087db96d56Sopenharmony_ci#ifdef ENABLE_IPV6 1097db96d56Sopenharmony_ci u_char pfx; 1107db96d56Sopenharmony_ci int h_error; 1117db96d56Sopenharmony_ci#endif 1127db96d56Sopenharmony_ci char numserv[512]; 1137db96d56Sopenharmony_ci char numaddr[512]; 1147db96d56Sopenharmony_ci 1157db96d56Sopenharmony_ci if (sa == NULL) 1167db96d56Sopenharmony_ci return ENI_NOSOCKET; 1177db96d56Sopenharmony_ci 1187db96d56Sopenharmony_ci#ifdef HAVE_SOCKADDR_SA_LEN 1197db96d56Sopenharmony_ci len = sa->sa_len; 1207db96d56Sopenharmony_ci if (len != salen) return ENI_SALEN; 1217db96d56Sopenharmony_ci#else 1227db96d56Sopenharmony_ci len = salen; 1237db96d56Sopenharmony_ci#endif 1247db96d56Sopenharmony_ci 1257db96d56Sopenharmony_ci family = sa->sa_family; 1267db96d56Sopenharmony_ci for (i = 0; gni_afdl[i].a_af; i++) 1277db96d56Sopenharmony_ci if (gni_afdl[i].a_af == family) { 1287db96d56Sopenharmony_ci gni_afd = &gni_afdl[i]; 1297db96d56Sopenharmony_ci goto found; 1307db96d56Sopenharmony_ci } 1317db96d56Sopenharmony_ci return ENI_FAMILY; 1327db96d56Sopenharmony_ci 1337db96d56Sopenharmony_ci found: 1347db96d56Sopenharmony_ci if (len != gni_afd->a_socklen) return ENI_SALEN; 1357db96d56Sopenharmony_ci 1367db96d56Sopenharmony_ci port = ((struct gni_sockinet *)sa)->si_port; /* network byte order */ 1377db96d56Sopenharmony_ci addr = (char *)sa + gni_afd->a_off; 1387db96d56Sopenharmony_ci 1397db96d56Sopenharmony_ci if (serv == NULL || servlen == 0) { 1407db96d56Sopenharmony_ci /* what we should do? */ 1417db96d56Sopenharmony_ci } else if (flags & NI_NUMERICSERV) { 1427db96d56Sopenharmony_ci sprintf(numserv, "%d", ntohs(port)); 1437db96d56Sopenharmony_ci if (strlen(numserv) > servlen) 1447db96d56Sopenharmony_ci return ENI_MEMORY; 1457db96d56Sopenharmony_ci strcpy(serv, numserv); 1467db96d56Sopenharmony_ci } else { 1477db96d56Sopenharmony_ci sp = getservbyport(port, (flags & NI_DGRAM) ? "udp" : "tcp"); 1487db96d56Sopenharmony_ci if (sp) { 1497db96d56Sopenharmony_ci if (strlen(sp->s_name) > servlen) 1507db96d56Sopenharmony_ci return ENI_MEMORY; 1517db96d56Sopenharmony_ci strcpy(serv, sp->s_name); 1527db96d56Sopenharmony_ci } else 1537db96d56Sopenharmony_ci return ENI_NOSERVNAME; 1547db96d56Sopenharmony_ci } 1557db96d56Sopenharmony_ci 1567db96d56Sopenharmony_ci switch (sa->sa_family) { 1577db96d56Sopenharmony_ci case AF_INET: 1587db96d56Sopenharmony_ci v4a = ((struct sockaddr_in *)sa)->sin_addr.s_addr; 1597db96d56Sopenharmony_ci if (IN_MULTICAST(v4a) || IN_EXPERIMENTAL(v4a)) 1607db96d56Sopenharmony_ci flags |= NI_NUMERICHOST; 1617db96d56Sopenharmony_ci v4a >>= IN_CLASSA_NSHIFT; 1627db96d56Sopenharmony_ci if (v4a == 0 || v4a == IN_LOOPBACKNET) 1637db96d56Sopenharmony_ci flags |= NI_NUMERICHOST; 1647db96d56Sopenharmony_ci break; 1657db96d56Sopenharmony_ci#ifdef ENABLE_IPV6 1667db96d56Sopenharmony_ci case AF_INET6: 1677db96d56Sopenharmony_ci pfx = ((struct sockaddr_in6 *)sa)->sin6_addr.s6_addr[0]; 1687db96d56Sopenharmony_ci if (pfx == 0 || pfx == 0xfe || pfx == 0xff) 1697db96d56Sopenharmony_ci flags |= NI_NUMERICHOST; 1707db96d56Sopenharmony_ci break; 1717db96d56Sopenharmony_ci#endif 1727db96d56Sopenharmony_ci } 1737db96d56Sopenharmony_ci if (host == NULL || hostlen == 0) { 1747db96d56Sopenharmony_ci /* what should we do? */ 1757db96d56Sopenharmony_ci } else if (flags & NI_NUMERICHOST) { 1767db96d56Sopenharmony_ci if (inet_ntop(gni_afd->a_af, addr, numaddr, sizeof(numaddr)) 1777db96d56Sopenharmony_ci == NULL) 1787db96d56Sopenharmony_ci return ENI_SYSTEM; 1797db96d56Sopenharmony_ci if (strlen(numaddr) > hostlen) 1807db96d56Sopenharmony_ci return ENI_MEMORY; 1817db96d56Sopenharmony_ci strcpy(host, numaddr); 1827db96d56Sopenharmony_ci } else { 1837db96d56Sopenharmony_ci#ifdef ENABLE_IPV6 1847db96d56Sopenharmony_ci hp = getipnodebyaddr(addr, gni_afd->a_addrlen, gni_afd->a_af, &h_error); 1857db96d56Sopenharmony_ci#else 1867db96d56Sopenharmony_ci hp = gethostbyaddr(addr, gni_afd->a_addrlen, gni_afd->a_af); 1877db96d56Sopenharmony_ci#endif 1887db96d56Sopenharmony_ci 1897db96d56Sopenharmony_ci if (hp) { 1907db96d56Sopenharmony_ci if (flags & NI_NOFQDN) { 1917db96d56Sopenharmony_ci p = strchr(hp->h_name, '.'); 1927db96d56Sopenharmony_ci if (p) *p = '\0'; 1937db96d56Sopenharmony_ci } 1947db96d56Sopenharmony_ci if (strlen(hp->h_name) > hostlen) { 1957db96d56Sopenharmony_ci#ifdef ENABLE_IPV6 1967db96d56Sopenharmony_ci freehostent(hp); 1977db96d56Sopenharmony_ci#endif 1987db96d56Sopenharmony_ci return ENI_MEMORY; 1997db96d56Sopenharmony_ci } 2007db96d56Sopenharmony_ci strcpy(host, hp->h_name); 2017db96d56Sopenharmony_ci#ifdef ENABLE_IPV6 2027db96d56Sopenharmony_ci freehostent(hp); 2037db96d56Sopenharmony_ci#endif 2047db96d56Sopenharmony_ci } else { 2057db96d56Sopenharmony_ci if (flags & NI_NAMEREQD) 2067db96d56Sopenharmony_ci return ENI_NOHOSTNAME; 2077db96d56Sopenharmony_ci if (inet_ntop(gni_afd->a_af, addr, numaddr, sizeof(numaddr)) 2087db96d56Sopenharmony_ci == NULL) 2097db96d56Sopenharmony_ci return ENI_NOHOSTNAME; 2107db96d56Sopenharmony_ci if (strlen(numaddr) > hostlen) 2117db96d56Sopenharmony_ci return ENI_MEMORY; 2127db96d56Sopenharmony_ci strcpy(host, numaddr); 2137db96d56Sopenharmony_ci } 2147db96d56Sopenharmony_ci } 2157db96d56Sopenharmony_ci return SUCCESS; 2167db96d56Sopenharmony_ci} 2177db96d56Sopenharmony_ci#endif // HAVE_NETDB_H 218