aboutsummaryrefslogtreecommitdiff
path: root/src/lib9
diff options
context:
space:
mode:
authorrsc <devnull@localhost>2005-02-13 18:33:26 +0000
committerrsc <devnull@localhost>2005-02-13 18:33:26 +0000
commite5d68728eb1fb4526b67358e7e55698eea4ed315 (patch)
treeabfc08f717f4894528492f09fa4ba23154db9b14 /src/lib9
parentfb7a39bc56092ecd2a52d8b6fc403eda6b905ba1 (diff)
downloadplan9port-e5d68728eb1fb4526b67358e7e55698eea4ed315.tar.gz
plan9port-e5d68728eb1fb4526b67358e7e55698eea4ed315.tar.bz2
plan9port-e5d68728eb1fb4526b67358e7e55698eea4ed315.zip
add local address to dial
Diffstat (limited to 'src/lib9')
-rw-r--r--src/lib9/dial.c45
1 files changed, 42 insertions, 3 deletions
diff --git a/src/lib9/dial.c b/src/lib9/dial.c
index 732cbb69..5b4ece07 100644
--- a/src/lib9/dial.c
+++ b/src/lib9/dial.c
@@ -19,18 +19,20 @@
#undef unix
int
-p9dial(char *addr, char *dummy1, char *dummy2, int *dummy3)
+p9dial(char *addr, char *local, char *dummy2, int *dummy3)
{
char *buf;
char *net, *unix;
u32int host;
int port;
int proto;
- struct sockaddr_in sa;
+ socklen_t sn;
+ int n;
+ struct sockaddr_in sa, sal;
struct sockaddr_un su;
int s;
- if(dummy1 || dummy2 || dummy3){
+ if(dummy2 || dummy3){
werrstr("cannot handle extra arguments in dial");
return -1;
}
@@ -63,6 +65,38 @@ p9dial(char *addr, char *dummy1, char *dummy2, int *dummy3)
sa.sin_port = htons(port);
if((s = socket(AF_INET, proto, 0)) < 0)
return -1;
+
+ if(local){
+ buf = strdup(local);
+ if(buf == nil){
+ close(s);
+ return -1;
+ }
+ if(p9dialparse(buf, &net, &unix, &host, &port) < 0){
+ badlocal:
+ free(buf);
+ close(s);
+ return -1;
+ }
+ if(unix){
+ werrstr("bad local address %s for dial %s", local, addr);
+ goto badlocal;
+ }
+ memset(&sal, 0, sizeof sal);
+ memmove(&sal.sin_addr, &local, 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)
+ goto badlocal;
+ free(buf);
+ }
+
if(connect(s, (struct sockaddr*)&sa, sizeof sa) < 0){
close(s);
return -1;
@@ -74,6 +108,11 @@ p9dial(char *addr, char *dummy1, char *dummy2, int *dummy3)
return s;
Unix:
+ if(local){
+ werrstr("local address not supported on unix network");
+ free(buf);
+ return -1;
+ }
memset(&su, 0, sizeof su);
su.sun_family = AF_UNIX;
if(strlen(unix)+1 > sizeof su.sun_path){