From 3dade5fe59d80e9d23916d15db93ea39407f694e Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Tue, 4 Sep 2012 18:45:19 -0400 Subject: 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 --- src/lib9/announce.c | 22 ++++++++++++++++++---- src/lib9/dial.c | 20 +++++++++++++++++--- 2 files changed, 35 insertions(+), 7 deletions(-) (limited to 'src/lib9') diff --git a/src/lib9/announce.c b/src/lib9/announce.c index 6e5357c5..cbf5b073 100644 --- a/src/lib9/announce.c +++ b/src/lib9/announce.c @@ -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) { @@ -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; } @@ -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); diff --git a/src/lib9/dial.c b/src/lib9/dial.c index 730b60e3..1ce3a147 100644 --- a/src/lib9/dial.c +++ b/src/lib9/dial.c @@ -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) { @@ -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); } @@ -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; } @@ -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; -- cgit v1.2.3