bug-gnulib
[Top][All Lists]
Advanced

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

[Bug-gnulib] Re: getaddrinfo


From: Simon Josefsson
Subject: [Bug-gnulib] Re: getaddrinfo
Date: Mon, 08 Nov 2004 13:49:27 +0100
User-agent: Gnus/5.110003 (No Gnus v0.3) Emacs/21.3.50 (gnu/linux)

Simon Josefsson <address@hidden> writes:

> Bruno Haible <address@hidden> writes:
>
>> Simon Josefsson wrote:
>>> This is unfinished, but I wanted to hear what people think of this.
>>
>> Sounds useful: getaddrinfo is in POSIX, but Solaris 7, AIX 3, IRIX 6,
>> HP-UX 10, HP-UX 11, OSF/1 4.0 don't have it, and Solaris 8, 9 have it
>> only in libsocket.
>>
>>> In particular, is it a good idea to add a partial implementation of an
>>> API?
>>
>> It depends :-) Certainly it's better if an implementation is complete,
>> but we already have incomplete POSIX replacements in gnulib:
>>   - an ftruncate which falls back to EIO when system support is insufficient.
>>   - a gethostname which falls back to the empty string.
>>   - a poll which doesn't work if the system's select() is too limited,
>>   - a regex which doesn't cope correctly with multibyte characters.
>
> I'll improve the patch, test it on some platforms, and then send an
> updated version...

I haven't really improved the patch, but the existing functionality
seem to be sufficient for my needs, and nobody has complained that it
doesn't work yet...  The latest GNU SASL release uses it, and I'll be
using it in more packages soon.  It feels good to now be able to
forget all about gethostbyname etc.

Ok to install?

2004-11-08  Simon Josefsson  <address@hidden>

        * MODULES.html.sh (Support for systems lacking POSIX:2001): Add
        getaddrinfo.

        * modules/getaddrinfo: New file.

2004-11-08  Simon Josefsson  <address@hidden>

        * getaddrinfo.m4: New file.

2004-11-08  Simon Josefsson  <address@hidden>

        * getaddrinfo.h, getaddrinfo.c: New file.

Index: modules/getaddrinfo
===================================================================
RCS file: modules/getaddrinfo
diff -N modules/getaddrinfo
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ modules/getaddrinfo 8 Nov 2004 12:46:54 -0000
@@ -0,0 +1,23 @@
+Description:
+Get address information.
+
+Files:
+lib/getaddrinfo.h
+lib/getaddrinfo.c
+m4/getaddrinfo.m4
+
+Depends-on:
+restrict
+gettext
+
+configure.ac:
+gl_GETADDRINFO
+
+Makefile.am:
+lib_SOURCES += getaddrinfo.h
+
+Include:
+"getaddrinfo.h"
+
+Maintainer:
+Simon Josefsson
Index: m4/getaddrinfo.m4
===================================================================
RCS file: m4/getaddrinfo.m4
diff -N m4/getaddrinfo.m4
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ m4/getaddrinfo.m4   8 Nov 2004 12:46:54 -0000
@@ -0,0 +1,19 @@
+# getaddrinfo.m4 serial 1
+dnl Copyright (C) 2004 Free Software Foundation, Inc.
+dnl This file is free software, distributed under the terms of the GNU
+dnl General Public License.  As a special exception to the GNU General
+dnl Public License, this file may be distributed as part of a program
+dnl that contains a configuration script generated by Autoconf, under
+dnl the same distribution terms as the rest of that program.
+
+AC_DEFUN([gl_GETADDRINFO],
+[
+  AC_REPLACE_FUNCS(getaddrinfo)
+  gl_PREREQ_GETADDRINFO
+])
+
+# Prerequisites of lib/getaddrinfo.h.
+AC_DEFUN([gl_PREREQ_GETADDRINFO], [
+  AC_REQUIRE([gl_C_RESTRICT])
+  :
+])
Index: lib/getaddrinfo.h
===================================================================
RCS file: lib/getaddrinfo.h
diff -N lib/getaddrinfo.h
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ lib/getaddrinfo.h   8 Nov 2004 12:46:54 -0000
@@ -0,0 +1,82 @@
+/* Get address information.
+   Copyright (C) 1996-2002, 2003, 2004 Free Software Foundation, Inc.
+   Contributed by Simon Josefsson <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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+
+#ifndef        GETADDRINFO_H
+# define GETADDRINFO_H
+
+/* Get getaddrinfo declarations, if available. */
+# include <sys/socket.h>
+# include <netdb.h>
+
+# if defined HAVE_GETADDRINFO && !HAVE_GETADDRINFO
+
+/* Get socklen_t, struct sockaddr. */
+#  include <sys/types.h>
+
+/* Structure to contain information about address of a service provider.  */
+struct addrinfo
+{
+  int ai_flags;                        /* Input flags.  */
+  int ai_family;               /* Protocol family for socket.  */
+  int ai_socktype;             /* Socket type.  */
+  int ai_protocol;             /* Protocol for socket.  */
+  socklen_t ai_addrlen;                /* Length of socket address.  */
+  struct sockaddr *ai_addr;    /* Socket address for socket.  */
+  char *ai_canonname;          /* Canonical name for service location.  */
+  struct addrinfo *ai_next;    /* Pointer to next in list.  */
+};
+
+/* Possible values for `ai_flags' field in `addrinfo' structure.  */
+# define AI_PASSIVE    0x0001  /* Socket address is intended for `bind'.  */
+# define AI_CANONNAME  0x0002  /* Request for canonical name.  */
+# define AI_NUMERICHOST        0x0004  /* Don't use name resolution.  */
+# define AI_V4MAPPED   0x0008  /* IPv4 mapped addresses are acceptable.  */
+# define AI_ALL                0x0010  /* Return IPv4 mapped and IPv6 
addresses.  */
+# define AI_ADDRCONFIG 0x0020  /* Use configuration of this host to choose
+                                  returned address type..  */
+
+/* Error values for `getaddrinfo' function.  */
+# define EAI_BADFLAGS    -1    /* Invalid value for `ai_flags' field.  */
+# define EAI_NONAME      -2    /* NAME or SERVICE is unknown.  */
+# define EAI_AGAIN       -3    /* Temporary failure in name resolution.  */
+# define EAI_FAIL        -4    /* Non-recoverable failure in name res.  */
+# define EAI_NODATA      -5    /* No address associated with NAME.  */
+# define EAI_FAMILY      -6    /* `ai_family' not supported.  */
+# define EAI_SOCKTYPE    -7    /* `ai_socktype' not supported.  */
+# define EAI_SERVICE     -8    /* SERVICE not supported for `ai_socktype'.  */
+# define EAI_ADDRFAMILY          -9    /* Address family for NAME not 
supported.  */
+# define EAI_MEMORY      -10   /* Memory allocation failure.  */
+# define EAI_SYSTEM      -11   /* System error returned in `errno'.  */
+# define EAI_OVERFLOW    -12   /* Argument buffer overflow.  */
+
+/* Translate name of a service location and/or a service name to set of
+   socket addresses.  */
+extern int getaddrinfo (const char *restrict nodename,
+                       const char *restrict servname,
+                       const struct addrinfo *restrict hints,
+                       struct addrinfo **restrict res);
+
+/* Free `addrinfo' structure AI including associated storage.  */
+extern void freeaddrinfo (struct addrinfo *ai);
+
+/* Convert error return from getaddrinfo() to a string.  */
+extern const char *gai_strerror (int ecode);
+
+# endif
+
+#endif /* GETADDRINFO_H */
Index: lib/getaddrinfo.c
===================================================================
RCS file: lib/getaddrinfo.c
diff -N lib/getaddrinfo.c
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ lib/getaddrinfo.c   8 Nov 2004 12:46:54 -0000
@@ -0,0 +1,185 @@
+/* Get address information (partial implementation).
+   Copyright (C) 1997, 2001, 2002, 2004 Free Software Foundation, Inc.
+   Contributed by Simon Josefsson <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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdio.h>
+#include <gettext.h>
+#define _(String) gettext (String)
+#define N_(String) String
+
+#include "getaddrinfo.h"
+
+/* Translate name of a service location and/or a service name to set of
+   socket addresses. */
+int
+getaddrinfo (const char *restrict nodename,
+            const char *restrict servname,
+            const struct addrinfo *restrict hints,
+            struct addrinfo **restrict res)
+{
+  struct addrinfo *tmp;
+  struct sockaddr sock;
+  struct sockaddr *sockp = &sock;
+  struct servent *se;
+  struct hostent *he;
+
+  if (hints && hints->ai_flags)
+    /* FIXME: Support more flags. */
+    return EAI_BADFLAGS;
+
+  if (hints &&
+      hints->ai_family != PF_UNSPEC &&
+      hints->ai_family != PF_INET &&
+      hints->ai_family != PF_INET6)
+    /* FIXME: Support more families. */
+    return EAI_FAMILY;
+
+  if (hints && hints->ai_socktype)
+    /* FIXME: Support more socket types. */
+    return EAI_SOCKTYPE;
+
+  if (hints &&
+      hints->ai_protocol != SOCK_STREAM &&
+      hints->ai_protocol != SOCK_DGRAM)
+      /* FIXME: Support other protocols. */
+    return EAI_SERVICE; /* FIXME: Better return code? */
+
+  if (!nodename)
+    /* FIXME: Support server bind mode. */
+    return EAI_NONAME;
+
+  if (servname)
+    {
+      /* FIXME: Use getservbyname_r if available. */
+      se = getservbyname (servname,
+                         hints->ai_protocol == SOCK_DGRAM ? "udp" : "tcp");
+      if (!se)
+       return EAI_SERVICE;
+    }
+
+  /* FIXME: Use gethostbyname_r if available. */
+  he = gethostbyname (connect_hostname);
+  if (!he || he->h_addr_list[0] == NULL)
+    return EAI_NONAME;
+
+  tmp = calloc (1, sizeof (*tmp));
+  if (!tmp)
+    return EAI_MEMORY;
+
+  tmp->ai_addr->sa_family = he->he_addrtype;
+
+  switch (tmp->ai_addr->sa_family)
+    {
+    case PF_INET6:
+      {
+       struct sockaddr_in6 *sinp;
+
+       sinp = calloc (1, sizeof (*sinp));
+       if (!sinp)
+         {
+           free (tmp);
+           return EAI_MEMORY;
+         }
+
+       sinp->sin_port = se->s_port;
+       memcpy (&sinp->sin_addr, he->h_addr_list[0], he->h_length);
+
+       tmp->ai_addr = sinp;
+       tmp->ai_addrlen = sizeof (sin);
+      }
+      break;
+
+    case PF_INET:
+      {
+       struct sockaddr_in *sinp;
+
+       sinp = calloc (1, sizeof (*sinp));
+       if (!sinp)
+         {
+           free (tmp);
+           return EAI_MEMORY;
+         }
+
+       sinp->sin_port = se->s_port;
+       memcpy (&sinp->sin_addr, he->h_addr_list[0], he->h_length);
+
+       tmp->ai_addr = sinp;
+       tmp->ai_addrlen = sizeof (sin);
+      }
+      break;
+
+    default:
+      free (tmp);
+      return EAI_NODATA;
+    }
+
+  /* FIXME: If more than one address, create linked list of addrinfo's. */
+
+  *res = tmp;
+
+  return 0;
+}
+
+/* Free `addrinfo' structure AI including associated storage.  */
+void
+freeaddrinfo (struct addrinfo *ai)
+{
+  while (ai)
+    {
+      struct addrinfo *cur;
+
+      cur = ai;
+      ai = ai->ai_next;
+      free (cur);
+    }
+}
+
+static struct
+  {
+    int code;
+    const char *msg;
+  }
+values[] =
+  {
+    { EAI_ADDRFAMILY, N_("Address family for hostname not supported") },
+    { EAI_AGAIN, N_("Temporary failure in name resolution") },
+    { EAI_BADFLAGS, N_("Bad value for ai_flags") },
+    { EAI_FAIL, N_("Non-recoverable failure in name resolution") },
+    { EAI_FAMILY, N_("ai_family not supported") },
+    { EAI_MEMORY, N_("Memory allocation failure") },
+    { EAI_NODATA, N_("No address associated with hostname") },
+    { EAI_NONAME, N_("Name or service not known") },
+    { EAI_SERVICE, N_("Servname not supported for ai_socktype") },
+    { EAI_SOCKTYPE, N_("ai_socktype not supported") },
+    { EAI_SYSTEM, N_("System error") },
+  };
+
+/* Convert error return from getaddrinfo() to a string.  */
+const char *
+gai_strerror (int code)
+{
+  size_t i;
+  for (i = 0; i < sizeof (values) / sizeof (values[0]); ++i)
+    if (values[i].code == code)
+      return _(values[i].msg);
+
+  return _("Unknown error");
+}
Index: MODULES.html.sh
===================================================================
RCS file: /cvsroot/gnulib/gnulib/MODULES.html.sh,v
retrieving revision 1.66
diff -u -p -r1.66 MODULES.html.sh
--- MODULES.html.sh     11 Oct 2004 13:08:55 -0000      1.66
+++ MODULES.html.sh     8 Nov 2004 12:46:54 -0000
@@ -1730,6 +1730,7 @@ func_all_modules ()
   func_module chown
   func_module dup2
   func_module ftruncate
+  func_module getaddrinfo
   func_module getcwd
   func_module getgroups
   func_module gethostname





reply via email to

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