aboutsummaryrefslogtreecommitdiff
path: root/src/lib9/dial.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib9/dial.c')
-rw-r--r--src/lib9/dial.c53
1 files changed, 24 insertions, 29 deletions
diff --git a/src/lib9/dial.c b/src/lib9/dial.c
index 7c7f7480..730b60e3 100644
--- a/src/lib9/dial.c
+++ b/src/lib9/dial.c
@@ -19,18 +19,29 @@
#undef unix
#define unix xunix
+static int
+isany(struct sockaddr_storage *ss)
+{
+ switch(ss->ss_family){
+ case AF_INET:
+ return (((struct sockaddr_in*)ss)->sin_addr.s_addr == INADDR_ANY);
+ case AF_INET6:
+ return (memcmp(((struct sockaddr_in6*)ss)->sin6_addr.s6_addr,
+ in6addr_any.s6_addr, sizeof (struct in6_addr)) == 0);
+ }
+ return 0;
+}
+
int
p9dial(char *addr, char *local, char *dummy2, int *dummy3)
{
char *buf;
char *net, *unix;
- u32int host;
int port;
int proto;
socklen_t sn;
int n;
- struct sockaddr_in sa, sal;
- struct sockaddr_un su;
+ struct sockaddr_storage ss, ssl;
int s;
if(dummy2 || dummy3){
@@ -42,11 +53,11 @@ p9dial(char *addr, char *local, char *dummy2, int *dummy3)
if(buf == nil)
return -1;
- if(p9dialparse(buf, &net, &unix, &host, &port) < 0){
+ if(p9dialparse(buf, &net, &unix, &ss, &port) < 0){
free(buf);
return -1;
}
- if(strcmp(net, "unix") != 0 && host == 0){
+ if(strcmp(net, "unix") != 0 && isany(&ss)){
werrstr("invalid dial address 0.0.0.0 (aka *)");
free(buf);
return -1;
@@ -65,7 +76,7 @@ p9dial(char *addr, char *local, char *dummy2, int *dummy3)
}
free(buf);
- if((s = socket(AF_INET, proto, 0)) < 0)
+ if((s = socket(ss.ss_family, proto, 0)) < 0)
return -1;
if(local){
@@ -74,7 +85,7 @@ p9dial(char *addr, char *local, char *dummy2, int *dummy3)
close(s);
return -1;
}
- if(p9dialparse(buf, &net, &unix, &host, &port) < 0){
+ if(p9dialparse(buf, &net, &unix, &ss, &port) < 0){
badlocal:
free(buf);
close(s);
@@ -84,29 +95,21 @@ p9dial(char *addr, char *local, char *dummy2, int *dummy3)
werrstr("bad local address %s for dial %s", local, addr);
goto badlocal;
}
- memset(&sal, 0, sizeof sal);
- memmove(&sal.sin_addr, &host, 4);
- sal.sin_family = AF_INET;
- sal.sin_port = htons(port);
sn = sizeof n;
if(port && getsockopt(s, SOL_SOCKET, SO_TYPE, (void*)&n, &sn) >= 0
&& n == SOCK_STREAM){
n = 1;
setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char*)&n, sizeof n);
}
- if(bind(s, (struct sockaddr*)&sal, sizeof sal) < 0)
+ if(bind(s, (struct sockaddr*)&ssl, sizeof ssl) < 0)
goto badlocal;
free(buf);
}
n = 1;
setsockopt(s, SOL_SOCKET, SO_BROADCAST, &n, sizeof n);
- if(host != 0){
- memset(&sa, 0, sizeof sa);
- memmove(&sa.sin_addr, &host, 4);
- sa.sin_family = AF_INET;
- sa.sin_port = htons(port);
- if(connect(s, (struct sockaddr*)&sa, sizeof sa) < 0){
+ if(!isany(&ss)){
+ if(connect(s, (struct sockaddr*)&ss, sizeof ss) < 0){
close(s);
return -1;
}
@@ -126,21 +129,13 @@ Unix:
/* Allow regular files in addition to Unix sockets. */
if((s = open(unix, ORDWR)) >= 0)
return s;
- memset(&su, 0, sizeof su);
- su.sun_family = AF_UNIX;
- if(strlen(unix)+1 > sizeof su.sun_path){
- werrstr("unix socket name too long");
- free(buf);
- return -1;
- }
- strcpy(su.sun_path, unix);
free(buf);
- if((s = socket(AF_UNIX, SOCK_STREAM, 0)) < 0){
+ if((s = socket(ss.ss_family, SOCK_STREAM, 0)) < 0){
werrstr("socket: %r");
return -1;
}
- if(connect(s, (struct sockaddr*)&su, sizeof su) < 0){
- werrstr("connect %s: %r", su.sun_path);
+ if(connect(s, (struct sockaddr*)&ss, sizeof (struct sockaddr_un)) < 0){
+ werrstr("connect %s: %r", ((struct sockaddr_un*)&ss)->sun_path);
close(s);
return -1;
}