164562Sgshapiro/*
2249729Sgshapiro *  Copyright (c) 1999-2001, 2004, 2010, 2013 Sendmail, Inc. and its suppliers.
364562Sgshapiro *	All rights reserved.
464562Sgshapiro *
564562Sgshapiro * By using this file, you agree to the terms and conditions set
664562Sgshapiro * forth in the LICENSE file which can be found at the top level of
764562Sgshapiro * the sendmail distribution.
864562Sgshapiro *
964562Sgshapiro */
1064562Sgshapiro
1190792Sgshapiro#include <sm/gen.h>
12249729SgshapiroSM_RCSID("@(#)$Id: sm_gethost.c,v 8.30 2013/02/22 22:43:33 gshapiro Exp $")
1364562Sgshapiro
1464562Sgshapiro#include <sendmail.h>
1564562Sgshapiro#if NETINET || NETINET6
1664562Sgshapiro# include <arpa/inet.h>
1764562Sgshapiro#endif /* NETINET || NETINET6 */
18141858Sgshapiro#include "libmilter.h"
1964562Sgshapiro
2090792Sgshapiro/*
2164562Sgshapiro**  MI_GETHOSTBY{NAME,ADDR} -- compatibility routines for gethostbyXXX
2264562Sgshapiro**
2364562Sgshapiro**	Some operating systems have wierd problems with the gethostbyXXX
2464562Sgshapiro**	routines.  For example, Solaris versions at least through 2.3
2564562Sgshapiro**	don't properly deliver a canonical h_name field.  This tries to
2664562Sgshapiro**	work around these problems.
2764562Sgshapiro**
2864562Sgshapiro**	Support IPv6 as well as IPv4.
2964562Sgshapiro*/
3064562Sgshapiro
3177349Sgshapiro#if NETINET6 && NEEDSGETIPNODE
3264562Sgshapiro
33223067Sgshapirostatic struct hostent *sm_getipnodebyname __P((const char *, int, int, int *));
34141858Sgshapiro
3580785Sgshapiro# ifndef AI_ADDRCONFIG
3680785Sgshapiro#  define AI_ADDRCONFIG	0	/* dummy */
3780785Sgshapiro# endif /* ! AI_ADDRCONFIG */
3864562Sgshapiro# ifndef AI_ALL
3964562Sgshapiro#  define AI_ALL	0	/* dummy */
4064562Sgshapiro# endif /* ! AI_ALL */
4180785Sgshapiro# ifndef AI_DEFAULT
4280785Sgshapiro#  define AI_DEFAULT	0	/* dummy */
4380785Sgshapiro# endif /* ! AI_DEFAULT */
4464562Sgshapiro
4564562Sgshapirostatic struct hostent *
46223067Sgshapirosm_getipnodebyname(name, family, flags, err)
47223067Sgshapiro	const char *name;
4864562Sgshapiro	int family;
4964562Sgshapiro	int flags;
5064562Sgshapiro	int *err;
5164562Sgshapiro{
5290792Sgshapiro	bool resv6 = true;
5364562Sgshapiro	struct hostent *h;
5464562Sgshapiro
5564562Sgshapiro	if (family == AF_INET6)
5664562Sgshapiro	{
5764562Sgshapiro		/* From RFC2133, section 6.1 */
5864562Sgshapiro		resv6 = bitset(RES_USE_INET6, _res.options);
5964562Sgshapiro		_res.options |= RES_USE_INET6;
6064562Sgshapiro	}
6173188Sgshapiro	SM_SET_H_ERRNO(0);
6264562Sgshapiro	h = gethostbyname(name);
6364562Sgshapiro	if (family == AF_INET6 && !resv6)
6464562Sgshapiro		_res.options &= ~RES_USE_INET6;
6590792Sgshapiro	*err = h_errno;
6664562Sgshapiro	return h;
6764562Sgshapiro}
6871345Sgshapiro
6971345Sgshapirovoid
7071345Sgshapirofreehostent(h)
7171345Sgshapiro	struct hostent *h;
7271345Sgshapiro{
7371345Sgshapiro	/*
7471345Sgshapiro	**  Stub routine -- if they don't have getipnodeby*(),
7571345Sgshapiro	**  they probably don't have the free routine either.
7671345Sgshapiro	*/
7771345Sgshapiro
7871345Sgshapiro	return;
7971345Sgshapiro}
80223067Sgshapiro#else /* NEEDSGETIPNODE && NETINET6 */
81223067Sgshapiro#define sm_getipnodebyname getipnodebyname
8277349Sgshapiro#endif /* NEEDSGETIPNODE && NETINET6 */
8364562Sgshapiro
8464562Sgshapirostruct hostent *
8564562Sgshapiromi_gethostbyname(name, family)
8664562Sgshapiro	char *name;
8764562Sgshapiro	int family;
8864562Sgshapiro{
8964562Sgshapiro	struct hostent *h = NULL;
9064562Sgshapiro#if (SOLARIS > 10000 && SOLARIS < 20400) || (defined(SOLARIS) && SOLARIS < 204) || (defined(sony_news) && defined(__svr4))
9164562Sgshapiro# if SOLARIS == 20300 || SOLARIS == 203
9264562Sgshapiro	static struct hostent hp;
9364562Sgshapiro	static char buf[1000];
9464562Sgshapiro	extern struct hostent *_switch_gethostbyname_r();
9564562Sgshapiro
9664562Sgshapiro	h = _switch_gethostbyname_r(name, &hp, buf, sizeof(buf), &h_errno);
9764562Sgshapiro# else /* SOLARIS == 20300 || SOLARIS == 203 */
9864562Sgshapiro	extern struct hostent *__switch_gethostbyname();
9964562Sgshapiro
10064562Sgshapiro	h = __switch_gethostbyname(name);
10164562Sgshapiro# endif /* SOLARIS == 20300 || SOLARIS == 203 */
10264562Sgshapiro#else /* (SOLARIS > 10000 && SOLARIS < 20400) || (defined(SOLARIS) && SOLARIS < 204) || (defined(sony_news) && defined(__svr4)) */
10364562Sgshapiro# if NETINET6
104249729Sgshapiro#  ifndef SM_IPNODEBYNAME_FLAGS
105249729Sgshapiro    /* For IPv4-mapped addresses, use: AI_DEFAULT|AI_ALL */
106249729Sgshapiro#   define SM_IPNODEBYNAME_FLAGS	AI_ADDRCONFIG
107249729Sgshapiro#  endif /* SM_IPNODEBYNAME_FLAGS */
108249729Sgshapiro
109249729Sgshapiro	int flags = SM_IPNODEBYNAME_FLAGS;
11064562Sgshapiro	int err;
11164562Sgshapiro# endif /* NETINET6 */
11264562Sgshapiro
11364562Sgshapiro# if NETINET6
11480785Sgshapiro#  if ADDRCONFIG_IS_BROKEN
11580785Sgshapiro	flags &= ~AI_ADDRCONFIG;
11680785Sgshapiro#  endif /* ADDRCONFIG_IS_BROKEN */
117223067Sgshapiro	h = sm_getipnodebyname(name, family, flags, &err);
11873188Sgshapiro	SM_SET_H_ERRNO(err);
11964562Sgshapiro# else /* NETINET6 */
12064562Sgshapiro	h = gethostbyname(name);
12164562Sgshapiro# endif /* NETINET6 */
12264562Sgshapiro
12364562Sgshapiro#endif /* (SOLARIS > 10000 && SOLARIS < 20400) || (defined(SOLARIS) && SOLARIS < 204) || (defined(sony_news) && defined(__svr4)) */
12464562Sgshapiro	return h;
12564562Sgshapiro}
12690792Sgshapiro
12790792Sgshapiro#if NETINET6
12890792Sgshapiro/*
12990792Sgshapiro**  MI_INET_PTON -- convert printed form to network address.
13090792Sgshapiro**
13190792Sgshapiro**	Wrapper for inet_pton() which handles IPv6: labels.
13290792Sgshapiro**
13390792Sgshapiro**	Parameters:
13490792Sgshapiro**		family -- address family
13590792Sgshapiro**		src -- string
13690792Sgshapiro**		dst -- destination address structure
13790792Sgshapiro**
13890792Sgshapiro**	Returns:
13990792Sgshapiro**		1 if the address was valid
14090792Sgshapiro**		0 if the address wasn't parseable
14190792Sgshapiro**		-1 if error
14290792Sgshapiro*/
14390792Sgshapiro
14490792Sgshapiroint
14590792Sgshapiromi_inet_pton(family, src, dst)
14690792Sgshapiro	int family;
14790792Sgshapiro	const char *src;
14890792Sgshapiro	void *dst;
14990792Sgshapiro{
15090792Sgshapiro	if (family == AF_INET6 &&
15190792Sgshapiro	    strncasecmp(src, "IPv6:", 5) == 0)
15290792Sgshapiro		src += 5;
15390792Sgshapiro	return inet_pton(family, src, dst);
15490792Sgshapiro}
15590792Sgshapiro#endif /* NETINET6 */
156