106f25ae9SGregory Neil Shapiro /*
25dd76dd0SGregory Neil Shapiro * Copyright (c) 1999-2001, 2004, 2010, 2013 Proofpoint, Inc. and its suppliers.
306f25ae9SGregory Neil Shapiro * All rights reserved.
406f25ae9SGregory Neil Shapiro *
506f25ae9SGregory Neil Shapiro * By using this file, you agree to the terms and conditions set
606f25ae9SGregory Neil Shapiro * forth in the LICENSE file which can be found at the top level of
706f25ae9SGregory Neil Shapiro * the sendmail distribution.
806f25ae9SGregory Neil Shapiro *
906f25ae9SGregory Neil Shapiro */
1006f25ae9SGregory Neil Shapiro
1140266059SGregory Neil Shapiro #include <sm/gen.h>
124313cc83SGregory Neil Shapiro SM_RCSID("@(#)$Id: sm_gethost.c,v 8.32 2013-11-22 20:51:36 ca Exp $")
1306f25ae9SGregory Neil Shapiro
1406f25ae9SGregory Neil Shapiro #include <sendmail.h>
1506f25ae9SGregory Neil Shapiro #if NETINET || NETINET6
1606f25ae9SGregory Neil Shapiro # include <arpa/inet.h>
17*5b0945b5SGregory Neil Shapiro #endif
18b6bacd31SGregory Neil Shapiro #include "libmilter.h"
1906f25ae9SGregory Neil Shapiro
2040266059SGregory Neil Shapiro /*
2106f25ae9SGregory Neil Shapiro ** MI_GETHOSTBY{NAME,ADDR} -- compatibility routines for gethostbyXXX
2206f25ae9SGregory Neil Shapiro **
23*5b0945b5SGregory Neil Shapiro ** Some operating systems have weird problems with the gethostbyXXX
2406f25ae9SGregory Neil Shapiro ** routines. For example, Solaris versions at least through 2.3
2506f25ae9SGregory Neil Shapiro ** don't properly deliver a canonical h_name field. This tries to
2606f25ae9SGregory Neil Shapiro ** work around these problems.
2706f25ae9SGregory Neil Shapiro **
2806f25ae9SGregory Neil Shapiro ** Support IPv6 as well as IPv4.
2906f25ae9SGregory Neil Shapiro */
3006f25ae9SGregory Neil Shapiro
318774250cSGregory Neil Shapiro #if NETINET6 && NEEDSGETIPNODE
3206f25ae9SGregory Neil Shapiro
336f9c8e5bSGregory Neil Shapiro static struct hostent *sm_getipnodebyname __P((const char *, int, int, int *));
34b6bacd31SGregory Neil Shapiro
3513058a91SGregory Neil Shapiro # ifndef AI_ADDRCONFIG
3613058a91SGregory Neil Shapiro # define AI_ADDRCONFIG 0 /* dummy */
37*5b0945b5SGregory Neil Shapiro # endif
3806f25ae9SGregory Neil Shapiro # ifndef AI_ALL
3906f25ae9SGregory Neil Shapiro # define AI_ALL 0 /* dummy */
40*5b0945b5SGregory Neil Shapiro # endif
4113058a91SGregory Neil Shapiro # ifndef AI_DEFAULT
4213058a91SGregory Neil Shapiro # define AI_DEFAULT 0 /* dummy */
43*5b0945b5SGregory Neil Shapiro # endif
4406f25ae9SGregory Neil Shapiro
4506f25ae9SGregory Neil Shapiro static struct hostent *
sm_getipnodebyname(name,family,flags,err)466f9c8e5bSGregory Neil Shapiro sm_getipnodebyname(name, family, flags, err)
476f9c8e5bSGregory Neil Shapiro const char *name;
4806f25ae9SGregory Neil Shapiro int family;
4906f25ae9SGregory Neil Shapiro int flags;
5006f25ae9SGregory Neil Shapiro int *err;
5106f25ae9SGregory Neil Shapiro {
5206f25ae9SGregory Neil Shapiro struct hostent *h;
53*5b0945b5SGregory Neil Shapiro # if HAS_GETHOSTBYNAME2
54*5b0945b5SGregory Neil Shapiro
55*5b0945b5SGregory Neil Shapiro h = gethostbyname2(name, family);
56*5b0945b5SGregory Neil Shapiro if (h == NULL)
57*5b0945b5SGregory Neil Shapiro *err = h_errno;
58*5b0945b5SGregory Neil Shapiro return h;
59*5b0945b5SGregory Neil Shapiro
60*5b0945b5SGregory Neil Shapiro # else /* HAS_GETHOSTBYNAME2 */
61*5b0945b5SGregory Neil Shapiro # ifdef RES_USE_INET6
62*5b0945b5SGregory Neil Shapiro bool resv6 = true;
6306f25ae9SGregory Neil Shapiro
6406f25ae9SGregory Neil Shapiro if (family == AF_INET6)
6506f25ae9SGregory Neil Shapiro {
6606f25ae9SGregory Neil Shapiro /* From RFC2133, section 6.1 */
6706f25ae9SGregory Neil Shapiro resv6 = bitset(RES_USE_INET6, _res.options);
6806f25ae9SGregory Neil Shapiro _res.options |= RES_USE_INET6;
6906f25ae9SGregory Neil Shapiro }
70*5b0945b5SGregory Neil Shapiro # endif /* RES_USE_INET6 */
71602a2b1bSGregory Neil Shapiro SM_SET_H_ERRNO(0);
7206f25ae9SGregory Neil Shapiro h = gethostbyname(name);
73*5b0945b5SGregory Neil Shapiro # ifdef RES_USE_INET6
74*5b0945b5SGregory Neil Shapiro if (!resv6)
7506f25ae9SGregory Neil Shapiro _res.options &= ~RES_USE_INET6;
76*5b0945b5SGregory Neil Shapiro # endif
775dd76dd0SGregory Neil Shapiro
785dd76dd0SGregory Neil Shapiro /* the function is supposed to return only the requested family */
795dd76dd0SGregory Neil Shapiro if (h != NULL && h->h_addrtype != family)
805dd76dd0SGregory Neil Shapiro {
815dd76dd0SGregory Neil Shapiro # if NETINET6
825dd76dd0SGregory Neil Shapiro freehostent(h);
83*5b0945b5SGregory Neil Shapiro # endif
845dd76dd0SGregory Neil Shapiro h = NULL;
855dd76dd0SGregory Neil Shapiro *err = NO_DATA;
865dd76dd0SGregory Neil Shapiro }
875dd76dd0SGregory Neil Shapiro else
8840266059SGregory Neil Shapiro *err = h_errno;
8906f25ae9SGregory Neil Shapiro return h;
90*5b0945b5SGregory Neil Shapiro # endif /* HAS_GETHOSTBYNAME2 */
9106f25ae9SGregory Neil Shapiro }
92193538b7SGregory Neil Shapiro
93193538b7SGregory Neil Shapiro void
freehostent(h)94193538b7SGregory Neil Shapiro freehostent(h)
95193538b7SGregory Neil Shapiro struct hostent *h;
96193538b7SGregory Neil Shapiro {
97193538b7SGregory Neil Shapiro /*
98193538b7SGregory Neil Shapiro ** Stub routine -- if they don't have getipnodeby*(),
99193538b7SGregory Neil Shapiro ** they probably don't have the free routine either.
100193538b7SGregory Neil Shapiro */
101193538b7SGregory Neil Shapiro
102193538b7SGregory Neil Shapiro return;
103193538b7SGregory Neil Shapiro }
1046f9c8e5bSGregory Neil Shapiro #else /* NEEDSGETIPNODE && NETINET6 */
1056f9c8e5bSGregory Neil Shapiro #define sm_getipnodebyname getipnodebyname
1068774250cSGregory Neil Shapiro #endif /* NEEDSGETIPNODE && NETINET6 */
10706f25ae9SGregory Neil Shapiro
10806f25ae9SGregory Neil Shapiro struct hostent *
mi_gethostbyname(name,family)10906f25ae9SGregory Neil Shapiro mi_gethostbyname(name, family)
11006f25ae9SGregory Neil Shapiro char *name;
11106f25ae9SGregory Neil Shapiro int family;
11206f25ae9SGregory Neil Shapiro {
11306f25ae9SGregory Neil Shapiro struct hostent *h = NULL;
11406f25ae9SGregory Neil Shapiro #if (SOLARIS > 10000 && SOLARIS < 20400) || (defined(SOLARIS) && SOLARIS < 204) || (defined(sony_news) && defined(__svr4))
11506f25ae9SGregory Neil Shapiro # if SOLARIS == 20300 || SOLARIS == 203
11606f25ae9SGregory Neil Shapiro static struct hostent hp;
11706f25ae9SGregory Neil Shapiro static char buf[1000];
11806f25ae9SGregory Neil Shapiro extern struct hostent *_switch_gethostbyname_r();
11906f25ae9SGregory Neil Shapiro
12006f25ae9SGregory Neil Shapiro h = _switch_gethostbyname_r(name, &hp, buf, sizeof(buf), &h_errno);
12106f25ae9SGregory Neil Shapiro # else /* SOLARIS == 20300 || SOLARIS == 203 */
12206f25ae9SGregory Neil Shapiro extern struct hostent *__switch_gethostbyname();
12306f25ae9SGregory Neil Shapiro
12406f25ae9SGregory Neil Shapiro h = __switch_gethostbyname(name);
12506f25ae9SGregory Neil Shapiro # endif /* SOLARIS == 20300 || SOLARIS == 203 */
12606f25ae9SGregory Neil Shapiro #else /* (SOLARIS > 10000 && SOLARIS < 20400) || (defined(SOLARIS) && SOLARIS < 204) || (defined(sony_news) && defined(__svr4)) */
12706f25ae9SGregory Neil Shapiro # if NETINET6
128552d4955SGregory Neil Shapiro # ifndef SM_IPNODEBYNAME_FLAGS
129552d4955SGregory Neil Shapiro /* For IPv4-mapped addresses, use: AI_DEFAULT|AI_ALL */
130552d4955SGregory Neil Shapiro # define SM_IPNODEBYNAME_FLAGS AI_ADDRCONFIG
131*5b0945b5SGregory Neil Shapiro # endif
132552d4955SGregory Neil Shapiro
133552d4955SGregory Neil Shapiro int flags = SM_IPNODEBYNAME_FLAGS;
13406f25ae9SGregory Neil Shapiro int err;
13506f25ae9SGregory Neil Shapiro # endif /* NETINET6 */
13606f25ae9SGregory Neil Shapiro
13706f25ae9SGregory Neil Shapiro # if NETINET6
13813058a91SGregory Neil Shapiro # if ADDRCONFIG_IS_BROKEN
13913058a91SGregory Neil Shapiro flags &= ~AI_ADDRCONFIG;
140*5b0945b5SGregory Neil Shapiro # endif
1416f9c8e5bSGregory Neil Shapiro h = sm_getipnodebyname(name, family, flags, &err);
142602a2b1bSGregory Neil Shapiro SM_SET_H_ERRNO(err);
14306f25ae9SGregory Neil Shapiro # else /* NETINET6 */
14406f25ae9SGregory Neil Shapiro h = gethostbyname(name);
14506f25ae9SGregory Neil Shapiro # endif /* NETINET6 */
14606f25ae9SGregory Neil Shapiro
14706f25ae9SGregory Neil Shapiro #endif /* (SOLARIS > 10000 && SOLARIS < 20400) || (defined(SOLARIS) && SOLARIS < 204) || (defined(sony_news) && defined(__svr4)) */
1485dd76dd0SGregory Neil Shapiro
1495dd76dd0SGregory Neil Shapiro /* the function is supposed to return only the requested family */
1505dd76dd0SGregory Neil Shapiro if (h != NULL && h->h_addrtype != family)
1515dd76dd0SGregory Neil Shapiro {
1525dd76dd0SGregory Neil Shapiro #if NETINET6
1535dd76dd0SGregory Neil Shapiro freehostent(h);
154*5b0945b5SGregory Neil Shapiro #endif
1555dd76dd0SGregory Neil Shapiro h = NULL;
1565dd76dd0SGregory Neil Shapiro SM_SET_H_ERRNO(NO_DATA);
1575dd76dd0SGregory Neil Shapiro }
15806f25ae9SGregory Neil Shapiro return h;
15906f25ae9SGregory Neil Shapiro }
16040266059SGregory Neil Shapiro
16140266059SGregory Neil Shapiro #if NETINET6
16240266059SGregory Neil Shapiro /*
16340266059SGregory Neil Shapiro ** MI_INET_PTON -- convert printed form to network address.
16440266059SGregory Neil Shapiro **
16540266059SGregory Neil Shapiro ** Wrapper for inet_pton() which handles IPv6: labels.
16640266059SGregory Neil Shapiro **
16740266059SGregory Neil Shapiro ** Parameters:
16840266059SGregory Neil Shapiro ** family -- address family
16940266059SGregory Neil Shapiro ** src -- string
17040266059SGregory Neil Shapiro ** dst -- destination address structure
17140266059SGregory Neil Shapiro **
17240266059SGregory Neil Shapiro ** Returns:
17340266059SGregory Neil Shapiro ** 1 if the address was valid
174*5b0945b5SGregory Neil Shapiro ** 0 if the address wasn't parsable
17540266059SGregory Neil Shapiro ** -1 if error
17640266059SGregory Neil Shapiro */
17740266059SGregory Neil Shapiro
17840266059SGregory Neil Shapiro int
mi_inet_pton(family,src,dst)17940266059SGregory Neil Shapiro mi_inet_pton(family, src, dst)
18040266059SGregory Neil Shapiro int family;
18140266059SGregory Neil Shapiro const char *src;
18240266059SGregory Neil Shapiro void *dst;
18340266059SGregory Neil Shapiro {
18440266059SGregory Neil Shapiro if (family == AF_INET6 &&
18540266059SGregory Neil Shapiro strncasecmp(src, "IPv6:", 5) == 0)
18640266059SGregory Neil Shapiro src += 5;
18740266059SGregory Neil Shapiro return inet_pton(family, src, dst);
18840266059SGregory Neil Shapiro }
18940266059SGregory Neil Shapiro #endif /* NETINET6 */
190