gethostent.c revision 7c478bd95313f5f23a4c958a745db2134aa03244
/*
* Copyright 2003 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/*
* Copyright (c) 1996-1999 by Internet Software Consortium.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
* ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
* CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
* ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
* SOFTWARE.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#if !defined(LINT) && !defined(CODECENTER)
static const char rcsid[] = "$Id: gethostent.c,v 1.34 2003/05/29 00:05:18 marka Exp $";
#endif
/* Imports */
#include "port_before.h"
#if !defined(__BIND_NOSTATIC)
#include <ctype.h>
#include <errno.h>
#include <stdlib.h>
#include <netdb.h>
#include <resolv.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <irs.h>
#include <isc/memcluster.h>
#include "port_after.h"
#include "irs_p.h"
#include "irs_data.h"
/* Definitions */
struct pvt {
char * aliases[1];
char * addrs[2];
char addr[NS_IN6ADDRSZ];
};
/* Forward */
#ifdef SUNW_OVERRIDE_RETRY
extern int __res_retry(int);
extern int __res_retry_reset(void);
#endif /* SUNW_OVERRIDE_RETRY */
/* Public */
struct hostent *
gethostbyname(const char *name) {
}
struct hostent *
}
struct hostent *
#ifdef ORIGINAL_ISC_CODE
#else
#endif /* ORIGINAL_ISC_CODE */
}
struct hostent *
gethostent() {
return (gethostent_p(net_data));
}
#ifdef ORIGINAL_ISC_CODE
void
#else
int
#endif
sethostent(int stayopen) {
#ifdef ORIGINAL_ISC_CODE
#else
return (0);
#endif
}
#ifdef ORIGINAL_ISC_CODE
void
#else
int
#endif
endhostent() {
#ifdef ORIGINAL_ISC_CODE
#else
return (0);
#endif
}
/* Shared private. */
struct hostent *
if (!net_data)
#ifdef SUNW_SETHERRNO
{
/*
* Should set the context h_errno, but since net_data
* is NULL, we don't have a context.
*/
return (NULL);
}
#else
return (NULL);
#endif /* SUNW_SETHERRNO */
if (hp)
return (hp);
}
}
struct hostent *
char tmp[NS_MAXDNAME];
const char *cp;
char **hap;
#ifdef SUNW_SETHERRNO
{
return (NULL);
}
#else
return (NULL);
#endif /* SUNW_SETHERRNO */
}
return (hp);
#ifdef SUNW_OVERRIDE_RETRY
#endif /* SUNW_OVERRIDE_RETRY */
#ifdef SUNW_OVERRIDE_RETRY
#endif /* SUNW_OVERRIDE_RETRY */
if (!net_data->ho_stayopen)
endhostent();
}
struct hostent *
char **hap;
#ifdef SUNW_SETHERRNO
{
return (NULL);
}
#else
return (NULL);
#endif /* SUNW_SETHERRNO */
hap++)
if (!net_data->ho_stayopen)
endhostent();
}
struct hostent *
#ifdef SUNW_SETHERRNO
{
return (NULL);
}
#else
return (NULL);
#endif /* SUNW_SETHERRNO */
continue;
}
void
return;
if (stayopen == 0)
}
void
}
#ifndef IN6_IS_ADDR_V4COMPAT
static const unsigned char in6addr_compat[12] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
((x)->s6_addr[12] != 0 || \
(x)->s6_addr[13] != 0 || \
(x)->s6_addr[14] != 0 || \
((x)->s6_addr[15] != 0 && \
#endif
#ifndef IN6_IS_ADDR_V4MAPPED
#endif
static const unsigned char in6addr_mapped[12] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff };
static int scan_interfaces(int *, int *);
/*
* Public functions
*/
/*
* AI_V4MAPPED + AF_INET6
* If no IPv6 address then a query for IPv4 and map returned values.
*
* AI_ALL + AI_V4MAPPED + AF_INET6
* Return IPv6 and IPv4 mapped.
*
* AI_ADDRCONFIG
* Only return IPv6 / IPv4 address if there is an interface of that
* type active.
*/
struct hostent *
int tmp_err;
*error_num = NO_RECOVERY;
return (NULL);
}
/* If we care about active interfaces then check. */
if ((flags & AI_ADDRCONFIG) != 0)
*error_num = NO_RECOVERY;
return (NULL);
}
/* Check for literal address. */
/* Impossible combination? */
return (NULL);
}
/* Literal address? */
char *addr_list[2];
char *aliases[1];
}
return (NULL);
} else {
}
}
if (have_v4 &&
return (NULL);
}
} else
return (he3);
}
struct hostent *
/* Sanity Checks. */
*error_num = NO_RECOVERY;
return (NULL);
}
switch (af) {
case AF_INET:
*error_num = NO_RECOVERY;
return (NULL);
}
break;
case AF_INET6:
*error_num = NO_RECOVERY;
return (NULL);
}
break;
default:
*error_num = NO_RECOVERY;
return (NULL);
}
/*
* Lookup IPv4 and IPv4 mapped/compatible addresses
*/
cp += 12;
return (NULL);
}
return (NULL);
/*
* Restore original address if mapped/compatible.
*/
return (he2);
}
/*
* Lookup IPv6 address.
*/
return (NULL);
}
return (NULL);
}
}
void
char **cpp;
int names = 1;
int addresses = 1;
cpp++;
addresses++;
}
cpp++;
names++;
}
}
/*
* Private
*/
/*
* Scan the interface table and set have_v4 and have_v6 depending
* upon whether there are IPv4 and IPv6 interface addresses.
*
* Returns:
* 0 on success
* -1 on failure.
*/
#if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR) && \
!defined(IRIX_EMUL_IOCTL_SIOCGIFCONF)
#define SETFAMILYFLAGS
static void
static unsigned int bufsiz = 4095;
int s, cpsize, n;
/* Get interface list from system. */
goto cleanup;
/*
* Grow buffer until large enough to contain all interface
* descriptions.
*/
for (;;) {
goto cleanup;
#ifdef SETFAMILYFLAGS
lifc.lifc_flags = 0;
#endif
/*
* Some OS's just return what will fit rather
* than set EINVAL if the buffer is too small
* to fit all the interfaces in. If
* lifc.lifc_len is too near to the end of the
* buffer we will grow it just in case and
* retry.
*/
break;
}
goto cleanup;
if (bufsiz > 1000000)
goto cleanup;
bufsiz += 4096;
}
/* Parse system's interface list. */
#ifdef HAVE_SA_LEN
#ifdef FIX_ZERO_SA_LEN
#endif
#ifdef HAVE_MINIMUM_IFREQ
(int)(sizeof (struct sockaddr));
#else
#endif /* HAVE_MINIMUM_IFREQ */
#elif defined SIOCGIFCONF_ADDR
#else
/* XXX maybe this should be a hard error? */
continue;
#endif
case AF_INET:
if (*have_v4 == 0) {
&((struct sockaddr_in *)
sizeof in4);
break;
if (n < 0)
break;
break;
*have_v4 = 1;
}
break;
case AF_INET6:
if (*have_v6 == 0) {
&((struct sockaddr_in6 *)
break;
if (n < 0)
break;
break;
*have_v6 = 1;
}
break;
}
}
close(s);
/* printf("scan interface -> 4=%d 6=%d\n", *have_v4, *have_v6); */
return;
if (s != -1)
close(s);
/* printf("scan interface -> 4=%d 6=%d\n", *have_v4, *have_v6); */
return;
}
#endif
static int
union {
} u;
static unsigned int bufsiz = 4095;
int s, n;
/* Set to zero. Used as loop terminators below. */
#if defined(SIOCGLIFCONF) && defined(SIOCGLIFADDR) && \
!defined(IRIX_EMUL_IOCTL_SIOCGIFCONF)
/*
* Try to scan the interfaces using IPv6 ioctls().
*/
return (0);
#endif
/* Get interface list from system. */
goto err_ret;
/*
* Grow buffer until large enough to contain all interface
* descriptions.
*/
for (;;) {
goto err_ret;
#ifdef IRIX_EMUL_IOCTL_SIOCGIFCONF
/*
* This is a fix for IRIX OS in which the call to ioctl with
* the flag SIOCGIFCONF may not return an entry for all the
* interfaces like most flavors of Unix.
*/
if (emul_ioctl(&ifc) >= 0)
break;
#else
/*
* Some OS's just return what will fit rather
* than set EINVAL if the buffer is too small
* to fit all the interfaces in. If
* ifc.ifc_len is too near to the end of the
* buffer we will grow it just in case and
* retry.
*/
break;
}
#endif
goto err_ret;
if (bufsiz > 1000000)
goto err_ret;
bufsiz += 4096;
}
/* Parse system's interface list. */
#ifdef HAVE_SA_LEN
#ifdef FIX_ZERO_SA_LEN
#endif
#ifdef HAVE_MINIMUM_IFREQ
(int)(sizeof (struct sockaddr));
#else
#endif /* HAVE_MINIMUM_IFREQ */
#elif defined SIOCGIFCONF_ADDR
#else
/* XXX maybe this should be a hard error? */
continue;
#endif
case AF_INET:
if (*have_v4 == 0) {
&((struct sockaddr_in *)
sizeof in4);
break;
if (n < 0)
break;
break;
*have_v4 = 1;
}
break;
case AF_INET6:
if (*have_v6 == 0) {
&((struct sockaddr_in6 *)
sizeof in6);
break;
if (n < 0)
break;
break;
*have_v6 = 1;
}
break;
}
}
close(s);
/* printf("scan interface -> 4=%d 6=%d\n", *have_v4, *have_v6); */
return (0);
if (s != -1)
close(s);
/* printf("scan interface -> 4=%d 6=%d\n", *have_v4, *have_v6); */
return (-1);
}
static struct hostent *
int len = 0;
/*
* Work out array sizes;
*/
addresses++;
cpp++;
}
names++;
cpp++;
}
}
addresses++;
cpp++;
}
names++;
cpp++;
}
}
}
if (addresses == 1) {
*error_num = NO_ADDRESS;
return (NULL);
}
goto no_recovery;
goto cleanup0;
/* copy addresses */
goto cleanup1;
/* convert to mapped if required */
sizeof in6addr_mapped);
INADDRSZ);
} else {
}
cpp++;
npp++;
}
}
goto cleanup1;
/* convert to mapped if required */
sizeof in6addr_mapped);
INADDRSZ);
} else {
}
cpp++;
npp++;
}
}
goto cleanup1;
/* copy aliases */
goto cleanup2;
npp++;
cpp++;
}
/* copy hostname */
goto cleanup2;
/* set address type and length */
return(he);
cpp++;
}
cpp++;
}
*error_num = NO_RECOVERY;
return (NULL);
}
static struct net_data *
init() {
goto error;
return (NULL);
}
}
return (net_data);
}
static void
}
}
static struct hostent *
return (NULL);
}
#ifndef __bsdi__
/*
* Unlike its forebear(inet_aton), our friendly inet_pton() is strict
* in its interpretation of its input, and it will only return "1" if
* the input string is a formally valid(and thus unambiguous with
* respect to host names) internet address specification for this AF.
*
* This means "telnet 0xdeadbeef" and "telnet 127.1" are dead now.
*/
#else
/* BSDI XXX
* We put this back to inet_aton -- we really want the old behavior
* Long live 127.1...
*/
#endif
return (NULL);
}
}
switch(af) {
case AF_INET:
break;
case AF_INET6:
break;
default:
return (NULL);
}
}
#ifdef grot /* for future use in gethostbyaddr(), for "SUNSECURITY" */
char **haddr;
/*
* turn off search as the name should be absolute,
* 'localhost' should be matched by defnames
*/
return (NULL);
}
break;
if (!*haddr) {
return (NULL);
}
}
#endif /* grot */
#endif /*__BIND_NOSTATIC*/