<URL: http://bugs.freeciv.org/Ticket/Display.html?id=40296 >

 This is my take of IPv6 support.

 As you probably already know, there is currently two sets of
networking functions in the Linux-world. Legacy ones work only with
IPv4, new ones can handle both IPv4 and IPv6.

 Configure option --enable-ipv6 can have three values:
 --disable-ipv6 - use old functions. Works in ancient systems, but has
no IPv6 support at all
 --enable-ipv6=test [default] - Test if system has required IPv6
compatible functions available and if it does, use them. Even though
functions capable of IPv6 support are used, this
    still uses IPv4 address family
 --enable-ipv6 - Use new functions and IPv6 address family


 Currently two things are not exactly according to division above. 1)
Server binds to IPv6 address even when --enable-ipv6=test is used. OS
maps incoming IPv4 requests so that this is not causing any trouble.
2) Lan broadcast is not yet implemented using IPv6 address family.


 Bugs:
 - Send to metaserver is not working when new functions are used. It
works fine when ipv6 support completely disabled.


 - ML

diff -Nurd -X.diff_ignore freeciv/client/clinet.c freeciv/client/clinet.c
--- freeciv/client/clinet.c	2008-03-08 16:13:03.000000000 +0200
+++ freeciv/client/clinet.c	2008-06-20 02:39:03.000000000 +0300
@@ -198,13 +198,13 @@
     (void) mystrlcpy(errbuf, _("Connection in progress."), errbufsize);
     return -1;
   }
-  
-  if ((client.conn.sock = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
+
+  if ((client.conn.sock = socket(FC_AF_FAMILY, SOCK_STREAM, 0)) == -1) {
     (void) mystrlcpy(errbuf, mystrerror(), errbufsize);
     return -1;
   }
 
-  if (my_connect(client.conn.sock, &server_addr.sockaddr,
+  if (my_connect(client.conn.sock, &server_addr.addr,
       sizeof(server_addr)) == -1) {
     (void) mystrlcpy(errbuf, mystrerror(), errbufsize);
     my_closesocket(client.conn.sock);
diff -Nurd -X.diff_ignore freeciv/client/servers.c freeciv/client/servers.c
--- freeciv/client/servers.c	2007-08-20 00:55:46.000000000 +0300
+++ freeciv/client/servers.c	2008-06-20 06:02:43.000000000 +0300
@@ -413,15 +413,15 @@
     (scan->error_func)(scan, _("Failed looking up metaserver's host"));
     return FALSE;
   }
-  
-  if ((s = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
+
+  if ((s = socket(FC_AF_FAMILY, SOCK_STREAM, 0)) == -1) {
     (scan->error_func)(scan, mystrerror());
     return FALSE;
   }
 
   my_nonblock(s);
-  
-  if (my_connect(s, (struct sockaddr *) &addr.sockaddr, sizeof(addr)) == -1) {
+
+  if (my_connect(s, &addr.addr, sizeof(addr.addr_in)) == -1) {
     if (errno == EINPROGRESS) {
       /* With non-blocking sockets this is the expected result. */
       scan->meta.state = META_CONNECTING;
@@ -540,9 +540,14 @@
 #ifndef HAVE_WINSOCK
   unsigned char ttl;
 #endif
+#ifdef HAVE_INET_PTON
+  char dst[FC_ADDR_SIZE];
+#else
+  in_addr_t dst;
+#endif
 
   /* Create a socket for broadcasting to servers. */
-  if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
+  if ((sock = socket(FC_AF_FAMILY, SOCK_DGRAM, 0)) < 0) {
     freelog(LOG_ERROR, "socket failed: %s", mystrerror());
     return FALSE;
   }
@@ -554,10 +559,15 @@
 
   /* Set the UDP Multicast group IP address. */
   group = get_multicast_group();
+#ifdef HAVE_INET_PTON
+  inet_pton(FC_AF_FAMILY, group, dst);
+#else
+  dst = inet_addr(group);
+#endif
   memset(&addr, 0, sizeof(addr));
-  addr.sockaddr_in.sin_family = AF_INET;
-  addr.sockaddr_in.sin_addr.s_addr = inet_addr(get_multicast_group());
-  addr.sockaddr_in.sin_port = htons(SERVER_LAN_PORT);
+  addr.addr_in.FC_SIN_FAMILY = FC_AF_FAMILY;
+  FC_SET_ADDR(&addr.addr_in, dst, sizeof(dst));
+  addr.addr_in.FC_SIN_PORT = htons(SERVER_LAN_PORT);
 
 /* this setsockopt call fails on Windows 98, so we stick with the default
  * value of 1 on Windows, which should be fine in most cases */
@@ -582,7 +592,7 @@
   size = dio_output_used(&dout);
  
 
-  if (sendto(sock, buffer, size, 0, &addr.sockaddr,
+  if (sendto(sock, buffer, size, 0, &addr.addr,
       sizeof(addr)) < 0) {
     /* This can happen when there's no network connection - it should
      * give an in-game message. */
@@ -595,7 +605,7 @@
   my_closesocket(sock);
 
   /* Create a socket for listening for server packets. */
-  if ((scan->sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
+  if ((scan->sock = socket(FC_AF_FAMILY, SOCK_DGRAM, 0)) < 0) {
     (scan->error_func)(scan, mystrerror());
     return FALSE;
   }
@@ -608,15 +618,17 @@
   }
                                                                                
   memset(&addr, 0, sizeof(addr));
-  addr.sockaddr_in.sin_family = AF_INET;
-  addr.sockaddr_in.sin_addr.s_addr = htonl(INADDR_ANY); 
-  addr.sockaddr_in.sin_port = htons(SERVER_LAN_PORT + 1);
+  addr.addr_in.FC_SIN_FAMILY = FC_AF_FAMILY;
+  FC_SET_SIN_LEN(&addr.addr_in, sizeof(addr.addr_in));
+  FC_SET_ADDR_ANY(&addr.addr_in);
+  addr.addr_in.FC_SIN_PORT = htons(SERVER_LAN_PORT + 1);
 
-  if (bind(scan->sock, &addr.sockaddr, sizeof(addr)) < 0) {
+  if (bind(scan->sock, &addr.addr, sizeof(addr)) < 0) {
     (scan->error_func)(scan, mystrerror());
     return FALSE;
   }
 
+  /* FIXME: IPv6 support */
   mreq.imr_multiaddr.s_addr = inet_addr(group);
   mreq.imr_interface.s_addr = htonl(INADDR_ANY);
   if (setsockopt(scan->sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, 
@@ -638,7 +650,6 @@
 {
   socklen_t fromlen;
   union my_sockaddr fromend;
-  struct hostent *from;
   char msgbuf[128];
   int type;
   struct data_in din;
@@ -660,7 +671,7 @@
     /* Try to receive a packet from a server.  No select loop is needed;
      * we just keep on reading until recvfrom returns -1. */
     if (recvfrom(scan->sock, msgbuf, sizeof(msgbuf), 0,
-		 &fromend.sockaddr, &fromlen) < 0) {
+		 &fromend.addr, &fromlen) < 0) {
       break;
     }
 
@@ -676,9 +687,41 @@
     dio_get_string(&din, message, sizeof(message));
 
     if (!mystrcasecmp("none", servername)) {
-      from = gethostbyaddr((char *) &fromend.sockaddr_in.sin_addr,
-			   sizeof(fromend.sockaddr_in.sin_addr), AF_INET);
-      sz_strlcpy(servername, inet_ntoa(fromend.sockaddr_in.sin_addr));
+      bool nameinfo = FALSE;
+#ifdef HAVE_INET_NTOP
+      char dst[INET6_ADDRSTRLEN];
+#else
+      const char *dst;
+#endif
+#ifdef HAVE_GETNAMEINFO
+      char host[NI_MAXHOST], service[NI_MAXSERV];
+
+      if (!getnameinfo(&fromend.addr, fromlen, host, NI_MAXHOST,
+                       service, NI_MAXSERV, NI_NUMERICSERV)) {
+        nameinfo = TRUE;
+      }
+#else
+      struct hostent *from;
+      char *host = NULL;
+
+      from = gethostbyaddr((char *) &fromend.addr_in.FC_SIN_ADDR,
+			   sizeof(fromend.addr_in.FC_SIN_ADDR), FC_AF_FAMILY);
+      if (from) {
+        host = from->h_name;
+        nameinfo = TRUE;
+      }
+#endif
+
+      if (!nameinfo) {
+#ifdef HAVE_INET_NTOP
+        inet_ntop(FC_AF_FAMILY, &fromend.addr_in.FC_SIN_ADDR,
+                  dst, sizeof(dst));
+#else
+        dst = inet_ntoa(fromend.addr_in.sin_addr);
+#endif
+      }
+
+      sz_strlcpy(servername, nameinfo ? host : dst);
     }
 
     /* UDP can send duplicate or delayed packets. */
diff -Nurd -X.diff_ignore freeciv/common/connection.c freeciv/common/connection.c
--- freeciv/common/connection.c	2008-04-16 21:39:40.000000000 +0300
+++ freeciv/common/connection.c	2008-06-20 05:20:51.000000000 +0300
@@ -48,7 +48,11 @@
 /* String used for connection.addr and related cases to indicate
  * blank/unknown/not-applicable address:
  */
+#ifdef IPV6_SUPPORT
+const char blank_addr_str[] = "?:?:?:?:?:?:?:?";
+#else
 const char blank_addr_str[] = "---.---.---.---";
+#endif
 
 /* This is only used by the server.
    If it is set the disconnection of conns is posponed. This is sometimes
diff -Nurd -X.diff_ignore freeciv/configure.ac freeciv/configure.ac
--- freeciv/configure.ac	2008-06-17 15:34:47.000000000 +0300
+++ freeciv/configure.ac	2008-06-20 05:30:01.000000000 +0300
@@ -66,6 +66,29 @@
 esac], [server=true])
 AM_CONDITIONAL(SERVER, test x$server = xtrue)
 
+AC_ARG_ENABLE(ipv6,
+[  --enable-ipv6         use ipv6],
+[case "${enableval}" in
+  yes|no|test) ipv6=${enableval} ;;
+  *)   AC_MSG_ERROR(bad value ${enableval} for --enable-ipv6) ;;
+esac], [ipv6=test])
+if test x$ipv6 != xno ; then
+  AC_CHECK_FUNCS([gethostbyname2 inet_pton inet_ntop inet_pton], [ipv6_possible=true], [
+if test x$ipv6 = xyes ; then
+  AC_MSG_ERROR([Cannot enable IPv6 functionality])
+fi ])
+  if test x$ipv6_possible ; then
+    AC_DEFINE([IPV6_SUPPORT], [1], [IPv6 Support built in])
+    dnl Do not use IPv6 by default (when ipv6 = test) yet.
+    dnl IPv6 is still experimental feature.
+    if test x$ipv6 = xyes ; then
+      AC_DEFINE([IPV6_USED], [1], [IPv6 Used])
+    fi
+  fi
+  dnl Non-critical functions
+  AC_CHECK_FUNCS([getnameinfo])
+fi
+
 AC_ARG_WITH(readline,
 [  --with-readline         support fancy command line editing],
 WITH_READLINE=$withval,	dnl yes/no - required to use / never use
diff -Nurd -X.diff_ignore freeciv/server/meta.c freeciv/server/meta.c
--- freeciv/server/meta.c	2008-06-16 04:25:57.000000000 +0300
+++ freeciv/server/meta.c	2008-06-20 06:18:49.000000000 +0300
@@ -212,14 +212,14 @@
     return FALSE;
   }
 
-  if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
+  if ((sock = socket(FC_AF_FAMILY, SOCK_STREAM, 0)) == -1) {
     freelog(LOG_ERROR, "Metaserver: can't open stream socket: %s",
 	    mystrerror());
     metaserver_failed();
     return FALSE;
   }
 
-  if (my_connect(sock, (struct sockaddr *) &meta_addr, sizeof(meta_addr)) == -1) {
+  if (my_connect(sock, (struct sockaddr *) &meta_addr, sizeof(meta_addr.addr_in)) == -1) {
     freelog(LOG_ERROR, "Metaserver: connect failed: %s", mystrerror());
     metaserver_failed();
     my_closesocket(sock);
diff -Nurd -X.diff_ignore freeciv/server/sernet.c freeciv/server/sernet.c
--- freeciv/server/sernet.c	2008-05-04 16:48:09.000000000 +0300
+++ freeciv/server/sernet.c	2008-06-20 05:37:25.000000000 +0300
@@ -816,23 +816,50 @@
 
   int new_sock;
   union my_sockaddr fromend;
+  bool nameinfo = FALSE;
+#ifdef HAVE_GETNAMEINFO
+  char host[NI_MAXHOST], service[NI_MAXSERV];
+#else
   struct hostent *from;
+  char *host = NULL;
+#endif
+#ifdef HAVE_INET_NTOP
+  char dst[INET6_ADDRSTRLEN];
+#else
+  const char *dst;
+#endif
 
   fromlen = sizeof(fromend);
 
-  if ((new_sock = accept(sockfd, &fromend.sockaddr, &fromlen)) == -1) {
+  if ((new_sock = accept(sockfd, &fromend.addr, &fromlen)) == -1) {
     freelog(LOG_ERROR, "accept failed: %s", mystrerror());
     return -1;
   }
 
+#ifdef HAVE_GETNAMEINFO
+  if (!getnameinfo(&fromend.addr, fromlen, host, NI_MAXHOST,
+                   service, NI_MAXSERV, NI_NUMERICSERV)) {
+    nameinfo = TRUE;
+  }
+#else
   from =
-      gethostbyaddr((char *) &fromend.sockaddr_in.sin_addr,
-		    sizeof(fromend.sockaddr_in.sin_addr), AF_INET);
+    gethostbyaddr((char *) &fromend.addr_in.FC_SIN_ADDR,
+                  sizeof(fromend.addr_in.FC_SIN_ADDR), FC_AF_FAMILY);
+  if (from) {
+    host = from->h_name;
+    nameinfo = TRUE;
+  }
+#endif
+
+#ifdef HAVE_INET_NTOP
+  inet_ntop(FC_AF_FAMILY, &fromend.addr_in.FC_SIN_ADDR,
+            dst, sizeof(dst));
+#else
+  dst = inet_ntoa(fromend.addr_in.sin_addr);
+#endif
 
   return server_make_connection(new_sock,
-				(from ? from->h_name
-				 : inet_ntoa(fromend.sockaddr_in.sin_addr)),
-				inet_ntoa(fromend.sockaddr_in.sin_addr));
+				(nameinfo ? host : dst), dst);
 }
 
 /********************************************************************
@@ -902,11 +929,11 @@
   int opt;
 
   /* Create socket for client connections. */
-  if((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
+  if((sock = socket(FC_AF_SRV_FAMILY, SOCK_STREAM, 0)) == -1) {
     die("socket failed: %s", mystrerror());
   }
 
-  opt=1; 
+  opt=1;
   if(setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, 
 		(char *)&opt, sizeof(opt)) == -1) {
     freelog(LOG_ERROR, "SO_REUSEADDR failed: %s", mystrerror());
@@ -918,8 +945,9 @@
     exit(EXIT_FAILURE);
   }
 
-  if(bind(sock, &src.sockaddr, sizeof (src)) == -1) {
-    freelog(LOG_FATAL, "bind failed: %s", mystrerror());
+  if(bind(sock, &src.addr, sizeof(src.addr_in)) == -1) {
+    freelog(LOG_FATAL, "Server bind failed: %s", mystrerror());
+    debug_sockaddr(&src);
     exit(EXIT_FAILURE);
   }
 
@@ -929,7 +957,7 @@
   }
 
   /* Create socket for server LAN announcements */
-  if ((socklan = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
+  if ((socklan = socket(FC_AF_FAMILY, SOCK_DGRAM, 0)) < 0) {
      freelog(LOG_ERROR, "socket failed: %s", mystrerror());
   }
 
@@ -943,14 +971,16 @@
   group = get_multicast_group();
 
   memset(&addr, 0, sizeof(addr));
-  addr.sockaddr_in.sin_family = AF_INET;
-  addr.sockaddr_in.sin_addr.s_addr = htonl(INADDR_ANY);
-  addr.sockaddr_in.sin_port = htons(SERVER_LAN_PORT);
+  addr.addr_in.FC_SIN_FAMILY = FC_AF_FAMILY;
+  FC_SET_SIN_LEN(&addr.addr_in, sizeof(addr.addr_in));
+  FC_SET_ADDR_ANY(&addr.addr_in);
+  addr.addr_in.FC_SIN_PORT = htons(SERVER_LAN_PORT);
 
-  if (bind(socklan, &addr.sockaddr, sizeof(addr)) < 0) {
-    freelog(LOG_ERROR, "bind failed: %s", mystrerror());
+  if (bind(socklan, &addr.addr, sizeof(addr)) < 0) {
+    freelog(LOG_ERROR, "Lan bind failed: %s", mystrerror());
   }
 
+  /* FIXME: IPv6 support */
   mreq.imr_multiaddr.s_addr = inet_addr(group);
   mreq.imr_interface.s_addr = htonl(INADDR_ANY);
 
@@ -1141,19 +1171,29 @@
 #ifndef HAVE_WINSOCK
   unsigned char ttl;
 #endif
+#ifdef HAVE_INET_PTON
+  char dst[FC_ADDR_SIZE];
+#else
+  in_addr_t dst;
+#endif
 
   /* Create a socket to broadcast to client. */
-  if ((socksend = socket(AF_INET,SOCK_DGRAM, 0)) < 0) {
+  if ((socksend = socket(FC_AF_FAMILY, SOCK_DGRAM, 0)) < 0) {
     freelog(LOG_ERROR, "socket failed: %s", mystrerror());
     return;
   }
 
   /* Set the UDP Multicast group IP address of the packet. */
   group = get_multicast_group();
+#ifdef HAVE_INET_PTON
+  inet_pton(FC_AF_FAMILY, group, dst);
+#else
+  dst = inet_addr(group);
+#endif
   memset(&addr, 0, sizeof(addr));
-  addr.sockaddr_in.sin_family = AF_INET;
-  addr.sockaddr_in.sin_addr.s_addr = inet_addr(group);
-  addr.sockaddr_in.sin_port = htons(SERVER_LAN_PORT + 1);
+  addr.addr_in.FC_SIN_FAMILY = FC_AF_FAMILY;
+  FC_SET_ADDR(&addr.addr_in, dst, sizeof(dst));
+  addr.addr_in.FC_SIN_PORT = htons(SERVER_LAN_PORT + 1);
 
 /* this setsockopt call fails on Windows 98, so we stick with the default
  * value of 1 on Windows, which should be fine in most cases */
@@ -1215,7 +1255,7 @@
   size = dio_output_used(&dout);
 
   /* Sending packet to client with the information gathered above. */
-  if (sendto(socksend, buffer,  size, 0, &addr.sockaddr,
+  if (sendto(socksend, buffer,  size, 0, &addr.addr,
       sizeof(addr)) < 0) {
     freelog(LOG_ERROR, "sendto failed: %s", mystrerror());
     return;
diff -Nurd -X.diff_ignore freeciv/utility/netintf.c freeciv/utility/netintf.c
--- freeciv/utility/netintf.c	2008-03-09 01:19:13.000000000 +0200
+++ freeciv/utility/netintf.c	2008-06-20 05:33:18.000000000 +0300
@@ -241,22 +241,49 @@
 }
 
 /***************************************************************************
+  Write information about socaddr to debug log.
+***************************************************************************/
+void debug_sockaddr(union my_sockaddr *addr)
+{
+  char buf[INET6_ADDRSTRLEN] = "Unknown";
+
+#ifdef HAVE_INET_NTOP
+  inet_ntop(FC_AF_FAMILY, &addr->addr_in.FC_SIN_ADDR, buf, INET6_ADDRSTRLEN);
+#endif
+
+  freelog(LOG_DEBUG, "Host: %s, Port: %d", buf, ntohs(addr->addr_in.FC_SIN_PORT));
+}
+
+/***************************************************************************
   Look up the service at hostname:port and fill in *sa.
 ***************************************************************************/
 bool net_lookup_service(const char *name, int port, union my_sockaddr *addr)
 {
   struct hostent *hp;
-  struct sockaddr_in *sock = &addr->sockaddr_in;
+  FC_SOCKADDR_IN *sock = &addr->addr_in;
+#ifdef HAVE_INET_PTON
+  void *dst;
+#endif
 
-  sock->sin_family = AF_INET;
-  sock->sin_port = htons(port);
+  sock->FC_SIN_FAMILY = FC_AF_FAMILY;
+  sock->FC_SIN_PORT = htons(port);
+
+  FC_SET_SIN_LEN(sock, sizeof(*sock));
 
   if (!name) {
-    sock->sin_addr.s_addr = htonl(INADDR_ANY);
+    FC_SET_ADDR_ANY(sock);
     return TRUE;
   }
 
-#ifdef HAVE_INET_ATON
+#ifdef HAVE_INET_PTON
+  dst = fc_malloc(FC_ADDR_SIZE);
+  if (inet_pton(FC_AF_FAMILY, name, dst) > 0) {
+    FC_SET_ADDR(sock, dst, FC_ADDR_SIZE);
+    free(dst);
+    return TRUE;
+  }
+  free(dst);
+#elif defined(HAVE_INET_ATON)
   if (inet_aton(name, &sock->sin_addr) != 0) {
     return TRUE;
   }
@@ -265,12 +292,13 @@
     return TRUE;
   }
 #endif
-  hp = gethostbyname(name);
-  if (!hp || hp->h_addrtype != AF_INET) {
+  hp = FC_GETHOSTBYNAME(name, FC_AF_FAMILY);
+  if (!hp || hp->h_addrtype != FC_AF_FAMILY) {
     return FALSE;
   }
 
-  memcpy(&sock->sin_addr, hp->h_addr, hp->h_length);
+  memcpy(&sock->FC_SIN_ADDR, hp->h_addr, hp->h_length);
+
   return TRUE;
 }
 
@@ -437,19 +465,20 @@
 **************************************************************************/ 
 int find_next_free_port(int starting_port)
 {
-  int port, s = socket(AF_INET, SOCK_STREAM, 0);
+  int port, s = socket(FC_AF_FAMILY, SOCK_STREAM, 0);
 
   for (port = starting_port;; port++) {
     union my_sockaddr tmp;
-    struct sockaddr_in *sock = &tmp.sockaddr_in;
+    FC_SOCKADDR_IN *sock = &tmp.addr_in;
 
     memset(&tmp, 0, sizeof(tmp));
 
-    sock->sin_family = AF_INET;
-    sock->sin_port = htons(port);
-    sock->sin_addr.s_addr = htonl(INADDR_ANY);
+    sock->FC_SIN_FAMILY = FC_AF_FAMILY;
+    sock->FC_SIN_PORT = htons(port);
+    FC_SET_SIN_LEN(sock, sizeof(*sock));
+    FC_SET_ADDR_ANY(sock);
 
-    if (bind(s, &tmp.sockaddr, sizeof(tmp.sockaddr)) == 0) {
+    if (bind(s, &tmp.addr, sizeof(tmp.addr)) == 0) {
       break;
     }
   }
diff -Nurd -X.diff_ignore freeciv/utility/netintf.h freeciv/utility/netintf.h
--- freeciv/utility/netintf.h	2007-10-29 23:26:25.000000000 +0200
+++ freeciv/utility/netintf.h	2008-06-20 05:15:31.000000000 +0300
@@ -43,6 +43,50 @@
 #include "ioz.h"
 #include "shared.h"		/* bool type */
 
+/* Define macros for IPv6 compatibility or not.
+ * Latter might be still needed for some platforms. */
+#ifdef IPV6_SUPPORT
+
+#define FC_SOCKADDR_IN   struct sockaddr_in6
+#define FC_SIN_FAMILY    sin6_family
+#define FC_SIN_PORT      sin6_port
+#define FC_SIN_ADDR      sin6_addr
+/* #define FC_SET_SIN_LEN(a, b) do { (a)->sin6_len = (b); } while(0); */
+#define FC_SET_SIN_LEN(a, b)
+#define FC_SET_ADDR(a, b, len) do { memcpy(&(a)->sin6_addr, (b), (len)); } while(0);
+/* Obsoleted gethostbyname2() should be replaced with getaddrinfo() */
+#define FC_GETHOSTBYNAME(a, b) gethostbyname2((a), (b))
+#define FC_AF_SRV_FAMILY AF_INET6
+
+#ifdef IPV6_USED
+#define FC_AF_FAMILY     AF_INET6
+#define FC_ADDR_SIZE     sizeof(struct in6_addr)
+#define FC_ADDR_IN_SIZE  sizeof(struct sockaddr_in6)
+#else
+#define FC_AF_FAMILY     AF_INET
+#define FC_ADDR_SIZE     sizeof(struct in_addr)
+#define FC_ADDR_IN_SIZE  sizeof(struct sockaddr_in)
+#endif
+#define FC_SET_ADDR_ANY(a)     do { (a)->sin6_addr = in6addr_any; } while(0);
+
+#else  /* IPV6_SUPPORT */
+
+#define FC_SOCKADDR_IN   struct sockaddr_in
+#define FC_SIN_FAMILY    sin_family
+#define FC_SIN_PORT      sin_port
+#define FC_SIN_ADDR      sin_addr
+#define FC_AF_SRV_FAMILY AF_INET
+#define FC_AF_FAMILY     AF_INET
+#define FC_SET_SIN_LEN(a, b)
+#define FC_SET_ADDR(a, b, len) do { (a)->sin_addr.s_addr = (b); } while(0);
+#define FC_SET_ADDR_ANY(a)     do { (a)->sin_addr.s_addr = htonl(INADDR_ANY); } while(0);
+#define FC_GETHOSTBYNAME(a, b) gethostbyname((a))
+#define FC_GETHOSTBYADDR(a, b) gethostbyaddr((char *) (a)->sockaddr_in.sin_addr,
+#define FC_ADDR_SIZE   sizeof(struct in_addr)
+#define FC_ADDR_IN_SIZE sizeof(struct sockaddr_in)
+
+#endif /* IPV6_SUPPORT */
+
 /* map symbolic Winsock error names to symbolic errno names */
 #ifdef HAVE_WINSOCK
 #undef EINTR
@@ -68,8 +112,8 @@
 #endif
 
 union my_sockaddr {
-  struct sockaddr sockaddr;
-  struct sockaddr_in sockaddr_in;
+  struct sockaddr addr;
+  FC_SOCKADDR_IN addr_in;
 };
 
 int my_connect(int sockfd, const struct sockaddr *serv_addr, socklen_t addrlen);
@@ -90,4 +134,6 @@
 const char *my_lookup_httpd(char *server, int *port, const char *url);
 const char *my_url_encode(const char *txt);
 
+void debug_sockaddr(union my_sockaddr *addr);
+
 #endif  /* FC__NETINTF_H */
_______________________________________________
Freeciv-dev mailing list
Freeciv-dev@gna.org
https://mail.gna.org/listinfo/freeciv-dev

Reply via email to