X-Git-Url: https://git.decadent.org.uk/gitweb/?p=nfs-utils.git;a=blobdiff_plain;f=support%2Fexport%2Fhostname.c;h=3e949a18fe52255b51a4d77713f28b1679f16b75;hp=232e04038daaa8f5b0c8592369ee5deff3a99c9e;hb=b50ad13298b3e9519a9bdecb8c146c9ecf39cef8;hpb=9c3f7a220b4812c5d560db5fcacad790fc8b17af diff --git a/support/export/hostname.c b/support/export/hostname.c index 232e040..3e949a1 100644 --- a/support/export/hostname.c +++ b/support/export/hostname.c @@ -30,20 +30,6 @@ #include "sockaddr.h" #include "exportfs.h" -#ifndef HAVE_DECL_AI_ADDRCONFIG -#define AI_ADDRCONFIG 0 -#endif - -#ifdef HAVE_GETNAMEINFO -static socklen_t -sockaddr_size(const struct sockaddr *sap) -{ - if (sap->sa_family != AF_INET) - return 0; - return (socklen_t)sizeof(struct sockaddr_in); -} -#endif /* HAVE_GETNAMEINFO */ - /** * host_ntop - generate presentation address given a sockaddr * @sap: pointer to socket address @@ -56,7 +42,7 @@ sockaddr_size(const struct sockaddr *sap) char * host_ntop(const struct sockaddr *sap, char *buf, const size_t buflen) { - socklen_t salen = sockaddr_size(sap); + socklen_t salen = nfs_sockaddr_length(sap); int error; memset(buf, 0, buflen); @@ -117,7 +103,7 @@ host_pton(const char *paddr) .ai_family = AF_UNSPEC, }; struct sockaddr_in sin; - int error; + int error, inet4; /* * Although getaddrinfo(3) is easier to use and supports @@ -129,12 +115,17 @@ host_pton(const char *paddr) * have a real AF_INET presentation address, before invoking * getaddrinfo(3) to generate the full addrinfo list. */ + inet4 = 1; if (inet_pton(AF_INET, paddr, &sin.sin_addr) == 0) - return NULL; + inet4 = 0; error = getaddrinfo(paddr, NULL, &hint, &ai); switch (error) { case 0: + if (!inet4 && ai->ai_addr->sa_family == AF_INET) { + freeaddrinfo(ai); + break; + } return ai; case EAI_NONAME: if (paddr == NULL) @@ -168,10 +159,14 @@ host_addrinfo(const char *hostname) { struct addrinfo *ai = NULL; struct addrinfo hint = { +#ifdef IPV6_SUPPORTED + .ai_family = AF_UNSPEC, +#else .ai_family = AF_INET, +#endif /* don't return duplicates */ .ai_protocol = (int)IPPROTO_UDP, - .ai_flags = AI_ADDRCONFIG | AI_CANONNAME, + .ai_flags = AI_CANONNAME, }; int error; @@ -208,7 +203,7 @@ __attribute_malloc__ char * host_canonname(const struct sockaddr *sap) { - socklen_t salen = sockaddr_size(sap); + socklen_t salen = nfs_sockaddr_length(sap); char buf[NI_MAXHOST]; int error; @@ -263,17 +258,19 @@ host_canonname(const struct sockaddr *sap) * @sap: pointer to socket address to look up * * Reverse and forward lookups are performed to ensure the address has - * proper forward and reverse mappings. + * matching forward and reverse mappings. * - * Returns address info structure with ai_canonname filled in, or NULL - * if no information is available for @sap. Caller must free the returned - * structure with freeaddrinfo(3). + * Returns addrinfo structure with just the provided address with + * ai_canonname filled in. If there is a problem with resolution or + * the resolved records don't match up properly then it returns NULL + * + * Caller must free the returned structure with freeaddrinfo(3). */ __attribute_malloc__ struct addrinfo * host_reliable_addrinfo(const struct sockaddr *sap) { - struct addrinfo *ai; + struct addrinfo *ai, *a; char *hostname; hostname = host_canonname(sap); @@ -281,9 +278,31 @@ host_reliable_addrinfo(const struct sockaddr *sap) return NULL; ai = host_addrinfo(hostname); + if (!ai) + goto out_free_hostname; + + /* make sure there's a matching address in the list */ + for (a = ai; a; a = a->ai_next) + if (nfs_compare_sockaddr(a->ai_addr, sap)) + break; + + freeaddrinfo(ai); + if (!a) + goto out_free_hostname; + + /* get addrinfo with just the original address */ + ai = host_numeric_addrinfo(sap); + if (!ai) + goto out_free_hostname; + + /* and populate its ai_canonname field */ + free(ai->ai_canonname); + ai->ai_canonname = hostname; + return ai; +out_free_hostname: free(hostname); - return ai; + return NULL; } /** @@ -298,8 +317,8 @@ __attribute_malloc__ struct addrinfo * host_numeric_addrinfo(const struct sockaddr *sap) { - socklen_t salen = sockaddr_size(sap); - char buf[INET_ADDRSTRLEN]; + socklen_t salen = nfs_sockaddr_length(sap); + char buf[INET6_ADDRSTRLEN]; struct addrinfo *ai; int error;