Blame contrib/idn/idnkit-1.0-src/tools/runidn/resolver.c

Packit Service ae04f2
#ifndef lint
Packit Service ae04f2
static char *rcsid = "$Id: resolver.c,v 1.1 2003/06/04 00:27:12 marka Exp $";
Packit Service ae04f2
#endif
Packit Service ae04f2
Packit Service ae04f2
/*
Packit Service ae04f2
 * Copyright (c) 2001 Japan Network Information Center.  All rights reserved.
Packit Service ae04f2
 *  
Packit Service ae04f2
 * By using this file, you agree to the terms and conditions set forth bellow.
Packit Service ae04f2
 * 
Packit Service ae04f2
 * 			LICENSE TERMS AND CONDITIONS 
Packit Service ae04f2
 * 
Packit Service ae04f2
 * The following License Terms and Conditions apply, unless a different
Packit Service ae04f2
 * license is obtained from Japan Network Information Center ("JPNIC"),
Packit Service ae04f2
 * a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
Packit Service ae04f2
 * Chiyoda-ku, Tokyo 101-0047, Japan.
Packit Service ae04f2
 * 
Packit Service ae04f2
 * 1. Use, Modification and Redistribution (including distribution of any
Packit Service ae04f2
 *    modified or derived work) in source and/or binary forms is permitted
Packit Service ae04f2
 *    under this License Terms and Conditions.
Packit Service ae04f2
 * 
Packit Service ae04f2
 * 2. Redistribution of source code must retain the copyright notices as they
Packit Service ae04f2
 *    appear in each source code file, this License Terms and Conditions.
Packit Service ae04f2
 * 
Packit Service ae04f2
 * 3. Redistribution in binary form must reproduce the Copyright Notice,
Packit Service ae04f2
 *    this License Terms and Conditions, in the documentation and/or other
Packit Service ae04f2
 *    materials provided with the distribution.  For the purposes of binary
Packit Service ae04f2
 *    distribution the "Copyright Notice" refers to the following language:
Packit Service ae04f2
 *    "Copyright (c) 2000-2002 Japan Network Information Center.  All rights reserved."
Packit Service ae04f2
 * 
Packit Service ae04f2
 * 4. The name of JPNIC may not be used to endorse or promote products
Packit Service ae04f2
 *    derived from this Software without specific prior written approval of
Packit Service ae04f2
 *    JPNIC.
Packit Service ae04f2
 * 
Packit Service ae04f2
 * 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
Packit Service ae04f2
 *    "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
Packit Service ae04f2
 *    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
Packit Service ae04f2
 *    PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL JPNIC BE LIABLE
Packit Service ae04f2
 *    FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
Packit Service ae04f2
 *    CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
Packit Service ae04f2
 *    SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
Packit Service ae04f2
 *    BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
Packit Service ae04f2
 *    WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
Packit Service ae04f2
 *    OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
Packit Service ae04f2
 *    ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
Packit Service ae04f2
 */
Packit Service ae04f2
Packit Service ae04f2
#include <config.h>
Packit Service ae04f2
Packit Service ae04f2
#include <stdio.h>
Packit Service ae04f2
#include <stddef.h>
Packit Service ae04f2
#include <stdarg.h>
Packit Service ae04f2
#include <stdlib.h>
Packit Service ae04f2
#include <string.h>
Packit Service ae04f2
#include <sys/types.h>
Packit Service ae04f2
#include <sys/socket.h>
Packit Service ae04f2
#include <netdb.h>
Packit Service ae04f2
#include <errno.h>
Packit Service ae04f2
Packit Service ae04f2
#include <idn/api.h>
Packit Service ae04f2
#include <idn/log.h>
Packit Service ae04f2
#include <idn/logmacro.h>
Packit Service ae04f2
#include <idn/debug.h>
Packit Service ae04f2
Packit Service ae04f2
#ifdef FOR_RUNIDN
Packit Service ae04f2
/*
Packit Service ae04f2
 * This file is specially compiled for runidn.
Packit Service ae04f2
 * runidn replaces existing resolver functions dynamically with ones
Packit Service ae04f2
 * with IDN processing (encoding conversion and normalization).
Packit Service ae04f2
 * So entry names must be same as the system's one.
Packit Service ae04f2
 */
Packit Service ae04f2
#include "stub.h"
Packit Service ae04f2
Packit Service ae04f2
#define ENTRY(name) name
Packit Service ae04f2
#define REAL(name) idn_stub_ ## name
Packit Service ae04f2
#else
Packit Service ae04f2
/*
Packit Service ae04f2
 * For normal use.  All the entry names are prefixed with "idn_resolver_".
Packit Service ae04f2
 * <idn/resolver.h> has bunch of #defines to substitute the standard
Packit Service ae04f2
 * name resolver functions with ones provided here.
Packit Service ae04f2
 */
Packit Service ae04f2
#include "resolver.h"
Packit Service ae04f2
#undef  gethostbyname
Packit Service ae04f2
#undef  gethostbyname2
Packit Service ae04f2
#undef  gethostbyaddr
Packit Service ae04f2
#undef  gethostbyname_r
Packit Service ae04f2
#undef  gethostbyname2_r
Packit Service ae04f2
#undef  gethostbyaddr_r
Packit Service ae04f2
#undef  getipnodebyname
Packit Service ae04f2
#undef  getipnodebyaddr
Packit Service ae04f2
#undef  getaddrinfo
Packit Service ae04f2
#undef  getnameinfo
Packit Service ae04f2
Packit Service ae04f2
#define ENTRY(name) idn_resolver_ ## name
Packit Service ae04f2
#define REAL(name) name
Packit Service ae04f2
#endif
Packit Service ae04f2
Packit Service ae04f2
#define IDN_NAME_SIZE		512
Packit Service ae04f2
Packit Service ae04f2
#define IDN_HOSTBUF_SIZE	2048
Packit Service ae04f2
typedef union {
Packit Service ae04f2
	char *dummy_for_alignment;
Packit Service ae04f2
	char data[IDN_HOSTBUF_SIZE];
Packit Service ae04f2
} hostbuf_t;
Packit Service ae04f2
Packit Service ae04f2
typedef struct obj_lock {
Packit Service ae04f2
	void *key;
Packit Service ae04f2
	struct obj_lock *next;
Packit Service ae04f2
} obj_lock_t;
Packit Service ae04f2
Packit Service ae04f2
#define OBJLOCKHASH_SIZE	127
Packit Service ae04f2
static obj_lock_t *obj_lock_hash[OBJLOCKHASH_SIZE];
Packit Service ae04f2
Packit Service ae04f2
/*
Packit Service ae04f2
 * This variable is to prevent IDN processing occurring more than once for
Packit Service ae04f2
 * a single name resolution.  This will happen if some resolver function
Packit Service ae04f2
 * is implemented using another function (e.g. gethostbyname() implemented
Packit Service ae04f2
 * using gethostbyname2()).
Packit Service ae04f2
 * No, using the static variable is not a correct thing to do for a multi-
Packit Service ae04f2
 * threading environment, but I don't think of a better solution..
Packit Service ae04f2
 */
Packit Service ae04f2
static int idn_isprocessing = 0;
Packit Service ae04f2
Packit Service ae04f2
static int		obj_hash(void *key);
Packit Service ae04f2
static int		obj_islocked(void *key);
Packit Service ae04f2
static void		obj_lock(void *key);
Packit Service ae04f2
static void		obj_unlock(void *key);
Packit Service ae04f2
static struct hostent	*copy_decode_hostent_static(struct hostent *hp,
Packit Service ae04f2
						    struct hostent *newhp,
Packit Service ae04f2
						    char *buf, size_t buflen,
Packit Service ae04f2
						    int *errp);
Packit Service ae04f2
static char		*decode_name_dynamic(const char *name);
Packit Service ae04f2
static struct hostent	*copy_decode_hostent_dynamic(struct hostent *hp,
Packit Service ae04f2
						     int *errp);
Packit Service ae04f2
static void		free_copied_hostent(struct hostent *hp);
Packit Service ae04f2
#ifdef HAVE_GETADDRINFO
Packit Service ae04f2
static struct addrinfo	*copy_decode_addrinfo_dynamic(struct addrinfo *aip);
Packit Service ae04f2
#endif
Packit Service ae04f2
#ifdef HAVE_FREEADDRINFO
Packit Service ae04f2
static void		free_copied_addrinfo(struct addrinfo *aip);
Packit Service ae04f2
#endif
Packit Service ae04f2
Packit Service ae04f2
/*
Packit Service ae04f2
 * Object locking facility.
Packit Service ae04f2
 */
Packit Service ae04f2
Packit Service ae04f2
static int
Packit Service ae04f2
obj_hash(void *key) {
Packit Service ae04f2
	/*
Packit Service ae04f2
	 * Hash function for obj_*.
Packit Service ae04f2
	 * 'key' is supposed to be an address.
Packit Service ae04f2
	 */
Packit Service ae04f2
	unsigned long v = (unsigned long)key;
Packit Service ae04f2
Packit Service ae04f2
	return ((v >> 3) % OBJLOCKHASH_SIZE);
Packit Service ae04f2
}
Packit Service ae04f2
Packit Service ae04f2
static int
Packit Service ae04f2
obj_islocked(void *key)
Packit Service ae04f2
{
Packit Service ae04f2
	/*
Packit Service ae04f2
	 * Check if the object specified by 'key' is locked.
Packit Service ae04f2
	 * Return 1 if so, 0 otherwise.
Packit Service ae04f2
	 */
Packit Service ae04f2
	int h = obj_hash(key);
Packit Service ae04f2
	obj_lock_t *olp = obj_lock_hash[h];
Packit Service ae04f2
Packit Service ae04f2
	while (olp != NULL) {
Packit Service ae04f2
		if (olp->key == key)
Packit Service ae04f2
			return (1);
Packit Service ae04f2
		olp = olp->next;
Packit Service ae04f2
	}
Packit Service ae04f2
	return (0);
Packit Service ae04f2
}
Packit Service ae04f2
Packit Service ae04f2
static void
Packit Service ae04f2
obj_lock(void *key)
Packit Service ae04f2
{
Packit Service ae04f2
	/*
Packit Service ae04f2
	 * Lock an object specified by 'key'.
Packit Service ae04f2
	 */
Packit Service ae04f2
	int h = obj_hash(key);
Packit Service ae04f2
	obj_lock_t *olp;
Packit Service ae04f2
Packit Service ae04f2
	olp = malloc(sizeof(obj_lock_t));
Packit Service ae04f2
	if (olp != NULL) {
Packit Service ae04f2
		olp->key = key;
Packit Service ae04f2
		olp->next = obj_lock_hash[h];
Packit Service ae04f2
		obj_lock_hash[h] = olp;
Packit Service ae04f2
	}
Packit Service ae04f2
}
Packit Service ae04f2
Packit Service ae04f2
static void
Packit Service ae04f2
obj_unlock(void *key)
Packit Service ae04f2
{
Packit Service ae04f2
	/*
Packit Service ae04f2
	 * Unlock an object specified by 'key'.
Packit Service ae04f2
	 */
Packit Service ae04f2
	int h = obj_hash(key);
Packit Service ae04f2
	obj_lock_t *olp, *olp0;
Packit Service ae04f2
Packit Service ae04f2
	olp = obj_lock_hash[h];
Packit Service ae04f2
	olp0 = NULL;
Packit Service ae04f2
	while (olp != NULL) {
Packit Service ae04f2
		if (olp->key == key) {
Packit Service ae04f2
			if (olp0 == NULL)
Packit Service ae04f2
				obj_lock_hash[h] = olp->next;
Packit Service ae04f2
			else
Packit Service ae04f2
				olp0->next = olp->next;
Packit Service ae04f2
			free(olp);
Packit Service ae04f2
			return;
Packit Service ae04f2
		}
Packit Service ae04f2
		olp0 = olp;
Packit Service ae04f2
		olp = olp->next;
Packit Service ae04f2
	}
Packit Service ae04f2
}
Packit Service ae04f2
Packit Service ae04f2
static struct hostent *
Packit Service ae04f2
copy_decode_hostent_static(struct hostent *hp, struct hostent *newhp,
Packit Service ae04f2
			   char *buf, size_t buflen, int *errp)
Packit Service ae04f2
{
Packit Service ae04f2
	/*
Packit Service ae04f2
	 * Copy "struct hostent" data referenced by 'hp' to 'newhp'.
Packit Service ae04f2
	 * It's a deep-copy, meaning all the data referenced by 'hp' are
Packit Service ae04f2
	 * also copied.  They are copied into 'buf', whose length is 'buflen'.
Packit Service ae04f2
	 * The domain names ('hp->h_name' and 'hp->h_aliases') are
Packit Service ae04f2
	 * decoded from ACE to the local encoding before they are copied.
Packit Service ae04f2
	 * If 'buf' is too small to hold all the data, NULL will be
Packit Service ae04f2
	 * returned and '*errp' is set to NO_RECOVERY.
Packit Service ae04f2
	 */
Packit Service ae04f2
	int naliases = 0;
Packit Service ae04f2
	int naddrs = 0;
Packit Service ae04f2
Packit Service ae04f2
	if (hp == NULL)
Packit Service ae04f2
		return (NULL);
Packit Service ae04f2
Packit Service ae04f2
	*newhp = *hp;
Packit Service ae04f2
Packit Service ae04f2
	if (hp->h_aliases != NULL) {
Packit Service ae04f2
		/*
Packit Service ae04f2
		 * Allocate aliase table in 'buf'.
Packit Service ae04f2
		 */
Packit Service ae04f2
		size_t sz;
Packit Service ae04f2
Packit Service ae04f2
		while (hp->h_aliases[naliases] != NULL)
Packit Service ae04f2
			naliases++;
Packit Service ae04f2
Packit Service ae04f2
		newhp->h_aliases = (char **)buf;
Packit Service ae04f2
		sz = sizeof(char *) * (naliases + 1);
Packit Service ae04f2
Packit Service ae04f2
		if (buflen < sz)
Packit Service ae04f2
			goto overflow;
Packit Service ae04f2
Packit Service ae04f2
		buf += sz;
Packit Service ae04f2
		buflen -= sz;
Packit Service ae04f2
	}
Packit Service ae04f2
Packit Service ae04f2
	if (hp->h_addr_list != NULL) {
Packit Service ae04f2
		/*
Packit Service ae04f2
		 * Allocate address table in 'buf'.
Packit Service ae04f2
		 */
Packit Service ae04f2
		size_t sz;
Packit Service ae04f2
		int i;
Packit Service ae04f2
Packit Service ae04f2
		while (hp->h_addr_list[naddrs] != NULL)
Packit Service ae04f2
			naddrs++;
Packit Service ae04f2
Packit Service ae04f2
		newhp->h_addr_list = (char **)buf;
Packit Service ae04f2
		sz = sizeof(char *) * (naddrs + 1);
Packit Service ae04f2
Packit Service ae04f2
		if (buflen < sz)
Packit Service ae04f2
			goto overflow;
Packit Service ae04f2
Packit Service ae04f2
		buf += sz;
Packit Service ae04f2
		buflen -= sz;
Packit Service ae04f2
Packit Service ae04f2
		/*
Packit Service ae04f2
		 * Copy the addresses.
Packit Service ae04f2
		 */
Packit Service ae04f2
		sz = hp->h_length * naddrs;
Packit Service ae04f2
		if (buflen < sz)
Packit Service ae04f2
			goto overflow;
Packit Service ae04f2
Packit Service ae04f2
		for (i = 0; i < naddrs; i++) {
Packit Service ae04f2
			newhp->h_addr_list[i] = buf;
Packit Service ae04f2
			memcpy(buf, hp->h_addr_list[i], hp->h_length);
Packit Service ae04f2
			buf += hp->h_length;
Packit Service ae04f2
		}
Packit Service ae04f2
		newhp->h_addr_list[naddrs] = NULL;
Packit Service ae04f2
Packit Service ae04f2
		buf += sz;
Packit Service ae04f2
		buflen -= sz;
Packit Service ae04f2
	}
Packit Service ae04f2
Packit Service ae04f2
	if (hp->h_name != NULL) {
Packit Service ae04f2
		/*
Packit Service ae04f2
		 * Decode the name in h_name.
Packit Service ae04f2
		 */
Packit Service ae04f2
		idn_result_t r;
Packit Service ae04f2
		size_t slen;
Packit Service ae04f2
Packit Service ae04f2
		idn_enable(1);
Packit Service ae04f2
		idn_nameinit(1);
Packit Service ae04f2
		r = idn_decodename(IDN_DECODE_APP, hp->h_name,
Packit Service ae04f2
				   buf, buflen);
Packit Service ae04f2
		switch (r) {
Packit Service ae04f2
		case idn_success:
Packit Service ae04f2
			newhp->h_name = buf;
Packit Service ae04f2
			break;
Packit Service ae04f2
		default:
Packit Service ae04f2
			/* Copy hp->h_name verbatim. */
Packit Service ae04f2
			if (strlen(hp->h_name) + 1 <= buflen) {
Packit Service ae04f2
				newhp->h_name = buf;
Packit Service ae04f2
				strcpy(buf, hp->h_name);
Packit Service ae04f2
				break;
Packit Service ae04f2
			}
Packit Service ae04f2
			/* falllthrough */
Packit Service ae04f2
		case idn_buffer_overflow:
Packit Service ae04f2
			goto overflow;
Packit Service ae04f2
		}
Packit Service ae04f2
Packit Service ae04f2
		slen = strlen(buf) + 1;
Packit Service ae04f2
		buf += slen;
Packit Service ae04f2
		buflen -= slen;
Packit Service ae04f2
	}
Packit Service ae04f2
Packit Service ae04f2
	if (hp->h_aliases != NULL) {
Packit Service ae04f2
		/*
Packit Service ae04f2
		 * Decode the names in h_aliases.
Packit Service ae04f2
		 */
Packit Service ae04f2
		char **aliases = hp->h_aliases;
Packit Service ae04f2
		char **newaliases = newhp->h_aliases;
Packit Service ae04f2
		int i;
Packit Service ae04f2
Packit Service ae04f2
		for (i = 0; i < naliases; i++) {
Packit Service ae04f2
			idn_result_t r;
Packit Service ae04f2
			size_t slen;
Packit Service ae04f2
Packit Service ae04f2
			idn_enable(1);
Packit Service ae04f2
			idn_nameinit(1);
Packit Service ae04f2
			r = idn_decodename(IDN_DECODE_APP, aliases[i],
Packit Service ae04f2
					   buf, buflen);
Packit Service ae04f2
Packit Service ae04f2
			switch (r) {
Packit Service ae04f2
			case idn_success:
Packit Service ae04f2
				newaliases[i] = buf;
Packit Service ae04f2
				break;
Packit Service ae04f2
			default:
Packit Service ae04f2
				/* Copy hp->h_name verbatim. */
Packit Service ae04f2
				if (strlen(aliases[i]) + 1 <= buflen) {
Packit Service ae04f2
					newaliases[i] = buf;
Packit Service ae04f2
					strcpy(buf, aliases[i]);
Packit Service ae04f2
					break;
Packit Service ae04f2
				}
Packit Service ae04f2
				/* falllthrough */
Packit Service ae04f2
			case idn_buffer_overflow:
Packit Service ae04f2
				goto overflow;
Packit Service ae04f2
			}
Packit Service ae04f2
Packit Service ae04f2
			slen = strlen(buf) + 1;
Packit Service ae04f2
			buf += slen;
Packit Service ae04f2
			buflen -= slen;
Packit Service ae04f2
		}
Packit Service ae04f2
		newaliases[naliases] = NULL;
Packit Service ae04f2
	}
Packit Service ae04f2
Packit Service ae04f2
	return (newhp);
Packit Service ae04f2
Packit Service ae04f2
 overflow:
Packit Service ae04f2
	*errp = NO_RECOVERY;
Packit Service ae04f2
	return (NULL);
Packit Service ae04f2
}
Packit Service ae04f2
Packit Service ae04f2
static char *
Packit Service ae04f2
decode_name_dynamic(const char *name) {
Packit Service ae04f2
	idn_result_t r;
Packit Service ae04f2
	char buf[IDN_NAME_SIZE];
Packit Service ae04f2
	char *s;
Packit Service ae04f2
Packit Service ae04f2
	idn_enable(1);
Packit Service ae04f2
	idn_nameinit(1);
Packit Service ae04f2
	r = idn_decodename(IDN_DECODE_APP, name, buf, sizeof(buf));
Packit Service ae04f2
	if (r == idn_success) {
Packit Service ae04f2
		name = buf;
Packit Service ae04f2
	}
Packit Service ae04f2
	s = malloc(strlen(name) + 1);
Packit Service ae04f2
	if (s == NULL)
Packit Service ae04f2
		return (NULL);
Packit Service ae04f2
	else
Packit Service ae04f2
		return (strcpy(s, name));
Packit Service ae04f2
}
Packit Service ae04f2
		
Packit Service ae04f2
static struct hostent *
Packit Service ae04f2
copy_decode_hostent_dynamic(struct hostent *hp, int *errp) {
Packit Service ae04f2
	/*
Packit Service ae04f2
	 * Make a deep-copy of the data referenced by 'hp', and return
Packit Service ae04f2
	 * a pointer to the copied data.
Packit Service ae04f2
	 * All the data are dynamically allocated using malloc().
Packit Service ae04f2
	 * The domain names ('hp->h_name' and 'hp->h_aliases') are
Packit Service ae04f2
	 * decoded from ACE to the local encoding before they are copied.
Packit Service ae04f2
	 * If malloc() fails, NULL will be returned and '*errp' is set to
Packit Service ae04f2
	 * NO_RECOVERY.
Packit Service ae04f2
	 */
Packit Service ae04f2
	struct hostent *newhp;
Packit Service ae04f2
	char **pp;
Packit Service ae04f2
	size_t alloc_size;
Packit Service ae04f2
	int naliases = 0;
Packit Service ae04f2
	int naddrs = 0;
Packit Service ae04f2
	int i;
Packit Service ae04f2
Packit Service ae04f2
	if (hp == NULL)
Packit Service ae04f2
		return (NULL);
Packit Service ae04f2
Packit Service ae04f2
	if (hp->h_aliases != NULL) {
Packit Service ae04f2
		while (hp->h_aliases[naliases] != NULL)
Packit Service ae04f2
			naliases++;
Packit Service ae04f2
	}
Packit Service ae04f2
Packit Service ae04f2
	if (hp->h_addr_list != NULL) {
Packit Service ae04f2
		while (hp->h_addr_list[naddrs] != NULL)
Packit Service ae04f2
			naddrs++;
Packit Service ae04f2
	}
Packit Service ae04f2
Packit Service ae04f2
	alloc_size = sizeof(struct hostent) +
Packit Service ae04f2
		sizeof(char *) * (naliases + 1) +
Packit Service ae04f2
		sizeof(char *) * (naddrs + 1) +
Packit Service ae04f2
		hp->h_length * naddrs;
Packit Service ae04f2
Packit Service ae04f2
	if ((newhp = malloc(alloc_size)) == NULL) {
Packit Service ae04f2
		return (hp);
Packit Service ae04f2
	}
Packit Service ae04f2
Packit Service ae04f2
	memset(newhp, 0, alloc_size);
Packit Service ae04f2
Packit Service ae04f2
	pp = (char **)(newhp + 1);
Packit Service ae04f2
Packit Service ae04f2
	if (hp->h_name != NULL) {
Packit Service ae04f2
		newhp->h_name = decode_name_dynamic(hp->h_name);
Packit Service ae04f2
		if (newhp->h_name == NULL)
Packit Service ae04f2
			goto alloc_fail;
Packit Service ae04f2
	}
Packit Service ae04f2
Packit Service ae04f2
	newhp->h_addrtype = hp->h_addrtype;
Packit Service ae04f2
	newhp->h_length = hp->h_length;
Packit Service ae04f2
Packit Service ae04f2
	if (hp->h_aliases != NULL) {
Packit Service ae04f2
		newhp->h_aliases = pp;
Packit Service ae04f2
		for (i = 0; i < naliases; i++) {
Packit Service ae04f2
			newhp->h_aliases[i] =
Packit Service ae04f2
				decode_name_dynamic(hp->h_aliases[i]);
Packit Service ae04f2
			if (newhp->h_aliases[i] == NULL)
Packit Service ae04f2
				goto alloc_fail;
Packit Service ae04f2
		}
Packit Service ae04f2
		newhp->h_aliases[naliases] = NULL;
Packit Service ae04f2
		pp += naliases + 1;
Packit Service ae04f2
	}
Packit Service ae04f2
Packit Service ae04f2
	if (hp->h_addr_list != NULL) {
Packit Service ae04f2
		char *p;
Packit Service ae04f2
Packit Service ae04f2
		newhp->h_addr_list = pp;
Packit Service ae04f2
		pp += naddrs + 1;
Packit Service ae04f2
		p = (char *)pp;
Packit Service ae04f2
Packit Service ae04f2
		for (i = 0; i < naddrs; i++) {
Packit Service ae04f2
			newhp->h_addr_list[i] = p;
Packit Service ae04f2
			memcpy(p, hp->h_addr_list[i], hp->h_length);
Packit Service ae04f2
			p += hp->h_length;
Packit Service ae04f2
		}
Packit Service ae04f2
		newhp->h_addr_list[naddrs] = NULL;
Packit Service ae04f2
	}
Packit Service ae04f2
Packit Service ae04f2
	return (newhp);
Packit Service ae04f2
Packit Service ae04f2
 alloc_fail:
Packit Service ae04f2
	free_copied_hostent(hp);
Packit Service ae04f2
	*errp = NO_RECOVERY;
Packit Service ae04f2
	return (NULL);
Packit Service ae04f2
}
Packit Service ae04f2
Packit Service ae04f2
static void
Packit Service ae04f2
free_copied_hostent(struct hostent *hp) {
Packit Service ae04f2
	/*
Packit Service ae04f2
	 * Free all the memory allocated by copy_decode_hostent_dynamic().
Packit Service ae04f2
	 */
Packit Service ae04f2
	if (hp->h_name != NULL)
Packit Service ae04f2
		free(hp->h_name);
Packit Service ae04f2
	if (hp->h_aliases != NULL) {
Packit Service ae04f2
		char **pp = hp->h_aliases;
Packit Service ae04f2
		while (*pp != NULL)
Packit Service ae04f2
			free(*pp++);
Packit Service ae04f2
	}
Packit Service ae04f2
	free(hp);
Packit Service ae04f2
}
Packit Service ae04f2
Packit Service ae04f2
#ifdef HAVE_GETNAMEINFO
Packit Service ae04f2
static struct addrinfo *
Packit Service ae04f2
copy_decode_addrinfo_dynamic(struct addrinfo *aip) {
Packit Service ae04f2
	struct addrinfo *newaip;
Packit Service ae04f2
Packit Service ae04f2
	if (aip == NULL)
Packit Service ae04f2
		return (NULL);
Packit Service ae04f2
Packit Service ae04f2
	newaip = malloc(sizeof(struct addrinfo) + aip->ai_addrlen);
Packit Service ae04f2
	if (newaip == NULL)
Packit Service ae04f2
		return (NULL);
Packit Service ae04f2
Packit Service ae04f2
	*newaip = *aip;
Packit Service ae04f2
	newaip->ai_addr = (struct sockaddr *)(newaip + 1);
Packit Service ae04f2
	memcpy(newaip->ai_addr, aip->ai_addr, aip->ai_addrlen);
Packit Service ae04f2
Packit Service ae04f2
	if (newaip->ai_canonname != NULL)
Packit Service ae04f2
		newaip->ai_canonname = decode_name_dynamic(aip->ai_canonname);
Packit Service ae04f2
Packit Service ae04f2
	newaip->ai_next = copy_decode_addrinfo_dynamic(aip->ai_next);
Packit Service ae04f2
	return (newaip);
Packit Service ae04f2
}
Packit Service ae04f2
#endif
Packit Service ae04f2
Packit Service ae04f2
#ifdef HAVE_FREEADDRINFO
Packit Service ae04f2
static void
Packit Service ae04f2
free_copied_addrinfo(struct addrinfo *aip) {
Packit Service ae04f2
	while (aip != NULL) {
Packit Service ae04f2
		struct addrinfo *next = aip->ai_next;
Packit Service ae04f2
Packit Service ae04f2
		if (aip->ai_canonname != NULL)
Packit Service ae04f2
			free(aip->ai_canonname);
Packit Service ae04f2
		free(aip);
Packit Service ae04f2
		aip = next;
Packit Service ae04f2
	}
Packit Service ae04f2
}
Packit Service ae04f2
#endif
Packit Service ae04f2
Packit Service ae04f2
#ifdef HAVE_GETHOSTBYNAME
Packit Service ae04f2
struct hostent *
Packit Service ae04f2
ENTRY(gethostbyname)(const char *name) {
Packit Service ae04f2
	static hostbuf_t buf;
Packit Service ae04f2
	static struct hostent he;
Packit Service ae04f2
	idn_result_t r;
Packit Service ae04f2
	struct hostent *hp;
Packit Service ae04f2
Packit Service ae04f2
	if (idn_isprocessing)
Packit Service ae04f2
		return (REAL(gethostbyname)(name));
Packit Service ae04f2
Packit Service ae04f2
	TRACE(("gethostbyname(name=%s)\n", idn__debug_xstring(name, 60)));
Packit Service ae04f2
Packit Service ae04f2
	idn_isprocessing = 1;
Packit Service ae04f2
	idn_enable(1);
Packit Service ae04f2
	idn_nameinit(1);
Packit Service ae04f2
	r = idn_encodename(IDN_ENCODE_APP, name, buf.data, sizeof(buf));
Packit Service ae04f2
	if (r == idn_success)
Packit Service ae04f2
		name = buf.data;
Packit Service ae04f2
Packit Service ae04f2
	hp = copy_decode_hostent_static(REAL(gethostbyname)(name),
Packit Service ae04f2
					&he, buf.data, sizeof(buf),
Packit Service ae04f2
					&h_errno);
Packit Service ae04f2
	idn_isprocessing = 0;
Packit Service ae04f2
	return (hp);
Packit Service ae04f2
}
Packit Service ae04f2
#endif
Packit Service ae04f2
Packit Service ae04f2
#ifdef HAVE_GETHOSTBYNAME2
Packit Service ae04f2
struct hostent *
Packit Service ae04f2
ENTRY(gethostbyname2)(const char *name, int af) {
Packit Service ae04f2
	static hostbuf_t buf;
Packit Service ae04f2
	static struct hostent he;
Packit Service ae04f2
	idn_result_t r;
Packit Service ae04f2
	struct hostent *hp;
Packit Service ae04f2
Packit Service ae04f2
	if (idn_isprocessing)
Packit Service ae04f2
		return (REAL(gethostbyname2)(name, af));
Packit Service ae04f2
Packit Service ae04f2
	TRACE(("gethostbyname2(name=%s)\n", idn__debug_xstring(name, 60), af));
Packit Service ae04f2
Packit Service ae04f2
	idn_isprocessing = 1;
Packit Service ae04f2
	idn_enable(1);
Packit Service ae04f2
	idn_nameinit(1);
Packit Service ae04f2
	r = idn_encodename(IDN_ENCODE_APP, name, buf.data, sizeof(buf));
Packit Service ae04f2
	if (r == idn_success)
Packit Service ae04f2
		name = buf.data;
Packit Service ae04f2
Packit Service ae04f2
	hp = copy_decode_hostent_static(REAL(gethostbyname2)(name, af),
Packit Service ae04f2
					&he, buf.data, sizeof(buf),
Packit Service ae04f2
					&h_errno);
Packit Service ae04f2
	idn_isprocessing = 0;
Packit Service ae04f2
	return (hp);
Packit Service ae04f2
}
Packit Service ae04f2
#endif
Packit Service ae04f2
Packit Service ae04f2
#ifdef HAVE_GETHOSTBYADDR
Packit Service ae04f2
struct hostent *
Packit Service ae04f2
ENTRY(gethostbyaddr)(GHBA_ADDR_T addr, GHBA_ADDRLEN_T len, int type) {
Packit Service ae04f2
	static hostbuf_t buf;
Packit Service ae04f2
	static struct hostent he;
Packit Service ae04f2
	struct hostent *hp;
Packit Service ae04f2
Packit Service ae04f2
	if (idn_isprocessing)
Packit Service ae04f2
		return (REAL(gethostbyaddr)(addr, len, type));
Packit Service ae04f2
Packit Service ae04f2
	TRACE(("gethostbyaddr()\n"));
Packit Service ae04f2
Packit Service ae04f2
	idn_isprocessing = 1;
Packit Service ae04f2
	hp = copy_decode_hostent_static(REAL(gethostbyaddr)(addr, len, type),
Packit Service ae04f2
					&he, buf.data, sizeof(buf),
Packit Service ae04f2
					&h_errno);
Packit Service ae04f2
	idn_isprocessing = 0;
Packit Service ae04f2
	return (hp);
Packit Service ae04f2
}
Packit Service ae04f2
#endif
Packit Service ae04f2
Packit Service ae04f2
#ifdef GETHOST_R_GLIBC_FLAVOR
Packit Service ae04f2
Packit Service ae04f2
#ifdef HAVE_GETHOSTBYNAME_R
Packit Service ae04f2
int
Packit Service ae04f2
ENTRY(gethostbyname_r)(const char *name, struct hostent *result,
Packit Service ae04f2
		       char *buffer, size_t buflen,
Packit Service ae04f2
		       struct hostent **rp, int *errp)
Packit Service ae04f2
{
Packit Service ae04f2
	char namebuf[IDN_NAME_SIZE];
Packit Service ae04f2
	char *data;
Packit Service ae04f2
	size_t datalen;
Packit Service ae04f2
	idn_result_t r;
Packit Service ae04f2
	struct hostent he;
Packit Service ae04f2
	hostbuf_t buf;
Packit Service ae04f2
	int n;
Packit Service ae04f2
Packit Service ae04f2
	if (idn_isprocessing)
Packit Service ae04f2
		return (REAL(gethostbyname_r)(name, result, buffer,
Packit Service ae04f2
					      buflen, rp, errp));
Packit Service ae04f2
Packit Service ae04f2
	TRACE(("gethostbyname_r(name=%s,buflen=%d)\n",
Packit Service ae04f2
	       idn__debug_xstring(name, 60), buflen));
Packit Service ae04f2
Packit Service ae04f2
	if (buflen <= sizeof(buf)) {
Packit Service ae04f2
		data = buf.data;
Packit Service ae04f2
		datalen = sizeof(buf);
Packit Service ae04f2
	} else {
Packit Service ae04f2
		data = malloc(buflen);
Packit Service ae04f2
		datalen = buflen;
Packit Service ae04f2
		if (data == NULL) {
Packit Service ae04f2
			*errp = NO_RECOVERY;
Packit Service ae04f2
			return (ENOMEM);
Packit Service ae04f2
		}
Packit Service ae04f2
	}
Packit Service ae04f2
Packit Service ae04f2
	idn_isprocessing = 1;
Packit Service ae04f2
	idn_enable(1);
Packit Service ae04f2
	idn_nameinit(1);
Packit Service ae04f2
	r = idn_encodename(IDN_ENCODE_APP, name, namebuf, sizeof(namebuf));
Packit Service ae04f2
	if (r == idn_success)
Packit Service ae04f2
		name = namebuf;
Packit Service ae04f2
Packit Service ae04f2
	*errp = 0;
Packit Service ae04f2
	n = REAL(gethostbyname_r)(name, &he, data, datalen, rp, errp);
Packit Service ae04f2
Packit Service ae04f2
	if (n == 0 && *rp != NULL)
Packit Service ae04f2
		*rp = copy_decode_hostent_static(*rp, result, buffer, buflen,
Packit Service ae04f2
						 errp);
Packit Service ae04f2
	idn_isprocessing = 0;
Packit Service ae04f2
Packit Service ae04f2
	if (data != buf.data)
Packit Service ae04f2
		free(data);
Packit Service ae04f2
Packit Service ae04f2
	if (*errp != 0)
Packit Service ae04f2
		n = EINVAL;	/* XXX */
Packit Service ae04f2
Packit Service ae04f2
	return (n);
Packit Service ae04f2
}
Packit Service ae04f2
#endif
Packit Service ae04f2
Packit Service ae04f2
#ifdef HAVE_GETHOSTBYNAME2_R
Packit Service ae04f2
int
Packit Service ae04f2
ENTRY(gethostbyname2_r)(const char *name, int af, struct hostent *result,
Packit Service ae04f2
			char *buffer, size_t buflen,
Packit Service ae04f2
			struct hostent **rp, int *errp)
Packit Service ae04f2
{
Packit Service ae04f2
	char namebuf[IDN_NAME_SIZE];
Packit Service ae04f2
	char *data;
Packit Service ae04f2
	size_t datalen;
Packit Service ae04f2
	idn_result_t r;
Packit Service ae04f2
	struct hostent he;
Packit Service ae04f2
	hostbuf_t buf;
Packit Service ae04f2
	int n;
Packit Service ae04f2
Packit Service ae04f2
	if (idn_isprocessing)
Packit Service ae04f2
		return (REAL(gethostbyname2_r)(name, af, result, buffer,
Packit Service ae04f2
					       buflen, rp, errp));
Packit Service ae04f2
Packit Service ae04f2
	TRACE(("gethostbyname2_r(name=%s,buflen=%d)\n",
Packit Service ae04f2
	       idn__debug_xstring(name, 60), buflen));
Packit Service ae04f2
Packit Service ae04f2
	if (buflen <= sizeof(buf)) {
Packit Service ae04f2
		data = buf.data;
Packit Service ae04f2
		datalen = sizeof(buf);
Packit Service ae04f2
	} else {
Packit Service ae04f2
		data = malloc(buflen);
Packit Service ae04f2
		datalen = buflen;
Packit Service ae04f2
		if (data == NULL) {
Packit Service ae04f2
			*errp = NO_RECOVERY;
Packit Service ae04f2
			return (ENOMEM);
Packit Service ae04f2
		}
Packit Service ae04f2
	}
Packit Service ae04f2
Packit Service ae04f2
	idn_isprocessing = 1;
Packit Service ae04f2
	idn_enable(1);
Packit Service ae04f2
	idn_nameinit(1);
Packit Service ae04f2
	r = idn_encodename(IDN_ENCODE_APP, name, namebuf, sizeof(namebuf));
Packit Service ae04f2
	if (r == idn_success)
Packit Service ae04f2
		name = namebuf;
Packit Service ae04f2
Packit Service ae04f2
	n = REAL(gethostbyname2_r)(name, af, &he, data, datalen, rp, errp);
Packit Service ae04f2
Packit Service ae04f2
	if (n == 0 && *rp != NULL)
Packit Service ae04f2
		*rp = copy_decode_hostent_static(*rp, result, buffer, buflen,
Packit Service ae04f2
						 errp);
Packit Service ae04f2
	idn_isprocessing = 0;
Packit Service ae04f2
Packit Service ae04f2
	if (data != buf.data)
Packit Service ae04f2
		free(data);
Packit Service ae04f2
Packit Service ae04f2
	if (*errp != 0)
Packit Service ae04f2
		n = EINVAL;	/* XXX */
Packit Service ae04f2
Packit Service ae04f2
	return (n);
Packit Service ae04f2
}
Packit Service ae04f2
#endif
Packit Service ae04f2
Packit Service ae04f2
#ifdef HAVE_GETHOSTBYADDR_R
Packit Service ae04f2
int
Packit Service ae04f2
ENTRY(gethostbyaddr_r)(GHBA_ADDR_T addr, GHBA_ADDRLEN_T len, int type,
Packit Service ae04f2
		       struct hostent *result,
Packit Service ae04f2
		       char *buffer, size_t buflen,
Packit Service ae04f2
		       struct hostent **rp, int *errp)
Packit Service ae04f2
{
Packit Service ae04f2
	char *data;
Packit Service ae04f2
	size_t datalen;
Packit Service ae04f2
	struct hostent he;
Packit Service ae04f2
	hostbuf_t buf;
Packit Service ae04f2
	int n;
Packit Service ae04f2
Packit Service ae04f2
	if (idn_isprocessing) {
Packit Service ae04f2
		return (REAL(gethostbyaddr_r)(addr, len, type, result,
Packit Service ae04f2
					      buffer, buflen, rp, errp));
Packit Service ae04f2
	}
Packit Service ae04f2
Packit Service ae04f2
	TRACE(("gethostbyaddr_r(buflen=%d)\n", buflen));
Packit Service ae04f2
Packit Service ae04f2
	if (buflen <= sizeof(buf)) {
Packit Service ae04f2
		data = buf.data;
Packit Service ae04f2
		datalen = sizeof(buf);
Packit Service ae04f2
	} else {
Packit Service ae04f2
		data = malloc(buflen);
Packit Service ae04f2
		datalen = buflen;
Packit Service ae04f2
		if (data == NULL) {
Packit Service ae04f2
			*errp = NO_RECOVERY;
Packit Service ae04f2
			return (ENOMEM);
Packit Service ae04f2
		}
Packit Service ae04f2
	}
Packit Service ae04f2
Packit Service ae04f2
	idn_isprocessing = 1;
Packit Service ae04f2
	n = REAL(gethostbyaddr_r)(addr, len, type, &he,
Packit Service ae04f2
				   data, datalen, rp, errp);
Packit Service ae04f2
Packit Service ae04f2
	if (n == 0 && *rp != NULL)
Packit Service ae04f2
		*rp = copy_decode_hostent_static(*rp, result, buffer, buflen,
Packit Service ae04f2
						 errp);
Packit Service ae04f2
	idn_isprocessing = 0;
Packit Service ae04f2
Packit Service ae04f2
	if (data != buf.data)
Packit Service ae04f2
		free(data);
Packit Service ae04f2
Packit Service ae04f2
	if (*errp != 0)
Packit Service ae04f2
		n = EINVAL;	/* XXX */
Packit Service ae04f2
Packit Service ae04f2
	return (0);
Packit Service ae04f2
}
Packit Service ae04f2
#endif
Packit Service ae04f2
Packit Service ae04f2
#else /* GETHOST_R_GLIBC_FLAVOR */
Packit Service ae04f2
Packit Service ae04f2
#ifdef HAVE_GETHOSTBYNAME_R
Packit Service ae04f2
struct hostent *
Packit Service ae04f2
ENTRY(gethostbyname_r)(const char *name, struct hostent *result,
Packit Service ae04f2
		       char *buffer, int buflen, int *errp)
Packit Service ae04f2
{
Packit Service ae04f2
	char namebuf[IDN_NAME_SIZE];
Packit Service ae04f2
	char *data;
Packit Service ae04f2
	size_t datalen;
Packit Service ae04f2
	idn_result_t r;
Packit Service ae04f2
	struct hostent *hp, he;
Packit Service ae04f2
	hostbuf_t buf;
Packit Service ae04f2
Packit Service ae04f2
	if (idn_isprocessing)
Packit Service ae04f2
		return (REAL(gethostbyname_r)(name, result, buffer,
Packit Service ae04f2
					      buflen, errp));
Packit Service ae04f2
Packit Service ae04f2
	TRACE(("gethostbyname_r(name=%s,buflen=%d)\n",
Packit Service ae04f2
	       idn__debug_xstring(name, 60), buflen));
Packit Service ae04f2
Packit Service ae04f2
	if (buflen <= sizeof(buf)) {
Packit Service ae04f2
		data = buf.data;
Packit Service ae04f2
		datalen = sizeof(buf);
Packit Service ae04f2
	} else {
Packit Service ae04f2
		data = malloc(buflen);
Packit Service ae04f2
		datalen = buflen;
Packit Service ae04f2
		if (data == NULL) {
Packit Service ae04f2
			*errp = NO_RECOVERY;
Packit Service ae04f2
			return (NULL);
Packit Service ae04f2
		}
Packit Service ae04f2
	}
Packit Service ae04f2
Packit Service ae04f2
	idn_isprocessing = 1;
Packit Service ae04f2
	idn_enable(1);
Packit Service ae04f2
	idn_nameinit(1);
Packit Service ae04f2
	r = idn_encodename(IDN_ENCODE_APP, name, namebuf, sizeof(namebuf));
Packit Service ae04f2
	if (r == idn_success)
Packit Service ae04f2
		name = namebuf;
Packit Service ae04f2
Packit Service ae04f2
	hp = REAL(gethostbyname_r)(name, &he, data, datalen, errp);
Packit Service ae04f2
Packit Service ae04f2
	if (hp != NULL)
Packit Service ae04f2
		hp = copy_decode_hostent_static(hp, result, buffer, buflen,
Packit Service ae04f2
						errp);
Packit Service ae04f2
	idn_isprocessing = 0;
Packit Service ae04f2
Packit Service ae04f2
	if (data != buf.data)
Packit Service ae04f2
		free(data);
Packit Service ae04f2
Packit Service ae04f2
	return (hp);
Packit Service ae04f2
}
Packit Service ae04f2
#endif
Packit Service ae04f2
Packit Service ae04f2
#ifdef HAVE_GETHOSTBYADDR_R
Packit Service ae04f2
struct hostent *
Packit Service ae04f2
ENTRY(gethostbyaddr_r)(GHBA_ADDR_T addr, GHBA_ADDRLEN_T len, int type,
Packit Service ae04f2
		       struct hostent *result,
Packit Service ae04f2
		       char *buffer, int buflen, int *errp)
Packit Service ae04f2
{
Packit Service ae04f2
	char *data;
Packit Service ae04f2
	size_t datalen;
Packit Service ae04f2
	struct hostent *hp, he;
Packit Service ae04f2
	hostbuf_t buf;
Packit Service ae04f2
Packit Service ae04f2
	if (idn_isprocessing) {
Packit Service ae04f2
		return (REAL(gethostbyaddr_r)(addr, len, type, result,
Packit Service ae04f2
					      buffer, buflen, errp));
Packit Service ae04f2
	}
Packit Service ae04f2
Packit Service ae04f2
	TRACE(("gethostbyaddr_r(buflen=%d)\n", buflen));
Packit Service ae04f2
Packit Service ae04f2
	if (buflen <= sizeof(buf)) {
Packit Service ae04f2
		data = buf.data;
Packit Service ae04f2
		datalen = sizeof(buf);
Packit Service ae04f2
	} else {
Packit Service ae04f2
		data = malloc(buflen);
Packit Service ae04f2
		datalen = buflen;
Packit Service ae04f2
		if (data == NULL) {
Packit Service ae04f2
			*errp = NO_RECOVERY;
Packit Service ae04f2
			return (NULL);
Packit Service ae04f2
		}
Packit Service ae04f2
	}
Packit Service ae04f2
Packit Service ae04f2
	idn_isprocessing = 1;
Packit Service ae04f2
	hp = REAL(gethostbyaddr_r)(addr, len, type, &he, data, datalen, errp);
Packit Service ae04f2
Packit Service ae04f2
	if (hp != NULL)
Packit Service ae04f2
		hp = copy_decode_hostent_static(hp, result, buffer, buflen,
Packit Service ae04f2
						errp);
Packit Service ae04f2
	idn_isprocessing = 0;
Packit Service ae04f2
Packit Service ae04f2
	if (data != buf.data)
Packit Service ae04f2
		free(data);
Packit Service ae04f2
Packit Service ae04f2
	return (hp);
Packit Service ae04f2
}
Packit Service ae04f2
#endif
Packit Service ae04f2
Packit Service ae04f2
#endif /* GETHOST_R_GLIBC_FLAVOR */
Packit Service ae04f2
Packit Service ae04f2
#ifdef HAVE_GETIPNODEBYNAME
Packit Service ae04f2
struct hostent *
Packit Service ae04f2
ENTRY(getipnodebyname)(const char *name, int af, int flags, int *errp) {
Packit Service ae04f2
	char namebuf[IDN_NAME_SIZE];
Packit Service ae04f2
	idn_result_t r;
Packit Service ae04f2
	struct hostent *hp;
Packit Service ae04f2
Packit Service ae04f2
	if (idn_isprocessing)
Packit Service ae04f2
		return (REAL(getipnodebyname)(name, af, flags, errp));
Packit Service ae04f2
Packit Service ae04f2
	TRACE(("getipnodebyname(name=%s)\n", idn__debug_xstring(name, 60), af));
Packit Service ae04f2
Packit Service ae04f2
	idn_isprocessing = 1;
Packit Service ae04f2
	idn_enable(1);
Packit Service ae04f2
	idn_nameinit(1);
Packit Service ae04f2
	r = idn_encodename(IDN_ENCODE_APP, name, namebuf, sizeof(namebuf));
Packit Service ae04f2
	if (r == idn_success)
Packit Service ae04f2
		name = namebuf;
Packit Service ae04f2
Packit Service ae04f2
	hp = REAL(getipnodebyname)(name, af, flags, errp);
Packit Service ae04f2
	if (hp != NULL) {
Packit Service ae04f2
		struct hostent *newhp = copy_decode_hostent_dynamic(hp, errp);
Packit Service ae04f2
		if (newhp != hp) {
Packit Service ae04f2
			REAL(freehostent)(hp);
Packit Service ae04f2
			obj_lock(newhp);
Packit Service ae04f2
			hp = newhp;
Packit Service ae04f2
		}
Packit Service ae04f2
	}
Packit Service ae04f2
	idn_isprocessing = 0;
Packit Service ae04f2
	return (hp);
Packit Service ae04f2
}
Packit Service ae04f2
#endif
Packit Service ae04f2
Packit Service ae04f2
#ifdef HAVE_GETIPNODEBYADDR
Packit Service ae04f2
struct hostent *
Packit Service ae04f2
ENTRY(getipnodebyaddr)(const void *src, size_t len, int af, int *errp) {
Packit Service ae04f2
	struct hostent *hp;
Packit Service ae04f2
Packit Service ae04f2
	if (idn_isprocessing)
Packit Service ae04f2
		return (REAL(getipnodebyaddr)(src, len, af, errp));
Packit Service ae04f2
Packit Service ae04f2
	TRACE(("getipnodebyaddr()\n"));
Packit Service ae04f2
Packit Service ae04f2
	idn_isprocessing = 1;
Packit Service ae04f2
	hp = REAL(getipnodebyaddr)(src, len, af, errp);
Packit Service ae04f2
	if (hp != NULL) {
Packit Service ae04f2
		struct hostent *newhp = copy_decode_hostent_dynamic(hp, errp);
Packit Service ae04f2
		if (newhp != hp) {
Packit Service ae04f2
			REAL(freehostent)(hp);
Packit Service ae04f2
			obj_lock(newhp);
Packit Service ae04f2
			hp = newhp;
Packit Service ae04f2
		}
Packit Service ae04f2
	}
Packit Service ae04f2
	idn_isprocessing = 0;
Packit Service ae04f2
	return (hp);
Packit Service ae04f2
}
Packit Service ae04f2
#endif
Packit Service ae04f2
Packit Service ae04f2
#ifdef HAVE_FREEHOSTENT
Packit Service ae04f2
void
Packit Service ae04f2
ENTRY(freehostent)(struct hostent *hp) {
Packit Service ae04f2
	TRACE(("freehostent(hp=%p)\n", (void *)hp));
Packit Service ae04f2
Packit Service ae04f2
	if (obj_islocked(hp)) {
Packit Service ae04f2
		/*
Packit Service ae04f2
		 * We allocated the data.
Packit Service ae04f2
		 */
Packit Service ae04f2
		obj_unlock(hp);
Packit Service ae04f2
		free_copied_hostent(hp);
Packit Service ae04f2
	} else {
Packit Service ae04f2
		/*
Packit Service ae04f2
		 * It was allocated the original getipnodeby*().
Packit Service ae04f2
		 */
Packit Service ae04f2
		REAL(freehostent)(hp);
Packit Service ae04f2
	}
Packit Service ae04f2
}
Packit Service ae04f2
#endif
Packit Service ae04f2
Packit Service ae04f2
#ifdef HAVE_GETADDRINFO
Packit Service ae04f2
int
Packit Service ae04f2
ENTRY(getaddrinfo)(const char *nodename, const char *servname,
Packit Service ae04f2
		   const struct addrinfo *hints, struct addrinfo **res)
Packit Service ae04f2
{
Packit Service ae04f2
	char namebuf[IDN_NAME_SIZE];
Packit Service ae04f2
	idn_result_t r;
Packit Service ae04f2
	struct addrinfo *aip;
Packit Service ae04f2
	int err;
Packit Service ae04f2
Packit Service ae04f2
	if (nodename == NULL || idn_isprocessing)
Packit Service ae04f2
		return (REAL(getaddrinfo)(nodename, servname, hints, res));
Packit Service ae04f2
Packit Service ae04f2
	TRACE(("getaddrinfo(nodename=%s)\n", idn__debug_xstring(nodename, 60)));
Packit Service ae04f2
Packit Service ae04f2
	idn_isprocessing = 1;
Packit Service ae04f2
	idn_enable(1);
Packit Service ae04f2
	idn_nameinit(1);
Packit Service ae04f2
	r = idn_encodename(IDN_ENCODE_APP, nodename,
Packit Service ae04f2
			   namebuf, sizeof(namebuf));
Packit Service ae04f2
	if (r == idn_success)
Packit Service ae04f2
		nodename = namebuf;
Packit Service ae04f2
Packit Service ae04f2
	err = REAL(getaddrinfo)(nodename, servname, hints, &aip);
Packit Service ae04f2
	if (err == 0 && aip != NULL) {
Packit Service ae04f2
		*res = copy_decode_addrinfo_dynamic(aip);
Packit Service ae04f2
		if (*res == NULL)
Packit Service ae04f2
			err = EAI_FAIL;
Packit Service ae04f2
		else 
Packit Service ae04f2
			obj_lock(*res);
Packit Service ae04f2
		if (aip != NULL)
Packit Service ae04f2
			REAL(freeaddrinfo)(aip);
Packit Service ae04f2
	}
Packit Service ae04f2
	idn_isprocessing = 0;
Packit Service ae04f2
	return (err);
Packit Service ae04f2
}
Packit Service ae04f2
#endif
Packit Service ae04f2
Packit Service ae04f2
#ifdef HAVE_FREEADDRINFO
Packit Service ae04f2
void
Packit Service ae04f2
ENTRY(freeaddrinfo)(struct addrinfo *aip) {
Packit Service ae04f2
	TRACE(("freeaddrinfo(aip=%p)\n", (void *)aip));
Packit Service ae04f2
Packit Service ae04f2
	if (obj_islocked(aip)) {
Packit Service ae04f2
		/*
Packit Service ae04f2
		 * We allocated the data.
Packit Service ae04f2
		 */
Packit Service ae04f2
		obj_unlock(aip);
Packit Service ae04f2
		free_copied_addrinfo(aip);
Packit Service ae04f2
	} else {
Packit Service ae04f2
		/*
Packit Service ae04f2
		 * It was allocated the original getaddrinfo().
Packit Service ae04f2
		 */
Packit Service ae04f2
		REAL(freeaddrinfo)(aip);
Packit Service ae04f2
	}
Packit Service ae04f2
}
Packit Service ae04f2
#endif
Packit Service ae04f2
Packit Service ae04f2
#ifdef HAVE_GETNAMEINFO
Packit Service ae04f2
int
Packit Service ae04f2
ENTRY(getnameinfo)(const struct sockaddr *sa, GNI_SALEN_T salen,
Packit Service ae04f2
		   char *host, GNI_HOSTLEN_T hostlen, char *serv,
Packit Service ae04f2
		   GNI_SERVLEN_T servlen, GNI_FLAGS_T flags)
Packit Service ae04f2
{
Packit Service ae04f2
	char name[IDN_NAME_SIZE];
Packit Service ae04f2
	size_t namelen = sizeof(name);
Packit Service ae04f2
	int code;
Packit Service ae04f2
	idn_result_t r;
Packit Service ae04f2
Packit Service ae04f2
	if (host == NULL || hostlen == 0 || idn_isprocessing) {
Packit Service ae04f2
		return (REAL(getnameinfo)(sa, salen, host, hostlen,
Packit Service ae04f2
					  serv, servlen, flags));
Packit Service ae04f2
	}
Packit Service ae04f2
Packit Service ae04f2
	TRACE(("getnameinfo(hostlen=%u)\n", hostlen));
Packit Service ae04f2
Packit Service ae04f2
	idn_isprocessing = 1;
Packit Service ae04f2
	code = REAL(getnameinfo)(sa, salen, name, namelen,
Packit Service ae04f2
				 serv, servlen, flags);
Packit Service ae04f2
	if (code == 0 && name[0] != '\0') {
Packit Service ae04f2
		idn_enable(1);
Packit Service ae04f2
		idn_nameinit(1);
Packit Service ae04f2
		r = idn_decodename(IDN_DECODE_APP, name, host, hostlen);
Packit Service ae04f2
		switch (r) {
Packit Service ae04f2
		case idn_success:
Packit Service ae04f2
			code = 0;
Packit Service ae04f2
			break;
Packit Service ae04f2
		case idn_buffer_overflow:
Packit Service ae04f2
		case idn_nomemory:
Packit Service ae04f2
			code = EAI_MEMORY;
Packit Service ae04f2
			break;
Packit Service ae04f2
		default:
Packit Service ae04f2
			code = EAI_FAIL;
Packit Service ae04f2
			break;
Packit Service ae04f2
		}
Packit Service ae04f2
	}
Packit Service ae04f2
	idn_isprocessing = 0;
Packit Service ae04f2
	return (code);
Packit Service ae04f2
}
Packit Service ae04f2
#endif