Jim Meyering wrote: >>suitable for gai_strerror. I'll have to extend lib/getaddrinfo.c a >>little to fill in ai_canonhost and add the gai_strerror function. Would >>that be acceptable? >> >> > >Good idea. More than `acceptable' :-) > >
Patch attached. I decided the reverse-lookup which used to be present in canon-host.c when gethostbyname returned an IP address was the bug since: - all the documentation on getaddrinfo and canonical names was quite explicit about reverse lookups *not* being done - canon_host used to trust getaddrinfo when it was present - the documentation on gethostbyname also implied that the hostname would be resolved and a test program on 1 linux & NetBSD 1.6.1 showed that it was. If we stumble across any systems where gethostbyname returns an IP address when it is given a real hostname, this can be fixed then. 2005-09-05 Derek Price <[EMAIL PROTECTED]> * 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. (freeaddrinfo): Free ai->ai_canonname when set. This works on 1 Linux and I am installing in CVS to run it through our compile farm. If all goes well and no one objects, I'll install it in GNULIB in a few days. Cheers, Derek -- Derek R. Price CVS Solutions Architect Ximbiot <http://ximbiot.com> v: +1 717.579.6168 f: +1 717.234.3125 <mailto:[EMAIL PROTECTED]>
Index: lib/canon-host.c =================================================================== RCS file: /cvsroot/gnulib/gnulib/lib/canon-host.c,v retrieving revision 1.18 diff -u -p -r1.18 canon-host.c --- lib/canon-host.c 24 Jun 2005 17:30:33 -0000 1.18 +++ lib/canon-host.c 6 Sep 2005 02:46:13 -0000 @@ -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 <[EMAIL PROTECTED]> + Written by Derek Price <[EMAIL PROTECTED]>. 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,76 @@ # include <config.h> #endif -#include <sys/types.h> -#ifdef HAVE_UNISTD_H -# include <unistd.h> -#endif -#include <stdlib.h> -#include <string.h> -#ifdef HAVE_NETDB_H -# include <netdb.h> -#endif -#ifdef HAVE_SYS_SOCKET_H -# include <sys/socket.h> -#endif - -#ifdef HAVE_NETINET_IN_H -# include <netinet/in.h> -#endif -#ifdef HAVE_ARPA_INET_H -# include <arpa/inet.h> -#endif +#include "canon-host.h" +#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. */ + + +/* Store the last error for the single-threaded version of this function. */ +static int last_cherror; + + + +/* Single-threaded of wrapper for canon_host_r. After a NULL return, error + messages may be retrieved via ch_strerror(). + */ char * -canon_host (char const *host) +canon_host (const char *host) { - char *h_addr_copy = NULL; + return canon_host_r (host, &last_cherror); +} -#if HAVE_GETADDRINFO - { - struct addrinfo hint = { 0, }; + + +/* 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 <http://www.opengroup.org/susv3xsh/getaddrinfo.html">, + RFC 1034 <http://www.faqs.org/rfcs/rfc1034.html>, & RFC 2181 + <http://www.faqs.org/rfcs/rfc2181.html> for more on what this confusing + term really refers to. + */ +char * +canon_host_r (char const *host, int *cherror) +{ + char *retval = NULL; + static struct addrinfo hints = { .ai_flags = AI_CANONNAME, }; struct addrinfo *res = NULL; - hint.ai_flags = AI_CANONNAME; - if (getaddrinfo (host, NULL, &hint, &res) == 0) - { - h_addr_copy = strdup (res->ai_canonname); + int status; + + status = getaddrinfo (host, NULL, &hints, &res); + if (!status) + { + retval = strdup (res->ai_canonname); freeaddrinfo (res); - } - } -#elif HAVE_GETHOSTBYNAME - { - struct hostent *he = gethostbyname (host); - - 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 */ + } + else if (cherror) + *cherror = status; - return h_addr_copy; + return retval; } -#ifdef TEST_CANON_HOST -int -main (int argc, char **argv) + + +/* Return a string describing the last error encountered by canon_host. */ +const char * +ch_strerror (void) { - int i; - for (i = 1; i < argc; i++) - { - char *s = canon_host (argv[i]); - printf ("%s: %s\n", argv[i], (s ? s : "<undef>")); - } - exit (0); + return gai_strerror (last_cherror); } -#endif /* TEST_CANON_HOST */ Index: lib/canon-host.h =================================================================== RCS file: lib/canon-host.h diff -N lib/canon-host.h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ lib/canon-host.h 6 Sep 2005 02:46:13 -0000 @@ -0,0 +1,30 @@ +/* Host name canonicalization + + Copyright (C) 2005 Free Software Foundation, Inc. + + Written by Derek Price <[EMAIL PROTECTED]> + + 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 */ Index: lib/getaddrinfo.c =================================================================== RCS file: /cvsroot/gnulib/gnulib/lib/getaddrinfo.c,v retrieving revision 1.3 diff -u -p -r1.3 getaddrinfo.c --- lib/getaddrinfo.c 14 May 2005 06:03:58 -0000 1.3 +++ lib/getaddrinfo.c 6 Sep 2005 02:46:13 -0000 @@ -20,6 +20,8 @@ # include <config.h> #endif +#include "getaddrinfo.h" + /* Get calloc. */ #include <stdlib.h> @@ -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 @@ getaddrinfo (const char *restrict nodena 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; @@ -167,6 +169,22 @@ getaddrinfo (const char *restrict nodena return EAI_NODATA; } + if (hints && hints->flags & AI_CANONNAME) + { + 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 @@ freeaddrinfo (struct addrinfo *ai) cur = ai; ai = ai->ai_next; + + if (cur->ai_canonname) free (cur->ai_canonname); free (cur); } } Index: m4/canon-host.m4 =================================================================== RCS file: /cvsroot/gnulib/gnulib/m4/canon-host.m4,v retrieving revision 1.7 diff -u -p -r1.7 canon-host.m4 --- m4/canon-host.m4 21 Mar 2005 22:06:27 -0000 1.7 +++ m4/canon-host.m4 6 Sep 2005 02:46:13 -0000 @@ -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 @@ dnl with or without modifications, as lo AC_DEFUN([gl_CANON_HOST], [ - AC_LIBSOURCES([canon-host.c]) + AC_LIBSOURCES([canon-host.c, canon-host.h]) AC_LIBOBJ([canon-host]) + gl_PREREQ_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) - - 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]) ]) Index: m4/getaddrinfo.m4 =================================================================== RCS file: /cvsroot/gnulib/gnulib/m4/getaddrinfo.m4,v retrieving revision 1.3 diff -u -p -r1.3 getaddrinfo.m4 --- m4/getaddrinfo.m4 10 May 2005 12:32:35 -0000 1.3 +++ m4/getaddrinfo.m4 6 Sep 2005 02:46:13 -0000 @@ -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 @@ dnl with or without modifications, as lo AC_DEFUN([gl_GETADDRINFO], [ AC_SEARCH_LIBS(getaddrinfo, nsl socket) - AC_REPLACE_FUNCS(getaddrinfo) + AC_REPLACE_FUNCS(getaddrinfo gai_strerror) gl_PREREQ_GETADDRINFO ]) Index: modules/canon-host =================================================================== RCS file: /cvsroot/gnulib/gnulib/modules/canon-host,v retrieving revision 1.6 diff -u -p -r1.6 canon-host --- modules/canon-host 21 Mar 2005 22:07:25 -0000 1.6 +++ modules/canon-host 6 Sep 2005 02:46:13 -0000 @@ -4,9 +4,11 @@ usually the host name including FQDN. Files: lib/canon-host.c +lib/canon-host.h m4/canon-host.m4 Depends-on: +getaddrinfo strdup configure.ac: @@ -15,9 +17,10 @@ gl_CANON_HOST Makefile.am: Include: +#include "canon-host.h" License: -GPL +LGPL Maintainer: Jim Meyering Index: modules/getaddrinfo =================================================================== RCS file: /cvsroot/gnulib/gnulib/modules/getaddrinfo,v retrieving revision 1.3 diff -u -p -r1.3 getaddrinfo --- modules/getaddrinfo 6 Jul 2005 15:58:47 -0000 1.3 +++ modules/getaddrinfo 6 Sep 2005 02:46:13 -0000 @@ -1,5 +1,5 @@ Description: -Get address information. +getaddrinfo() function: Get address information. Files: lib/getaddrinfo.h @@ -12,6 +12,7 @@ Depends-on: restrict gettext-h stdbool +strdup configure.ac: gl_GETADDRINFO
_______________________________________________ bug-gnulib mailing list bug-gnulib@gnu.org http://lists.gnu.org/mailman/listinfo/bug-gnulib