]>
Commit | Line | Data |
---|---|---|
53e1b683 | 1 | /* SPDX-License-Identifier: LGPL-2.1+ */ |
6b21f0cf | 2 | |
6b21f0cf | 3 | #include <errno.h> |
4e8c8252 | 4 | #include <net/if.h> |
07630cea LP |
5 | #include <netdb.h> |
6 | #include <nss.h> | |
8041b5ba | 7 | #include <stdlib.h> |
8041b5ba | 8 | |
b5efdb8a | 9 | #include "alloc-util.h" |
2b2fec7d | 10 | #include "errno-util.h" |
07630cea | 11 | #include "hostname-util.h" |
e80af1bd | 12 | #include "local-addresses.h" |
1c633045 | 13 | #include "macro.h" |
c9fdc26e | 14 | #include "nss-util.h" |
0c5eb056 | 15 | #include "signal-util.h" |
07630cea | 16 | #include "string-util.h" |
4e8c8252 LP |
17 | |
18 | /* We use 127.0.0.2 as IPv4 address. This has the advantage over | |
19 | * 127.0.0.1 that it can be translated back to the local hostname. For | |
20 | * IPv6 we use ::1 which unfortunately will not translate back to the | |
3fdcecc8 | 21 | * hostname but instead something like "localhost" or so. */ |
4e8c8252 | 22 | |
8e38570e | 23 | #define LOCALADDRESS_IPV4 (htobe32(0x7F000002)) |
4e8c8252 | 24 | #define LOCALADDRESS_IPV6 &in6addr_loopback |
4e8c8252 | 25 | |
c9fdc26e LP |
26 | NSS_GETHOSTBYNAME_PROTOTYPES(myhostname); |
27 | NSS_GETHOSTBYADDR_PROTOTYPES(myhostname); | |
8041b5ba | 28 | |
4e8c8252 LP |
29 | enum nss_status _nss_myhostname_gethostbyname4_r( |
30 | const char *name, | |
31 | struct gaih_addrtuple **pat, | |
32 | char *buffer, size_t buflen, | |
33 | int *errnop, int *h_errnop, | |
34 | int32_t *ttlp) { | |
35 | ||
8041b5ba | 36 | struct gaih_addrtuple *r_tuple, *r_tuple_prev = NULL; |
e80af1bd | 37 | _cleanup_free_ struct local_address *addresses = NULL; |
5502f0d9 LP |
38 | _cleanup_free_ char *hn = NULL; |
39 | const char *canonical = NULL; | |
a1077c84 | 40 | int n_addresses = 0; |
e8a7a315 | 41 | uint32_t local_address_ipv4; |
e80af1bd | 42 | struct local_address *a; |
5502f0d9 LP |
43 | size_t l, idx, ms; |
44 | char *r_name; | |
e80af1bd | 45 | unsigned n; |
4e8c8252 | 46 | |
06202b9e | 47 | PROTECT_ERRNO; |
0c5eb056 LP |
48 | BLOCK_SIGNALS(NSS_SIGNALS_BLOCK); |
49 | ||
5502f0d9 LP |
50 | assert(name); |
51 | assert(pat); | |
52 | assert(buffer); | |
53 | assert(errnop); | |
54 | assert(h_errnop); | |
55 | ||
56 | if (is_localhost(name)) { | |
e8a7a315 LP |
57 | /* We respond to 'localhost', so that /etc/hosts |
58 | * is optional */ | |
4e8c8252 | 59 | |
e8a7a315 | 60 | canonical = "localhost"; |
8e38570e | 61 | local_address_ipv4 = htobe32(INADDR_LOOPBACK); |
e9140aff | 62 | |
46a5e0e7 | 63 | } else if (is_gateway_hostname(name)) { |
e9140aff | 64 | |
1d050e1e | 65 | n_addresses = local_gateways(NULL, 0, AF_UNSPEC, &addresses); |
e09e7ac3 LP |
66 | if (n_addresses <= 0) |
67 | goto not_found; | |
e9140aff | 68 | |
5248e7e1 | 69 | canonical = "_gateway"; |
e9140aff | 70 | |
e8a7a315 | 71 | } else { |
5502f0d9 LP |
72 | hn = gethostname_malloc(); |
73 | if (!hn) { | |
cdccd29f | 74 | UNPROTECT_ERRNO; |
0192cbdb | 75 | *errnop = ENOMEM; |
e8a7a315 | 76 | *h_errnop = NO_RECOVERY; |
5502f0d9 | 77 | return NSS_STATUS_TRYAGAIN; |
e8a7a315 LP |
78 | } |
79 | ||
38b38500 | 80 | /* We respond to our local hostname, our hostname suffixed with a single dot. */ |
e09e7ac3 LP |
81 | if (!streq(name, hn) && !streq_ptr(startswith(name, hn), ".")) |
82 | goto not_found; | |
e8a7a315 | 83 | |
1d050e1e | 84 | n_addresses = local_addresses(NULL, 0, AF_UNSPEC, &addresses); |
e80af1bd LP |
85 | if (n_addresses < 0) |
86 | n_addresses = 0; | |
e8a7a315 LP |
87 | |
88 | canonical = hn; | |
89 | local_address_ipv4 = LOCALADDRESS_IPV4; | |
90 | } | |
8041b5ba | 91 | |
e8a7a315 | 92 | l = strlen(canonical); |
5502f0d9 | 93 | ms = ALIGN(l+1) + ALIGN(sizeof(struct gaih_addrtuple)) * (n_addresses > 0 ? n_addresses : 2); |
4e8c8252 | 94 | if (buflen < ms) { |
cdccd29f | 95 | UNPROTECT_ERRNO; |
0192cbdb | 96 | *errnop = ERANGE; |
cda458a5 | 97 | *h_errnop = NETDB_INTERNAL; |
4e8c8252 LP |
98 | return NSS_STATUS_TRYAGAIN; |
99 | } | |
100 | ||
101 | /* First, fill in hostname */ | |
102 | r_name = buffer; | |
e8a7a315 | 103 | memcpy(r_name, canonical, l+1); |
4e8c8252 LP |
104 | idx = ALIGN(l+1); |
105 | ||
68a9c7c4 ZJS |
106 | assert(n_addresses >= 0); |
107 | if (n_addresses == 0) { | |
8041b5ba LP |
108 | /* Second, fill in IPv6 tuple */ |
109 | r_tuple = (struct gaih_addrtuple*) (buffer + idx); | |
110 | r_tuple->next = r_tuple_prev; | |
111 | r_tuple->name = r_name; | |
112 | r_tuple->family = AF_INET6; | |
113 | memcpy(r_tuple->addr, LOCALADDRESS_IPV6, 16); | |
a1077c84 | 114 | r_tuple->scopeid = 0; |
8041b5ba LP |
115 | |
116 | idx += ALIGN(sizeof(struct gaih_addrtuple)); | |
117 | r_tuple_prev = r_tuple; | |
118 | ||
119 | /* Third, fill in IPv4 tuple */ | |
120 | r_tuple = (struct gaih_addrtuple*) (buffer + idx); | |
121 | r_tuple->next = r_tuple_prev; | |
122 | r_tuple->name = r_name; | |
123 | r_tuple->family = AF_INET; | |
e8a7a315 | 124 | *(uint32_t*) r_tuple->addr = local_address_ipv4; |
a1077c84 | 125 | r_tuple->scopeid = 0; |
8041b5ba LP |
126 | |
127 | idx += ALIGN(sizeof(struct gaih_addrtuple)); | |
128 | r_tuple_prev = r_tuple; | |
129 | } | |
130 | ||
131 | /* Fourth, fill actual addresses in, but in backwards order */ | |
e80af1bd | 132 | for (a = addresses + n_addresses - 1, n = 0; (int) n < n_addresses; n++, a--) { |
8041b5ba LP |
133 | r_tuple = (struct gaih_addrtuple*) (buffer + idx); |
134 | r_tuple->next = r_tuple_prev; | |
135 | r_tuple->name = r_name; | |
136 | r_tuple->family = a->family; | |
a1077c84 | 137 | r_tuple->scopeid = a->family == AF_INET6 && IN6_IS_ADDR_LINKLOCAL(&a->address.in6) ? a->ifindex : 0; |
5502f0d9 | 138 | memcpy(r_tuple->addr, &a->address, 16); |
8041b5ba LP |
139 | |
140 | idx += ALIGN(sizeof(struct gaih_addrtuple)); | |
141 | r_tuple_prev = r_tuple; | |
142 | } | |
4e8c8252 LP |
143 | |
144 | /* Verify the size matches */ | |
145 | assert(idx == ms); | |
146 | ||
d2f1f23a ED |
147 | /* Nscd expects us to store the first record in **pat. */ |
148 | if (*pat) | |
149 | **pat = *r_tuple_prev; | |
150 | else | |
151 | *pat = r_tuple_prev; | |
4e8c8252 LP |
152 | |
153 | if (ttlp) | |
154 | *ttlp = 0; | |
155 | ||
06202b9e YW |
156 | /* Explicitly reset both *h_errnop and h_errno to work around |
157 | * https://bugzilla.redhat.com/show_bug.cgi?id=1125975 */ | |
e70df46b LP |
158 | *h_errnop = NETDB_SUCCESS; |
159 | h_errno = 0; | |
160 | ||
4e8c8252 | 161 | return NSS_STATUS_SUCCESS; |
e09e7ac3 LP |
162 | |
163 | not_found: | |
164 | *h_errnop = HOST_NOT_FOUND; | |
165 | return NSS_STATUS_NOTFOUND; | |
4e8c8252 | 166 | } |
6b21f0cf LP |
167 | |
168 | static enum nss_status fill_in_hostent( | |
e8a7a315 | 169 | const char *canonical, const char *additional, |
4e8c8252 | 170 | int af, |
e80af1bd | 171 | struct local_address *addresses, unsigned n_addresses, |
e8a7a315 | 172 | uint32_t local_address_ipv4, |
4e8c8252 LP |
173 | struct hostent *result, |
174 | char *buffer, size_t buflen, | |
0192cbdb | 175 | int *errnop, int *h_errnop, |
4e8c8252 LP |
176 | int32_t *ttlp, |
177 | char **canonp) { | |
178 | ||
d4c9895d | 179 | size_t l_canonical, l_additional, idx, ms, alen; |
e8a7a315 | 180 | char *r_addr, *r_name, *r_aliases, *r_alias = NULL, *r_addr_list; |
e80af1bd | 181 | struct local_address *a; |
e8a7a315 | 182 | unsigned n, c; |
8041b5ba | 183 | |
5502f0d9 LP |
184 | assert(canonical); |
185 | assert(result); | |
186 | assert(buffer); | |
187 | assert(errnop); | |
188 | assert(h_errnop); | |
189 | ||
cdccd29f LP |
190 | PROTECT_ERRNO; |
191 | ||
9d485985 | 192 | alen = FAMILY_ADDRESS_SIZE(af); |
8041b5ba | 193 | |
8041b5ba LP |
194 | for (a = addresses, n = 0, c = 0; n < n_addresses; a++, n++) |
195 | if (af == a->family) | |
196 | c++; | |
4e8c8252 | 197 | |
e8a7a315 | 198 | l_canonical = strlen(canonical); |
7bf7ce28 | 199 | l_additional = strlen_ptr(additional); |
e8a7a315 LP |
200 | ms = ALIGN(l_canonical+1)+ |
201 | (additional ? ALIGN(l_additional+1) : 0) + | |
5502f0d9 | 202 | sizeof(char*) + |
e8a7a315 | 203 | (additional ? sizeof(char*) : 0) + |
d4c9895d | 204 | (c > 0 ? c : 1) * ALIGN(alen) + |
5502f0d9 | 205 | (c > 0 ? c+1 : 2) * sizeof(char*); |
8041b5ba | 206 | |
4e8c8252 | 207 | if (buflen < ms) { |
cdccd29f | 208 | UNPROTECT_ERRNO; |
0192cbdb | 209 | *errnop = ERANGE; |
cda458a5 | 210 | *h_errnop = NETDB_INTERNAL; |
4e8c8252 LP |
211 | return NSS_STATUS_TRYAGAIN; |
212 | } | |
213 | ||
e8a7a315 | 214 | /* First, fill in hostnames */ |
4e8c8252 | 215 | r_name = buffer; |
e8a7a315 LP |
216 | memcpy(r_name, canonical, l_canonical+1); |
217 | idx = ALIGN(l_canonical+1); | |
4e8c8252 | 218 | |
e8a7a315 LP |
219 | if (additional) { |
220 | r_alias = buffer + idx; | |
221 | memcpy(r_alias, additional, l_additional+1); | |
222 | idx += ALIGN(l_additional+1); | |
223 | } | |
224 | ||
225 | /* Second, create aliases array */ | |
4e8c8252 | 226 | r_aliases = buffer + idx; |
e8a7a315 LP |
227 | if (additional) { |
228 | ((char**) r_aliases)[0] = r_alias; | |
229 | ((char**) r_aliases)[1] = NULL; | |
230 | idx += 2*sizeof(char*); | |
231 | } else { | |
232 | ((char**) r_aliases)[0] = NULL; | |
233 | idx += sizeof(char*); | |
234 | } | |
4e8c8252 | 235 | |
8041b5ba | 236 | /* Third, add addresses */ |
4e8c8252 | 237 | r_addr = buffer + idx; |
8041b5ba LP |
238 | if (c > 0) { |
239 | unsigned i = 0; | |
240 | ||
241 | for (a = addresses, n = 0; n < n_addresses; a++, n++) { | |
242 | if (af != a->family) | |
243 | continue; | |
244 | ||
5502f0d9 | 245 | memcpy(r_addr + i*ALIGN(alen), &a->address, alen); |
8041b5ba LP |
246 | i++; |
247 | } | |
248 | ||
249 | assert(i == c); | |
250 | idx += c*ALIGN(alen); | |
251 | } else { | |
252 | if (af == AF_INET) | |
e8a7a315 | 253 | *(uint32_t*) r_addr = local_address_ipv4; |
8041b5ba LP |
254 | else |
255 | memcpy(r_addr, LOCALADDRESS_IPV6, 16); | |
256 | ||
257 | idx += ALIGN(alen); | |
258 | } | |
4e8c8252 LP |
259 | |
260 | /* Fourth, add address pointer array */ | |
261 | r_addr_list = buffer + idx; | |
8041b5ba | 262 | if (c > 0) { |
d4c9895d | 263 | unsigned i; |
8041b5ba | 264 | |
d4c9895d LP |
265 | for (i = 0; i < c; i++) |
266 | ((char**) r_addr_list)[i] = r_addr + i*ALIGN(alen); | |
8041b5ba | 267 | |
d4c9895d LP |
268 | ((char**) r_addr_list)[i] = NULL; |
269 | idx += (c+1) * sizeof(char*); | |
8041b5ba LP |
270 | |
271 | } else { | |
272 | ((char**) r_addr_list)[0] = r_addr; | |
273 | ((char**) r_addr_list)[1] = NULL; | |
d4c9895d | 274 | idx += 2 * sizeof(char*); |
8041b5ba | 275 | } |
4e8c8252 LP |
276 | |
277 | /* Verify the size matches */ | |
278 | assert(idx == ms); | |
279 | ||
280 | result->h_name = r_name; | |
281 | result->h_aliases = (char**) r_aliases; | |
282 | result->h_addrtype = af; | |
283 | result->h_length = alen; | |
284 | result->h_addr_list = (char**) r_addr_list; | |
285 | ||
286 | if (ttlp) | |
287 | *ttlp = 0; | |
288 | ||
289 | if (canonp) | |
290 | *canonp = r_name; | |
291 | ||
06202b9e YW |
292 | /* Explicitly reset both *h_errnop and h_errno to work around |
293 | * https://bugzilla.redhat.com/show_bug.cgi?id=1125975 */ | |
e70df46b LP |
294 | *h_errnop = NETDB_SUCCESS; |
295 | h_errno = 0; | |
296 | ||
4e8c8252 | 297 | return NSS_STATUS_SUCCESS; |
6b21f0cf LP |
298 | } |
299 | ||
4e8c8252 LP |
300 | enum nss_status _nss_myhostname_gethostbyname3_r( |
301 | const char *name, | |
302 | int af, | |
303 | struct hostent *host, | |
304 | char *buffer, size_t buflen, | |
305 | int *errnop, int *h_errnop, | |
306 | int32_t *ttlp, | |
307 | char **canonp) { | |
6b21f0cf | 308 | |
e80af1bd | 309 | _cleanup_free_ struct local_address *addresses = NULL; |
e8a7a315 | 310 | const char *canonical, *additional = NULL; |
5502f0d9 | 311 | _cleanup_free_ char *hn = NULL; |
e9140aff | 312 | uint32_t local_address_ipv4 = 0; |
e80af1bd | 313 | int n_addresses = 0; |
5502f0d9 | 314 | |
06202b9e | 315 | PROTECT_ERRNO; |
0c5eb056 LP |
316 | BLOCK_SIGNALS(NSS_SIGNALS_BLOCK); |
317 | ||
5502f0d9 LP |
318 | assert(name); |
319 | assert(host); | |
320 | assert(buffer); | |
321 | assert(errnop); | |
322 | assert(h_errnop); | |
6b21f0cf | 323 | |
4e8c8252 LP |
324 | if (af == AF_UNSPEC) |
325 | af = AF_INET; | |
6b21f0cf | 326 | |
ec2ce0c5 | 327 | if (!IN_SET(af, AF_INET, AF_INET6)) { |
cdccd29f | 328 | UNPROTECT_ERRNO; |
0192cbdb | 329 | *errnop = EAFNOSUPPORT; |
4e8c8252 LP |
330 | *h_errnop = NO_DATA; |
331 | return NSS_STATUS_UNAVAIL; | |
332 | } | |
6b21f0cf | 333 | |
5502f0d9 | 334 | if (is_localhost(name)) { |
e8a7a315 | 335 | canonical = "localhost"; |
8e38570e | 336 | local_address_ipv4 = htobe32(INADDR_LOOPBACK); |
e9140aff | 337 | |
46a5e0e7 | 338 | } else if (is_gateway_hostname(name)) { |
e9140aff | 339 | |
1d050e1e | 340 | n_addresses = local_gateways(NULL, 0, af, &addresses); |
e09e7ac3 LP |
341 | if (n_addresses <= 0) |
342 | goto not_found; | |
e9140aff | 343 | |
5248e7e1 | 344 | canonical = "_gateway"; |
e9140aff | 345 | |
e8a7a315 | 346 | } else { |
5502f0d9 LP |
347 | hn = gethostname_malloc(); |
348 | if (!hn) { | |
cdccd29f | 349 | UNPROTECT_ERRNO; |
0192cbdb | 350 | *errnop = ENOMEM; |
e8a7a315 | 351 | *h_errnop = NO_RECOVERY; |
5502f0d9 | 352 | return NSS_STATUS_TRYAGAIN; |
e8a7a315 | 353 | } |
6b21f0cf | 354 | |
e09e7ac3 LP |
355 | if (!streq(name, hn) && !streq_ptr(startswith(name, hn), ".")) |
356 | goto not_found; | |
e8a7a315 | 357 | |
1d050e1e | 358 | n_addresses = local_addresses(NULL, 0, af, &addresses); |
e80af1bd LP |
359 | if (n_addresses < 0) |
360 | n_addresses = 0; | |
e8a7a315 LP |
361 | |
362 | canonical = hn; | |
363 | additional = n_addresses <= 0 && af == AF_INET6 ? "localhost" : NULL; | |
364 | local_address_ipv4 = LOCALADDRESS_IPV4; | |
4e8c8252 | 365 | } |
6b21f0cf | 366 | |
cdccd29f LP |
367 | UNPROTECT_ERRNO; |
368 | ||
e8a7a315 LP |
369 | return fill_in_hostent( |
370 | canonical, additional, | |
371 | af, | |
372 | addresses, n_addresses, | |
373 | local_address_ipv4, | |
374 | host, | |
375 | buffer, buflen, | |
0192cbdb | 376 | errnop, h_errnop, |
e8a7a315 LP |
377 | ttlp, |
378 | canonp); | |
e09e7ac3 LP |
379 | |
380 | not_found: | |
381 | *h_errnop = HOST_NOT_FOUND; | |
382 | return NSS_STATUS_NOTFOUND; | |
4e8c8252 | 383 | } |
6b21f0cf | 384 | |
4e8c8252 LP |
385 | enum nss_status _nss_myhostname_gethostbyaddr2_r( |
386 | const void* addr, socklen_t len, | |
387 | int af, | |
388 | struct hostent *host, | |
389 | char *buffer, size_t buflen, | |
390 | int *errnop, int *h_errnop, | |
391 | int32_t *ttlp) { | |
6b21f0cf | 392 | |
e8a7a315 | 393 | const char *canonical = NULL, *additional = NULL; |
5502f0d9 | 394 | uint32_t local_address_ipv4 = LOCALADDRESS_IPV4; |
e80af1bd | 395 | _cleanup_free_ struct local_address *addresses = NULL; |
5502f0d9 | 396 | _cleanup_free_ char *hn = NULL; |
e80af1bd LP |
397 | int n_addresses = 0; |
398 | struct local_address *a; | |
3fdcecc8 | 399 | bool additional_from_hostname = false; |
e80af1bd | 400 | unsigned n; |
5502f0d9 | 401 | |
06202b9e | 402 | PROTECT_ERRNO; |
0c5eb056 LP |
403 | BLOCK_SIGNALS(NSS_SIGNALS_BLOCK); |
404 | ||
5502f0d9 LP |
405 | assert(addr); |
406 | assert(host); | |
407 | assert(buffer); | |
408 | assert(errnop); | |
409 | assert(h_errnop); | |
8041b5ba | 410 | |
555bd6e9 | 411 | if (!IN_SET(af, AF_INET, AF_INET6)) { |
cdccd29f | 412 | UNPROTECT_ERRNO; |
0192cbdb | 413 | *errnop = EAFNOSUPPORT; |
555bd6e9 LP |
414 | *h_errnop = NO_DATA; |
415 | return NSS_STATUS_UNAVAIL; | |
416 | } | |
417 | ||
9d485985 | 418 | if (len != FAMILY_ADDRESS_SIZE(af)) { |
cdccd29f | 419 | UNPROTECT_ERRNO; |
0192cbdb | 420 | *errnop = EINVAL; |
8041b5ba LP |
421 | *h_errnop = NO_RECOVERY; |
422 | return NSS_STATUS_UNAVAIL; | |
423 | } | |
6b21f0cf | 424 | |
4e8c8252 | 425 | if (af == AF_INET) { |
8041b5ba LP |
426 | if ((*(uint32_t*) addr) == LOCALADDRESS_IPV4) |
427 | goto found; | |
6b21f0cf | 428 | |
8e38570e | 429 | if ((*(uint32_t*) addr) == htobe32(INADDR_LOOPBACK)) { |
e8a7a315 | 430 | canonical = "localhost"; |
8e38570e | 431 | local_address_ipv4 = htobe32(INADDR_LOOPBACK); |
e8a7a315 LP |
432 | goto found; |
433 | } | |
434 | ||
555bd6e9 LP |
435 | } else { |
436 | assert(af == AF_INET6); | |
8041b5ba | 437 | |
e8a7a315 | 438 | if (memcmp(addr, LOCALADDRESS_IPV6, 16) == 0) { |
3fdcecc8 LP |
439 | canonical = "localhost"; |
440 | additional_from_hostname = true; | |
8041b5ba | 441 | goto found; |
e8a7a315 | 442 | } |
4e8c8252 LP |
443 | } |
444 | ||
1d050e1e | 445 | n_addresses = local_addresses(NULL, 0, AF_UNSPEC, &addresses); |
68a9c7c4 ZJS |
446 | for (a = addresses, n = 0; (int) n < n_addresses; n++, a++) { |
447 | if (af != a->family) | |
448 | continue; | |
8041b5ba | 449 | |
68a9c7c4 ZJS |
450 | if (memcmp(addr, &a->address, FAMILY_ADDRESS_SIZE(af)) == 0) |
451 | goto found; | |
e9140aff LP |
452 | } |
453 | ||
97b11eed | 454 | addresses = mfree(addresses); |
e9140aff | 455 | |
1d050e1e | 456 | n_addresses = local_gateways(NULL, 0, AF_UNSPEC, &addresses); |
68a9c7c4 ZJS |
457 | for (a = addresses, n = 0; (int) n < n_addresses; n++, a++) { |
458 | if (af != a->family) | |
459 | continue; | |
e9140aff | 460 | |
68a9c7c4 | 461 | if (memcmp(addr, &a->address, FAMILY_ADDRESS_SIZE(af)) == 0) { |
5248e7e1 | 462 | canonical = "_gateway"; |
68a9c7c4 | 463 | goto found; |
e9140aff | 464 | } |
8041b5ba LP |
465 | } |
466 | ||
8041b5ba | 467 | *h_errnop = HOST_NOT_FOUND; |
8041b5ba LP |
468 | return NSS_STATUS_NOTFOUND; |
469 | ||
470 | found: | |
82e4c2d6 | 471 | if (!canonical || additional_from_hostname) { |
3fdcecc8 LP |
472 | hn = gethostname_malloc(); |
473 | if (!hn) { | |
cdccd29f | 474 | UNPROTECT_ERRNO; |
0192cbdb | 475 | *errnop = ENOMEM; |
3fdcecc8 LP |
476 | *h_errnop = NO_RECOVERY; |
477 | return NSS_STATUS_TRYAGAIN; | |
478 | } | |
479 | ||
480 | if (!canonical) | |
481 | canonical = hn; | |
82e4c2d6 | 482 | else |
3fdcecc8 LP |
483 | additional = hn; |
484 | } | |
4e8c8252 | 485 | |
cdccd29f | 486 | UNPROTECT_ERRNO; |
e8a7a315 LP |
487 | return fill_in_hostent( |
488 | canonical, additional, | |
489 | af, | |
490 | addresses, n_addresses, | |
491 | local_address_ipv4, | |
492 | host, | |
493 | buffer, buflen, | |
0192cbdb | 494 | errnop, h_errnop, |
e8a7a315 LP |
495 | ttlp, |
496 | NULL); | |
4e8c8252 | 497 | } |
6b21f0cf | 498 | |
c9fdc26e LP |
499 | NSS_GETHOSTBYNAME_FALLBACKS(myhostname); |
500 | NSS_GETHOSTBYADDR_FALLBACKS(myhostname); |