]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/nss-resolve/nss-resolve.c
resolved: make DnsQuestion logic handle NULL arrays as empty arrays
[thirdparty/systemd.git] / src / nss-resolve / nss-resolve.c
CommitLineData
4d1cf1e2
LP
1/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3/***
4 This file is part of systemd.
5
6 Copyright 2014 Lennart Poettering
7
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
12
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
17
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20***/
21
4d1cf1e2 22#include <nss.h>
4d1cf1e2
LP
23#include <netdb.h>
24#include <errno.h>
25#include <string.h>
4d1cf1e2 26#include <stdlib.h>
7c2a5e26 27#include <dlfcn.h>
4d1cf1e2
LP
28
29#include "sd-bus.h"
30#include "bus-util.h"
96aad8d1 31#include "bus-common-errors.h"
4d1cf1e2
LP
32#include "macro.h"
33#include "nss-util.h"
34#include "util.h"
35#include "in-addr-util.h"
36
37NSS_GETHOSTBYNAME_PROTOTYPES(resolve);
38NSS_GETHOSTBYADDR_PROTOTYPES(resolve);
39
40#define DNS_CALL_TIMEOUT_USEC (45*USEC_PER_SEC)
41
7c2a5e26
LP
42typedef void (*voidfunc_t)(void);
43
44static voidfunc_t find_fallback(const char *module, const char *symbol) {
45 void *dl;
46
47 /* Try to find a fallback NSS module symbol */
48
49 dl = dlopen(module, RTLD_LAZY|RTLD_NODELETE);
50 if (!dl)
51 return NULL;
52
53 return dlsym(dl, symbol);
54}
55
56static bool bus_error_shall_fallback(sd_bus_error *e) {
57 return sd_bus_error_has_name(e, SD_BUS_ERROR_SERVICE_UNKNOWN) ||
58 sd_bus_error_has_name(e, SD_BUS_ERROR_NAME_HAS_NO_OWNER) ||
59 sd_bus_error_has_name(e, SD_BUS_ERROR_NO_REPLY) ||
60 sd_bus_error_has_name(e, SD_BUS_ERROR_ACCESS_DENIED);
61}
62
0dd25fb9 63static int count_addresses(sd_bus_message *m, int af, const char **canonical) {
51323288 64 int c = 0, r, ifindex;
4d1cf1e2
LP
65
66 assert(m);
309e9d86
LP
67 assert(canonical);
68
51323288 69 r = sd_bus_message_read(m, "i", &ifindex);
309e9d86
LP
70 if (r < 0)
71 return r;
4d1cf1e2 72
51323288
LP
73 r = sd_bus_message_enter_container(m, 'a', "(iay)");
74 if (r < 0)
75 return r;
76
77 while ((r = sd_bus_message_enter_container(m, 'r', "iay")) > 0) {
0dd25fb9 78 int family;
4d1cf1e2 79
0dd25fb9 80 r = sd_bus_message_read(m, "i", &family);
4d1cf1e2
LP
81 if (r < 0)
82 return r;
83
51323288 84 r = sd_bus_message_skip(m, "ay");
4d1cf1e2
LP
85 if (r < 0)
86 return r;
87
88 r = sd_bus_message_exit_container(m);
89 if (r < 0)
90 return r;
91
92 if (af != AF_UNSPEC && family != af)
93 continue;
94
95 c ++;
96 }
97 if (r < 0)
98 return r;
99
309e9d86
LP
100 r = sd_bus_message_exit_container(m);
101 if (r < 0)
102 return r;
103
104 r = sd_bus_message_read(m, "s", canonical);
4d1cf1e2
LP
105 if (r < 0)
106 return r;
107
309e9d86
LP
108 r = sd_bus_message_rewind(m, true);
109 if (r < 0)
110 return r;
111
112 return c;
4d1cf1e2
LP
113}
114
115enum nss_status _nss_resolve_gethostbyname4_r(
116 const char *name,
117 struct gaih_addrtuple **pat,
118 char *buffer, size_t buflen,
119 int *errnop, int *h_errnop,
120 int32_t *ttlp) {
121
122 _cleanup_bus_message_unref_ sd_bus_message *req = NULL, *reply = NULL;
123 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
124 struct gaih_addrtuple *r_tuple, *r_tuple_first = NULL;
03976f7b 125 _cleanup_bus_flush_close_unref_ sd_bus *bus = NULL;
309e9d86 126 const char *canonical = NULL;
4d1cf1e2
LP
127 size_t l, ms, idx;
128 char *r_name;
51323288 129 int c, r, i = 0, ifindex;
4d1cf1e2
LP
130
131 assert(name);
132 assert(pat);
133 assert(buffer);
134 assert(errnop);
135 assert(h_errnop);
136
137 r = sd_bus_open_system(&bus);
138 if (r < 0)
139 goto fail;
140
141 r = sd_bus_message_new_method_call(
142 bus,
143 &req,
144 "org.freedesktop.resolve1",
145 "/org/freedesktop/resolve1",
146 "org.freedesktop.resolve1.Manager",
147 "ResolveHostname");
148 if (r < 0)
149 goto fail;
150
151 r = sd_bus_message_set_auto_start(req, false);
152 if (r < 0)
153 goto fail;
154
51323288 155 r = sd_bus_message_append(req, "isit", 0, name, AF_UNSPEC, (uint64_t) 0);
4d1cf1e2
LP
156 if (r < 0)
157 goto fail;
158
159 r = sd_bus_call(bus, req, DNS_CALL_TIMEOUT_USEC, &error, &reply);
160 if (r < 0) {
161 if (sd_bus_error_has_name(&error, _BUS_ERROR_DNS "NXDOMAIN")) {
162 *errnop = ESRCH;
163 *h_errnop = HOST_NOT_FOUND;
164 return NSS_STATUS_NOTFOUND;
165 }
166
7c2a5e26
LP
167 if (bus_error_shall_fallback(&error)) {
168
169 enum nss_status (*fallback)(
170 const char *name,
171 struct gaih_addrtuple **pat,
172 char *buffer, size_t buflen,
173 int *errnop, int *h_errnop,
174 int32_t *ttlp);
175
176 fallback = (enum nss_status (*)(const char *name,
177 struct gaih_addrtuple **pat,
178 char *buffer, size_t buflen,
179 int *errnop, int *h_errnop,
180 int32_t *ttlp))
181 find_fallback("libnss_dns.so.2", "_nss_dns_gethostbyname4_r");
182 if (fallback)
183 return fallback(name, pat, buffer, buflen, errnop, h_errnop, ttlp);
184 }
185
4d1cf1e2
LP
186 *errnop = -r;
187 *h_errnop = NO_RECOVERY;
188 return NSS_STATUS_UNAVAIL;
189 }
190
309e9d86
LP
191 c = count_addresses(reply, AF_UNSPEC, &canonical);
192 if (c < 0) {
193 r = c;
4d1cf1e2 194 goto fail;
309e9d86
LP
195 }
196 if (c == 0) {
4d1cf1e2
LP
197 *errnop = ESRCH;
198 *h_errnop = HOST_NOT_FOUND;
199 return NSS_STATUS_NOTFOUND;
200 }
201
309e9d86
LP
202 if (isempty(canonical))
203 canonical = name;
204
205 l = strlen(canonical);
4d1cf1e2
LP
206 ms = ALIGN(l+1) + ALIGN(sizeof(struct gaih_addrtuple)) * c;
207 if (buflen < ms) {
208 *errnop = ENOMEM;
209 *h_errnop = TRY_AGAIN;
210 return NSS_STATUS_TRYAGAIN;
211 }
212
213 /* First, append name */
214 r_name = buffer;
309e9d86 215 memcpy(r_name, canonical, l+1);
4d1cf1e2
LP
216 idx = ALIGN(l+1);
217
218 /* Second, append addresses */
219 r_tuple_first = (struct gaih_addrtuple*) (buffer + idx);
309e9d86 220
51323288
LP
221 r = sd_bus_message_read(reply, "i", &ifindex);
222 if (r < 0)
223 goto fail;
224
225 if (ifindex < 0) {
226 r = -EINVAL;
227 goto fail;
228 }
229
230 r = sd_bus_message_enter_container(reply, 'a', "(iay)");
309e9d86
LP
231 if (r < 0)
232 goto fail;
233
51323288
LP
234 while ((r = sd_bus_message_enter_container(reply, 'r', "iay")) > 0) {
235 int family;
4d1cf1e2 236 const void *a;
4d1cf1e2
LP
237 size_t sz;
238
0dd25fb9 239 r = sd_bus_message_read(reply, "i", &family);
4d1cf1e2
LP
240 if (r < 0)
241 goto fail;
242
243 r = sd_bus_message_read_array(reply, 'y', &a, &sz);
244 if (r < 0)
245 goto fail;
246
4d1cf1e2
LP
247 r = sd_bus_message_exit_container(reply);
248 if (r < 0)
249 goto fail;
250
251 if (!IN_SET(family, AF_INET, AF_INET6))
252 continue;
253
9d485985 254 if (sz != FAMILY_ADDRESS_SIZE(family)) {
4d1cf1e2
LP
255 r = -EINVAL;
256 goto fail;
257 }
258
4d1cf1e2
LP
259 r_tuple = (struct gaih_addrtuple*) (buffer + idx);
260 r_tuple->next = i == c-1 ? NULL : (struct gaih_addrtuple*) ((char*) r_tuple + ALIGN(sizeof(struct gaih_addrtuple)));
261 r_tuple->name = r_name;
262 r_tuple->family = family;
263 r_tuple->scopeid = ifindex;
264 memcpy(r_tuple->addr, a, sz);
265
266 idx += ALIGN(sizeof(struct gaih_addrtuple));
267 i++;
268 }
4d1cf1e2
LP
269 if (r < 0)
270 goto fail;
271
309e9d86 272 assert(i == c);
4d1cf1e2
LP
273 assert(idx == ms);
274
275 if (*pat)
276 **pat = *r_tuple_first;
277 else
278 *pat = r_tuple_first;
279
280 if (ttlp)
281 *ttlp = 0;
282
e70df46b
LP
283 /* Explicitly reset all error variables */
284 *errnop = 0;
285 *h_errnop = NETDB_SUCCESS;
286 h_errno = 0;
287
4d1cf1e2
LP
288 return NSS_STATUS_SUCCESS;
289
290fail:
291 *errnop = -r;
292 *h_errnop = NO_DATA;
293 return NSS_STATUS_UNAVAIL;
294}
295
296enum nss_status _nss_resolve_gethostbyname3_r(
297 const char *name,
298 int af,
299 struct hostent *result,
300 char *buffer, size_t buflen,
301 int *errnop, int *h_errnop,
302 int32_t *ttlp,
303 char **canonp) {
304
305 _cleanup_bus_message_unref_ sd_bus_message *req = NULL, *reply = NULL;
306 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
307 char *r_name, *r_aliases, *r_addr, *r_addr_list;
03976f7b 308 _cleanup_bus_flush_close_unref_ sd_bus *bus = NULL;
4d1cf1e2 309 size_t l, idx, ms, alen;
309e9d86 310 const char *canonical;
51323288 311 int c, r, i = 0, ifindex;
4d1cf1e2
LP
312
313 assert(name);
314 assert(result);
315 assert(buffer);
316 assert(errnop);
317 assert(h_errnop);
318
319 if (af == AF_UNSPEC)
320 af = AF_INET;
321
322 if (af != AF_INET && af != AF_INET6) {
323 r = -EAFNOSUPPORT;
324 goto fail;
325 }
326
327 r = sd_bus_open_system(&bus);
328 if (r < 0)
329 goto fail;
330
331 r = sd_bus_message_new_method_call(
332 bus,
333 &req,
334 "org.freedesktop.resolve1",
335 "/org/freedesktop/resolve1",
336 "org.freedesktop.resolve1.Manager",
337 "ResolveHostname");
338 if (r < 0)
339 goto fail;
340
341 r = sd_bus_message_set_auto_start(req, false);
342 if (r < 0)
343 goto fail;
344
51323288 345 r = sd_bus_message_append(req, "isit", 0, name, af, (uint64_t) 0);
4d1cf1e2
LP
346 if (r < 0)
347 goto fail;
348
349 r = sd_bus_call(bus, req, DNS_CALL_TIMEOUT_USEC, &error, &reply);
350 if (r < 0) {
351 if (sd_bus_error_has_name(&error, _BUS_ERROR_DNS "NXDOMAIN")) {
352 *errnop = ESRCH;
353 *h_errnop = HOST_NOT_FOUND;
354 return NSS_STATUS_NOTFOUND;
355 }
356
7c2a5e26
LP
357 if (bus_error_shall_fallback(&error)) {
358
359 enum nss_status (*fallback)(
360 const char *name,
361 int af,
362 struct hostent *result,
363 char *buffer, size_t buflen,
364 int *errnop, int *h_errnop,
365 int32_t *ttlp,
366 char **canonp);
367
920b52e4
TA
368 fallback = (enum nss_status (*)(const char *name,
369 int af,
370 struct hostent *result,
371 char *buffer, size_t buflen,
372 int *errnop, int *h_errnop,
373 int32_t *ttlp,
374 char **canonp))
7c2a5e26
LP
375 find_fallback("libnss_dns.so.2", "_nss_dns_gethostbyname3_r");
376 if (fallback)
377 return fallback(name, af, result, buffer, buflen, errnop, h_errnop, ttlp, canonp);
378 }
379
4d1cf1e2
LP
380 *errnop = -r;
381 *h_errnop = NO_RECOVERY;
382 return NSS_STATUS_UNAVAIL;
383 }
384
309e9d86
LP
385 c = count_addresses(reply, af, &canonical);
386 if (c < 0) {
387 r = c;
4d1cf1e2 388 goto fail;
309e9d86
LP
389 }
390 if (c == 0) {
4d1cf1e2
LP
391 *errnop = ESRCH;
392 *h_errnop = HOST_NOT_FOUND;
393 return NSS_STATUS_NOTFOUND;
394 }
395
309e9d86
LP
396 if (isempty(canonical))
397 canonical = name;
398
9d485985 399 alen = FAMILY_ADDRESS_SIZE(af);
309e9d86 400 l = strlen(canonical);
4d1cf1e2 401
66a16e7e 402 ms = ALIGN(l+1) + c * ALIGN(alen) + (c+2) * sizeof(char*);
4d1cf1e2
LP
403
404 if (buflen < ms) {
405 *errnop = ENOMEM;
406 *h_errnop = TRY_AGAIN;
407 return NSS_STATUS_TRYAGAIN;
408 }
409
410 /* First, append name */
411 r_name = buffer;
309e9d86 412 memcpy(r_name, canonical, l+1);
4d1cf1e2
LP
413 idx = ALIGN(l+1);
414
309e9d86 415 /* Second, create empty aliases array */
4d1cf1e2
LP
416 r_aliases = buffer + idx;
417 ((char**) r_aliases)[0] = NULL;
418 idx += sizeof(char*);
419
420 /* Third, append addresses */
421 r_addr = buffer + idx;
309e9d86 422
51323288 423 r = sd_bus_message_read(reply, "i", &ifindex);
309e9d86
LP
424 if (r < 0)
425 goto fail;
426
51323288
LP
427 if (ifindex < 0) {
428 r = -EINVAL;
429 goto fail;
430 }
431
432 r = sd_bus_message_enter_container(reply, 'a', "(iay)");
433 if (r < 0)
434 goto fail;
435
436 while ((r = sd_bus_message_enter_container(reply, 'r', "iay")) > 0) {
437 int family;
4d1cf1e2 438 const void *a;
4d1cf1e2
LP
439 size_t sz;
440
0dd25fb9 441 r = sd_bus_message_read(reply, "i", &family);
4d1cf1e2
LP
442 if (r < 0)
443 goto fail;
444
445 r = sd_bus_message_read_array(reply, 'y', &a, &sz);
446 if (r < 0)
447 goto fail;
448
4d1cf1e2
LP
449 r = sd_bus_message_exit_container(reply);
450 if (r < 0)
451 goto fail;
452
453 if (family != af)
454 continue;
455
456 if (sz != alen) {
457 r = -EINVAL;
458 goto fail;
459 }
460
4d1cf1e2
LP
461 memcpy(r_addr + i*ALIGN(alen), a, alen);
462 i++;
463 }
309e9d86
LP
464 if (r < 0)
465 goto fail;
4d1cf1e2
LP
466
467 assert(i == c);
468 idx += c * ALIGN(alen);
469
309e9d86 470 /* Fourth, append address pointer array */
4d1cf1e2
LP
471 r_addr_list = buffer + idx;
472 for (i = 0; i < c; i++)
473 ((char**) r_addr_list)[i] = r_addr + i*ALIGN(alen);
474
475 ((char**) r_addr_list)[i] = NULL;
476 idx += (c+1) * sizeof(char*);
477
478 assert(idx == ms);
479
480 result->h_name = r_name;
481 result->h_aliases = (char**) r_aliases;
482 result->h_addrtype = af;
483 result->h_length = alen;
484 result->h_addr_list = (char**) r_addr_list;
485
e70df46b
LP
486 /* Explicitly reset all error variables */
487 *errnop = 0;
488 *h_errnop = NETDB_SUCCESS;
489 h_errno = 0;
490
4d1cf1e2
LP
491 if (ttlp)
492 *ttlp = 0;
493
494 if (canonp)
495 *canonp = r_name;
496
497 return NSS_STATUS_SUCCESS;
498
499fail:
500 *errnop = -r;
501 *h_errnop = NO_DATA;
502 return NSS_STATUS_UNAVAIL;
503}
504
505enum nss_status _nss_resolve_gethostbyaddr2_r(
506 const void* addr, socklen_t len,
507 int af,
508 struct hostent *result,
509 char *buffer, size_t buflen,
510 int *errnop, int *h_errnop,
511 int32_t *ttlp) {
512
513 _cleanup_bus_message_unref_ sd_bus_message *req = NULL, *reply = NULL;
514 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
515 char *r_name, *r_aliases, *r_addr, *r_addr_list;
03976f7b 516 _cleanup_bus_flush_close_unref_ sd_bus *bus = NULL;
4d1cf1e2
LP
517 unsigned c = 0, i = 0;
518 size_t ms = 0, idx;
519 const char *n;
51323288 520 int r, ifindex;
4d1cf1e2
LP
521
522 assert(addr);
523 assert(result);
524 assert(buffer);
525 assert(errnop);
526 assert(h_errnop);
527
528 if (!IN_SET(af, AF_INET, AF_INET6)) {
529 *errnop = EAFNOSUPPORT;
530 *h_errnop = NO_DATA;
531 return NSS_STATUS_UNAVAIL;
532 }
533
9d485985 534 if (len != FAMILY_ADDRESS_SIZE(af)) {
4d1cf1e2
LP
535 *errnop = EINVAL;
536 *h_errnop = NO_RECOVERY;
537 return NSS_STATUS_UNAVAIL;
538 }
539
540 r = sd_bus_open_system(&bus);
541 if (r < 0)
542 goto fail;
543
544 r = sd_bus_message_new_method_call(
545 bus,
546 &req,
547 "org.freedesktop.resolve1",
548 "/org/freedesktop/resolve1",
549 "org.freedesktop.resolve1.Manager",
550 "ResolveAddress");
551 if (r < 0)
552 goto fail;
553
554 r = sd_bus_message_set_auto_start(req, false);
555 if (r < 0)
556 goto fail;
557
51323288 558 r = sd_bus_message_append(req, "ii", 0, af);
4d1cf1e2
LP
559 if (r < 0)
560 goto fail;
561
562 r = sd_bus_message_append_array(req, 'y', addr, len);
563 if (r < 0)
564 goto fail;
565
51323288 566 r = sd_bus_message_append(req, "t", (uint64_t) 0);
4d1cf1e2
LP
567 if (r < 0)
568 goto fail;
569
570 r = sd_bus_call(bus, req, DNS_CALL_TIMEOUT_USEC, &error, &reply);
571 if (r < 0) {
572 if (sd_bus_error_has_name(&error, _BUS_ERROR_DNS "NXDOMAIN")) {
573 *errnop = ESRCH;
574 *h_errnop = HOST_NOT_FOUND;
575 return NSS_STATUS_NOTFOUND;
576 }
577
7c2a5e26
LP
578 if (bus_error_shall_fallback(&error)) {
579
580 enum nss_status (*fallback)(
581 const void* addr, socklen_t len,
582 int af,
583 struct hostent *result,
584 char *buffer, size_t buflen,
585 int *errnop, int *h_errnop,
586 int32_t *ttlp);
587
588 fallback = (enum nss_status (*)(
589 const void* addr, socklen_t len,
590 int af,
591 struct hostent *result,
592 char *buffer, size_t buflen,
593 int *errnop, int *h_errnop,
594 int32_t *ttlp))
595 find_fallback("libnss_dns.so.2", "_nss_dns_gethostbyaddr2_r");
596
597 if (fallback)
598 return fallback(addr, len, af, result, buffer, buflen, errnop, h_errnop, ttlp);
599 }
600
4d1cf1e2
LP
601 *errnop = -r;
602 *h_errnop = NO_RECOVERY;
603 return NSS_STATUS_UNAVAIL;
604 }
605
51323288
LP
606 r = sd_bus_message_read(reply, "i", &ifindex);
607 if (r < 0)
608 goto fail;
609
610 if (ifindex < 0) {
611 r = -EINVAL;
612 goto fail;
613 }
614
4d1cf1e2
LP
615 r = sd_bus_message_enter_container(reply, 'a', "s");
616 if (r < 0)
617 goto fail;
618
619 while ((r = sd_bus_message_read(reply, "s", &n)) > 0) {
620 c++;
621 ms += ALIGN(strlen(n) + 1);
622 }
623 if (r < 0)
624 goto fail;
625
626 r = sd_bus_message_rewind(reply, false);
627 if (r < 0)
628 return r;
629
630 if (c <= 0) {
631 *errnop = ESRCH;
632 *h_errnop = HOST_NOT_FOUND;
633 return NSS_STATUS_NOTFOUND;
634 }
635
636 ms += ALIGN(len) + /* the address */
637 2 * sizeof(char*) + /* pointers to the address, plus trailing NULL */
638 c * sizeof(char*); /* pointers to aliases, plus trailing NULL */
639
640 if (buflen < ms) {
641 *errnop = ENOMEM;
642 *h_errnop = TRY_AGAIN;
643 return NSS_STATUS_TRYAGAIN;
644 }
645
646 /* First, place address */
647 r_addr = buffer;
648 memcpy(r_addr, addr, len);
649 idx = ALIGN(len);
650
651 /* Second, place address list */
652 r_addr_list = buffer + idx;
653 ((char**) r_addr_list)[0] = r_addr;
654 ((char**) r_addr_list)[1] = NULL;
655 idx += sizeof(char*) * 2;
656
657 /* Third, reserve space for the aliases array */
658 r_aliases = buffer + idx;
659 idx += sizeof(char*) * c;
660
661 /* Fourth, place aliases */
662 i = 0;
663 r_name = buffer + idx;
664 while ((r = sd_bus_message_read(reply, "s", &n)) > 0) {
665 char *p;
666 size_t l;
667
668 l = strlen(n);
669 p = buffer + idx;
670 memcpy(p, n, l+1);
671
672 if (i > 1)
673 ((char**) r_aliases)[i-1] = p;
674 i++;
675
676 idx += ALIGN(l+1);
677 }
309e9d86
LP
678 if (r < 0)
679 goto fail;
4d1cf1e2
LP
680
681 ((char**) r_aliases)[c-1] = NULL;
682 assert(idx == ms);
683
684 result->h_name = r_name;
685 result->h_aliases = (char**) r_aliases;
686 result->h_addrtype = af;
687 result->h_length = len;
688 result->h_addr_list = (char**) r_addr_list;
689
690 if (ttlp)
691 *ttlp = 0;
692
e70df46b
LP
693 /* Explicitly reset all error variables */
694 *errnop = 0;
695 *h_errnop = NETDB_SUCCESS;
696 h_errno = 0;
697
4d1cf1e2
LP
698 return NSS_STATUS_SUCCESS;
699
700fail:
701 *errnop = -r;
702 *h_errnop = NO_DATA;
703 return NSS_STATUS_UNAVAIL;
704}
705
706NSS_GETHOSTBYNAME_FALLBACKS(resolve);
707NSS_GETHOSTBYADDR_FALLBACKS(resolve);