00001
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
#include "socket.h"
00030
#include "get_xby.h"
00031
#include "udp_dom.h"
00032
00033
#if defined(USE_BSD_API)
00034
00035
static struct hostent *copyandmerge (
const struct hostent *he1,
00036
const struct hostent *he2,
00037
int af,
int *err);
00038
00039
static __inline
void scan_interface (BOOL *have_v4, BOOL *have_v6)
00040 {
00041
if (have_v4)
00042 *have_v4 = TRUE;
00043
00044
if (have_v6)
00045
#if defined(USE_IPV6)
00046
*have_v6 = dns_do_ipv6;
00047
#else
00048
*have_v6 = FALSE;
00049
#endif
00050
}
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
struct hostent * W32_CALL
00064 getipnodebyname (
const char *name,
int af,
int flags,
int *error)
00065 {
00066
struct hostent *he1 = NULL;
00067
struct hostent *he2 = NULL;
00068
struct in_addr in4;
00069
struct in6_addr in6;
00070 BOOL have_v4 = TRUE, have_v6 = TRUE;
00071 BOOL v4 = FALSE, v6 = FALSE;
00072
int tmp_err;
00073
00074 SOCK_DEBUGF ((
"\ngetipnodebyname: %s ", name));
00075
00076
00077
00078
if (flags & AI_ADDRCONFIG)
00079 scan_interface (&have_v4, &have_v6);
00080
00081
00082
00083 v4 =
inet_pton (AF_INET, name, &in4);
00084
if (!v4)
00085 v6 =
inet_pton (AF_INET6, name, &in6);
00086
00087
00088
00089
if ((af == AF_INET6 && !(flags & AI_V4MAPPED) && v4) ||
00090 (af == AF_INET && v6) ||
00091 (!have_v4 && v4) ||
00092 (!have_v6 && v6) ||
00093 (!have_v4 && af == AF_INET) ||
00094 ((!have_v6 && af == AF_INET6) && ((flags & AI_V4MAPPED) && have_v4)) ||
00095 !(flags & AI_V4MAPPED))
00096 {
00097 *error = HOST_NOT_FOUND;
00098
return (NULL);
00099 }
00100
00101
00102
00103
if (v4 || v6)
00104 {
00105
struct hostent he;
00106
char *addr_list[2];
00107
char *aliases[1];
00108
00109 he.h_name = (
char*) name;
00110 he.h_addr_list = addr_list;
00111 he.h_addr_list[0] = (v4 ? (
char*)&in4 : (
char*)&in6);
00112 he.h_addr_list[1] = NULL;
00113 he.h_aliases = aliases;
00114 he.h_aliases[0] = NULL;
00115 he.h_length = (v4 ? INADDRSZ : IN6ADDRSZ);
00116 he.h_addrtype = (v4 ? AF_INET : AF_INET6);
00117
return copyandmerge (&he, NULL, af, error);
00118 }
00119
00120 tmp_err = NO_RECOVERY;
00121
if (have_v6 && af == AF_INET6)
00122 {
00123
#if defined(USE_IPV6)
00124
he1 = gethostbyname6 (name);
00125
#else
00126
he1 = NULL;
00127
#endif
00128
if (!he1)
00129 tmp_err = HOST_NOT_FOUND;
00130 }
00131
00132
if (have_v4 &&
00133 (af == AF_INET ||
00134 (af == AF_INET6 &&
00135 (flags & AI_V4MAPPED) && (!he1 || (flags & AI_ALL)))))
00136 {
00137 SOCK_ENTER_SCOPE();
00138 he2 = gethostbyname (name);
00139 SOCK_LEAVE_SCOPE();
00140
if (!he2 || !he1)
00141 {
00142 *error = HOST_NOT_FOUND;
00143
return (NULL);
00144 }
00145 }
00146
else
00147 *error = tmp_err;
00148
00149
return copyandmerge (he1, he2, af, error);
00150 }
00151
00152
struct hostent * W32_CALL
00153 getipnodebyaddr (
const void *src, size_t len,
int af,
int *error)
00154 {
00155
struct hostent *he1, *he2;
00156
const BYTE *cp = (
const BYTE*) src;
00157
00158 SOCK_DEBUGF ((
"\ngetipnodebyaddr: "));
00159
00160
if (!src)
00161 {
00162 *error = NO_RECOVERY;
00163
return (NULL);
00164 }
00165
00166
switch (af)
00167 {
00168
case AF_INET:
00169
if (len < INADDRSZ)
00170 {
00171 *error = NO_RECOVERY;
00172
return (NULL);
00173 }
00174
break;
00175
#if defined(USE_IPV6)
00176
case AF_INET6:
00177
if (len < IN6ADDRSZ)
00178 {
00179 *error = NO_RECOVERY;
00180
return (NULL);
00181 }
00182
break;
00183
#endif
00184
default:
00185 *error = NO_RECOVERY;
00186
return (NULL);
00187 }
00188
00189
00190
00191
if ((af == AF_INET6 && IN6_IS_ADDR_V4COMPAT(cp)) ||
00192 (af == AF_INET6 && IN6_IS_ADDR_V4MAPPED(cp)) ||
00193 (af == AF_INET))
00194 {
00195
if (af == AF_INET6)
00196 cp += 12;
00197
00198 SOCK_ENTER_SCOPE();
00199 he1 = gethostbyaddr ((
const char*)cp, 4, AF_INET);
00200 SOCK_LEAVE_SCOPE();
00201
00202
if (af == AF_INET)
00203
goto ret_copy;
00204
00205
00206
00207 he2 = copyandmerge (he1, NULL, af, error);
00208
if (he2)
00209 {
00210 memcpy (he2->h_addr, src, len);
00211 SOCK_DEBUGF ((
"%s", af == AF_INET ?
00212 inet_ntoa(*(
struct in_addr*)&he2->h_addr) :
00213
_inet6_ntoa(he2->h_addr)));
00214 }
00215
return (he2);
00216 }
00217
00218 he1 = gethostbyaddr (src, len, AF_INET6);
00219
00220 ret_copy:
00221
if (!he1)
00222 {
00223 *error = HOST_NOT_FOUND;
00224
return (NULL);
00225 }
00226
return copyandmerge (he1, NULL, af, error);
00227 }
00228
00229
void W32_CALL freehostent (
struct hostent *he)
00230 {
00231
char *p;
00232
00233 SOCK_DEBUGF ((
"\nfreehostent: %s ", he->h_name));
00234
00235
if (!he->h_name)
00236
return;
00237
00238 free (he->h_name);
00239 he->h_name = NULL;
00240
00241
for (p = he->h_addr_list[0]; p; p++)
00242 free (p);
00243
00244
for (p = he->h_aliases[0]; p; p++)
00245 free (p);
00246
00247 free (he->h_aliases);
00248 free (he->h_addr_list);
00249 free (he);
00250 }
00251
00252
static struct hostent *copyandmerge (
const struct hostent *he1,
00253
const struct hostent *he2,
00254
int af,
int *error)
00255 {
00256
struct hostent *he = NULL;
00257
int addresses = 1;
00258
int names = 1;
00259
char **cpp, **npp;
00260
00261
00262
00263
if (he1)
00264 {
00265 cpp = he1->h_addr_list;
00266
while (*cpp)
00267 {
00268 addresses++;
00269 cpp++;
00270 }
00271 cpp = he1->h_aliases;
00272
while (*cpp)
00273 {
00274 names++;
00275 cpp++;
00276 }
00277 }
00278
00279
if (he2)
00280 {
00281 cpp = he2->h_addr_list;
00282
while (*cpp)
00283 {
00284 addresses++;
00285 cpp++;
00286 }
00287
if (!he1)
00288 {
00289 cpp = he2->h_aliases;
00290
while (*cpp)
00291 {
00292 names++;
00293 cpp++;
00294 }
00295 }
00296 }
00297
00298
if (addresses == 1)
00299 {
00300 *error = NO_ADDRESS;
00301
return (NULL);
00302 }
00303
00304 he = malloc (
sizeof(*he));
00305
if (!he)
00306 {
00307 *error = NO_RECOVERY;
00308
return (NULL);
00309 }
00310
00311 he->h_addr_list = calloc (addresses *
sizeof(
char*), 1);
00312
if (!he->h_addr_list)
00313
goto cleanup0;
00314
00315
00316
00317 npp = he->h_addr_list;
00318
if (he1)
00319 {
00320 cpp = he1->h_addr_list;
00321
while (*cpp)
00322 {
00323 *npp = malloc (af == AF_INET ? INADDRSZ : IN6ADDRSZ);
00324
if (!*npp)
00325
goto cleanup1;
00326
00327
00328
00329
if (af == AF_INET6 && he1->h_addrtype == AF_INET)
00330 {
00331 memcpy (*npp, in6addr_mapped,
sizeof(in6addr_mapped));
00332 memcpy (*npp +
sizeof(in6addr_mapped), *cpp, INADDRSZ);
00333 }
00334
else
00335 memcpy (*npp, *cpp, af == AF_INET ? INADDRSZ : IN6ADDRSZ);
00336 cpp++;
00337 npp++;
00338 }
00339 }
00340
00341
if (he2)
00342 {
00343 cpp = he2->h_addr_list;
00344
while (*cpp)
00345 {
00346 *npp = malloc (af == AF_INET ? INADDRSZ : IN6ADDRSZ);
00347
if (!*npp)
00348
goto cleanup1;
00349
00350
00351
00352
if (af == AF_INET6 && he2->h_addrtype == AF_INET)
00353 {
00354 memcpy (*npp, in6addr_mapped,
sizeof(in6addr_mapped));
00355 memcpy (*npp +
sizeof(in6addr_mapped), *cpp, INADDRSZ);
00356 }
00357
else
00358 memcpy (*npp, *cpp, af == AF_INET ? INADDRSZ : IN6ADDRSZ);
00359 cpp++;
00360 npp++;
00361 }
00362 }
00363
00364 he->h_aliases = calloc (names *
sizeof(
char*), 1);
00365
if (!he->h_aliases)
00366
goto cleanup1;
00367
00368
00369
00370 npp = he->h_aliases;
00371 cpp = (he1 ? he1->h_aliases : he2->h_aliases);
00372
while (*cpp)
00373 {
00374 *npp = strdup (*cpp);
00375
if (!*npp)
00376
goto cleanup2;
00377 npp++;
00378 cpp++;
00379 }
00380
00381
00382
00383
if (he1)
00384 he->h_name = strdup (he1->h_name);
00385
else he->h_name = strdup (he2->h_name);
00386
00387
if (!he->h_name)
00388
goto cleanup2;
00389
00390 he->h_addrtype = af;
00391 he->h_length = (af == AF_INET ? INADDRSZ : IN6ADDRSZ);
00392
return (he);
00393
00394 cleanup2:
00395
for (cpp = he->h_aliases; *cpp; *cpp++ = NULL)
00396 free (*cpp);
00397 free (he->h_aliases);
00398
00399 cleanup1:
00400
for (cpp = he->h_addr_list; *cpp; *cpp++ = NULL)
00401 free (*cpp);
00402 free (he->h_addr_list);
00403
00404 cleanup0:
00405 free (he);
00406 *error = NO_RECOVERY;
00407
return (NULL);
00408 }
00409
#endif