plan9port/src/lib9/dial.c

97 lines
1.7 KiB
C
Raw Normal View History

2003-11-23 18:12:54 +00:00
#include <u.h>
#include <libc.h>
#undef accept
#undef announce
#undef dial
#undef setnetmtpt
#undef hangup
#undef listen
#undef netmkaddr
#undef reject
#include <sys/socket.h>
#include <netinet/in.h>
2004-02-09 19:33:05 +00:00
#include <netinet/tcp.h>
2003-11-23 18:12:54 +00:00
#include <sys/un.h>
#include <netdb.h>
extern int _p9dialparse(char*, char**, char**, u32int*, int*);
#undef unix
int
p9dial(char *addr, char *dummy1, char *dummy2, int *dummy3)
{
char *buf;
char *net, *unix;
u32int host;
int port;
int proto;
struct sockaddr_in sa;
struct sockaddr_un su;
int s;
if(dummy1 || dummy2 || dummy3){
werrstr("cannot handle extra arguments in dial");
return -1;
}
buf = strdup(addr);
if(buf == nil)
return -1;
if(_p9dialparse(buf, &net, &unix, &host, &port) < 0){
free(buf);
return -1;
}
if(strcmp(net, "tcp") == 0)
proto = SOCK_STREAM;
else if(strcmp(net, "udp") == 0)
proto = SOCK_DGRAM;
else if(strcmp(net, "unix") == 0)
goto Unix;
else{
werrstr("can only handle tcp, udp, and unix: not %s", net);
free(buf);
return -1;
}
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)
return -1;
if(connect(s, (struct sockaddr*)&sa, sizeof sa) < 0){
close(s);
return -1;
}
2004-02-09 19:33:05 +00:00
if(proto == SOCK_STREAM){
int one = 1;
setsockopt(s, IPPROTO_TCP, TCP_NODELAY, (char*)&one, sizeof one);
}
2003-11-23 18:12:54 +00:00
return s;
Unix:
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)
return -1;
if(connect(s, (struct sockaddr*)&su, sizeof su) < 0){
close(s);
return -1;
}
return s;
}