diff options
author | David du Colombier <0intro@gmail.com> | 2012-06-02 21:50:59 +0200 |
---|---|---|
committer | David du Colombier <0intro@gmail.com> | 2012-06-02 21:50:59 +0200 |
commit | 3409bc9ae1614ba47430a3f593fdbe5fc177c878 (patch) | |
tree | fbc0743e04e514a8fd5f46f532b4e0b54153e711 /src/lib9/announce.c | |
parent | 5d03af6557cc215cabc0f83a274d9add703f526e (diff) | |
download | plan9port-3409bc9ae1614ba47430a3f593fdbe5fc177c878.tar.gz plan9port-3409bc9ae1614ba47430a3f593fdbe5fc177c878.tar.bz2 plan9port-3409bc9ae1614ba47430a3f593fdbe5fc177c878.zip |
lib9/dial: add support for IPv6
The function p9dialparse() returns the host as a sockaddr_storage
structure instead of a u32int, to be able to handle both IPv4
and IPv6 addresses. Because the sockaddr_storage structure also
handle port numbers and Unix path names, there is no longer
need to set them in the calling functions. However, these values
are still returned for convenience.
The sockaddr_in and sockaddr_un structures have been replaced
by sockaddr_storage to handle Unix, IPv4 and IPv6 sockets.
Names and addresses are resolved using either gethostbyname()
or getaddrinfo() functions.
The getaddrinfo() function is documented in RFC2553 and standardized
since POSIX.1-2001. It supports both IPv4 and IPv6 addresses.
The gethostbyname() function is deprecated since POSIX.1-2008.
However, some libc implementations don't handle getaddrinfo()
properly, thus we preferred to try gethostbyname() first.
I've tried to preserve most of the old code logic to prevent
from surprising or unwanted behavior.
R=rsc
http://codereview.appspot.com/6255068
Diffstat (limited to 'src/lib9/announce.c')
-rw-r--r-- | src/lib9/announce.c | 28 |
1 files changed, 9 insertions, 19 deletions
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); |