getnameinfo.c revision 2949f58a438f6fd85f66a8b7ed4708042cde4b37
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#ifndef lint
452949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Projectstatic const char rcsid[] _U_ =
462949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project     "@(#) $Header: /tcpdump/master/tcpdump/missing/getnameinfo.c,v 1.11 2003/11/16 09:36:49 guy Exp $";
472949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project#endif
482949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project
492949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project#include <sys/types.h>
502949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project#include <sys/socket.h>
512949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project#include <net/if.h>
522949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project#include <netinet/in.h>
532949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project#include <arpa/inet.h>
542949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project#include <arpa/nameser.h>
552949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project#include <netdb.h>
562949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project#include <resolv.h>
572949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project#include <string.h>
582949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project#include <stddef.h>
592949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project#include <errno.h>
602949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project
612949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project#ifdef NEED_ADDRINFO_H
622949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project#include "addrinfo.h"
632949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project#endif
642949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project
652949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project#define SUCCESS 0
662949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project#define ANY 0
672949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project#define YES 1
682949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project#define NO  0
692949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project
702949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Projectstatic struct afd {
712949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project	int a_af;
722949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project	int a_addrlen;
732949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project	int a_socklen;
742949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project	int a_off;
752949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project} afdl [] = {
762949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project#ifdef INET6
772949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project	{PF_INET6, sizeof(struct in6_addr), sizeof(struct sockaddr_in6),
782949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project		offsetof(struct sockaddr_in6, sin6_addr)},
792949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project#endif
802949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project	{PF_INET, sizeof(struct in_addr), sizeof(struct sockaddr_in),
812949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project		offsetof(struct sockaddr_in, sin_addr)},
822949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project	{0, 0, 0},
832949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project};
842949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project
852949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Projectstruct sockinet {
862949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project	u_char	si_len;
872949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project	u_char	si_family;
882949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project	u_short	si_port;
892949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project};
902949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project
912949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project#define ENI_NOSOCKET 	0
922949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project#define ENI_NOSERVNAME	1
932949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project#define ENI_NOHOSTNAME	2
942949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project#define ENI_MEMORY	3
952949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project#define ENI_SYSTEM	4
962949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project#define ENI_FAMILY	5
972949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project#define ENI_SALEN	6
982949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project
992949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Projectint
1002949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Projectgetnameinfo(sa, salen, host, hostlen, serv, servlen, flags)
1012949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project	const struct sockaddr *sa;
1022949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project	size_t salen;
1032949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project	char *host;
1042949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project	size_t hostlen;
1052949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project	char *serv;
1062949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project	size_t servlen;
1072949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project	int flags;
1082949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project{
1092949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project	struct afd *afd;
1102949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project	struct servent *sp;
1112949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project	struct hostent *hp;
1122949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project	u_short port;
1132949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project	int family, i;
1142949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project	char *addr, *p;
1152949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project	u_int32_t v4a;
1162949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project	int h_error;
1172949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project	char numserv[512];
1182949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project	char numaddr[512];
1192949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project
1202949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project	if (sa == NULL)
1212949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project		return ENI_NOSOCKET;
1222949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project
1232949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project#ifdef HAVE_SA_LEN	/*XXX*/
1242949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project	if (sa->sa_len != salen)
1252949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project		return ENI_SALEN;
1262949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project#endif
1272949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project
1282949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project	family = sa->sa_family;
1292949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project	for (i = 0; afdl[i].a_af; i++)
1302949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project		if (afdl[i].a_af == family) {
1312949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project			afd = &afdl[i];
1322949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project			goto found;
1332949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project		}
1342949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project	return ENI_FAMILY;
1352949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project
1362949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project found:
1372949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project	if (salen != afd->a_socklen)
1382949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project		return ENI_SALEN;
1392949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project
1402949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project	port = ((struct sockinet *)sa)->si_port; /* network byte order */
1412949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project	addr = (char *)sa + afd->a_off;
1422949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project
1432949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project	if (serv == NULL || servlen == 0) {
1442949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project		/*
1452949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project		 * do nothing in this case.
1462949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project		 * in case you are wondering if "&&" is more correct than
1472949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project		 * "||" here: RFC2553 says that serv == NULL OR servlen == 0
1482949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project		 * means that the caller does not want the result.
1492949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project		 */
1502949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project	} else {
1512949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project		if (flags & NI_NUMERICSERV)
1522949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project			sp = NULL;
1532949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project		else {
1542949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project			sp = getservbyport(port,
1552949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project				(flags & NI_DGRAM) ? "udp" : "tcp");
1562949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project		}
1572949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project		if (sp) {
1582949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project			if (strlen(sp->s_name) + 1 > servlen)
1592949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project				return ENI_MEMORY;
1602949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project			strcpy(serv, sp->s_name);
1612949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project		} else {
1622949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project			snprintf(numserv, sizeof(numserv), "%d", ntohs(port));
1632949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project			if (strlen(numserv) + 1 > servlen)
1642949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project				return ENI_MEMORY;
1652949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project			strcpy(serv, numserv);
1662949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project		}
1672949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project	}
1682949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project
1692949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project	switch (sa->sa_family) {
1702949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project	case AF_INET:
1712949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project		v4a = (u_int32_t)
1722949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project			ntohl(((struct sockaddr_in *)sa)->sin_addr.s_addr);
1732949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project		if (IN_MULTICAST(v4a) || IN_EXPERIMENTAL(v4a))
1742949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project			flags |= NI_NUMERICHOST;
1752949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project		v4a >>= IN_CLASSA_NSHIFT;
1762949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project		if (v4a == 0)
1772949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project			flags |= NI_NUMERICHOST;
1782949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project		break;
1792949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project#ifdef INET6
1802949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project	case AF_INET6:
1812949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project	    {
1822949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project		struct sockaddr_in6 *sin6;
1832949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project		sin6 = (struct sockaddr_in6 *)sa;
1842949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project		switch (sin6->sin6_addr.s6_addr[0]) {
1852949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project		case 0x00:
1862949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project			if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr))
1872949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project				;
1882949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project			else if (IN6_IS_ADDR_LOOPBACK(&sin6->sin6_addr))
1892949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project				;
1902949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project			else
1912949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project				flags |= NI_NUMERICHOST;
1922949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project			break;
1932949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project		default:
1942949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project			if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) {
1952949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project				flags |= NI_NUMERICHOST;
1962949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project			}
1972949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project			else if (IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr))
1982949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project				flags |= NI_NUMERICHOST;
1992949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project			break;
2002949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project		}
2012949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project	    }
2022949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project		break;
2032949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project#endif
2042949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project	}
2052949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project	if (host == NULL || hostlen == 0) {
2062949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project		/*
2072949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project		 * do nothing in this case.
2082949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project		 * in case you are wondering if "&&" is more correct than
2092949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project		 * "||" here: RFC2553 says that host == NULL OR hostlen == 0
2102949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project		 * means that the caller does not want the result.
2112949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project		 */
2122949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project	} else if (flags & NI_NUMERICHOST) {
2132949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project		/* NUMERICHOST and NAMEREQD conflicts with each other */
2142949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project		if (flags & NI_NAMEREQD)
2152949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project			return ENI_NOHOSTNAME;
2162949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project		if (inet_ntop(afd->a_af, addr, numaddr, sizeof(numaddr))
2172949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project		    == NULL)
2182949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project			return ENI_SYSTEM;
2192949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project		if (strlen(numaddr) + 1 > hostlen)
2202949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project			return ENI_MEMORY;
2212949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project		strcpy(host, numaddr);
2222949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project#if defined(INET6) && defined(NI_WITHSCOPEID)
2232949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project		if (afd->a_af == AF_INET6 &&
2242949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project		    (IN6_IS_ADDR_LINKLOCAL((struct in6_addr *)addr) ||
2252949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project		     IN6_IS_ADDR_MULTICAST((struct in6_addr *)addr)) &&
2262949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project		    ((struct sockaddr_in6 *)sa)->sin6_scope_id) {
2272949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project#ifndef ALWAYS_WITHSCOPE
2282949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project			if (flags & NI_WITHSCOPEID)
2292949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project#endif /* !ALWAYS_WITHSCOPE */
2302949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project			{
2312949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project				char *ep = strchr(host, '\0');
2322949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project				unsigned int ifindex =
2332949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project					((struct sockaddr_in6 *)sa)->sin6_scope_id;
2342949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project
2352949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project				*ep = SCOPE_DELIMITER;
2362949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project				if ((if_indextoname(ifindex, ep + 1)) == NULL)
2372949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project					/* XXX what should we do? */
2382949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project					strncpy(ep + 1, "???", 3);
2392949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project			}
2402949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project		}
2412949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project#endif /* INET6 */
2422949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project	} else {
2432949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project#ifdef USE_GETIPNODEBY
2442949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project		hp = getipnodebyaddr(addr, afd->a_addrlen, afd->a_af, &h_error);
2452949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project#else
2462949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project		hp = gethostbyaddr(addr, afd->a_addrlen, afd->a_af);
2472949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project#ifdef HAVE_H_ERRNO
2482949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project		h_error = h_errno;
2492949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project#else
2502949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project		h_error = EINVAL;
2512949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project#endif
2522949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project#endif
2532949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project
2542949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project		if (hp) {
2552949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project			if (flags & NI_NOFQDN) {
2562949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project				p = strchr(hp->h_name, '.');
2572949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project				if (p) *p = '\0';
2582949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project			}
2592949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project			if (strlen(hp->h_name) + 1 > hostlen) {
2602949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project#ifdef USE_GETIPNODEBY
2612949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project				freehostent(hp);
2622949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project#endif
2632949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project				return ENI_MEMORY;
2642949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project			}
2652949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project			strcpy(host, hp->h_name);
2662949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project#ifdef USE_GETIPNODEBY
2672949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project			freehostent(hp);
2682949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project#endif
2692949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project		} else {
2702949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project			if (flags & NI_NAMEREQD)
2712949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project				return ENI_NOHOSTNAME;
2722949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project			if (inet_ntop(afd->a_af, addr, numaddr, sizeof(numaddr))
2732949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project			    == NULL)
2742949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project				return ENI_NOHOSTNAME;
2752949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project			if (strlen(numaddr) + 1 > hostlen)
2762949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project				return ENI_MEMORY;
2772949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project			strcpy(host, numaddr);
2782949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project		}
2792949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project	}
2802949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project	return SUCCESS;
2812949f58a438f6fd85f66a8b7ed4708042cde4b37The Android Open Source Project}
282