159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan * Copyright (C) 2001,2002,2003,2004,2005,2006 by the Massachusetts Institute of Technology,
505d05c73a6e56769f263d4803b22eddd168ee24gtb * Cambridge, MA, USA. All Rights Reserved.
505d05c73a6e56769f263d4803b22eddd168ee24gtb * This software is being provided to you, the LICENSEE, by the
505d05c73a6e56769f263d4803b22eddd168ee24gtb * Massachusetts Institute of Technology (M.I.T.) under the following
505d05c73a6e56769f263d4803b22eddd168ee24gtb * license. By obtaining, using and/or copying this software, you agree
505d05c73a6e56769f263d4803b22eddd168ee24gtb * that you have read, understood, and will comply with these terms and
505d05c73a6e56769f263d4803b22eddd168ee24gtb * conditions:
505d05c73a6e56769f263d4803b22eddd168ee24gtb * Export of this software from the United States of America may
505d05c73a6e56769f263d4803b22eddd168ee24gtb * require a specific license from the United States Government.
505d05c73a6e56769f263d4803b22eddd168ee24gtb * It is the responsibility of any person or organization contemplating
505d05c73a6e56769f263d4803b22eddd168ee24gtb * export to obtain such a license before exporting.
505d05c73a6e56769f263d4803b22eddd168ee24gtb * WITHIN THAT CONSTRAINT, permission to use, copy, modify and distribute
505d05c73a6e56769f263d4803b22eddd168ee24gtb * this software and its documentation for any purpose and without fee or
505d05c73a6e56769f263d4803b22eddd168ee24gtb * royalty is hereby granted, provided that you agree to comply with the
505d05c73a6e56769f263d4803b22eddd168ee24gtb * following copyright notice and statements, including the disclaimer, and
505d05c73a6e56769f263d4803b22eddd168ee24gtb * that the same appear on ALL copies of the software and documentation,
505d05c73a6e56769f263d4803b22eddd168ee24gtb * including modifications that you make for internal use or for
505d05c73a6e56769f263d4803b22eddd168ee24gtb * distribution:
505d05c73a6e56769f263d4803b22eddd168ee24gtb * THIS SOFTWARE IS PROVIDED "AS IS", AND M.I.T. MAKES NO REPRESENTATIONS
505d05c73a6e56769f263d4803b22eddd168ee24gtb * OR WARRANTIES, EXPRESS OR IMPLIED. By way of example, but not
505d05c73a6e56769f263d4803b22eddd168ee24gtb * limitation, M.I.T. MAKES NO REPRESENTATIONS OR WARRANTIES OF
505d05c73a6e56769f263d4803b22eddd168ee24gtb * MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF
505d05c73a6e56769f263d4803b22eddd168ee24gtb * THE LICENSED SOFTWARE OR DOCUMENTATION WILL NOT INFRINGE ANY THIRD PARTY
505d05c73a6e56769f263d4803b22eddd168ee24gtb * PATENTS, COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS.
505d05c73a6e56769f263d4803b22eddd168ee24gtb * The name of the Massachusetts Institute of Technology or M.I.T. may NOT
505d05c73a6e56769f263d4803b22eddd168ee24gtb * be used in advertising or publicity pertaining to distribution of the
505d05c73a6e56769f263d4803b22eddd168ee24gtb * software. Title to copyright in this software and any associated
505d05c73a6e56769f263d4803b22eddd168ee24gtb * documentation shall at all times remain with M.I.T., and USER agrees to
505d05c73a6e56769f263d4803b22eddd168ee24gtb * preserve same.
505d05c73a6e56769f263d4803b22eddd168ee24gtb * Furthermore if you modify this software you must label
505d05c73a6e56769f263d4803b22eddd168ee24gtb * your software as modified software and not distribute it in such a
505d05c73a6e56769f263d4803b22eddd168ee24gtb * fashion that it might be confused with the original M.I.T. software.
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan/* Approach overview:
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan If a system version is available but buggy, save handles to it,
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan redefine the names to refer to static functions defined here, and
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan in those functions, call the system versions and fix up the
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan returned data. Use the native data structures and flag values.
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan If no system version exists, use gethostby* and fake it. Define
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan the data structures and flag values locally.
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan On Mac OS X, getaddrinfo results aren't cached (though
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan gethostbyname results are), so we need to build a cache here. Now
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan things are getting really messy. Because the cache is in use, we
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan use getservbyname, and throw away thread safety. (Not that the
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan cache is thread safe, but when we get locking support, that'll be
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan dealt with.) This code needs tearing down and rebuilding, soon.
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan Note that recent Windows developers' code has an interesting hack:
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan When you include the right header files, with the right set of
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan macros indicating system versions, you'll get an inline function
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan that looks for getaddrinfo (or whatever) in the system library, and
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan calls it if it's there. If it's not there, it fakes it with
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan gethostby* calls.
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan We're taking a simpler approach: A system provides these routines or
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan it does not.
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan Someday, we may want to take into account different versions (say,
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan different revs of GNU libc) where some are broken in one way, and
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan some work or are broken in another way. Cross that bridge when we
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan come to it. */
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan/* To do, maybe:
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan + For AIX 4.3.3, using the RFC 2133 definition: Implement
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan AI_NUMERICHOST. It's not defined in the header file.
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan For certain (old?) versions of GNU libc, AI_NUMERICHOST is
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan defined but not implemented.
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan + Use gethostbyname2, inet_aton and other IPv6 or thread-safe
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan functions if available. But, see
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=135182 for one
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan gethostbyname2 problem on Linux. And besides, if a platform is
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan supporting IPv6 at all, they really should be doing getaddrinfo
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan + inet_ntop, inet_pton
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan + Conditionally export/import the function definitions, so a
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan library can have a single copy instead of multiple.
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan + Upgrade host requirements to include working implementations of
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan these functions, and throw all this away. Pleeease? :-) */
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan/*@-incondefs@*/
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalanfreeaddrinfo (/*@only@*/ /*@out@*/ struct addrinfo *)
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalangetnameinfo (const struct sockaddr *addr, socklen_t addrsz,
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan /*@requires (maxSet(h)+1) >= hsz /\ (maxSet(s)+1) >= ssz @*/
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan /* too hard: maxRead(addr) >= (addrsz-1) */
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan /*@modifies *h, *s@*/;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalanextern /*@dependent@*/ char *gai_strerror (int code) /*@*/;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan/*@=incondefs@*/
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#if (defined (__linux__) && defined(HAVE_GETADDRINFO)) || defined (_AIX)
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan/* See comments below. */
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#if defined (__linux__) && defined(HAVE_GETADDRINFO)
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan/* Do we actually have *any* systems we care about that don't provide
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan either getaddrinfo or one of these two flavors of
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan gethostbyname_r? */
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#if !defined(HAVE_GETHOSTBYNAME_R) || defined(THREADSAFE_GETHOSTBYNAME)
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan { TMP = gethostbyname (NAME); (ERR) = h_errno; (HP) = TMP; }
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#define GET_HOST_BY_ADDR(ADDR, ADDRLEN, FAMILY, HP, ERR, TMP) \
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan { TMP = gethostbyaddr ((ADDR), (ADDRLEN), (FAMILY)); (ERR) = h_errno; (HP) = TMP; }
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#ifdef _AIX /* XXX should have a feature test! */
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalantypedef struct {
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan (HP) = (gethostbyname_r((NAME), &TMP.ent, &TMP.data) \
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#define GET_HOST_BY_ADDR(ADDR, ADDRLEN, FAMILY, HP, ERR) \
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan struct hostent my_h_ent; \
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan struct hostent_data my_h_ent_data; \
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan (HP) = (gethostbyaddr_r((ADDR), (ADDRLEN), (FAMILY), &my_h_ent, \
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan &my_h_ent_data) \
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan : &my_h_ent); \
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan (ERR) = my_h_err; \
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalantypedef struct {
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan (HP) = (((my_ret != 0) || (my_hp != &TMP.ent)) \
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#define GET_HOST_BY_ADDR(ADDR, ADDRLEN, FAMILY, HP, ERR, TMP) \
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan my_ret = gethostbyaddr_r((ADDR), (ADDRLEN), (FAMILY), &TMP.ent, \
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan (HP) = (((my_ret != 0) || (my_hp != &TMP.ent)) \
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalantypedef struct {
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#define GET_HOST_BY_ADDR(ADDR, ADDRLEN, FAMILY, HP, ERR, TMP) \
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan (HP) = gethostbyaddr_r((ADDR), (ADDRLEN), (FAMILY), &TMP.ent, \
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#endif /* returns int? */
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#endif /* _AIX */
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan/* Now do the same for getservby* functions. */
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#define GET_SERV_BY_NAME(NAME, PROTO, SP, ERR, TMP) \
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan (TMP = getservbyname (NAME, PROTO), (SP) = TMP, (ERR) = (SP) ? 0 : -1)
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#define GET_SERV_BY_PORT(PORT, PROTO, SP, ERR, TMP) \
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan (TMP = getservbyport (PORT, PROTO), (SP) = TMP, (ERR) = (SP) ? 0 : -1)
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalantypedef struct {
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#define GET_SERV_BY_NAME(NAME, PROTO, SP, ERR, TMP) \
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan (SP) = (getservbyname_r((NAME), (PROTO), &TMP.ent, \
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#define GET_SERV_BY_PORT(PORT, PROTO, SP, ERR, TMP) \
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan (SP) = (getservbyport_r((PORT), (PROTO), &TMP.ent, \
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan/* returns ptr -- IRIX? */
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalantypedef struct {
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#define GET_SERV_BY_NAME(NAME, PROTO, SP, ERR, TMP) \
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan (SP) = getservbyname_r((NAME), (PROTO), &TMP.ent, \
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#define GET_SERV_BY_PORT(PORT, PROTO, SP, ERR, TMP) \
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan my_sp = getservbyport_r((PORT), (PROTO), &TMP.ent, \
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#if defined(WRAP_GETADDRINFO) || defined(FAI_CACHE)
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalanstatic inline int
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalansystem_getaddrinfo (const char *name, const char *serv,
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalanstatic inline void
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan/* Note: Implementations written to RFC 2133 use size_t, while RFC
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan 2553 implementations use socklen_t, for the second parameter.
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan Mac OS X (10.2) and AIX 4.3.3 appear to be in the RFC 2133 camp,
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan but we don't have an autoconf test for that right now. */
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalanstatic inline int
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalansystem_getnameinfo (const struct sockaddr *sa, socklen_t salen,
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan char *host, size_t hostlen, char *serv, size_t servlen,
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan return getnameinfo(sa, salen, host, hostlen, serv, servlen, flags);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#if !defined (HAVE_GETADDRINFO) || defined(WRAP_GETADDRINFO) || defined(FAI_CACHE)
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#endif /* ! HAVE_GETADDRINFO */
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#if (!defined (HAVE_GETADDRINFO) || defined (WRAP_GETADDRINFO)) && defined(DEBUG_ADDRINFO)
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan/* Some debug routines. */
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalanstatic const char *protoname (int p, char *buf) {
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#define X(N) if (p == IPPROTO_ ## N) return #N
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalanstatic const char *socktypename (int t, char *buf) {
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan switch (t) {
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalanstatic const char *familyname (int f, char *buf) {
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan switch (f) {
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalanstatic void debug_dump_getaddrinfo_args (const char *name, const char *serv,
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan "getaddrinfo(hostname %s, service %s,\n"
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan " hints { ",
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan name ? name : "(null)", serv ? serv : "(null)");
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#define Z(FLAG) if (hint->ai_flags & AI_##FLAG) fprintf(stderr, "%s%s", sep, #FLAG), sep = "|"
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan if (sep[0] == 0)
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan fprintf(stderr, " %s", familyname(hint->ai_family, buf));
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan fprintf(stderr, " SOCK_%s", socktypename(hint->ai_socktype, buf));
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan fprintf(stderr, " IPPROTO_%s", protoname(hint->ai_protocol, buf));
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan fprintf(stderr, "error %d: %s\n", err, gai_strerror(err));
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalanstatic void debug_dump_addrinfos (const struct addrinfo *ai)
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan fprintf(stderr, " socktype=%s", socktypename(ai->ai_socktype, buf));
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan fprintf(stderr, " ai_family=%s", familyname(ai->ai_family, buf));
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan fprintf(stderr, "end addrinfos returned (%d)\n");
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#if !defined (HAVE_GETADDRINFO) || defined (WRAP_GETADDRINFO)
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalanint getaddrinfo (const char *name, const char *serv,
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan const struct addrinfo *hint, struct addrinfo **result);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#define HAVE_FAKE_GETADDRINFO /* was not originally HAVE_GETADDRINFO */
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalanint getnameinfo (const struct sockaddr *addr, socklen_t len,
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan/* Fudge things on older gai implementations. */
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan/* AIX 4.3.3 is based on RFC 2133; no AI_NUMERICHOST. */
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan/* Partial RFC 2553 implementations may not have AI_ADDRCONFIG and
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan friends, which RFC 3493 says are now part of the getaddrinfo
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan interface, and we'll want to use. */
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#if defined(HAVE_FAKE_GETADDRINFO) || defined(FAI_CACHE)
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#if defined(NEED_FAKE_GETADDRINFO) || defined(WRAP_GETADDRINFO)
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalanstatic inline int translate_h_errno (int h);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalanstatic inline int fai_add_entry (struct addrinfo **result, void *addr,
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan struct addrinfo *n = malloc (sizeof (struct addrinfo));
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan memset (sin4, 0, sizeof (struct sockaddr_in)); /* for sin_zero */
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan memset (sin6, 0, sizeof (struct sockaddr_in6)); /* for sin_zero */
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan/* fake addrinfo cache entries */
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalanstatic void plant_face (const char *name, struct face *entry)
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan /* @@ Wastes memory. */
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan entry->expiration = time(0) + CACHE_ENTRY_LIFETIME;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan printf("added cache entry '%s' at %p: %d ipv4, %d ipv6; expire %d\n",
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan name, entry, entry->naddrs4, entry->naddrs6, entry->expiration);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalanstatic int find_face (const char *name, struct face **entry)
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan /* First, scan for expired entries and free them.
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan (Future improvement: Integrate these two loops.) */
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan printf("scanning cache at %d for '%s'...\n", now, name);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan printf(" checking expiration time of @%p: %d\n",
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan /* Stay at this point in the list, and check again. */
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan /* Move forward. */
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan for (fp = krb5int_fac.data; fp; fp = fp->next) {
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalanstatic int krb5int_lock_fac(void), krb5int_unlock_fac(void);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalanstatic inline int fai_add_hosts_by_name (const char *name,
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan printf("looking up new data for '%s'...\n", name);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan /* Don't set ai_family -- we want to cache all address types,
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan because the next lookup may not use the same constraints as
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan the current one. We *could* cache them separately, so that
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan we never have to look up an IPv6 address if we are always
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan asked for IPv4 only, but let's deal with that later, if we
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan /* Try NULL for the service for now.
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan It would be nice to use the requested service name, and not
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan have to patch things up, but then we'd be doing multiple
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan queries for the same host when we get different services.
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan We were using "telnet" for a little more confidence that
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan getaddrinfo would heed the hints to only give us stream
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan socket types (with no socket type and null service name, we
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan might get stream *and* dgram *and* raw, for each address,
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan or only raw). The RFC 3493 description of ai_socktype
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan sometimes associates it with the specified service,
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan sometimes not.
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan But on Mac OS X (10.3, 10.4) they've "extended" getaddrinfo
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan to make SRV RR queries. (Please, somebody, show me
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan something in the specs that actually supports this? RFC
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan 3493 says nothing about it, but it does say getaddrinfo is
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan the new way to look up hostnames. RFC 2782 says SRV
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan records should *not* be used unless the application
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan protocol spec says to do so. The Telnet spec does not say
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan to do it.) And then they complain when our code
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan "unexpectedly" seems to use this "extension" in cases where
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan they don't want it to be used.
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan Fortunately, it appears that if we specify ai_socktype as
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan SOCK_STREAM and use a null service name, we only get one
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan copy of each address on all the platforms I've tried,
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan although it may not have ai_socktype filled in properly.
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan So, we'll fudge it with that for now. */
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan aierr = system_getaddrinfo(name, NULL, &myhints, &ai);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan printf(" found an address in family %d...\n", ai2->ai_family);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan ce->addrs4 = calloc(ce->naddrs4, sizeof(*ce->addrs4));
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan ce->addrs6 = calloc(ce->naddrs6, sizeof(*ce->addrs6));
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan for (ai2 = ai, i4 = i6 = 0; ai2; ai2 = ai2->ai_next) {
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan ce->addrs4[i4++] = ((struct sockaddr_in *)ai2->ai_addr)->sin_addr;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan ce->addrs6[i6++] = ((struct sockaddr_in6 *)ai2->ai_addr)->sin6_addr;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan ce->canonname = ai->ai_canonname ? strdup(ai->ai_canonname) : 0;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan template->ai_addrlen = sizeof(struct sockaddr_in6);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan r = fai_add_entry (result, &ce->addrs6[i], portnum, template);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan template->ai_addrlen = sizeof(struct sockaddr_in);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan r = fai_add_entry (result, &ce->addrs4[i], portnum, template);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan r = fai_add_entry (result, hp->h_addr_list[i], portnum, template);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalanstatic inline void
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalanstatic inline int
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalanfake_getaddrinfo (const char *name, const char *serv,
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan const struct addrinfo *hint, struct addrinfo **result)
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan if (hint->ai_family != 0 && hint->ai_family != AF_INET)
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan /* pure numeric */
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan if (p == 0 || p > 65535)
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan GET_SERV_BY_NAME(serv, socktype == SOCK_STREAM ? "tcp" : "udp",
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan name = (flags & AI_PASSIVE) ? "0.0.0.0" : "127.0.0.1";
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan template.ai_addrlen = sizeof (struct sockaddr_in);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan /* If NUMERICHOST is set, parse a numeric address.
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan If it's not set, don't accept such names. */
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan if (addr4.s_addr == 0xffffffff || addr4.s_addr == -1)
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan /* 255.255.255.255 or parse error, both bad */
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan ret = fai_add_entry (&res, &addr4, port, &template);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan ret = fai_add_hosts_by_name (name, &template, port, flags,
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalanstatic inline int
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalanfake_getnameinfo (const struct sockaddr *sa, socklen_t len,
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#if (defined(__GNUC__) && defined(__mips__)) || 1 /* thread safety always */
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan /* The inet_ntoa call, passing a struct, fails on IRIX 6.5
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan using gcc 2.95; we get back "0.0.0.0". Since this in a
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan configuration still important at Athena, here's the
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan workaround, which also happens to be thread-safe.... */
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan sprintf(tmpbuf, "%d.%d.%d.%d", uc[0], uc[1], uc[2], uc[3]);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan GET_HOST_BY_ADDR((const char *) &sinp->sin_addr,
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan sizeof (struct in_addr),
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan if (herr == NO_ADDRESS && !(flags & NI_NAMEREQD)) /* ??? */
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan /* According to the Open Group spec, getnameinfo can
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan silently truncate, but must still return a
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan null-terminated string. */
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#if defined(HAVE_FAKE_GETADDRINFO) || defined(NEED_FAKE_GETNAMEINFO)
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalanstatic inline
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan case EAI_ADDRFAMILY: return "address family for nodename not supported";
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan case EAI_AGAIN: return "temporary failure in name resolution";
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan case EAI_BADFLAGS: return "bad flags to getaddrinfo/getnameinfo";
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan case EAI_FAIL: return "non-recoverable failure in name resolution";
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan case EAI_FAMILY: return "ai_family not supported";
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan case EAI_NODATA: return "no address associated with hostname";
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan case EAI_SERVICE: return "service name not supported for specified socket type";
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan case EAI_SOCKTYPE: return "ai_socktype not supported";
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan default: return "bogus getaddrinfo error?";
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan switch (h) {
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#if defined(HAVE_FAKE_GETADDRINFO) || defined(FAI_CACHE)
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalanstatic inline
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalanint getaddrinfo (const char *name, const char *serv,
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan const struct addrinfo *hint, struct addrinfo **result)
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan return fake_getaddrinfo(name, serv, hint, result);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalanstatic inline
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalanstatic inline
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalanint getnameinfo (const struct sockaddr *sa, socklen_t len,
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan return fake_getnameinfo(sa, len, host, hostlen, service, servicelen,
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#endif /* NEED_FAKE_GETNAMEINFO */
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#endif /* HAVE_FAKE_GETADDRINFO */
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#endif /* NEED_FAKE_GETADDRINFO */
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalanstatic inline
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalangetaddrinfo (const char *name, const char *serv, const struct addrinfo *hint,
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#if defined(_AIX) || defined(COPY_FIRST_CANONNAME)
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan /* AIX 4.3.3 is broken. (Or perhaps out of date?)
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan If a numeric service is provided, and it doesn't correspond to
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan a known service name for tcp or udp (as appropriate), an error
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan code (for "host not found") is returned. If the port maps to a
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan known service for both udp and tcp, all is well. */
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan serv = "discard"; /* defined for both udp and tcp */
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan aierr = system_getaddrinfo (name, serv, hint, result);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan /* Linux libc version 6 (libc-2.2.4.so on Debian) is broken.
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan RFC 2553 says that when AI_CANONNAME is set, the ai_canonname
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan flag of the first returned structure has the canonical name of
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan the host. Instead, GNU libc sets ai_canonname in each returned
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan structure to the name that the corresponding address maps to,
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan if any, or a printable numeric form.
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan RFC 2553 bis and the new Open Group spec say that field will be
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan the canonical name if it can be determined, otherwise, the
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan provided hostname or a copy of it.
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan IMNSHO, "canonical name" means CNAME processing and not PTR
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan processing, but I can see arguing it. Using the numeric form
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan when that's not the form provided is just wrong. So, let's fix
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan The glibc 2.2.5 sources indicate that the canonical name is
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan *not* allocated separately, it's just some extra storage tacked
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan on the end of the addrinfo structure. So, let's try this
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan approach: If getaddrinfo sets ai_canonname, we'll replace the
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan *first* one with allocated storage, and free up that pointer in
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan freeaddrinfo if it's set; the other ai_canonname fields will be
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan left untouched. And we'll just pray that the application code
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan won't mess around with the list structure; if we start doing
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan that, we'll have to start replacing and freeing all of the
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan ai_canonname fields.
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan Ref: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=133668 .
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan Since it's dependent on the target hostname, it's hard to check
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan for at configure time. Always do it on Linux for now. When
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan they get around to fixing it, add a compile-time or run-time
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan check for the glibc version in use.
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan Some Windows documentation says that even when AI_CANONNAME is
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan set, the returned ai_canonname field can be null. The NetBSD
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan 1.5 implementation also does this, if the input hostname is a
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan numeric host address string. That case isn't handled well at
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan Libc version 5 didn't have getaddrinfo at all. */
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan * This code must *always* return an error, return a null
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan * ai_canonname, or return an ai_canonname allocated here using
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan * malloc, so that freeaddrinfo can always free a non-null
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan * ai_canonname. Note that it really doesn't matter if the
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan * AI_CANONNAME flag was set.
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan * Current versions of GET_HOST_BY_NAME will fail if the
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan * target hostname has IPv6 addresses only. Make sure it
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan * fails fairly cleanly.
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan * This case probably means it's an IPv6-only name. If
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan * ai_canonname is a numeric address, get rid of it.
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan if (ai->ai_canonname && strchr(ai->ai_canonname, ':'))
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan name2 = ai->ai_canonname ? ai->ai_canonname : name;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan /* Sometimes gethostbyname will be directed to /etc/hosts
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan first, and sometimes that file will have entries with
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan the unqualified name first. So take the first entry
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan that looks like it could be a FQDN. */
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan /* Give up, just use the first name (h_name ==
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan h_aliases[0] on all systems I've seen). */
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan /* Zap the remaining ai_canonname fields glibc fills in, in
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan case the application messes around with the list
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan structure. */
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan /* Is this check actually needed? */
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan ((struct sockaddr_in *)ai->ai_addr)->sin_port = service_port;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan ((struct sockaddr_in6 *)ai->ai_addr)->sin6_port = service_port;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan /* AIX 4.3.3 libc is broken. It doesn't set the family or len
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan fields of the sockaddr structures. Usually, sa_family is
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan zero, but I've seen it set to 1 in some cases also (maybe
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan just leftover from previous contents of the memory
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan block?). So, always override what libc returned. */
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#ifdef HAVE_SA_LEN /* always true on AIX, actually */
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan /* Not dealt with currently:
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan - Some versions of GNU libc can lose some IPv4 addresses in
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan certain cases when multiple IPv4 and IPv6 addresses are
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan available. */
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalanstatic inline
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#endif /* WRAP_GETADDRINFO */
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan/* Some systems don't define in6addr_any. */
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalanconst struct in6_addr krb5int_in6addr_any = IN6ADDR_ANY_INIT;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalanint krb5int_getaddrinfo (const char *node, const char *service,
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalanint krb5int_getnameinfo (const struct sockaddr *sa, socklen_t salen,