13 #include <sys/socket.h>
14 #include <netinet/in.h>
15 #include <netinet/tcp.h>
23 isany(struct sockaddr_storage *ss)
25 switch(ss->ss_family){
27 return (((struct sockaddr_in*)ss)->sin_addr.s_addr == INADDR_ANY);
29 return (memcmp(((struct sockaddr_in6*)ss)->sin6_addr.s6_addr,
30 in6addr_any.s6_addr, sizeof (struct in6_addr)) == 0);
36 addrlen(struct sockaddr_storage *ss)
38 switch(ss->ss_family){
40 return sizeof(struct sockaddr_in);
42 return sizeof(struct sockaddr_in6);
44 return sizeof(struct sockaddr_un);
50 p9dial(char *addr, char *local, char *dummy2, int *dummy3)
58 struct sockaddr_storage ss, ssl;
62 werrstr("cannot handle extra arguments in dial");
70 if(p9dialparse(buf, &net, &unix, &ss, &port) < 0){
74 if(strcmp(net, "unix") != 0 && isany(&ss)){
75 werrstr("invalid dial address 0.0.0.0 (aka *)");
80 if(strcmp(net, "tcp") == 0)
82 else if(strcmp(net, "udp") == 0)
84 else if(strcmp(net, "unix") == 0)
87 werrstr("can only handle tcp, udp, and unix: not %s", net);
93 if((s = socket(ss.ss_family, proto, 0)) < 0)
102 if(p9dialparse(buf, &net, &unix, &ss, &port) < 0){
109 werrstr("bad local address %s for dial %s", local, addr);
113 if(port && getsockopt(s, SOL_SOCKET, SO_TYPE, (void*)&n, &sn) >= 0
114 && n == SOCK_STREAM){
116 setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char*)&n, sizeof n);
118 if(bind(s, (struct sockaddr*)&ssl, addrlen(&ssl)) < 0)
124 setsockopt(s, SOL_SOCKET, SO_BROADCAST, &n, sizeof n);
126 if(connect(s, (struct sockaddr*)&ss, addrlen(&ss)) < 0){
131 if(proto == SOCK_STREAM){
133 setsockopt(s, IPPROTO_TCP, TCP_NODELAY, (char*)&one, sizeof one);
139 werrstr("local address not supported on unix network");
143 /* Allow regular files in addition to Unix sockets. */
144 if((s = open(unix, ORDWR)) >= 0)
147 if((s = socket(ss.ss_family, SOCK_STREAM, 0)) < 0){
148 werrstr("socket: %r");
151 if(connect(s, (struct sockaddr*)&ss, addrlen(&ss)) < 0){
152 werrstr("connect %s: %r", ((struct sockaddr_un*)&ss)->sun_path);