17dd7cddfSDavid du Colombier #include <u.h>
27dd7cddfSDavid du Colombier #include <libc.h>
37dd7cddfSDavid du Colombier #include <ctype.h>
47dd7cddfSDavid du Colombier
57dd7cddfSDavid du Colombier static int nettrans(char*, char*, int na, char*, int);
67dd7cddfSDavid du Colombier
77dd7cddfSDavid du Colombier enum
87dd7cddfSDavid du Colombier {
97dd7cddfSDavid du Colombier Maxpath= 256,
107dd7cddfSDavid du Colombier };
117dd7cddfSDavid du Colombier
127dd7cddfSDavid du Colombier /*
137dd7cddfSDavid du Colombier * announce a network service.
147dd7cddfSDavid du Colombier */
157dd7cddfSDavid du Colombier int
announce(char * addr,char * dir)167dd7cddfSDavid du Colombier announce(char *addr, char *dir)
177dd7cddfSDavid du Colombier {
187dd7cddfSDavid du Colombier int ctl, n, m;
197dd7cddfSDavid du Colombier char buf[Maxpath];
207dd7cddfSDavid du Colombier char buf2[Maxpath];
217dd7cddfSDavid du Colombier char netdir[Maxpath];
227dd7cddfSDavid du Colombier char naddr[Maxpath];
237dd7cddfSDavid du Colombier char *cp;
247dd7cddfSDavid du Colombier
257dd7cddfSDavid du Colombier /*
267dd7cddfSDavid du Colombier * translate the address
277dd7cddfSDavid du Colombier */
287dd7cddfSDavid du Colombier if(nettrans(addr, naddr, sizeof(naddr), netdir, sizeof(netdir)) < 0)
297dd7cddfSDavid du Colombier return -1;
307dd7cddfSDavid du Colombier
317dd7cddfSDavid du Colombier /*
327dd7cddfSDavid du Colombier * get a control channel
337dd7cddfSDavid du Colombier */
347dd7cddfSDavid du Colombier ctl = open(netdir, ORDWR);
357dd7cddfSDavid du Colombier if(ctl<0){
367dd7cddfSDavid du Colombier werrstr("announce opening %s: %r", netdir);
377dd7cddfSDavid du Colombier return -1;
387dd7cddfSDavid du Colombier }
397dd7cddfSDavid du Colombier cp = strrchr(netdir, '/');
407dd7cddfSDavid du Colombier if(cp == nil){
417dd7cddfSDavid du Colombier werrstr("announce arg format %s", netdir);
427dd7cddfSDavid du Colombier close(ctl);
437dd7cddfSDavid du Colombier return -1;
447dd7cddfSDavid du Colombier }
457dd7cddfSDavid du Colombier *cp = 0;
467dd7cddfSDavid du Colombier
477dd7cddfSDavid du Colombier /*
487dd7cddfSDavid du Colombier * find out which line we have
497dd7cddfSDavid du Colombier */
507dd7cddfSDavid du Colombier n = snprint(buf, sizeof(buf), "%s/", netdir);
517dd7cddfSDavid du Colombier m = read(ctl, &buf[n], sizeof(buf)-n-1);
527dd7cddfSDavid du Colombier if(m <= 0){
537dd7cddfSDavid du Colombier werrstr("announce reading %s: %r", netdir);
547dd7cddfSDavid du Colombier close(ctl);
557dd7cddfSDavid du Colombier return -1;
567dd7cddfSDavid du Colombier }
577dd7cddfSDavid du Colombier buf[n+m] = 0;
587dd7cddfSDavid du Colombier
597dd7cddfSDavid du Colombier /*
607dd7cddfSDavid du Colombier * make the call
617dd7cddfSDavid du Colombier */
627dd7cddfSDavid du Colombier n = snprint(buf2, sizeof(buf2), "announce %s", naddr);
637dd7cddfSDavid du Colombier if(write(ctl, buf2, n)!=n){
647dd7cddfSDavid du Colombier werrstr("announce writing %s: %r", netdir);
657dd7cddfSDavid du Colombier close(ctl);
667dd7cddfSDavid du Colombier return -1;
677dd7cddfSDavid du Colombier }
687dd7cddfSDavid du Colombier
697dd7cddfSDavid du Colombier /*
707dd7cddfSDavid du Colombier * return directory etc.
717dd7cddfSDavid du Colombier */
727dd7cddfSDavid du Colombier if(dir){
737dd7cddfSDavid du Colombier strncpy(dir, buf, NETPATHLEN);
747dd7cddfSDavid du Colombier dir[NETPATHLEN-1] = 0;
757dd7cddfSDavid du Colombier }
767dd7cddfSDavid du Colombier return ctl;
777dd7cddfSDavid du Colombier }
787dd7cddfSDavid du Colombier
797dd7cddfSDavid du Colombier /*
807dd7cddfSDavid du Colombier * listen for an incoming call
817dd7cddfSDavid du Colombier */
827dd7cddfSDavid du Colombier int
listen(char * dir,char * newdir)837dd7cddfSDavid du Colombier listen(char *dir, char *newdir)
847dd7cddfSDavid du Colombier {
857dd7cddfSDavid du Colombier int ctl, n, m;
867dd7cddfSDavid du Colombier char buf[Maxpath];
877dd7cddfSDavid du Colombier char *cp;
887dd7cddfSDavid du Colombier
897dd7cddfSDavid du Colombier /*
907dd7cddfSDavid du Colombier * open listen, wait for a call
917dd7cddfSDavid du Colombier */
927dd7cddfSDavid du Colombier snprint(buf, sizeof(buf), "%s/listen", dir);
937dd7cddfSDavid du Colombier ctl = open(buf, ORDWR);
947dd7cddfSDavid du Colombier if(ctl < 0){
957dd7cddfSDavid du Colombier werrstr("listen opening %s: %r", buf);
967dd7cddfSDavid du Colombier return -1;
977dd7cddfSDavid du Colombier }
987dd7cddfSDavid du Colombier
997dd7cddfSDavid du Colombier /*
1007dd7cddfSDavid du Colombier * find out which line we have
1017dd7cddfSDavid du Colombier */
1027dd7cddfSDavid du Colombier strncpy(buf, dir, sizeof(buf) - 1);
1037dd7cddfSDavid du Colombier buf[sizeof(buf) - 1] = 0;
1047dd7cddfSDavid du Colombier cp = strrchr(buf, '/');
1057dd7cddfSDavid du Colombier if(cp == nil){
1067dd7cddfSDavid du Colombier close(ctl);
1077dd7cddfSDavid du Colombier werrstr("listen arg format %s", dir);
1087dd7cddfSDavid du Colombier return -1;
1097dd7cddfSDavid du Colombier }
1107dd7cddfSDavid du Colombier *++cp = 0;
1117dd7cddfSDavid du Colombier n = cp-buf;
1127dd7cddfSDavid du Colombier m = read(ctl, cp, sizeof(buf) - n - 1);
1137dd7cddfSDavid du Colombier if(m <= 0){
1147dd7cddfSDavid du Colombier close(ctl);
1157dd7cddfSDavid du Colombier werrstr("listen reading %s/listen: %r", dir);
1167dd7cddfSDavid du Colombier return -1;
1177dd7cddfSDavid du Colombier }
1187dd7cddfSDavid du Colombier buf[n+m] = 0;
1197dd7cddfSDavid du Colombier
1207dd7cddfSDavid du Colombier /*
1217dd7cddfSDavid du Colombier * return directory etc.
1227dd7cddfSDavid du Colombier */
1237dd7cddfSDavid du Colombier if(newdir){
1247dd7cddfSDavid du Colombier strncpy(newdir, buf, NETPATHLEN);
1257dd7cddfSDavid du Colombier newdir[NETPATHLEN-1] = 0;
1267dd7cddfSDavid du Colombier }
1277dd7cddfSDavid du Colombier return ctl;
1287dd7cddfSDavid du Colombier
1297dd7cddfSDavid du Colombier }
1307dd7cddfSDavid du Colombier
1317dd7cddfSDavid du Colombier /*
1327dd7cddfSDavid du Colombier * accept a call, return an fd to the open data file
1337dd7cddfSDavid du Colombier */
1347dd7cddfSDavid du Colombier int
accept(int ctl,char * dir)1357dd7cddfSDavid du Colombier accept(int ctl, char *dir)
1367dd7cddfSDavid du Colombier {
1377dd7cddfSDavid du Colombier char buf[Maxpath];
1387dd7cddfSDavid du Colombier char *num;
1397dd7cddfSDavid du Colombier long n;
1407dd7cddfSDavid du Colombier
1417dd7cddfSDavid du Colombier num = strrchr(dir, '/');
1427dd7cddfSDavid du Colombier if(num == nil)
1437dd7cddfSDavid du Colombier num = dir;
1447dd7cddfSDavid du Colombier else
1457dd7cddfSDavid du Colombier num++;
1467dd7cddfSDavid du Colombier
1477dd7cddfSDavid du Colombier n = snprint(buf, sizeof(buf), "accept %s", num);
1487dd7cddfSDavid du Colombier write(ctl, buf, n); /* ignore return value, network might not need accepts */
1497dd7cddfSDavid du Colombier
1507dd7cddfSDavid du Colombier snprint(buf, sizeof(buf), "%s/data", dir);
1517dd7cddfSDavid du Colombier return open(buf, ORDWR);
1527dd7cddfSDavid du Colombier }
1537dd7cddfSDavid du Colombier
1547dd7cddfSDavid du Colombier /*
1557dd7cddfSDavid du Colombier * reject a call, tell device the reason for the rejection
1567dd7cddfSDavid du Colombier */
1577dd7cddfSDavid du Colombier int
reject(int ctl,char * dir,char * cause)1587dd7cddfSDavid du Colombier reject(int ctl, char *dir, char *cause)
1597dd7cddfSDavid du Colombier {
1607dd7cddfSDavid du Colombier char buf[Maxpath];
1617dd7cddfSDavid du Colombier char *num;
1627dd7cddfSDavid du Colombier long n;
1637dd7cddfSDavid du Colombier
1647dd7cddfSDavid du Colombier num = strrchr(dir, '/');
1657dd7cddfSDavid du Colombier if(num == 0)
1667dd7cddfSDavid du Colombier num = dir;
1677dd7cddfSDavid du Colombier else
1687dd7cddfSDavid du Colombier num++;
1697dd7cddfSDavid du Colombier snprint(buf, sizeof(buf), "reject %s %s", num, cause);
1707dd7cddfSDavid du Colombier n = strlen(buf);
1717dd7cddfSDavid du Colombier if(write(ctl, buf, n) != n)
1727dd7cddfSDavid du Colombier return -1;
1737dd7cddfSDavid du Colombier return 0;
1747dd7cddfSDavid du Colombier }
1757dd7cddfSDavid du Colombier
1767dd7cddfSDavid du Colombier /*
1777dd7cddfSDavid du Colombier * perform the identity translation (in case we can't reach cs)
1787dd7cddfSDavid du Colombier */
1797dd7cddfSDavid du Colombier static int
identtrans(char * netdir,char * addr,char * naddr,int na,char * file,int nf)1807dd7cddfSDavid du Colombier identtrans(char *netdir, char *addr, char *naddr, int na, char *file, int nf)
1817dd7cddfSDavid du Colombier {
1827dd7cddfSDavid du Colombier char proto[Maxpath];
1837dd7cddfSDavid du Colombier char *p;
1847dd7cddfSDavid du Colombier
1857dd7cddfSDavid du Colombier USED(nf);
1867dd7cddfSDavid du Colombier
1877dd7cddfSDavid du Colombier /* parse the protocol */
1887dd7cddfSDavid du Colombier strncpy(proto, addr, sizeof(proto));
1897dd7cddfSDavid du Colombier proto[sizeof(proto)-1] = 0;
1907dd7cddfSDavid du Colombier p = strchr(proto, '!');
1917dd7cddfSDavid du Colombier if(p)
1927dd7cddfSDavid du Colombier *p++ = 0;
1937dd7cddfSDavid du Colombier
1947dd7cddfSDavid du Colombier snprint(file, nf, "%s/%s/clone", netdir, proto);
1957dd7cddfSDavid du Colombier strncpy(naddr, p, na);
1967dd7cddfSDavid du Colombier naddr[na-1] = 0;
1977dd7cddfSDavid du Colombier
1987dd7cddfSDavid du Colombier return 1;
1997dd7cddfSDavid du Colombier }
2007dd7cddfSDavid du Colombier
2017dd7cddfSDavid du Colombier /*
2027dd7cddfSDavid du Colombier * call up the connection server and get a translation
2037dd7cddfSDavid du Colombier */
2047dd7cddfSDavid du Colombier static int
nettrans(char * addr,char * naddr,int na,char * file,int nf)2057dd7cddfSDavid du Colombier nettrans(char *addr, char *naddr, int na, char *file, int nf)
2067dd7cddfSDavid du Colombier {
2077dd7cddfSDavid du Colombier int i, fd;
2087dd7cddfSDavid du Colombier char buf[Maxpath];
2097dd7cddfSDavid du Colombier char netdir[Maxpath];
2107dd7cddfSDavid du Colombier char *p, *p2;
2117dd7cddfSDavid du Colombier long n;
2127dd7cddfSDavid du Colombier
2137dd7cddfSDavid du Colombier /*
2147dd7cddfSDavid du Colombier * parse, get network directory
2157dd7cddfSDavid du Colombier */
2167dd7cddfSDavid du Colombier p = strchr(addr, '!');
2177dd7cddfSDavid du Colombier if(p == 0){
2187dd7cddfSDavid du Colombier werrstr("bad dial string: %s", addr);
2197dd7cddfSDavid du Colombier return -1;
2207dd7cddfSDavid du Colombier }
2217dd7cddfSDavid du Colombier if(*addr != '/'){
2227dd7cddfSDavid du Colombier strncpy(netdir, "/net", sizeof(netdir));
2237dd7cddfSDavid du Colombier netdir[sizeof(netdir) - 1] = 0;
2247dd7cddfSDavid du Colombier } else {
2257dd7cddfSDavid du Colombier for(p2 = p; *p2 != '/'; p2--)
2267dd7cddfSDavid du Colombier ;
2277dd7cddfSDavid du Colombier i = p2 - addr;
2287dd7cddfSDavid du Colombier if(i == 0 || i >= sizeof(netdir)){
2297dd7cddfSDavid du Colombier werrstr("bad dial string: %s", addr);
2307dd7cddfSDavid du Colombier return -1;
2317dd7cddfSDavid du Colombier }
2327dd7cddfSDavid du Colombier strncpy(netdir, addr, i);
2337dd7cddfSDavid du Colombier netdir[i] = 0;
2347dd7cddfSDavid du Colombier addr = p2 + 1;
2357dd7cddfSDavid du Colombier }
2367dd7cddfSDavid du Colombier
2377dd7cddfSDavid du Colombier /*
2387dd7cddfSDavid du Colombier * ask the connection server
2397dd7cddfSDavid du Colombier */
2407dd7cddfSDavid du Colombier snprint(buf, sizeof(buf), "%s/cs", netdir);
2417dd7cddfSDavid du Colombier fd = open(buf, ORDWR);
2427dd7cddfSDavid du Colombier if(fd < 0)
2437dd7cddfSDavid du Colombier return identtrans(netdir, addr, naddr, na, file, nf);
2447dd7cddfSDavid du Colombier if(write(fd, addr, strlen(addr)) < 0){
2457dd7cddfSDavid du Colombier close(fd);
2467dd7cddfSDavid du Colombier return -1;
2477dd7cddfSDavid du Colombier }
2487dd7cddfSDavid du Colombier seek(fd, 0, 0);
2497dd7cddfSDavid du Colombier n = read(fd, buf, sizeof(buf)-1);
2507dd7cddfSDavid du Colombier close(fd);
2517dd7cddfSDavid du Colombier if(n <= 0)
2527dd7cddfSDavid du Colombier return -1;
2537dd7cddfSDavid du Colombier buf[n] = 0;
2547dd7cddfSDavid du Colombier
2557dd7cddfSDavid du Colombier /*
2567dd7cddfSDavid du Colombier * parse the reply
2577dd7cddfSDavid du Colombier */
2587dd7cddfSDavid du Colombier p = strchr(buf, ' ');
2597dd7cddfSDavid du Colombier if(p == 0)
2607dd7cddfSDavid du Colombier return -1;
2617dd7cddfSDavid du Colombier *p++ = 0;
2627dd7cddfSDavid du Colombier strncpy(naddr, p, na);
2637dd7cddfSDavid du Colombier naddr[na-1] = 0;
264*da51d93aSDavid du Colombier
265*da51d93aSDavid du Colombier if(buf[0] == '/'){
266*da51d93aSDavid du Colombier p = strchr(buf+1, '/');
267*da51d93aSDavid du Colombier if(p == nil)
268*da51d93aSDavid du Colombier p = buf;
269*da51d93aSDavid du Colombier else
270*da51d93aSDavid du Colombier p++;
271*da51d93aSDavid du Colombier }
272*da51d93aSDavid du Colombier snprint(file, nf, "%s/%s", netdir, p);
2737dd7cddfSDavid du Colombier return 0;
2747dd7cddfSDavid du Colombier }
275