# HG changeset patch # User Derek R. Price # Date 1126584915 0 # Node ID 85d0a6143cc4d464e0267c2b089a52bd99e958d1 # Parent 1c8ef7732db02ec182946f23255f3bc12338065a * modules/canon-host: Add canon-host.h. Depend on getaddrinfo. Make LGPL. * modules/getaddrinfo: Add link to opengroup spec. Depend on strdup. Make canon-host require getaddrinfo. * m4/canon-host.m4 (gl_CANON_HOST): Remove most dependencies. AC_LIBSOURCE canon-host.h. Call... (gl_PREREQ_CANON_HOST): ...this new function, which requires gl_GETADDRINFO. * m4/getaddrinfo.m4 (gl_GETADDRINFO): Compile gai_strerror when needed. Return usable errors from canon-host. * lib/canon-host.h: New file. * lib/canon-host.c (canon_host): Wrap... (canon_host_r): ...this new function, which now relies exclusively on getaddrinfo. (ch_strerror): New function. (last_cherror): New global. * lib/getaddrinfo.c: Move include of getaddrinfo.h first to test interface. (getaddrinfo): Add AI_CANONNAME functionality. Don't do arithmetic on void *. (freeaddrinfo): Free ai->ai_canonname when set. diff --git a/ChangeLog b/ChangeLog --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2005-09-12 Derek Price + + * modules/canon-host: Add canon-host.h. Depend on getaddrinfo. Make + LGPL. + * modules/getaddrinfo: Add link to opengroup spec. Depend on strdup. + 2005-09-12 Derek Price Paul Eggert diff --git a/lib/ChangeLog b/lib/ChangeLog --- a/lib/ChangeLog +++ b/lib/ChangeLog @@ -1,3 +1,17 @@ +2005-09-12 Derek Price + + Return usable errors from canon-host. + * canon-host.h: New file. + * canon-host.c (canon_host): Wrap... + (canon_host_r): ...this new function, which now relies exclusively on + getaddrinfo. + (ch_strerror): New function. + (last_cherror): New global. + * getaddrinfo.c: Move include of getaddrinfo.h first to test interface. + (getaddrinfo): Add AI_CANONNAME functionality. Don't do arithmetic on + void *. + (freeaddrinfo): Free ai->ai_canonname when set. + 2005-09-12 Derek Price Paul Eggert diff --git a/lib/canon-host.c b/lib/canon-host.c --- a/lib/canon-host.c +++ b/lib/canon-host.c @@ -1,9 +1,9 @@ /* Host name canonicalization - Copyright (C) 1995, 1999, 2000, 2002, 2003, 2004, 2005 Free Software + Copyright (C) 2005 Free Software Foundation, Inc. - Written by Miles Bader + Written by Derek Price . This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as @@ -23,105 +23,77 @@ # include #endif -#include -#ifdef HAVE_UNISTD_H -# include -#endif -#include -#include -#ifdef HAVE_NETDB_H -# include -#endif -#ifdef HAVE_SYS_SOCKET_H -# include -#endif +#include "canon-host.h" -#ifdef HAVE_NETINET_IN_H -# include -#endif -#ifdef HAVE_ARPA_INET_H -# include -#endif - +#include "getaddrinfo.h" #include "strdup.h" -/* Returns the canonical hostname associated with HOST (allocated in a static - buffer), or NULL if it can't be determined. */ -char * -canon_host (char const *host) -{ - char *h_addr_copy = NULL; + -#if HAVE_GETADDRINFO - { - struct addrinfo hint = { 0, }; - struct addrinfo *res = NULL; - hint.ai_flags = AI_CANONNAME; - if (getaddrinfo (host, NULL, &hint, &res) == 0) - { - h_addr_copy = strdup (res->ai_canonname); - freeaddrinfo (res); - } - } -#elif HAVE_GETHOSTBYNAME - { - struct hostent *he = gethostbyname (host); +/* Store the last error for the single-threaded version of this function. */ +static int last_cherror; - if (he) - { -# ifdef HAVE_GETHOSTBYADDR - char *addr = NULL; + - /* Try and get an ascii version of the numeric host address. */ - switch (he->h_addrtype) - { -# ifdef HAVE_INET_NTOA - case AF_INET: - addr = inet_ntoa (*(struct in_addr *) he->h_addr); - break; -# endif /* HAVE_INET_NTOA */ - } - - if (addr && strcmp (he->h_name, addr) == 0) - { - /* gethostbyname has returned a string representation of the IP - address, for example, "127.0.0.1". So now, look up the host - name via the address. Although it may seem reasonable to look - up the host name via the address, we must not pass `he->h_addr' - directly to gethostbyaddr because on some systems he->h_addr - is located in a static library buffer that is reused in the - gethostbyaddr call. Make a copy and use that instead. */ - h_addr_copy = (char *) malloc (he->h_length); - if (h_addr_copy == NULL) - he = NULL; - else - { - memcpy (h_addr_copy, he->h_addr, he->h_length); - he = gethostbyaddr (h_addr_copy, he->h_length, he->h_addrtype); - free (h_addr_copy); - } - } -# endif /* HAVE_GETHOSTBYADDR */ - - if (he) - h_addr_copy = strdup (he->h_name); - } - } -#endif /* HAVE_GETHOSTBYNAME */ - - return h_addr_copy; +/* Single-threaded of wrapper for canon_host_r. After a NULL return, error + messages may be retrieved via ch_strerror(). + */ +char * +canon_host (const char *host) +{ + return canon_host_r (host, &last_cherror); } -#ifdef TEST_CANON_HOST -int -main (int argc, char **argv) + + +/* Returns a malloc'd string containing the canonical hostname associated with + HOST, or NULL if a canonical name cannot be determined. On NULL return, if + CHERROR is not NULL, *CHERROR will be set to an error code as returned by + getaddrinfo(). Error codes from CHERROR may be converted to a string + suitable for error messages by ch_strerror_r() or gai_strerror(). + + WARNINGS + HOST must be a string representation of a resolvable name for this host. + Strings containing an IP address in dotted decimal notation will be + returned as-is, without further resolution. + + The use of the word "canonical" in this context is unfortunate but + entrenched. The value returned by this function will be the end result + of the resolution of any CNAME chains in the DNS. There may only be one + such value for any given hostname, though the actual IP address + referenced by this value and the device using that IP address may each + actually have any number of such "canonical" hostnames. See the POSIX + getaddrinfo spec , + RFC 1034 , & RFC 2181 + for more on what this confusing + term really refers to. + */ +char * +canon_host_r (char const *host, int *cherror) { - int i; - for (i = 1; i < argc; i++) + char *retval = NULL; + static struct addrinfo hints; + struct addrinfo *res = NULL; + int status; + + hints.ai_flags = AI_CANONNAME; + status = getaddrinfo (host, NULL, &hints, &res); + if (!status) { - char *s = canon_host (argv[i]); - printf ("%s: %s\n", argv[i], (s ? s : "")); + retval = strdup (res->ai_canonname); + freeaddrinfo (res); } - exit (0); + else if (cherror) + *cherror = status; + + return retval; } -#endif /* TEST_CANON_HOST */ + + + +/* Return a string describing the last error encountered by canon_host. */ +const char * +ch_strerror (void) +{ + return gai_strerror (last_cherror); +} diff --git a/lib/canon-host.h b/lib/canon-host.h new file mode 100644 --- /dev/null +++ b/lib/canon-host.h @@ -0,0 +1,30 @@ +/* Host name canonicalization + + Copyright (C) 2005 Free Software Foundation, Inc. + + Written by Derek Price + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2, or (at + your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ + +#ifndef CANON_HOST_H +# define CANON_HOST_H 1 + +char *canon_host (char const *host); +char *canon_host_r (char const *host, int *cherror); + +const char *ch_strerror (void); +#define ch_strerror_r(cherror) gai_strerror (cherror); + +#endif /* !CANON_HOST_H */ diff --git a/lib/getaddrinfo.c b/lib/getaddrinfo.c --- a/lib/getaddrinfo.c +++ b/lib/getaddrinfo.c @@ -20,6 +20,8 @@ # include #endif +#include "getaddrinfo.h" + /* Get calloc. */ #include @@ -35,7 +37,7 @@ #define _(String) gettext (String) #define N_(String) String -#include "getaddrinfo.h" +#include "strdup.h" static inline bool validate_family (int family) @@ -67,7 +69,7 @@ struct hostent *he; size_t sinlen; - if (hints && hints->ai_flags) + if (hints && (hints->ai_flags & ~AI_CANONNAME)) /* FIXME: Support more flags. */ return EAI_BADFLAGS; @@ -127,7 +129,7 @@ #if HAVE_IPV6 case PF_INET6: { - struct sockaddr_in6 *sinp = (void *) tmp + sizeof (*tmp); + struct sockaddr_in6 *sinp = (char *) tmp + sizeof (*tmp); if (se) sinp->sin6_port = se->s_port; @@ -146,7 +148,7 @@ #if HAVE_IPV4 case PF_INET: { - struct sockaddr_in *sinp = (void *) tmp + sizeof (*tmp); + struct sockaddr_in *sinp = (char *) tmp + sizeof (*tmp); if (se) sinp->sin_port = se->s_port; @@ -167,6 +169,22 @@ return EAI_NODATA; } + if (hints && hints->ai_flags & AI_CANONNAME) + { + const char *cn; + if (he->h_name) + cn = he->h_name; + else + cn = nodename; + + tmp->ai_canonname = strdup (cn); + if (!tmp->ai_canonname) + { + free (tmp); + return EAI_MEMORY; + } + } + tmp->ai_protocol = (hints) ? hints->ai_protocol : 0; tmp->ai_socktype = (hints) ? hints->ai_socktype : 0; tmp->ai_addr->sa_family = he->h_addrtype; @@ -188,6 +206,8 @@ cur = ai; ai = ai->ai_next; + + if (cur->ai_canonname) free (cur->ai_canonname); free (cur); } } diff --git a/lib/getaddrinfo.h b/lib/getaddrinfo.h --- a/lib/getaddrinfo.h +++ b/lib/getaddrinfo.h @@ -25,7 +25,7 @@ # include # include -# if defined HAVE_GETADDRINFO && !HAVE_GETADDRINFO +# if !HAVE_GETADDRINFO /* Structure to contain information about address of a service provider. */ struct addrinfo @@ -90,6 +90,6 @@ . */ extern const char *gai_strerror (int ecode); -# endif +# endif /* !HAVE_GETADDRINFO */ #endif /* GETADDRINFO_H */ diff --git a/m4/ChangeLog b/m4/ChangeLog --- a/m4/ChangeLog +++ b/m4/ChangeLog @@ -1,3 +1,12 @@ +2005-09-12 Derek Price + + Make canon-host require getaddrinfo. + * canon-host.m4 (gl_CANON_HOST): Remove most dependencies. + AC_LIBSOURCE canon-host.h. Call... + (gl_PREREQ_CANON_HOST): ...this new function, which requires + gl_GETADDRINFO. + * getaddrinfo.m4 (gl_GETADDRINFO): Compile gai_strerror when needed. + 2005-09-12 Derek Price Paul Eggert diff --git a/m4/canon-host.m4 b/m4/canon-host.m4 --- a/m4/canon-host.m4 +++ b/m4/canon-host.m4 @@ -1,4 +1,4 @@ -# canon-host.m4 serial 6 +# canon-host.m4 serial 7 dnl Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, @@ -6,18 +6,11 @@ AC_DEFUN([gl_CANON_HOST], [ - AC_LIBSOURCES([canon-host.c]) + AC_LIBSOURCES([canon-host.c, canon-host.h]) AC_LIBOBJ([canon-host]) - - dnl Prerequisites of lib/canon-host.c. - AC_CHECK_HEADERS_ONCE(unistd.h) - AC_CHECK_HEADERS(netdb.h sys/socket.h netinet/in.h arpa/inet.h) + gl_PREREQ_CANON_HOST +]) - dnl Add any libraries as early as possible. - dnl In particular, inet_ntoa needs -lnsl at least on Solaris 2.5.1, - dnl so we have to add -lnsl to LIBS before checking for that function. - AC_SEARCH_LIBS(gethostbyname, [inet nsl]) - - dnl These come from -lnsl on Solaris 2.5.1. - AC_CHECK_FUNCS(getaddrinfo gethostbyname gethostbyaddr inet_ntoa) +AC_DEFUN([gl_PREREQ_CANON_HOST], [ + AC_REQUIRE([gl_GETADDRINFO]) ]) diff --git a/m4/getaddrinfo.m4 b/m4/getaddrinfo.m4 --- a/m4/getaddrinfo.m4 +++ b/m4/getaddrinfo.m4 @@ -1,4 +1,4 @@ -# getaddrinfo.m4 serial 2 +# getaddrinfo.m4 serial 3 dnl Copyright (C) 2004 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, @@ -7,7 +7,7 @@ AC_DEFUN([gl_GETADDRINFO], [ AC_SEARCH_LIBS(getaddrinfo, nsl socket) - AC_REPLACE_FUNCS(getaddrinfo) + AC_REPLACE_FUNCS(getaddrinfo gai_strerror) gl_PREREQ_GETADDRINFO ]) diff --git a/modules/canon-host b/modules/canon-host --- a/modules/canon-host +++ b/modules/canon-host @@ -4,9 +4,11 @@ Files: lib/canon-host.c +lib/canon-host.h m4/canon-host.m4 Depends-on: +getaddrinfo strdup configure.ac: @@ -15,9 +17,10 @@ Makefile.am: Include: +#include "canon-host.h" License: -GPL +LGPL Maintainer: Jim Meyering diff --git a/modules/getaddrinfo b/modules/getaddrinfo --- a/modules/getaddrinfo +++ b/modules/getaddrinfo @@ -1,5 +1,5 @@ Description: -Get address information. +getaddrinfo() function: Get address information. Files: lib/getaddrinfo.h @@ -12,6 +12,7 @@ restrict gettext-h stdbool +strdup configure.ac: gl_GETADDRINFO