enum nss_status _nss_myhostname_gethostbyname3_r( const char *name, int af, struct hostent *host, char *buffer, size_t buflen, int *errnop, int *h_errnop, int32_t *ttlp, char **canonp) { char hn[HOST_NAME_MAX+1] = {}; struct address *addresses = NULL; unsigned n_addresses = 0; const char *canonical, *additional = NULL; uint32_t local_address_ipv4; if (af == AF_UNSPEC) af = AF_INET; if (af != AF_INET && af != AF_INET6) { *errnop = EAFNOSUPPORT; *h_errnop = NO_DATA; return NSS_STATUS_UNAVAIL; } if (strcasecmp(name, "localhost") == 0) { canonical = "localhost"; local_address_ipv4 = htonl(INADDR_LOOPBACK); } else { if (gethostname(hn, sizeof(hn)-1) < 0) { *errnop = errno; *h_errnop = NO_RECOVERY; return NSS_STATUS_UNAVAIL; } if (strcasecmp(name, hn) != 0) { *errnop = ENOENT; *h_errnop = HOST_NOT_FOUND; return NSS_STATUS_NOTFOUND; } ifconf_acquire_addresses(&addresses, &n_addresses); canonical = hn; additional = n_addresses <= 0 && af == AF_INET6 ? "localhost" : NULL; local_address_ipv4 = LOCALADDRESS_IPV4; } return fill_in_hostent( canonical, additional, af, addresses, n_addresses, local_address_ipv4, host, buffer, buflen, errnop, h_errnop, ttlp, canonp); }
enum nss_status _nss_myhostname_gethostbyaddr2_r( const void* addr, socklen_t len, int af, struct hostent *host, char *buffer, size_t buflen, int *errnop, int *h_errnop, int32_t *ttlp) { const char *canonical = NULL, *additional = NULL; uint32_t local_address_ipv4 = LOCALADDRESS_IPV4; _cleanup_free_ struct local_address *addresses = NULL; _cleanup_free_ char *hn = NULL; int n_addresses = 0; struct local_address *a; bool additional_from_hostname = false; unsigned n; assert(addr); assert(host); assert(buffer); assert(errnop); assert(h_errnop); if (!IN_SET(af, AF_INET, AF_INET6)) { *errnop = EAFNOSUPPORT; *h_errnop = NO_DATA; return NSS_STATUS_UNAVAIL; } if (len != FAMILY_ADDRESS_SIZE(af)) { *errnop = EINVAL; *h_errnop = NO_RECOVERY; return NSS_STATUS_UNAVAIL; } if (af == AF_INET) { if ((*(uint32_t*) addr) == LOCALADDRESS_IPV4) goto found; if ((*(uint32_t*) addr) == htonl(INADDR_LOOPBACK)) { canonical = "localhost"; local_address_ipv4 = htonl(INADDR_LOOPBACK); goto found; } } else { assert(af == AF_INET6); if (memcmp(addr, LOCALADDRESS_IPV6, 16) == 0) { canonical = "localhost"; additional_from_hostname = true; goto found; } } n_addresses = local_addresses(NULL, 0, AF_UNSPEC, &addresses); if (n_addresses > 0) { for (a = addresses, n = 0; (int) n < n_addresses; n++, a++) { if (af != a->family) continue; if (memcmp(addr, &a->address, FAMILY_ADDRESS_SIZE(af)) == 0) goto found; } } addresses = mfree(addresses); n_addresses = local_gateways(NULL, 0, AF_UNSPEC, &addresses); if (n_addresses > 0) { for (a = addresses, n = 0; (int) n < n_addresses; n++, a++) { if (af != a->family) continue; if (memcmp(addr, &a->address, FAMILY_ADDRESS_SIZE(af)) == 0) { canonical = "gateway"; goto found; } } } *errnop = ENOENT; *h_errnop = HOST_NOT_FOUND; return NSS_STATUS_NOTFOUND; found: if (!canonical || (!additional && additional_from_hostname)) { hn = gethostname_malloc(); if (!hn) { *errnop = ENOMEM; *h_errnop = NO_RECOVERY; return NSS_STATUS_TRYAGAIN; } if (!canonical) canonical = hn; if (!additional && additional_from_hostname) additional = hn; } return fill_in_hostent( canonical, additional, af, addresses, n_addresses, local_address_ipv4, host, buffer, buflen, errnop, h_errnop, ttlp, NULL); }
enum nss_status _nss_myhostname_gethostbyname3_r( const char *name, int af, struct hostent *host, char *buffer, size_t buflen, int *errnop, int *h_errnop, int32_t *ttlp, char **canonp) { _cleanup_free_ struct local_address *addresses = NULL; const char *canonical, *additional = NULL; _cleanup_free_ char *hn = NULL; uint32_t local_address_ipv4 = 0; int n_addresses = 0; assert(name); assert(host); assert(buffer); assert(errnop); assert(h_errnop); if (af == AF_UNSPEC) af = AF_INET; if (af != AF_INET && af != AF_INET6) { *errnop = EAFNOSUPPORT; *h_errnop = NO_DATA; return NSS_STATUS_UNAVAIL; } if (is_localhost(name)) { canonical = "localhost"; local_address_ipv4 = htonl(INADDR_LOOPBACK); } else if (is_gateway_hostname(name)) { n_addresses = local_gateways(NULL, 0, af, &addresses); if (n_addresses <= 0) { *errnop = ENOENT; *h_errnop = HOST_NOT_FOUND; return NSS_STATUS_NOTFOUND; } canonical = "gateway"; } else { hn = gethostname_malloc(); if (!hn) { *errnop = ENOMEM; *h_errnop = NO_RECOVERY; return NSS_STATUS_TRYAGAIN; } if (!streq(name, hn) && !streq_ptr(startswith(name, hn), ".")) { *errnop = ENOENT; *h_errnop = HOST_NOT_FOUND; return NSS_STATUS_NOTFOUND; } n_addresses = local_addresses(NULL, 0, af, &addresses); if (n_addresses < 0) n_addresses = 0; canonical = hn; additional = n_addresses <= 0 && af == AF_INET6 ? "localhost" : NULL; local_address_ipv4 = LOCALADDRESS_IPV4; } return fill_in_hostent( canonical, additional, af, addresses, n_addresses, local_address_ipv4, host, buffer, buflen, errnop, h_errnop, ttlp, canonp); }
enum nss_status _nss_myhostname_gethostbyaddr2_r( const void* addr, socklen_t len, int af, struct hostent *host, char *buffer, size_t buflen, int *errnop, int *h_errnop, int32_t *ttlp) { char hn[HOST_NAME_MAX+1] = {}; struct address *addresses = NULL; struct address *a; unsigned n_addresses = 0, n; uint32_t local_address_ipv4 = LOCALADDRESS_IPV4; const char *canonical = NULL, *additional = NULL; if (len != PROTO_ADDRESS_SIZE(af)) { *errnop = EINVAL; *h_errnop = NO_RECOVERY; return NSS_STATUS_UNAVAIL; } if (af == AF_INET) { if ((*(uint32_t*) addr) == LOCALADDRESS_IPV4) goto found; if ((*(uint32_t*) addr) == htonl(INADDR_LOOPBACK)) { canonical = "localhost"; local_address_ipv4 = htonl(INADDR_LOOPBACK); goto found; } } else if (af == AF_INET6) { if (memcmp(addr, LOCALADDRESS_IPV6, 16) == 0) { additional = "localhost"; goto found; } } else { *errnop = EAFNOSUPPORT; *h_errnop = NO_DATA; return NSS_STATUS_UNAVAIL; } ifconf_acquire_addresses(&addresses, &n_addresses); for (a = addresses, n = 0; n < n_addresses; n++, a++) { if (af != a->family) continue; if (memcmp(addr, a->address, PROTO_ADDRESS_SIZE(af)) == 0) goto found; } *errnop = ENOENT; *h_errnop = HOST_NOT_FOUND; free(addresses); return NSS_STATUS_NOTFOUND; found: if (!canonical) { if (gethostname(hn, sizeof(hn)-1) < 0) { *errnop = errno; *h_errnop = NO_RECOVERY; free(addresses); return NSS_STATUS_UNAVAIL; } canonical = hn; } return fill_in_hostent( canonical, additional, af, addresses, n_addresses, local_address_ipv4, host, buffer, buflen, errnop, h_errnop, ttlp, NULL); }