Commits

Anonymous committed c9886c8

PR#5676: add ipv6 support on Windows.

Patch by Jérôme Vouillon <Jerome.Vouillon@pps.jussieu.fr>

git-svn-id: http://caml.inria.fr/svn/ocaml/trunk@12710f963ae5c-01c2-4b8c-9fe0-0dff7051ff02

  • Participants
  • Parent commits 422c753

Comments (0)

Files changed (20)

 #define HAS_PUTENV
 #define HAS_LOCALE
 #define HAS_BROKEN_PRINTF
+#define HAS_IPV6

otherlibs/unix/addrofstr.c

 /* $Id$ */
 
 #include <mlvalues.h>
+#include <memory.h>
 #include <fail.h>
 #include "unixsupport.h"
 
 CAMLprim value unix_inet_addr_of_string(value s)
 {
 #if defined(HAS_IPV6)
+#ifdef _WIN32
+  CAMLparam1(s);
+  CAMLlocal1(vres);
+  struct addrinfo hints;
+  struct addrinfo * res;
+  int retcode;
+  memset(&hints, 0, sizeof(hints));
+  hints.ai_family = AF_UNSPEC;
+  hints.ai_flags = AI_NUMERICHOST;
+  retcode = getaddrinfo(String_val(s), NULL, &hints, &res);
+  if (retcode != 0) failwith("inet_addr_of_string");
+  switch (res->ai_addr->sa_family) {
+  case AF_INET:
+    {
+      vres =
+        alloc_inet_addr(&((struct sockaddr_in *) res->ai_addr)->sin_addr);
+      break;
+    }
+  case AF_INET6:
+    {
+      vres =
+        alloc_inet6_addr(&((struct sockaddr_in6 *) res->ai_addr)->sin6_addr);
+      break;
+    }
+  default:
+    {
+      freeaddrinfo(res);
+      failwith("inet_addr_of_string");
+    }
+  }
+  freeaddrinfo(res);
+  CAMLreturn (vres);
+#else
   struct in_addr address;
   struct in6_addr address6;
   if (inet_pton(AF_INET, String_val(s), &address) > 0)
     return alloc_inet6_addr(&address6);
   else
     failwith("inet_addr_of_string");
+#endif
 #elif defined(HAS_INET_ATON)
   struct in_addr address;
   if (inet_aton(String_val(s), &address) == 0)

otherlibs/unix/gethostname.c

 #include <mlvalues.h>
 #include <alloc.h>
 #include <fail.h>
-#if defined (_WIN32)
-#include <winsock.h>
-#else
+#ifndef _WIN32
 #include <sys/param.h>
 #endif
 #include "unixsupport.h"

otherlibs/unix/getproto.c

 
 #ifndef _WIN32
 #include <netdb.h>
-#else
-#include <winsock.h>
 #endif
 
 static value alloc_proto_entry(struct protoent *entry)

otherlibs/unix/getserv.c

 #include <sys/socket.h>
 #include <netinet/in.h>
 #include <netdb.h>
-#else
-#include <winsock.h>
 #endif
 
 static value alloc_service_entry(struct servent *entry)

otherlibs/unix/strofaddr.c

 {
   char * res;
 #ifdef HAS_IPV6
+#ifdef _WIN32
+  char buffer[64];
+  union sock_addr_union sa;
+  int len;
+  int retcode;
+  if (string_length(a) == 16) {
+    memset(&sa.s_inet6, 0, sizeof(struct sockaddr_in6));
+    sa.s_inet6.sin6_family = AF_INET6;
+    sa.s_inet6.sin6_addr = GET_INET6_ADDR(a);
+    len = sizeof(struct sockaddr_in6);
+  } else {
+    memset(&sa.s_inet, 0, sizeof(struct sockaddr_in));
+    sa.s_inet.sin_family = AF_INET;
+    sa.s_inet.sin_addr = GET_INET_ADDR(a);
+    len = sizeof(struct sockaddr_in);
+  }
+  retcode = getnameinfo
+    (&sa.s_gen, len, buffer, sizeof(buffer), NULL, 0, NI_NUMERICHOST);
+  if (retcode != 0)
+    res = NULL;
+  else
+    res = buffer;
+#else
   char buffer[64];
   if (string_length(a) == 16)
     res = (char *)
     res = (char *)
       inet_ntop(AF_INET, (const void *) &GET_INET_ADDR(a),
                 buffer, sizeof(buffer));
+#endif
 #else
   res = inet_ntoa(GET_INET_ADDR(a));
 #endif

otherlibs/win32unix/Makefile.nt

 # Files from the ../unix directory
 UNIX_FILES = access.c addrofstr.c chdir.c chmod.c cst2constr.c \
   cstringv.c envir.c execv.c execve.c execvp.c \
-  exit.c getcwd.c gethost.c gethostname.c getproto.c \
+  exit.c getaddrinfo.c getcwd.c gethost.c gethostname.c \
+  getnameinfo.c getproto.c \
   getserv.c gmtime.c putenv.c rmdir.c \
   socketaddr.c strofaddr.c time.c unlink.c utimes.c
 

otherlibs/win32unix/close_on.c

 /* $Id$ */
 
 #include <mlvalues.h>
-#include <windows.h>
 #include "unixsupport.h"
+#include <windows.h>
 
 int win_set_inherit(value fd, BOOL inherit)
 {

otherlibs/win32unix/createprocess.c

 
 /* $Id$ */
 
+#include "unixsupport.h"
 #include <windows.h>
 #include <mlvalues.h>
 #include <osdeps.h>
-#include "unixsupport.h"
 
 static int win_has_console(void);
 

otherlibs/win32unix/link.c

 
 /* $Id$ */
 
+#include "unixsupport.h"
 #include <windows.h>
 #include <mlvalues.h>
 #include <fail.h>
-#include "unixsupport.h"
 
 typedef
 BOOL (WINAPI *tCreateHardLink)(

otherlibs/win32unix/select.c

 
 /* $Id$ */
 
+#include "winworker.h"
 #include <mlvalues.h>
 #include <alloc.h>
 #include <memory.h>
 #include <fail.h>
 #include <signals.h>
-#include <winsock2.h>
-#include <windows.h>
 #include <stdio.h>
-#include "unixsupport.h"
 #include "windbug.h"
-#include "winworker.h"
 #include "winlist.h"
 
 /* This constant define the maximum number of objects that

otherlibs/win32unix/socket.c

 #include "unixsupport.h"
 
 int socket_domain_table[] = {
-  PF_UNIX, PF_INET /*, PF_INET6 */
+  PF_UNIX, PF_INET,
+#if defined(HAS_IPV6)
+  PF_INET6
+#else
+  0
+#endif
 };
 
 int socket_type_table[] = {
 {
   SOCKET s;
 
+  #ifndef HAS_IPV6
   /* IPv6 requires WinSock2, we must raise an error on PF_INET6 */
   if (Int_val(domain) >= sizeof(socket_domain_table)/sizeof(int)) {
     win32_maperr(WSAEPFNOSUPPORT);
     uerror("socket", Nothing);
   }
+  #endif
 
   s = socket(socket_domain_table[Int_val(domain)],
                    socket_type_table[Int_val(type)],

otherlibs/win32unix/socketaddr.h

 union sock_addr_union {
   struct sockaddr s_gen;
   struct sockaddr_in s_inet;
+#ifdef HAS_IPV6
+  struct sockaddr_in6 s_inet6;
+#endif
 };
 
 extern union sock_addr_union sock_addr;
                       socklen_param_type addr_len, int close_on_error);
 CAMLprim value alloc_inet_addr (struct in_addr * inaddr);
 #define GET_INET_ADDR(v) (*((struct in_addr *) (v)))
+
+#ifdef HAS_IPV6
+CAMLexport value alloc_inet6_addr (struct in6_addr * inaddr);
+#define GET_INET6_ADDR(v) (*((struct in6_addr *) (v)))
+#endif

otherlibs/win32unix/startup.c

 /*                                                                     */
 /***********************************************************************/
 
+#include "winworker.h"
 #include <stdio.h>
 #include <fcntl.h>
 #include <stdlib.h>
 #include <mlvalues.h>
-#include "unixsupport.h"
-#include "winworker.h"
 #include "windbug.h"
 
 value val_process_id;

otherlibs/win32unix/times.c

+#include "unixsupport.h"
 #include <windows.h>
 #include <mlvalues.h>
-#include "unixsupport.h"
+#include <alloc.h>
 
 
 double to_sec(FILETIME ft) {

otherlibs/win32unix/unix.ml

   | AI_CANONNAME
   | AI_PASSIVE
 
-let getaddrinfo node service opts =
+external getaddrinfo_system
+  : string -> string -> getaddrinfo_option list -> addr_info list
+  = "unix_getaddrinfo"
+
+let getaddrinfo_emulation node service opts =
   (* Parse options *)
   let opt_socktype = ref None
   and opt_protocol = ref 0
           addresses)
       ports)
 
+let getaddrinfo node service opts =
+  try
+    List.rev(getaddrinfo_system node service opts)
+  with Invalid_argument _ ->
+    getaddrinfo_emulation node service opts
+
 type name_info =
   { ni_hostname : string;
     ni_service : string }
   | NI_NUMERICSERV
   | NI_DGRAM
 
-let getnameinfo addr opts =
+external getnameinfo_system
+  : sockaddr -> getnameinfo_option list -> name_info
+  = "unix_getnameinfo"
+
+let getnameinfo_emulation addr opts =
   match addr with
   | ADDR_UNIX f ->
       { ni_hostname = ""; ni_service = f } (* why not? *)
           string_of_int p in
       { ni_hostname = hostname; ni_service = service }
 
+let getnameinfo addr opts =
+  try
+    getnameinfo_system addr opts
+  with Invalid_argument _ ->
+    getnameinfo_emulation addr opts
+
 (* High-level process management (system, popen) *)
 
 external win_create_process : string -> string -> string option ->
 (* High-level network functions *)
 
 let open_connection sockaddr =
-  let domain =
-    match sockaddr with ADDR_UNIX _ -> PF_UNIX | ADDR_INET(_,_) -> PF_INET in
   let sock =
-    socket domain SOCK_STREAM 0 in
-  connect sock sockaddr;
-  (in_channel_of_descr sock, out_channel_of_descr sock)
+    socket (domain_of_sockaddr sockaddr) SOCK_STREAM 0 in
+  try
+    connect sock sockaddr;
+    set_close_on_exec sock;
+    (in_channel_of_descr sock, out_channel_of_descr sock)
+  with exn ->
+    close sock; raise exn
 
 let shutdown_connection inchan =
   shutdown (descr_of_in_channel inchan) SHUTDOWN_SEND

otherlibs/win32unix/unixsupport.h

 #include <direct.h>
 #include <process.h>
 #include <sys/types.h>
-#include <winsock.h>
+#include <winsock2.h>
+#ifdef HAS_IPV6
+#include <ws2tcpip.h>
+#include <wspiapi.h>
+#endif
 
 struct filedescr {
   union {

otherlibs/win32unix/winwait.c

 
 /* $Id$ */
 
+#include "unixsupport.h"
 #include <windows.h>
 #include <mlvalues.h>
 #include <alloc.h>
 #include <memory.h>
-#include "unixsupport.h"
 #include <sys/types.h>
 #include <signals.h>
 

otherlibs/win32unix/winworker.c

 #include "windbug.h"
 #include <mlvalues.h>
 #include <alloc.h>
-#include "unixsupport.h"
+#include <memory.h>
+#include <signals.h>
 
 typedef enum {
   WORKER_CMD_NONE = 0,

otherlibs/win32unix/winworker.h

 #define _WINWORKER_H
 
 #define _WIN32_WINNT 0x0400
+#include "unixsupport.h"
 #include <windows.h>
 
 /* Pool of worker threads.