00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include <config.h>
00023 #include <string.h>
00024
00025 #include <isc/net.h>
00026 #include <isc/netaddr.h>
00027 #include <isc/netdb.h>
00028 #include <isc/netscope.h>
00029 #include <isc/result.h>
00030 #include <isc/sockaddr.h>
00031 #include <isc/util.h>
00032
00033 #include <bind9/getaddresses.h>
00034
00035 #ifdef HAVE_ADDRINFO
00036 #ifdef HAVE_GETADDRINFO
00037 #ifdef HAVE_GAISTRERROR
00038 #define USE_GETADDRINFO
00039 #endif
00040 #endif
00041 #endif
00042
00043 #ifndef USE_GETADDRINFO
00044 #ifndef ISC_PLATFORM_NONSTDHERRNO
00045 extern int h_errno;
00046 #endif
00047 #endif
00048
00049 isc_result_t
00050 bind9_getaddresses(const char *hostname, in_port_t port,
00051 isc_sockaddr_t *addrs, int addrsize, int *addrcount)
00052 {
00053 struct in_addr in4;
00054 struct in6_addr in6;
00055 isc_boolean_t have_ipv4, have_ipv6;
00056 int i;
00057
00058 #ifdef USE_GETADDRINFO
00059 struct addrinfo *ai = NULL, *tmpai, hints;
00060 int result;
00061 #else
00062 struct hostent *he;
00063 #endif
00064
00065 REQUIRE(hostname != NULL);
00066 REQUIRE(addrs != NULL);
00067 REQUIRE(addrcount != NULL);
00068 REQUIRE(addrsize > 0);
00069
00070 have_ipv4 = ISC_TF((isc_net_probeipv4() == ISC_R_SUCCESS));
00071 have_ipv6 = ISC_TF((isc_net_probeipv6() == ISC_R_SUCCESS));
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082 if (inet_pton(AF_INET, hostname, &in4) == 1) {
00083 if (have_ipv4)
00084 isc_sockaddr_fromin(&addrs[0], &in4, port);
00085 else
00086 isc_sockaddr_v6fromin(&addrs[0], &in4, port);
00087 *addrcount = 1;
00088 return (ISC_R_SUCCESS);
00089 } else if (strlen(hostname) <= 127U) {
00090 char tmpbuf[128], *d;
00091 isc_uint32_t zone = 0;
00092
00093 strcpy(tmpbuf, hostname);
00094 d = strchr(tmpbuf, '%');
00095 if (d != NULL)
00096 *d = '\0';
00097
00098 if (inet_pton(AF_INET6, tmpbuf, &in6) == 1) {
00099 isc_netaddr_t na;
00100
00101 if (!have_ipv6)
00102 return (ISC_R_FAMILYNOSUPPORT);
00103
00104 if (d != NULL) {
00105 #ifdef ISC_PLATFORM_HAVESCOPEID
00106 isc_result_t iresult;
00107
00108 iresult = isc_netscope_pton(AF_INET6, d + 1,
00109 &in6, &zone);
00110
00111 if (iresult != ISC_R_SUCCESS)
00112 return (iresult);
00113 #else
00114
00115
00116
00117
00118
00119
00120 return (ISC_R_BADADDRESSFORM);
00121 #endif
00122 }
00123
00124 isc_netaddr_fromin6(&na, &in6);
00125 isc_netaddr_setzone(&na, zone);
00126 isc_sockaddr_fromnetaddr(&addrs[0],
00127 (const isc_netaddr_t *)&na,
00128 port);
00129
00130 *addrcount = 1;
00131 return (ISC_R_SUCCESS);
00132 }
00133 }
00134 #ifdef USE_GETADDRINFO
00135 memset(&hints, 0, sizeof(hints));
00136 if (!have_ipv6)
00137 hints.ai_family = PF_INET;
00138 else if (!have_ipv4)
00139 hints.ai_family = PF_INET6;
00140 else {
00141 hints.ai_family = PF_UNSPEC;
00142 #ifdef AI_ADDRCONFIG
00143 hints.ai_flags = AI_ADDRCONFIG;
00144 #endif
00145 }
00146 hints.ai_socktype = SOCK_STREAM;
00147 #ifdef AI_ADDRCONFIG
00148 again:
00149 #endif
00150 result = getaddrinfo(hostname, NULL, &hints, &ai);
00151 switch (result) {
00152 case 0:
00153 break;
00154 case EAI_NONAME:
00155 #if defined(EAI_NODATA) && (EAI_NODATA != EAI_NONAME)
00156 case EAI_NODATA:
00157 #endif
00158 return (ISC_R_NOTFOUND);
00159 #ifdef AI_ADDRCONFIG
00160 case EAI_BADFLAGS:
00161 if ((hints.ai_flags & AI_ADDRCONFIG) != 0) {
00162 hints.ai_flags &= ~AI_ADDRCONFIG;
00163 goto again;
00164 }
00165 #endif
00166 default:
00167 return (ISC_R_FAILURE);
00168 }
00169 for (tmpai = ai, i = 0;
00170 tmpai != NULL && i < addrsize;
00171 tmpai = tmpai->ai_next)
00172 {
00173 if (tmpai->ai_family != AF_INET &&
00174 tmpai->ai_family != AF_INET6)
00175 continue;
00176 if (tmpai->ai_family == AF_INET) {
00177 struct sockaddr_in *sin;
00178 sin = (struct sockaddr_in *)tmpai->ai_addr;
00179 isc_sockaddr_fromin(&addrs[i], &sin->sin_addr, port);
00180 } else {
00181 struct sockaddr_in6 *sin6;
00182 sin6 = (struct sockaddr_in6 *)tmpai->ai_addr;
00183 isc_sockaddr_fromin6(&addrs[i], &sin6->sin6_addr,
00184 port);
00185 }
00186 i++;
00187
00188 }
00189 freeaddrinfo(ai);
00190 *addrcount = i;
00191 #else
00192 he = gethostbyname(hostname);
00193 if (he == NULL) {
00194 switch (h_errno) {
00195 case HOST_NOT_FOUND:
00196 #ifdef NO_DATA
00197 case NO_DATA:
00198 #endif
00199 #if defined(NO_ADDRESS) && (!defined(NO_DATA) || (NO_DATA != NO_ADDRESS))
00200 case NO_ADDRESS:
00201 #endif
00202 return (ISC_R_NOTFOUND);
00203 default:
00204 return (ISC_R_FAILURE);
00205 }
00206 }
00207 if (he->h_addrtype != AF_INET && he->h_addrtype != AF_INET6)
00208 return (ISC_R_NOTFOUND);
00209 for (i = 0; i < addrsize; i++) {
00210 if (he->h_addrtype == AF_INET) {
00211 struct in_addr *inp;
00212 inp = (struct in_addr *)(he->h_addr_list[i]);
00213 if (inp == NULL)
00214 break;
00215 isc_sockaddr_fromin(&addrs[i], inp, port);
00216 } else {
00217 struct in6_addr *in6p;
00218 in6p = (struct in6_addr *)(he->h_addr_list[i]);
00219 if (in6p == NULL)
00220 break;
00221 isc_sockaddr_fromin6(&addrs[i], in6p, port);
00222 }
00223 }
00224 *addrcount = i;
00225 #endif
00226 if (*addrcount == 0)
00227 return (ISC_R_NOTFOUND);
00228 else
00229 return (ISC_R_SUCCESS);
00230 }