505d05c73a6e56769f263d4803b22eddd168ee24gtb/*
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan * Copyright (C) 2001,2002,2003,2004,2005,2006 by the Massachusetts Institute of Technology,
505d05c73a6e56769f263d4803b22eddd168ee24gtb * Cambridge, MA, USA. All Rights Reserved.
505d05c73a6e56769f263d4803b22eddd168ee24gtb *
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 *
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 *
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 *
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 *
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 *
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.
505d05c73a6e56769f263d4803b22eddd168ee24gtb */
505d05c73a6e56769f263d4803b22eddd168ee24gtb
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan/* Approach overview:
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
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
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan If no system version exists, use gethostby* and fake it. Define
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan the data structures and flag values locally.
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
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
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
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
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan We're taking a simpler approach: A system provides these routines or
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan it does not.
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
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
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan/* To do, maybe:
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
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
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan For certain (old?) versions of GNU libc, AI_NUMERICHOST is
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan defined but not implemented.
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
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 by now.
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan + inet_ntop, inet_pton
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan + Conditionally export/import the function definitions, so a
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan library can have a single copy instead of multiple.
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan + Upgrade host requirements to include working implementations of
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan these functions, and throw all this away. Pleeease? :-) */
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#include "port-sockets.h"
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#include "socket-utils.h"
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#include "k5-platform.h"
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#include "k5-thread.h"
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#include "supp-int.h"
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#include <stdio.h> /* for sprintf */
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#include <errno.h>
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#define IMPLEMENT_FAKE_GETADDRINFO
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#include "fake-addrinfo.h"
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#ifdef S_SPLINT_S
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan/*@-incondefs@*/
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalanextern int
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalangetaddrinfo (/*@in@*/ /*@null@*/ const char *,
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan /*@in@*/ /*@null@*/ const char *,
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan /*@in@*/ /*@null@*/ const struct addrinfo *,
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan /*@out@*/ struct addrinfo **)
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan ;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalanextern void
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalanfreeaddrinfo (/*@only@*/ /*@out@*/ struct addrinfo *)
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan ;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalanextern int
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalangetnameinfo (const struct sockaddr *addr, socklen_t addrsz,
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan /*@out@*/ /*@null@*/ char *h, socklen_t hsz,
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan /*@out@*/ /*@null@*/ char *s, socklen_t ssz,
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan int flags)
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#endif
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#include "cache-addrinfo.h"
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#if (defined (__linux__) && defined(HAVE_GETADDRINFO)) || defined (_AIX)
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan/* See comments below. */
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan# define WRAP_GETADDRINFO
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#endif
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#if defined (__linux__) && defined(HAVE_GETADDRINFO)
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan# define COPY_FIRST_CANONNAME
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#endif
505d05c73a6e56769f263d4803b22eddd168ee24gtb
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#ifdef _AIX
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan# define NUMERIC_SERVICE_BROKEN
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan# define COPY_FIRST_CANONNAME
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#endif
505d05c73a6e56769f263d4803b22eddd168ee24gtb
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#ifdef COPY_FIRST_CANONNAME
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan# include <string.h>
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#endif
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#ifdef NUMERIC_SERVICE_BROKEN
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan# include <ctype.h> /* isdigit */
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan# include <stdlib.h> /* strtoul */
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#endif
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
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 Phalantypedef struct hostent *GET_HOST_TMP;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#define GET_HOST_BY_NAME(NAME, HP, ERR, TMP) \
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#else
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#ifdef _AIX /* XXX should have a feature test! */
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalantypedef struct {
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan struct hostent ent;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan struct hostent_data data;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan} GET_HOST_TMP;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#define GET_HOST_BY_NAME(NAME, HP, ERR, TMP) \
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan { \
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan (HP) = (gethostbyname_r((NAME), &TMP.ent, &TMP.data) \
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan ? 0 \
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan : &TMP.ent); \
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan (ERR) = h_errno; \
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan }
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan/*
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#define GET_HOST_BY_ADDR(ADDR, ADDRLEN, FAMILY, HP, ERR) \
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan { \
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 ? 0 \
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan : &my_h_ent); \
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan (ERR) = my_h_err; \
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan }
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan*/
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#else
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#ifdef GETHOSTBYNAME_R_RETURNS_INT
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalantypedef struct {
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan struct hostent ent;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan char buf[8192];
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan} GET_HOST_TMP;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#define GET_HOST_BY_NAME(NAME, HP, ERR, TMP) \
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan { \
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan struct hostent *my_hp = NULL; \
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan int my_h_err, my_ret; \
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan my_ret = gethostbyname_r((NAME), &TMP.ent, \
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan TMP.buf, sizeof (TMP.buf), &my_hp, \
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan &my_h_err); \
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan (HP) = (((my_ret != 0) || (my_hp != &TMP.ent)) \
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan ? 0 \
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan : &TMP.ent); \
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan (ERR) = my_h_err; \
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan }
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#define GET_HOST_BY_ADDR(ADDR, ADDRLEN, FAMILY, HP, ERR, TMP) \
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan { \
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan struct hostent *my_hp; \
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan int my_h_err, my_ret; \
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan my_ret = gethostbyaddr_r((ADDR), (ADDRLEN), (FAMILY), &TMP.ent, \
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan TMP.buf, sizeof (TMP.buf), &my_hp, \
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan &my_h_err); \
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan (HP) = (((my_ret != 0) || (my_hp != &TMP.ent)) \
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan ? 0 \
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan : &TMP.ent); \
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan (ERR) = my_h_err; \
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan }
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#else
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalantypedef struct {
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan struct hostent ent;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan char buf[8192];
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan} GET_HOST_TMP;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#define GET_HOST_BY_NAME(NAME, HP, ERR, TMP) \
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan { \
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan int my_h_err; \
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan (HP) = gethostbyname_r((NAME), &TMP.ent, \
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan TMP.buf, sizeof (TMP.buf), &my_h_err); \
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan (ERR) = my_h_err; \
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan }
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#define GET_HOST_BY_ADDR(ADDR, ADDRLEN, FAMILY, HP, ERR, TMP) \
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan { \
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan int my_h_err; \
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan (HP) = gethostbyaddr_r((ADDR), (ADDRLEN), (FAMILY), &TMP.ent, \
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan TMP.buf, sizeof (TMP.buf), &my_h_err); \
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan (ERR) = my_h_err; \
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan }
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#endif /* returns int? */
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#endif /* _AIX */
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#endif
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan/* Now do the same for getservby* functions. */
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#ifndef HAVE_GETSERVBYNAME_R
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalantypedef struct servent *GET_SERV_TMP;
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 Phalan#else
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#ifdef GETSERVBYNAME_R_RETURNS_INT
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalantypedef struct {
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan struct servent ent;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan char buf[8192];
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan} GET_SERV_TMP;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#define GET_SERV_BY_NAME(NAME, PROTO, SP, ERR, TMP) \
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan { \
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan struct servent *my_sp; \
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan int my_s_err; \
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan (SP) = (getservbyname_r((NAME), (PROTO), &TMP.ent, \
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan TMP.buf, sizeof (TMP.buf), &my_sp, \
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan &my_s_err) \
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan ? 0 \
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan : &TMP.ent); \
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan (ERR) = my_s_err; \
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan }
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#define GET_SERV_BY_PORT(PORT, PROTO, SP, ERR, TMP) \
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan { \
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan struct servent *my_sp; \
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan int my_s_err; \
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan (SP) = (getservbyport_r((PORT), (PROTO), &TMP.ent, \
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan TMP.buf, sizeof (TMP.buf), &my_sp, \
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan &my_s_err) \
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan ? 0 \
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan : &TMP.ent); \
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan (ERR) = my_s_err; \
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan }
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#else
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan/* returns ptr -- IRIX? */
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalantypedef struct {
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan struct servent ent;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan char buf[8192];
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan} GET_SERV_TMP;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#define GET_SERV_BY_NAME(NAME, PROTO, SP, ERR, TMP) \
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan { \
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan (SP) = getservbyname_r((NAME), (PROTO), &TMP.ent, \
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan TMP.buf, sizeof (TMP.buf)); \
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan (ERR) = (SP) == NULL; \
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan }
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#define GET_SERV_BY_PORT(PORT, PROTO, SP, ERR, TMP) \
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan { \
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan struct servent *my_sp; \
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan my_sp = getservbyport_r((PORT), (PROTO), &TMP.ent, \
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan TMP.buf, sizeof (TMP.buf)); \
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan (SP) = my_sp; \
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan (ERR) = my_sp == 0; \
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan (ERR) = (ERR); /* avoid "unused" warning */ \
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan }
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#endif
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#endif
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#if defined(WRAP_GETADDRINFO) || defined(FAI_CACHE)
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalanstatic inline int
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalansystem_getaddrinfo (const char *name, const char *serv,
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan const struct addrinfo *hint,
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan struct addrinfo **res)
505d05c73a6e56769f263d4803b22eddd168ee24gtb{
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan return getaddrinfo(name, serv, hint, res);
505d05c73a6e56769f263d4803b22eddd168ee24gtb}
505d05c73a6e56769f263d4803b22eddd168ee24gtb
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalanstatic inline void
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalansystem_freeaddrinfo (struct addrinfo *ai)
505d05c73a6e56769f263d4803b22eddd168ee24gtb{
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan freeaddrinfo(ai);
505d05c73a6e56769f263d4803b22eddd168ee24gtb}
505d05c73a6e56769f263d4803b22eddd168ee24gtb
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
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 int flags)
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan{
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan return getnameinfo(sa, salen, host, hostlen, serv, servlen, flags);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan}
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#endif
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#if !defined (HAVE_GETADDRINFO) || defined(WRAP_GETADDRINFO) || defined(FAI_CACHE)
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#undef getaddrinfo
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#define getaddrinfo my_fake_getaddrinfo
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#undef freeaddrinfo
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#define freeaddrinfo my_fake_freeaddrinfo
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#endif
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#if !defined (HAVE_GETADDRINFO)
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#undef gai_strerror
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#define gai_strerror my_fake_gai_strerror
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#endif /* ! HAVE_GETADDRINFO */
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#if (!defined (HAVE_GETADDRINFO) || defined (WRAP_GETADDRINFO)) && defined(DEBUG_ADDRINFO)
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan/* Some debug routines. */
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalanstatic const char *protoname (int p, char *buf) {
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#define X(N) if (p == IPPROTO_ ## N) return #N
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan X(TCP);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan X(UDP);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan X(ICMP);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan X(IPV6);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#ifdef IPPROTO_GRE
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan X(GRE);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#endif
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan X(NONE);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan X(RAW);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#ifdef IPPROTO_COMP
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan X(COMP);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#endif
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#ifdef IPPROTO_IGMP
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan X(IGMP);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#endif
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan sprintf(buf, " %-2d", p);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan return buf;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan}
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalanstatic const char *socktypename (int t, char *buf) {
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan switch (t) {
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan case SOCK_DGRAM: return "DGRAM";
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan case SOCK_STREAM: return "STREAM";
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan case SOCK_RAW: return "RAW";
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan case SOCK_RDM: return "RDM";
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan case SOCK_SEQPACKET: return "SEQPACKET";
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan }
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan sprintf(buf, " %-2d", t);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan return buf;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan}
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalanstatic const char *familyname (int f, char *buf) {
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan switch (f) {
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan default:
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan sprintf(buf, "AF %d", f);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan return buf;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan case AF_INET: return "AF_INET";
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan case AF_INET6: return "AF_INET6";
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#ifdef AF_UNIX
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan case AF_UNIX: return "AF_UNIX";
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#endif
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan }
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan}
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalanstatic void debug_dump_getaddrinfo_args (const char *name, const char *serv,
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan const struct addrinfo *hint)
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan{
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan const char *sep;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan fprintf(stderr,
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan "getaddrinfo(hostname %s, service %s,\n"
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan " hints { ",
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan name ? name : "(null)", serv ? serv : "(null)");
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan if (hint) {
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan char buf[30];
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan sep = "";
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#define Z(FLAG) if (hint->ai_flags & AI_##FLAG) fprintf(stderr, "%s%s", sep, #FLAG), sep = "|"
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan Z(CANONNAME);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan Z(PASSIVE);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#ifdef AI_NUMERICHOST
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan Z(NUMERICHOST);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#endif
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan if (sep[0] == 0)
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan fprintf(stderr, "no-flags");
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan if (hint->ai_family)
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan fprintf(stderr, " %s", familyname(hint->ai_family, buf));
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan if (hint->ai_socktype)
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan fprintf(stderr, " SOCK_%s", socktypename(hint->ai_socktype, buf));
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan if (hint->ai_protocol)
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan fprintf(stderr, " IPPROTO_%s", protoname(hint->ai_protocol, buf));
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan } else
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan fprintf(stderr, "(null)");
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan fprintf(stderr, " }):\n");
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan}
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalanstatic void debug_dump_error (int err)
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan{
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan fprintf(stderr, "error %d: %s\n", err, gai_strerror(err));
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan}
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalanstatic void debug_dump_addrinfos (const struct addrinfo *ai)
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan{
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan int count = 0;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan char buf[10];
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan fprintf(stderr, "addrinfos returned:\n");
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan while (ai) {
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan fprintf(stderr, "%p...", 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 if (ai->ai_family != ai->ai_addr->sa_family)
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan fprintf(stderr, " sa_family=%s",
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan familyname(ai->ai_addr->sa_family, buf));
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan fprintf(stderr, "\n");
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan ai = ai->ai_next;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan count++;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan }
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan fprintf(stderr, "end addrinfos returned (%d)\n");
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan}
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#endif
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#if !defined (HAVE_GETADDRINFO) || defined (WRAP_GETADDRINFO)
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalanstatic
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalanint getaddrinfo (const char *name, const char *serv,
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan const struct addrinfo *hint, struct addrinfo **result);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalanstatic
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalanvoid freeaddrinfo (struct addrinfo *ai);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#endif
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#if !defined (HAVE_GETADDRINFO)
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#define HAVE_FAKE_GETADDRINFO /* was not originally HAVE_GETADDRINFO */
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#define HAVE_GETADDRINFO
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#define NEED_FAKE_GETNAMEINFO
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#undef HAVE_GETNAMEINFO
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#define HAVE_GETNAMEINFO 1
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#undef getnameinfo
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#define getnameinfo my_fake_getnameinfo
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalanstatic
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalanchar *gai_strerror (int code);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#endif
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#if !defined (HAVE_GETADDRINFO)
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalanstatic
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalanint getnameinfo (const struct sockaddr *addr, socklen_t len,
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan char *host, socklen_t hostlen,
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan char *service, socklen_t servicelen,
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan int flags);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#endif
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan/* Fudge things on older gai implementations. */
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan/* AIX 4.3.3 is based on RFC 2133; no AI_NUMERICHOST. */
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#ifndef AI_NUMERICHOST
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan# define AI_NUMERICHOST 0
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#endif
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#ifndef AI_ADDRCONFIG
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan# define AI_ADDRCONFIG 0
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#endif
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#ifndef AI_V4MAPPED
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan# define AI_V4MAPPED 0
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#endif
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#ifndef AI_ALL
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan# define AI_ALL 0
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#endif
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#ifndef AI_DEFAULT
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan# define AI_DEFAULT (AI_ADDRCONFIG|AI_V4MAPPED)
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#endif
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#if defined(HAVE_FAKE_GETADDRINFO) || defined(FAI_CACHE)
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#define NEED_FAKE_GETADDRINFO
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#endif
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#if defined(NEED_FAKE_GETADDRINFO) || defined(WRAP_GETADDRINFO)
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#include <stdlib.h>
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#endif
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#ifdef NEED_FAKE_GETADDRINFO
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#include <string.h> /* for strspn */
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalanstatic inline int translate_h_errno (int h);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalanstatic inline int fai_add_entry (struct addrinfo **result, void *addr,
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan int port, const struct addrinfo *template)
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan{
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan struct addrinfo *n = malloc (sizeof (struct addrinfo));
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan if (n == 0)
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan return EAI_MEMORY;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan if (template->ai_family != AF_INET
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#ifdef KRB5_USE_INET6
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan && template->ai_family != AF_INET6
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#endif
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan )
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan return EAI_FAMILY;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan *n = *template;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan if (template->ai_family == AF_INET) {
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan struct sockaddr_in *sin4;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan sin4 = malloc (sizeof (struct sockaddr_in));
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan if (sin4 == 0)
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan return EAI_MEMORY;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan memset (sin4, 0, sizeof (struct sockaddr_in)); /* for sin_zero */
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan n->ai_addr = (struct sockaddr *) sin4;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan sin4->sin_family = AF_INET;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan sin4->sin_addr = *(struct in_addr *)addr;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan sin4->sin_port = port;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#ifdef HAVE_SA_LEN
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan sin4->sin_len = sizeof (struct sockaddr_in);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#endif
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan }
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#ifdef KRB5_USE_INET6
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan if (template->ai_family == AF_INET6) {
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan struct sockaddr_in6 *sin6;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan sin6 = malloc (sizeof (struct sockaddr_in6));
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan if (sin6 == 0)
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan return EAI_MEMORY;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan memset (sin6, 0, sizeof (struct sockaddr_in6)); /* for sin_zero */
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan n->ai_addr = (struct sockaddr *) sin6;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan sin6->sin6_family = AF_INET6;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan sin6->sin6_addr = *(struct in6_addr *)addr;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan sin6->sin6_port = port;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#ifdef HAVE_SA_LEN
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan sin6->sin6_len = sizeof (struct sockaddr_in6);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#endif
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan }
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#endif
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan n->ai_next = *result;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan *result = n;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan return 0;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan}
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#ifdef FAI_CACHE
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan/* fake addrinfo cache entries */
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#define CACHE_ENTRY_LIFETIME 15 /* seconds */
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalanstatic void plant_face (const char *name, struct face *entry)
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan{
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan entry->name = strdup(name);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan if (entry->name == NULL)
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan /* @@ Wastes memory. */
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan return;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan k5_mutex_assert_locked(&krb5int_fac.lock);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan entry->next = krb5int_fac.data;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan entry->expiration = time(0) + CACHE_ENTRY_LIFETIME;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan krb5int_fac.data = entry;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#ifdef DEBUG_ADDRINFO
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 Phalan#endif
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan}
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalanstatic int find_face (const char *name, struct face **entry)
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan{
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan struct face *fp, **fpp;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan time_t now = time(0);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan /* First, scan for expired entries and free them.
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan (Future improvement: Integrate these two loops.) */
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#ifdef DEBUG_ADDRINFO
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan printf("scanning cache at %d for '%s'...\n", now, name);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#endif
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan k5_mutex_assert_locked(&krb5int_fac.lock);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan for (fpp = &krb5int_fac.data; *fpp; ) {
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan fp = *fpp;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#ifdef DEBUG_ADDRINFO
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan printf(" checking expiration time of @%p: %d\n",
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan fp, fp->expiration);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#endif
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan if (fp->expiration < now) {
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#ifdef DEBUG_ADDRINFO
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan printf("\texpiring cache entry\n");
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#endif
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan free(fp->name);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan free(fp->canonname);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan free(fp->addrs4);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan free(fp->addrs6);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan *fpp = fp->next;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan free(fp);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan /* Stay at this point in the list, and check again. */
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan } else
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan /* Move forward. */
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan fpp = &(*fpp)->next;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan }
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan for (fp = krb5int_fac.data; fp; fp = fp->next) {
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#ifdef DEBUG_ADDRINFO
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan printf(" comparing entry @%p\n", fp);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#endif
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan if (!strcasecmp(fp->name, name)) {
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#ifdef DEBUG_ADDRINFO
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan printf("\tMATCH!\n");
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#endif
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan *entry = fp;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan return 1;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan }
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan }
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan return 0;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan}
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#endif
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalanstatic int krb5int_lock_fac(void), krb5int_unlock_fac(void);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalanstatic inline int fai_add_hosts_by_name (const char *name,
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan struct addrinfo *template,
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan int portnum, int flags,
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan struct addrinfo **result)
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan{
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#ifdef FAI_CACHE
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan struct face *ce;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan int i, r, err;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan err = krb5int_lock_fac();
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan if (err) {
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan errno = err;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan return EAI_SYSTEM;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan }
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan if (!find_face(name, &ce)) {
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan struct addrinfo myhints = { 0 }, *ai, *ai2;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan int i4, i6, aierr;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#ifdef DEBUG_ADDRINFO
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan printf("looking up new data for '%s'...\n", name);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#endif
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan myhints.ai_socktype = SOCK_STREAM;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan myhints.ai_flags = AI_CANONNAME;
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 have to. */
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan /* Try NULL for the service for now.
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
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
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
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 if (aierr) {
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan krb5int_unlock_fac();
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan return aierr;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan }
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan ce = malloc(sizeof(struct face));
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan memset(ce, 0, sizeof(*ce));
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan ce->expiration = time(0) + 30;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan for (ai2 = ai; ai2; ai2 = ai2->ai_next) {
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#ifdef DEBUG_ADDRINFO
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan printf(" found an address in family %d...\n", ai2->ai_family);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#endif
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan switch (ai2->ai_family) {
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan case AF_INET:
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan ce->naddrs4++;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan break;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan case AF_INET6:
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan ce->naddrs6++;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan break;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan default:
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan break;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan }
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan }
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan ce->addrs4 = calloc(ce->naddrs4, sizeof(*ce->addrs4));
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan if (ce->addrs4 == NULL && ce->naddrs4 != 0) {
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan krb5int_unlock_fac();
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan system_freeaddrinfo(ai);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan return EAI_MEMORY;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan }
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan ce->addrs6 = calloc(ce->naddrs6, sizeof(*ce->addrs6));
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan if (ce->addrs6 == NULL && ce->naddrs6 != 0) {
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan krb5int_unlock_fac();
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan free(ce->addrs4);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan system_freeaddrinfo(ai);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan return EAI_MEMORY;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan }
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan for (ai2 = ai, i4 = i6 = 0; ai2; ai2 = ai2->ai_next) {
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan switch (ai2->ai_family) {
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan case AF_INET:
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan ce->addrs4[i4++] = ((struct sockaddr_in *)ai2->ai_addr)->sin_addr;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan break;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan case AF_INET6:
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan ce->addrs6[i6++] = ((struct sockaddr_in6 *)ai2->ai_addr)->sin6_addr;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan break;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan default:
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan break;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan }
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan }
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan ce->canonname = ai->ai_canonname ? strdup(ai->ai_canonname) : 0;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan system_freeaddrinfo(ai);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan plant_face(name, ce);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan }
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan template->ai_family = AF_INET6;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan template->ai_addrlen = sizeof(struct sockaddr_in6);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan for (i = 0; i < ce->naddrs6; i++) {
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan r = fai_add_entry (result, &ce->addrs6[i], portnum, template);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan if (r) {
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan krb5int_unlock_fac();
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan return r;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan }
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan }
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan template->ai_family = AF_INET;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan template->ai_addrlen = sizeof(struct sockaddr_in);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan for (i = 0; i < ce->naddrs4; i++) {
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan r = fai_add_entry (result, &ce->addrs4[i], portnum, template);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan if (r) {
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan krb5int_unlock_fac();
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan return r;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan }
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan }
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan if (*result && (flags & AI_CANONNAME))
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan (*result)->ai_canonname = (ce->canonname
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan ? strdup(ce->canonname)
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan : NULL);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan krb5int_unlock_fac();
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan return 0;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#else
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan struct hostent *hp;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan int i, r;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan int herr;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan GET_HOST_TMP htmp;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan GET_HOST_BY_NAME (name, hp, herr, htmp);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan if (hp == 0)
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan return translate_h_errno (herr);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan for (i = 0; hp->h_addr_list[i]; i++) {
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan r = fai_add_entry (result, hp->h_addr_list[i], portnum, template);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan if (r)
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan return r;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan }
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan if (*result && (flags & AI_CANONNAME))
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan (*result)->ai_canonname = strdup (hp->h_name);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan return 0;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#endif
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan}
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalanstatic inline void
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalanfake_freeaddrinfo (struct addrinfo *ai)
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan{
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan struct addrinfo *next;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan while (ai) {
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan next = ai->ai_next;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan if (ai->ai_canonname)
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan free (ai->ai_canonname);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan if (ai->ai_addr)
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan free (ai->ai_addr);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan free (ai);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan ai = next;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan }
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan}
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalanstatic inline int
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalanfake_getaddrinfo (const char *name, const char *serv,
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan const struct addrinfo *hint, struct addrinfo **result)
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan{
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan struct addrinfo *res = 0;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan int ret;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan int port = 0, socktype;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan int flags;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan struct addrinfo template;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#ifdef DEBUG_ADDRINFO
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan debug_dump_getaddrinfo_args(name, serv, hint);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#endif
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan if (hint != 0) {
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan if (hint->ai_family != 0 && hint->ai_family != AF_INET)
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan return EAI_NODATA;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan socktype = hint->ai_socktype;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan flags = hint->ai_flags;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan } else {
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan socktype = 0;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan flags = 0;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan }
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan if (serv) {
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan size_t numlen = strspn (serv, "0123456789");
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan if (serv[numlen] == '\0') {
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan /* pure numeric */
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan unsigned long p = strtoul (serv, 0, 10);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan if (p == 0 || p > 65535)
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan return EAI_NONAME;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan port = htons (p);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan } else {
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan struct servent *sp;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan int try_dgram_too = 0, s_err;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan GET_SERV_TMP stmp;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan if (socktype == 0) {
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan try_dgram_too = 1;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan socktype = SOCK_STREAM;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan }
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan try_service_lookup:
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan GET_SERV_BY_NAME(serv, socktype == SOCK_STREAM ? "tcp" : "udp",
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan sp, s_err, stmp);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan if (sp == 0) {
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan if (try_dgram_too) {
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan socktype = SOCK_DGRAM;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan goto try_service_lookup;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan }
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan return EAI_SERVICE;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan }
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan port = sp->s_port;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan }
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan }
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan if (name == 0) {
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan name = (flags & AI_PASSIVE) ? "0.0.0.0" : "127.0.0.1";
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan flags |= AI_NUMERICHOST;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan }
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan template.ai_family = AF_INET;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan template.ai_addrlen = sizeof (struct sockaddr_in);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan template.ai_socktype = socktype;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan template.ai_protocol = 0;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan template.ai_flags = 0;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan template.ai_canonname = 0;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan template.ai_next = 0;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan template.ai_addr = 0;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
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 (flags & AI_NUMERICHOST) {
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan struct in_addr addr4;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#if 0
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan ret = inet_aton (name, &addr4);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan if (ret)
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan return EAI_NONAME;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#else
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan addr4.s_addr = inet_addr (name);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan if (addr4.s_addr == 0xffffffff || addr4.s_addr == -1)
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan /* 255.255.255.255 or parse error, both bad */
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan return EAI_NONAME;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#endif
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan ret = fai_add_entry (&res, &addr4, port, &template);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan } else {
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan ret = fai_add_hosts_by_name (name, &template, port, flags,
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan &res);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan }
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan if (ret && ret != NO_ADDRESS) {
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan fake_freeaddrinfo (res);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan return ret;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan }
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan if (res == 0)
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan return NO_ADDRESS;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan *result = res;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan return 0;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan}
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#ifdef NEED_FAKE_GETNAMEINFO
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalanstatic inline int
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalanfake_getnameinfo (const struct sockaddr *sa, socklen_t len,
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan char *host, socklen_t hostlen,
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan char *service, socklen_t servicelen,
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan int flags)
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan{
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan struct hostent *hp;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan const struct sockaddr_in *sinp;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan struct servent *sp;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan size_t hlen, slen;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan if (sa->sa_family != AF_INET) {
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan return EAI_FAMILY;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan }
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan sinp = (const struct sockaddr_in *) sa;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan hlen = hostlen;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan if (hostlen < 0 || hlen != hostlen) {
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan errno = EINVAL;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan return EAI_SYSTEM;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan }
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan slen = servicelen;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan if (servicelen < 0 || slen != servicelen) {
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan errno = EINVAL;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan return EAI_SYSTEM;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan }
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan if (host) {
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan if (flags & NI_NUMERICHOST) {
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 const unsigned char *uc;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan char tmpbuf[20];
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan numeric_host:
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan uc = (const unsigned char *) &sinp->sin_addr;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan sprintf(tmpbuf, "%d.%d.%d.%d", uc[0], uc[1], uc[2], uc[3]);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan strncpy(host, tmpbuf, hlen);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#else
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan char *p;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan numeric_host:
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan p = inet_ntoa (sinp->sin_addr);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan strncpy (host, p, hlen);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#endif
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan } else {
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan int herr;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan GET_HOST_TMP htmp;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan GET_HOST_BY_ADDR((const char *) &sinp->sin_addr,
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan sizeof (struct in_addr),
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan sa->sa_family, hp, herr, htmp);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan if (hp == 0) {
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan if (herr == NO_ADDRESS && !(flags & NI_NAMEREQD)) /* ??? */
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan goto numeric_host;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan return translate_h_errno (herr);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan }
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 strncpy (host, hp->h_name, hlen);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan }
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan host[hostlen-1] = 0;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan }
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan if (service) {
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan if (flags & NI_NUMERICSERV) {
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan char numbuf[10];
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan int port;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan numeric_service:
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan port = ntohs (sinp->sin_port);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan if (port < 0 || port > 65535)
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan return EAI_FAIL;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan sprintf (numbuf, "%d", port);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan strncpy (service, numbuf, slen);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan } else {
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan int serr;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan GET_SERV_TMP stmp;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan GET_SERV_BY_PORT(sinp->sin_port,
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan (flags & NI_DGRAM) ? "udp" : "tcp",
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan sp, serr, stmp);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan if (sp == 0)
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan goto numeric_service;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan strncpy (service, sp->s_name, slen);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan }
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan service[servicelen-1] = 0;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan }
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan return 0;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan}
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#endif
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#if defined(HAVE_FAKE_GETADDRINFO) || defined(NEED_FAKE_GETNAMEINFO)
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalanstatic inline
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalanchar *gai_strerror (int code)
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan{
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan switch (code) {
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_MEMORY: return "out of memory";
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan case EAI_NODATA: return "no address associated with hostname";
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan case EAI_NONAME: return "name does not exist";
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 case EAI_SYSTEM: return strerror (errno);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan default: return "bogus getaddrinfo error?";
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan }
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan}
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#endif
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalanstatic inline int translate_h_errno (int h)
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan{
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan switch (h) {
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan case 0:
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan return 0;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#ifdef NETDB_INTERNAL
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan case NETDB_INTERNAL:
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan if (errno == ENOMEM)
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan return EAI_MEMORY;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan return EAI_SYSTEM;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#endif
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan case HOST_NOT_FOUND:
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan return EAI_NONAME;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan case TRY_AGAIN:
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan return EAI_AGAIN;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan case NO_RECOVERY:
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan return EAI_FAIL;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan case NO_DATA:
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#if NO_DATA != NO_ADDRESS
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan case NO_ADDRESS:
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#endif
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan return EAI_NODATA;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan default:
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan return EAI_SYSTEM;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan }
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan}
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
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{
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan return fake_getaddrinfo(name, serv, hint, result);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan}
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalanstatic inline
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalanvoid freeaddrinfo (struct addrinfo *ai)
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan{
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan fake_freeaddrinfo(ai);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan}
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#ifdef NEED_FAKE_GETNAMEINFO
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalanstatic inline
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalanint getnameinfo (const struct sockaddr *sa, socklen_t len,
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan char *host, socklen_t hostlen,
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan char *service, socklen_t servicelen,
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan int flags)
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan{
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan return fake_getnameinfo(sa, len, host, hostlen, service, servicelen,
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan flags);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan}
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#endif /* NEED_FAKE_GETNAMEINFO */
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#endif /* HAVE_FAKE_GETADDRINFO */
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#endif /* NEED_FAKE_GETADDRINFO */
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#ifdef WRAP_GETADDRINFO
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalanstatic inline
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalanint
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalangetaddrinfo (const char *name, const char *serv, const struct addrinfo *hint,
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan struct addrinfo **result)
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan{
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan int aierr;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#if defined(_AIX) || defined(COPY_FIRST_CANONNAME)
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan struct addrinfo *ai;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#endif
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#ifdef NUMERIC_SERVICE_BROKEN
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan int service_is_numeric = 0;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan int service_port = 0;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan int socket_type = 0;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#endif
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#ifdef DEBUG_ADDRINFO
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan debug_dump_getaddrinfo_args(name, serv, hint);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#endif
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#ifdef NUMERIC_SERVICE_BROKEN
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan /* AIX 4.3.3 is broken. (Or perhaps out of date?)
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
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 if (serv && serv[0] && isdigit(serv[0])) {
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan unsigned long lport;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan char *end;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan lport = strtoul(serv, &end, 10);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan if (!*end) {
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan if (lport > 65535)
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan return EAI_SOCKTYPE;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan service_is_numeric = 1;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan service_port = htons(lport);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#ifdef AI_NUMERICSERV
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan if (hint && hint->ai_flags & AI_NUMERICSERV)
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan serv = "9";
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan else
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#endif
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan serv = "discard"; /* defined for both udp and tcp */
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan if (hint)
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan socket_type = hint->ai_socktype;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan }
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan }
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#endif
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan aierr = system_getaddrinfo (name, serv, hint, result);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan if (aierr || *result == 0) {
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#ifdef DEBUG_ADDRINFO
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan debug_dump_error(aierr);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#endif
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan return aierr;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan }
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan /* Linux libc version 6 (libc-2.2.4.so on Debian) is broken.
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
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
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
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 it.
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
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
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan Ref: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=133668 .
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
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
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 the moment.
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan Libc version 5 didn't have getaddrinfo at all. */
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#ifdef COPY_FIRST_CANONNAME
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan /*
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 */
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan ai = *result;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan if (ai->ai_canonname) {
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan struct hostent *hp;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan const char *name2 = 0;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan int i, herr;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan GET_HOST_TMP htmp;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan /*
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 */
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan GET_HOST_BY_NAME (name, hp, herr, htmp);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan if (hp == 0) {
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan /*
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 */
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan if (ai->ai_canonname && strchr(ai->ai_canonname, ':'))
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan ai->ai_canonname = 0;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan name2 = ai->ai_canonname ? ai->ai_canonname : name;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan } else {
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 for (i = 0; hp->h_aliases[i]; i++) {
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan if (strchr(hp->h_aliases[i], '.') != 0) {
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan name2 = hp->h_aliases[i];
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan break;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan }
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan }
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan /* Give up, just use the first name (h_name ==
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan h_aliases[0] on all systems I've seen). */
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan if (hp->h_aliases[i] == 0)
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan name2 = hp->h_name;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan }
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan ai->ai_canonname = strdup(name2);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan if (name2 != 0 && ai->ai_canonname == 0) {
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan system_freeaddrinfo(ai);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan *result = 0;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#ifdef DEBUG_ADDRINFO
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan debug_dump_error(EAI_MEMORY);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#endif
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan return EAI_MEMORY;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan }
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 while ((ai = ai->ai_next) != NULL)
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan ai->ai_canonname = 0;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan }
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#endif
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#ifdef NUMERIC_SERVICE_BROKEN
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan if (service_port != 0) {
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan for (ai = *result; ai; ai = ai->ai_next) {
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan if (socket_type != 0 && ai->ai_socktype == 0)
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan /* Is this check actually needed? */
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan ai->ai_socktype = socket_type;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan switch (ai->ai_family) {
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan case AF_INET:
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan ((struct sockaddr_in *)ai->ai_addr)->sin_port = service_port;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan break;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan case AF_INET6:
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan ((struct sockaddr_in6 *)ai->ai_addr)->sin6_port = service_port;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan break;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan }
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan }
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan }
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#endif
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#ifdef _AIX
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan for (ai = *result; ai; ai = ai->ai_next) {
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 ai->ai_addr->sa_family = ai->ai_family;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#ifdef HAVE_SA_LEN /* always true on AIX, actually */
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan ai->ai_addr->sa_len = ai->ai_addrlen;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#endif
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan }
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#endif
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan /* Not dealt with currently:
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
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 Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#ifdef DEBUG_ADDRINFO
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan debug_dump_addrinfos(*result);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#endif
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan return 0;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan}
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalanstatic inline
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalanvoid freeaddrinfo (struct addrinfo *ai)
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan{
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#ifdef COPY_FIRST_CANONNAME
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan if (ai) {
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan free(ai->ai_canonname);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan ai->ai_canonname = 0;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan system_freeaddrinfo(ai);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan }
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#else
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan system_freeaddrinfo(ai);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#endif
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan}
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan#endif /* WRAP_GETADDRINFO */
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalanstatic int krb5int_lock_fac (void)
505d05c73a6e56769f263d4803b22eddd168ee24gtb{
505d05c73a6e56769f263d4803b22eddd168ee24gtb int err;
505d05c73a6e56769f263d4803b22eddd168ee24gtb err = krb5int_call_thread_support_init();
505d05c73a6e56769f263d4803b22eddd168ee24gtb if (err)
505d05c73a6e56769f263d4803b22eddd168ee24gtb return err;
505d05c73a6e56769f263d4803b22eddd168ee24gtb return k5_mutex_lock(&krb5int_fac.lock);
505d05c73a6e56769f263d4803b22eddd168ee24gtb}
505d05c73a6e56769f263d4803b22eddd168ee24gtb
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalanstatic int krb5int_unlock_fac (void)
505d05c73a6e56769f263d4803b22eddd168ee24gtb{
505d05c73a6e56769f263d4803b22eddd168ee24gtb return k5_mutex_unlock(&krb5int_fac.lock);
505d05c73a6e56769f263d4803b22eddd168ee24gtb}
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan/* Some systems don't define in6addr_any. */
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalanconst struct in6_addr krb5int_in6addr_any = IN6ADDR_ANY_INIT;
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalanint krb5int_getaddrinfo (const char *node, const char *service,
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan const struct addrinfo *hints,
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan struct addrinfo **aip)
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan{
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan return getaddrinfo(node, service, hints, aip);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan}
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalanvoid krb5int_freeaddrinfo (struct addrinfo *ai)
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan{
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan freeaddrinfo(ai);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan}
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalanconst char *krb5int_gai_strerror(int err)
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan{
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan return gai_strerror(err);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan}
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalanint krb5int_getnameinfo (const struct sockaddr *sa, socklen_t salen,
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan char *hbuf, size_t hbuflen,
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan char *sbuf, size_t sbuflen,
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan int flags)
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan{
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan return getnameinfo(sa, salen, hbuf, hbuflen, sbuf, sbuflen, flags);
159d09a20817016f09b3ea28d1bdada4a336bb91Mark Phalan}