1*162f803dSDavid du Colombier /* 2*162f803dSDavid du Colombier * tftpd - tftp service, see /lib/rfc/rfc783 3*162f803dSDavid du Colombier */ 43e12c5d1SDavid du Colombier #include <u.h> 53e12c5d1SDavid du Colombier #include <libc.h> 6c0eadb1cSDavid du Colombier #include <auth.h> 73e12c5d1SDavid du Colombier #include <bio.h> 83e12c5d1SDavid du Colombier #include <ip.h> 93e12c5d1SDavid du Colombier #include <ndb.h> 103e12c5d1SDavid du Colombier 119a747e4fSDavid du Colombier enum 129a747e4fSDavid du Colombier { 139a747e4fSDavid du Colombier Maxpath= 128, 149a747e4fSDavid du Colombier Maxerr= 256, 159a747e4fSDavid du Colombier }; 169a747e4fSDavid du Colombier 173e12c5d1SDavid du Colombier int dbg; 18219b2ee8SDavid du Colombier int restricted; 193e12c5d1SDavid du Colombier void sendfile(int, char*, char*); 203e12c5d1SDavid du Colombier void recvfile(int, char*, char*); 213e12c5d1SDavid du Colombier void nak(int, int, char*); 223e12c5d1SDavid du Colombier void ack(int, ushort); 233e12c5d1SDavid du Colombier void clrcon(void); 243e12c5d1SDavid du Colombier void setuser(void); 253e12c5d1SDavid du Colombier char* sunkernel(char*); 267dd7cddfSDavid du Colombier void remoteaddr(char*, char*, int); 277dd7cddfSDavid du Colombier void doserve(int); 283e12c5d1SDavid du Colombier 297dd7cddfSDavid du Colombier char bigbuf[32768]; 307dd7cddfSDavid du Colombier char raddr[64]; 313e12c5d1SDavid du Colombier 323e12c5d1SDavid du Colombier char *dir = "/lib/tftpd"; 33219b2ee8SDavid du Colombier char *dirsl; 34219b2ee8SDavid du Colombier int dirsllen; 353e12c5d1SDavid du Colombier char flog[] = "ipboot"; 369a747e4fSDavid du Colombier char net[Maxpath]; 373e12c5d1SDavid du Colombier 383e12c5d1SDavid du Colombier enum 393e12c5d1SDavid du Colombier { 403e12c5d1SDavid du Colombier Tftp_READ = 1, 413e12c5d1SDavid du Colombier Tftp_WRITE = 2, 423e12c5d1SDavid du Colombier Tftp_DATA = 3, 433e12c5d1SDavid du Colombier Tftp_ACK = 4, 443e12c5d1SDavid du Colombier Tftp_ERROR = 5, 453e12c5d1SDavid du Colombier Segsize = 512, 463e12c5d1SDavid du Colombier }; 473e12c5d1SDavid du Colombier 483e12c5d1SDavid du Colombier void 497dd7cddfSDavid du Colombier usage(void) 507dd7cddfSDavid du Colombier { 51c0eadb1cSDavid du Colombier fprint(2, "usage: %s [-dr] [-h homedir] [-s svc] [-x netmtpt]\n", 52c0eadb1cSDavid du Colombier argv0); 537dd7cddfSDavid du Colombier exits("usage"); 547dd7cddfSDavid du Colombier } 557dd7cddfSDavid du Colombier 567dd7cddfSDavid du Colombier void 573e12c5d1SDavid du Colombier main(int argc, char **argv) 583e12c5d1SDavid du Colombier { 597dd7cddfSDavid du Colombier char buf[64]; 607dd7cddfSDavid du Colombier char adir[64], ldir[64]; 617dd7cddfSDavid du Colombier int cfd, lcfd, dfd; 62*162f803dSDavid du Colombier char *svc = "69"; 633e12c5d1SDavid du Colombier 64*162f803dSDavid du Colombier setnetmtpt(net, sizeof net, nil); 653e12c5d1SDavid du Colombier ARGBEGIN{ 663e12c5d1SDavid du Colombier case 'd': 673e12c5d1SDavid du Colombier dbg++; 683e12c5d1SDavid du Colombier break; 693e12c5d1SDavid du Colombier case 'h': 70*162f803dSDavid du Colombier dir = EARGF(usage()); 713e12c5d1SDavid du Colombier break; 72219b2ee8SDavid du Colombier case 'r': 73219b2ee8SDavid du Colombier restricted = 1; 74219b2ee8SDavid du Colombier break; 75c0eadb1cSDavid du Colombier case 's': 76c0eadb1cSDavid du Colombier svc = EARGF(usage()); 77c0eadb1cSDavid du Colombier break; 787dd7cddfSDavid du Colombier case 'x': 79*162f803dSDavid du Colombier setnetmtpt(net, sizeof net, EARGF(usage())); 807dd7cddfSDavid du Colombier break; 813e12c5d1SDavid du Colombier default: 827dd7cddfSDavid du Colombier usage(); 833e12c5d1SDavid du Colombier }ARGEND 843e12c5d1SDavid du Colombier 85219b2ee8SDavid du Colombier snprint(buf, sizeof buf, "%s/", dir); 86219b2ee8SDavid du Colombier dirsl = strdup(buf); 87219b2ee8SDavid du Colombier dirsllen = strlen(dirsl); 88219b2ee8SDavid du Colombier 899a747e4fSDavid du Colombier fmtinstall('E', eipfmt); 909a747e4fSDavid du Colombier fmtinstall('I', eipfmt); 913e12c5d1SDavid du Colombier 923e12c5d1SDavid du Colombier if(chdir(dir) < 0) 937dd7cddfSDavid du Colombier sysfatal("can't get to directory %s: %r", dir); 943e12c5d1SDavid du Colombier 957dd7cddfSDavid du Colombier if(!dbg) 963e12c5d1SDavid du Colombier switch(rfork(RFNOTEG|RFPROC|RFFDG)) { 973e12c5d1SDavid du Colombier case -1: 987dd7cddfSDavid du Colombier sysfatal("fork: %r"); 993e12c5d1SDavid du Colombier case 0: 1003e12c5d1SDavid du Colombier break; 1013e12c5d1SDavid du Colombier default: 1023e12c5d1SDavid du Colombier exits(0); 1033e12c5d1SDavid du Colombier } 1043e12c5d1SDavid du Colombier 105c0eadb1cSDavid du Colombier snprint(buf, sizeof buf, "%s/udp!*!%s", net, svc); 1067dd7cddfSDavid du Colombier cfd = announce(buf, adir); 107c0eadb1cSDavid du Colombier if (cfd < 0) 108c0eadb1cSDavid du Colombier sysfatal("announcing on %s: %r", buf); 109c0eadb1cSDavid du Colombier syslog(dbg, flog, "tftpd started on %s dir %s", buf, adir); 11027e10919SDavid du Colombier setuser(); 1113e12c5d1SDavid du Colombier for(;;) { 1127dd7cddfSDavid du Colombier lcfd = listen(adir, ldir); 1137dd7cddfSDavid du Colombier if(lcfd < 0) 114c0eadb1cSDavid du Colombier sysfatal("listening on %s: %r", adir); 1157dd7cddfSDavid du Colombier 1167dd7cddfSDavid du Colombier switch(fork()) { 1177dd7cddfSDavid du Colombier case -1: 1187dd7cddfSDavid du Colombier sysfatal("fork: %r"); 1197dd7cddfSDavid du Colombier case 0: 120c0eadb1cSDavid du Colombier dfd = accept(lcfd, ldir); 1217dd7cddfSDavid du Colombier if(dfd < 0) 1227dd7cddfSDavid du Colombier exits(0); 1237dd7cddfSDavid du Colombier remoteaddr(ldir, raddr, sizeof(raddr)); 124c0eadb1cSDavid du Colombier syslog(0, flog, "tftp connection from %s dir %s", 125c0eadb1cSDavid du Colombier raddr, ldir); 1267dd7cddfSDavid du Colombier doserve(dfd); 1277dd7cddfSDavid du Colombier exits("done"); 1287dd7cddfSDavid du Colombier break; 1297dd7cddfSDavid du Colombier default: 1307dd7cddfSDavid du Colombier close(lcfd); 1317dd7cddfSDavid du Colombier continue; 1327dd7cddfSDavid du Colombier } 1337dd7cddfSDavid du Colombier } 1347dd7cddfSDavid du Colombier } 1357dd7cddfSDavid du Colombier 1367dd7cddfSDavid du Colombier void 1377dd7cddfSDavid du Colombier doserve(int fd) 1387dd7cddfSDavid du Colombier { 1397dd7cddfSDavid du Colombier int dlen; 1407dd7cddfSDavid du Colombier char *mode, *p; 1417dd7cddfSDavid du Colombier short op; 1427dd7cddfSDavid du Colombier 1437dd7cddfSDavid du Colombier dlen = read(fd, bigbuf, sizeof(bigbuf)); 1443e12c5d1SDavid du Colombier if(dlen < 0) 1457dd7cddfSDavid du Colombier sysfatal("listen read: %r"); 1463e12c5d1SDavid du Colombier 1477dd7cddfSDavid du Colombier op = (bigbuf[0]<<8) | bigbuf[1]; 1483e12c5d1SDavid du Colombier dlen -= 2; 1497dd7cddfSDavid du Colombier mode = bigbuf+2; 1503e12c5d1SDavid du Colombier while(*mode != '\0' && dlen--) 1513e12c5d1SDavid du Colombier mode++; 1523e12c5d1SDavid du Colombier mode++; 1533e12c5d1SDavid du Colombier p = mode; 1543e12c5d1SDavid du Colombier while(*p && dlen--) 1553e12c5d1SDavid du Colombier p++; 1563e12c5d1SDavid du Colombier if(dlen == 0) { 1577dd7cddfSDavid du Colombier nak(fd, 0, "bad tftpmode"); 1587dd7cddfSDavid du Colombier close(fd); 159c0eadb1cSDavid du Colombier syslog(dbg, flog, "bad mode from %s", raddr); 1607dd7cddfSDavid du Colombier return; 1613e12c5d1SDavid du Colombier } 1623e12c5d1SDavid du Colombier 1633e12c5d1SDavid du Colombier if(op != Tftp_READ && op != Tftp_WRITE) { 1647dd7cddfSDavid du Colombier nak(fd, 4, "Illegal TFTP operation"); 1657dd7cddfSDavid du Colombier close(fd); 1663e12c5d1SDavid du Colombier syslog(dbg, flog, "bad request %d %s", op, raddr); 1677dd7cddfSDavid du Colombier return; 1683e12c5d1SDavid du Colombier } 1697dd7cddfSDavid du Colombier 170219b2ee8SDavid du Colombier if(restricted){ 17167031067SDavid du Colombier if(bigbuf[2] == '#' || 17267031067SDavid du Colombier strncmp(bigbuf+2, "../", 3)==0 || strstr(bigbuf+2, "/../") || 1737dd7cddfSDavid du Colombier (bigbuf[2] == '/' && strncmp(bigbuf+2, dirsl, dirsllen)!=0)){ 1747dd7cddfSDavid du Colombier nak(fd, 4, "Permission denied"); 1757dd7cddfSDavid du Colombier close(fd); 17639734e7eSDavid du Colombier syslog(dbg, flog, "bad request %d from %s file %s", op, raddr, bigbuf+2); 1777dd7cddfSDavid du Colombier return; 178219b2ee8SDavid du Colombier } 179219b2ee8SDavid du Colombier } 1807dd7cddfSDavid du Colombier 1813e12c5d1SDavid du Colombier if(op == Tftp_READ) 1827dd7cddfSDavid du Colombier sendfile(fd, bigbuf+2, mode); 1833e12c5d1SDavid du Colombier else 1847dd7cddfSDavid du Colombier recvfile(fd, bigbuf+2, mode); 1853e12c5d1SDavid du Colombier } 1863e12c5d1SDavid du Colombier 1873e12c5d1SDavid du Colombier void 1883e12c5d1SDavid du Colombier catcher(void *junk, char *msg) 1893e12c5d1SDavid du Colombier { 1903e12c5d1SDavid du Colombier USED(junk); 1913e12c5d1SDavid du Colombier 1923e12c5d1SDavid du Colombier if(strncmp(msg, "exit", 4) == 0) 1933e12c5d1SDavid du Colombier noted(NDFLT); 1943e12c5d1SDavid du Colombier noted(NCONT); 1953e12c5d1SDavid du Colombier } 1963e12c5d1SDavid du Colombier 1973e12c5d1SDavid du Colombier void 1983e12c5d1SDavid du Colombier sendfile(int fd, char *name, char *mode) 1993e12c5d1SDavid du Colombier { 2003e12c5d1SDavid du Colombier int file; 2013e12c5d1SDavid du Colombier uchar buf[Segsize+4]; 2023e12c5d1SDavid du Colombier uchar ack[1024]; 2039a747e4fSDavid du Colombier char errbuf[Maxerr]; 2043e12c5d1SDavid du Colombier int ackblock, block, ret; 2053e12c5d1SDavid du Colombier int rexmit, n, al, txtry, rxl; 2063e12c5d1SDavid du Colombier short op; 2073e12c5d1SDavid du Colombier 2083e12c5d1SDavid du Colombier syslog(dbg, flog, "send file '%s' %s to %s", name, mode, raddr); 2093e12c5d1SDavid du Colombier name = sunkernel(name); 2103e12c5d1SDavid du Colombier if(name == 0){ 2113e12c5d1SDavid du Colombier nak(fd, 0, "not in our database"); 2123e12c5d1SDavid du Colombier return; 2133e12c5d1SDavid du Colombier } 2143e12c5d1SDavid du Colombier 2153e12c5d1SDavid du Colombier notify(catcher); 2163e12c5d1SDavid du Colombier 2173e12c5d1SDavid du Colombier file = open(name, OREAD); 2183e12c5d1SDavid du Colombier if(file < 0) { 2199a747e4fSDavid du Colombier errstr(errbuf, sizeof errbuf); 2203e12c5d1SDavid du Colombier nak(fd, 0, errbuf); 2213e12c5d1SDavid du Colombier return; 2223e12c5d1SDavid du Colombier } 2233e12c5d1SDavid du Colombier block = 0; 2243e12c5d1SDavid du Colombier rexmit = 0; 2253e12c5d1SDavid du Colombier n = 0; 226219b2ee8SDavid du Colombier for(txtry = 0; txtry < 5;) { 2273e12c5d1SDavid du Colombier if(rexmit == 0) { 2283e12c5d1SDavid du Colombier block++; 2293e12c5d1SDavid du Colombier buf[0] = 0; 2303e12c5d1SDavid du Colombier buf[1] = Tftp_DATA; 2313e12c5d1SDavid du Colombier buf[2] = block>>8; 2323e12c5d1SDavid du Colombier buf[3] = block; 2333e12c5d1SDavid du Colombier n = read(file, buf+4, Segsize); 2343e12c5d1SDavid du Colombier if(n < 0) { 2359a747e4fSDavid du Colombier errstr(errbuf, sizeof errbuf); 2363e12c5d1SDavid du Colombier nak(fd, 0, errbuf); 2373e12c5d1SDavid du Colombier return; 2383e12c5d1SDavid du Colombier } 239219b2ee8SDavid du Colombier txtry = 0; 2403e12c5d1SDavid du Colombier } 2417dd7cddfSDavid du Colombier else { 242*162f803dSDavid du Colombier syslog(dbg, flog, "rexmit %d %s:%d to %s", 243*162f803dSDavid du Colombier 4+n, name, block, raddr); 2443e12c5d1SDavid du Colombier txtry++; 2457dd7cddfSDavid du Colombier } 2467dd7cddfSDavid du Colombier 2473e12c5d1SDavid du Colombier ret = write(fd, buf, 4+n); 2483e12c5d1SDavid du Colombier if(ret < 0) 2497dd7cddfSDavid du Colombier sysfatal("tftpd: network write error: %r"); 2503e12c5d1SDavid du Colombier 2513e12c5d1SDavid du Colombier for(rxl = 0; rxl < 10; rxl++) { 2523e12c5d1SDavid du Colombier rexmit = 0; 253219b2ee8SDavid du Colombier alarm(500); 2543e12c5d1SDavid du Colombier al = read(fd, ack, sizeof(ack)); 2553e12c5d1SDavid du Colombier alarm(0); 2563e12c5d1SDavid du Colombier if(al < 0) { 2573e12c5d1SDavid du Colombier rexmit = 1; 2583e12c5d1SDavid du Colombier break; 2593e12c5d1SDavid du Colombier } 2603e12c5d1SDavid du Colombier op = ack[0]<<8|ack[1]; 2613e12c5d1SDavid du Colombier if(op == Tftp_ERROR) 2623e12c5d1SDavid du Colombier goto error; 2633e12c5d1SDavid du Colombier ackblock = ack[2]<<8|ack[3]; 2643e12c5d1SDavid du Colombier if(ackblock == block) 2653e12c5d1SDavid du Colombier break; 2663e12c5d1SDavid du Colombier if(ackblock == 0xffff) { 2673e12c5d1SDavid du Colombier rexmit = 1; 2683e12c5d1SDavid du Colombier break; 2693e12c5d1SDavid du Colombier } 2703e12c5d1SDavid du Colombier } 2713e12c5d1SDavid du Colombier if(ret != Segsize+4 && rexmit == 0) 2723e12c5d1SDavid du Colombier break; 2733e12c5d1SDavid du Colombier } 2743e12c5d1SDavid du Colombier error: 2753e12c5d1SDavid du Colombier close(fd); 2763e12c5d1SDavid du Colombier close(file); 2773e12c5d1SDavid du Colombier } 2783e12c5d1SDavid du Colombier 279*162f803dSDavid du Colombier enum { Hdrsize = 2 * sizeof(short), }; /* op, block */ 280*162f803dSDavid du Colombier 2813e12c5d1SDavid du Colombier void 2823e12c5d1SDavid du Colombier recvfile(int fd, char *name, char *mode) 2833e12c5d1SDavid du Colombier { 2843e12c5d1SDavid du Colombier ushort op, block, inblock; 2853e12c5d1SDavid du Colombier uchar buf[Segsize+8]; 2869a747e4fSDavid du Colombier char errbuf[Maxerr]; 2873e12c5d1SDavid du Colombier int n, ret, file; 2883e12c5d1SDavid du Colombier 2893e12c5d1SDavid du Colombier syslog(dbg, flog, "receive file '%s' %s from %s", name, mode, raddr); 2903e12c5d1SDavid du Colombier 2913e12c5d1SDavid du Colombier file = create(name, OWRITE, 0666); 2923e12c5d1SDavid du Colombier if(file < 0) { 2939a747e4fSDavid du Colombier errstr(errbuf, sizeof errbuf); 2943e12c5d1SDavid du Colombier nak(fd, 0, errbuf); 295*162f803dSDavid du Colombier syslog(dbg, flog, "can't create %s: %r", name); 2963e12c5d1SDavid du Colombier return; 2973e12c5d1SDavid du Colombier } 2983e12c5d1SDavid du Colombier 2993e12c5d1SDavid du Colombier block = 0; 3003e12c5d1SDavid du Colombier ack(fd, block); 3013e12c5d1SDavid du Colombier block++; 3023e12c5d1SDavid du Colombier 3033e12c5d1SDavid du Colombier for (;;) { 3043e12c5d1SDavid du Colombier alarm(15000); 3053e12c5d1SDavid du Colombier n = read(fd, buf, sizeof(buf)); 3063e12c5d1SDavid du Colombier alarm(0); 307*162f803dSDavid du Colombier if(n < 0) { 308*162f803dSDavid du Colombier syslog(dbg, flog, "tftpd: network error reading %s: %r", 309*162f803dSDavid du Colombier name); 3103e12c5d1SDavid du Colombier goto error; 311*162f803dSDavid du Colombier } 312*162f803dSDavid du Colombier if(n <= Hdrsize) { 313*162f803dSDavid du Colombier syslog(dbg, flog, 314*162f803dSDavid du Colombier "tftpd: short read from network, reading %s", 315*162f803dSDavid du Colombier name); 316*162f803dSDavid du Colombier goto error; 317*162f803dSDavid du Colombier } 3183e12c5d1SDavid du Colombier op = buf[0]<<8|buf[1]; 319*162f803dSDavid du Colombier if(op == Tftp_ERROR) { 320*162f803dSDavid du Colombier syslog(dbg, flog, "tftpd: tftp error reading %s", name); 3213e12c5d1SDavid du Colombier goto error; 322*162f803dSDavid du Colombier } 3233e12c5d1SDavid du Colombier 324*162f803dSDavid du Colombier n -= Hdrsize; 3253e12c5d1SDavid du Colombier inblock = buf[2]<<8|buf[3]; 3263e12c5d1SDavid du Colombier if(op == Tftp_DATA) { 3273e12c5d1SDavid du Colombier if(inblock == block) { 328*162f803dSDavid du Colombier ret = write(file, buf+Hdrsize, n); 329*162f803dSDavid du Colombier if(ret != n) { 3309a747e4fSDavid du Colombier errstr(errbuf, sizeof errbuf); 3313e12c5d1SDavid du Colombier nak(fd, 0, errbuf); 332*162f803dSDavid du Colombier syslog(dbg, flog, 333*162f803dSDavid du Colombier "tftpd: error writing %s: %s", 334*162f803dSDavid du Colombier name, errbuf); 3353e12c5d1SDavid du Colombier goto error; 3363e12c5d1SDavid du Colombier } 3373e12c5d1SDavid du Colombier ack(fd, block); 3383e12c5d1SDavid du Colombier block++; 3393e12c5d1SDavid du Colombier } 3403e12c5d1SDavid du Colombier ack(fd, 0xffff); 3413e12c5d1SDavid du Colombier } 3423e12c5d1SDavid du Colombier } 3433e12c5d1SDavid du Colombier error: 3443e12c5d1SDavid du Colombier close(file); 3453e12c5d1SDavid du Colombier } 3463e12c5d1SDavid du Colombier 3473e12c5d1SDavid du Colombier void 3483e12c5d1SDavid du Colombier ack(int fd, ushort block) 3493e12c5d1SDavid du Colombier { 3503e12c5d1SDavid du Colombier uchar ack[4]; 3513e12c5d1SDavid du Colombier int n; 3523e12c5d1SDavid du Colombier 3533e12c5d1SDavid du Colombier ack[0] = 0; 3543e12c5d1SDavid du Colombier ack[1] = Tftp_ACK; 3553e12c5d1SDavid du Colombier ack[2] = block>>8; 3563e12c5d1SDavid du Colombier ack[3] = block; 3573e12c5d1SDavid du Colombier 3583e12c5d1SDavid du Colombier n = write(fd, ack, 4); 359*162f803dSDavid du Colombier if(n < 4) 3607dd7cddfSDavid du Colombier sysfatal("network write: %r"); 3613e12c5d1SDavid du Colombier } 3623e12c5d1SDavid du Colombier 3633e12c5d1SDavid du Colombier void 3643e12c5d1SDavid du Colombier nak(int fd, int code, char *msg) 3653e12c5d1SDavid du Colombier { 3663e12c5d1SDavid du Colombier char buf[128]; 3673e12c5d1SDavid du Colombier int n; 3683e12c5d1SDavid du Colombier 3693e12c5d1SDavid du Colombier buf[0] = 0; 3703e12c5d1SDavid du Colombier buf[1] = Tftp_ERROR; 3713e12c5d1SDavid du Colombier buf[2] = 0; 3723e12c5d1SDavid du Colombier buf[3] = code; 3733e12c5d1SDavid du Colombier strcpy(buf+4, msg); 3743e12c5d1SDavid du Colombier n = strlen(msg) + 4 + 1; 3753e12c5d1SDavid du Colombier n = write(fd, buf, n); 3763e12c5d1SDavid du Colombier if(n < 0) 3777dd7cddfSDavid du Colombier sysfatal("write nak: %r"); 3783e12c5d1SDavid du Colombier } 3793e12c5d1SDavid du Colombier 3803e12c5d1SDavid du Colombier void 3813e12c5d1SDavid du Colombier setuser(void) 3823e12c5d1SDavid du Colombier { 383c0eadb1cSDavid du Colombier int fd; 3843e12c5d1SDavid du Colombier 385c0eadb1cSDavid du Colombier fd = open("#c/user", OWRITE); 386c0eadb1cSDavid du Colombier if(fd < 0 || write(fd, "none", strlen("none")) < 0) 387c0eadb1cSDavid du Colombier sysfatal("can't become none: %r"); 388c0eadb1cSDavid du Colombier close(fd); 389c0eadb1cSDavid du Colombier if(newns("none", nil) < 0) 390c0eadb1cSDavid du Colombier sysfatal("can't build namespace: %r"); 3913e12c5d1SDavid du Colombier } 3923e12c5d1SDavid du Colombier 3937dd7cddfSDavid du Colombier char* 394da51d93aSDavid du Colombier lookup(char *sattr, char *sval, char *tattr, char *tval, int len) 3957dd7cddfSDavid du Colombier { 3967dd7cddfSDavid du Colombier static Ndb *db; 3977dd7cddfSDavid du Colombier char *attrs[1]; 3987dd7cddfSDavid du Colombier Ndbtuple *t; 3997dd7cddfSDavid du Colombier 4007dd7cddfSDavid du Colombier if(db == nil) 4017dd7cddfSDavid du Colombier db = ndbopen(0); 4027dd7cddfSDavid du Colombier if(db == nil) 4037dd7cddfSDavid du Colombier return nil; 4047dd7cddfSDavid du Colombier 4057dd7cddfSDavid du Colombier if(sattr == nil) 4067dd7cddfSDavid du Colombier sattr = ipattr(sval); 4077dd7cddfSDavid du Colombier 4087dd7cddfSDavid du Colombier attrs[0] = tattr; 4097dd7cddfSDavid du Colombier t = ndbipinfo(db, sattr, sval, attrs, 1); 4107dd7cddfSDavid du Colombier if(t == nil) 4117dd7cddfSDavid du Colombier return nil; 412da51d93aSDavid du Colombier strncpy(tval, t->val, len); 413da51d93aSDavid du Colombier tval[len-1] = 0; 4147dd7cddfSDavid du Colombier ndbfree(t); 4157dd7cddfSDavid du Colombier return tval; 4167dd7cddfSDavid du Colombier } 4177dd7cddfSDavid du Colombier 4183e12c5d1SDavid du Colombier /* 4193e12c5d1SDavid du Colombier * for sun kernel boots, replace the requested file name with 4203e12c5d1SDavid du Colombier * a one from our database. If the database doesn't specify a file, 4213e12c5d1SDavid du Colombier * don't answer. 4223e12c5d1SDavid du Colombier */ 4233e12c5d1SDavid du Colombier char* 4243e12c5d1SDavid du Colombier sunkernel(char *name) 4253e12c5d1SDavid du Colombier { 4263e12c5d1SDavid du Colombier ulong addr; 4277dd7cddfSDavid du Colombier uchar v4[IPv4addrlen]; 4287dd7cddfSDavid du Colombier uchar v6[IPaddrlen]; 429da51d93aSDavid du Colombier char buf[256]; 430da51d93aSDavid du Colombier char ipbuf[128]; 43127e10919SDavid du Colombier char *suffix; 4323e12c5d1SDavid du Colombier 43327e10919SDavid du Colombier addr = strtoul(name, &suffix, 16); 43427e10919SDavid du Colombier if(suffix-name != 8 || (strcmp(suffix, "") != 0 && strcmp(suffix, ".SUN") != 0)) 4353e12c5d1SDavid du Colombier return name; 4363e12c5d1SDavid du Colombier 4377dd7cddfSDavid du Colombier v4[0] = addr>>24; 4387dd7cddfSDavid du Colombier v4[1] = addr>>16; 4397dd7cddfSDavid du Colombier v4[2] = addr>>8; 4407dd7cddfSDavid du Colombier v4[3] = addr; 4417dd7cddfSDavid du Colombier v4tov6(v6, v4); 4427dd7cddfSDavid du Colombier sprint(ipbuf, "%I", v6); 443da51d93aSDavid du Colombier return lookup("ip", ipbuf, "bootf", buf, sizeof buf); 4447dd7cddfSDavid du Colombier } 4457dd7cddfSDavid du Colombier 4467dd7cddfSDavid du Colombier void 4477dd7cddfSDavid du Colombier remoteaddr(char *dir, char *raddr, int len) 4487dd7cddfSDavid du Colombier { 4497dd7cddfSDavid du Colombier char buf[64]; 4507dd7cddfSDavid du Colombier int fd, n; 4517dd7cddfSDavid du Colombier 4527dd7cddfSDavid du Colombier snprint(buf, sizeof(buf), "%s/remote", dir); 4537dd7cddfSDavid du Colombier fd = open(buf, OREAD); 4547dd7cddfSDavid du Colombier if(fd < 0){ 4557dd7cddfSDavid du Colombier snprint(raddr, sizeof(raddr), "unknown"); 4567dd7cddfSDavid du Colombier return; 4577dd7cddfSDavid du Colombier } 4587dd7cddfSDavid du Colombier n = read(fd, raddr, len-1); 4597dd7cddfSDavid du Colombier close(fd); 4607dd7cddfSDavid du Colombier if(n <= 0){ 4617dd7cddfSDavid du Colombier snprint(raddr, sizeof(raddr), "unknown"); 4627dd7cddfSDavid du Colombier return; 4637dd7cddfSDavid du Colombier } 4647dd7cddfSDavid du Colombier if(n > 0) 4657dd7cddfSDavid du Colombier n--; 4667dd7cddfSDavid du Colombier raddr[n] = 0; 4673e12c5d1SDavid du Colombier } 468