Commit Diff


commit - 5d03af6557cc215cabc0f83a274d9add703f526e
commit + 3409bc9ae1614ba47430a3f593fdbe5fc177c878
blob - d16b40436389d9e7533621976ebd95265af1aedb
blob + 45b22b691cded6bfcfdf2e11fd3883bd049d5c3b
--- include/libc.h
+++ include/libc.h
@@ -542,7 +542,7 @@ extern	void	privfree(void**);
 extern	int	p9accept(int, char*);
 extern	int	p9announce(char*, char*);
 extern	int	p9dial(char*, char*, char*, int*);
-extern	int	p9dialparse(char *ds, char **net, char **unixa, u32int *ip, int *port);
+extern	int	p9dialparse(char *ds, char **net, char **unixa, void *ip, int *port);
 extern	void	p9setnetmtpt(char*, int, char*);
 extern	int	p9listen(char*, char*);
 extern	char*	p9netmkaddr(char*, char*, char*);
blob - bdb283fb1cad7c87c89fdc6b9479cea98d953ddc
blob + dda0949f41a8449a16b480a85b77c82124e30e69
--- src/cmd/vbackup/vmount.c
+++ src/cmd/vbackup/vmount.c
@@ -1,6 +1,7 @@
 #include <u.h>
 #include <sys/socket.h>
 #include <netinet/in.h>
+#include <arpa/inet.h>
 #include <libc.h>
 #include "mountnfs.h"
 
@@ -20,7 +21,7 @@ void
 main(int argc, char **argv)
 {
 	char *p, *net, *unx;
-	u32int host;
+	char host[INET_ADDRSTRLEN];
 	int n, port, proto, verbose;
 	struct sockaddr_in sa;
 
@@ -50,12 +51,17 @@ main(int argc, char **argv)
 		usage();
 
 	p = p9netmkaddr(argv[0], "udp", "nfs");
-	if(p9dialparse(strdup(p), &net, &unx, &host, &port) < 0)
+	if(p9dialparse(strdup(p), &net, &unx, &sa, &port) < 0)
 		sysfatal("bad address '%s'", p);
 
+	if(sa.sin_family != AF_INET)
+		sysfatal("only IPv4 is supported");
+
+	inet_ntop(AF_INET, &(sa.sin_addr), host, INET_ADDRSTRLEN);
+
 	if(verbose)
-		print("nfs server is net=%s addr=%d.%d.%d.%d port=%d\n",
-			net, host&0xFF, (host>>8)&0xFF, (host>>16)&0xFF, host>>24, port);
+		print("nfs server is net=%s addr=%s port=%d\n",
+			net, host, port);
 
 	proto = 0;
 	if(strcmp(net, "tcp") == 0)
@@ -65,11 +71,6 @@ main(int argc, char **argv)
 	else
 		sysfatal("bad proto %s: can only handle tcp and udp", net);
 
-	memset(&sa, 0, sizeof sa);
-	memmove(&sa.sin_addr, &host, 4);
-	sa.sin_family = AF_INET;
-	sa.sin_port = htons(port);
-
 	mountnfs(proto, &sa, handle, handlelen, argv[1]);
 	exits(0);
 }
blob - 93340c116d348a38d893249221526c9888289ed9
blob + 064e057b60784c94472ad22e5f60a3e3556bcdfd
--- src/cmd/vbackup/vmount0.c
+++ src/cmd/vbackup/vmount0.c
@@ -1,6 +1,7 @@
 #include <u.h>
 #include <sys/socket.h>
 #include <netinet/in.h>
+#include <arpa/inet.h>
 #include <libc.h>
 #include "mountnfs.h"
 
@@ -22,7 +23,7 @@ void
 main(int argc, char **argv)
 {
 	char *p, *net, *unx;
-	u32int host;
+	char host[INET_ADDRSTRLEN];
 	int n, port, proto, verbose;
 	struct sockaddr_in sa;
 
@@ -52,12 +53,17 @@ main(int argc, char **argv)
 		usage();
 
 	p = p9netmkaddr(argv[0], "udp", "nfs");
-	if(p9dialparse(strdup(p), &net, &unx, &host, &port) < 0)
+	if(p9dialparse(strdup(p), &net, &unx, &sa, &port) < 0)
 		sysfatal("bad address '%s'", p);
 
+	if(sa.sin_family != AF_INET)
+		sysfatal("only IPv4 is supported");
+
+	inet_ntop(AF_INET, &(sa.sin_addr), host, INET_ADDRSTRLEN);
+
 	if(verbose)
-		print("nfs server is net=%s addr=%d.%d.%d.%d port=%d\n",
-			net, host&0xFF, (host>>8)&0xFF, (host>>16)&0xFF, host>>24, port);
+		print("nfs server is net=%s addr=%s port=%d\n",
+			net, host, port);
 
 	proto = 0;
 	if(strcmp(net, "tcp") == 0)
@@ -67,11 +73,6 @@ main(int argc, char **argv)
 	else
 		sysfatal("bad proto %s: can only handle tcp and udp", net);
 
-	memset(&sa, 0, sizeof sa);
-	memmove(&sa.sin_addr, &host, 4);
-	sa.sin_family = AF_INET;
-	sa.sin_port = htons(port);
-
 	mountnfs(proto, &sa, handle, handlelen, argv[1]);
 	exits(0);
 }
blob - 0c84ecdb287689aeebbbda85581cb7547b721b7c
blob + d8e910030bbc1330a5a35cfe9fcc38de6446ba45
--- src/lib9/_p9dialparse.c
+++ src/lib9/_p9dialparse.c
@@ -31,59 +31,36 @@ static struct {
 };
 
 static int
-parseip(char *host, u32int *pip)
+setport(struct sockaddr_storage *ss, int port)
 {
-	uchar addr[4];
-	int x, i;
-	char *p;
-
-	p = host;
-	for(i=0; i<4 && *p; i++){
-		x = strtoul(p, &p, 0);
-		if(x < 0 || x >= 256)
-			return -1;
-		if(*p != '.' && *p != 0)
-			return -1;
-		if(*p == '.')
-			p++;
-		addr[i] = x;
-	}
-
-	switch(CLASS(addr)){
-	case 0:
-	case 1:
-		if(i == 3){
-			addr[3] = addr[2];
-			addr[2] = addr[1];
-			addr[1] = 0;
-		}else if(i == 2){
-			addr[3] = addr[1];
-			addr[2] = 0;
-			addr[1] = 0;
-		}else if(i != 4)
-			return -1;
+	switch(ss->ss_family){
+	case AF_INET:
+		((struct sockaddr_in*)ss)->sin_port = htons(port);
 		break;
-	case 2:
-		if(i == 3){
-			addr[3] = addr[2];
-			addr[2] = 0;
-		}else if(i != 4)
-			return -1;
+	case AF_INET6:
+		((struct sockaddr_in6*)ss)->sin6_port = htons(port);
 		break;
+	default:
+		errstr("unknown protocol family %d", ss->ss_family);
+		return -1;
 	}
-	memmove(pip, addr, 4);
 	return 0;
 }
 
 int
-p9dialparse(char *addr, char **pnet, char **punix, u32int *phost, int *pport)
+p9dialparse(char *addr, char **pnet, char **punix, void *phost, int *pport)
 {
 	char *net, *host, *port, *e;
 	int i;
 	struct servent *se;
 	struct hostent *he;
-	struct sockaddr_un *sockun;
+	struct sockaddr_storage *ss;
+	struct addrinfo *result;
 
+	ss = phost;
+
+	memset(ss, 0, sizeof(ss));
+
 	*punix = nil;
 	net = addr;
 	if((host = strchr(net, '!')) == nil){
@@ -94,13 +71,14 @@ p9dialparse(char *addr, char **pnet, char **punix, u32
 	if((port = strchr(host, '!')) == nil){
 		if(strcmp(net, "unix")==0 || strcmp(net, "net")==0){
 		Unix:
-			if(strlen(host)+1 > sizeof sockun->sun_path){
+			if(strlen(host)+1 > sizeof ((struct sockaddr_un*)&ss)->sun_path){
 				werrstr("unix socket name too long");
 				return -1;
 			}
 			*punix = host;
 			*pnet = "unix";
-			*phost = 0;
+			ss->ss_family = AF_UNIX;
+			strcpy(((struct sockaddr_un*)ss)->sun_path, host);
 			*pport = 0;
 			return 0;
 		}
@@ -127,13 +105,36 @@ p9dialparse(char *addr, char **pnet, char **punix, u32
 	}
 
 	/* translate host */
-	if(strcmp(host, "*") == 0)
-		*phost = 0;
-	else if(parseip(host, phost) == 0)
-		{}
-	else if((he = gethostbyname(host)) != nil)
-		*phost = *(u32int*)(he->h_addr);
-	else{
+	if(strcmp(host, "*") == 0){
+		ss->ss_family = AF_INET6;
+		((struct sockaddr_in6*)ss)->sin6_addr = in6addr_any;
+	}else if((he = gethostbyname(host)) != nil){
+		ss->ss_family = he->h_addrtype;
+		switch(ss->ss_family){
+		case AF_INET:
+			((struct sockaddr_in*)ss)->sin_addr = *(struct in_addr*) *(he->h_addr_list);
+			break;
+		case AF_INET6:
+			((struct sockaddr_in6*)ss)->sin6_addr = *(struct in6_addr*) *(he->h_addr_list);
+			break;
+		default:
+			errstr("unknown protocol family %d", ss->ss_family);
+			return -1;
+		}
+	}else if(getaddrinfo(host, NULL, NULL, &result) == 0) {
+		ss->ss_family = result->ai_family;
+		switch (ss->ss_family) {
+		case AF_INET:
+			memcpy((struct sockaddr_in*)ss, result->ai_addr, result->ai_addrlen);
+			break;
+		case AF_INET6:
+			memcpy((struct sockaddr_in6*)ss, result->ai_addr, result->ai_addrlen);
+			break;
+		default:
+			errstr("unknown protocol family %d", ss->ss_family);
+			return -1;
+		}
+	}else{
 		werrstr("unknown host %s", host);
 		return -1;
 	}
@@ -144,7 +145,7 @@ p9dialparse(char *addr, char **pnet, char **punix, u32
 			if((se = getservbyname(port, nets[i])) != nil){
 				*pnet = nets[i];
 				*pport = ntohs(se->s_port);
-				return 0;
+				return setport(ss, *pport);
 			}
 		}
 	}
@@ -154,7 +155,7 @@ p9dialparse(char *addr, char **pnet, char **punix, u32
 		if(strcmp(porttbl[i].service, port) == 0){
 			*pnet = porttbl[i].net;
 			*pport = porttbl[i].port;
-			return 0;
+			return setport(ss, *pport);
 		}
 	}
 
@@ -172,12 +173,12 @@ p9dialparse(char *addr, char **pnet, char **punix, u32
 	i = strtol(port, &e, 0);
 	if(*e == 0){
 		*pport = i;
-		return 0;
+		return setport(ss, *pport);
 	}
 
 	if((se = getservbyname(port, net)) != nil){
 		*pport = ntohs(se->s_port);
-		return 0;
+		return setport(ss, *pport);
 	}
 	werrstr("unknown service %s!*!%s", net, port);
 	return -1;
blob - ecdd897a4a951c62d9e17f976590c5fd7e2557c0
blob + 6e5357c5dbea5ed36e413d360320f6e07fd5d1e2
--- src/lib9/announce.c
+++ src/lib9/announce.c
@@ -39,18 +39,16 @@ p9announce(char *addr, char *dir)
 	int proto;
 	char *buf, *unix;
 	char *net;
-	u32int host;
 	int port, s;
 	int n;
 	socklen_t sn;
-	struct sockaddr_in sa;
-	struct sockaddr_un sun;
+	struct sockaddr_storage ss;
 
 	buf = strdup(addr);
 	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;
 	}
@@ -67,11 +65,7 @@ p9announce(char *addr, char *dir)
 	}
 	free(buf);
 
-	memset(&sa, 0, sizeof sa);
-	memmove(&sa.sin_addr, &host, 4);
-	sa.sin_family = AF_INET;
-	sa.sin_port = htons(port);
-	if((s = socket(AF_INET, proto, 0)) < 0)
+	if((s = socket(ss.ss_family, proto, 0)) < 0)
 		return -1;
 	sn = sizeof n;
 	if(port && getsockopt(s, SOL_SOCKET, SO_TYPE, (void*)&n, &sn) >= 0
@@ -79,7 +73,7 @@ p9announce(char *addr, char *dir)
 		n = 1;
 		setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char*)&n, sizeof n);
 	}
-	if(bind(s, (struct sockaddr*)&sa, sizeof sa) < 0){
+	if(bind(s, (struct sockaddr*)&ss, sizeof ss) < 0){
 		close(s);
 		return -1;
 	}
@@ -90,22 +84,18 @@ p9announce(char *addr, char *dir)
 	return s;
 
 Unix:
-	memset(&sun, 0, sizeof sun);
-	sun.sun_family = AF_UNIX;
-	strcpy(sun.sun_path, unix);
-	if((s = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
+	if((s = socket(ss.ss_family, SOCK_STREAM, 0)) < 0)
 		return -1;
-	sn = sizeof sun;
-	if(bind(s, (struct sockaddr*)&sun, sizeof sun) < 0){
+	if(bind(s, (struct sockaddr*)&ss, sizeof (struct sockaddr_un)) < 0){
 		if(errno == EADDRINUSE
-		&& connect(s, (struct sockaddr*)&sun, sizeof sun) < 0
+		&& connect(s, (struct sockaddr*)&ss, sizeof (struct sockaddr_un)) < 0
 		&& errno == ECONNREFUSED){
 			/* dead socket, so remove it */
 			remove(unix);
 			close(s);
-			if((s = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
+			if((s = socket(ss.ss_family, SOCK_STREAM, 0)) < 0)
 				return -1;
-			if(bind(s, (struct sockaddr*)&sun, sizeof sun) >= 0)
+			if(bind(s, (struct sockaddr*)&ss, sizeof (struct sockaddr_un)) >= 0)
 				goto Success;
 		}
 		close(s);
blob - 7c7f74808cf137e6dd69f564fcd1572ab1f98aa0
blob + 730b60e3500e2ef3bab341adeacb444126974304
--- src/lib9/dial.c
+++ 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 *dum
 	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 *dum
 	}
 	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 *dum
 			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 *dum
 			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;
 	}