aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/libc.h2
-rw-r--r--src/cmd/vbackup/vmount.c19
-rw-r--r--src/cmd/vbackup/vmount0.c19
-rw-r--r--src/lib9/_p9dialparse.c105
-rw-r--r--src/lib9/announce.c28
-rw-r--r--src/lib9/dial.c53
6 files changed, 107 insertions, 119 deletions
diff --git a/include/libc.h b/include/libc.h
index d16b4043..45b22b69 100644
--- a/include/libc.h
+++ b/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*);
diff --git a/src/cmd/vbackup/vmount.c b/src/cmd/vbackup/vmount.c
index bdb283fb..dda0949f 100644
--- a/src/cmd/vbackup/vmount.c
+++ b/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);
}
diff --git a/src/cmd/vbackup/vmount0.c b/src/cmd/vbackup/vmount0.c
index 93340c11..064e057b 100644
--- a/src/cmd/vbackup/vmount0.c
+++ b/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);
}
diff --git a/src/lib9/_p9dialparse.c b/src/lib9/_p9dialparse.c
index 0c84ecdb..d8e91003 100644
--- a/src/lib9/_p9dialparse.c
+++ b/src/lib9/_p9dialparse.c
@@ -31,58 +31,35 @@ 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;
@@ -94,13 +71,14 @@ p9dialparse(char *addr, char **pnet, char **punix, u32int *phost, int *pport)
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, u32int *phost, int *pport)
}
/* 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, u32int *phost, int *pport)
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, u32int *phost, int *pport)
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, u32int *phost, int *pport)
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;
diff --git a/src/lib9/announce.c b/src/lib9/announce.c
index ecdd897a..6e5357c5 100644
--- a/src/lib9/announce.c
+++ b/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);
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;
}