12949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project/*
22949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
32949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project * All rights reserved.
42949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project *
52949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project * Redistribution and use in source and binary forms, with or without
62949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project * modification, are permitted provided that the following conditions
72949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project * are met:
82949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project * 1. Redistributions of source code must retain the above copyright
92949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project *    notice, this list of conditions and the following disclaimer.
102949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project * 2. Redistributions in binary form must reproduce the above copyright
112949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project *    notice, this list of conditions and the following disclaimer in the
122949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project *    documentation and/or other materials provided with the distribution.
132949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project * 3. Neither the name of the project nor the names of its contributors
142949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project *    may be used to endorse or promote products derived from this software
152949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project *    without specific prior written permission.
162949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project *
172949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
182949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
192949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
202949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
212949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
222949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
232949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
242949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
252949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
262949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
272949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project * SUCH DAMAGE.
282949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project */
292949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project
302949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project/*
312949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project * Issues to be discussed:
322949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project * - Thread safe-ness must be checked
332949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project * - Return values.  There seems to be no standard for return value (RFC2553)
342949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project *   but INRIA implementation returns EAI_xxx defined for getaddrinfo().
352949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project * - RFC2553 says that we should raise error on short buffer.  X/Open says
362949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project *   we need to truncate the result.  We obey RFC2553 (and X/Open should be
372949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project *   modified).
382949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project */
392949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project
402949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project#ifdef HAVE_CONFIG_H
412949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project#include <config.h>
422949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project#endif
432949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project
442949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project#include <sys/types.h>
452949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project#include <sys/socket.h>
462949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project#include <net/if.h>
472949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project#include <netinet/in.h>
482949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project#include <arpa/inet.h>
492949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project#include <arpa/nameser.h>
502949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project#include <netdb.h>
512949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project#include <resolv.h>
522949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project#include <string.h>
532949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project#include <stddef.h>
542949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project#include <errno.h>
552949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project
562949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project#ifdef NEED_ADDRINFO_H
572949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project#include "addrinfo.h"
582949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project#endif
592949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project
602949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project#define SUCCESS 0
612949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project#define ANY 0
622949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project#define YES 1
632949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project#define NO  0
642949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project
652949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Projectstatic struct afd {
662949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project	int a_af;
672949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project	int a_addrlen;
682949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project	int a_socklen;
692949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project	int a_off;
702949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project} afdl [] = {
712949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project#ifdef INET6
722949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project	{PF_INET6, sizeof(struct in6_addr), sizeof(struct sockaddr_in6),
732949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project		offsetof(struct sockaddr_in6, sin6_addr)},
742949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project#endif
752949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project	{PF_INET, sizeof(struct in_addr), sizeof(struct sockaddr_in),
762949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project		offsetof(struct sockaddr_in, sin_addr)},
772949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project	{0, 0, 0},
782949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project};
792949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project
802949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Projectstruct sockinet {
812949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project	u_char	si_len;
822949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project	u_char	si_family;
832949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project	u_short	si_port;
842949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project};
852949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project
862949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project#define ENI_NOSOCKET 	0
872949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project#define ENI_NOSERVNAME	1
882949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project#define ENI_NOHOSTNAME	2
892949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project#define ENI_MEMORY	3
902949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project#define ENI_SYSTEM	4
912949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project#define ENI_FAMILY	5
922949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project#define ENI_SALEN	6
932949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project
942949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Projectint
952949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Projectgetnameinfo(sa, salen, host, hostlen, serv, servlen, flags)
962949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project	const struct sockaddr *sa;
972949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project	size_t salen;
982949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project	char *host;
992949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project	size_t hostlen;
1002949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project	char *serv;
1012949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project	size_t servlen;
1022949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project	int flags;
1032949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project{
1042949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project	struct afd *afd;
1052949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project	struct servent *sp;
1062949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project	struct hostent *hp;
1072949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project	u_short port;
1082949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project	int family, i;
1092949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project	char *addr, *p;
110892a68bdf2f50b40781212e4d7ee7369c8165953Elliott Hughes	uint32_t v4a;
1112949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project	int h_error;
1122949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project	char numserv[512];
1132949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project	char numaddr[512];
1142949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project
1152949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project	if (sa == NULL)
1162949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project		return ENI_NOSOCKET;
1172949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project
1182949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project#ifdef HAVE_SA_LEN	/*XXX*/
1192949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project	if (sa->sa_len != salen)
1202949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project		return ENI_SALEN;
1212949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project#endif
1222949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project
1232949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project	family = sa->sa_family;
1242949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project	for (i = 0; afdl[i].a_af; i++)
1252949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project		if (afdl[i].a_af == family) {
1262949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project			afd = &afdl[i];
1272949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project			goto found;
1282949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project		}
1292949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project	return ENI_FAMILY;
1302949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project
1312949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project found:
1322949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project	if (salen != afd->a_socklen)
1332949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project		return ENI_SALEN;
1342949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project
1352949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project	port = ((struct sockinet *)sa)->si_port; /* network byte order */
1362949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project	addr = (char *)sa + afd->a_off;
1372949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project
1382949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project	if (serv == NULL || servlen == 0) {
1392949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project		/*
1402949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project		 * do nothing in this case.
1412949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project		 * in case you are wondering if "&&" is more correct than
1422949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project		 * "||" here: RFC2553 says that serv == NULL OR servlen == 0
1432949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project		 * means that the caller does not want the result.
1442949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project		 */
1452949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project	} else {
1462949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project		if (flags & NI_NUMERICSERV)
1472949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project			sp = NULL;
1482949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project		else {
1492949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project			sp = getservbyport(port,
1502949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project				(flags & NI_DGRAM) ? "udp" : "tcp");
1512949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project		}
1522949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project		if (sp) {
1532949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project			if (strlen(sp->s_name) + 1 > servlen)
1542949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project				return ENI_MEMORY;
1552949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project			strcpy(serv, sp->s_name);
1562949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project		} else {
1572949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project			snprintf(numserv, sizeof(numserv), "%d", ntohs(port));
1582949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project			if (strlen(numserv) + 1 > servlen)
1592949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project				return ENI_MEMORY;
1602949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project			strcpy(serv, numserv);
1612949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project		}
1622949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project	}
1632949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project
1642949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project	switch (sa->sa_family) {
1652949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project	case AF_INET:
166892a68bdf2f50b40781212e4d7ee7369c8165953Elliott Hughes                v4a = (uint32_t)
1672949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project			ntohl(((struct sockaddr_in *)sa)->sin_addr.s_addr);
1682949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project		if (IN_MULTICAST(v4a) || IN_EXPERIMENTAL(v4a))
1692949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project			flags |= NI_NUMERICHOST;
1702949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project		v4a >>= IN_CLASSA_NSHIFT;
1712949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project		if (v4a == 0)
1722949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project			flags |= NI_NUMERICHOST;
1732949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project		break;
1742949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project#ifdef INET6
1752949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project	case AF_INET6:
1762949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project	    {
1772949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project		struct sockaddr_in6 *sin6;
1782949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project		sin6 = (struct sockaddr_in6 *)sa;
1792949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project		switch (sin6->sin6_addr.s6_addr[0]) {
1802949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project		case 0x00:
1812949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project			if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr))
1822949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project				;
1832949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project			else if (IN6_IS_ADDR_LOOPBACK(&sin6->sin6_addr))
1842949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project				;
1852949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project			else
1862949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project				flags |= NI_NUMERICHOST;
1872949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project			break;
1882949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project		default:
1892949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project			if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) {
1902949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project				flags |= NI_NUMERICHOST;
1912949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project			}
1922949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project			else if (IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr))
1932949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project				flags |= NI_NUMERICHOST;
1942949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project			break;
1952949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project		}
1962949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project	    }
1972949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project		break;
1982949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project#endif
1992949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project	}
2002949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project	if (host == NULL || hostlen == 0) {
2012949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project		/*
2022949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project		 * do nothing in this case.
2032949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project		 * in case you are wondering if "&&" is more correct than
2042949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project		 * "||" here: RFC2553 says that host == NULL OR hostlen == 0
2052949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project		 * means that the caller does not want the result.
2062949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project		 */
2072949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project	} else if (flags & NI_NUMERICHOST) {
2082949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project		/* NUMERICHOST and NAMEREQD conflicts with each other */
2092949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project		if (flags & NI_NAMEREQD)
2102949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project			return ENI_NOHOSTNAME;
2112949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project		if (inet_ntop(afd->a_af, addr, numaddr, sizeof(numaddr))
2122949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project		    == NULL)
2132949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project			return ENI_SYSTEM;
2142949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project		if (strlen(numaddr) + 1 > hostlen)
2152949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project			return ENI_MEMORY;
2162949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project		strcpy(host, numaddr);
2172949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project#if defined(INET6) && defined(NI_WITHSCOPEID)
2182949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project		if (afd->a_af == AF_INET6 &&
2192949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project		    (IN6_IS_ADDR_LINKLOCAL((struct in6_addr *)addr) ||
2202949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project		     IN6_IS_ADDR_MULTICAST((struct in6_addr *)addr)) &&
2212949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project		    ((struct sockaddr_in6 *)sa)->sin6_scope_id) {
2222949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project#ifndef ALWAYS_WITHSCOPE
2232949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project			if (flags & NI_WITHSCOPEID)
2242949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project#endif /* !ALWAYS_WITHSCOPE */
2252949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project			{
2262949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project				char *ep = strchr(host, '\0');
2272949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project				unsigned int ifindex =
2282949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project					((struct sockaddr_in6 *)sa)->sin6_scope_id;
2292949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project
2302949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project				*ep = SCOPE_DELIMITER;
2312949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project				if ((if_indextoname(ifindex, ep + 1)) == NULL)
2322949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project					/* XXX what should we do? */
2332949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project					strncpy(ep + 1, "???", 3);
2342949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project			}
2352949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project		}
2362949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project#endif /* INET6 */
2372949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project	} else {
2382949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project#ifdef USE_GETIPNODEBY
2392949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project		hp = getipnodebyaddr(addr, afd->a_addrlen, afd->a_af, &h_error);
2402949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project#else
2412949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project		hp = gethostbyaddr(addr, afd->a_addrlen, afd->a_af);
2422949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project#ifdef HAVE_H_ERRNO
2432949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project		h_error = h_errno;
2442949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project#else
2452949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project		h_error = EINVAL;
2462949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project#endif
2472949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project#endif
2482949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project
2492949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project		if (hp) {
2502949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project			if (flags & NI_NOFQDN) {
2512949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project				p = strchr(hp->h_name, '.');
2522949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project				if (p) *p = '\0';
2532949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project			}
2542949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project			if (strlen(hp->h_name) + 1 > hostlen) {
2552949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project#ifdef USE_GETIPNODEBY
2562949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project				freehostent(hp);
2572949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project#endif
2582949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project				return ENI_MEMORY;
2592949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project			}
2602949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project			strcpy(host, hp->h_name);
2612949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project#ifdef USE_GETIPNODEBY
2622949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project			freehostent(hp);
2632949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project#endif
2642949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project		} else {
2652949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project			if (flags & NI_NAMEREQD)
2662949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project				return ENI_NOHOSTNAME;
2672949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project			if (inet_ntop(afd->a_af, addr, numaddr, sizeof(numaddr))
2682949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project			    == NULL)
2692949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project				return ENI_NOHOSTNAME;
2702949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project			if (strlen(numaddr) + 1 > hostlen)
2712949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project				return ENI_MEMORY;
2722949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project			strcpy(host, numaddr);
2732949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project		}
2742949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project	}
2752949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project	return SUCCESS;
2762949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project}
277