10646e4
diff -up gimp-2.6.9/configure.in.script-fu-ipv6 gimp-2.6.9/configure.in
10646e4
--- gimp-2.6.9/configure.in.script-fu-ipv6	2010-06-21 21:20:20.000000000 +0200
10646e4
+++ gimp-2.6.9/configure.in	2010-06-29 17:28:24.153566227 +0200
10646e4
@@ -602,14 +602,14 @@ AC_CHECK_FUNC(rint, AC_DEFINE(HAVE_RINT,
0236e30
     AC_DEFINE(HAVE_RINT)])])
0236e30
 
0236e30
 
0236e30
-######################################################
0236e30
-# Check for extra libs needed for inet_ntoa and socket
0236e30
-######################################################
0236e30
+########################################################
0236e30
+# Check for extra libs needed for getnameinfo and socket
0236e30
+########################################################
0236e30
 
0236e30
 gimp_save_LIBS=$LIBS
0236e30
 LIBS=""
0236e30
 
0236e30
-AC_CHECK_FUNCS(inet_ntoa, , AC_CHECK_LIB(nsl, inet_ntoa))
0236e30
+AC_CHECK_FUNCS(getnameinfo, , AC_CHECK_LIB(nsl, getnameinfo))
0236e30
 AC_CHECK_LIB(socket, socket)
0236e30
 
0236e30
 SOCKET_LIBS="$LIBS"
10646e4
diff -up gimp-2.6.9/plug-ins/script-fu/script-fu-server.c.script-fu-ipv6 gimp-2.6.9/plug-ins/script-fu/script-fu-server.c
10646e4
--- gimp-2.6.9/plug-ins/script-fu/script-fu-server.c.script-fu-ipv6	2009-07-20 22:20:51.000000000 +0200
10646e4
+++ gimp-2.6.9/plug-ins/script-fu/script-fu-server.c	2010-06-29 17:28:24.154289648 +0200
10646e4
@@ -137,7 +137,8 @@ static void      server_start       (gin
e345da6
                                      const gchar *logfile);
e345da6
 static gboolean  execute_command    (SFCommand   *cmd);
e345da6
 static gint      read_from_client   (gint         filedes);
e345da6
-static gint      make_socket        (guint        port);
e345da6
+static gint      make_socket        (const struct addrinfo
e345da6
+                                                 *ai);
e345da6
 static void      server_log         (const gchar *format,
e345da6
                                      ...) G_GNUC_PRINTF (1, 2);
e345da6
 static void      server_quit        (void);
10646e4
@@ -151,7 +152,10 @@ static void      print_socket_api_error 
e345da6
 /*
e345da6
  *  Local variables
e345da6
  */
e345da6
-static gint         server_sock;
e345da6
+static gint         server_socks[2],
e345da6
+                    server_socks_used = 0;
e345da6
+static const gint   server_socks_len = sizeof (server_socks) /
e345da6
+                                       sizeof (server_socks[0]);
e345da6
 static GList       *command_queue   = NULL;
e345da6
 static gint         queue_length    = 0;
e345da6
 static gint         request_no      = 0;
e345da6
@@ -285,6 +289,7 @@ script_fu_server_listen (gint timeout)
e345da6
   struct timeval  tv;
e345da6
   struct timeval *tvp = NULL;
e345da6
   SELECT_MASK     fds;
e345da6
+  gint            sockno;
e345da6
 
e345da6
   /*  Set time struct  */
e345da6
   if (timeout)
e345da6
@@ -295,7 +300,10 @@ script_fu_server_listen (gint timeout)
e345da6
     }
e345da6
 
e345da6
   FD_ZERO (&fds);
e345da6
-  FD_SET (server_sock, &fds);
e345da6
+  for (sockno = 0; sockno < server_socks_used; sockno++)
e345da6
+    {
e345da6
+      FD_SET (server_socks[sockno], &fds);
e345da6
+    }
e345da6
   g_hash_table_foreach (clients, script_fu_server_add_fd, &fds);
e345da6
 
e345da6
   /* Block until input arrives on one or more active sockets
e345da6
@@ -307,15 +315,25 @@ script_fu_server_listen (gint timeout)
e345da6
       return;
e345da6
     }
e345da6
 
e345da6
-  /* Service the server socket if it has input pending. */
e345da6
-  if (FD_ISSET (server_sock, &fds))
e345da6
+  /* Service the server sockets if any has input pending. */
e345da6
+  for (sockno = 0; sockno < server_socks_used; sockno++)
0236e30
     {
0236e30
-      struct sockaddr_in  clientname;
0236e30
+      struct sockaddr_storage  client;
0236e30
+      struct sockaddr_in      *client_in;
0236e30
+      struct sockaddr_in6     *client_in6;
0236e30
+      gchar                    clientname[NI_MAXHOST];
0236e30
 
0236e30
       /* Connection request on original socket. */
0236e30
-      guint size = sizeof (clientname);
e345da6
-      gint  new  = accept (server_sock,
0236e30
-                           (struct sockaddr *) &clientname, &size);
e345da6
+      guint                    size = sizeof (client);
e345da6
+      gint                     new;
e345da6
+      guint                    portno;
e345da6
+
e345da6
+      if (! FD_ISSET (server_socks[sockno], &fds))
e345da6
+        {
e345da6
+          continue;
e345da6
+        }
e345da6
+
e345da6
+      new = accept (server_socks[sockno], (struct sockaddr *) &client, &size);
0236e30
 
0236e30
       if (new < 0)
0236e30
         {
e345da6
@@ -324,13 +342,34 @@ script_fu_server_listen (gint timeout)
0236e30
         }
0236e30
 
0236e30
       /*  Associate the client address with the socket  */
0236e30
-      g_hash_table_insert (clients,
0236e30
-                           GINT_TO_POINTER (new),
0236e30
-                           g_strdup (inet_ntoa (clientname.sin_addr)));
0236e30
+
0236e30
+      /* If all else fails ... */
0236e30
+      strncpy (clientname, "(error during host address lookup)", NI_MAXHOST-1);
0236e30
+
0236e30
+      /* Lookup address */
0236e30
+      (void) getnameinfo ((struct sockaddr *) &client, size, clientname,
0236e30
+                          sizeof (clientname), NULL, 0, NI_NUMERICHOST);
0236e30
+
e345da6
+      g_hash_table_insert (clients, GINT_TO_POINTER (new),
e345da6
+                           g_strdup (clientname));
e345da6
+
0236e30
+      /* Determine port number */
0236e30
+      switch (client.ss_family)
0236e30
+        {
0236e30
+          case AF_INET:
0236e30
+            client_in = (struct sockaddr_in *) &client;
0236e30
+            portno = (guint) g_ntohs (client_in->sin_port);
0236e30
+            break;
0236e30
+          case AF_INET6:
0236e30
+            client_in6 = (struct sockaddr_in6 *) &client;
0236e30
+            portno = (guint) g_ntohs (client_in6->sin6_port);
0236e30
+            break;
0236e30
+          default:
0236e30
+            portno = 0;
0236e30
+        }
0236e30
 
0236e30
       server_log ("Server: connect from host %s, port %d.\n",
0236e30
-                  inet_ntoa (clientname.sin_addr),
0236e30
-                  (unsigned int) ntohs (clientname.sin_port));
0236e30
+                  clientname, portno);
0236e30
     }
0236e30
 
0236e30
   /* Service the client sockets. */
e345da6
@@ -392,18 +431,46 @@ static void
e345da6
 server_start (gint         port,
e345da6
               const gchar *logfile)
e345da6
 {
e345da6
-  const gchar *progress;
10646e4
-
10646e4
-  /* First of all, create the socket and set it up to accept connections. */
10646e4
-  /* This may fail if there's a server running on this port already.      */
10646e4
-  server_sock = make_socket (port);
e345da6
+  struct addrinfo *ai,
e345da6
+                  *ai_curr;
e345da6
+  struct addrinfo  hints;
e345da6
+  gint             e,
e345da6
+                   sockno;
e345da6
+  gchar           *port_s;
10646e4
+
e345da6
+  const gchar     *progress;
10646e4
+
e345da6
+  memset (&hints, 0, sizeof (hints));
e345da6
+  hints.ai_flags = AI_PASSIVE | AI_ADDRCONFIG;
e345da6
+  hints.ai_socktype = SOCK_STREAM;
e345da6
+
e345da6
+  port_s = g_strdup_printf ("%d", port);
e345da6
+  e = getaddrinfo (NULL, port_s, &hints, &ai;;
e345da6
+  g_free (port_s);
10646e4
 
10646e4
-  if (listen (server_sock, 5) < 0)
e345da6
+  if (e != 0)
e345da6
     {
e345da6
-      print_socket_api_error ("listen");
e345da6
+      g_printerr ("getaddrinfo: %s", gai_strerror (e));
e345da6
       return;
e345da6
     }
e345da6
 
e345da6
+  for (ai_curr = ai, sockno = 0;
e345da6
+       ai_curr != NULL && sockno < server_socks_len;
e345da6
+       ai_curr = ai_curr->ai_next, sockno++)
e345da6
+    {
e345da6
+      /* Create the socket and set it up to accept connections.          */
e345da6
+      /* This may fail if there's a server running on this port already. */
e345da6
+      server_socks[sockno] = make_socket (ai_curr);
e345da6
+
e345da6
+      if (listen (server_socks[sockno], 5) < 0)
e345da6
+        {
e345da6
+          print_socket_api_error ("listen");
e345da6
+          return;
e345da6
+        }
e345da6
+    }
e345da6
+
e345da6
+  server_socks_used = sockno;
e345da6
+
e345da6
   /*  Setup up the server log file  */
e345da6
   if (logfile && *logfile)
e345da6
     server_log_file = g_fopen (logfile, "a");
e345da6
@@ -592,11 +659,10 @@ read_from_client (gint filedes)
e345da6
 }
e345da6
 
e345da6
 static gint
e345da6
-make_socket (guint port)
e345da6
+make_socket (const struct addrinfo *ai)
e345da6
 {
e345da6
-  struct sockaddr_in name;
e345da6
-  gint               sock;
e345da6
-  gint               v = 1;
e345da6
+  gint                    sock;
e345da6
+  gint                    v = 1;
e345da6
 
e345da6
   /*  Win32 needs the winsock library initialized.  */
e345da6
 #ifdef G_OS_WIN32
e345da6
@@ -620,7 +686,7 @@ make_socket (guint port)
e345da6
 #endif
e345da6
 
e345da6
   /* Create the socket. */
e345da6
-  sock = socket (PF_INET, SOCK_STREAM, 0);
e345da6
+  sock = socket (ai->ai_family, ai->ai_socktype, ai->ai_protocol);
e345da6
   if (sock < 0)
e345da6
     {
e345da6
       print_socket_api_error ("socket");
e345da6
@@ -629,12 +695,20 @@ make_socket (guint port)
e345da6
 
e345da6
   setsockopt (sock, SOL_SOCKET, SO_REUSEADDR, &v, sizeof(v));
e345da6
 
e345da6
-  /* Give the socket a name. */
e345da6
-  name.sin_family      = AF_INET;
e345da6
-  name.sin_port        = htons (port);
e345da6
-  name.sin_addr.s_addr = htonl (INADDR_ANY);
e345da6
+#ifdef IPV6_V6ONLY
e345da6
+  /* Only listen on IPv6 addresses, otherwise bind() will fail. */
e345da6
+  if (ai->ai_family == AF_INET6)
e345da6
+    {
e345da6
+      v = 1;
e345da6
+      if (setsockopt (sock, IPPROTO_IPV6, IPV6_V6ONLY, &v, sizeof(v)) < 0)
e345da6
+        {
e345da6
+          print_socket_api_error ("setsockopt");
e345da6
+          gimp_quit();
e345da6
+        }
e345da6
+    }
e345da6
+#endif
e345da6
 
e345da6
-  if (bind (sock, (struct sockaddr *) &name, sizeof (name)) < 0)
e345da6
+  if (bind (sock, ai->ai_addr, ai->ai_addrlen) < 0)
e345da6
     {
e345da6
       print_socket_api_error ("bind");
e345da6
       gimp_quit ();
10646e4
@@ -672,7 +746,12 @@ script_fu_server_shutdown_fd (gpointer k
e345da6
 static void
e345da6
 server_quit (void)
e345da6
 {
e345da6
-  CLOSESOCKET (server_sock);
e345da6
+  gint sockno;
e345da6
+
e345da6
+  for (sockno = 0; sockno < server_socks_used; sockno++)
e345da6
+    {
e345da6
+      CLOSESOCKET (server_socks[sockno]);
e345da6
+    }
e345da6
 
e345da6
   if (clients)
e345da6
     {