IPv6 Patch

Tomash Brechko tomash.brechko at gmail.com
Tue Jan 29 07:54:08 UTC 2008


On Mon, Jan 28, 2008 at 16:46:03 -0800, Brian Aker wrote:
> The attached patch does the following:
> 1) Adds support for binding with host names (not just ip addresses)
> 2) Makes memcached support IPv6 for TCP connections.

The patch is not 100% complete, getaddrinfo() returns the list of
addresses, and you have to bind to all of them on the server side (and
try to connect to all of them in turn on the client side).  This page
explains how:

  http://people.redhat.com/drepper/userapi-ipv6.html

and this gives some clues why:

  http://people.redhat.com/drepper/linux-rfc3484.html


Here are some more minor issues:


> @@ -2046,7 +2047,7 @@
>      bool stop = false;
>      int sfd, flags = 1;
>      socklen_t addrlen;
> -    struct sockaddr addr;
> +    struct sockaddr_storage addr;
>      int res;
>  
>      assert(c != NULL);
> @@ -2056,7 +2057,7 @@
>          switch(c->state) {
>          case conn_listening:
>              addrlen = sizeof(addr);
> -            if ((sfd = accept(c->sfd, &addr, &addrlen)) == -1) {
> +            if ((sfd = accept(c->sfd, (struct sockaddr *)&addr, &addrlen)) == -1) {

The code fills addr and addrlen, but never uses them if I'm correct,
so accept(c->sfd, NULL, NULL) would do better.


> +    /*
> +     * the memset call clears nonstandard fields in some impementations
> +     * that otherwise mess things up.
> +     */
> +    memset(&hints, 0, sizeof (hints));
> +    hints.ai_flags = AI_PASSIVE;
> +    if (is_udp)
> +    {
> +      hints.ai_protocol = IPPROTO_UDP;
> +      hints.ai_socktype = SOCK_DGRAM;
> +      hints.ai_family = AF_INET;
> +    }
> +    else
> +    {
> +      hints.ai_family = AF_UNSPEC;
> +      hints.ai_protocol = IPPROTO_TCP;
> +      hints.ai_socktype = SOCK_STREAM;
> +    }

It is recommended to set AI_ADDRCONFIG flag, and you shouldn't set
ai_family and ai_protocol, the whole getaddrinfo() mechanism is
positioned to be protocol independent.


> +    error= getaddrinfo(settings.inter, port_buf, &hints, &ai);
> +    if (error)
> +    {
> +      fprintf(stderr, "getaddrinfo(): %s\n", gai_strerror(error));
> +      return -1;
> +    }

It should be

       if (error != 0) {
           if (error != EAI_SYSTEM)
               fprintf(stderr, "getaddrinfo(): %s\n", gai_strerror(error));
           else
               perror("getaddrinfo()");
     
           return -1;
       }


> +    if (bind(sfd, ai->ai_addr, ai->ai_addrlen) == -1) {
>          perror("bind()");
>          close(sfd);
>          return -1;

When binding to several addresses, you will have to to handle
EADDRINUSE differently (even though SO_REUSEADDR is set, pointers
above explain why).


> @@ -2379,6 +2402,8 @@
>          close(sfd);
>          return -1;
>      }
> +    freeaddrinfo(ai);
> +
>      return sfd;
>  }

You have lots of premature returns where you better to do
freeaddrinfo() too, just for the case ;).



-- 
   Tomash Brechko


More information about the memcached mailing list