]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/nss-resolve/nss-resolve.c
tree-wide: drop 'This file is part of systemd' blurb
[thirdparty/systemd.git] / src / nss-resolve / nss-resolve.c
CommitLineData
53e1b683 1/* SPDX-License-Identifier: LGPL-2.1+ */
4d1cf1e2 2/***
4d1cf1e2 3 Copyright 2014 Lennart Poettering
4d1cf1e2
LP
4***/
5
4d1cf1e2 6#include <errno.h>
07630cea
LP
7#include <netdb.h>
8#include <nss.h>
4d1cf1e2 9#include <stdlib.h>
07630cea 10#include <string.h>
4d1cf1e2
LP
11
12#include "sd-bus.h"
07630cea 13
96aad8d1 14#include "bus-common-errors.h"
07630cea 15#include "in-addr-util.h"
4d1cf1e2
LP
16#include "macro.h"
17#include "nss-util.h"
4cbfd62b 18#include "resolved-def.h"
07630cea 19#include "string-util.h"
4d1cf1e2 20#include "util.h"
0c5eb056 21#include "signal-util.h"
4d1cf1e2
LP
22
23NSS_GETHOSTBYNAME_PROTOTYPES(resolve);
24NSS_GETHOSTBYADDR_PROTOTYPES(resolve);
25
7c2a5e26
LP
26static bool bus_error_shall_fallback(sd_bus_error *e) {
27 return sd_bus_error_has_name(e, SD_BUS_ERROR_SERVICE_UNKNOWN) ||
28 sd_bus_error_has_name(e, SD_BUS_ERROR_NAME_HAS_NO_OWNER) ||
29 sd_bus_error_has_name(e, SD_BUS_ERROR_NO_REPLY) ||
30 sd_bus_error_has_name(e, SD_BUS_ERROR_ACCESS_DENIED);
31}
32
0dd25fb9 33static int count_addresses(sd_bus_message *m, int af, const char **canonical) {
78c6a153 34 int c = 0, r;
4d1cf1e2
LP
35
36 assert(m);
309e9d86
LP
37 assert(canonical);
38
78c6a153 39 r = sd_bus_message_enter_container(m, 'a', "(iiay)");
309e9d86
LP
40 if (r < 0)
41 return r;
4d1cf1e2 42
78c6a153
LP
43 while ((r = sd_bus_message_enter_container(m, 'r', "iiay")) > 0) {
44 int family, ifindex;
51323288 45
78c6a153 46 assert_cc(sizeof(int32_t) == sizeof(int));
4d1cf1e2 47
78c6a153 48 r = sd_bus_message_read(m, "ii", &ifindex, &family);
4d1cf1e2
LP
49 if (r < 0)
50 return r;
51
51323288 52 r = sd_bus_message_skip(m, "ay");
4d1cf1e2
LP
53 if (r < 0)
54 return r;
55
56 r = sd_bus_message_exit_container(m);
57 if (r < 0)
58 return r;
59
60 if (af != AF_UNSPEC && family != af)
61 continue;
62
313cefa1 63 c++;
4d1cf1e2
LP
64 }
65 if (r < 0)
66 return r;
67
309e9d86
LP
68 r = sd_bus_message_exit_container(m);
69 if (r < 0)
70 return r;
71
72 r = sd_bus_message_read(m, "s", canonical);
4d1cf1e2
LP
73 if (r < 0)
74 return r;
75
309e9d86
LP
76 r = sd_bus_message_rewind(m, true);
77 if (r < 0)
78 return r;
79
80 return c;
4d1cf1e2
LP
81}
82
27007eff
LP
83static uint32_t ifindex_to_scopeid(int family, const void *a, int ifindex) {
84 struct in6_addr in6;
85
86 if (family != AF_INET6)
87 return 0;
88
89 /* Some apps can't deal with the scope ID attached to non-link-local addresses. Hence, let's suppress that. */
90
11814bbb 91 assert(sizeof(in6) == FAMILY_ADDRESS_SIZE(AF_INET6));
27007eff
LP
92 memcpy(&in6, a, sizeof(struct in6_addr));
93
94 return IN6_IS_ADDR_LINKLOCAL(&in6) ? ifindex : 0;
95}
96
4d1cf1e2
LP
97enum nss_status _nss_resolve_gethostbyname4_r(
98 const char *name,
99 struct gaih_addrtuple **pat,
100 char *buffer, size_t buflen,
101 int *errnop, int *h_errnop,
102 int32_t *ttlp) {
103
4afd3348
LP
104 _cleanup_(sd_bus_message_unrefp) sd_bus_message *req = NULL, *reply = NULL;
105 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
4d1cf1e2 106 struct gaih_addrtuple *r_tuple, *r_tuple_first = NULL;
4afd3348 107 _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
344874fc 108 enum nss_status ret = NSS_STATUS_UNAVAIL;
309e9d86 109 const char *canonical = NULL;
4d1cf1e2
LP
110 size_t l, ms, idx;
111 char *r_name;
78c6a153 112 int c, r, i = 0;
4d1cf1e2 113
0c5eb056
LP
114 BLOCK_SIGNALS(NSS_SIGNALS_BLOCK);
115
4d1cf1e2
LP
116 assert(name);
117 assert(pat);
118 assert(buffer);
119 assert(errnop);
120 assert(h_errnop);
121
122 r = sd_bus_open_system(&bus);
123 if (r < 0)
5486a31d 124 goto fail;
4d1cf1e2
LP
125
126 r = sd_bus_message_new_method_call(
127 bus,
128 &req,
129 "org.freedesktop.resolve1",
130 "/org/freedesktop/resolve1",
131 "org.freedesktop.resolve1.Manager",
132 "ResolveHostname");
133 if (r < 0)
134 goto fail;
135
136 r = sd_bus_message_set_auto_start(req, false);
137 if (r < 0)
138 goto fail;
139
51323288 140 r = sd_bus_message_append(req, "isit", 0, name, AF_UNSPEC, (uint64_t) 0);
4d1cf1e2
LP
141 if (r < 0)
142 goto fail;
143
4cbfd62b 144 r = sd_bus_call(bus, req, SD_RESOLVED_QUERY_TIMEOUT_USEC, &error, &reply);
4d1cf1e2
LP
145 if (r < 0) {
146 if (sd_bus_error_has_name(&error, _BUS_ERROR_DNS "NXDOMAIN")) {
147 *errnop = ESRCH;
148 *h_errnop = HOST_NOT_FOUND;
149 return NSS_STATUS_NOTFOUND;
150 }
151
5486a31d
ZJS
152 /* Return NSS_STATUS_UNAVAIL when communication with systemd-resolved fails,
153 allowing falling back to other nss modules. Treat all other error conditions as
154 NOTFOUND. This includes DNSSEC errors and suchlike. (We don't use UNAVAIL in this
155 case so that the nsswitch.conf configuration can distuingish such executed but
156 negative replies from complete failure to talk to resolved). */
157 if (!bus_error_shall_fallback(&error))
158 ret = NSS_STATUS_NOTFOUND;
7c2a5e26 159
a464cf80 160 goto fail;
4d1cf1e2
LP
161 }
162
309e9d86
LP
163 c = count_addresses(reply, AF_UNSPEC, &canonical);
164 if (c < 0) {
165 r = c;
4d1cf1e2 166 goto fail;
309e9d86
LP
167 }
168 if (c == 0) {
4d1cf1e2
LP
169 *errnop = ESRCH;
170 *h_errnop = HOST_NOT_FOUND;
171 return NSS_STATUS_NOTFOUND;
172 }
173
309e9d86
LP
174 if (isempty(canonical))
175 canonical = name;
176
177 l = strlen(canonical);
4d1cf1e2
LP
178 ms = ALIGN(l+1) + ALIGN(sizeof(struct gaih_addrtuple)) * c;
179 if (buflen < ms) {
e36c6e48
MV
180 *errnop = ERANGE;
181 *h_errnop = NETDB_INTERNAL;
4d1cf1e2
LP
182 return NSS_STATUS_TRYAGAIN;
183 }
184
185 /* First, append name */
186 r_name = buffer;
309e9d86 187 memcpy(r_name, canonical, l+1);
4d1cf1e2
LP
188 idx = ALIGN(l+1);
189
190 /* Second, append addresses */
191 r_tuple_first = (struct gaih_addrtuple*) (buffer + idx);
309e9d86 192
78c6a153 193 r = sd_bus_message_enter_container(reply, 'a', "(iiay)");
309e9d86
LP
194 if (r < 0)
195 goto fail;
196
78c6a153
LP
197 while ((r = sd_bus_message_enter_container(reply, 'r', "iiay")) > 0) {
198 int family, ifindex;
4d1cf1e2 199 const void *a;
4d1cf1e2
LP
200 size_t sz;
201
78c6a153
LP
202 assert_cc(sizeof(int32_t) == sizeof(int));
203
204 r = sd_bus_message_read(reply, "ii", &ifindex, &family);
4d1cf1e2
LP
205 if (r < 0)
206 goto fail;
207
78c6a153
LP
208 if (ifindex < 0) {
209 r = -EINVAL;
210 goto fail;
211 }
212
4d1cf1e2
LP
213 r = sd_bus_message_read_array(reply, 'y', &a, &sz);
214 if (r < 0)
215 goto fail;
216
4d1cf1e2
LP
217 r = sd_bus_message_exit_container(reply);
218 if (r < 0)
219 goto fail;
220
221 if (!IN_SET(family, AF_INET, AF_INET6))
222 continue;
223
9d485985 224 if (sz != FAMILY_ADDRESS_SIZE(family)) {
4d1cf1e2
LP
225 r = -EINVAL;
226 goto fail;
227 }
228
4d1cf1e2
LP
229 r_tuple = (struct gaih_addrtuple*) (buffer + idx);
230 r_tuple->next = i == c-1 ? NULL : (struct gaih_addrtuple*) ((char*) r_tuple + ALIGN(sizeof(struct gaih_addrtuple)));
231 r_tuple->name = r_name;
232 r_tuple->family = family;
27007eff 233 r_tuple->scopeid = ifindex_to_scopeid(family, a, ifindex);
4d1cf1e2
LP
234 memcpy(r_tuple->addr, a, sz);
235
236 idx += ALIGN(sizeof(struct gaih_addrtuple));
237 i++;
238 }
4d1cf1e2
LP
239 if (r < 0)
240 goto fail;
241
309e9d86 242 assert(i == c);
4d1cf1e2
LP
243 assert(idx == ms);
244
245 if (*pat)
246 **pat = *r_tuple_first;
247 else
248 *pat = r_tuple_first;
249
250 if (ttlp)
251 *ttlp = 0;
252
e70df46b
LP
253 /* Explicitly reset all error variables */
254 *errnop = 0;
255 *h_errnop = NETDB_SUCCESS;
256 h_errno = 0;
257
4d1cf1e2
LP
258 return NSS_STATUS_SUCCESS;
259
260fail:
261 *errnop = -r;
a464cf80 262 *h_errnop = NO_RECOVERY;
344874fc 263 return ret;
4d1cf1e2
LP
264}
265
266enum nss_status _nss_resolve_gethostbyname3_r(
267 const char *name,
268 int af,
269 struct hostent *result,
270 char *buffer, size_t buflen,
271 int *errnop, int *h_errnop,
272 int32_t *ttlp,
273 char **canonp) {
274
4afd3348
LP
275 _cleanup_(sd_bus_message_unrefp) sd_bus_message *req = NULL, *reply = NULL;
276 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
4d1cf1e2 277 char *r_name, *r_aliases, *r_addr, *r_addr_list;
4afd3348 278 _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
344874fc 279 enum nss_status ret = NSS_STATUS_UNAVAIL;
4d1cf1e2 280 size_t l, idx, ms, alen;
309e9d86 281 const char *canonical;
78c6a153 282 int c, r, i = 0;
4d1cf1e2 283
0c5eb056
LP
284 BLOCK_SIGNALS(NSS_SIGNALS_BLOCK);
285
4d1cf1e2
LP
286 assert(name);
287 assert(result);
288 assert(buffer);
289 assert(errnop);
290 assert(h_errnop);
291
292 if (af == AF_UNSPEC)
293 af = AF_INET;
294
4c701096 295 if (!IN_SET(af, AF_INET, AF_INET6)) {
4d1cf1e2
LP
296 r = -EAFNOSUPPORT;
297 goto fail;
298 }
299
300 r = sd_bus_open_system(&bus);
301 if (r < 0)
5486a31d 302 goto fail;
4d1cf1e2
LP
303
304 r = sd_bus_message_new_method_call(
305 bus,
306 &req,
307 "org.freedesktop.resolve1",
308 "/org/freedesktop/resolve1",
309 "org.freedesktop.resolve1.Manager",
310 "ResolveHostname");
311 if (r < 0)
312 goto fail;
313
314 r = sd_bus_message_set_auto_start(req, false);
315 if (r < 0)
316 goto fail;
317
51323288 318 r = sd_bus_message_append(req, "isit", 0, name, af, (uint64_t) 0);
4d1cf1e2
LP
319 if (r < 0)
320 goto fail;
321
4cbfd62b 322 r = sd_bus_call(bus, req, SD_RESOLVED_QUERY_TIMEOUT_USEC, &error, &reply);
4d1cf1e2
LP
323 if (r < 0) {
324 if (sd_bus_error_has_name(&error, _BUS_ERROR_DNS "NXDOMAIN")) {
325 *errnop = ESRCH;
326 *h_errnop = HOST_NOT_FOUND;
327 return NSS_STATUS_NOTFOUND;
328 }
329
5486a31d
ZJS
330 if (!bus_error_shall_fallback(&error))
331 ret = NSS_STATUS_NOTFOUND;
7c2a5e26 332
a464cf80 333 goto fail;
4d1cf1e2
LP
334 }
335
309e9d86
LP
336 c = count_addresses(reply, af, &canonical);
337 if (c < 0) {
338 r = c;
4d1cf1e2 339 goto fail;
309e9d86
LP
340 }
341 if (c == 0) {
4d1cf1e2
LP
342 *errnop = ESRCH;
343 *h_errnop = HOST_NOT_FOUND;
344 return NSS_STATUS_NOTFOUND;
345 }
346
309e9d86
LP
347 if (isempty(canonical))
348 canonical = name;
349
9d485985 350 alen = FAMILY_ADDRESS_SIZE(af);
309e9d86 351 l = strlen(canonical);
4d1cf1e2 352
66a16e7e 353 ms = ALIGN(l+1) + c * ALIGN(alen) + (c+2) * sizeof(char*);
4d1cf1e2
LP
354
355 if (buflen < ms) {
e36c6e48
MV
356 *errnop = ERANGE;
357 *h_errnop = NETDB_INTERNAL;
4d1cf1e2
LP
358 return NSS_STATUS_TRYAGAIN;
359 }
360
361 /* First, append name */
362 r_name = buffer;
309e9d86 363 memcpy(r_name, canonical, l+1);
4d1cf1e2
LP
364 idx = ALIGN(l+1);
365
309e9d86 366 /* Second, create empty aliases array */
4d1cf1e2
LP
367 r_aliases = buffer + idx;
368 ((char**) r_aliases)[0] = NULL;
369 idx += sizeof(char*);
370
371 /* Third, append addresses */
372 r_addr = buffer + idx;
309e9d86 373
78c6a153 374 r = sd_bus_message_enter_container(reply, 'a', "(iiay)");
51323288
LP
375 if (r < 0)
376 goto fail;
377
78c6a153
LP
378 while ((r = sd_bus_message_enter_container(reply, 'r', "iiay")) > 0) {
379 int ifindex, family;
4d1cf1e2 380 const void *a;
4d1cf1e2
LP
381 size_t sz;
382
78c6a153 383 r = sd_bus_message_read(reply, "ii", &ifindex, &family);
4d1cf1e2
LP
384 if (r < 0)
385 goto fail;
386
78c6a153
LP
387 if (ifindex < 0) {
388 r = -EINVAL;
389 goto fail;
390 }
391
4d1cf1e2
LP
392 r = sd_bus_message_read_array(reply, 'y', &a, &sz);
393 if (r < 0)
394 goto fail;
395
4d1cf1e2
LP
396 r = sd_bus_message_exit_container(reply);
397 if (r < 0)
398 goto fail;
399
400 if (family != af)
401 continue;
402
403 if (sz != alen) {
404 r = -EINVAL;
405 goto fail;
406 }
407
4d1cf1e2
LP
408 memcpy(r_addr + i*ALIGN(alen), a, alen);
409 i++;
410 }
309e9d86
LP
411 if (r < 0)
412 goto fail;
4d1cf1e2
LP
413
414 assert(i == c);
415 idx += c * ALIGN(alen);
416
309e9d86 417 /* Fourth, append address pointer array */
4d1cf1e2
LP
418 r_addr_list = buffer + idx;
419 for (i = 0; i < c; i++)
420 ((char**) r_addr_list)[i] = r_addr + i*ALIGN(alen);
421
422 ((char**) r_addr_list)[i] = NULL;
423 idx += (c+1) * sizeof(char*);
424
425 assert(idx == ms);
426
427 result->h_name = r_name;
428 result->h_aliases = (char**) r_aliases;
429 result->h_addrtype = af;
430 result->h_length = alen;
431 result->h_addr_list = (char**) r_addr_list;
432
e70df46b
LP
433 /* Explicitly reset all error variables */
434 *errnop = 0;
435 *h_errnop = NETDB_SUCCESS;
436 h_errno = 0;
437
4d1cf1e2
LP
438 if (ttlp)
439 *ttlp = 0;
440
441 if (canonp)
442 *canonp = r_name;
443
444 return NSS_STATUS_SUCCESS;
445
446fail:
447 *errnop = -r;
a464cf80 448 *h_errnop = NO_RECOVERY;
344874fc 449 return ret;
4d1cf1e2
LP
450}
451
452enum nss_status _nss_resolve_gethostbyaddr2_r(
453 const void* addr, socklen_t len,
454 int af,
455 struct hostent *result,
456 char *buffer, size_t buflen,
457 int *errnop, int *h_errnop,
458 int32_t *ttlp) {
459
4afd3348
LP
460 _cleanup_(sd_bus_message_unrefp) sd_bus_message *req = NULL, *reply = NULL;
461 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
4d1cf1e2 462 char *r_name, *r_aliases, *r_addr, *r_addr_list;
4afd3348 463 _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
344874fc 464 enum nss_status ret = NSS_STATUS_UNAVAIL;
4d1cf1e2
LP
465 unsigned c = 0, i = 0;
466 size_t ms = 0, idx;
467 const char *n;
51323288 468 int r, ifindex;
4d1cf1e2 469
0c5eb056
LP
470 BLOCK_SIGNALS(NSS_SIGNALS_BLOCK);
471
4d1cf1e2
LP
472 assert(addr);
473 assert(result);
474 assert(buffer);
475 assert(errnop);
476 assert(h_errnop);
477
478 if (!IN_SET(af, AF_INET, AF_INET6)) {
479 *errnop = EAFNOSUPPORT;
480 *h_errnop = NO_DATA;
481 return NSS_STATUS_UNAVAIL;
482 }
483
9d485985 484 if (len != FAMILY_ADDRESS_SIZE(af)) {
4d1cf1e2
LP
485 *errnop = EINVAL;
486 *h_errnop = NO_RECOVERY;
487 return NSS_STATUS_UNAVAIL;
488 }
489
490 r = sd_bus_open_system(&bus);
491 if (r < 0)
5486a31d 492 goto fail;
4d1cf1e2
LP
493
494 r = sd_bus_message_new_method_call(
495 bus,
496 &req,
497 "org.freedesktop.resolve1",
498 "/org/freedesktop/resolve1",
499 "org.freedesktop.resolve1.Manager",
500 "ResolveAddress");
501 if (r < 0)
502 goto fail;
503
504 r = sd_bus_message_set_auto_start(req, false);
505 if (r < 0)
506 goto fail;
507
51323288 508 r = sd_bus_message_append(req, "ii", 0, af);
4d1cf1e2
LP
509 if (r < 0)
510 goto fail;
511
512 r = sd_bus_message_append_array(req, 'y', addr, len);
513 if (r < 0)
514 goto fail;
515
51323288 516 r = sd_bus_message_append(req, "t", (uint64_t) 0);
4d1cf1e2
LP
517 if (r < 0)
518 goto fail;
519
4cbfd62b 520 r = sd_bus_call(bus, req, SD_RESOLVED_QUERY_TIMEOUT_USEC, &error, &reply);
4d1cf1e2
LP
521 if (r < 0) {
522 if (sd_bus_error_has_name(&error, _BUS_ERROR_DNS "NXDOMAIN")) {
523 *errnop = ESRCH;
524 *h_errnop = HOST_NOT_FOUND;
525 return NSS_STATUS_NOTFOUND;
526 }
527
5486a31d
ZJS
528 if (!bus_error_shall_fallback(&error))
529 ret = NSS_STATUS_NOTFOUND;
7c2a5e26 530
46c7a7ac 531 goto fail;
4d1cf1e2
LP
532 }
533
78c6a153 534 r = sd_bus_message_enter_container(reply, 'a', "(is)");
51323288
LP
535 if (r < 0)
536 goto fail;
537
78c6a153 538 while ((r = sd_bus_message_read(reply, "(is)", &ifindex, &n)) > 0) {
51323288 539
78c6a153
LP
540 if (ifindex < 0) {
541 r = -EINVAL;
542 goto fail;
543 }
4d1cf1e2 544
4d1cf1e2
LP
545 c++;
546 ms += ALIGN(strlen(n) + 1);
547 }
548 if (r < 0)
549 goto fail;
550
551 r = sd_bus_message_rewind(reply, false);
552 if (r < 0)
553 return r;
554
555 if (c <= 0) {
556 *errnop = ESRCH;
557 *h_errnop = HOST_NOT_FOUND;
558 return NSS_STATUS_NOTFOUND;
559 }
560
561 ms += ALIGN(len) + /* the address */
562 2 * sizeof(char*) + /* pointers to the address, plus trailing NULL */
563 c * sizeof(char*); /* pointers to aliases, plus trailing NULL */
564
565 if (buflen < ms) {
e36c6e48
MV
566 *errnop = ERANGE;
567 *h_errnop = NETDB_INTERNAL;
4d1cf1e2
LP
568 return NSS_STATUS_TRYAGAIN;
569 }
570
571 /* First, place address */
572 r_addr = buffer;
573 memcpy(r_addr, addr, len);
574 idx = ALIGN(len);
575
576 /* Second, place address list */
577 r_addr_list = buffer + idx;
578 ((char**) r_addr_list)[0] = r_addr;
579 ((char**) r_addr_list)[1] = NULL;
580 idx += sizeof(char*) * 2;
581
582 /* Third, reserve space for the aliases array */
583 r_aliases = buffer + idx;
584 idx += sizeof(char*) * c;
585
586 /* Fourth, place aliases */
587 i = 0;
588 r_name = buffer + idx;
78c6a153 589 while ((r = sd_bus_message_read(reply, "(is)", &ifindex, &n)) > 0) {
4d1cf1e2
LP
590 char *p;
591 size_t l;
592
593 l = strlen(n);
594 p = buffer + idx;
595 memcpy(p, n, l+1);
596
963783d7 597 if (i > 0)
4d1cf1e2
LP
598 ((char**) r_aliases)[i-1] = p;
599 i++;
600
601 idx += ALIGN(l+1);
602 }
309e9d86
LP
603 if (r < 0)
604 goto fail;
4d1cf1e2
LP
605
606 ((char**) r_aliases)[c-1] = NULL;
607 assert(idx == ms);
608
609 result->h_name = r_name;
610 result->h_aliases = (char**) r_aliases;
611 result->h_addrtype = af;
612 result->h_length = len;
613 result->h_addr_list = (char**) r_addr_list;
614
615 if (ttlp)
616 *ttlp = 0;
617
e70df46b
LP
618 /* Explicitly reset all error variables */
619 *errnop = 0;
620 *h_errnop = NETDB_SUCCESS;
621 h_errno = 0;
622
4d1cf1e2
LP
623 return NSS_STATUS_SUCCESS;
624
625fail:
626 *errnop = -r;
a464cf80 627 *h_errnop = NO_RECOVERY;
344874fc 628 return ret;
4d1cf1e2
LP
629}
630
631NSS_GETHOSTBYNAME_FALLBACKS(resolve);
632NSS_GETHOSTBYADDR_FALLBACKS(resolve);