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