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