1N/A/*
1N/A * Copyright (c) 1999-2001, 2004, 2010 Sendmail, Inc. and its suppliers.
1N/A * All rights reserved.
1N/A *
1N/A * By using this file, you agree to the terms and conditions set
1N/A * forth in the LICENSE file which can be found at the top level of
1N/A * the sendmail distribution.
1N/A *
1N/A */
1N/A
1N/A#include <sm/gen.h>
1N/ASM_RCSID("@(#)$Id: sm_gethost.c,v 8.29 2010/07/27 01:09:31 ca Exp $")
1N/A
1N/A#include <sendmail.h>
1N/A#if NETINET || NETINET6
1N/A# include <arpa/inet.h>
1N/A#endif /* NETINET || NETINET6 */
1N/A#include "libmilter.h"
1N/A
1N/A/*
1N/A** MI_GETHOSTBY{NAME,ADDR} -- compatibility routines for gethostbyXXX
1N/A**
1N/A** Some operating systems have wierd problems with the gethostbyXXX
1N/A** routines. For example, Solaris versions at least through 2.3
1N/A** don't properly deliver a canonical h_name field. This tries to
1N/A** work around these problems.
1N/A**
1N/A** Support IPv6 as well as IPv4.
1N/A*/
1N/A
1N/A#if NETINET6 && NEEDSGETIPNODE
1N/A
1N/Astatic struct hostent *sm_getipnodebyname __P((const char *, int, int, int *));
1N/A
1N/A# ifndef AI_ADDRCONFIG
1N/A# define AI_ADDRCONFIG 0 /* dummy */
1N/A# endif /* ! AI_ADDRCONFIG */
1N/A# ifndef AI_ALL
1N/A# define AI_ALL 0 /* dummy */
1N/A# endif /* ! AI_ALL */
1N/A# ifndef AI_DEFAULT
1N/A# define AI_DEFAULT 0 /* dummy */
1N/A# endif /* ! AI_DEFAULT */
1N/A
1N/Astatic struct hostent *
1N/Asm_getipnodebyname(name, family, flags, err)
1N/A const char *name;
1N/A int family;
1N/A int flags;
1N/A int *err;
1N/A{
1N/A bool resv6 = true;
1N/A struct hostent *h;
1N/A
1N/A if (family == AF_INET6)
1N/A {
1N/A /* From RFC2133, section 6.1 */
1N/A resv6 = bitset(RES_USE_INET6, _res.options);
1N/A _res.options |= RES_USE_INET6;
1N/A }
1N/A SM_SET_H_ERRNO(0);
1N/A h = gethostbyname(name);
1N/A if (family == AF_INET6 && !resv6)
1N/A _res.options &= ~RES_USE_INET6;
1N/A *err = h_errno;
1N/A return h;
1N/A}
1N/A
1N/Avoid
1N/Afreehostent(h)
1N/A struct hostent *h;
1N/A{
1N/A /*
1N/A ** Stub routine -- if they don't have getipnodeby*(),
1N/A ** they probably don't have the free routine either.
1N/A */
1N/A
1N/A return;
1N/A}
1N/A#else /* NEEDSGETIPNODE && NETINET6 */
1N/A#define sm_getipnodebyname getipnodebyname
1N/A#endif /* NEEDSGETIPNODE && NETINET6 */
1N/A
1N/Astruct hostent *
1N/Ami_gethostbyname(name, family)
1N/A char *name;
1N/A int family;
1N/A{
1N/A struct hostent *h = NULL;
1N/A#if (SOLARIS > 10000 && SOLARIS < 20400) || (defined(SOLARIS) && SOLARIS < 204) || (defined(sony_news) && defined(__svr4))
1N/A# if SOLARIS == 20300 || SOLARIS == 203
1N/A static struct hostent hp;
1N/A static char buf[1000];
1N/A extern struct hostent *_switch_gethostbyname_r();
1N/A
1N/A h = _switch_gethostbyname_r(name, &hp, buf, sizeof(buf), &h_errno);
1N/A# else /* SOLARIS == 20300 || SOLARIS == 203 */
1N/A extern struct hostent *__switch_gethostbyname();
1N/A
1N/A h = __switch_gethostbyname(name);
1N/A# endif /* SOLARIS == 20300 || SOLARIS == 203 */
1N/A#else /* (SOLARIS > 10000 && SOLARIS < 20400) || (defined(SOLARIS) && SOLARIS < 204) || (defined(sony_news) && defined(__svr4)) */
1N/A# if NETINET6
1N/A int flags = AI_DEFAULT|AI_ALL;
1N/A int err;
1N/A# endif /* NETINET6 */
1N/A
1N/A# if NETINET6
1N/A# if ADDRCONFIG_IS_BROKEN
1N/A flags &= ~AI_ADDRCONFIG;
1N/A# endif /* ADDRCONFIG_IS_BROKEN */
1N/A h = sm_getipnodebyname(name, family, flags, &err);
1N/A SM_SET_H_ERRNO(err);
1N/A# else /* NETINET6 */
1N/A h = gethostbyname(name);
1N/A# endif /* NETINET6 */
1N/A
1N/A#endif /* (SOLARIS > 10000 && SOLARIS < 20400) || (defined(SOLARIS) && SOLARIS < 204) || (defined(sony_news) && defined(__svr4)) */
1N/A return h;
1N/A}
1N/A
1N/A#if NETINET6
1N/A/*
1N/A** MI_INET_PTON -- convert printed form to network address.
1N/A**
1N/A** Wrapper for inet_pton() which handles IPv6: labels.
1N/A**
1N/A** Parameters:
1N/A** family -- address family
1N/A** src -- string
1N/A** dst -- destination address structure
1N/A**
1N/A** Returns:
1N/A** 1 if the address was valid
1N/A** 0 if the address wasn't parseable
1N/A** -1 if error
1N/A*/
1N/A
1N/Aint
1N/Ami_inet_pton(family, src, dst)
1N/A int family;
1N/A const char *src;
1N/A void *dst;
1N/A{
1N/A if (family == AF_INET6 &&
1N/A strncasecmp(src, "IPv6:", 5) == 0)
1N/A src += 5;
1N/A return inet_pton(family, src, dst);
1N/A}
1N/A#endif /* NETINET6 */