Fix getaddrinfo on Windows 2000.
authorSimon Josefsson <simon@josefsson.org>
Wed, 21 Jun 2006 17:22:32 +0000 (17:22 +0000)
committerSimon Josefsson <simon@josefsson.org>
Wed, 21 Jun 2006 17:22:32 +0000 (17:22 +0000)
doc/gnulib.texi
lib/getaddrinfo.c
m4/getaddrinfo.m4
modules/getaddrinfo-tests [new file with mode: 0644]
tests/test-getaddrinfo.c [new file with mode: 0644]

index c61ab57..6d62e87 100644 (file)
@@ -1,5 +1,5 @@
 \input texinfo   @c -*-texinfo-*-
-@comment $Id: gnulib.texi,v 1.22 2006-06-19 20:40:26 karl Exp $
+@comment $Id: gnulib.texi,v 1.23 2006-06-21 17:22:32 jas Exp $
 @comment %**start of header
 @setfilename gnulib.info
 @settitle GNU Gnulib
@@ -7,7 +7,7 @@
 @syncodeindex pg cp
 @comment %**end of header
 
-@set UPDATED $Date: 2006-06-19 20:40:26 $
+@set UPDATED $Date: 2006-06-21 17:22:32 $
 
 @copying
 This manual is for GNU Gnulib (updated @value{UPDATED}),
@@ -89,6 +89,7 @@ Getting started:
 * Out of memory handling::
 * Library version handling::
 * Regular expressions::
+* Windows sockets::
 @end menu
 
 
@@ -294,6 +295,38 @@ generated automatically.
 @include regexprops-generic.texi
 
 
+@node Windows sockets
+@section Windows sockets
+
+There are several issues when building applications that should work
+under Windows.  The most problematic part is for applications that use
+sockets.
+
+Hopefully, we can add helpful notes to this section that will help you
+port your application to Windows using gnulib.
+
+@subsection Getaddrinfo and WINVER
+
+This was written for the getaddrinfo module, but may be applicable to
+other functions too.
+
+The getaddrinfo function exists in ws2tcpip.h and -lws2_32 on Windows
+XP.  The function declaration is present if @code{WINVER >= 0x0501}.
+Windows 2000 does not have getaddrinfo in its @file{WS2_32.dll}.
+
+Thus, if you want to assume Windows XP or later, you can add
+AC_DEFINE(WINVER, 0x0501) to avoid compiling to (partial) getaddrinfo
+implementation.
+
+If you want to support Windows 2000, don't do anything, but be aware
+that gnulib will use its own (partial) getaddrinfo implementation even
+on Windows XP.  Currently the code does not attempt to determine if
+the getaddrinfo function is available during runtime.
+
+Todo: Make getaddrinfo.c open the WS2_32.DLL and check for the
+getaddrinfo symbol and use it if present, otherwise fall back to our
+own implementation.
+
 @include gnulib-tool.texi
 
 
index 7ea6967..d2029ae 100644 (file)
@@ -212,6 +212,7 @@ getaddrinfo (const char *restrict nodename,
   tmp->ai_protocol = (hints) ? hints->ai_protocol : 0;
   tmp->ai_socktype = (hints) ? hints->ai_socktype : 0;
   tmp->ai_addr->sa_family = he->h_addrtype;
+  tmp->ai_family = he->h_addrtype;
 
   /* FIXME: If more than one address, create linked list of addrinfo's. */
 
index c367190..fef311f 100644 (file)
@@ -17,7 +17,6 @@ AC_DEFUN([gl_GETADDRINFO],
       LIBS="$LIBS -lws2_32"
       AC_TRY_LINK([
 #ifdef HAVE_WS2TCPIP_H
-#define WINVER 0x0501
 #include <ws2tcpip.h>
 #endif
 ], [getaddrinfo(0, 0, 0, 0);], gl_cv_w32_getaddrinfo=yes)
@@ -37,6 +36,22 @@ AC_DEFUN([gl_GETADDRINFO],
 AC_DEFUN([gl_PREREQ_GETADDRINFO], [
   AC_SEARCH_LIBS(gethostbyname, [inet nsl])
   AC_SEARCH_LIBS(getservbyname, [inet nsl socket xnet])
+  AC_CHECK_FUNCS(gethostbyname,, [
+    AC_CACHE_CHECK(for gethostbyname in winsock2.h and -lws2_32,
+                  gl_cv_w32_gethostbyname, [
+      gl_cv_w32_gethostbyname=no
+      am_save_LIBS="$LIBS"
+      LIBS="$LIBS -lws2_32"
+      AC_TRY_LINK([
+#ifdef HAVE_WINSOCK2_H
+#include <winsock2.h>
+#endif
+], [gethostbyname(0);], gl_cv_w32_gethostbyname=yes)
+    LIBS="$am_save_LIBS"])
+    if test "$gl_cv_w32_gethostbyname" = "yes"; then
+      LIBS="$LIBS -lws2_32"
+    fi
+    ])
   AC_REQUIRE([gl_C_RESTRICT])
   AC_REQUIRE([gl_SOCKET_FAMILIES])
   AC_REQUIRE([gl_HEADER_SYS_SOCKET])
@@ -55,7 +70,6 @@ AC_DEFUN([gl_PREREQ_GETADDRINFO], [
 #include <netdb.h>
 #endif
 #ifdef HAVE_WS2TCPIP_H
-#define WINVER 0x0501
 #include <ws2tcpip.h>
 #endif
 ])
@@ -68,7 +82,6 @@ AC_DEFUN([gl_PREREQ_GETADDRINFO], [
 #include <netdb.h>
 #endif
 #ifdef HAVE_WS2TCPIP_H
-#define WINVER 0x0501
 #include <ws2tcpip.h>
 #endif
 ])
diff --git a/modules/getaddrinfo-tests b/modules/getaddrinfo-tests
new file mode 100644 (file)
index 0000000..86d70c2
--- /dev/null
@@ -0,0 +1,14 @@
+Files:
+tests/test-getaddrinfo.c
+
+Depends-on:
+inet_ntop
+
+configure.ac:
+
+Makefile.am:
+TESTS += test-getaddrinfo$(EXEEXT)
+check_PROGRAMS += test-getaddrinfo
+
+License:
+LGPL
diff --git a/tests/test-getaddrinfo.c b/tests/test-getaddrinfo.c
new file mode 100644 (file)
index 0000000..adf29e4
--- /dev/null
@@ -0,0 +1,63 @@
+#include "config.h"
+#include "getaddrinfo.h"
+#include "inet_ntop.h"
+#include <stdio.h>
+#include <string.h>
+
+int simple (char *host, char *service)
+{
+  char buf[BUFSIZ];
+  struct addrinfo hints;
+  struct addrinfo *ai0, *ai;
+  int res;
+
+  printf ("Finding %s service %s...\n", host, service);
+
+  memset (&hints, 0, sizeof (hints));
+  hints.ai_flags = AI_CANONNAME;
+  hints.ai_family = AF_INET;
+  hints.ai_socktype = SOCK_STREAM;
+  res = getaddrinfo (host, 0, 0, &ai0);
+
+  printf ("res %d: %s\n", res, gai_strerror (res));
+
+  if (res != 0)
+    return 1;
+
+  for (ai = ai0; ai; ai = ai->ai_next)
+    {
+      printf ("\tflags %x\n", ai->ai_flags);
+      printf ("\tfamily %x\n", ai->ai_family);
+      printf ("\tsocktype %x\n", ai->ai_socktype);
+      printf ("\tprotocol %x\n", ai->ai_protocol);
+      printf ("\taddrlen %d: ", ai->ai_addrlen);
+      printf ("\tFound %s\n",
+             inet_ntop (ai->ai_family,
+                        &((struct sockaddr_in *)
+                         ai->ai_addr)->sin_addr,
+                        buf, sizeof (buf) - 1));
+      if (ai->ai_canonname)
+       printf ("\tFound %s...\n", ai->ai_canonname);
+    }
+
+  freeaddrinfo (ai0);
+
+  return 0;
+}
+
+#define HOST1 "www.gnu.org"
+#define SERV1 "http"
+#define HOST2 "www.ibm.com"
+#define SERV2 "http"
+#define HOST3 "ibm.org"
+#define SERV3 "http"
+#define HOST4 "google.org"
+#define SERV4 "http"
+
+int main (void)
+{
+  return simple (HOST1, SERV1)
+    + simple (HOST2, SERV2)
+    + simple (HOST3, SERV3)
+    + simple (HOST4, SERV4);
+}