Index: src/cgi.c
==================================================================
--- src/cgi.c
+++ src/cgi.c
@@ -42,10 +42,11 @@
 #endif
 #include <time.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>
+#include <netdb.h>
 #include "cgi.h"
 
 #if INTERFACE
 /*
 ** Shortcuts for cgi_parameter.  P("x") returns the value of query parameter
@@ -1119,10 +1120,21 @@
   }
   if( zLeftOver ){ *zLeftOver = zInput; }
   return zResult;
 }
 
+/*
+** All possible forms of an IP address.  Needed to work around GCC strict
+** aliasing rules.
+*/
+typedef union {
+  struct sockaddr sa;              /* Abstract superclass */
+  struct sockaddr_in sa4;          /* IPv4 */
+  struct sockaddr_in6 sa6;         /* IPv6 */
+  struct sockaddr_storage sas;     /* Should be the maximum of the above 3 */
+} address;
+
 /*
 ** This routine handles a single HTTP request which is coming in on
 ** standard input and which replies on standard output.
 **
 ** The HTTP request is read from standard input and is used to initialize
@@ -1157,15 +1169,19 @@
   cgi_setenv("REQUEST_URI", zToken);
   for(i=0; zToken[i] && zToken[i]!='?'; i++){}
   if( zToken[i] ) zToken[i++] = 0;
   cgi_setenv("PATH_INFO", zToken);
   cgi_setenv("QUERY_STRING", &zToken[i]);
-  if( zIpAddr==0 &&
-        getpeername(fileno(g.httpIn), (struct sockaddr*)&remoteName, 
-                                &size)>=0
-  ){
-    zIpAddr = inet_ntoa(remoteName.sin_addr);
+  if( zIpAddr==0 ){
+    address remoteAddr;
+    unsigned int size = sizeof(remoteAddr);
+    char zHost[NI_MAXHOST];
+    if( getpeername(fileno(g.httpIn), &remoteAddr.sa, &size)>=0 ){
+      getnameinfo(&remoteAddr.sa, size, zHost, sizeof(zHost), 0, 0,
+                  NI_NUMERICHOST);
+      zIpAddr = mprintf("%s", zHost);
+    }
   }
   if( zIpAddr ){   
     cgi_setenv("REMOTE_ADDR", zIpAddr);
     g.zIpAddr = mprintf("%s", zIpAddr);
   }

Index: src/http_socket.c
==================================================================
--- src/http_socket.c
+++ src/http_socket.c
@@ -41,10 +41,11 @@
 #  include <netdb.h>
 #endif
 #include <assert.h>
 #include <sys/types.h>
 #include <signal.h>
+#include <errno.h>
 
 /*
 ** There can only be a single socket connection open at a time.
 ** State information about that socket is stored in the following
 ** local variables:
@@ -136,46 +137,61 @@
 **
 ** Return the number of errors.
 */
 int socket_open(void){
   static struct sockaddr_in addr;  /* The server address */
-  static int addrIsInit = 0;       /* True once addr is initialized */
+  static int addrIsInit = 0;       /* True when initialized once */
+  static struct addrinfo *p = 0;   /* Succcessful open */
 
   socket_global_init();
   if( !addrIsInit ){
-    addr.sin_family = AF_INET;
-    addr.sin_port = htons(g.urlPort);
-    *(int*)&addr.sin_addr = inet_addr(g.urlName);
-    if( -1 == *(int*)&addr.sin_addr ){
-#ifndef FOSSIL_STATIC_LINK
-      struct hostent *pHost;
-      pHost = gethostbyname(g.urlName);
-      if( pHost!=0 ){
-        memcpy(&addr.sin_addr,pHost->h_addr_list[0],pHost->h_length);
-      }else
-#endif
-      {
-        socket_set_errmsg("can't resolve host name: %s", g.urlName);
-        return 1;
-      }
+    struct addrinfo sHints;
+    int rc;
+    char zPort[30];
+    
+    memset(&sHints, 0, sizeof(sHints));
+    sHints.ai_family = AF_UNSPEC;
+    sHints.ai_socktype = SOCK_STREAM;
+    sHints.ai_flags = 0;
+    sHints.ai_protocol = 0;
+    sqlite3_snprintf(sizeof(zPort), zPort, "%d", g.urlPort);
+    rc = getaddrinfo(g.urlName, zPort, &sHints, &p);
+    if( rc!=0 ){
+      fossil_fatal("getaddrinfo(\"%s\",\"%s\",...): %s",
+                   g.urlName, zPort, gai_strerror(rc));
+    }
+    if( p==0 ){
+      fossil_fatal("no IP addresses returned by getaddrinfo()");
     }
     addrIsInit = 1;
+  }
 
-    /* Set the Global.zIpAddr variable to the server we are talking to.
-    ** This is used to populate the ipaddr column of the rcvfrom table,
-    ** if any files are received from the server.
-    */
-    g.zIpAddr = mprintf("%s", inet_ntoa(addr.sin_addr));
-  }
-  iSocket = socket(AF_INET,SOCK_STREAM,0);
-  if( iSocket<0 ){
-    socket_set_errmsg("cannot create a socket");
-    return 1;
+  while( p ){
+    char zHost[NI_MAXHOST];
+    iSocket = socket(p->ai_family, p->ai_socktype, p->ai_protocol);
+    if( iSocket<0 ){
+      fossil_warning("socket() failed: %s", strerror(errno));
+      p = p->ai_next;
+      continue;
+    }
+    if( connect(iSocket, p->ai_addr, p->ai_addrlen)<0 ){
+      fossil_warning("connect() failed: %s", strerror(errno));
+      p = p->ai_next;
+      socket_close();
+      continue;
+    }
+    p->ai_next = 0;
+    if( getnameinfo(p->ai_addr, p->ai_addrlen, zHost, sizeof(zHost),
+                    0, 0, NI_NUMERICHOST)==0 ){
+      g.zIpAddr = mprintf("%s", zHost);
+    }else{
+      fossil_fatal("cannot find numeric host IP address");
+    }
+    break;
   }
-  if( connect(iSocket,(struct sockaddr*)&addr,sizeof(addr))<0 ){
-    socket_set_errmsg("cannot connect to host %s:%d", g.urlName, g.urlPort);
-    socket_close();
+  if( p==0 ){
+    socket_set_errmsg("cannot create a socket");
     return 1;
   }
 #if !defined(_WIN32)
   signal(SIGPIPE, SIG_IGN);
 #endif

Index: src/url.c
==================================================================
--- src/url.c
+++ src/url.c
@@ -101,12 +101,22 @@
       }
       for(j=i+1; (c=zUrl[j])!=0 && c!='/' && c!=':'; j++){}
       g.urlName = mprintf("%.*s", j-i-1, &zUrl[i+1]);
       i = j;
     }else{
-      for(i=iStart; (c=zUrl[i])!=0 && c!='/' && c!=':'; i++){}
+      int inSquare = 0;
+      int n;
+      for(i=iStart; (c=zUrl[i])!=0 && c!='/' && (inSquare || c!=':'); i++){
+        if( c=='[' ) inSquare = 1;
+        if( c==']' ) inSquare = 0;
+      }
       g.urlName = mprintf("%.*s", i-iStart, &zUrl[iStart]);
+      n = strlen(g.urlName);
+      if( g.urlName[0]=='[' && n>2 && g.urlName[n-1]==']' ){
+        g.urlName++;
+        g.urlName[n-2] = 0;
+      }
       zLogin = mprintf("");
     }
     url_tolower(g.urlName);
     if( c==':' ){
       g.urlPort = 0;