X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Fnss-myhostname%2Fnss-myhostname.c;h=fed76c62e72f1ce2e915c556e4ff60991d9782bd;hb=dc75168823540076b354135f6e2de7a9a978fbca;hp=23646e6e8a6c68924f27a35da9856c639af688da;hpb=d4c9895d93700d20b7d092244a278009789d8e74;p=elogind.git diff --git a/src/nss-myhostname/nss-myhostname.c b/src/nss-myhostname/nss-myhostname.c index 23646e6e8..fed76c62e 100644 --- a/src/nss-myhostname/nss-myhostname.c +++ b/src/nss-myhostname/nss-myhostname.c @@ -19,31 +19,22 @@ along with systemd; If not, see . ***/ -#include #include -#include #include #include #include -#include #include #include -#include #include "local-addresses.h" #include "macro.h" #include "nss-util.h" #include "util.h" -/* Ensure that glibc's assert is used. We cannot use assert from macro.h, as - * libnss_myhostname will be linked into arbitrary programs which will, in turn - * attempt to write to the journal via log_dispatch() */ -#include - /* 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 * 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 "localhost" or so. */ #define LOCALADDRESS_IPV4 (htonl(0x7F000002)) #define LOCALADDRESS_IPV6 &in6addr_loopback @@ -52,6 +43,13 @@ NSS_GETHOSTBYNAME_PROTOTYPES(myhostname); NSS_GETHOSTBYADDR_PROTOTYPES(myhostname); +static bool is_gateway(const char *hostname) { + assert(hostname); + + return streq(hostname, "gateway") || + streq(hostname, "gateway."); +} + enum nss_status _nss_myhostname_gethostbyname4_r( const char *name, struct gaih_addrtuple **pat, @@ -82,6 +80,18 @@ enum nss_status _nss_myhostname_gethostbyname4_r( canonical = "localhost"; local_address_ipv4 = htonl(INADDR_LOOPBACK); + + } else if (is_gateway(name)) { + + n_addresses = local_gateways(NULL, 0, AF_UNSPEC, &addresses); + if (n_addresses <= 0) { + *errnop = ENOENT; + *h_errnop = HOST_NOT_FOUND; + return NSS_STATUS_NOTFOUND; + } + + canonical = "gateway"; + } else { hn = gethostname_malloc(); if (!hn) { @@ -97,7 +107,7 @@ enum nss_status _nss_myhostname_gethostbyname4_r( return NSS_STATUS_NOTFOUND; } - n_addresses = local_addresses(&addresses); + n_addresses = local_addresses(NULL, 0, AF_UNSPEC, &addresses); if (n_addresses < 0) n_addresses = 0; @@ -170,6 +180,11 @@ enum nss_status _nss_myhostname_gethostbyname4_r( if (ttlp) *ttlp = 0; + /* Explicitly reset all error variables */ + *errnop = 0; + *h_errnop = NETDB_SUCCESS; + h_errno = 0; + return NSS_STATUS_SUCCESS; } @@ -195,7 +210,7 @@ static enum nss_status fill_in_hostent( assert(errnop); assert(h_errnop); - alen = PROTO_ADDRESS_SIZE(af); + alen = FAMILY_ADDRESS_SIZE(af); for (a = addresses, n = 0, c = 0; n < n_addresses; a++, n++) if (af == a->family) @@ -294,6 +309,11 @@ static enum nss_status fill_in_hostent( if (canonp) *canonp = r_name; + /* Explicitly reset all error variables */ + *errnop = 0; + *h_errnop = NETDB_SUCCESS; + h_errno = 0; + return NSS_STATUS_SUCCESS; } @@ -309,7 +329,7 @@ enum nss_status _nss_myhostname_gethostbyname3_r( _cleanup_free_ struct local_address *addresses = NULL; const char *canonical, *additional = NULL; _cleanup_free_ char *hn = NULL; - uint32_t local_address_ipv4; + uint32_t local_address_ipv4 = 0; int n_addresses = 0; assert(name); @@ -330,6 +350,18 @@ enum nss_status _nss_myhostname_gethostbyname3_r( if (is_localhost(name)) { canonical = "localhost"; local_address_ipv4 = htonl(INADDR_LOOPBACK); + + } else if (is_gateway(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) { @@ -344,7 +376,7 @@ enum nss_status _nss_myhostname_gethostbyname3_r( return NSS_STATUS_NOTFOUND; } - n_addresses = local_addresses(&addresses); + n_addresses = local_addresses(NULL, 0, af, &addresses); if (n_addresses < 0) n_addresses = 0; @@ -379,6 +411,7 @@ enum nss_status _nss_myhostname_gethostbyaddr2_r( _cleanup_free_ char *hn = NULL; int n_addresses = 0; struct local_address *a; + bool additional_from_hostname = false; unsigned n; assert(addr); @@ -387,14 +420,19 @@ enum nss_status _nss_myhostname_gethostbyaddr2_r( 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; *h_errnop = NO_RECOVERY; return NSS_STATUS_UNAVAIL; } if (af == AF_INET) { - if ((*(uint32_t*) addr) == LOCALADDRESS_IPV4) goto found; @@ -404,29 +442,41 @@ enum nss_status _nss_myhostname_gethostbyaddr2_r( goto found; } - } else if (af == AF_INET6) { + } else { + assert(af == AF_INET6); if (memcmp(addr, LOCALADDRESS_IPV6, 16) == 0) { - additional = "localhost"; + canonical = "localhost"; + additional_from_hostname = true; goto found; } + } - } else { - *errnop = EAFNOSUPPORT; - *h_errnop = NO_DATA; - return NSS_STATUS_UNAVAIL; + 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; + } } - n_addresses = local_addresses(&addresses); - if (n_addresses < 0) - n_addresses = 0; + free(addresses); + addresses = NULL; - for (a = addresses, n = 0; (int) n < n_addresses; n++, a++) { - if (af != a->family) - continue; + 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, PROTO_ADDRESS_SIZE(af)) == 0) - goto found; + if (memcmp(addr, &a->address, FAMILY_ADDRESS_SIZE(af)) == 0) { + canonical = "gateway"; + goto found; + } + } } *errnop = ENOENT; @@ -435,7 +485,7 @@ enum nss_status _nss_myhostname_gethostbyaddr2_r( return NSS_STATUS_NOTFOUND; found: - if (!canonical) { + if (!canonical || (!additional && additional_from_hostname)) { hn = gethostname_malloc(); if (!hn) { *errnop = ENOMEM; @@ -443,7 +493,11 @@ found: return NSS_STATUS_TRYAGAIN; } - canonical = hn; + if (!canonical) + canonical = hn; + + if (!additional && additional_from_hostname) + additional = hn; } return fill_in_hostent( @@ -456,7 +510,6 @@ found: errnop, h_errnop, ttlp, NULL); - } NSS_GETHOSTBYNAME_FALLBACKS(myhostname);