1 #include <u.h> 2 #include <libc.h> 3 4 typedef struct DS DS; 5 6 static int call(char*, char*, DS*); 7 static int csdial(DS*); 8 static void _dial_string_parse(char*, DS*); 9 10 enum 11 { 12 Maxstring = 128, 13 Maxpath = 256, 14 }; 15 16 struct DS { 17 /* dist string */ 18 char buf[Maxstring]; 19 char *netdir; 20 char *proto; 21 char *rem; 22 23 /* other args */ 24 char *local; 25 char *dir; 26 int *cfdp; 27 }; 28 29 30 /* 31 * the dialstring is of the form '[/net/]proto!dest' 32 */ 33 int 34 dial(char *dest, char *local, char *dir, int *cfdp) 35 { 36 DS ds; 37 int rv; 38 char err[ERRMAX], alterr[ERRMAX]; 39 40 ds.local = local; 41 ds.dir = dir; 42 ds.cfdp = cfdp; 43 44 _dial_string_parse(dest, &ds); 45 if(ds.netdir) 46 return csdial(&ds); 47 48 ds.netdir = "/net"; 49 rv = csdial(&ds); 50 if(rv >= 0) 51 return rv; 52 err[0] = '\0'; 53 errstr(err, sizeof err); 54 if(strstr(err, "refused") != 0){ 55 werrstr("%s", err); 56 return rv; 57 } 58 ds.netdir = "/net.alt"; 59 rv = csdial(&ds); 60 if(rv >= 0) 61 return rv; 62 63 alterr[0] = 0; 64 errstr(alterr, sizeof alterr); 65 if(strstr(alterr, "translate") || strstr(alterr, "does not exist")) 66 werrstr("%s", err); 67 else 68 werrstr("%s", alterr); 69 return rv; 70 } 71 72 static int 73 csdial(DS *ds) 74 { 75 int n, fd, rv; 76 char *p, buf[Maxstring], clone[Maxpath], err[ERRMAX], besterr[ERRMAX]; 77 78 /* 79 * open connection server 80 */ 81 snprint(buf, sizeof(buf), "%s/cs", ds->netdir); 82 fd = open(buf, ORDWR); 83 if(fd < 0){ 84 /* no connection server, don't translate */ 85 snprint(clone, sizeof(clone), "%s/%s/clone", ds->netdir, ds->proto); 86 return call(clone, ds->rem, ds); 87 } 88 89 /* 90 * ask connection server to translate 91 */ 92 snprint(buf, sizeof(buf), "%s!%s", ds->proto, ds->rem); 93 if(write(fd, buf, strlen(buf)) < 0){ 94 close(fd); 95 return -1; 96 } 97 98 /* 99 * loop through each address from the connection server till 100 * we get one that works. 101 */ 102 *besterr = 0; 103 rv = -1; 104 seek(fd, 0, 0); 105 strcpy(err, "cs gave empty translation list"); 106 while((n = read(fd, buf, sizeof(buf) - 1)) > 0){ 107 buf[n] = 0; 108 p = strchr(buf, ' '); 109 if(p == 0) 110 continue; 111 *p++ = 0; 112 rv = call(buf, p, ds); 113 if(rv >= 0) 114 break; 115 err[0] = '\0'; 116 errstr(err, sizeof err); 117 if(strstr(err, "does not exist") == 0) 118 strcpy(besterr, err); 119 } 120 close(fd); 121 122 if(rv < 0 && *besterr) 123 werrstr("%s", besterr); 124 else 125 werrstr("%s", err); 126 return rv; 127 } 128 129 static int 130 call(char *clone, char *dest, DS *ds) 131 { 132 int fd, cfd, n; 133 char name[Maxpath], data[Maxpath], *p; 134 135 cfd = open(clone, ORDWR); 136 if(cfd < 0) 137 return -1; 138 139 /* get directory name */ 140 n = read(cfd, name, sizeof(name)-1); 141 if(n < 0){ 142 close(cfd); 143 return -1; 144 } 145 name[n] = 0; 146 for(p = name; *p == ' '; p++) 147 ; 148 snprint(name, sizeof(name), "%ld", strtoul(p, 0, 0)); 149 p = strrchr(clone, '/'); 150 *p = 0; 151 if(ds->dir) 152 snprint(ds->dir, NETPATHLEN, "%s/%s", clone, name); 153 snprint(data, sizeof(data), "%s/%s/data", clone, name); 154 155 /* connect */ 156 if(ds->local) 157 snprint(name, sizeof(name), "connect %s %s", dest, ds->local); 158 else 159 snprint(name, sizeof(name), "connect %s", dest); 160 if(write(cfd, name, strlen(name)) < 0){ 161 close(cfd); 162 return -1; 163 } 164 165 /* open data connection */ 166 fd = open(data, ORDWR); 167 if(fd < 0){ 168 print("open %s: %r\n", data); 169 close(cfd); 170 return -1; 171 } 172 if(ds->cfdp) 173 *ds->cfdp = cfd; 174 else 175 close(cfd); 176 return fd; 177 } 178 179 /* 180 * parse a dial string 181 */ 182 static void 183 _dial_string_parse(char *str, DS *ds) 184 { 185 char *p, *p2; 186 187 strncpy(ds->buf, str, Maxstring); 188 ds->buf[Maxstring-1] = 0; 189 190 p = strchr(ds->buf, '!'); 191 if(p == 0) { 192 ds->netdir = 0; 193 ds->proto = "net"; 194 ds->rem = ds->buf; 195 } else { 196 if(*ds->buf != '/' && *ds->buf != '#'){ 197 ds->netdir = 0; 198 ds->proto = ds->buf; 199 } else { 200 for(p2 = p; *p2 != '/'; p2--) 201 ; 202 *p2++ = 0; 203 ds->netdir = ds->buf; 204 ds->proto = p2; 205 } 206 *p = 0; 207 ds->rem = p + 1; 208 } 209 } 210