URI:
       tlib9/dial: fix addrlen in connect() and bind() - plan9port - [fork] Plan 9 from user space
  HTML git clone git://src.adamsgaard.dk/plan9port
   DIR Log
   DIR Files
   DIR Refs
   DIR README
   DIR LICENSE
       ---
   DIR commit 3dade5fe59d80e9d23916d15db93ea39407f694e
   DIR parent e31375ac4e12494f6a085cb2c9d51e9e61dd8216
  HTML Author: David du Colombier <0intro@gmail.com>
       Date:   Tue,  4 Sep 2012 18:45:19 -0400
       
       lib9/dial: fix addrlen in connect() and bind()
       
       On some systems, the third argument of connect() and bind()
       is expected to be the length of the address family instead
       of the length of the sockaddr structure.
       
       R=rsc
       http://codereview.appspot.com/6489072
       
       Diffstat:
         M src/lib9/announce.c                 |      22 ++++++++++++++++++----
         M src/lib9/dial.c                     |      20 +++++++++++++++++---
       
       2 files changed, 35 insertions(+), 7 deletions(-)
       ---
   DIR diff --git a/src/lib9/announce.c b/src/lib9/announce.c
       t@@ -33,6 +33,20 @@ putfd(char *dir, int fd)
        #undef unix
        #define unix sockunix
        
       +static int
       +addrlen(struct sockaddr_storage *ss)
       +{
       +        switch(ss->ss_family){
       +        case AF_INET:
       +                return sizeof(struct sockaddr_in);
       +        case AF_INET6:
       +                return sizeof(struct sockaddr_in6);
       +        case AF_UNIX:
       +                return sizeof(struct sockaddr_un);
       +        }
       +        return 0;
       +}
       +
        int
        p9announce(char *addr, char *dir)
        {
       t@@ -73,7 +87,7 @@ p9announce(char *addr, char *dir)
                        n = 1;
                        setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char*)&n, sizeof n);
                }
       -        if(bind(s, (struct sockaddr*)&ss, sizeof ss) < 0){
       +        if(bind(s, (struct sockaddr*)&ss, addrlen(&ss)) < 0){
                        close(s);
                        return -1;
                }
       t@@ -86,16 +100,16 @@ p9announce(char *addr, char *dir)
        Unix:
                if((s = socket(ss.ss_family, SOCK_STREAM, 0)) < 0)
                        return -1;
       -        if(bind(s, (struct sockaddr*)&ss, sizeof (struct sockaddr_un)) < 0){
       +        if(bind(s, (struct sockaddr*)&ss, addrlen(&ss)) < 0){
                        if(errno == EADDRINUSE
       -                && connect(s, (struct sockaddr*)&ss, sizeof (struct sockaddr_un)) < 0
       +                && connect(s, (struct sockaddr*)&ss, addrlen(&ss)) < 0
                        && errno == ECONNREFUSED){
                                /* dead socket, so remove it */
                                remove(unix);
                                close(s);
                                if((s = socket(ss.ss_family, SOCK_STREAM, 0)) < 0)
                                        return -1;
       -                        if(bind(s, (struct sockaddr*)&ss, sizeof (struct sockaddr_un)) >= 0)
       +                        if(bind(s, (struct sockaddr*)&ss, addrlen(&ss)) >= 0)
                                        goto Success;
                        }
                        close(s);
   DIR diff --git a/src/lib9/dial.c b/src/lib9/dial.c
       t@@ -32,6 +32,20 @@ isany(struct sockaddr_storage *ss)
                return 0;
        }
        
       +static int
       +addrlen(struct sockaddr_storage *ss)
       +{
       +        switch(ss->ss_family){
       +        case AF_INET:
       +                return sizeof(struct sockaddr_in);
       +        case AF_INET6:
       +                return sizeof(struct sockaddr_in6);
       +        case AF_UNIX:
       +                return sizeof(struct sockaddr_un);
       +        }
       +        return 0;
       +}
       +
        int
        p9dial(char *addr, char *local, char *dummy2, int *dummy3)
        {
       t@@ -101,7 +115,7 @@ p9dial(char *addr, char *local, char *dummy2, int *dummy3)
                                n = 1;
                                setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char*)&n, sizeof n);
                        }
       -                if(bind(s, (struct sockaddr*)&ssl, sizeof ssl) < 0)
       +                if(bind(s, (struct sockaddr*)&ssl, addrlen(&ssl)) < 0)
                                goto badlocal;
                        free(buf);
                }
       t@@ -109,7 +123,7 @@ p9dial(char *addr, char *local, char *dummy2, int *dummy3)
                n = 1;
                setsockopt(s, SOL_SOCKET, SO_BROADCAST, &n, sizeof n);
                if(!isany(&ss)){
       -                if(connect(s, (struct sockaddr*)&ss, sizeof ss) < 0){
       +                if(connect(s, (struct sockaddr*)&ss, addrlen(&ss)) < 0){
                                close(s);
                                return -1;
                        }
       t@@ -134,7 +148,7 @@ Unix:
                        werrstr("socket: %r");
                        return -1;
                }
       -        if(connect(s, (struct sockaddr*)&ss, sizeof (struct sockaddr_un)) < 0){
       +        if(connect(s, (struct sockaddr*)&ss, addrlen(&ss)) < 0){
                        werrstr("connect %s: %r", ((struct sockaddr_un*)&ss)->sun_path);
                        close(s);
                        return -1;