Changes On Branch ipv6
Not logged in

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Changes In Branch ipv6 Excluding Merge-Ins

This is equivalent to a diff from e40e79b7ab to 89fb414274

2012-07-07
14:07
Update the inetd handler so that it works with IPv6. Leaf check-in: 89fb414274 user: drh tags: ipv6
13:32
Fix the URL parser so that it is able to handle IPv6 addresses. Fixes to the IPv6 client-side code. check-in: beea59873a user: drh tags: ipv6
2012-07-06
16:18
/json/query now fails without executing the query if the provided query has no result _columns_ (to explicitly disallow INSERT/DELETE/DROP, etc.). check-in: 3e1dd97f77 user: stephan tags: trunk
2012-07-05
21:25
Work toward getting Fossil to be able to sync over IPV6. This check-in compiles, but we do not yet have a server to test it on. check-in: 0268e771ef user: drh tags: ipv6
19:24
Minor interal json refactoring made possible by recent cson changes. check-in: e40e79b7ab user: stephan tags: trunk
19:03
Pulled in latest cson amalgamation for the cson_type_id addition and started refactoring some O(N) lookups to O(1) based on that addition. check-in: cde55bd7a3 user: stephan tags: trunk

Changes to src/cgi.c.

    40     40   #ifdef __EMX__
    41     41     typedef int socklen_t;
    42     42   #endif
    43     43   #include <time.h>
    44     44   #include <stdio.h>
    45     45   #include <stdlib.h>
    46     46   #include <unistd.h>
           47  +#include <netdb.h>
    47     48   #include "cgi.h"
    48     49   
    49     50   #if INTERFACE
    50     51   /*
    51     52   ** Shortcuts for cgi_parameter.  P("x") returns the value of query parameter
    52     53   ** or cookie "x", or NULL if there is no such parameter or cookie.  PD("x","y")
    53     54   ** does the same except "y" is returned in place of NULL if there is not match.
................................................................................
  1117   1118       zInput++;
  1118   1119       while( fossil_isspace(*zInput) ){ zInput++; }
  1119   1120     }
  1120   1121     if( zLeftOver ){ *zLeftOver = zInput; }
  1121   1122     return zResult;
  1122   1123   }
  1123   1124   
         1125  +/*
         1126  +** All possible forms of an IP address.  Needed to work around GCC strict
         1127  +** aliasing rules.
         1128  +*/
         1129  +typedef union {
         1130  +  struct sockaddr sa;              /* Abstract superclass */
         1131  +  struct sockaddr_in sa4;          /* IPv4 */
         1132  +  struct sockaddr_in6 sa6;         /* IPv6 */
         1133  +  struct sockaddr_storage sas;     /* Should be the maximum of the above 3 */
         1134  +} address;
         1135  +
  1124   1136   /*
  1125   1137   ** This routine handles a single HTTP request which is coming in on
  1126   1138   ** standard input and which replies on standard output.
  1127   1139   **
  1128   1140   ** The HTTP request is read from standard input and is used to initialize
  1129   1141   ** environment variables as per CGI.  The cgi_init() routine to complete
  1130   1142   ** the setup.  Once all the setup is finished, this procedure returns
................................................................................
  1155   1167       malformed_request();
  1156   1168     }
  1157   1169     cgi_setenv("REQUEST_URI", zToken);
  1158   1170     for(i=0; zToken[i] && zToken[i]!='?'; i++){}
  1159   1171     if( zToken[i] ) zToken[i++] = 0;
  1160   1172     cgi_setenv("PATH_INFO", zToken);
  1161   1173     cgi_setenv("QUERY_STRING", &zToken[i]);
  1162         -  if( zIpAddr==0 &&
  1163         -        getpeername(fileno(g.httpIn), (struct sockaddr*)&remoteName, 
  1164         -                                &size)>=0
  1165         -  ){
  1166         -    zIpAddr = inet_ntoa(remoteName.sin_addr);
         1174  +  if( zIpAddr==0 ){
         1175  +    address remoteAddr;
         1176  +    unsigned int size = sizeof(remoteAddr);
         1177  +    char zHost[NI_MAXHOST];
         1178  +    if( getpeername(fileno(g.httpIn), &remoteAddr.sa, &size)>=0 ){
         1179  +      getnameinfo(&remoteAddr.sa, size, zHost, sizeof(zHost), 0, 0,
         1180  +                  NI_NUMERICHOST);
         1181  +      zIpAddr = mprintf("%s", zHost);
         1182  +    }
  1167   1183     }
  1168   1184     if( zIpAddr ){   
  1169   1185       cgi_setenv("REMOTE_ADDR", zIpAddr);
  1170   1186       g.zIpAddr = mprintf("%s", zIpAddr);
  1171   1187     }
  1172   1188    
  1173   1189     /* Get all the optional fields that follow the first line.

Changes to src/http_socket.c.

    39     39   #  include <arpa/inet.h>
    40     40   #  include <sys/socket.h>
    41     41   #  include <netdb.h>
    42     42   #endif
    43     43   #include <assert.h>
    44     44   #include <sys/types.h>
    45     45   #include <signal.h>
           46  +#include <errno.h>
    46     47   
    47     48   /*
    48     49   ** There can only be a single socket connection open at a time.
    49     50   ** State information about that socket is stored in the following
    50     51   ** local variables:
    51     52   */
    52     53   static int socketIsInit = 0;    /* True after global initialization */
................................................................................
   134    135   **    g.urlName       Name of the server.  Ex: www.fossil-scm.org
   135    136   **    g.urlPort       TCP/IP port to use.  Ex: 80
   136    137   **
   137    138   ** Return the number of errors.
   138    139   */
   139    140   int socket_open(void){
   140    141     static struct sockaddr_in addr;  /* The server address */
   141         -  static int addrIsInit = 0;       /* True once addr is initialized */
          142  +  static int addrIsInit = 0;       /* True when initialized once */
          143  +  static struct addrinfo *p = 0;   /* Succcessful open */
   142    144   
   143    145     socket_global_init();
   144    146     if( !addrIsInit ){
   145         -    addr.sin_family = AF_INET;
   146         -    addr.sin_port = htons(g.urlPort);
   147         -    *(int*)&addr.sin_addr = inet_addr(g.urlName);
   148         -    if( -1 == *(int*)&addr.sin_addr ){
   149         -#ifndef FOSSIL_STATIC_LINK
   150         -      struct hostent *pHost;
   151         -      pHost = gethostbyname(g.urlName);
   152         -      if( pHost!=0 ){
   153         -        memcpy(&addr.sin_addr,pHost->h_addr_list[0],pHost->h_length);
   154         -      }else
   155         -#endif
   156         -      {
   157         -        socket_set_errmsg("can't resolve host name: %s", g.urlName);
   158         -        return 1;
   159         -      }
          147  +    struct addrinfo sHints;
          148  +    int rc;
          149  +    char zPort[30];
          150  +    
          151  +    memset(&sHints, 0, sizeof(sHints));
          152  +    sHints.ai_family = AF_UNSPEC;
          153  +    sHints.ai_socktype = SOCK_STREAM;
          154  +    sHints.ai_flags = 0;
          155  +    sHints.ai_protocol = 0;
          156  +    sqlite3_snprintf(sizeof(zPort), zPort, "%d", g.urlPort);
          157  +    rc = getaddrinfo(g.urlName, zPort, &sHints, &p);
          158  +    if( rc!=0 ){
          159  +      fossil_fatal("getaddrinfo(\"%s\",\"%s\",...): %s",
          160  +                   g.urlName, zPort, gai_strerror(rc));
          161  +    }
          162  +    if( p==0 ){
          163  +      fossil_fatal("no IP addresses returned by getaddrinfo()");
   160    164       }
   161    165       addrIsInit = 1;
          166  +  }
   162    167   
   163         -    /* Set the Global.zIpAddr variable to the server we are talking to.
   164         -    ** This is used to populate the ipaddr column of the rcvfrom table,
   165         -    ** if any files are received from the server.
   166         -    */
   167         -    g.zIpAddr = mprintf("%s", inet_ntoa(addr.sin_addr));
   168         -  }
   169         -  iSocket = socket(AF_INET,SOCK_STREAM,0);
   170         -  if( iSocket<0 ){
   171         -    socket_set_errmsg("cannot create a socket");
   172         -    return 1;
          168  +  while( p ){
          169  +    char zHost[NI_MAXHOST];
          170  +    iSocket = socket(p->ai_family, p->ai_socktype, p->ai_protocol);
          171  +    if( iSocket<0 ){
          172  +      fossil_warning("socket() failed: %s", strerror(errno));
          173  +      p = p->ai_next;
          174  +      continue;
          175  +    }
          176  +    if( connect(iSocket, p->ai_addr, p->ai_addrlen)<0 ){
          177  +      fossil_warning("connect() failed: %s", strerror(errno));
          178  +      p = p->ai_next;
          179  +      socket_close();
          180  +      continue;
          181  +    }
          182  +    p->ai_next = 0;
          183  +    if( getnameinfo(p->ai_addr, p->ai_addrlen, zHost, sizeof(zHost),
          184  +                    0, 0, NI_NUMERICHOST)==0 ){
          185  +      g.zIpAddr = mprintf("%s", zHost);
          186  +    }else{
          187  +      fossil_fatal("cannot find numeric host IP address");
          188  +    }
          189  +    break;
   173    190     }
   174         -  if( connect(iSocket,(struct sockaddr*)&addr,sizeof(addr))<0 ){
   175         -    socket_set_errmsg("cannot connect to host %s:%d", g.urlName, g.urlPort);
   176         -    socket_close();
          191  +  if( p==0 ){
          192  +    socket_set_errmsg("cannot create a socket");
   177    193       return 1;
   178    194     }
   179    195   #if !defined(_WIN32)
   180    196     signal(SIGPIPE, SIG_IGN);
   181    197   #endif
   182    198     return 0;
   183    199   }

Changes to src/url.c.

    99     99         }else{
   100    100           zLogin = mprintf("%t@", g.urlUser);
   101    101         }
   102    102         for(j=i+1; (c=zUrl[j])!=0 && c!='/' && c!=':'; j++){}
   103    103         g.urlName = mprintf("%.*s", j-i-1, &zUrl[i+1]);
   104    104         i = j;
   105    105       }else{
   106         -      for(i=iStart; (c=zUrl[i])!=0 && c!='/' && c!=':'; i++){}
          106  +      int inSquare = 0;
          107  +      int n;
          108  +      for(i=iStart; (c=zUrl[i])!=0 && c!='/' && (inSquare || c!=':'); i++){
          109  +        if( c=='[' ) inSquare = 1;
          110  +        if( c==']' ) inSquare = 0;
          111  +      }
   107    112         g.urlName = mprintf("%.*s", i-iStart, &zUrl[iStart]);
          113  +      n = strlen(g.urlName);
          114  +      if( g.urlName[0]=='[' && n>2 && g.urlName[n-1]==']' ){
          115  +        g.urlName++;
          116  +        g.urlName[n-2] = 0;
          117  +      }
   108    118         zLogin = mprintf("");
   109    119       }
   110    120       url_tolower(g.urlName);
   111    121       if( c==':' ){
   112    122         g.urlPort = 0;
   113    123         i++;
   114    124         while( (c = zUrl[i])!=0 && fossil_isdigit(c) ){