13e12c5d1SDavid du Colombier #include <u.h> 23e12c5d1SDavid du Colombier #include <libc.h> 3219b2ee8SDavid du Colombier #include <auth.h> 43e12c5d1SDavid du Colombier #include <fcall.h> 53e12c5d1SDavid du Colombier #include <bio.h> 63e12c5d1SDavid du Colombier #include <ctype.h> 77dd7cddfSDavid du Colombier #include <ip.h> 89a747e4fSDavid du Colombier #include <pool.h> 93e12c5d1SDavid du Colombier #include "dns.h" 103e12c5d1SDavid du Colombier 113e12c5d1SDavid du Colombier enum 123e12c5d1SDavid du Colombier { 139a747e4fSDavid du Colombier Maxrequest= 1024, 147dd7cddfSDavid du Colombier Maxreply= 512, 157dd7cddfSDavid du Colombier Maxrrr= 16, 169a747e4fSDavid du Colombier Maxfdata= 8192, 173e12c5d1SDavid du Colombier 18*4f8f669cSDavid du Colombier Defmaxage= 60*60, /* 1 hour */ 19*4f8f669cSDavid du Colombier 209a747e4fSDavid du Colombier Qdir= 0, 213e12c5d1SDavid du Colombier Qdns= 1, 223e12c5d1SDavid du Colombier }; 233e12c5d1SDavid du Colombier 243e12c5d1SDavid du Colombier typedef struct Mfile Mfile; 257dd7cddfSDavid du Colombier typedef struct Job Job; 263e12c5d1SDavid du Colombier typedef struct Network Network; 273e12c5d1SDavid du Colombier 283e12c5d1SDavid du Colombier int vers; /* incremented each clone/attach */ 293e12c5d1SDavid du Colombier 303e12c5d1SDavid du Colombier struct Mfile 313e12c5d1SDavid du Colombier { 327dd7cddfSDavid du Colombier Mfile *next; /* next free mfile */ 339a747e4fSDavid du Colombier int ref; 347dd7cddfSDavid du Colombier 359a747e4fSDavid du Colombier char *user; 363e12c5d1SDavid du Colombier Qid qid; 373e12c5d1SDavid du Colombier int fid; 383e12c5d1SDavid du Colombier 393e12c5d1SDavid du Colombier int type; /* reply type */ 407dd7cddfSDavid du Colombier char reply[Maxreply]; 417dd7cddfSDavid du Colombier ushort rr[Maxrrr]; /* offset of rr's */ 427dd7cddfSDavid du Colombier ushort nrr; /* number of rr's */ 433e12c5d1SDavid du Colombier }; 443e12c5d1SDavid du Colombier 45*4f8f669cSDavid du Colombier /* 46*4f8f669cSDavid du Colombier * active local requests 47*4f8f669cSDavid du Colombier */ 487dd7cddfSDavid du Colombier struct Job 497dd7cddfSDavid du Colombier { 507dd7cddfSDavid du Colombier Job *next; 517dd7cddfSDavid du Colombier int flushed; 527dd7cddfSDavid du Colombier Fcall request; 537dd7cddfSDavid du Colombier Fcall reply; 547dd7cddfSDavid du Colombier }; 557dd7cddfSDavid du Colombier Lock joblock; 567dd7cddfSDavid du Colombier Job *joblist; 577dd7cddfSDavid du Colombier 587dd7cddfSDavid du Colombier struct { 597dd7cddfSDavid du Colombier Lock; 607dd7cddfSDavid du Colombier Mfile *inuse; /* active mfile's */ 617dd7cddfSDavid du Colombier } mfalloc; 627dd7cddfSDavid du Colombier 63*4f8f669cSDavid du Colombier Cfg cfg; 646b0d5c8bSDavid du Colombier int debug; 65*4f8f669cSDavid du Colombier uchar ipaddr[IPaddrlen]; /* my ip address */ 66*4f8f669cSDavid du Colombier int maxage = Defmaxage; 67*4f8f669cSDavid du Colombier int mfd[2]; 68*4f8f669cSDavid du Colombier int needrefresh; 697dd7cddfSDavid du Colombier ulong now; 70*4f8f669cSDavid du Colombier int sendnotifies; 717dd7cddfSDavid du Colombier int testing; 727dd7cddfSDavid du Colombier char *trace; 73*4f8f669cSDavid du Colombier int traceactivity; 74dc5a79c1SDavid du Colombier char *zonerefreshprogram; 753e12c5d1SDavid du Colombier 76*4f8f669cSDavid du Colombier char *logfile = "dns"; /* or "dns.test" */ 776b0d5c8bSDavid du Colombier char *dbfile; 786b0d5c8bSDavid du Colombier char mntpt[Maxpath]; 79*4f8f669cSDavid du Colombier 80*4f8f669cSDavid du Colombier int fillreply(Mfile*, int); 81*4f8f669cSDavid du Colombier void freejob(Job*); 82*4f8f669cSDavid du Colombier void io(void); 83*4f8f669cSDavid du Colombier void mountinit(char*, char*); 84*4f8f669cSDavid du Colombier Job* newjob(void); 85*4f8f669cSDavid du Colombier void rattach(Job*, Mfile*); 86*4f8f669cSDavid du Colombier void rauth(Job*); 87*4f8f669cSDavid du Colombier void rclunk(Job*, Mfile*); 88*4f8f669cSDavid du Colombier void rcreate(Job*, Mfile*); 89*4f8f669cSDavid du Colombier void rflush(Job*); 90*4f8f669cSDavid du Colombier void ropen(Job*, Mfile*); 91*4f8f669cSDavid du Colombier void rread(Job*, Mfile*); 92*4f8f669cSDavid du Colombier void rremove(Job*, Mfile*); 93*4f8f669cSDavid du Colombier void rstat(Job*, Mfile*); 94*4f8f669cSDavid du Colombier void rversion(Job*); 95*4f8f669cSDavid du Colombier char* rwalk(Job*, Mfile*); 96*4f8f669cSDavid du Colombier void rwrite(Job*, Mfile*, Request*); 97*4f8f669cSDavid du Colombier void rwstat(Job*, Mfile*); 98*4f8f669cSDavid du Colombier void sendmsg(Job*, char*); 99*4f8f669cSDavid du Colombier void setext(char*, int, char*); 1006b0d5c8bSDavid du Colombier 1017dd7cddfSDavid du Colombier void 1027dd7cddfSDavid du Colombier usage(void) 1037dd7cddfSDavid du Colombier { 104*4f8f669cSDavid du Colombier fprint(2, "usage: %s [-norRst] [-a maxage] [-f ndb-file] [-N target] " 105*4f8f669cSDavid du Colombier "[-x netmtpt] [-z refreshprog]\n", argv0); 1067dd7cddfSDavid du Colombier exits("usage"); 1077dd7cddfSDavid du Colombier } 108219b2ee8SDavid du Colombier 1093e12c5d1SDavid du Colombier void 1103e12c5d1SDavid du Colombier main(int argc, char *argv[]) 1113e12c5d1SDavid du Colombier { 112*4f8f669cSDavid du Colombier char servefile[Maxpath], ext[Maxpath]; 113219b2ee8SDavid du Colombier 114*4f8f669cSDavid du Colombier setnetmtpt(mntpt, sizeof mntpt, nil); 1157dd7cddfSDavid du Colombier ext[0] = 0; 1163e12c5d1SDavid du Colombier ARGBEGIN{ 117*4f8f669cSDavid du Colombier case 'a': 118*4f8f669cSDavid du Colombier maxage = atol(EARGF(usage())); 119*4f8f669cSDavid du Colombier if (maxage <= 0) 120*4f8f669cSDavid du Colombier maxage = Defmaxage; 121*4f8f669cSDavid du Colombier break; 1223e12c5d1SDavid du Colombier case 'd': 1233e12c5d1SDavid du Colombier debug = 1; 12439734e7eSDavid du Colombier traceactivity = 1; 1253e12c5d1SDavid du Colombier break; 126219b2ee8SDavid du Colombier case 'f': 127*4f8f669cSDavid du Colombier dbfile = EARGF(usage()); 1287dd7cddfSDavid du Colombier break; 129*4f8f669cSDavid du Colombier case 'n': 130*4f8f669cSDavid du Colombier sendnotifies = 1; 131*4f8f669cSDavid du Colombier break; 132*4f8f669cSDavid du Colombier case 'N': 133*4f8f669cSDavid du Colombier target = atol(EARGF(usage())); 134*4f8f669cSDavid du Colombier if (target < 100) 135*4f8f669cSDavid du Colombier target = 100; 136*4f8f669cSDavid du Colombier break; 137*4f8f669cSDavid du Colombier case 'o': 138*4f8f669cSDavid du Colombier cfg.straddle = 1; /* straddle inside & outside networks */ 1394fafed5dSDavid du Colombier break; 1407dd7cddfSDavid du Colombier case 'r': 141*4f8f669cSDavid du Colombier cfg.resolver = 1; 142219b2ee8SDavid du Colombier break; 143b85a8364SDavid du Colombier case 'R': 144b85a8364SDavid du Colombier norecursion = 1; 145b85a8364SDavid du Colombier break; 1463e12c5d1SDavid du Colombier case 's': 147*4f8f669cSDavid du Colombier cfg.serve = 1; /* serve network */ 148*4f8f669cSDavid du Colombier cfg.cachedb = 1; 1496b0d5c8bSDavid du Colombier break; 1507dd7cddfSDavid du Colombier case 't': 1517dd7cddfSDavid du Colombier testing = 1; 1523e12c5d1SDavid du Colombier break; 153*4f8f669cSDavid du Colombier case 'x': 154*4f8f669cSDavid du Colombier setnetmtpt(mntpt, sizeof mntpt, EARGF(usage())); 155*4f8f669cSDavid du Colombier setext(ext, sizeof ext, mntpt); 1566b0d5c8bSDavid du Colombier break; 157*4f8f669cSDavid du Colombier case 'z': 158*4f8f669cSDavid du Colombier zonerefreshprogram = EARGF(usage()); 159dc5a79c1SDavid du Colombier break; 1603e12c5d1SDavid du Colombier }ARGEND 1613e12c5d1SDavid du Colombier USED(argc); 1623e12c5d1SDavid du Colombier USED(argv); 1633e12c5d1SDavid du Colombier 164*4f8f669cSDavid du Colombier if(testing) 165*4f8f669cSDavid du Colombier mainmem->flags |= POOL_NOREUSE | POOL_ANTAGONISM; 1667dd7cddfSDavid du Colombier rfork(RFREND|RFNOTEG); 1673e12c5d1SDavid du Colombier 168*4f8f669cSDavid du Colombier cfg.inside = (*mntpt == '\0' || strcmp(mntpt, "/net") == 0); 169*4f8f669cSDavid du Colombier 1707dd7cddfSDavid du Colombier /* start syslog before we fork */ 1719a747e4fSDavid du Colombier fmtinstall('F', fcallfmt); 172219b2ee8SDavid du Colombier dninit(); 1739a747e4fSDavid du Colombier if(myipaddr(ipaddr, mntpt) < 0) 1747dd7cddfSDavid du Colombier sysfatal("can't read my ip address"); 175*4f8f669cSDavid du Colombier dnslog("starting %s%sdns %s%son %I's %s", 176*4f8f669cSDavid du Colombier (cfg.straddle? "straddling ": ""), 177*4f8f669cSDavid du Colombier (cfg.cachedb? "caching ": ""), 178*4f8f669cSDavid du Colombier (cfg.serve? "udp server ": ""), 179*4f8f669cSDavid du Colombier (cfg.resolver? "resolver ": ""), ipaddr, mntpt); 1807dd7cddfSDavid du Colombier 1817dd7cddfSDavid du Colombier opendatabase(); 1827dd7cddfSDavid du Colombier 183*4f8f669cSDavid du Colombier snprint(servefile, sizeof servefile, "#s/dns%s", ext); 1847dd7cddfSDavid du Colombier unmount(servefile, mntpt); 1857dd7cddfSDavid du Colombier remove(servefile); 1867dd7cddfSDavid du Colombier mountinit(servefile, mntpt); 1877dd7cddfSDavid du Colombier 188*4f8f669cSDavid du Colombier now = time(nil); 1897dd7cddfSDavid du Colombier srand(now*getpid()); 1907dd7cddfSDavid du Colombier db2cache(1); 1917dd7cddfSDavid du Colombier 192*4f8f669cSDavid du Colombier if (cfg.straddle && !seerootns()) 193*4f8f669cSDavid du Colombier dnslog("straddle server misconfigured; can't see root name servers"); 194*4f8f669cSDavid du Colombier if(cfg.serve) 1957dd7cddfSDavid du Colombier dnudpserver(mntpt); 196dc5a79c1SDavid du Colombier if(sendnotifies) 197dc5a79c1SDavid du Colombier notifyproc(); 198dc5a79c1SDavid du Colombier 1993e12c5d1SDavid du Colombier io(); 200*4f8f669cSDavid du Colombier dnslog("io returned, exiting"); 2013e12c5d1SDavid du Colombier exits(0); 2023e12c5d1SDavid du Colombier } 2033e12c5d1SDavid du Colombier 2047dd7cddfSDavid du Colombier /* 205*4f8f669cSDavid du Colombier * if a mount point is specified, set the cs extension to be the mount point 2067dd7cddfSDavid du Colombier * with '_'s replacing '/'s 2077dd7cddfSDavid du Colombier */ 2083e12c5d1SDavid du Colombier void 2097dd7cddfSDavid du Colombier setext(char *ext, int n, char *p) 2107dd7cddfSDavid du Colombier { 2117dd7cddfSDavid du Colombier int i, c; 2127dd7cddfSDavid du Colombier 2137dd7cddfSDavid du Colombier n--; 2147dd7cddfSDavid du Colombier for(i = 0; i < n; i++){ 2157dd7cddfSDavid du Colombier c = p[i]; 2167dd7cddfSDavid du Colombier if(c == 0) 2177dd7cddfSDavid du Colombier break; 2187dd7cddfSDavid du Colombier if(c == '/') 2197dd7cddfSDavid du Colombier c = '_'; 2207dd7cddfSDavid du Colombier ext[i] = c; 2217dd7cddfSDavid du Colombier } 2227dd7cddfSDavid du Colombier ext[i] = 0; 2237dd7cddfSDavid du Colombier } 2247dd7cddfSDavid du Colombier 2257dd7cddfSDavid du Colombier void 2267dd7cddfSDavid du Colombier mountinit(char *service, char *mntpt) 2273e12c5d1SDavid du Colombier { 2283e12c5d1SDavid du Colombier int f; 2293e12c5d1SDavid du Colombier int p[2]; 2303e12c5d1SDavid du Colombier char buf[32]; 2313e12c5d1SDavid du Colombier 2323e12c5d1SDavid du Colombier if(pipe(p) < 0) 2337dd7cddfSDavid du Colombier abort(); /* "pipe failed" */; 234219b2ee8SDavid du Colombier switch(rfork(RFFDG|RFPROC|RFNAMEG)){ 2353e12c5d1SDavid du Colombier case 0: 236219b2ee8SDavid du Colombier close(p[1]); 237*4f8f669cSDavid du Colombier procsetname("main"); 2383e12c5d1SDavid du Colombier break; 2393e12c5d1SDavid du Colombier case -1: 2407dd7cddfSDavid du Colombier abort(); /* "fork failed\n" */; 2413e12c5d1SDavid du Colombier default: 242219b2ee8SDavid du Colombier close(p[0]); 243219b2ee8SDavid du Colombier 2443e12c5d1SDavid du Colombier /* 2453e12c5d1SDavid du Colombier * make a /srv/dns 2463e12c5d1SDavid du Colombier */ 2473e12c5d1SDavid du Colombier f = create(service, 1, 0666); 2483e12c5d1SDavid du Colombier if(f < 0) 2497dd7cddfSDavid du Colombier abort(); /* service */; 250*4f8f669cSDavid du Colombier snprint(buf, sizeof buf, "%d", p[1]); 2513e12c5d1SDavid du Colombier if(write(f, buf, strlen(buf)) != strlen(buf)) 2527dd7cddfSDavid du Colombier abort(); /* "write %s", service */; 2533e12c5d1SDavid du Colombier close(f); 2543e12c5d1SDavid du Colombier 2553e12c5d1SDavid du Colombier /* 2563e12c5d1SDavid du Colombier * put ourselves into the file system 2573e12c5d1SDavid du Colombier */ 2589a747e4fSDavid du Colombier if(mount(p[1], -1, mntpt, MAFTER, "") < 0) 2599a747e4fSDavid du Colombier fprint(2, "dns mount failed: %r\n"); 260219b2ee8SDavid du Colombier _exits(0); 2613e12c5d1SDavid du Colombier } 2623e12c5d1SDavid du Colombier mfd[0] = mfd[1] = p[0]; 2633e12c5d1SDavid du Colombier } 2643e12c5d1SDavid du Colombier 2653e12c5d1SDavid du Colombier Mfile* 2667dd7cddfSDavid du Colombier newfid(int fid, int needunused) 2673e12c5d1SDavid du Colombier { 2683e12c5d1SDavid du Colombier Mfile *mf; 2693e12c5d1SDavid du Colombier 2707dd7cddfSDavid du Colombier lock(&mfalloc); 271*4f8f669cSDavid du Colombier for(mf = mfalloc.inuse; mf != nil; mf = mf->next) 2727dd7cddfSDavid du Colombier if(mf->fid == fid){ 2737dd7cddfSDavid du Colombier unlock(&mfalloc); 2747dd7cddfSDavid du Colombier if(needunused) 2757dd7cddfSDavid du Colombier return nil; 2763e12c5d1SDavid du Colombier return mf; 2773e12c5d1SDavid du Colombier } 2789a747e4fSDavid du Colombier mf = emalloc(sizeof(*mf)); 2797dd7cddfSDavid du Colombier if(mf == nil) 2807dd7cddfSDavid du Colombier sysfatal("out of memory"); 2813e12c5d1SDavid du Colombier mf->fid = fid; 2827dd7cddfSDavid du Colombier mf->next = mfalloc.inuse; 2837dd7cddfSDavid du Colombier mfalloc.inuse = mf; 2847dd7cddfSDavid du Colombier unlock(&mfalloc); 2853e12c5d1SDavid du Colombier return mf; 2863e12c5d1SDavid du Colombier } 2873e12c5d1SDavid du Colombier 2883e12c5d1SDavid du Colombier void 2897dd7cddfSDavid du Colombier freefid(Mfile *mf) 2907dd7cddfSDavid du Colombier { 2917dd7cddfSDavid du Colombier Mfile **l; 2927dd7cddfSDavid du Colombier 2937dd7cddfSDavid du Colombier lock(&mfalloc); 294*4f8f669cSDavid du Colombier for(l = &mfalloc.inuse; *l != nil; l = &(*l)->next) 2957dd7cddfSDavid du Colombier if(*l == mf){ 2967dd7cddfSDavid du Colombier *l = mf->next; 2976b0d5c8bSDavid du Colombier if(mf->user) 2989a747e4fSDavid du Colombier free(mf->user); 299*4f8f669cSDavid du Colombier memset(mf, 0, sizeof *mf); /* cause trouble */ 3007dd7cddfSDavid du Colombier free(mf); 3017dd7cddfSDavid du Colombier unlock(&mfalloc); 3027dd7cddfSDavid du Colombier return; 3037dd7cddfSDavid du Colombier } 3047dd7cddfSDavid du Colombier sysfatal("freeing unused fid"); 3057dd7cddfSDavid du Colombier } 3067dd7cddfSDavid du Colombier 3077dd7cddfSDavid du Colombier Mfile* 3087dd7cddfSDavid du Colombier copyfid(Mfile *mf, int fid) 3097dd7cddfSDavid du Colombier { 3107dd7cddfSDavid du Colombier Mfile *nmf; 3117dd7cddfSDavid du Colombier 3127dd7cddfSDavid du Colombier nmf = newfid(fid, 1); 3137dd7cddfSDavid du Colombier if(nmf == nil) 3147dd7cddfSDavid du Colombier return nil; 3157dd7cddfSDavid du Colombier nmf->fid = fid; 3169a747e4fSDavid du Colombier nmf->user = estrdup(mf->user); 3179a747e4fSDavid du Colombier nmf->qid.type = mf->qid.type; 3187dd7cddfSDavid du Colombier nmf->qid.path = mf->qid.path; 3197dd7cddfSDavid du Colombier nmf->qid.vers = vers++; 3207dd7cddfSDavid du Colombier return nmf; 3217dd7cddfSDavid du Colombier } 3227dd7cddfSDavid du Colombier 3237dd7cddfSDavid du Colombier Job* 3247dd7cddfSDavid du Colombier newjob(void) 3257dd7cddfSDavid du Colombier { 3267dd7cddfSDavid du Colombier Job *job; 3277dd7cddfSDavid du Colombier 328*4f8f669cSDavid du Colombier job = emalloc(sizeof *job); 3297dd7cddfSDavid du Colombier lock(&joblock); 3307dd7cddfSDavid du Colombier job->next = joblist; 3317dd7cddfSDavid du Colombier joblist = job; 3327dd7cddfSDavid du Colombier job->request.tag = -1; 3337dd7cddfSDavid du Colombier unlock(&joblock); 3347dd7cddfSDavid du Colombier return job; 3357dd7cddfSDavid du Colombier } 3367dd7cddfSDavid du Colombier 3377dd7cddfSDavid du Colombier void 3387dd7cddfSDavid du Colombier freejob(Job *job) 3397dd7cddfSDavid du Colombier { 3407dd7cddfSDavid du Colombier Job **l; 3417dd7cddfSDavid du Colombier 3427dd7cddfSDavid du Colombier lock(&joblock); 343*4f8f669cSDavid du Colombier for(l = &joblist; *l; l = &(*l)->next) 344*4f8f669cSDavid du Colombier if(*l == job){ 3457dd7cddfSDavid du Colombier *l = job->next; 346*4f8f669cSDavid du Colombier memset(job, 0, sizeof *job); /* cause trouble */ 3477dd7cddfSDavid du Colombier free(job); 3487dd7cddfSDavid du Colombier break; 3497dd7cddfSDavid du Colombier } 3507dd7cddfSDavid du Colombier unlock(&joblock); 3517dd7cddfSDavid du Colombier } 3527dd7cddfSDavid du Colombier 3537dd7cddfSDavid du Colombier void 3547dd7cddfSDavid du Colombier flushjob(int tag) 3557dd7cddfSDavid du Colombier { 3567dd7cddfSDavid du Colombier Job *job; 3577dd7cddfSDavid du Colombier 3587dd7cddfSDavid du Colombier lock(&joblock); 359*4f8f669cSDavid du Colombier for(job = joblist; job; job = job->next) 3607dd7cddfSDavid du Colombier if(job->request.tag == tag && job->request.type != Tflush){ 3617dd7cddfSDavid du Colombier job->flushed = 1; 3627dd7cddfSDavid du Colombier break; 3637dd7cddfSDavid du Colombier } 3647dd7cddfSDavid du Colombier unlock(&joblock); 3657dd7cddfSDavid du Colombier } 3667dd7cddfSDavid du Colombier 3677dd7cddfSDavid du Colombier void 3683e12c5d1SDavid du Colombier io(void) 3693e12c5d1SDavid du Colombier { 3703e12c5d1SDavid du Colombier long n; 3713e12c5d1SDavid du Colombier Mfile *mf; 3729a747e4fSDavid du Colombier uchar mdata[IOHDRSZ + Maxfdata]; 3733e12c5d1SDavid du Colombier Request req; 3747dd7cddfSDavid du Colombier Job *job; 3753e12c5d1SDavid du Colombier 376*4f8f669cSDavid du Colombier memset(&req, 0, sizeof req); 3773e12c5d1SDavid du Colombier /* 3783e12c5d1SDavid du Colombier * a slave process is sometimes forked to wait for replies from other 3793e12c5d1SDavid du Colombier * servers. The master process returns immediately via a longjmp 380219b2ee8SDavid du Colombier * through 'mret'. 3813e12c5d1SDavid du Colombier */ 3827dd7cddfSDavid du Colombier if(setjmp(req.mret)) 383b4b9fc2fSDavid du Colombier putactivity(0); 384*4f8f669cSDavid du Colombier procsetname("main 9p reading loop"); 3853e12c5d1SDavid du Colombier req.isslave = 0; 3867dd7cddfSDavid du Colombier for(;;){ 3879a747e4fSDavid du Colombier n = read9pmsg(mfd[0], mdata, sizeof mdata); 3887dd7cddfSDavid du Colombier if(n<=0){ 389*4f8f669cSDavid du Colombier dnslog("error reading mntpt: %r"); 3907dd7cddfSDavid du Colombier exits(0); 3917dd7cddfSDavid du Colombier } 392*4f8f669cSDavid du Colombier 3937dd7cddfSDavid du Colombier job = newjob(); 3949a747e4fSDavid du Colombier if(convM2S(mdata, n, &job->request) != n){ 3957dd7cddfSDavid du Colombier freejob(job); 3967dd7cddfSDavid du Colombier continue; 3977dd7cddfSDavid du Colombier } 3987dd7cddfSDavid du Colombier mf = newfid(job->request.fid, 0); 399219b2ee8SDavid du Colombier if(debug) 400*4f8f669cSDavid du Colombier dnslog("%F", &job->request); 4017dd7cddfSDavid du Colombier 402b4b9fc2fSDavid du Colombier getactivity(&req, 0); 403*4f8f669cSDavid du Colombier req.aborttime = now + Maxreqtm; 4047dd7cddfSDavid du Colombier 4057dd7cddfSDavid du Colombier switch(job->request.type){ 4063e12c5d1SDavid du Colombier default: 407*4f8f669cSDavid du Colombier warning("unknown request type %d", job->request.type); 4083e12c5d1SDavid du Colombier break; 4099a747e4fSDavid du Colombier case Tversion: 4109a747e4fSDavid du Colombier rversion(job); 4113e12c5d1SDavid du Colombier break; 4129a747e4fSDavid du Colombier case Tauth: 4139a747e4fSDavid du Colombier rauth(job); 4143e12c5d1SDavid du Colombier break; 4153e12c5d1SDavid du Colombier case Tflush: 4167dd7cddfSDavid du Colombier rflush(job); 4173e12c5d1SDavid du Colombier break; 4183e12c5d1SDavid du Colombier case Tattach: 4197dd7cddfSDavid du Colombier rattach(job, mf); 4203e12c5d1SDavid du Colombier break; 4213e12c5d1SDavid du Colombier case Twalk: 4227dd7cddfSDavid du Colombier rwalk(job, mf); 4233e12c5d1SDavid du Colombier break; 4243e12c5d1SDavid du Colombier case Topen: 4257dd7cddfSDavid du Colombier ropen(job, mf); 4263e12c5d1SDavid du Colombier break; 4273e12c5d1SDavid du Colombier case Tcreate: 4287dd7cddfSDavid du Colombier rcreate(job, mf); 4293e12c5d1SDavid du Colombier break; 4303e12c5d1SDavid du Colombier case Tread: 4317dd7cddfSDavid du Colombier rread(job, mf); 4323e12c5d1SDavid du Colombier break; 4333e12c5d1SDavid du Colombier case Twrite: 4347dd7cddfSDavid du Colombier rwrite(job, mf, &req); 4353e12c5d1SDavid du Colombier break; 4363e12c5d1SDavid du Colombier case Tclunk: 4377dd7cddfSDavid du Colombier rclunk(job, mf); 4383e12c5d1SDavid du Colombier break; 4393e12c5d1SDavid du Colombier case Tremove: 4407dd7cddfSDavid du Colombier rremove(job, mf); 4413e12c5d1SDavid du Colombier break; 4423e12c5d1SDavid du Colombier case Tstat: 4437dd7cddfSDavid du Colombier rstat(job, mf); 4443e12c5d1SDavid du Colombier break; 4453e12c5d1SDavid du Colombier case Twstat: 4467dd7cddfSDavid du Colombier rwstat(job, mf); 4473e12c5d1SDavid du Colombier break; 4483e12c5d1SDavid du Colombier } 4497dd7cddfSDavid du Colombier 4507dd7cddfSDavid du Colombier freejob(job); 4517dd7cddfSDavid du Colombier 4523e12c5d1SDavid du Colombier /* 4533e12c5d1SDavid du Colombier * slave processes die after replying 4543e12c5d1SDavid du Colombier */ 4557dd7cddfSDavid du Colombier if(req.isslave){ 456b4b9fc2fSDavid du Colombier putactivity(0); 4573e12c5d1SDavid du Colombier _exits(0); 4587dd7cddfSDavid du Colombier } 4597dd7cddfSDavid du Colombier 460b4b9fc2fSDavid du Colombier putactivity(0); 4617dd7cddfSDavid du Colombier } 4623e12c5d1SDavid du Colombier } 4633e12c5d1SDavid du Colombier 4643e12c5d1SDavid du Colombier void 4659a747e4fSDavid du Colombier rversion(Job *job) 466219b2ee8SDavid du Colombier { 4679a747e4fSDavid du Colombier if(job->request.msize > IOHDRSZ + Maxfdata) 4689a747e4fSDavid du Colombier job->reply.msize = IOHDRSZ + Maxfdata; 4699a747e4fSDavid du Colombier else 4709a747e4fSDavid du Colombier job->reply.msize = job->request.msize; 4719a747e4fSDavid du Colombier if(strncmp(job->request.version, "9P2000", 6) != 0) 4729a747e4fSDavid du Colombier sendmsg(job, "unknown 9P version"); 4739a747e4fSDavid du Colombier else{ 4749a747e4fSDavid du Colombier job->reply.version = "9P2000"; 4757dd7cddfSDavid du Colombier sendmsg(job, 0); 476219b2ee8SDavid du Colombier } 4779a747e4fSDavid du Colombier } 478219b2ee8SDavid du Colombier 479219b2ee8SDavid du Colombier void 4809a747e4fSDavid du Colombier rauth(Job *job) 4813e12c5d1SDavid du Colombier { 4823ff48bf5SDavid du Colombier sendmsg(job, "dns: authentication not required"); 4837dd7cddfSDavid du Colombier } 4847dd7cddfSDavid du Colombier 4859a747e4fSDavid du Colombier /* 4869a747e4fSDavid du Colombier * don't flush till all the slaves are done 4879a747e4fSDavid du Colombier */ 4887dd7cddfSDavid du Colombier void 4897dd7cddfSDavid du Colombier rflush(Job *job) 4907dd7cddfSDavid du Colombier { 4917dd7cddfSDavid du Colombier flushjob(job->request.oldtag); 4927dd7cddfSDavid du Colombier sendmsg(job, 0); 4933e12c5d1SDavid du Colombier } 4943e12c5d1SDavid du Colombier 4953e12c5d1SDavid du Colombier void 4967dd7cddfSDavid du Colombier rattach(Job *job, Mfile *mf) 4973e12c5d1SDavid du Colombier { 4989a747e4fSDavid du Colombier if(mf->user != nil) 4999a747e4fSDavid du Colombier free(mf->user); 5009a747e4fSDavid du Colombier mf->user = estrdup(job->request.uname); 5013e12c5d1SDavid du Colombier mf->qid.vers = vers++; 5029a747e4fSDavid du Colombier mf->qid.type = QTDIR; 5039a747e4fSDavid du Colombier mf->qid.path = 0LL; 5047dd7cddfSDavid du Colombier job->reply.qid = mf->qid; 5057dd7cddfSDavid du Colombier sendmsg(job, 0); 5063e12c5d1SDavid du Colombier } 5073e12c5d1SDavid du Colombier 5083e12c5d1SDavid du Colombier char* 5097dd7cddfSDavid du Colombier rwalk(Job *job, Mfile *mf) 5103e12c5d1SDavid du Colombier { 511*4f8f669cSDavid du Colombier int i, nelems; 5123e12c5d1SDavid du Colombier char *err; 5139a747e4fSDavid du Colombier char **elems; 5149a747e4fSDavid du Colombier Mfile *nmf; 5159a747e4fSDavid du Colombier Qid qid; 5163e12c5d1SDavid du Colombier 5173e12c5d1SDavid du Colombier err = 0; 5189a747e4fSDavid du Colombier nmf = nil; 5199a747e4fSDavid du Colombier elems = job->request.wname; 5209a747e4fSDavid du Colombier nelems = job->request.nwname; 5219a747e4fSDavid du Colombier job->reply.nwqid = 0; 5229a747e4fSDavid du Colombier 5239a747e4fSDavid du Colombier if(job->request.newfid != job->request.fid){ 5249a747e4fSDavid du Colombier /* clone fid */ 5259a747e4fSDavid du Colombier nmf = copyfid(mf, job->request.newfid); 5269a747e4fSDavid du Colombier if(nmf == nil){ 5279a747e4fSDavid du Colombier err = "clone bad newfid"; 5289a747e4fSDavid du Colombier goto send; 5299a747e4fSDavid du Colombier } 5309a747e4fSDavid du Colombier mf = nmf; 5319a747e4fSDavid du Colombier } 5329a747e4fSDavid du Colombier /* else nmf will be nil */ 5339a747e4fSDavid du Colombier 5349a747e4fSDavid du Colombier qid = mf->qid; 535*4f8f669cSDavid du Colombier if(nelems > 0) 5369a747e4fSDavid du Colombier /* walk fid */ 5379a747e4fSDavid du Colombier for(i=0; i<nelems && i<MAXWELEM; i++){ 5389a747e4fSDavid du Colombier if((qid.type & QTDIR) == 0){ 5393e12c5d1SDavid du Colombier err = "not a directory"; 5409a747e4fSDavid du Colombier break; 5413e12c5d1SDavid du Colombier } 542*4f8f669cSDavid du Colombier if (strcmp(elems[i], "..") == 0 || 543*4f8f669cSDavid du Colombier strcmp(elems[i], ".") == 0){ 5449a747e4fSDavid du Colombier qid.type = QTDIR; 5459a747e4fSDavid du Colombier qid.path = Qdir; 5469a747e4fSDavid du Colombier Found: 5479a747e4fSDavid du Colombier job->reply.wqid[i] = qid; 5489a747e4fSDavid du Colombier job->reply.nwqid++; 5499a747e4fSDavid du Colombier continue; 5503e12c5d1SDavid du Colombier } 5519a747e4fSDavid du Colombier if(strcmp(elems[i], "dns") == 0){ 5529a747e4fSDavid du Colombier qid.type = QTFILE; 5539a747e4fSDavid du Colombier qid.path = Qdns; 5549a747e4fSDavid du Colombier goto Found; 5553e12c5d1SDavid du Colombier } 5569a747e4fSDavid du Colombier err = "file does not exist"; 5579a747e4fSDavid du Colombier break; 5589a747e4fSDavid du Colombier } 5599a747e4fSDavid du Colombier 5603e12c5d1SDavid du Colombier send: 5619a747e4fSDavid du Colombier if(nmf != nil && (err!=nil || job->reply.nwqid<nelems)) 5629a747e4fSDavid du Colombier freefid(nmf); 5639a747e4fSDavid du Colombier if(err == nil) 5649a747e4fSDavid du Colombier mf->qid = qid; 5657dd7cddfSDavid du Colombier sendmsg(job, err); 5663e12c5d1SDavid du Colombier return err; 5673e12c5d1SDavid du Colombier } 5683e12c5d1SDavid du Colombier 5693e12c5d1SDavid du Colombier void 5707dd7cddfSDavid du Colombier ropen(Job *job, Mfile *mf) 5713e12c5d1SDavid du Colombier { 5723e12c5d1SDavid du Colombier int mode; 5733e12c5d1SDavid du Colombier char *err; 5743e12c5d1SDavid du Colombier 5753e12c5d1SDavid du Colombier err = 0; 5767dd7cddfSDavid du Colombier mode = job->request.mode; 577*4f8f669cSDavid du Colombier if(mf->qid.type & QTDIR) 5783e12c5d1SDavid du Colombier if(mode) 5793e12c5d1SDavid du Colombier err = "permission denied"; 5807dd7cddfSDavid du Colombier job->reply.qid = mf->qid; 5819a747e4fSDavid du Colombier job->reply.iounit = 0; 5827dd7cddfSDavid du Colombier sendmsg(job, err); 5833e12c5d1SDavid du Colombier } 5843e12c5d1SDavid du Colombier 5853e12c5d1SDavid du Colombier void 5867dd7cddfSDavid du Colombier rcreate(Job *job, Mfile *mf) 5873e12c5d1SDavid du Colombier { 5883e12c5d1SDavid du Colombier USED(mf); 5897dd7cddfSDavid du Colombier sendmsg(job, "creation permission denied"); 5903e12c5d1SDavid du Colombier } 5913e12c5d1SDavid du Colombier 5923e12c5d1SDavid du Colombier void 5937dd7cddfSDavid du Colombier rread(Job *job, Mfile *mf) 5943e12c5d1SDavid du Colombier { 595*4f8f669cSDavid du Colombier int i, n; 5966b0d5c8bSDavid du Colombier long clock; 597*4f8f669cSDavid du Colombier ulong cnt; 598*4f8f669cSDavid du Colombier vlong off; 599*4f8f669cSDavid du Colombier char *err; 600*4f8f669cSDavid du Colombier uchar buf[Maxfdata]; 601*4f8f669cSDavid du Colombier Dir dir; 6023e12c5d1SDavid du Colombier 6033e12c5d1SDavid du Colombier n = 0; 604*4f8f669cSDavid du Colombier err = nil; 6057dd7cddfSDavid du Colombier off = job->request.offset; 6067dd7cddfSDavid du Colombier cnt = job->request.count; 607*4f8f669cSDavid du Colombier *buf = '\0'; 608*4f8f669cSDavid du Colombier job->reply.data = (char*)buf; 6099a747e4fSDavid du Colombier if(mf->qid.type & QTDIR){ 610*4f8f669cSDavid du Colombier clock = time(nil); 6113e12c5d1SDavid du Colombier if(off == 0){ 6129a747e4fSDavid du Colombier dir.name = "dns"; 6139a747e4fSDavid du Colombier dir.qid.type = QTFILE; 6143e12c5d1SDavid du Colombier dir.qid.vers = vers; 6153e12c5d1SDavid du Colombier dir.qid.path = Qdns; 6163e12c5d1SDavid du Colombier dir.mode = 0666; 6173e12c5d1SDavid du Colombier dir.length = 0; 618*4f8f669cSDavid du Colombier dir.uid = dir.gid = dir.muid = mf->user; 619*4f8f669cSDavid du Colombier dir.atime = dir.mtime = clock; /* wrong */ 6209a747e4fSDavid du Colombier n = convD2M(&dir, buf, sizeof buf); 6213e12c5d1SDavid du Colombier } 622*4f8f669cSDavid du Colombier } else if (off < 0) 623*4f8f669cSDavid du Colombier err = "negative read offset"; 624*4f8f669cSDavid du Colombier else { 625*4f8f669cSDavid du Colombier /* first offset will always be zero */ 6267dd7cddfSDavid du Colombier for(i = 1; i <= mf->nrr; i++) 6277dd7cddfSDavid du Colombier if(mf->rr[i] > off) 6283e12c5d1SDavid du Colombier break; 629*4f8f669cSDavid du Colombier if(i <= mf->nrr) { 6307dd7cddfSDavid du Colombier if(off + cnt > mf->rr[i]) 6317dd7cddfSDavid du Colombier n = mf->rr[i] - off; 6327dd7cddfSDavid du Colombier else 6337dd7cddfSDavid du Colombier n = cnt; 634*4f8f669cSDavid du Colombier assert(n >= 0); 6357dd7cddfSDavid du Colombier job->reply.data = mf->reply + off; 6363e12c5d1SDavid du Colombier } 637*4f8f669cSDavid du Colombier } 6387dd7cddfSDavid du Colombier job->reply.count = n; 6397dd7cddfSDavid du Colombier sendmsg(job, err); 6403e12c5d1SDavid du Colombier } 6413e12c5d1SDavid du Colombier 6423e12c5d1SDavid du Colombier void 6437dd7cddfSDavid du Colombier rwrite(Job *job, Mfile *mf, Request *req) 6443e12c5d1SDavid du Colombier { 645*4f8f669cSDavid du Colombier int rooted, status, wantsav; 6467dd7cddfSDavid du Colombier long n; 647*4f8f669cSDavid du Colombier ulong cnt; 6487dd7cddfSDavid du Colombier char *err, *p, *atype; 6497dd7cddfSDavid du Colombier RR *rp, *tp, *neg; 6503e12c5d1SDavid du Colombier 651*4f8f669cSDavid du Colombier err = nil; 6527dd7cddfSDavid du Colombier cnt = job->request.count; 6539a747e4fSDavid du Colombier if(mf->qid.type & QTDIR){ 6543e12c5d1SDavid du Colombier err = "can't write directory"; 6553e12c5d1SDavid du Colombier goto send; 6563e12c5d1SDavid du Colombier } 657*4f8f669cSDavid du Colombier if (job->request.offset != 0) { 658*4f8f669cSDavid du Colombier err = "writing at non-zero offset"; 659*4f8f669cSDavid du Colombier goto send; 660*4f8f669cSDavid du Colombier } 6613e12c5d1SDavid du Colombier if(cnt >= Maxrequest){ 6623e12c5d1SDavid du Colombier err = "request too long"; 6633e12c5d1SDavid du Colombier goto send; 6643e12c5d1SDavid du Colombier } 6657dd7cddfSDavid du Colombier job->request.data[cnt] = 0; 6667dd7cddfSDavid du Colombier if(cnt > 0 && job->request.data[cnt-1] == '\n') 6677dd7cddfSDavid du Colombier job->request.data[cnt-1] = 0; 6683e12c5d1SDavid du Colombier 6693e12c5d1SDavid du Colombier /* 6707dd7cddfSDavid du Colombier * special commands 671219b2ee8SDavid du Colombier */ 672*4f8f669cSDavid du Colombier if(strcmp(job->request.data, "debug")==0){ 673219b2ee8SDavid du Colombier debug ^= 1; 674219b2ee8SDavid du Colombier goto send; 675*4f8f669cSDavid du Colombier } else if(strcmp(job->request.data, "dump")==0){ 676219b2ee8SDavid du Colombier dndump("/lib/ndb/dnsdump"); 677219b2ee8SDavid du Colombier goto send; 678*4f8f669cSDavid du Colombier } else if(strcmp(job->request.data, "refresh")==0){ 6797dd7cddfSDavid du Colombier needrefresh = 1; 6807dd7cddfSDavid du Colombier goto send; 681*4f8f669cSDavid du Colombier } else if(strcmp(job->request.data, "poolcheck")==0){ 6829a747e4fSDavid du Colombier poolcheck(mainmem); 6839a747e4fSDavid du Colombier goto send; 684219b2ee8SDavid du Colombier } 685219b2ee8SDavid du Colombier 686219b2ee8SDavid du Colombier /* 6877dd7cddfSDavid du Colombier * kill previous reply 6887dd7cddfSDavid du Colombier */ 6897dd7cddfSDavid du Colombier mf->nrr = 0; 6907dd7cddfSDavid du Colombier mf->rr[0] = 0; 6917dd7cddfSDavid du Colombier 6927dd7cddfSDavid du Colombier /* 6933e12c5d1SDavid du Colombier * break up request (into a name and a type) 6943e12c5d1SDavid du Colombier */ 6957dd7cddfSDavid du Colombier atype = strchr(job->request.data, ' '); 6963e12c5d1SDavid du Colombier if(atype == 0){ 6973e12c5d1SDavid du Colombier err = "illegal request"; 6983e12c5d1SDavid du Colombier goto send; 6993e12c5d1SDavid du Colombier } else 7003e12c5d1SDavid du Colombier *atype++ = 0; 7013e12c5d1SDavid du Colombier 7027dd7cddfSDavid du Colombier /* 7037dd7cddfSDavid du Colombier * tracing request 7047dd7cddfSDavid du Colombier */ 7057dd7cddfSDavid du Colombier if(strcmp(atype, "trace") == 0){ 7067dd7cddfSDavid du Colombier if(trace) 7077dd7cddfSDavid du Colombier free(trace); 7087dd7cddfSDavid du Colombier if(*job->request.data) 7099a747e4fSDavid du Colombier trace = estrdup(job->request.data); 7107dd7cddfSDavid du Colombier else 7117dd7cddfSDavid du Colombier trace = 0; 7127dd7cddfSDavid du Colombier goto send; 7137dd7cddfSDavid du Colombier } 7147dd7cddfSDavid du Colombier 715*4f8f669cSDavid du Colombier /* normal request: domain [type] */ 7163e12c5d1SDavid du Colombier mf->type = rrtype(atype); 7173e12c5d1SDavid du Colombier if(mf->type < 0){ 7183e12c5d1SDavid du Colombier err = "unknown type"; 7193e12c5d1SDavid du Colombier goto send; 7203e12c5d1SDavid du Colombier } 7213e12c5d1SDavid du Colombier 7227dd7cddfSDavid du Colombier p = atype - 2; 7237dd7cddfSDavid du Colombier if(p >= job->request.data && *p == '.'){ 7247dd7cddfSDavid du Colombier rooted = 1; 7257dd7cddfSDavid du Colombier *p = 0; 7267dd7cddfSDavid du Colombier } else 7277dd7cddfSDavid du Colombier rooted = 0; 7283e12c5d1SDavid du Colombier 7297dd7cddfSDavid du Colombier p = job->request.data; 7307dd7cddfSDavid du Colombier if(*p == '!'){ 7317dd7cddfSDavid du Colombier wantsav = 1; 7327dd7cddfSDavid du Colombier p++; 7337dd7cddfSDavid du Colombier } else 7347dd7cddfSDavid du Colombier wantsav = 0; 735*4f8f669cSDavid du Colombier 7369a747e4fSDavid du Colombier dncheck(0, 1); 737*4f8f669cSDavid du Colombier status = 0; 7387dd7cddfSDavid du Colombier rp = dnresolve(p, Cin, mf->type, req, 0, 0, Recurse, rooted, &status); 739*4f8f669cSDavid du Colombier 7409a747e4fSDavid du Colombier dncheck(0, 1); 7417dd7cddfSDavid du Colombier neg = rrremneg(&rp); 7427dd7cddfSDavid du Colombier if(neg){ 7437dd7cddfSDavid du Colombier status = neg->negrcode; 7447dd7cddfSDavid du Colombier rrfreelist(neg); 7457dd7cddfSDavid du Colombier } 746*4f8f669cSDavid du Colombier 747*4f8f669cSDavid du Colombier if(rp == nil) 748271b8d73SDavid du Colombier switch(status){ 749271b8d73SDavid du Colombier case Rname: 7507dd7cddfSDavid du Colombier err = "name does not exist"; 751271b8d73SDavid du Colombier break; 752271b8d73SDavid du Colombier case Rserver: 753271b8d73SDavid du Colombier err = "dns failure"; 754271b8d73SDavid du Colombier break; 755271b8d73SDavid du Colombier default: 756271b8d73SDavid du Colombier err = "resource does not exist"; 757271b8d73SDavid du Colombier break; 758271b8d73SDavid du Colombier } 759*4f8f669cSDavid du Colombier else { 76034f77ae3SDavid du Colombier lock(&joblock); 76134f77ae3SDavid du Colombier if(!job->flushed){ 7627dd7cddfSDavid du Colombier /* format data to be read later */ 7637dd7cddfSDavid du Colombier n = 0; 7647dd7cddfSDavid du Colombier mf->nrr = 0; 7657dd7cddfSDavid du Colombier for(tp = rp; mf->nrr < Maxrrr-1 && n < Maxreply && tp && 7667dd7cddfSDavid du Colombier tsame(mf->type, tp->type); tp = tp->next){ 7677dd7cddfSDavid du Colombier mf->rr[mf->nrr++] = n; 7687dd7cddfSDavid du Colombier if(wantsav) 769*4f8f669cSDavid du Colombier n += snprint(mf->reply+n, Maxreply-n, 770*4f8f669cSDavid du Colombier "%Q", tp); 7717dd7cddfSDavid du Colombier else 772*4f8f669cSDavid du Colombier n += snprint(mf->reply+n, Maxreply-n, 773*4f8f669cSDavid du Colombier "%R", tp); 7747dd7cddfSDavid du Colombier } 7757dd7cddfSDavid du Colombier mf->rr[mf->nrr] = n; 77634f77ae3SDavid du Colombier } 77734f77ae3SDavid du Colombier unlock(&joblock); 7787dd7cddfSDavid du Colombier rrfreelist(rp); 7797dd7cddfSDavid du Colombier } 7803e12c5d1SDavid du Colombier send: 7819a747e4fSDavid du Colombier dncheck(0, 1); 7827dd7cddfSDavid du Colombier job->reply.count = cnt; 7837dd7cddfSDavid du Colombier sendmsg(job, err); 7843e12c5d1SDavid du Colombier } 7853e12c5d1SDavid du Colombier 7863e12c5d1SDavid du Colombier void 7877dd7cddfSDavid du Colombier rclunk(Job *job, Mfile *mf) 7883e12c5d1SDavid du Colombier { 7897dd7cddfSDavid du Colombier freefid(mf); 7907dd7cddfSDavid du Colombier sendmsg(job, 0); 7913e12c5d1SDavid du Colombier } 7923e12c5d1SDavid du Colombier 7933e12c5d1SDavid du Colombier void 7947dd7cddfSDavid du Colombier rremove(Job *job, Mfile *mf) 7953e12c5d1SDavid du Colombier { 7963e12c5d1SDavid du Colombier USED(mf); 7977dd7cddfSDavid du Colombier sendmsg(job, "remove permission denied"); 7983e12c5d1SDavid du Colombier } 7993e12c5d1SDavid du Colombier 8003e12c5d1SDavid du Colombier void 8017dd7cddfSDavid du Colombier rstat(Job *job, Mfile *mf) 8023e12c5d1SDavid du Colombier { 8033e12c5d1SDavid du Colombier Dir dir; 8049a747e4fSDavid du Colombier uchar buf[IOHDRSZ+Maxfdata]; 8053e12c5d1SDavid du Colombier 8069a747e4fSDavid du Colombier if(mf->qid.type & QTDIR){ 8079a747e4fSDavid du Colombier dir.name = "."; 8089a747e4fSDavid du Colombier dir.mode = DMDIR|0555; 809219b2ee8SDavid du Colombier } else { 8109a747e4fSDavid du Colombier dir.name = "dns"; 8113e12c5d1SDavid du Colombier dir.mode = 0666; 812219b2ee8SDavid du Colombier } 813219b2ee8SDavid du Colombier dir.qid = mf->qid; 8143e12c5d1SDavid du Colombier dir.length = 0; 815*4f8f669cSDavid du Colombier dir.uid = dir.gid = dir.muid = mf->user; 816*4f8f669cSDavid du Colombier dir.atime = dir.mtime = time(nil); 8179a747e4fSDavid du Colombier job->reply.nstat = convD2M(&dir, buf, sizeof buf); 8189a747e4fSDavid du Colombier job->reply.stat = buf; 8197dd7cddfSDavid du Colombier sendmsg(job, 0); 8203e12c5d1SDavid du Colombier } 8213e12c5d1SDavid du Colombier 8223e12c5d1SDavid du Colombier void 8237dd7cddfSDavid du Colombier rwstat(Job *job, Mfile *mf) 8243e12c5d1SDavid du Colombier { 8253e12c5d1SDavid du Colombier USED(mf); 8267dd7cddfSDavid du Colombier sendmsg(job, "wstat permission denied"); 8273e12c5d1SDavid du Colombier } 8283e12c5d1SDavid du Colombier 8293e12c5d1SDavid du Colombier void 8307dd7cddfSDavid du Colombier sendmsg(Job *job, char *err) 8313e12c5d1SDavid du Colombier { 8323e12c5d1SDavid du Colombier int n; 8339a747e4fSDavid du Colombier uchar mdata[IOHDRSZ + Maxfdata]; 8349a747e4fSDavid du Colombier char ename[ERRMAX]; 8353e12c5d1SDavid du Colombier 8363e12c5d1SDavid du Colombier if(err){ 8377dd7cddfSDavid du Colombier job->reply.type = Rerror; 838*4f8f669cSDavid du Colombier snprint(ename, sizeof ename, "dns: %s", err); 8399a747e4fSDavid du Colombier job->reply.ename = ename; 840*4f8f669cSDavid du Colombier }else 8417dd7cddfSDavid du Colombier job->reply.type = job->request.type+1; 8427dd7cddfSDavid du Colombier job->reply.tag = job->request.tag; 8439a747e4fSDavid du Colombier n = convS2M(&job->reply, mdata, sizeof mdata); 8449a747e4fSDavid du Colombier if(n == 0){ 845*4f8f669cSDavid du Colombier warning("sendmsg convS2M of %F returns 0", &job->reply); 8469a747e4fSDavid du Colombier abort(); 8473e12c5d1SDavid du Colombier } 8489a747e4fSDavid du Colombier lock(&joblock); 8499a747e4fSDavid du Colombier if(job->flushed == 0) 8509a747e4fSDavid du Colombier if(write(mfd[1], mdata, n)!=n) 8519a747e4fSDavid du Colombier sysfatal("mount write"); 8527dd7cddfSDavid du Colombier unlock(&joblock); 8539a747e4fSDavid du Colombier if(debug) 854*4f8f669cSDavid du Colombier dnslog("%F %d", &job->reply, n); 8553e12c5d1SDavid du Colombier } 8563e12c5d1SDavid du Colombier 8573e12c5d1SDavid du Colombier /* 8587dd7cddfSDavid du Colombier * the following varies between dnsdebug and dns 8593e12c5d1SDavid du Colombier */ 8603e12c5d1SDavid du Colombier void 8617dd7cddfSDavid du Colombier logreply(int id, uchar *addr, DNSmsg *mp) 8623e12c5d1SDavid du Colombier { 8637dd7cddfSDavid du Colombier RR *rp; 8643e12c5d1SDavid du Colombier 865*4f8f669cSDavid du Colombier dnslog("%d: rcvd %I flags:%s%s%s%s%s", id, addr, 8667dd7cddfSDavid du Colombier mp->flags & Fauth? " auth": "", 8677dd7cddfSDavid du Colombier mp->flags & Ftrunc? " trunc": "", 8687dd7cddfSDavid du Colombier mp->flags & Frecurse? " rd": "", 8697dd7cddfSDavid du Colombier mp->flags & Fcanrec? " ra": "", 870*4f8f669cSDavid du Colombier (mp->flags & (Fauth|Rmask)) == (Fauth|Rname)? " nx": ""); 8717dd7cddfSDavid du Colombier for(rp = mp->qd; rp != nil; rp = rp->next) 872*4f8f669cSDavid du Colombier dnslog("%d: rcvd %I qd %s", id, addr, rp->owner->name); 8737dd7cddfSDavid du Colombier for(rp = mp->an; rp != nil; rp = rp->next) 874*4f8f669cSDavid du Colombier dnslog("%d: rcvd %I an %R", id, addr, rp); 8757dd7cddfSDavid du Colombier for(rp = mp->ns; rp != nil; rp = rp->next) 876*4f8f669cSDavid du Colombier dnslog("%d: rcvd %I ns %R", id, addr, rp); 8777dd7cddfSDavid du Colombier for(rp = mp->ar; rp != nil; rp = rp->next) 878*4f8f669cSDavid du Colombier dnslog("%d: rcvd %I ar %R", id, addr, rp); 8793e12c5d1SDavid du Colombier } 8807dd7cddfSDavid du Colombier 8817dd7cddfSDavid du Colombier void 8827dd7cddfSDavid du Colombier logsend(int id, int subid, uchar *addr, char *sname, char *rname, int type) 8837dd7cddfSDavid du Colombier { 8847dd7cddfSDavid du Colombier char buf[12]; 8857dd7cddfSDavid du Colombier 886*4f8f669cSDavid du Colombier dnslog("[%d] %d.%d: sending to %I/%s %s %s", 887*4f8f669cSDavid du Colombier getpid(), id, subid, addr, sname, rname, 888*4f8f669cSDavid du Colombier rrname(type, buf, sizeof buf)); 8897dd7cddfSDavid du Colombier } 8907dd7cddfSDavid du Colombier 8917dd7cddfSDavid du Colombier RR* 8927dd7cddfSDavid du Colombier getdnsservers(int class) 8937dd7cddfSDavid du Colombier { 8947dd7cddfSDavid du Colombier return dnsservers(class); 8953e12c5d1SDavid du Colombier } 896