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