sm_gethost.c revision 302408
1235368Sgnn/*
2235368Sgnn *  Copyright (c) 1999-2001, 2004, 2010, 2013 Proofpoint, Inc. and its suppliers.
3235368Sgnn *	All rights reserved.
4235368Sgnn *
5235368Sgnn * By using this file, you agree to the terms and conditions set
6235368Sgnn * forth in the LICENSE file which can be found at the top level of
7235368Sgnn * the sendmail distribution.
8235368Sgnn *
9235368Sgnn */
10235368Sgnn
11235368Sgnn#include <sm/gen.h>
12235368SgnnSM_RCSID("@(#)$Id: sm_gethost.c,v 8.32 2013-11-22 20:51:36 ca Exp $")
13235368Sgnn
14235368Sgnn#include <sendmail.h>
15235368Sgnn#if NETINET || NETINET6
16235368Sgnn# include <arpa/inet.h>
17235368Sgnn#endif /* NETINET || NETINET6 */
18235368Sgnn#include "libmilter.h"
19235368Sgnn
20235368Sgnn/*
21235368Sgnn**  MI_GETHOSTBY{NAME,ADDR} -- compatibility routines for gethostbyXXX
22235368Sgnn**
23235368Sgnn**	Some operating systems have wierd problems with the gethostbyXXX
24235368Sgnn**	routines.  For example, Solaris versions at least through 2.3
25235368Sgnn**	don't properly deliver a canonical h_name field.  This tries to
26235368Sgnn**	work around these problems.
27235368Sgnn**
28235368Sgnn**	Support IPv6 as well as IPv4.
29235368Sgnn*/
30235368Sgnn
31235368Sgnn#if NETINET6 && NEEDSGETIPNODE
32235368Sgnn
33235368Sgnnstatic struct hostent *sm_getipnodebyname __P((const char *, int, int, int *));
34235368Sgnn
35235368Sgnn# ifndef AI_ADDRCONFIG
36235368Sgnn#  define AI_ADDRCONFIG	0	/* dummy */
37235368Sgnn# endif /* ! AI_ADDRCONFIG */
38235368Sgnn# ifndef AI_ALL
39235368Sgnn#  define AI_ALL	0	/* dummy */
40235368Sgnn# endif /* ! AI_ALL */
41235368Sgnn# ifndef AI_DEFAULT
42235368Sgnn#  define AI_DEFAULT	0	/* dummy */
43235368Sgnn# endif /* ! AI_DEFAULT */
44235368Sgnn
45235368Sgnnstatic struct hostent *
46235368Sgnnsm_getipnodebyname(name, family, flags, err)
47235368Sgnn	const char *name;
48235368Sgnn	int family;
49235368Sgnn	int flags;
50235368Sgnn	int *err;
51235368Sgnn{
52235368Sgnn	bool resv6 = true;
53235368Sgnn	struct hostent *h;
54235368Sgnn
55235368Sgnn	if (family == AF_INET6)
56235368Sgnn	{
57235368Sgnn		/* From RFC2133, section 6.1 */
58235368Sgnn		resv6 = bitset(RES_USE_INET6, _res.options);
59235368Sgnn		_res.options |= RES_USE_INET6;
60235368Sgnn	}
61235368Sgnn	SM_SET_H_ERRNO(0);
62235368Sgnn	h = gethostbyname(name);
63235368Sgnn	if (family == AF_INET6 && !resv6)
64235368Sgnn		_res.options &= ~RES_USE_INET6;
65235368Sgnn
66235368Sgnn	/* the function is supposed to return only the requested family */
67235368Sgnn	if (h != NULL && h->h_addrtype != family)
68235368Sgnn	{
69235368Sgnn# if NETINET6
70235368Sgnn		freehostent(h);
71235368Sgnn# endif /* NETINET6 */
72235368Sgnn		h = NULL;
73235368Sgnn		*err = NO_DATA;
74235368Sgnn	}
75235368Sgnn	else
76235368Sgnn		*err = h_errno;
77235368Sgnn	return h;
78235368Sgnn}
79235368Sgnn
80235368Sgnnvoid
81235368Sgnnfreehostent(h)
82235368Sgnn	struct hostent *h;
83235368Sgnn{
84235368Sgnn	/*
85235368Sgnn	**  Stub routine -- if they don't have getipnodeby*(),
86235368Sgnn	**  they probably don't have the free routine either.
87235368Sgnn	*/
88235368Sgnn
89235368Sgnn	return;
90235368Sgnn}
91235368Sgnn#else /* NEEDSGETIPNODE && NETINET6 */
92235368Sgnn#define sm_getipnodebyname getipnodebyname
93235368Sgnn#endif /* NEEDSGETIPNODE && NETINET6 */
94235368Sgnn
95235368Sgnnstruct hostent *
96235368Sgnnmi_gethostbyname(name, family)
97235368Sgnn	char *name;
98235368Sgnn	int family;
99235368Sgnn{
100235368Sgnn	struct hostent *h = NULL;
101235368Sgnn#if (SOLARIS > 10000 && SOLARIS < 20400) || (defined(SOLARIS) && SOLARIS < 204) || (defined(sony_news) && defined(__svr4))
102235368Sgnn# if SOLARIS == 20300 || SOLARIS == 203
103235368Sgnn	static struct hostent hp;
104235368Sgnn	static char buf[1000];
105235368Sgnn	extern struct hostent *_switch_gethostbyname_r();
106235368Sgnn
107235368Sgnn	h = _switch_gethostbyname_r(name, &hp, buf, sizeof(buf), &h_errno);
108235368Sgnn# else /* SOLARIS == 20300 || SOLARIS == 203 */
109235368Sgnn	extern struct hostent *__switch_gethostbyname();
110235368Sgnn
111235368Sgnn	h = __switch_gethostbyname(name);
112235368Sgnn# endif /* SOLARIS == 20300 || SOLARIS == 203 */
113235368Sgnn#else /* (SOLARIS > 10000 && SOLARIS < 20400) || (defined(SOLARIS) && SOLARIS < 204) || (defined(sony_news) && defined(__svr4)) */
114235368Sgnn# if NETINET6
115235368Sgnn#  ifndef SM_IPNODEBYNAME_FLAGS
116235368Sgnn    /* For IPv4-mapped addresses, use: AI_DEFAULT|AI_ALL */
117235368Sgnn#   define SM_IPNODEBYNAME_FLAGS	AI_ADDRCONFIG
118235368Sgnn#  endif /* SM_IPNODEBYNAME_FLAGS */
119235368Sgnn
120235368Sgnn	int flags = SM_IPNODEBYNAME_FLAGS;
121235368Sgnn	int err;
122235368Sgnn# endif /* NETINET6 */
123235368Sgnn
124235368Sgnn# if NETINET6
125235368Sgnn#  if ADDRCONFIG_IS_BROKEN
126235368Sgnn	flags &= ~AI_ADDRCONFIG;
127235368Sgnn#  endif /* ADDRCONFIG_IS_BROKEN */
128235368Sgnn	h = sm_getipnodebyname(name, family, flags, &err);
129235368Sgnn	SM_SET_H_ERRNO(err);
130235368Sgnn# else /* NETINET6 */
131235368Sgnn	h = gethostbyname(name);
132235368Sgnn# endif /* NETINET6 */
133235368Sgnn
134235368Sgnn#endif /* (SOLARIS > 10000 && SOLARIS < 20400) || (defined(SOLARIS) && SOLARIS < 204) || (defined(sony_news) && defined(__svr4)) */
135235368Sgnn
136235368Sgnn	/* the function is supposed to return only the requested family */
137235368Sgnn	if (h != NULL && h->h_addrtype != family)
138235368Sgnn	{
139235368Sgnn# if NETINET6
140235368Sgnn		freehostent(h);
141235368Sgnn# endif /* NETINET6 */
142235368Sgnn		h = NULL;
143235368Sgnn		SM_SET_H_ERRNO(NO_DATA);
144235368Sgnn	}
145235368Sgnn	return h;
146235368Sgnn}
147235368Sgnn
148235368Sgnn#if NETINET6
149235368Sgnn/*
150235368Sgnn**  MI_INET_PTON -- convert printed form to network address.
151235368Sgnn**
152235368Sgnn**	Wrapper for inet_pton() which handles IPv6: labels.
153235368Sgnn**
154235368Sgnn**	Parameters:
155235368Sgnn**		family -- address family
156235368Sgnn**		src -- string
157235368Sgnn**		dst -- destination address structure
158235368Sgnn**
159235368Sgnn**	Returns:
160235368Sgnn**		1 if the address was valid
161235368Sgnn**		0 if the address wasn't parseable
162235368Sgnn**		-1 if error
163235368Sgnn*/
164235368Sgnn
165235368Sgnnint
166235368Sgnnmi_inet_pton(family, src, dst)
167235368Sgnn	int family;
168235368Sgnn	const char *src;
169235368Sgnn	void *dst;
170235368Sgnn{
171235368Sgnn	if (family == AF_INET6 &&
172235368Sgnn	    strncasecmp(src, "IPv6:", 5) == 0)
173235368Sgnn		src += 5;
174235368Sgnn	return inet_pton(family, src, dst);
175235368Sgnn}
176235368Sgnn#endif /* NETINET6 */
177235368Sgnn