164562Sgshapiro/* 2261194Sgshapiro * Copyright (c) 1999-2001, 2004, 2010, 2013 Proofpoint, 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> 12266527SgshapiroSM_RCSID("@(#)$Id: sm_gethost.c,v 8.32 2013-11-22 20:51:36 ca Exp $") 1364562Sgshapiro 1464562Sgshapiro#include <sendmail.h> 1564562Sgshapiro#if NETINET || NETINET6 1664562Sgshapiro# include <arpa/inet.h> 17363466Sgshapiro#endif 18141858Sgshapiro#include "libmilter.h" 1964562Sgshapiro 2090792Sgshapiro/* 2164562Sgshapiro** MI_GETHOSTBY{NAME,ADDR} -- compatibility routines for gethostbyXXX 2264562Sgshapiro** 23363466Sgshapiro** Some operating systems have weird 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 */ 37363466Sgshapiro# endif 3864562Sgshapiro# ifndef AI_ALL 3964562Sgshapiro# define AI_ALL 0 /* dummy */ 40363466Sgshapiro# endif 4180785Sgshapiro# ifndef AI_DEFAULT 4280785Sgshapiro# define AI_DEFAULT 0 /* dummy */ 43363466Sgshapiro# endif 4464562Sgshapiro 4564562Sgshapirostatic struct hostent * 46223067Sgshapirosm_getipnodebyname(name, family, flags, err) 47223067Sgshapiro const char *name; 4864562Sgshapiro int family; 4964562Sgshapiro int flags; 5064562Sgshapiro int *err; 5164562Sgshapiro{ 5264562Sgshapiro struct hostent *h; 53363466Sgshapiro# if HAS_GETHOSTBYNAME2 5464562Sgshapiro 55363466Sgshapiro h = gethostbyname2(name, family); 56363466Sgshapiro if (h == NULL) 57363466Sgshapiro *err = h_errno; 58363466Sgshapiro return h; 59363466Sgshapiro 60363466Sgshapiro# else /* HAS_GETHOSTBYNAME2 */ 61363466Sgshapiro# ifdef RES_USE_INET6 62363466Sgshapiro bool resv6 = true; 63363466Sgshapiro 6464562Sgshapiro if (family == AF_INET6) 6564562Sgshapiro { 6664562Sgshapiro /* From RFC2133, section 6.1 */ 6764562Sgshapiro resv6 = bitset(RES_USE_INET6, _res.options); 6864562Sgshapiro _res.options |= RES_USE_INET6; 6964562Sgshapiro } 70363466Sgshapiro# endif /* RES_USE_INET6 */ 7173188Sgshapiro SM_SET_H_ERRNO(0); 7264562Sgshapiro h = gethostbyname(name); 73363466Sgshapiro# ifdef RES_USE_INET6 74363466Sgshapiro if (!resv6) 7564562Sgshapiro _res.options &= ~RES_USE_INET6; 76363466Sgshapiro# endif 77261194Sgshapiro 78261194Sgshapiro /* the function is supposed to return only the requested family */ 79261194Sgshapiro if (h != NULL && h->h_addrtype != family) 80261194Sgshapiro { 81363466Sgshapiro# if NETINET6 82261194Sgshapiro freehostent(h); 83363466Sgshapiro# endif 84261194Sgshapiro h = NULL; 85261194Sgshapiro *err = NO_DATA; 86261194Sgshapiro } 87261194Sgshapiro else 88261194Sgshapiro *err = h_errno; 8964562Sgshapiro return h; 90363466Sgshapiro# endif /* HAS_GETHOSTBYNAME2 */ 9164562Sgshapiro} 9271345Sgshapiro 9371345Sgshapirovoid 9471345Sgshapirofreehostent(h) 9571345Sgshapiro struct hostent *h; 9671345Sgshapiro{ 9771345Sgshapiro /* 9871345Sgshapiro ** Stub routine -- if they don't have getipnodeby*(), 9971345Sgshapiro ** they probably don't have the free routine either. 10071345Sgshapiro */ 10171345Sgshapiro 10271345Sgshapiro return; 10371345Sgshapiro} 104223067Sgshapiro#else /* NEEDSGETIPNODE && NETINET6 */ 105363466Sgshapiro#define sm_getipnodebyname getipnodebyname 10677349Sgshapiro#endif /* NEEDSGETIPNODE && NETINET6 */ 10764562Sgshapiro 10864562Sgshapirostruct hostent * 10964562Sgshapiromi_gethostbyname(name, family) 11064562Sgshapiro char *name; 11164562Sgshapiro int family; 11264562Sgshapiro{ 11364562Sgshapiro struct hostent *h = NULL; 11464562Sgshapiro#if (SOLARIS > 10000 && SOLARIS < 20400) || (defined(SOLARIS) && SOLARIS < 204) || (defined(sony_news) && defined(__svr4)) 11564562Sgshapiro# if SOLARIS == 20300 || SOLARIS == 203 11664562Sgshapiro static struct hostent hp; 11764562Sgshapiro static char buf[1000]; 11864562Sgshapiro extern struct hostent *_switch_gethostbyname_r(); 11964562Sgshapiro 12064562Sgshapiro h = _switch_gethostbyname_r(name, &hp, buf, sizeof(buf), &h_errno); 12164562Sgshapiro# else /* SOLARIS == 20300 || SOLARIS == 203 */ 12264562Sgshapiro extern struct hostent *__switch_gethostbyname(); 12364562Sgshapiro 12464562Sgshapiro h = __switch_gethostbyname(name); 12564562Sgshapiro# endif /* SOLARIS == 20300 || SOLARIS == 203 */ 12664562Sgshapiro#else /* (SOLARIS > 10000 && SOLARIS < 20400) || (defined(SOLARIS) && SOLARIS < 204) || (defined(sony_news) && defined(__svr4)) */ 12764562Sgshapiro# if NETINET6 128249729Sgshapiro# ifndef SM_IPNODEBYNAME_FLAGS 129249729Sgshapiro /* For IPv4-mapped addresses, use: AI_DEFAULT|AI_ALL */ 130249729Sgshapiro# define SM_IPNODEBYNAME_FLAGS AI_ADDRCONFIG 131363466Sgshapiro# endif 132249729Sgshapiro 133249729Sgshapiro int flags = SM_IPNODEBYNAME_FLAGS; 13464562Sgshapiro int err; 13564562Sgshapiro# endif /* NETINET6 */ 13664562Sgshapiro 13764562Sgshapiro# if NETINET6 13880785Sgshapiro# if ADDRCONFIG_IS_BROKEN 13980785Sgshapiro flags &= ~AI_ADDRCONFIG; 140363466Sgshapiro# endif 141223067Sgshapiro h = sm_getipnodebyname(name, family, flags, &err); 14273188Sgshapiro SM_SET_H_ERRNO(err); 14364562Sgshapiro# else /* NETINET6 */ 14464562Sgshapiro h = gethostbyname(name); 14564562Sgshapiro# endif /* NETINET6 */ 14664562Sgshapiro 14764562Sgshapiro#endif /* (SOLARIS > 10000 && SOLARIS < 20400) || (defined(SOLARIS) && SOLARIS < 204) || (defined(sony_news) && defined(__svr4)) */ 148261194Sgshapiro 149261194Sgshapiro /* the function is supposed to return only the requested family */ 150261194Sgshapiro if (h != NULL && h->h_addrtype != family) 151261194Sgshapiro { 152261194Sgshapiro# if NETINET6 153261194Sgshapiro freehostent(h); 154363466Sgshapiro# endif 155261194Sgshapiro h = NULL; 156261194Sgshapiro SM_SET_H_ERRNO(NO_DATA); 157261194Sgshapiro } 15864562Sgshapiro return h; 15964562Sgshapiro} 16090792Sgshapiro 16190792Sgshapiro#if NETINET6 16290792Sgshapiro/* 16390792Sgshapiro** MI_INET_PTON -- convert printed form to network address. 16490792Sgshapiro** 16590792Sgshapiro** Wrapper for inet_pton() which handles IPv6: labels. 16690792Sgshapiro** 16790792Sgshapiro** Parameters: 16890792Sgshapiro** family -- address family 16990792Sgshapiro** src -- string 17090792Sgshapiro** dst -- destination address structure 17190792Sgshapiro** 17290792Sgshapiro** Returns: 17390792Sgshapiro** 1 if the address was valid 174363466Sgshapiro** 0 if the address wasn't parsable 17590792Sgshapiro** -1 if error 17690792Sgshapiro*/ 17790792Sgshapiro 17890792Sgshapiroint 17990792Sgshapiromi_inet_pton(family, src, dst) 18090792Sgshapiro int family; 18190792Sgshapiro const char *src; 18290792Sgshapiro void *dst; 18390792Sgshapiro{ 18490792Sgshapiro if (family == AF_INET6 && 18590792Sgshapiro strncasecmp(src, "IPv6:", 5) == 0) 18690792Sgshapiro src += 5; 18790792Sgshapiro return inet_pton(family, src, dst); 18890792Sgshapiro} 18990792Sgshapiro#endif /* NETINET6 */ 190