aboutsummaryrefslogtreecommitdiff
path: root/src/lib9/dial.c
blob: 732cbb6916b896549eb43bfc7721f0672f722152 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
#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>
#include <netinet/tcp.h>
#include <sys/un.h>
#include <netdb.h>

#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;
	}
	if(proto == SOCK_STREAM){
		int one = 1;
		setsockopt(s, IPPROTO_TCP, TCP_NODELAY, (char*)&one, sizeof one);
	}
	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;
}