xref: /plan9/sys/src/ape/lib/net/dial.c (revision 9a747e4fd48b9f4522c70c07e8f882a15030f964)
1 #include <stdlib.h>
2 #include <sys/types.h>
3 #include <string.h>
4 #include <fcntl.h>
5 #include <stdio.h>
6 #include <unistd.h>
7 #include <libnet.h>
8 
9 #define NAMELEN 28
10 
11 static int
call(char * clone,char * dest,int * cfdp,char * dir,char * local)12 call(char *clone, char *dest, int *cfdp, char *dir, char *local)
13 {
14 	int fd, cfd;
15 	int n;
16 	char name[3*NAMELEN+5];
17 	char data[3*NAMELEN+10];
18 	char *p;
19 
20 	cfd = open(clone, O_RDWR);
21 	if(cfd < 0)
22 		return -1;
23 
24 	/* get directory name */
25 	n = read(cfd, name, sizeof(name)-1);
26 	if(n < 0){
27 		close(cfd);
28 		return -1;
29 	}
30 	name[n] = 0;
31 	p = strrchr(clone, '/');
32 	*p = 0;
33 	if(dir)
34 		sprintf(dir, "%.*s/%.*s", 2*NAMELEN+1, clone, NAMELEN, name);
35 	sprintf(data, "%.*s/%.*s/data", 2*NAMELEN+1, clone, NAMELEN, name);
36 
37 	/* set local side (port number, for example) if we need to */
38 	if(local)
39 		sprintf(name, "connect %.*s %.*s", 2*NAMELEN, dest, NAMELEN, local);
40 	else
41 		sprintf(name, "connect %.*s", 2*NAMELEN, dest);
42 
43 	/* connect */
44 	if(write(cfd, name, strlen(name)) < 0){
45 		close(cfd);
46 		return -1;
47 	}
48 
49 	/* open data connection */
50 	fd = open(data, O_RDWR);
51 	if(fd < 0){
52 		close(cfd);
53 		return -1;
54 	}
55 	if(cfdp)
56 		*cfdp = cfd;
57 	else
58 		close(cfd);
59 	return fd;
60 }
61 
62 int
dial(char * dest,char * local,char * dir,int * cfdp)63 dial(char *dest, char *local, char *dir, int *cfdp)
64 {
65 	char net[128];
66 	char netdir[128], csname[NETPATHLEN], *slp;
67 	char clone[NAMELEN+12];
68 	char *p;
69 	int n;
70 	int fd;
71 	int rv;
72 
73 	/* go for a standard form net!... */
74 	p = strchr(dest, '!');
75 	if(p == 0){
76 		sprintf(net, "net!%.*s", sizeof(net)-5, dest);
77 	} else {
78 		strncpy(net, dest, sizeof(net)-1);
79 		net[sizeof(net)-1] = 0;
80 	}
81 
82 	slp = strrchr(net, '/');
83 	if (slp != 0) {
84 		*slp++ = '\0';
85 		strcpy(netdir, net);
86 		memmove(net, slp, strlen(slp)+1);
87 	} else
88 		strcpy(netdir, "/net");
89 
90 
91 	/* call the connection server */
92 	sprintf(csname, "%s/cs", netdir);
93 	fd = open(csname, O_RDWR);
94 	if(fd < 0){
95 		/* no connection server, don't translate */
96 		p = strchr(net, '!');
97 		*p++ = 0;
98 		sprintf(clone, "%s/%s/clone", netdir, net);
99 		return call(clone, p, cfdp, dir, local);
100 	}
101 
102 	/*
103 	 *  send dest to connection to translate
104 	 */
105 	if(write(fd, net, strlen(net)) < 0){
106 		close(fd);
107 		return -1;
108 	}
109 
110 	/*
111 	 *  loop through each address from the connection server till
112 	 *  we get one that works.
113 	 */
114 	rv = -1;
115 	lseek(fd, 0, 0);
116 	while((n = read(fd, net, sizeof(net) - 1)) > 0){
117 		net[n] = 0;
118 		p = strchr(net, ' ');
119 		if(p == 0)
120 			continue;
121 		*p++ = 0;
122 		rv = call(net, p, cfdp, dir, local);
123 		if(rv >= 0)
124 			break;
125 	}
126 	close(fd);
127 	return rv;
128 }
129