nss-myhostname.c | nss-myhostname.c | |||
---|---|---|---|---|
skipping to change at line 33 | skipping to change at line 33 | |||
#include <nss.h> | #include <nss.h> | |||
#include <sys/types.h> | #include <sys/types.h> | |||
#include <netdb.h> | #include <netdb.h> | |||
#include <errno.h> | #include <errno.h> | |||
#include <string.h> | #include <string.h> | |||
#include <unistd.h> | #include <unistd.h> | |||
#include <net/if.h> | #include <net/if.h> | |||
#include <stdlib.h> | #include <stdlib.h> | |||
#include <arpa/inet.h> | #include <arpa/inet.h> | |||
#include "ifconf.h" | #include "local-addresses.h" | |||
#include "macro.h" | #include "macro.h" | |||
#include "nss-util.h" | ||||
/* Ensure that glibc's assert is used. We cannot use assert from macro.h, a | #include "util.h" | |||
s | ||||
* libnss_myhostname will be linked into arbitrary programs which will, in | ||||
turn | ||||
* attempt to write to the journal via log_dispatch() */ | ||||
#include <assert.h> | ||||
/* We use 127.0.0.2 as IPv4 address. This has the advantage over | /* We use 127.0.0.2 as IPv4 address. This has the advantage over | |||
* 127.0.0.1 that it can be translated back to the local hostname. For | * 127.0.0.1 that it can be translated back to the local hostname. For | |||
* IPv6 we use ::1 which unfortunately will not translate back to the | * IPv6 we use ::1 which unfortunately will not translate back to the | |||
* hostname but instead something like "localhost6" or so. */ | * hostname but instead something like "localhost6" or so. */ | |||
#define LOCALADDRESS_IPV4 (htonl(0x7F000002)) | #define LOCALADDRESS_IPV4 (htonl(0x7F000002)) | |||
#define LOCALADDRESS_IPV6 &in6addr_loopback | #define LOCALADDRESS_IPV6 &in6addr_loopback | |||
#define LOOPBACK_INTERFACE "lo" | #define LOOPBACK_INTERFACE "lo" | |||
enum nss_status _nss_myhostname_gethostbyname4_r( | NSS_GETHOSTBYNAME_PROTOTYPES(myhostname); | |||
const char *name, | NSS_GETHOSTBYADDR_PROTOTYPES(myhostname); | |||
struct gaih_addrtuple **pat, | ||||
char *buffer, size_t buflen, | ||||
int *errnop, int *h_errnop, | ||||
int32_t *ttlp) _public_; | ||||
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) _public_; | ||||
enum nss_status _nss_myhostname_gethostbyname2_r( | ||||
const char *name, | ||||
int af, | ||||
struct hostent *host, | ||||
char *buffer, size_t buflen, | ||||
int *errnop, int *h_errnop) _public_; | ||||
enum nss_status _nss_myhostname_gethostbyname_r( | ||||
const char *name, | ||||
struct hostent *host, | ||||
char *buffer, size_t buflen, | ||||
int *errnop, int *h_errnop) _public_; | ||||
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) _public_; | ||||
enum nss_status _nss_myhostname_gethostbyaddr_r( | ||||
const void* addr, socklen_t len, | ||||
int af, | ||||
struct hostent *host, | ||||
char *buffer, size_t buflen, | ||||
int *errnop, int *h_errnop) _public_; | ||||
enum nss_status _nss_myhostname_gethostbyname4_r( | enum nss_status _nss_myhostname_gethostbyname4_r( | |||
const char *name, | const char *name, | |||
struct gaih_addrtuple **pat, | struct gaih_addrtuple **pat, | |||
char *buffer, size_t buflen, | char *buffer, size_t buflen, | |||
int *errnop, int *h_errnop, | int *errnop, int *h_errnop, | |||
int32_t *ttlp) { | int32_t *ttlp) { | |||
unsigned lo_ifi; | struct gaih_addrtuple *r_tuple, *r_tuple_prev = NULL; | |||
char hn[HOST_NAME_MAX+1] = {}; | _cleanup_free_ struct local_address *addresses = NULL; | |||
_cleanup_free_ char *hn = NULL; | ||||
const char *canonical = NULL; | const char *canonical = NULL; | |||
int n_addresses = 0, lo_ifi; | ||||
uint32_t local_address_ipv4; | ||||
struct local_address *a; | ||||
size_t l, idx, ms; | size_t l, idx, ms; | |||
char *r_name; | char *r_name; | |||
struct gaih_addrtuple *r_tuple, *r_tuple_prev = NULL; | unsigned n; | |||
struct address *addresses = NULL, *a; | ||||
unsigned n_addresses = 0, n; | assert(name); | |||
uint32_t local_address_ipv4; | assert(pat); | |||
assert(buffer); | ||||
assert(errnop); | ||||
assert(h_errnop); | ||||
if (strcasecmp(name, "localhost") == 0) { | if (is_localhost(name)) { | |||
/* We respond to 'localhost', so that /etc/hosts | /* We respond to 'localhost', so that /etc/hosts | |||
* is optional */ | * is optional */ | |||
canonical = "localhost"; | canonical = "localhost"; | |||
local_address_ipv4 = htonl(INADDR_LOOPBACK); | local_address_ipv4 = htonl(INADDR_LOOPBACK); | |||
} else { | } else { | |||
/* We respond to our local host name */ | hn = gethostname_malloc(); | |||
if (!hn) { | ||||
if (gethostname(hn, sizeof(hn)-1) < 0) { | *errnop = ENOMEM; | |||
*errnop = errno; | ||||
*h_errnop = NO_RECOVERY; | *h_errnop = NO_RECOVERY; | |||
return NSS_STATUS_UNAVAIL; | return NSS_STATUS_TRYAGAIN; | |||
} | } | |||
if (strcasecmp(name, hn) != 0) { | /* We respond to our local host name, our our hostname suff | |||
ixed with a single dot. */ | ||||
if (!streq(name, hn) && !streq_ptr(startswith(name, hn), ". | ||||
")) { | ||||
*errnop = ENOENT; | *errnop = ENOENT; | |||
*h_errnop = HOST_NOT_FOUND; | *h_errnop = HOST_NOT_FOUND; | |||
return NSS_STATUS_NOTFOUND; | return NSS_STATUS_NOTFOUND; | |||
} | } | |||
/* If this fails, n_addresses is 0. Which is fine */ | n_addresses = local_addresses(NULL, 0, &addresses); | |||
ifconf_acquire_addresses(&addresses, &n_addresses); | if (n_addresses < 0) | |||
n_addresses = 0; | ||||
canonical = hn; | canonical = hn; | |||
local_address_ipv4 = LOCALADDRESS_IPV4; | local_address_ipv4 = LOCALADDRESS_IPV4; | |||
} | } | |||
/* If this call fails we fill in 0 as scope. Which is fine */ | /* If this call fails we fill in 0 as scope. Which is fine */ | |||
lo_ifi = n_addresses <= 0 ? if_nametoindex(LOOPBACK_INTERFACE) : 0; | lo_ifi = n_addresses <= 0 ? if_nametoindex(LOOPBACK_INTERFACE) : 0; | |||
l = strlen(canonical); | l = strlen(canonical); | |||
ms = ALIGN(l+1)+ALIGN(sizeof(struct gaih_addrtuple))*(n_addresses > 0 ? n_addresses : 2); | ms = ALIGN(l+1) + ALIGN(sizeof(struct gaih_addrtuple)) * (n_address es > 0 ? n_addresses : 2); | |||
if (buflen < ms) { | if (buflen < ms) { | |||
*errnop = ENOMEM; | *errnop = ENOMEM; | |||
*h_errnop = NO_RECOVERY; | *h_errnop = NO_RECOVERY; | |||
free(addresses); | ||||
return NSS_STATUS_TRYAGAIN; | return NSS_STATUS_TRYAGAIN; | |||
} | } | |||
/* First, fill in hostname */ | /* First, fill in hostname */ | |||
r_name = buffer; | r_name = buffer; | |||
memcpy(r_name, canonical, l+1); | memcpy(r_name, canonical, l+1); | |||
idx = ALIGN(l+1); | idx = ALIGN(l+1); | |||
if (n_addresses <= 0) { | if (n_addresses <= 0) { | |||
/* Second, fill in IPv6 tuple */ | /* Second, fill in IPv6 tuple */ | |||
skipping to change at line 181 | skipping to change at line 144 | |||
r_tuple->name = r_name; | r_tuple->name = r_name; | |||
r_tuple->family = AF_INET; | r_tuple->family = AF_INET; | |||
*(uint32_t*) r_tuple->addr = local_address_ipv4; | *(uint32_t*) r_tuple->addr = local_address_ipv4; | |||
r_tuple->scopeid = (uint32_t) lo_ifi; | r_tuple->scopeid = (uint32_t) lo_ifi; | |||
idx += ALIGN(sizeof(struct gaih_addrtuple)); | idx += ALIGN(sizeof(struct gaih_addrtuple)); | |||
r_tuple_prev = r_tuple; | r_tuple_prev = r_tuple; | |||
} | } | |||
/* Fourth, fill actual addresses in, but in backwards order */ | /* Fourth, fill actual addresses in, but in backwards order */ | |||
for (a = addresses + n_addresses - 1, n = 0; n < n_addresses; n++, a--) { | for (a = addresses + n_addresses - 1, n = 0; (int) n < n_addresses; n++, a--) { | |||
r_tuple = (struct gaih_addrtuple*) (buffer + idx); | r_tuple = (struct gaih_addrtuple*) (buffer + idx); | |||
r_tuple->next = r_tuple_prev; | r_tuple->next = r_tuple_prev; | |||
r_tuple->name = r_name; | r_tuple->name = r_name; | |||
r_tuple->family = a->family; | r_tuple->family = a->family; | |||
r_tuple->scopeid = a->ifindex; | r_tuple->scopeid = a->ifindex; | |||
memcpy(r_tuple->addr, a->address, 16); | memcpy(r_tuple->addr, &a->address, 16); | |||
idx += ALIGN(sizeof(struct gaih_addrtuple)); | idx += ALIGN(sizeof(struct gaih_addrtuple)); | |||
r_tuple_prev = r_tuple; | r_tuple_prev = r_tuple; | |||
} | } | |||
/* Verify the size matches */ | /* Verify the size matches */ | |||
assert(idx == ms); | assert(idx == ms); | |||
/* Nscd expects us to store the first record in **pat. */ | /* Nscd expects us to store the first record in **pat. */ | |||
if (*pat) | if (*pat) | |||
**pat = *r_tuple_prev; | **pat = *r_tuple_prev; | |||
else | else | |||
*pat = r_tuple_prev; | *pat = r_tuple_prev; | |||
if (ttlp) | if (ttlp) | |||
*ttlp = 0; | *ttlp = 0; | |||
free(addresses); | /* Explicitly reset all error variables */ | |||
*errnop = 0; | ||||
*h_errnop = NETDB_SUCCESS; | ||||
h_errno = 0; | ||||
return NSS_STATUS_SUCCESS; | return NSS_STATUS_SUCCESS; | |||
} | } | |||
static enum nss_status fill_in_hostent( | static enum nss_status fill_in_hostent( | |||
const char *canonical, const char *additional, | const char *canonical, const char *additional, | |||
int af, | int af, | |||
struct address *addresses, unsigned n_addresses, | struct local_address *addresses, unsigned n_addresses, | |||
uint32_t local_address_ipv4, | uint32_t local_address_ipv4, | |||
struct hostent *result, | struct hostent *result, | |||
char *buffer, size_t buflen, | char *buffer, size_t buflen, | |||
int *errnop, int *h_errnop, | int *errnop, int *h_errnop, | |||
int32_t *ttlp, | int32_t *ttlp, | |||
char **canonp) { | char **canonp) { | |||
size_t l_canonical, l_additional, idx, ms; | size_t l_canonical, l_additional, idx, ms, alen; | |||
char *r_addr, *r_name, *r_aliases, *r_alias = NULL, *r_addr_list; | char *r_addr, *r_name, *r_aliases, *r_alias = NULL, *r_addr_list; | |||
size_t alen; | struct local_address *a; | |||
struct address *a; | ||||
unsigned n, c; | unsigned n, c; | |||
alen = PROTO_ADDRESS_SIZE(af); | assert(canonical); | |||
assert(result); | ||||
assert(buffer); | ||||
assert(errnop); | ||||
assert(h_errnop); | ||||
alen = FAMILY_ADDRESS_SIZE(af); | ||||
for (a = addresses, n = 0, c = 0; n < n_addresses; a++, n++) | for (a = addresses, n = 0, c = 0; n < n_addresses; a++, n++) | |||
if (af == a->family) | if (af == a->family) | |||
c++; | c++; | |||
l_canonical = strlen(canonical); | l_canonical = strlen(canonical); | |||
l_additional = additional ? strlen(additional) : 0; | l_additional = additional ? strlen(additional) : 0; | |||
ms = ALIGN(l_canonical+1)+ | ms = ALIGN(l_canonical+1)+ | |||
(additional ? ALIGN(l_additional+1) : 0) + | (additional ? ALIGN(l_additional+1) : 0) + | |||
sizeof(char*)+ | sizeof(char*) + | |||
(additional ? sizeof(char*) : 0) + | (additional ? sizeof(char*) : 0) + | |||
(c > 0 ? c : 1)*ALIGN(alen)+ | (c > 0 ? c : 1) * ALIGN(alen) + | |||
(c > 0 ? c+1 : 2)*sizeof(char*); | (c > 0 ? c+1 : 2) * sizeof(char*); | |||
if (buflen < ms) { | if (buflen < ms) { | |||
*errnop = ENOMEM; | *errnop = ENOMEM; | |||
*h_errnop = NO_RECOVERY; | *h_errnop = NO_RECOVERY; | |||
free(addresses); | ||||
return NSS_STATUS_TRYAGAIN; | return NSS_STATUS_TRYAGAIN; | |||
} | } | |||
/* First, fill in hostnames */ | /* First, fill in hostnames */ | |||
r_name = buffer; | r_name = buffer; | |||
memcpy(r_name, canonical, l_canonical+1); | memcpy(r_name, canonical, l_canonical+1); | |||
idx = ALIGN(l_canonical+1); | idx = ALIGN(l_canonical+1); | |||
if (additional) { | if (additional) { | |||
r_alias = buffer + idx; | r_alias = buffer + idx; | |||
skipping to change at line 280 | skipping to change at line 250 | |||
/* Third, add addresses */ | /* Third, add addresses */ | |||
r_addr = buffer + idx; | r_addr = buffer + idx; | |||
if (c > 0) { | if (c > 0) { | |||
unsigned i = 0; | unsigned i = 0; | |||
for (a = addresses, n = 0; n < n_addresses; a++, n++) { | for (a = addresses, n = 0; n < n_addresses; a++, n++) { | |||
if (af != a->family) | if (af != a->family) | |||
continue; | continue; | |||
memcpy(r_addr + i*ALIGN(alen), a->address, alen); | memcpy(r_addr + i*ALIGN(alen), &a->address, alen); | |||
i++; | i++; | |||
} | } | |||
assert(i == c); | assert(i == c); | |||
idx += c*ALIGN(alen); | idx += c*ALIGN(alen); | |||
} else { | } else { | |||
if (af == AF_INET) | if (af == AF_INET) | |||
*(uint32_t*) r_addr = local_address_ipv4; | *(uint32_t*) r_addr = local_address_ipv4; | |||
else | else | |||
memcpy(r_addr, LOCALADDRESS_IPV6, 16); | memcpy(r_addr, LOCALADDRESS_IPV6, 16); | |||
idx += ALIGN(alen); | idx += ALIGN(alen); | |||
} | } | |||
/* Fourth, add address pointer array */ | /* Fourth, add address pointer array */ | |||
r_addr_list = buffer + idx; | r_addr_list = buffer + idx; | |||
if (c > 0) { | if (c > 0) { | |||
unsigned i = 0; | unsigned i; | |||
for (a = addresses, n = 0; n < n_addresses; a++, n++) { | ||||
if (af != a->family) | ||||
continue; | ||||
((char**) r_addr_list)[i] = (r_addr + i*ALIGN(alen) | for (i = 0; i < c; i++) | |||
); | ((char**) r_addr_list)[i] = r_addr + i*ALIGN(alen); | |||
i++; | ||||
} | ||||
assert(i == c); | ((char**) r_addr_list)[i] = NULL; | |||
((char**) r_addr_list)[c] = NULL; | idx += (c+1) * sizeof(char*); | |||
idx += (c+1)*sizeof(char*); | ||||
} else { | } else { | |||
((char**) r_addr_list)[0] = r_addr; | ((char**) r_addr_list)[0] = r_addr; | |||
((char**) r_addr_list)[1] = NULL; | ((char**) r_addr_list)[1] = NULL; | |||
idx += 2*sizeof(char*); | idx += 2 * sizeof(char*); | |||
} | } | |||
/* Verify the size matches */ | /* Verify the size matches */ | |||
assert(idx == ms); | assert(idx == ms); | |||
result->h_name = r_name; | result->h_name = r_name; | |||
result->h_aliases = (char**) r_aliases; | result->h_aliases = (char**) r_aliases; | |||
result->h_addrtype = af; | result->h_addrtype = af; | |||
result->h_length = alen; | result->h_length = alen; | |||
result->h_addr_list = (char**) r_addr_list; | result->h_addr_list = (char**) r_addr_list; | |||
if (ttlp) | if (ttlp) | |||
*ttlp = 0; | *ttlp = 0; | |||
if (canonp) | if (canonp) | |||
*canonp = r_name; | *canonp = r_name; | |||
free(addresses); | /* Explicitly reset all error variables */ | |||
*errnop = 0; | ||||
*h_errnop = NETDB_SUCCESS; | ||||
h_errno = 0; | ||||
return NSS_STATUS_SUCCESS; | return NSS_STATUS_SUCCESS; | |||
} | } | |||
enum nss_status _nss_myhostname_gethostbyname3_r( | enum nss_status _nss_myhostname_gethostbyname3_r( | |||
const char *name, | const char *name, | |||
int af, | int af, | |||
struct hostent *host, | struct hostent *host, | |||
char *buffer, size_t buflen, | char *buffer, size_t buflen, | |||
int *errnop, int *h_errnop, | int *errnop, int *h_errnop, | |||
int32_t *ttlp, | int32_t *ttlp, | |||
char **canonp) { | char **canonp) { | |||
char hn[HOST_NAME_MAX+1] = {}; | _cleanup_free_ struct local_address *addresses = NULL; | |||
struct address *addresses = NULL; | ||||
unsigned n_addresses = 0; | ||||
const char *canonical, *additional = NULL; | const char *canonical, *additional = NULL; | |||
_cleanup_free_ char *hn = NULL; | ||||
uint32_t local_address_ipv4; | uint32_t local_address_ipv4; | |||
int n_addresses = 0; | ||||
assert(name); | ||||
assert(host); | ||||
assert(buffer); | ||||
assert(errnop); | ||||
assert(h_errnop); | ||||
if (af == AF_UNSPEC) | if (af == AF_UNSPEC) | |||
af = AF_INET; | af = AF_INET; | |||
if (af != AF_INET && af != AF_INET6) { | if (af != AF_INET && af != AF_INET6) { | |||
*errnop = EAFNOSUPPORT; | *errnop = EAFNOSUPPORT; | |||
*h_errnop = NO_DATA; | *h_errnop = NO_DATA; | |||
return NSS_STATUS_UNAVAIL; | return NSS_STATUS_UNAVAIL; | |||
} | } | |||
if (strcasecmp(name, "localhost") == 0) { | if (is_localhost(name)) { | |||
canonical = "localhost"; | canonical = "localhost"; | |||
local_address_ipv4 = htonl(INADDR_LOOPBACK); | local_address_ipv4 = htonl(INADDR_LOOPBACK); | |||
} else { | } else { | |||
if (gethostname(hn, sizeof(hn)-1) < 0) { | hn = gethostname_malloc(); | |||
*errnop = errno; | if (!hn) { | |||
*errnop = ENOMEM; | ||||
*h_errnop = NO_RECOVERY; | *h_errnop = NO_RECOVERY; | |||
return NSS_STATUS_UNAVAIL; | return NSS_STATUS_TRYAGAIN; | |||
} | } | |||
if (strcasecmp(name, hn) != 0) { | if (!streq(name, hn) && !streq_ptr(startswith(name, hn), ". ")) { | |||
*errnop = ENOENT; | *errnop = ENOENT; | |||
*h_errnop = HOST_NOT_FOUND; | *h_errnop = HOST_NOT_FOUND; | |||
return NSS_STATUS_NOTFOUND; | return NSS_STATUS_NOTFOUND; | |||
} | } | |||
ifconf_acquire_addresses(&addresses, &n_addresses); | n_addresses = local_addresses(NULL, 0, &addresses); | |||
if (n_addresses < 0) | ||||
n_addresses = 0; | ||||
canonical = hn; | canonical = hn; | |||
additional = n_addresses <= 0 && af == AF_INET6 ? "localhos t" : NULL; | additional = n_addresses <= 0 && af == AF_INET6 ? "localhos t" : NULL; | |||
local_address_ipv4 = LOCALADDRESS_IPV4; | local_address_ipv4 = LOCALADDRESS_IPV4; | |||
} | } | |||
return fill_in_hostent( | return fill_in_hostent( | |||
canonical, additional, | canonical, additional, | |||
af, | af, | |||
addresses, n_addresses, | addresses, n_addresses, | |||
local_address_ipv4, | local_address_ipv4, | |||
host, | host, | |||
buffer, buflen, | buffer, buflen, | |||
errnop, h_errnop, | errnop, h_errnop, | |||
ttlp, | ttlp, | |||
canonp); | canonp); | |||
} | } | |||
enum nss_status _nss_myhostname_gethostbyname2_r( | ||||
const char *name, | ||||
int af, | ||||
struct hostent *host, | ||||
char *buffer, size_t buflen, | ||||
int *errnop, int *h_errnop) { | ||||
return _nss_myhostname_gethostbyname3_r( | ||||
name, | ||||
af, | ||||
host, | ||||
buffer, buflen, | ||||
errnop, h_errnop, | ||||
NULL, | ||||
NULL); | ||||
} | ||||
enum nss_status _nss_myhostname_gethostbyname_r( | ||||
const char *name, | ||||
struct hostent *host, | ||||
char *buffer, size_t buflen, | ||||
int *errnop, int *h_errnop) { | ||||
return _nss_myhostname_gethostbyname3_r( | ||||
name, | ||||
AF_UNSPEC, | ||||
host, | ||||
buffer, buflen, | ||||
errnop, h_errnop, | ||||
NULL, | ||||
NULL); | ||||
} | ||||
enum nss_status _nss_myhostname_gethostbyaddr2_r( | enum nss_status _nss_myhostname_gethostbyaddr2_r( | |||
const void* addr, socklen_t len, | const void* addr, socklen_t len, | |||
int af, | int af, | |||
struct hostent *host, | struct hostent *host, | |||
char *buffer, size_t buflen, | char *buffer, size_t buflen, | |||
int *errnop, int *h_errnop, | int *errnop, int *h_errnop, | |||
int32_t *ttlp) { | 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; | 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; | ||||
unsigned n; | ||||
assert(addr); | ||||
assert(host); | ||||
assert(buffer); | ||||
assert(errnop); | ||||
assert(h_errnop); | ||||
if (len != PROTO_ADDRESS_SIZE(af)) { | 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; | *errnop = EINVAL; | |||
*h_errnop = NO_RECOVERY; | *h_errnop = NO_RECOVERY; | |||
return NSS_STATUS_UNAVAIL; | return NSS_STATUS_UNAVAIL; | |||
} | } | |||
if (af == AF_INET) { | if (af == AF_INET) { | |||
if ((*(uint32_t*) addr) == LOCALADDRESS_IPV4) | if ((*(uint32_t*) addr) == LOCALADDRESS_IPV4) | |||
goto found; | goto found; | |||
if ((*(uint32_t*) addr) == htonl(INADDR_LOOPBACK)) { | if ((*(uint32_t*) addr) == htonl(INADDR_LOOPBACK)) { | |||
canonical = "localhost"; | canonical = "localhost"; | |||
local_address_ipv4 = htonl(INADDR_LOOPBACK); | local_address_ipv4 = htonl(INADDR_LOOPBACK); | |||
goto found; | goto found; | |||
} | } | |||
} else if (af == AF_INET6) { | } else { | |||
assert(af == AF_INET6); | ||||
if (memcmp(addr, LOCALADDRESS_IPV6, 16) == 0) { | if (memcmp(addr, LOCALADDRESS_IPV6, 16) == 0) { | |||
additional = "localhost"; | additional = "localhost"; | |||
goto found; | goto found; | |||
} | } | |||
} else { | ||||
*errnop = EAFNOSUPPORT; | ||||
*h_errnop = NO_DATA; | ||||
return NSS_STATUS_UNAVAIL; | ||||
} | } | |||
ifconf_acquire_addresses(&addresses, &n_addresses); | n_addresses = local_addresses(NULL, 0, &addresses); | |||
if (n_addresses < 0) | ||||
n_addresses = 0; | ||||
for (a = addresses, n = 0; n < n_addresses; n++, a++) { | for (a = addresses, n = 0; (int) n < n_addresses; n++, a++) { | |||
if (af != a->family) | if (af != a->family) | |||
continue; | continue; | |||
if (memcmp(addr, a->address, PROTO_ADDRESS_SIZE(af)) == 0) | if (memcmp(addr, &a->address, FAMILY_ADDRESS_SIZE(af)) == 0 ) | |||
goto found; | goto found; | |||
} | } | |||
*errnop = ENOENT; | *errnop = ENOENT; | |||
*h_errnop = HOST_NOT_FOUND; | *h_errnop = HOST_NOT_FOUND; | |||
free(addresses); | ||||
return NSS_STATUS_NOTFOUND; | return NSS_STATUS_NOTFOUND; | |||
found: | found: | |||
if (!canonical) { | if (!canonical) { | |||
if (gethostname(hn, sizeof(hn)-1) < 0) { | hn = gethostname_malloc(); | |||
*errnop = errno; | if (!hn) { | |||
*errnop = ENOMEM; | ||||
*h_errnop = NO_RECOVERY; | *h_errnop = NO_RECOVERY; | |||
return NSS_STATUS_TRYAGAIN; | ||||
free(addresses); | ||||
return NSS_STATUS_UNAVAIL; | ||||
} | } | |||
canonical = hn; | canonical = hn; | |||
} | } | |||
return fill_in_hostent( | return fill_in_hostent( | |||
canonical, additional, | canonical, additional, | |||
af, | af, | |||
addresses, n_addresses, | addresses, n_addresses, | |||
local_address_ipv4, | local_address_ipv4, | |||
host, | host, | |||
buffer, buflen, | buffer, buflen, | |||
errnop, h_errnop, | errnop, h_errnop, | |||
ttlp, | ttlp, | |||
NULL); | NULL); | |||
} | } | |||
enum nss_status _nss_myhostname_gethostbyaddr_r( | NSS_GETHOSTBYNAME_FALLBACKS(myhostname); | |||
const void* addr, socklen_t len, | NSS_GETHOSTBYADDR_FALLBACKS(myhostname); | |||
int af, | ||||
struct hostent *host, | ||||
char *buffer, size_t buflen, | ||||
int *errnop, int *h_errnop) { | ||||
return _nss_myhostname_gethostbyaddr2_r( | ||||
addr, len, | ||||
af, | ||||
host, | ||||
buffer, buflen, | ||||
errnop, h_errnop, | ||||
NULL); | ||||
} | ||||
End of changes. 50 change blocks. | ||||
159 lines changed or deleted | 109 lines changed or added | |||
This html diff was produced by rfcdiff 1.41. The latest version is available from http://tools.ietf.org/tools/rfcdiff/ |