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
This commit is contained in:
parent
e31375ac4e
commit
3dade5fe59
2 changed files with 35 additions and 7 deletions
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue