bug-gnulib
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: canon-host errors


From: Derek Price
Subject: Re: canon-host errors
Date: Mon, 05 Sep 2005 23:27:07 -0400
User-agent: Mozilla Thunderbird 1.0.6 (Windows/20050716)

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  <address@hidden>

    * 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:address@hidden>

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 <address@hidden>
+   Written by Derek Price <address@hidden>.
 
    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 <address@hidden>
+
+   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

reply via email to

[Prev in Thread] Current Thread [Next in Thread]