1 #include <stdlib.h> 2 #include <sys/types.h> 3 #include <unistd.h> 4 #include <fcntl.h> 5 #include <stdio.h> 6 #include <string.h> 7 #include <ctype.h> 8 #include <libnet.h> 9 10 #define NAMELEN 28 11 12 static int nettrans(char*, char*, int na, char*, int); 13 14 /* 15 * announce a network service. 16 */ 17 int 18 announce(char *addr, char *dir) 19 { 20 int ctl, n, m; 21 char buf[3*NAMELEN]; 22 char buf2[3*NAMELEN]; 23 char netdir[2*NAMELEN]; 24 char naddr[3*NAMELEN]; 25 char *cp; 26 27 /* 28 * translate the address 29 */ 30 if(nettrans(addr, naddr, sizeof(naddr), netdir, sizeof(netdir)) < 0) 31 return -1; 32 33 /* 34 * get a control channel 35 */ 36 ctl = open(netdir, O_RDWR); 37 if(ctl<0) 38 return -1; 39 cp = strrchr(netdir, '/'); 40 *cp = 0; 41 42 /* 43 * find out which line we have 44 */ 45 n = sprintf(buf, "%.*s/", 2*NAMELEN+1, netdir); 46 m = read(ctl, &buf[n], sizeof(buf)-n-1); 47 if(n<=0){ 48 close(ctl); 49 return -1; 50 } 51 buf[n+m] = 0; 52 53 /* 54 * make the call 55 */ 56 n = sprintf(buf2, "announce %.*s", 2*NAMELEN, naddr); 57 if(write(ctl, buf2, n)!=n){ 58 close(ctl); 59 return -1; 60 } 61 62 /* 63 * return directory etc. 64 */ 65 if(dir) 66 strcpy(dir, buf); 67 return ctl; 68 } 69 70 /* 71 * listen for an incoming call 72 */ 73 int 74 listen(char *dir, char *newdir) 75 { 76 int ctl, n, m; 77 char buf[3*NAMELEN]; 78 char *cp; 79 80 /* 81 * open listen, wait for a call 82 */ 83 sprintf(buf, "%.*s/listen", 2*NAMELEN+1, dir); 84 ctl = open(buf, O_RDWR); 85 if(ctl < 0) 86 return -1; 87 88 /* 89 * find out which line we have 90 */ 91 strcpy(buf, dir); 92 cp = strrchr(buf, '/'); 93 *++cp = 0; 94 n = cp-buf; 95 m = read(ctl, cp, sizeof(buf) - n - 1); 96 if(n<=0){ 97 close(ctl); 98 return -1; 99 } 100 buf[n+m] = 0; 101 102 /* 103 * return directory etc. 104 */ 105 if(newdir) 106 strcpy(newdir, buf); 107 return ctl; 108 109 } 110 111 /* 112 * accept a call, return an fd to the open data file 113 */ 114 int 115 accept(int ctl, char *dir) 116 { 117 char buf[128]; 118 char *num; 119 long n; 120 121 num = strrchr(dir, '/'); 122 if(num == 0) 123 num = dir; 124 else 125 num++; 126 127 sprintf(buf, "accept %s", num); 128 n = strlen(buf); 129 write(ctl, buf, n); /* ignore return value, netowrk might not need accepts */ 130 131 sprintf(buf, "%s/data", dir); 132 return open(buf, O_RDWR); 133 } 134 135 /* 136 * reject a call, tell device the reason for the rejection 137 */ 138 int 139 reject(int ctl, char *dir, char *cause) 140 { 141 char buf[128]; 142 char *num; 143 long n; 144 145 num = strrchr(dir, '/'); 146 if(num == 0) 147 num = dir; 148 else 149 num++; 150 sprintf(buf, "reject %s %s", num, cause); 151 n = strlen(buf); 152 if(write(ctl, buf, n) != n) 153 return -1; 154 return 0; 155 } 156 157 /* 158 * perform the identity translation (in case we can't reach cs) 159 */ 160 static int 161 identtrans(char *addr, char *naddr, int na, char *file, int nf) 162 { 163 char reply[4*NAMELEN]; 164 char *p; 165 166 USED(nf); 167 168 /* parse the network */ 169 strncpy(reply, addr, sizeof(reply)); 170 reply[sizeof(reply)-1] = 0; 171 p = strchr(addr, '!'); 172 if(p) 173 *p++ = 0; 174 175 sprintf(file, "/net/%.*s/clone", na - sizeof("/net//clone"), reply); 176 strncpy(naddr, p, na); 177 naddr[na-1] = 0; 178 179 return 1; 180 } 181 182 /* 183 * call up the connection server and get a translation 184 */ 185 static int 186 nettrans(char *addr, char *naddr, int na, char *file, int nf) 187 { 188 int fd; 189 char reply[4*NAMELEN]; 190 char *cp; 191 long n; 192 193 /* 194 * ask the connection server 195 */ 196 fd = open("/net/cs", O_RDWR); 197 if(fd < 0) 198 return identtrans(addr, naddr, na, file, nf); 199 if(write(fd, addr, strlen(addr)) < 0){ 200 close(fd); 201 return -1; 202 } 203 lseek(fd, 0, 0); 204 n = read(fd, reply, sizeof(reply)-1); 205 close(fd); 206 if(n <= 0) 207 return -1; 208 reply[n] = 0; 209 210 /* 211 * parse the reply 212 */ 213 cp = strchr(reply, ' '); 214 if(cp == 0) 215 return -1; 216 *cp++ = 0; 217 strncpy(naddr, cp, na); 218 naddr[na-1] = 0; 219 strncpy(file, reply, nf); 220 file[nf-1] = 0; 221 return 0; 222 } 223