13e12c5d1SDavid du Colombier #include <u.h> 23e12c5d1SDavid du Colombier #include <libc.h> 3*219b2ee8SDavid du Colombier #include <auth.h> 43e12c5d1SDavid du Colombier #include <fcall.h> 53e12c5d1SDavid du Colombier #include <bio.h> 63e12c5d1SDavid du Colombier #include <ctype.h> 73e12c5d1SDavid du Colombier #include "dns.h" 83e12c5d1SDavid du Colombier 93e12c5d1SDavid du Colombier enum 103e12c5d1SDavid du Colombier { 113e12c5d1SDavid du Colombier Maxrequest= 4*NAMELEN, 123e12c5d1SDavid du Colombier Ncache= 8, 133e12c5d1SDavid du Colombier 143e12c5d1SDavid du Colombier Qdns= 1, 153e12c5d1SDavid du Colombier }; 163e12c5d1SDavid du Colombier 173e12c5d1SDavid du Colombier typedef struct Mfile Mfile; 183e12c5d1SDavid du Colombier typedef struct Network Network; 193e12c5d1SDavid du Colombier 203e12c5d1SDavid du Colombier int vers; /* incremented each clone/attach */ 213e12c5d1SDavid du Colombier 223e12c5d1SDavid du Colombier struct Mfile 233e12c5d1SDavid du Colombier { 243e12c5d1SDavid du Colombier int busy; 253e12c5d1SDavid du Colombier char user[NAMELEN]; 263e12c5d1SDavid du Colombier Qid qid; 273e12c5d1SDavid du Colombier int fid; 283e12c5d1SDavid du Colombier 293e12c5d1SDavid du Colombier int tag; /* tag of current request */ 303e12c5d1SDavid du Colombier RR *rp; /* start of reply */ 313e12c5d1SDavid du Colombier int type; /* reply type */ 323e12c5d1SDavid du Colombier }; 333e12c5d1SDavid du Colombier 343e12c5d1SDavid du Colombier Mfile *mfile; 353e12c5d1SDavid du Colombier int nmfile = 0; 363e12c5d1SDavid du Colombier int mfd[2]; 373e12c5d1SDavid du Colombier char user[NAMELEN]; 383e12c5d1SDavid du Colombier Fcall *rhp; 393e12c5d1SDavid du Colombier Fcall *thp; 403e12c5d1SDavid du Colombier int debug; 413e12c5d1SDavid du Colombier 42*219b2ee8SDavid du Colombier void rsession(void); 433e12c5d1SDavid du Colombier void rsimple(void); 443e12c5d1SDavid du Colombier void rflush(int tag); 453e12c5d1SDavid du Colombier void rattach(Mfile*); 463e12c5d1SDavid du Colombier void rclone(Mfile*); 473e12c5d1SDavid du Colombier char* rwalk(Mfile*); 483e12c5d1SDavid du Colombier void rclwalk(Mfile*); 493e12c5d1SDavid du Colombier void ropen(Mfile*); 503e12c5d1SDavid du Colombier void rcreate(Mfile*); 513e12c5d1SDavid du Colombier void rread(Mfile*); 523e12c5d1SDavid du Colombier void rwrite(Mfile*, Request*); 533e12c5d1SDavid du Colombier void rclunk(Mfile*); 543e12c5d1SDavid du Colombier void rremove(Mfile*); 553e12c5d1SDavid du Colombier void rstat(Mfile*); 563e12c5d1SDavid du Colombier void rauth(void); 573e12c5d1SDavid du Colombier void rwstat(Mfile*); 583e12c5d1SDavid du Colombier void sendmsg(char*); 593e12c5d1SDavid du Colombier void mountinit(char*); 603e12c5d1SDavid du Colombier void io(void); 613e12c5d1SDavid du Colombier int lookup(Mfile*, char*, char*, char*); 623e12c5d1SDavid du Colombier int fillreply(Mfile*, int); 633e12c5d1SDavid du Colombier int mygetfields(char*, char**, int, char); 643e12c5d1SDavid du Colombier 653e12c5d1SDavid du Colombier char *mname[]={ 663e12c5d1SDavid du Colombier [Tnop] "Tnop", 673e12c5d1SDavid du Colombier [Tsession] "Tsession", 683e12c5d1SDavid du Colombier [Tflush] "Tflush", 693e12c5d1SDavid du Colombier [Tattach] "Tattach", 703e12c5d1SDavid du Colombier [Tclone] "Tclone", 713e12c5d1SDavid du Colombier [Twalk] "Twalk", 723e12c5d1SDavid du Colombier [Topen] "Topen", 733e12c5d1SDavid du Colombier [Tcreate] "Tcreate", 743e12c5d1SDavid du Colombier [Tclunk] "Tclunk", 753e12c5d1SDavid du Colombier [Tread] "Tread", 763e12c5d1SDavid du Colombier [Twrite] "Twrite", 773e12c5d1SDavid du Colombier [Tremove] "Tremove", 783e12c5d1SDavid du Colombier [Tstat] "Tstat", 793e12c5d1SDavid du Colombier [Twstat] "Twstat", 803e12c5d1SDavid du Colombier 0, 813e12c5d1SDavid du Colombier }; 823e12c5d1SDavid du Colombier 83*219b2ee8SDavid du Colombier char *logfile = "dns"; 84*219b2ee8SDavid du Colombier char *dbfile; 85*219b2ee8SDavid du Colombier 863e12c5d1SDavid du Colombier void 873e12c5d1SDavid du Colombier main(int argc, char *argv[]) 883e12c5d1SDavid du Colombier { 893e12c5d1SDavid du Colombier Fcall rhdr; 903e12c5d1SDavid du Colombier Fcall thdr; 913e12c5d1SDavid du Colombier int serve; 923e12c5d1SDavid du Colombier 93*219b2ee8SDavid du Colombier 943e12c5d1SDavid du Colombier serve = 0; 953e12c5d1SDavid du Colombier rhp = &rhdr; 963e12c5d1SDavid du Colombier thp = &thdr; 973e12c5d1SDavid du Colombier ARGBEGIN{ 983e12c5d1SDavid du Colombier case 'd': 993e12c5d1SDavid du Colombier debug = 1; 1003e12c5d1SDavid du Colombier break; 101*219b2ee8SDavid du Colombier case 'f': 102*219b2ee8SDavid du Colombier dbfile = ARGF(); 103*219b2ee8SDavid du Colombier break; 1043e12c5d1SDavid du Colombier case 's': 1053e12c5d1SDavid du Colombier serve = 1; /* serve network */ 1063e12c5d1SDavid du Colombier break; 1073e12c5d1SDavid du Colombier }ARGEND 1083e12c5d1SDavid du Colombier USED(argc); 1093e12c5d1SDavid du Colombier USED(argv); 1103e12c5d1SDavid du Colombier 111*219b2ee8SDavid du Colombier remove("#s/dns"); 1123e12c5d1SDavid du Colombier unmount("/net/dns", "/net"); 1133e12c5d1SDavid du Colombier mountinit("#s/dns"); 1143e12c5d1SDavid du Colombier 115*219b2ee8SDavid du Colombier fmtinstall('F', fcallconv); 116*219b2ee8SDavid du Colombier dninit(); 117*219b2ee8SDavid du Colombier 118*219b2ee8SDavid du Colombier syslog(1, logfile, "started%s%s", serve?" serving":"", 119bd389b36SDavid du Colombier debug?" debuging":""); 120bd389b36SDavid du Colombier if(serve) 121bd389b36SDavid du Colombier dnserver(); 1223e12c5d1SDavid du Colombier io(); 1233e12c5d1SDavid du Colombier exits(0); 1243e12c5d1SDavid du Colombier } 1253e12c5d1SDavid du Colombier 1263e12c5d1SDavid du Colombier void 1273e12c5d1SDavid du Colombier mountinit(char *service) 1283e12c5d1SDavid du Colombier { 1293e12c5d1SDavid du Colombier int f; 1303e12c5d1SDavid du Colombier int p[2]; 1313e12c5d1SDavid du Colombier char buf[32]; 1323e12c5d1SDavid du Colombier 1333e12c5d1SDavid du Colombier if(pipe(p) < 0) 1343e12c5d1SDavid du Colombier fatal("pipe failed"); 135*219b2ee8SDavid du Colombier switch(rfork(RFFDG|RFPROC|RFNAMEG)){ 1363e12c5d1SDavid du Colombier case 0: 137*219b2ee8SDavid du Colombier close(p[1]); 1383e12c5d1SDavid du Colombier break; 1393e12c5d1SDavid du Colombier case -1: 1403e12c5d1SDavid du Colombier fatal("fork failed\n"); 1413e12c5d1SDavid du Colombier default: 142*219b2ee8SDavid du Colombier close(p[0]); 143*219b2ee8SDavid du Colombier 1443e12c5d1SDavid du Colombier /* 1453e12c5d1SDavid du Colombier * make a /srv/dns 1463e12c5d1SDavid du Colombier */ 1473e12c5d1SDavid du Colombier f = create(service, 1, 0666); 1483e12c5d1SDavid du Colombier if(f < 0) 1493e12c5d1SDavid du Colombier fatal(service); 150bd389b36SDavid du Colombier snprint(buf, sizeof(buf), "%d", p[1]); 1513e12c5d1SDavid du Colombier if(write(f, buf, strlen(buf)) != strlen(buf)) 1523e12c5d1SDavid du Colombier fatal("write %s", service); 1533e12c5d1SDavid du Colombier close(f); 1543e12c5d1SDavid du Colombier 1553e12c5d1SDavid du Colombier /* 1563e12c5d1SDavid du Colombier * put ourselves into the file system 1573e12c5d1SDavid du Colombier */ 158*219b2ee8SDavid du Colombier if(mount(p[1], "/net", MAFTER, "") < 0) 1593e12c5d1SDavid du Colombier fatal("mount failed\n"); 160*219b2ee8SDavid du Colombier _exits(0); 1613e12c5d1SDavid du Colombier } 1623e12c5d1SDavid du Colombier mfd[0] = mfd[1] = p[0]; 1633e12c5d1SDavid du Colombier } 1643e12c5d1SDavid du Colombier 1653e12c5d1SDavid du Colombier #define INC 4 1663e12c5d1SDavid du Colombier Mfile* 1673e12c5d1SDavid du Colombier newfid(int fid) 1683e12c5d1SDavid du Colombier { 1693e12c5d1SDavid du Colombier Mfile *mf; 1703e12c5d1SDavid du Colombier Mfile *freemf; 1713e12c5d1SDavid du Colombier int old; 1723e12c5d1SDavid du Colombier Mfile *o; 1733e12c5d1SDavid du Colombier 1743e12c5d1SDavid du Colombier freemf = 0; 1753e12c5d1SDavid du Colombier for(mf = mfile; mf < &mfile[nmfile]; mf++){ 1763e12c5d1SDavid du Colombier if(mf->fid==fid) 1773e12c5d1SDavid du Colombier return mf; 1783e12c5d1SDavid du Colombier if(mf->busy == 0) 1793e12c5d1SDavid du Colombier freemf = mf; 1803e12c5d1SDavid du Colombier } 1813e12c5d1SDavid du Colombier if(freemf == 0){ 1823e12c5d1SDavid du Colombier old = nmfile; 1833e12c5d1SDavid du Colombier nmfile += INC; 1843e12c5d1SDavid du Colombier o = mfile; 1853e12c5d1SDavid du Colombier mfile = realloc(mfile, nmfile*sizeof(Mfile)); 1863e12c5d1SDavid du Colombier if(mfile == 0){ 1873e12c5d1SDavid du Colombier fprint(2, "dns: realloc(0x%lux, %d)\n", o, nmfile*sizeof(Mfile)); 1883e12c5d1SDavid du Colombier fatal("realloc failure"); 1893e12c5d1SDavid du Colombier } 1903e12c5d1SDavid du Colombier mf = &mfile[old]; 1913e12c5d1SDavid du Colombier memset(mf, 0, INC*sizeof(Mfile)); 1923e12c5d1SDavid du Colombier } else 1933e12c5d1SDavid du Colombier mf = freemf; 1943e12c5d1SDavid du Colombier 1953e12c5d1SDavid du Colombier memset(mf, 0, sizeof mfile[0]); 1963e12c5d1SDavid du Colombier mf->fid = fid; 1973e12c5d1SDavid du Colombier return mf; 1983e12c5d1SDavid du Colombier } 1993e12c5d1SDavid du Colombier 2003e12c5d1SDavid du Colombier void 2013e12c5d1SDavid du Colombier io(void) 2023e12c5d1SDavid du Colombier { 2033e12c5d1SDavid du Colombier long n; 2043e12c5d1SDavid du Colombier Mfile *mf; 2053e12c5d1SDavid du Colombier char mdata[MAXFDATA + MAXMSG]; 2063e12c5d1SDavid du Colombier Request req; 2073e12c5d1SDavid du Colombier 2083e12c5d1SDavid du Colombier /* 2093e12c5d1SDavid du Colombier * a slave process is sometimes forked to wait for replies from other 2103e12c5d1SDavid du Colombier * servers. The master process returns immediately via a longjmp 211*219b2ee8SDavid du Colombier * through 'mret'. 2123e12c5d1SDavid du Colombier */ 2133e12c5d1SDavid du Colombier setjmp(req.mret); 2143e12c5d1SDavid du Colombier req.isslave = 0; 2153e12c5d1SDavid du Colombier loop: 2163e12c5d1SDavid du Colombier n = read(mfd[0], mdata, sizeof mdata); 2173e12c5d1SDavid du Colombier if(n<=0) 2183e12c5d1SDavid du Colombier fatal("mount read"); 2193e12c5d1SDavid du Colombier if(convM2S(mdata, rhp, n) == 0) 2203e12c5d1SDavid du Colombier goto loop; 2213e12c5d1SDavid du Colombier if(rhp->fid<0) 2223e12c5d1SDavid du Colombier fatal("fid out of range"); 2233e12c5d1SDavid du Colombier mf = newfid(rhp->fid); 224*219b2ee8SDavid du Colombier if(debug) 225*219b2ee8SDavid du Colombier syslog(0, logfile, "%F", rhp); 2263e12c5d1SDavid du Colombier mf->tag = rhp->tag; 2273e12c5d1SDavid du Colombier switch(rhp->type){ 2283e12c5d1SDavid du Colombier default: 2293e12c5d1SDavid du Colombier fatal("type"); 2303e12c5d1SDavid du Colombier break; 2313e12c5d1SDavid du Colombier case Tsession: 232*219b2ee8SDavid du Colombier rsession(); 2333e12c5d1SDavid du Colombier break; 2343e12c5d1SDavid du Colombier case Tnop: 2353e12c5d1SDavid du Colombier rsimple(); 2363e12c5d1SDavid du Colombier break; 2373e12c5d1SDavid du Colombier case Tflush: 2383e12c5d1SDavid du Colombier rflush(rhp->tag); 2393e12c5d1SDavid du Colombier break; 2403e12c5d1SDavid du Colombier case Tattach: 2413e12c5d1SDavid du Colombier rattach(mf); 2423e12c5d1SDavid du Colombier break; 2433e12c5d1SDavid du Colombier case Tclone: 2443e12c5d1SDavid du Colombier rclone(mf); 2453e12c5d1SDavid du Colombier break; 2463e12c5d1SDavid du Colombier case Twalk: 2473e12c5d1SDavid du Colombier rwalk(mf); 2483e12c5d1SDavid du Colombier break; 2493e12c5d1SDavid du Colombier case Tclwalk: 2503e12c5d1SDavid du Colombier rclwalk(mf); 2513e12c5d1SDavid du Colombier break; 2523e12c5d1SDavid du Colombier case Topen: 2533e12c5d1SDavid du Colombier ropen(mf); 2543e12c5d1SDavid du Colombier break; 2553e12c5d1SDavid du Colombier case Tcreate: 2563e12c5d1SDavid du Colombier rcreate(mf); 2573e12c5d1SDavid du Colombier break; 2583e12c5d1SDavid du Colombier case Tread: 2593e12c5d1SDavid du Colombier rread(mf); 2603e12c5d1SDavid du Colombier break; 2613e12c5d1SDavid du Colombier case Twrite: 2623e12c5d1SDavid du Colombier rwrite(mf, &req); 2633e12c5d1SDavid du Colombier break; 2643e12c5d1SDavid du Colombier case Tclunk: 2653e12c5d1SDavid du Colombier rclunk(mf); 2663e12c5d1SDavid du Colombier break; 2673e12c5d1SDavid du Colombier case Tremove: 2683e12c5d1SDavid du Colombier rremove(mf); 2693e12c5d1SDavid du Colombier break; 2703e12c5d1SDavid du Colombier case Tstat: 2713e12c5d1SDavid du Colombier rstat(mf); 2723e12c5d1SDavid du Colombier break; 2733e12c5d1SDavid du Colombier case Twstat: 2743e12c5d1SDavid du Colombier rwstat(mf); 2753e12c5d1SDavid du Colombier break; 2763e12c5d1SDavid du Colombier } 2773e12c5d1SDavid du Colombier /* 2783e12c5d1SDavid du Colombier * slave processes die after replying 2793e12c5d1SDavid du Colombier */ 2803e12c5d1SDavid du Colombier if(req.isslave) 2813e12c5d1SDavid du Colombier _exits(0); 2823e12c5d1SDavid du Colombier goto loop; 2833e12c5d1SDavid du Colombier } 2843e12c5d1SDavid du Colombier 2853e12c5d1SDavid du Colombier void 286*219b2ee8SDavid du Colombier rsession(void) 287*219b2ee8SDavid du Colombier { 288*219b2ee8SDavid du Colombier memset(thp->authid, 0, sizeof(thp->authid)); 289*219b2ee8SDavid du Colombier memset(thp->authdom, 0, sizeof(thp->authdom)); 290*219b2ee8SDavid du Colombier memset(thp->chal, 0, sizeof(thp->chal)); 291*219b2ee8SDavid du Colombier sendmsg(0); 292*219b2ee8SDavid du Colombier } 293*219b2ee8SDavid du Colombier 294*219b2ee8SDavid du Colombier void 2953e12c5d1SDavid du Colombier rsimple(void) 2963e12c5d1SDavid du Colombier { 2973e12c5d1SDavid du Colombier sendmsg(0); 2983e12c5d1SDavid du Colombier } 2993e12c5d1SDavid du Colombier 3003e12c5d1SDavid du Colombier void 3013e12c5d1SDavid du Colombier rflush(int tag) 3023e12c5d1SDavid du Colombier { 3033e12c5d1SDavid du Colombier Mfile *mf; 3043e12c5d1SDavid du Colombier 3053e12c5d1SDavid du Colombier for(mf = mfile; mf < &mfile[nmfile]; mf++){ 3063e12c5d1SDavid du Colombier if(mf->busy == 0) 3073e12c5d1SDavid du Colombier continue; 3083e12c5d1SDavid du Colombier if(mf->tag == tag){ 3093e12c5d1SDavid du Colombier mf->tag = -1; 3103e12c5d1SDavid du Colombier break; 3113e12c5d1SDavid du Colombier } 3123e12c5d1SDavid du Colombier } 3133e12c5d1SDavid du Colombier sendmsg(0); 3143e12c5d1SDavid du Colombier } 3153e12c5d1SDavid du Colombier 3163e12c5d1SDavid du Colombier void 3173e12c5d1SDavid du Colombier rauth(void) 3183e12c5d1SDavid du Colombier { 3193e12c5d1SDavid du Colombier sendmsg("Authentication failed"); 3203e12c5d1SDavid du Colombier } 3213e12c5d1SDavid du Colombier 3223e12c5d1SDavid du Colombier void 3233e12c5d1SDavid du Colombier rattach(Mfile *mf) 3243e12c5d1SDavid du Colombier { 3253e12c5d1SDavid du Colombier if(mf->busy == 0){ 3263e12c5d1SDavid du Colombier mf->busy = 1; 3273e12c5d1SDavid du Colombier strcpy(mf->user, rhp->uname); 3283e12c5d1SDavid du Colombier } 3293e12c5d1SDavid du Colombier mf->qid.vers = vers++; 3303e12c5d1SDavid du Colombier mf->qid.path = CHDIR; 3313e12c5d1SDavid du Colombier thp->qid = mf->qid; 3323e12c5d1SDavid du Colombier sendmsg(0); 3333e12c5d1SDavid du Colombier } 3343e12c5d1SDavid du Colombier 3353e12c5d1SDavid du Colombier void 3363e12c5d1SDavid du Colombier rclone(Mfile *mf) 3373e12c5d1SDavid du Colombier { 3383e12c5d1SDavid du Colombier Mfile *nmf; 3393e12c5d1SDavid du Colombier char *err=0; 3403e12c5d1SDavid du Colombier 3413e12c5d1SDavid du Colombier if(rhp->newfid<0){ 3423e12c5d1SDavid du Colombier err = "clone nfid out of range"; 3433e12c5d1SDavid du Colombier goto send; 3443e12c5d1SDavid du Colombier } 3453e12c5d1SDavid du Colombier nmf = newfid(rhp->newfid); 3463e12c5d1SDavid du Colombier if(nmf->busy){ 3473e12c5d1SDavid du Colombier err = "clone to used channel"; 3483e12c5d1SDavid du Colombier goto send; 3493e12c5d1SDavid du Colombier } 3503e12c5d1SDavid du Colombier *nmf = *mf; 3513e12c5d1SDavid du Colombier nmf->fid = rhp->newfid; 3523e12c5d1SDavid du Colombier nmf->qid.vers = vers++; 3533e12c5d1SDavid du Colombier send: 3543e12c5d1SDavid du Colombier sendmsg(err); 3553e12c5d1SDavid du Colombier } 3563e12c5d1SDavid du Colombier 3573e12c5d1SDavid du Colombier void 3583e12c5d1SDavid du Colombier rclwalk(Mfile *mf) 3593e12c5d1SDavid du Colombier { 3603e12c5d1SDavid du Colombier Mfile *nmf; 3613e12c5d1SDavid du Colombier 3623e12c5d1SDavid du Colombier if(rhp->newfid<0){ 3633e12c5d1SDavid du Colombier sendmsg("clone nfid out of range"); 3643e12c5d1SDavid du Colombier return; 3653e12c5d1SDavid du Colombier } 3663e12c5d1SDavid du Colombier nmf = newfid(rhp->newfid); 3673e12c5d1SDavid du Colombier if(nmf->busy){ 3683e12c5d1SDavid du Colombier sendmsg("clone to used channel"); 3693e12c5d1SDavid du Colombier return; 3703e12c5d1SDavid du Colombier } 3713e12c5d1SDavid du Colombier *nmf = *mf; 3723e12c5d1SDavid du Colombier nmf->fid = rhp->newfid; 3733e12c5d1SDavid du Colombier rhp->fid = rhp->newfid; 3743e12c5d1SDavid du Colombier nmf->qid.vers = vers++; 3753e12c5d1SDavid du Colombier if(rwalk(nmf)) 3763e12c5d1SDavid du Colombier nmf->busy = 0; 3773e12c5d1SDavid du Colombier } 3783e12c5d1SDavid du Colombier 3793e12c5d1SDavid du Colombier char* 3803e12c5d1SDavid du Colombier rwalk(Mfile *mf) 3813e12c5d1SDavid du Colombier { 3823e12c5d1SDavid du Colombier char *err; 3833e12c5d1SDavid du Colombier char *name; 3843e12c5d1SDavid du Colombier 3853e12c5d1SDavid du Colombier err = 0; 3863e12c5d1SDavid du Colombier name = rhp->name; 3873e12c5d1SDavid du Colombier if((mf->qid.path & CHDIR) == 0){ 3883e12c5d1SDavid du Colombier err = "not a directory"; 3893e12c5d1SDavid du Colombier goto send; 3903e12c5d1SDavid du Colombier } 3913e12c5d1SDavid du Colombier if(strcmp(name, ".") == 0){ 3923e12c5d1SDavid du Colombier mf->qid.path = CHDIR; 3933e12c5d1SDavid du Colombier goto send; 3943e12c5d1SDavid du Colombier } 3953e12c5d1SDavid du Colombier if(strcmp(name, "dns") == 0){ 3963e12c5d1SDavid du Colombier mf->qid.path = Qdns; 3973e12c5d1SDavid du Colombier goto send; 3983e12c5d1SDavid du Colombier } 3993e12c5d1SDavid du Colombier err = "nonexistent file"; 4003e12c5d1SDavid du Colombier send: 4013e12c5d1SDavid du Colombier thp->qid = mf->qid; 4023e12c5d1SDavid du Colombier sendmsg(err); 4033e12c5d1SDavid du Colombier return err; 4043e12c5d1SDavid du Colombier } 4053e12c5d1SDavid du Colombier 4063e12c5d1SDavid du Colombier void 4073e12c5d1SDavid du Colombier ropen(Mfile *mf) 4083e12c5d1SDavid du Colombier { 4093e12c5d1SDavid du Colombier int mode; 4103e12c5d1SDavid du Colombier char *err; 4113e12c5d1SDavid du Colombier 4123e12c5d1SDavid du Colombier err = 0; 4133e12c5d1SDavid du Colombier mode = rhp->mode; 4143e12c5d1SDavid du Colombier if(mf->qid.path & CHDIR){ 4153e12c5d1SDavid du Colombier if(mode) 4163e12c5d1SDavid du Colombier err = "permission denied"; 4173e12c5d1SDavid du Colombier } 4183e12c5d1SDavid du Colombier send: 4193e12c5d1SDavid du Colombier thp->qid = mf->qid; 4203e12c5d1SDavid du Colombier sendmsg(err); 4213e12c5d1SDavid du Colombier } 4223e12c5d1SDavid du Colombier 4233e12c5d1SDavid du Colombier void 4243e12c5d1SDavid du Colombier rcreate(Mfile *mf) 4253e12c5d1SDavid du Colombier { 4263e12c5d1SDavid du Colombier USED(mf); 4273e12c5d1SDavid du Colombier sendmsg("creation permission denied"); 4283e12c5d1SDavid du Colombier } 4293e12c5d1SDavid du Colombier 4303e12c5d1SDavid du Colombier void 4313e12c5d1SDavid du Colombier rread(Mfile *mf) 4323e12c5d1SDavid du Colombier { 4333e12c5d1SDavid du Colombier int n, cnt, len; 4343e12c5d1SDavid du Colombier long toff, off, clock; 4353e12c5d1SDavid du Colombier Dir dir; 4363e12c5d1SDavid du Colombier char buf[MAXFDATA]; 4373e12c5d1SDavid du Colombier char *err; 4383e12c5d1SDavid du Colombier RR *rp; 4393e12c5d1SDavid du Colombier 4403e12c5d1SDavid du Colombier n = 0; 4413e12c5d1SDavid du Colombier err = 0; 4423e12c5d1SDavid du Colombier off = rhp->offset; 4433e12c5d1SDavid du Colombier cnt = rhp->count; 4443e12c5d1SDavid du Colombier if(mf->qid.path & CHDIR){ 4453e12c5d1SDavid du Colombier if(off%DIRLEN || cnt%DIRLEN){ 4463e12c5d1SDavid du Colombier err = "bad offset"; 4473e12c5d1SDavid du Colombier goto send; 4483e12c5d1SDavid du Colombier } 4493e12c5d1SDavid du Colombier clock = time(0); 4503e12c5d1SDavid du Colombier if(off == 0){ 4513e12c5d1SDavid du Colombier memmove(dir.name, "dns", NAMELEN); 4523e12c5d1SDavid du Colombier dir.qid.vers = vers; 4533e12c5d1SDavid du Colombier dir.qid.path = Qdns; 4543e12c5d1SDavid du Colombier dir.mode = 0666; 4553e12c5d1SDavid du Colombier dir.length = 0; 4563e12c5d1SDavid du Colombier dir.hlength = 0; 4573e12c5d1SDavid du Colombier strcpy(dir.uid, mf->user); 4583e12c5d1SDavid du Colombier strcpy(dir.gid, mf->user); 4593e12c5d1SDavid du Colombier dir.atime = clock; /* wrong */ 4603e12c5d1SDavid du Colombier dir.mtime = clock; /* wrong */ 4613e12c5d1SDavid du Colombier convD2M(&dir, buf+n); 4623e12c5d1SDavid du Colombier n += DIRLEN; 4633e12c5d1SDavid du Colombier } 4643e12c5d1SDavid du Colombier thp->data = buf; 4653e12c5d1SDavid du Colombier } else { 4663e12c5d1SDavid du Colombier toff = 0; 4673e12c5d1SDavid du Colombier n = 0; 4683e12c5d1SDavid du Colombier thp->data = buf; 469*219b2ee8SDavid du Colombier for(rp = mf->rp; rp && tsame(mf->type, rp->type); rp = rp->next){ 470bd389b36SDavid du Colombier len = snprint(buf, sizeof(buf), "%R", rp); 4713e12c5d1SDavid du Colombier if(toff + len > off){ 4723e12c5d1SDavid du Colombier toff = off - toff; 4733e12c5d1SDavid du Colombier if(cnt > len - toff) 4743e12c5d1SDavid du Colombier cnt = len - toff; 4753e12c5d1SDavid du Colombier thp->data = buf + toff; 4763e12c5d1SDavid du Colombier n = cnt; 4773e12c5d1SDavid du Colombier break; 4783e12c5d1SDavid du Colombier } 4793e12c5d1SDavid du Colombier toff += len; 4803e12c5d1SDavid du Colombier } 4813e12c5d1SDavid du Colombier } 4823e12c5d1SDavid du Colombier send: 4833e12c5d1SDavid du Colombier thp->count = n; 4843e12c5d1SDavid du Colombier sendmsg(err); 4853e12c5d1SDavid du Colombier } 4863e12c5d1SDavid du Colombier 4873e12c5d1SDavid du Colombier void 4883e12c5d1SDavid du Colombier rwrite(Mfile *mf, Request *req) 4893e12c5d1SDavid du Colombier { 4903e12c5d1SDavid du Colombier int cnt; 4913e12c5d1SDavid du Colombier char *err; 4923e12c5d1SDavid du Colombier char *atype; 4933e12c5d1SDavid du Colombier 4943e12c5d1SDavid du Colombier err = 0; 4953e12c5d1SDavid du Colombier cnt = rhp->count; 4963e12c5d1SDavid du Colombier if(mf->qid.path & CHDIR){ 4973e12c5d1SDavid du Colombier err = "can't write directory"; 4983e12c5d1SDavid du Colombier goto send; 4993e12c5d1SDavid du Colombier } 5003e12c5d1SDavid du Colombier if(cnt >= Maxrequest){ 5013e12c5d1SDavid du Colombier err = "request too long"; 5023e12c5d1SDavid du Colombier goto send; 5033e12c5d1SDavid du Colombier } 5043e12c5d1SDavid du Colombier rhp->data[cnt] = 0; 5053e12c5d1SDavid du Colombier 5063e12c5d1SDavid du Colombier /* 507*219b2ee8SDavid du Colombier * toggle debugging 508*219b2ee8SDavid du Colombier */ 509*219b2ee8SDavid du Colombier if(strncmp(rhp->data, "debug", 5)==0){ 510*219b2ee8SDavid du Colombier debug ^= 1; 511*219b2ee8SDavid du Colombier goto send; 512*219b2ee8SDavid du Colombier } else if(strncmp(rhp->data, "dump", 4)==0){ 513*219b2ee8SDavid du Colombier dndump("/lib/ndb/dnsdump"); 514*219b2ee8SDavid du Colombier goto send; 515*219b2ee8SDavid du Colombier } 516*219b2ee8SDavid du Colombier 517*219b2ee8SDavid du Colombier /* 5183e12c5d1SDavid du Colombier * break up request (into a name and a type) 5193e12c5d1SDavid du Colombier */ 5203e12c5d1SDavid du Colombier atype = strchr(rhp->data, ' '); 5213e12c5d1SDavid du Colombier if(atype == 0){ 5223e12c5d1SDavid du Colombier err = "illegal request"; 5233e12c5d1SDavid du Colombier goto send; 5243e12c5d1SDavid du Colombier } else 5253e12c5d1SDavid du Colombier *atype++ = 0; 5263e12c5d1SDavid du Colombier 5273e12c5d1SDavid du Colombier mf->type = rrtype(atype); 5283e12c5d1SDavid du Colombier if(mf->type < 0){ 5293e12c5d1SDavid du Colombier err = "unknown type"; 5303e12c5d1SDavid du Colombier goto send; 5313e12c5d1SDavid du Colombier } 5323e12c5d1SDavid du Colombier 5333e12c5d1SDavid du Colombier mf->rp = dnresolve(rhp->data, Cin, mf->type, req, 0); 5343e12c5d1SDavid du Colombier if(mf->rp == 0){ 5353e12c5d1SDavid du Colombier err = "not found"; 536*219b2ee8SDavid du Colombier } 5373e12c5d1SDavid du Colombier 5383e12c5d1SDavid du Colombier /* don't reply if the request was flushed */ 5393e12c5d1SDavid du Colombier if(mf->tag < 0) 5403e12c5d1SDavid du Colombier return; 5413e12c5d1SDavid du Colombier 5423e12c5d1SDavid du Colombier send: 5433e12c5d1SDavid du Colombier thp->count = cnt; 5443e12c5d1SDavid du Colombier sendmsg(err); 5453e12c5d1SDavid du Colombier } 5463e12c5d1SDavid du Colombier 5473e12c5d1SDavid du Colombier void 5483e12c5d1SDavid du Colombier rclunk(Mfile *mf) 5493e12c5d1SDavid du Colombier { 5503e12c5d1SDavid du Colombier if(mf->rp){ 5513e12c5d1SDavid du Colombier /* free resource records from the database */ 5523e12c5d1SDavid du Colombier if(mf->rp->db) 5533e12c5d1SDavid du Colombier rrfreelist(mf->rp); 5543e12c5d1SDavid du Colombier mf->rp = 0; 5553e12c5d1SDavid du Colombier } 5563e12c5d1SDavid du Colombier mf->busy = 0; 5573e12c5d1SDavid du Colombier mf->fid = 0; 5583e12c5d1SDavid du Colombier sendmsg(0); 5593e12c5d1SDavid du Colombier } 5603e12c5d1SDavid du Colombier 5613e12c5d1SDavid du Colombier void 5623e12c5d1SDavid du Colombier rremove(Mfile *mf) 5633e12c5d1SDavid du Colombier { 5643e12c5d1SDavid du Colombier USED(mf); 5653e12c5d1SDavid du Colombier sendmsg("remove permission denied"); 5663e12c5d1SDavid du Colombier } 5673e12c5d1SDavid du Colombier 5683e12c5d1SDavid du Colombier void 5693e12c5d1SDavid du Colombier rstat(Mfile *mf) 5703e12c5d1SDavid du Colombier { 5713e12c5d1SDavid du Colombier Dir dir; 5723e12c5d1SDavid du Colombier 573*219b2ee8SDavid du Colombier if(mf->qid.path & CHDIR){ 574*219b2ee8SDavid du Colombier strcpy(dir.name, "."); 575*219b2ee8SDavid du Colombier dir.mode = CHDIR|0555; 576*219b2ee8SDavid du Colombier } else { 577*219b2ee8SDavid du Colombier strcpy(dir.name, "dns"); 5783e12c5d1SDavid du Colombier dir.mode = 0666; 579*219b2ee8SDavid du Colombier } 580*219b2ee8SDavid du Colombier dir.qid = mf->qid; 5813e12c5d1SDavid du Colombier dir.length = 0; 5823e12c5d1SDavid du Colombier dir.hlength = 0; 5833e12c5d1SDavid du Colombier strcpy(dir.uid, mf->user); 5843e12c5d1SDavid du Colombier strcpy(dir.gid, mf->user); 5853e12c5d1SDavid du Colombier dir.atime = dir.mtime = time(0); 5863e12c5d1SDavid du Colombier convD2M(&dir, (char*)thp->stat); 5873e12c5d1SDavid du Colombier sendmsg(0); 5883e12c5d1SDavid du Colombier } 5893e12c5d1SDavid du Colombier 5903e12c5d1SDavid du Colombier void 5913e12c5d1SDavid du Colombier rwstat(Mfile *mf) 5923e12c5d1SDavid du Colombier { 5933e12c5d1SDavid du Colombier USED(mf); 5943e12c5d1SDavid du Colombier sendmsg("wstat permission denied"); 5953e12c5d1SDavid du Colombier } 5963e12c5d1SDavid du Colombier 5973e12c5d1SDavid du Colombier void 5983e12c5d1SDavid du Colombier sendmsg(char *err) 5993e12c5d1SDavid du Colombier { 6003e12c5d1SDavid du Colombier int n; 6013e12c5d1SDavid du Colombier char mdata[MAXFDATA + MAXMSG]; 6023e12c5d1SDavid du Colombier 6033e12c5d1SDavid du Colombier if(err){ 6043e12c5d1SDavid du Colombier thp->type = Rerror; 605bd389b36SDavid du Colombier snprint(thp->ename, sizeof(thp->ename), "dns: %s", err); 6063e12c5d1SDavid du Colombier }else{ 6073e12c5d1SDavid du Colombier thp->type = rhp->type+1; 6083e12c5d1SDavid du Colombier thp->fid = rhp->fid; 6093e12c5d1SDavid du Colombier } 6103e12c5d1SDavid du Colombier thp->tag = rhp->tag; 611*219b2ee8SDavid du Colombier if(debug) 612*219b2ee8SDavid du Colombier syslog(0, logfile, "%F", thp); 6133e12c5d1SDavid du Colombier n = convS2M(thp, mdata); 6143e12c5d1SDavid du Colombier if(write(mfd[1], mdata, n)!=n) 6153e12c5d1SDavid du Colombier fatal("mount write"); 6163e12c5d1SDavid du Colombier } 6173e12c5d1SDavid du Colombier 6183e12c5d1SDavid du Colombier int 6193e12c5d1SDavid du Colombier mygetfields(char *lp, char **fields, int n, char sep) 6203e12c5d1SDavid du Colombier { 6213e12c5d1SDavid du Colombier int i; 6223e12c5d1SDavid du Colombier char sep2=0; 6233e12c5d1SDavid du Colombier 6243e12c5d1SDavid du Colombier if(sep == ' ') 6253e12c5d1SDavid du Colombier sep2 = '\t'; 6263e12c5d1SDavid du Colombier for(i=0; lp && *lp && i<n; i++){ 6273e12c5d1SDavid du Colombier if(*lp==sep || *lp==sep2) 6283e12c5d1SDavid du Colombier *lp++=0; 6293e12c5d1SDavid du Colombier if(*lp == 0) 6303e12c5d1SDavid du Colombier break; 6313e12c5d1SDavid du Colombier fields[i]=lp; 6323e12c5d1SDavid du Colombier while(*lp && *lp!=sep && *lp!=sep2) 6333e12c5d1SDavid du Colombier lp++; 6343e12c5d1SDavid du Colombier } 6353e12c5d1SDavid du Colombier return i; 6363e12c5d1SDavid du Colombier } 6373e12c5d1SDavid du Colombier 6383e12c5d1SDavid du Colombier void 639bd389b36SDavid du Colombier warning(char *fmt, ...) 640bd389b36SDavid du Colombier { 641bd389b36SDavid du Colombier int n; 642bd389b36SDavid du Colombier char dnserr[128]; 643bd389b36SDavid du Colombier 644bd389b36SDavid du Colombier n = doprint(dnserr, dnserr+sizeof(dnserr), fmt, &fmt+1) - dnserr; 645bd389b36SDavid du Colombier dnserr[n] = 0; 646bd389b36SDavid du Colombier syslog(1, "dns", dnserr); 647bd389b36SDavid du Colombier } 648bd389b36SDavid du Colombier 649bd389b36SDavid du Colombier void 6503e12c5d1SDavid du Colombier fatal(char *fmt, ...) 6513e12c5d1SDavid du Colombier { 6523e12c5d1SDavid du Colombier int n; 6533e12c5d1SDavid du Colombier char dnserr[128]; 6543e12c5d1SDavid du Colombier 6553e12c5d1SDavid du Colombier n = doprint(dnserr, dnserr+sizeof(dnserr), fmt, &fmt+1) - dnserr; 6563e12c5d1SDavid du Colombier dnserr[n] = 0; 6573e12c5d1SDavid du Colombier syslog(1, "dns", dnserr); 6583e12c5d1SDavid du Colombier abort(); 6593e12c5d1SDavid du Colombier } 6603e12c5d1SDavid du Colombier 6613e12c5d1SDavid du Colombier /* 6623e12c5d1SDavid du Colombier * create a slave process to handle a request to avoid one request blocking 6633e12c5d1SDavid du Colombier * another 6643e12c5d1SDavid du Colombier */ 6653e12c5d1SDavid du Colombier void 6663e12c5d1SDavid du Colombier slave(Request *req) 6673e12c5d1SDavid du Colombier { 6683e12c5d1SDavid du Colombier if(req->isslave) 6693e12c5d1SDavid du Colombier return; /* we're already a slave process */ 6703e12c5d1SDavid du Colombier 6713e12c5d1SDavid du Colombier switch(rfork(RFPROC|RFNOTEG|RFMEM|RFNOWAIT)){ 6723e12c5d1SDavid du Colombier case -1: 6733e12c5d1SDavid du Colombier break; 6743e12c5d1SDavid du Colombier case 0: 6753e12c5d1SDavid du Colombier req->isslave = 1; 6763e12c5d1SDavid du Colombier break; 6773e12c5d1SDavid du Colombier default: 6783e12c5d1SDavid du Colombier longjmp(req->mret, 1); 6793e12c5d1SDavid du Colombier } 6803e12c5d1SDavid du Colombier } 681