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