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, 1476783259SDavid du Colombier Maxreply= 8192, /* was 512 */ 1576783259SDavid du Colombier Maxrrr= 32, /* was 16 */ 169a747e4fSDavid du Colombier Maxfdata= 8192, 173e12c5d1SDavid du Colombier 18*f46c709fSDavid du Colombier Defmaxage= 60*60, /* default domain name max. age */ 194f8f669cSDavid 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 454f8f669cSDavid du Colombier /* 464f8f669cSDavid du Colombier * active local requests 474f8f669cSDavid 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 634f8f669cSDavid du Colombier Cfg cfg; 646b0d5c8bSDavid du Colombier int debug; 654f8f669cSDavid du Colombier uchar ipaddr[IPaddrlen]; /* my ip address */ 664f8f669cSDavid du Colombier int maxage = Defmaxage; 674f8f669cSDavid du Colombier int mfd[2]; 684f8f669cSDavid du Colombier int needrefresh; 697dd7cddfSDavid du Colombier ulong now; 70a41547ffSDavid du Colombier vlong nowns; 714f8f669cSDavid du Colombier int sendnotifies; 727dd7cddfSDavid du Colombier int testing; 737dd7cddfSDavid du Colombier char *trace; 744f8f669cSDavid du Colombier int traceactivity; 75dc5a79c1SDavid du Colombier char *zonerefreshprogram; 763e12c5d1SDavid du Colombier 774f8f669cSDavid du Colombier char *logfile = "dns"; /* or "dns.test" */ 786b0d5c8bSDavid du Colombier char *dbfile; 796b0d5c8bSDavid du Colombier char mntpt[Maxpath]; 804f8f669cSDavid du Colombier 814f8f669cSDavid du Colombier int fillreply(Mfile*, int); 824f8f669cSDavid du Colombier void freejob(Job*); 834f8f669cSDavid du Colombier void io(void); 844f8f669cSDavid du Colombier void mountinit(char*, char*); 854f8f669cSDavid du Colombier Job* newjob(void); 864f8f669cSDavid du Colombier void rattach(Job*, Mfile*); 874f8f669cSDavid du Colombier void rauth(Job*); 884f8f669cSDavid du Colombier void rclunk(Job*, Mfile*); 894f8f669cSDavid du Colombier void rcreate(Job*, Mfile*); 904f8f669cSDavid du Colombier void rflush(Job*); 914f8f669cSDavid du Colombier void ropen(Job*, Mfile*); 924f8f669cSDavid du Colombier void rread(Job*, Mfile*); 934f8f669cSDavid du Colombier void rremove(Job*, Mfile*); 944f8f669cSDavid du Colombier void rstat(Job*, Mfile*); 954f8f669cSDavid du Colombier void rversion(Job*); 964f8f669cSDavid du Colombier char* rwalk(Job*, Mfile*); 974f8f669cSDavid du Colombier void rwrite(Job*, Mfile*, Request*); 984f8f669cSDavid du Colombier void rwstat(Job*, Mfile*); 994f8f669cSDavid du Colombier void sendmsg(Job*, char*); 1004f8f669cSDavid du Colombier void setext(char*, int, char*); 1016b0d5c8bSDavid du Colombier 1027dd7cddfSDavid du Colombier void 1037dd7cddfSDavid du Colombier usage(void) 1047dd7cddfSDavid du Colombier { 105a41547ffSDavid du Colombier fprint(2, "usage: %s [-FnorRst] [-a maxage] [-f ndb-file] [-N target] " 1064f8f669cSDavid du Colombier "[-x netmtpt] [-z refreshprog]\n", argv0); 1077dd7cddfSDavid du Colombier exits("usage"); 1087dd7cddfSDavid du Colombier } 109219b2ee8SDavid du Colombier 1103e12c5d1SDavid du Colombier void 1113e12c5d1SDavid du Colombier main(int argc, char *argv[]) 1123e12c5d1SDavid du Colombier { 1134f8f669cSDavid du Colombier char servefile[Maxpath], ext[Maxpath]; 114219b2ee8SDavid du Colombier 1154f8f669cSDavid du Colombier setnetmtpt(mntpt, sizeof mntpt, nil); 1167dd7cddfSDavid du Colombier ext[0] = 0; 1173e12c5d1SDavid du Colombier ARGBEGIN{ 1184f8f669cSDavid du Colombier case 'a': 1194f8f669cSDavid du Colombier maxage = atol(EARGF(usage())); 1204f8f669cSDavid du Colombier if (maxage <= 0) 1214f8f669cSDavid du Colombier maxage = Defmaxage; 1224f8f669cSDavid du Colombier break; 1233e12c5d1SDavid du Colombier case 'd': 1243e12c5d1SDavid du Colombier debug = 1; 12539734e7eSDavid du Colombier traceactivity = 1; 1263e12c5d1SDavid du Colombier break; 127219b2ee8SDavid du Colombier case 'f': 1284f8f669cSDavid du Colombier dbfile = EARGF(usage()); 1297dd7cddfSDavid du Colombier break; 130a41547ffSDavid du Colombier case 'F': 131a41547ffSDavid du Colombier cfg.justforw = cfg.resolver = 1; 132a41547ffSDavid du Colombier break; 1334f8f669cSDavid du Colombier case 'n': 1344f8f669cSDavid du Colombier sendnotifies = 1; 1354f8f669cSDavid du Colombier break; 1364f8f669cSDavid du Colombier case 'N': 1374f8f669cSDavid du Colombier target = atol(EARGF(usage())); 138a41547ffSDavid du Colombier if (target < 1000) 139a41547ffSDavid du Colombier target = 1000; 1404f8f669cSDavid du Colombier break; 1414f8f669cSDavid du Colombier case 'o': 1424f8f669cSDavid du Colombier cfg.straddle = 1; /* straddle inside & outside networks */ 1434fafed5dSDavid du Colombier break; 1447dd7cddfSDavid du Colombier case 'r': 1454f8f669cSDavid du Colombier cfg.resolver = 1; 146219b2ee8SDavid du Colombier break; 147b85a8364SDavid du Colombier case 'R': 148b85a8364SDavid du Colombier norecursion = 1; 149b85a8364SDavid du Colombier break; 1503e12c5d1SDavid du Colombier case 's': 1514f8f669cSDavid du Colombier cfg.serve = 1; /* serve network */ 1524f8f669cSDavid du Colombier cfg.cachedb = 1; 1536b0d5c8bSDavid du Colombier break; 1547dd7cddfSDavid du Colombier case 't': 1557dd7cddfSDavid du Colombier testing = 1; 1563e12c5d1SDavid du Colombier break; 1574f8f669cSDavid du Colombier case 'x': 1584f8f669cSDavid du Colombier setnetmtpt(mntpt, sizeof mntpt, EARGF(usage())); 1594f8f669cSDavid du Colombier setext(ext, sizeof ext, mntpt); 1606b0d5c8bSDavid du Colombier break; 1614f8f669cSDavid du Colombier case 'z': 1624f8f669cSDavid du Colombier zonerefreshprogram = EARGF(usage()); 163dc5a79c1SDavid du Colombier break; 1643e12c5d1SDavid du Colombier }ARGEND 1653e12c5d1SDavid du Colombier USED(argc); 1663e12c5d1SDavid du Colombier USED(argv); 1673e12c5d1SDavid du Colombier 1684f8f669cSDavid du Colombier if(testing) 1694f8f669cSDavid du Colombier mainmem->flags |= POOL_NOREUSE | POOL_ANTAGONISM; 17076783259SDavid du Colombier // mainmem->flags |= POOL_ANTAGONISM; 1717dd7cddfSDavid du Colombier rfork(RFREND|RFNOTEG); 1723e12c5d1SDavid du Colombier 1734f8f669cSDavid du Colombier cfg.inside = (*mntpt == '\0' || strcmp(mntpt, "/net") == 0); 1744f8f669cSDavid du Colombier 1757dd7cddfSDavid du Colombier /* start syslog before we fork */ 1769a747e4fSDavid du Colombier fmtinstall('F', fcallfmt); 177219b2ee8SDavid du Colombier dninit(); 17876783259SDavid du Colombier /* this really shouldn't be fatal */ 1799a747e4fSDavid du Colombier if(myipaddr(ipaddr, mntpt) < 0) 1807dd7cddfSDavid du Colombier sysfatal("can't read my ip address"); 181a41547ffSDavid du Colombier dnslog("starting %s%sdns %s%s%son %I's %s", 1824f8f669cSDavid du Colombier (cfg.straddle? "straddling ": ""), 1834f8f669cSDavid du Colombier (cfg.cachedb? "caching ": ""), 1844f8f669cSDavid du Colombier (cfg.serve? "udp server ": ""), 185a41547ffSDavid du Colombier (cfg.justforw? "forwarding-only ": ""), 1864f8f669cSDavid du Colombier (cfg.resolver? "resolver ": ""), ipaddr, mntpt); 1877dd7cddfSDavid du Colombier 1887dd7cddfSDavid du Colombier opendatabase(); 189a41547ffSDavid du Colombier now = time(nil); /* open time files before we fork */ 190a41547ffSDavid du Colombier nowns = nsec(); 1917dd7cddfSDavid du Colombier 1924f8f669cSDavid du Colombier snprint(servefile, sizeof servefile, "#s/dns%s", ext); 1937dd7cddfSDavid du Colombier unmount(servefile, mntpt); 1947dd7cddfSDavid du Colombier remove(servefile); 195a41547ffSDavid du Colombier mountinit(servefile, mntpt); /* forks */ 1967dd7cddfSDavid du Colombier 1977dd7cddfSDavid du Colombier srand(now*getpid()); 1987dd7cddfSDavid du Colombier db2cache(1); 199a41547ffSDavid du Colombier dnagenever(); 2007dd7cddfSDavid du Colombier 2014f8f669cSDavid du Colombier if (cfg.straddle && !seerootns()) 2024f8f669cSDavid du Colombier dnslog("straddle server misconfigured; can't see root name servers"); 2034f8f669cSDavid du Colombier if(cfg.serve) 2047dd7cddfSDavid du Colombier dnudpserver(mntpt); 205dc5a79c1SDavid du Colombier if(sendnotifies) 206dc5a79c1SDavid du Colombier notifyproc(); 207dc5a79c1SDavid du Colombier 2083e12c5d1SDavid du Colombier io(); 2094f8f669cSDavid du Colombier dnslog("io returned, exiting"); 2103e12c5d1SDavid du Colombier exits(0); 2113e12c5d1SDavid du Colombier } 2123e12c5d1SDavid du Colombier 2137dd7cddfSDavid du Colombier /* 2144f8f669cSDavid du Colombier * if a mount point is specified, set the cs extension to be the mount point 2157dd7cddfSDavid du Colombier * with '_'s replacing '/'s 2167dd7cddfSDavid du Colombier */ 2173e12c5d1SDavid du Colombier void 2187dd7cddfSDavid du Colombier setext(char *ext, int n, char *p) 2197dd7cddfSDavid du Colombier { 2207dd7cddfSDavid du Colombier int i, c; 2217dd7cddfSDavid du Colombier 2227dd7cddfSDavid du Colombier n--; 2237dd7cddfSDavid du Colombier for(i = 0; i < n; i++){ 2247dd7cddfSDavid du Colombier c = p[i]; 2257dd7cddfSDavid du Colombier if(c == 0) 2267dd7cddfSDavid du Colombier break; 2277dd7cddfSDavid du Colombier if(c == '/') 2287dd7cddfSDavid du Colombier c = '_'; 2297dd7cddfSDavid du Colombier ext[i] = c; 2307dd7cddfSDavid du Colombier } 2317dd7cddfSDavid du Colombier ext[i] = 0; 2327dd7cddfSDavid du Colombier } 2337dd7cddfSDavid du Colombier 2347dd7cddfSDavid du Colombier void 2357dd7cddfSDavid du Colombier mountinit(char *service, char *mntpt) 2363e12c5d1SDavid du Colombier { 2373e12c5d1SDavid du Colombier int f; 2383e12c5d1SDavid du Colombier int p[2]; 2393e12c5d1SDavid du Colombier char buf[32]; 2403e12c5d1SDavid du Colombier 2413e12c5d1SDavid du Colombier if(pipe(p) < 0) 2427dd7cddfSDavid du Colombier abort(); /* "pipe failed" */; 243219b2ee8SDavid du Colombier switch(rfork(RFFDG|RFPROC|RFNAMEG)){ 2443e12c5d1SDavid du Colombier case 0: 245219b2ee8SDavid du Colombier close(p[1]); 2464f8f669cSDavid du Colombier procsetname("main"); 2473e12c5d1SDavid du Colombier break; 2483e12c5d1SDavid du Colombier case -1: 2497dd7cddfSDavid du Colombier abort(); /* "fork failed\n" */; 2503e12c5d1SDavid du Colombier default: 251219b2ee8SDavid du Colombier close(p[0]); 252219b2ee8SDavid du Colombier 2533e12c5d1SDavid du Colombier /* 2543e12c5d1SDavid du Colombier * make a /srv/dns 2553e12c5d1SDavid du Colombier */ 2563e12c5d1SDavid du Colombier f = create(service, 1, 0666); 2573e12c5d1SDavid du Colombier if(f < 0) 2587dd7cddfSDavid du Colombier abort(); /* service */; 2594f8f669cSDavid du Colombier snprint(buf, sizeof buf, "%d", p[1]); 2603e12c5d1SDavid du Colombier if(write(f, buf, strlen(buf)) != strlen(buf)) 2617dd7cddfSDavid du Colombier abort(); /* "write %s", service */; 2623e12c5d1SDavid du Colombier close(f); 2633e12c5d1SDavid du Colombier 2643e12c5d1SDavid du Colombier /* 2653e12c5d1SDavid du Colombier * put ourselves into the file system 2663e12c5d1SDavid du Colombier */ 2679a747e4fSDavid du Colombier if(mount(p[1], -1, mntpt, MAFTER, "") < 0) 2689a747e4fSDavid du Colombier fprint(2, "dns mount failed: %r\n"); 269219b2ee8SDavid du Colombier _exits(0); 2703e12c5d1SDavid du Colombier } 2713e12c5d1SDavid du Colombier mfd[0] = mfd[1] = p[0]; 2723e12c5d1SDavid du Colombier } 2733e12c5d1SDavid du Colombier 2743e12c5d1SDavid du Colombier Mfile* 2757dd7cddfSDavid du Colombier newfid(int fid, int needunused) 2763e12c5d1SDavid du Colombier { 2773e12c5d1SDavid du Colombier Mfile *mf; 2783e12c5d1SDavid du Colombier 2797dd7cddfSDavid du Colombier lock(&mfalloc); 2804f8f669cSDavid du Colombier for(mf = mfalloc.inuse; mf != nil; mf = mf->next) 2817dd7cddfSDavid du Colombier if(mf->fid == fid){ 2827dd7cddfSDavid du Colombier unlock(&mfalloc); 2837dd7cddfSDavid du Colombier if(needunused) 2847dd7cddfSDavid du Colombier return nil; 2853e12c5d1SDavid du Colombier return mf; 2863e12c5d1SDavid du Colombier } 2879a747e4fSDavid du Colombier mf = emalloc(sizeof(*mf)); 2887dd7cddfSDavid du Colombier if(mf == nil) 2897dd7cddfSDavid du Colombier sysfatal("out of memory"); 2903e12c5d1SDavid du Colombier mf->fid = fid; 2917dd7cddfSDavid du Colombier mf->next = mfalloc.inuse; 2927dd7cddfSDavid du Colombier mfalloc.inuse = mf; 2937dd7cddfSDavid du Colombier unlock(&mfalloc); 2943e12c5d1SDavid du Colombier return mf; 2953e12c5d1SDavid du Colombier } 2963e12c5d1SDavid du Colombier 2973e12c5d1SDavid du Colombier void 2987dd7cddfSDavid du Colombier freefid(Mfile *mf) 2997dd7cddfSDavid du Colombier { 3007dd7cddfSDavid du Colombier Mfile **l; 3017dd7cddfSDavid du Colombier 3027dd7cddfSDavid du Colombier lock(&mfalloc); 3034f8f669cSDavid du Colombier for(l = &mfalloc.inuse; *l != nil; l = &(*l)->next) 3047dd7cddfSDavid du Colombier if(*l == mf){ 3057dd7cddfSDavid du Colombier *l = mf->next; 3066b0d5c8bSDavid du Colombier if(mf->user) 3079a747e4fSDavid du Colombier free(mf->user); 3084f8f669cSDavid du Colombier memset(mf, 0, sizeof *mf); /* cause trouble */ 3097dd7cddfSDavid du Colombier free(mf); 3107dd7cddfSDavid du Colombier unlock(&mfalloc); 3117dd7cddfSDavid du Colombier return; 3127dd7cddfSDavid du Colombier } 3137dd7cddfSDavid du Colombier sysfatal("freeing unused fid"); 3147dd7cddfSDavid du Colombier } 3157dd7cddfSDavid du Colombier 3167dd7cddfSDavid du Colombier Mfile* 3177dd7cddfSDavid du Colombier copyfid(Mfile *mf, int fid) 3187dd7cddfSDavid du Colombier { 3197dd7cddfSDavid du Colombier Mfile *nmf; 3207dd7cddfSDavid du Colombier 3217dd7cddfSDavid du Colombier nmf = newfid(fid, 1); 3227dd7cddfSDavid du Colombier if(nmf == nil) 3237dd7cddfSDavid du Colombier return nil; 3247dd7cddfSDavid du Colombier nmf->fid = fid; 3259a747e4fSDavid du Colombier nmf->user = estrdup(mf->user); 3269a747e4fSDavid du Colombier nmf->qid.type = mf->qid.type; 3277dd7cddfSDavid du Colombier nmf->qid.path = mf->qid.path; 3287dd7cddfSDavid du Colombier nmf->qid.vers = vers++; 3297dd7cddfSDavid du Colombier return nmf; 3307dd7cddfSDavid du Colombier } 3317dd7cddfSDavid du Colombier 3327dd7cddfSDavid du Colombier Job* 3337dd7cddfSDavid du Colombier newjob(void) 3347dd7cddfSDavid du Colombier { 3357dd7cddfSDavid du Colombier Job *job; 3367dd7cddfSDavid du Colombier 3374f8f669cSDavid du Colombier job = emalloc(sizeof *job); 3387dd7cddfSDavid du Colombier lock(&joblock); 3397dd7cddfSDavid du Colombier job->next = joblist; 3407dd7cddfSDavid du Colombier joblist = job; 3417dd7cddfSDavid du Colombier job->request.tag = -1; 3427dd7cddfSDavid du Colombier unlock(&joblock); 3437dd7cddfSDavid du Colombier return job; 3447dd7cddfSDavid du Colombier } 3457dd7cddfSDavid du Colombier 3467dd7cddfSDavid du Colombier void 3477dd7cddfSDavid du Colombier freejob(Job *job) 3487dd7cddfSDavid du Colombier { 3497dd7cddfSDavid du Colombier Job **l; 3507dd7cddfSDavid du Colombier 3517dd7cddfSDavid du Colombier lock(&joblock); 3524f8f669cSDavid du Colombier for(l = &joblist; *l; l = &(*l)->next) 3534f8f669cSDavid du Colombier if(*l == job){ 3547dd7cddfSDavid du Colombier *l = job->next; 3554f8f669cSDavid du Colombier memset(job, 0, sizeof *job); /* cause trouble */ 3567dd7cddfSDavid du Colombier free(job); 3577dd7cddfSDavid du Colombier break; 3587dd7cddfSDavid du Colombier } 3597dd7cddfSDavid du Colombier unlock(&joblock); 3607dd7cddfSDavid du Colombier } 3617dd7cddfSDavid du Colombier 3627dd7cddfSDavid du Colombier void 3637dd7cddfSDavid du Colombier flushjob(int tag) 3647dd7cddfSDavid du Colombier { 3657dd7cddfSDavid du Colombier Job *job; 3667dd7cddfSDavid du Colombier 3677dd7cddfSDavid du Colombier lock(&joblock); 3684f8f669cSDavid du Colombier for(job = joblist; job; job = job->next) 3697dd7cddfSDavid du Colombier if(job->request.tag == tag && job->request.type != Tflush){ 3707dd7cddfSDavid du Colombier job->flushed = 1; 3717dd7cddfSDavid du Colombier break; 3727dd7cddfSDavid du Colombier } 3737dd7cddfSDavid du Colombier unlock(&joblock); 3747dd7cddfSDavid du Colombier } 3757dd7cddfSDavid du Colombier 3767dd7cddfSDavid du Colombier void 3773e12c5d1SDavid du Colombier io(void) 3783e12c5d1SDavid du Colombier { 3793e12c5d1SDavid du Colombier long n; 3803e12c5d1SDavid du Colombier Mfile *mf; 3819a747e4fSDavid du Colombier uchar mdata[IOHDRSZ + Maxfdata]; 3823e12c5d1SDavid du Colombier Request req; 3837dd7cddfSDavid du Colombier Job *job; 3843e12c5d1SDavid du Colombier 3854f8f669cSDavid du Colombier memset(&req, 0, sizeof req); 3863e12c5d1SDavid du Colombier /* 3873e12c5d1SDavid du Colombier * a slave process is sometimes forked to wait for replies from other 3883e12c5d1SDavid du Colombier * servers. The master process returns immediately via a longjmp 389219b2ee8SDavid du Colombier * through 'mret'. 3903e12c5d1SDavid du Colombier */ 3917dd7cddfSDavid du Colombier if(setjmp(req.mret)) 392b4b9fc2fSDavid du Colombier putactivity(0); 3934f8f669cSDavid du Colombier procsetname("main 9p reading loop"); 3943e12c5d1SDavid du Colombier req.isslave = 0; 3957dd7cddfSDavid du Colombier for(;;){ 3969a747e4fSDavid du Colombier n = read9pmsg(mfd[0], mdata, sizeof mdata); 3977dd7cddfSDavid du Colombier if(n<=0){ 3984f8f669cSDavid du Colombier dnslog("error reading mntpt: %r"); 3997dd7cddfSDavid du Colombier exits(0); 4007dd7cddfSDavid du Colombier } 4014f8f669cSDavid du Colombier 4027dd7cddfSDavid du Colombier job = newjob(); 4039a747e4fSDavid du Colombier if(convM2S(mdata, n, &job->request) != n){ 4047dd7cddfSDavid du Colombier freejob(job); 4057dd7cddfSDavid du Colombier continue; 4067dd7cddfSDavid du Colombier } 4077dd7cddfSDavid du Colombier mf = newfid(job->request.fid, 0); 408219b2ee8SDavid du Colombier if(debug) 4094f8f669cSDavid du Colombier dnslog("%F", &job->request); 4107dd7cddfSDavid du Colombier 411b4b9fc2fSDavid du Colombier getactivity(&req, 0); 4124f8f669cSDavid du Colombier req.aborttime = now + Maxreqtm; 413*f46c709fSDavid du Colombier req.from = "9p"; 4147dd7cddfSDavid du Colombier 4157dd7cddfSDavid du Colombier switch(job->request.type){ 4163e12c5d1SDavid du Colombier default: 4174f8f669cSDavid du Colombier warning("unknown request type %d", job->request.type); 4183e12c5d1SDavid du Colombier break; 4199a747e4fSDavid du Colombier case Tversion: 4209a747e4fSDavid du Colombier rversion(job); 4213e12c5d1SDavid du Colombier break; 4229a747e4fSDavid du Colombier case Tauth: 4239a747e4fSDavid du Colombier rauth(job); 4243e12c5d1SDavid du Colombier break; 4253e12c5d1SDavid du Colombier case Tflush: 4267dd7cddfSDavid du Colombier rflush(job); 4273e12c5d1SDavid du Colombier break; 4283e12c5d1SDavid du Colombier case Tattach: 4297dd7cddfSDavid du Colombier rattach(job, mf); 4303e12c5d1SDavid du Colombier break; 4313e12c5d1SDavid du Colombier case Twalk: 4327dd7cddfSDavid du Colombier rwalk(job, mf); 4333e12c5d1SDavid du Colombier break; 4343e12c5d1SDavid du Colombier case Topen: 4357dd7cddfSDavid du Colombier ropen(job, mf); 4363e12c5d1SDavid du Colombier break; 4373e12c5d1SDavid du Colombier case Tcreate: 4387dd7cddfSDavid du Colombier rcreate(job, mf); 4393e12c5d1SDavid du Colombier break; 4403e12c5d1SDavid du Colombier case Tread: 4417dd7cddfSDavid du Colombier rread(job, mf); 4423e12c5d1SDavid du Colombier break; 4433e12c5d1SDavid du Colombier case Twrite: 4447dd7cddfSDavid du Colombier rwrite(job, mf, &req); 4453e12c5d1SDavid du Colombier break; 4463e12c5d1SDavid du Colombier case Tclunk: 4477dd7cddfSDavid du Colombier rclunk(job, mf); 4483e12c5d1SDavid du Colombier break; 4493e12c5d1SDavid du Colombier case Tremove: 4507dd7cddfSDavid du Colombier rremove(job, mf); 4513e12c5d1SDavid du Colombier break; 4523e12c5d1SDavid du Colombier case Tstat: 4537dd7cddfSDavid du Colombier rstat(job, mf); 4543e12c5d1SDavid du Colombier break; 4553e12c5d1SDavid du Colombier case Twstat: 4567dd7cddfSDavid du Colombier rwstat(job, mf); 4573e12c5d1SDavid du Colombier break; 4583e12c5d1SDavid du Colombier } 4597dd7cddfSDavid du Colombier 4607dd7cddfSDavid du Colombier freejob(job); 4617dd7cddfSDavid du Colombier 4623e12c5d1SDavid du Colombier /* 4633e12c5d1SDavid du Colombier * slave processes die after replying 4643e12c5d1SDavid du Colombier */ 4657dd7cddfSDavid du Colombier if(req.isslave){ 466b4b9fc2fSDavid du Colombier putactivity(0); 4673e12c5d1SDavid du Colombier _exits(0); 4687dd7cddfSDavid du Colombier } 4697dd7cddfSDavid du Colombier 470b4b9fc2fSDavid du Colombier putactivity(0); 4717dd7cddfSDavid du Colombier } 4723e12c5d1SDavid du Colombier } 4733e12c5d1SDavid du Colombier 4743e12c5d1SDavid du Colombier void 4759a747e4fSDavid du Colombier rversion(Job *job) 476219b2ee8SDavid du Colombier { 4779a747e4fSDavid du Colombier if(job->request.msize > IOHDRSZ + Maxfdata) 4789a747e4fSDavid du Colombier job->reply.msize = IOHDRSZ + Maxfdata; 4799a747e4fSDavid du Colombier else 4809a747e4fSDavid du Colombier job->reply.msize = job->request.msize; 4819a747e4fSDavid du Colombier if(strncmp(job->request.version, "9P2000", 6) != 0) 4829a747e4fSDavid du Colombier sendmsg(job, "unknown 9P version"); 4839a747e4fSDavid du Colombier else{ 4849a747e4fSDavid du Colombier job->reply.version = "9P2000"; 4857dd7cddfSDavid du Colombier sendmsg(job, 0); 486219b2ee8SDavid du Colombier } 4879a747e4fSDavid du Colombier } 488219b2ee8SDavid du Colombier 489219b2ee8SDavid du Colombier void 4909a747e4fSDavid du Colombier rauth(Job *job) 4913e12c5d1SDavid du Colombier { 4923ff48bf5SDavid du Colombier sendmsg(job, "dns: authentication not required"); 4937dd7cddfSDavid du Colombier } 4947dd7cddfSDavid du Colombier 4959a747e4fSDavid du Colombier /* 4969a747e4fSDavid du Colombier * don't flush till all the slaves are done 4979a747e4fSDavid du Colombier */ 4987dd7cddfSDavid du Colombier void 4997dd7cddfSDavid du Colombier rflush(Job *job) 5007dd7cddfSDavid du Colombier { 5017dd7cddfSDavid du Colombier flushjob(job->request.oldtag); 5027dd7cddfSDavid du Colombier sendmsg(job, 0); 5033e12c5d1SDavid du Colombier } 5043e12c5d1SDavid du Colombier 5053e12c5d1SDavid du Colombier void 5067dd7cddfSDavid du Colombier rattach(Job *job, Mfile *mf) 5073e12c5d1SDavid du Colombier { 5089a747e4fSDavid du Colombier if(mf->user != nil) 5099a747e4fSDavid du Colombier free(mf->user); 5109a747e4fSDavid du Colombier mf->user = estrdup(job->request.uname); 5113e12c5d1SDavid du Colombier mf->qid.vers = vers++; 5129a747e4fSDavid du Colombier mf->qid.type = QTDIR; 5139a747e4fSDavid du Colombier mf->qid.path = 0LL; 5147dd7cddfSDavid du Colombier job->reply.qid = mf->qid; 5157dd7cddfSDavid du Colombier sendmsg(job, 0); 5163e12c5d1SDavid du Colombier } 5173e12c5d1SDavid du Colombier 5183e12c5d1SDavid du Colombier char* 5197dd7cddfSDavid du Colombier rwalk(Job *job, Mfile *mf) 5203e12c5d1SDavid du Colombier { 5214f8f669cSDavid du Colombier int i, nelems; 5223e12c5d1SDavid du Colombier char *err; 5239a747e4fSDavid du Colombier char **elems; 5249a747e4fSDavid du Colombier Mfile *nmf; 5259a747e4fSDavid du Colombier Qid qid; 5263e12c5d1SDavid du Colombier 5273e12c5d1SDavid du Colombier err = 0; 5289a747e4fSDavid du Colombier nmf = nil; 5299a747e4fSDavid du Colombier elems = job->request.wname; 5309a747e4fSDavid du Colombier nelems = job->request.nwname; 5319a747e4fSDavid du Colombier job->reply.nwqid = 0; 5329a747e4fSDavid du Colombier 5339a747e4fSDavid du Colombier if(job->request.newfid != job->request.fid){ 5349a747e4fSDavid du Colombier /* clone fid */ 5359a747e4fSDavid du Colombier nmf = copyfid(mf, job->request.newfid); 5369a747e4fSDavid du Colombier if(nmf == nil){ 5379a747e4fSDavid du Colombier err = "clone bad newfid"; 5389a747e4fSDavid du Colombier goto send; 5399a747e4fSDavid du Colombier } 5409a747e4fSDavid du Colombier mf = nmf; 5419a747e4fSDavid du Colombier } 5429a747e4fSDavid du Colombier /* else nmf will be nil */ 5439a747e4fSDavid du Colombier 5449a747e4fSDavid du Colombier qid = mf->qid; 5454f8f669cSDavid du Colombier if(nelems > 0) 5469a747e4fSDavid du Colombier /* walk fid */ 5479a747e4fSDavid du Colombier for(i=0; i<nelems && i<MAXWELEM; i++){ 5489a747e4fSDavid du Colombier if((qid.type & QTDIR) == 0){ 5493e12c5d1SDavid du Colombier err = "not a directory"; 5509a747e4fSDavid du Colombier break; 5513e12c5d1SDavid du Colombier } 5524f8f669cSDavid du Colombier if (strcmp(elems[i], "..") == 0 || 5534f8f669cSDavid du Colombier strcmp(elems[i], ".") == 0){ 5549a747e4fSDavid du Colombier qid.type = QTDIR; 5559a747e4fSDavid du Colombier qid.path = Qdir; 5569a747e4fSDavid du Colombier Found: 5579a747e4fSDavid du Colombier job->reply.wqid[i] = qid; 5589a747e4fSDavid du Colombier job->reply.nwqid++; 5599a747e4fSDavid du Colombier continue; 5603e12c5d1SDavid du Colombier } 5619a747e4fSDavid du Colombier if(strcmp(elems[i], "dns") == 0){ 5629a747e4fSDavid du Colombier qid.type = QTFILE; 5639a747e4fSDavid du Colombier qid.path = Qdns; 5649a747e4fSDavid du Colombier goto Found; 5653e12c5d1SDavid du Colombier } 5669a747e4fSDavid du Colombier err = "file does not exist"; 5679a747e4fSDavid du Colombier break; 5689a747e4fSDavid du Colombier } 5699a747e4fSDavid du Colombier 5703e12c5d1SDavid du Colombier send: 5719a747e4fSDavid du Colombier if(nmf != nil && (err!=nil || job->reply.nwqid<nelems)) 5729a747e4fSDavid du Colombier freefid(nmf); 5739a747e4fSDavid du Colombier if(err == nil) 5749a747e4fSDavid du Colombier mf->qid = qid; 5757dd7cddfSDavid du Colombier sendmsg(job, err); 5763e12c5d1SDavid du Colombier return err; 5773e12c5d1SDavid du Colombier } 5783e12c5d1SDavid du Colombier 5793e12c5d1SDavid du Colombier void 5807dd7cddfSDavid du Colombier ropen(Job *job, Mfile *mf) 5813e12c5d1SDavid du Colombier { 5823e12c5d1SDavid du Colombier int mode; 5833e12c5d1SDavid du Colombier char *err; 5843e12c5d1SDavid du Colombier 5853e12c5d1SDavid du Colombier err = 0; 5867dd7cddfSDavid du Colombier mode = job->request.mode; 5874f8f669cSDavid du Colombier if(mf->qid.type & QTDIR) 5883e12c5d1SDavid du Colombier if(mode) 5893e12c5d1SDavid du Colombier err = "permission denied"; 5907dd7cddfSDavid du Colombier job->reply.qid = mf->qid; 5919a747e4fSDavid du Colombier job->reply.iounit = 0; 5927dd7cddfSDavid du Colombier sendmsg(job, err); 5933e12c5d1SDavid du Colombier } 5943e12c5d1SDavid du Colombier 5953e12c5d1SDavid du Colombier void 5967dd7cddfSDavid du Colombier rcreate(Job *job, Mfile *mf) 5973e12c5d1SDavid du Colombier { 5983e12c5d1SDavid du Colombier USED(mf); 5997dd7cddfSDavid du Colombier sendmsg(job, "creation permission denied"); 6003e12c5d1SDavid du Colombier } 6013e12c5d1SDavid du Colombier 6023e12c5d1SDavid du Colombier void 6037dd7cddfSDavid du Colombier rread(Job *job, Mfile *mf) 6043e12c5d1SDavid du Colombier { 6054f8f669cSDavid du Colombier int i, n; 6066b0d5c8bSDavid du Colombier long clock; 6074f8f669cSDavid du Colombier ulong cnt; 6084f8f669cSDavid du Colombier vlong off; 6094f8f669cSDavid du Colombier char *err; 6104f8f669cSDavid du Colombier uchar buf[Maxfdata]; 6114f8f669cSDavid du Colombier Dir dir; 6123e12c5d1SDavid du Colombier 6133e12c5d1SDavid du Colombier n = 0; 6144f8f669cSDavid du Colombier err = nil; 6157dd7cddfSDavid du Colombier off = job->request.offset; 6167dd7cddfSDavid du Colombier cnt = job->request.count; 6174f8f669cSDavid du Colombier *buf = '\0'; 6184f8f669cSDavid du Colombier job->reply.data = (char*)buf; 6199a747e4fSDavid du Colombier if(mf->qid.type & QTDIR){ 6204f8f669cSDavid du Colombier clock = time(nil); 6213e12c5d1SDavid du Colombier if(off == 0){ 6229a747e4fSDavid du Colombier dir.name = "dns"; 6239a747e4fSDavid du Colombier dir.qid.type = QTFILE; 6243e12c5d1SDavid du Colombier dir.qid.vers = vers; 6253e12c5d1SDavid du Colombier dir.qid.path = Qdns; 6263e12c5d1SDavid du Colombier dir.mode = 0666; 6273e12c5d1SDavid du Colombier dir.length = 0; 6284f8f669cSDavid du Colombier dir.uid = dir.gid = dir.muid = mf->user; 6294f8f669cSDavid du Colombier dir.atime = dir.mtime = clock; /* wrong */ 6309a747e4fSDavid du Colombier n = convD2M(&dir, buf, sizeof buf); 6313e12c5d1SDavid du Colombier } 6324f8f669cSDavid du Colombier } else if (off < 0) 6334f8f669cSDavid du Colombier err = "negative read offset"; 6344f8f669cSDavid du Colombier else { 6354f8f669cSDavid du Colombier /* first offset will always be zero */ 6367dd7cddfSDavid du Colombier for(i = 1; i <= mf->nrr; i++) 6377dd7cddfSDavid du Colombier if(mf->rr[i] > off) 6383e12c5d1SDavid du Colombier break; 6394f8f669cSDavid du Colombier if(i <= mf->nrr) { 6407dd7cddfSDavid du Colombier if(off + cnt > mf->rr[i]) 6417dd7cddfSDavid du Colombier n = mf->rr[i] - off; 6427dd7cddfSDavid du Colombier else 6437dd7cddfSDavid du Colombier n = cnt; 6444f8f669cSDavid du Colombier assert(n >= 0); 6457dd7cddfSDavid du Colombier job->reply.data = mf->reply + off; 6463e12c5d1SDavid du Colombier } 6474f8f669cSDavid du Colombier } 6487dd7cddfSDavid du Colombier job->reply.count = n; 6497dd7cddfSDavid du Colombier sendmsg(job, err); 6503e12c5d1SDavid du Colombier } 6513e12c5d1SDavid du Colombier 6523e12c5d1SDavid du Colombier void 6537dd7cddfSDavid du Colombier rwrite(Job *job, Mfile *mf, Request *req) 6543e12c5d1SDavid du Colombier { 6554f8f669cSDavid du Colombier int rooted, status, wantsav; 6567dd7cddfSDavid du Colombier long n; 6574f8f669cSDavid du Colombier ulong cnt; 6587dd7cddfSDavid du Colombier char *err, *p, *atype; 6597dd7cddfSDavid du Colombier RR *rp, *tp, *neg; 6603e12c5d1SDavid du Colombier 6614f8f669cSDavid du Colombier err = nil; 6627dd7cddfSDavid du Colombier cnt = job->request.count; 6639a747e4fSDavid du Colombier if(mf->qid.type & QTDIR){ 6643e12c5d1SDavid du Colombier err = "can't write directory"; 6653e12c5d1SDavid du Colombier goto send; 6663e12c5d1SDavid du Colombier } 6674f8f669cSDavid du Colombier if (job->request.offset != 0) { 6684f8f669cSDavid du Colombier err = "writing at non-zero offset"; 6694f8f669cSDavid du Colombier goto send; 6704f8f669cSDavid du Colombier } 6713e12c5d1SDavid du Colombier if(cnt >= Maxrequest){ 6723e12c5d1SDavid du Colombier err = "request too long"; 6733e12c5d1SDavid du Colombier goto send; 6743e12c5d1SDavid du Colombier } 6757dd7cddfSDavid du Colombier job->request.data[cnt] = 0; 6767dd7cddfSDavid du Colombier if(cnt > 0 && job->request.data[cnt-1] == '\n') 6777dd7cddfSDavid du Colombier job->request.data[cnt-1] = 0; 6783e12c5d1SDavid du Colombier 6793e12c5d1SDavid du Colombier /* 6807dd7cddfSDavid du Colombier * special commands 681219b2ee8SDavid du Colombier */ 6824f8f669cSDavid du Colombier if(strcmp(job->request.data, "debug")==0){ 683219b2ee8SDavid du Colombier debug ^= 1; 684219b2ee8SDavid du Colombier goto send; 6854f8f669cSDavid du Colombier } else if(strcmp(job->request.data, "dump")==0){ 686219b2ee8SDavid du Colombier dndump("/lib/ndb/dnsdump"); 687219b2ee8SDavid du Colombier goto send; 6884f8f669cSDavid du Colombier } else if(strcmp(job->request.data, "refresh")==0){ 6897dd7cddfSDavid du Colombier needrefresh = 1; 6907dd7cddfSDavid du Colombier goto send; 6914f8f669cSDavid du Colombier } else if(strcmp(job->request.data, "poolcheck")==0){ 6929a747e4fSDavid du Colombier poolcheck(mainmem); 6939a747e4fSDavid du Colombier goto send; 694219b2ee8SDavid du Colombier } 695219b2ee8SDavid du Colombier 696219b2ee8SDavid du Colombier /* 6977dd7cddfSDavid du Colombier * kill previous reply 6987dd7cddfSDavid du Colombier */ 6997dd7cddfSDavid du Colombier mf->nrr = 0; 7007dd7cddfSDavid du Colombier mf->rr[0] = 0; 7017dd7cddfSDavid du Colombier 7027dd7cddfSDavid du Colombier /* 7033e12c5d1SDavid du Colombier * break up request (into a name and a type) 7043e12c5d1SDavid du Colombier */ 7057dd7cddfSDavid du Colombier atype = strchr(job->request.data, ' '); 7063e12c5d1SDavid du Colombier if(atype == 0){ 7073e12c5d1SDavid du Colombier err = "illegal request"; 7083e12c5d1SDavid du Colombier goto send; 7093e12c5d1SDavid du Colombier } else 7103e12c5d1SDavid du Colombier *atype++ = 0; 7113e12c5d1SDavid du Colombier 7127dd7cddfSDavid du Colombier /* 7137dd7cddfSDavid du Colombier * tracing request 7147dd7cddfSDavid du Colombier */ 7157dd7cddfSDavid du Colombier if(strcmp(atype, "trace") == 0){ 7167dd7cddfSDavid du Colombier if(trace) 7177dd7cddfSDavid du Colombier free(trace); 7187dd7cddfSDavid du Colombier if(*job->request.data) 7199a747e4fSDavid du Colombier trace = estrdup(job->request.data); 7207dd7cddfSDavid du Colombier else 7217dd7cddfSDavid du Colombier trace = 0; 7227dd7cddfSDavid du Colombier goto send; 7237dd7cddfSDavid du Colombier } 7247dd7cddfSDavid du Colombier 7254f8f669cSDavid du Colombier /* normal request: domain [type] */ 726a41547ffSDavid du Colombier stats.qrecvd9p++; 7273e12c5d1SDavid du Colombier mf->type = rrtype(atype); 7283e12c5d1SDavid du Colombier if(mf->type < 0){ 7293e12c5d1SDavid du Colombier err = "unknown type"; 7303e12c5d1SDavid du Colombier goto send; 7313e12c5d1SDavid du Colombier } 7323e12c5d1SDavid du Colombier 7337dd7cddfSDavid du Colombier p = atype - 2; 7347dd7cddfSDavid du Colombier if(p >= job->request.data && *p == '.'){ 7357dd7cddfSDavid du Colombier rooted = 1; 7367dd7cddfSDavid du Colombier *p = 0; 7377dd7cddfSDavid du Colombier } else 7387dd7cddfSDavid du Colombier rooted = 0; 7393e12c5d1SDavid du Colombier 7407dd7cddfSDavid du Colombier p = job->request.data; 7417dd7cddfSDavid du Colombier if(*p == '!'){ 7427dd7cddfSDavid du Colombier wantsav = 1; 7437dd7cddfSDavid du Colombier p++; 7447dd7cddfSDavid du Colombier } else 7457dd7cddfSDavid du Colombier wantsav = 0; 7464f8f669cSDavid du Colombier 7479a747e4fSDavid du Colombier dncheck(0, 1); 7484f8f669cSDavid du Colombier status = 0; 7497dd7cddfSDavid du Colombier rp = dnresolve(p, Cin, mf->type, req, 0, 0, Recurse, rooted, &status); 7504f8f669cSDavid du Colombier 7519a747e4fSDavid du Colombier dncheck(0, 1); 7527dd7cddfSDavid du Colombier neg = rrremneg(&rp); 7537dd7cddfSDavid du Colombier if(neg){ 7547dd7cddfSDavid du Colombier status = neg->negrcode; 7557dd7cddfSDavid du Colombier rrfreelist(neg); 7567dd7cddfSDavid du Colombier } 7574f8f669cSDavid du Colombier 7584f8f669cSDavid du Colombier if(rp == nil) 759271b8d73SDavid du Colombier switch(status){ 760271b8d73SDavid du Colombier case Rname: 7617dd7cddfSDavid du Colombier err = "name does not exist"; 762271b8d73SDavid du Colombier break; 763271b8d73SDavid du Colombier case Rserver: 764271b8d73SDavid du Colombier err = "dns failure"; 765271b8d73SDavid du Colombier break; 766271b8d73SDavid du Colombier default: 767271b8d73SDavid du Colombier err = "resource does not exist"; 768271b8d73SDavid du Colombier break; 769271b8d73SDavid du Colombier } 7704f8f669cSDavid du Colombier else { 77134f77ae3SDavid du Colombier lock(&joblock); 77234f77ae3SDavid du Colombier if(!job->flushed){ 7737dd7cddfSDavid du Colombier /* format data to be read later */ 7747dd7cddfSDavid du Colombier n = 0; 7757dd7cddfSDavid du Colombier mf->nrr = 0; 7767dd7cddfSDavid du Colombier for(tp = rp; mf->nrr < Maxrrr-1 && n < Maxreply && tp && 7777dd7cddfSDavid du Colombier tsame(mf->type, tp->type); tp = tp->next){ 7787dd7cddfSDavid du Colombier mf->rr[mf->nrr++] = n; 7797dd7cddfSDavid du Colombier if(wantsav) 7804f8f669cSDavid du Colombier n += snprint(mf->reply+n, Maxreply-n, 7814f8f669cSDavid du Colombier "%Q", tp); 7827dd7cddfSDavid du Colombier else 7834f8f669cSDavid du Colombier n += snprint(mf->reply+n, Maxreply-n, 7844f8f669cSDavid du Colombier "%R", tp); 7857dd7cddfSDavid du Colombier } 7867dd7cddfSDavid du Colombier mf->rr[mf->nrr] = n; 78734f77ae3SDavid du Colombier } 78834f77ae3SDavid du Colombier unlock(&joblock); 7897dd7cddfSDavid du Colombier rrfreelist(rp); 7907dd7cddfSDavid du Colombier } 7913e12c5d1SDavid du Colombier send: 7929a747e4fSDavid du Colombier dncheck(0, 1); 7937dd7cddfSDavid du Colombier job->reply.count = cnt; 7947dd7cddfSDavid du Colombier sendmsg(job, err); 7953e12c5d1SDavid du Colombier } 7963e12c5d1SDavid du Colombier 7973e12c5d1SDavid du Colombier void 7987dd7cddfSDavid du Colombier rclunk(Job *job, Mfile *mf) 7993e12c5d1SDavid du Colombier { 8007dd7cddfSDavid du Colombier freefid(mf); 8017dd7cddfSDavid du Colombier sendmsg(job, 0); 8023e12c5d1SDavid du Colombier } 8033e12c5d1SDavid du Colombier 8043e12c5d1SDavid du Colombier void 8057dd7cddfSDavid du Colombier rremove(Job *job, Mfile *mf) 8063e12c5d1SDavid du Colombier { 8073e12c5d1SDavid du Colombier USED(mf); 8087dd7cddfSDavid du Colombier sendmsg(job, "remove permission denied"); 8093e12c5d1SDavid du Colombier } 8103e12c5d1SDavid du Colombier 8113e12c5d1SDavid du Colombier void 8127dd7cddfSDavid du Colombier rstat(Job *job, Mfile *mf) 8133e12c5d1SDavid du Colombier { 8143e12c5d1SDavid du Colombier Dir dir; 8159a747e4fSDavid du Colombier uchar buf[IOHDRSZ+Maxfdata]; 8163e12c5d1SDavid du Colombier 8179a747e4fSDavid du Colombier if(mf->qid.type & QTDIR){ 8189a747e4fSDavid du Colombier dir.name = "."; 8199a747e4fSDavid du Colombier dir.mode = DMDIR|0555; 820219b2ee8SDavid du Colombier } else { 8219a747e4fSDavid du Colombier dir.name = "dns"; 8223e12c5d1SDavid du Colombier dir.mode = 0666; 823219b2ee8SDavid du Colombier } 824219b2ee8SDavid du Colombier dir.qid = mf->qid; 8253e12c5d1SDavid du Colombier dir.length = 0; 8264f8f669cSDavid du Colombier dir.uid = dir.gid = dir.muid = mf->user; 8274f8f669cSDavid du Colombier dir.atime = dir.mtime = time(nil); 8289a747e4fSDavid du Colombier job->reply.nstat = convD2M(&dir, buf, sizeof buf); 8299a747e4fSDavid du Colombier job->reply.stat = buf; 8307dd7cddfSDavid du Colombier sendmsg(job, 0); 8313e12c5d1SDavid du Colombier } 8323e12c5d1SDavid du Colombier 8333e12c5d1SDavid du Colombier void 8347dd7cddfSDavid du Colombier rwstat(Job *job, Mfile *mf) 8353e12c5d1SDavid du Colombier { 8363e12c5d1SDavid du Colombier USED(mf); 8377dd7cddfSDavid du Colombier sendmsg(job, "wstat permission denied"); 8383e12c5d1SDavid du Colombier } 8393e12c5d1SDavid du Colombier 8403e12c5d1SDavid du Colombier void 8417dd7cddfSDavid du Colombier sendmsg(Job *job, char *err) 8423e12c5d1SDavid du Colombier { 8433e12c5d1SDavid du Colombier int n; 8449a747e4fSDavid du Colombier uchar mdata[IOHDRSZ + Maxfdata]; 8459a747e4fSDavid du Colombier char ename[ERRMAX]; 8463e12c5d1SDavid du Colombier 8473e12c5d1SDavid du Colombier if(err){ 8487dd7cddfSDavid du Colombier job->reply.type = Rerror; 8494f8f669cSDavid du Colombier snprint(ename, sizeof ename, "dns: %s", err); 8509a747e4fSDavid du Colombier job->reply.ename = ename; 8514f8f669cSDavid du Colombier }else 8527dd7cddfSDavid du Colombier job->reply.type = job->request.type+1; 8537dd7cddfSDavid du Colombier job->reply.tag = job->request.tag; 8549a747e4fSDavid du Colombier n = convS2M(&job->reply, mdata, sizeof mdata); 8559a747e4fSDavid du Colombier if(n == 0){ 8564f8f669cSDavid du Colombier warning("sendmsg convS2M of %F returns 0", &job->reply); 8579a747e4fSDavid du Colombier abort(); 8583e12c5d1SDavid du Colombier } 8599a747e4fSDavid du Colombier lock(&joblock); 8609a747e4fSDavid du Colombier if(job->flushed == 0) 8619a747e4fSDavid du Colombier if(write(mfd[1], mdata, n)!=n) 8629a747e4fSDavid du Colombier sysfatal("mount write"); 8637dd7cddfSDavid du Colombier unlock(&joblock); 8649a747e4fSDavid du Colombier if(debug) 8654f8f669cSDavid du Colombier dnslog("%F %d", &job->reply, n); 8663e12c5d1SDavid du Colombier } 8673e12c5d1SDavid du Colombier 8683e12c5d1SDavid du Colombier /* 8697dd7cddfSDavid du Colombier * the following varies between dnsdebug and dns 8703e12c5d1SDavid du Colombier */ 8713e12c5d1SDavid du Colombier void 8727dd7cddfSDavid du Colombier logreply(int id, uchar *addr, DNSmsg *mp) 8733e12c5d1SDavid du Colombier { 8747dd7cddfSDavid du Colombier RR *rp; 8753e12c5d1SDavid du Colombier 8764f8f669cSDavid du Colombier dnslog("%d: rcvd %I flags:%s%s%s%s%s", id, addr, 8777dd7cddfSDavid du Colombier mp->flags & Fauth? " auth": "", 8787dd7cddfSDavid du Colombier mp->flags & Ftrunc? " trunc": "", 8797dd7cddfSDavid du Colombier mp->flags & Frecurse? " rd": "", 8807dd7cddfSDavid du Colombier mp->flags & Fcanrec? " ra": "", 8814f8f669cSDavid du Colombier (mp->flags & (Fauth|Rmask)) == (Fauth|Rname)? " nx": ""); 8827dd7cddfSDavid du Colombier for(rp = mp->qd; rp != nil; rp = rp->next) 8834f8f669cSDavid du Colombier dnslog("%d: rcvd %I qd %s", id, addr, rp->owner->name); 8847dd7cddfSDavid du Colombier for(rp = mp->an; rp != nil; rp = rp->next) 8854f8f669cSDavid du Colombier dnslog("%d: rcvd %I an %R", id, addr, rp); 8867dd7cddfSDavid du Colombier for(rp = mp->ns; rp != nil; rp = rp->next) 8874f8f669cSDavid du Colombier dnslog("%d: rcvd %I ns %R", id, addr, rp); 8887dd7cddfSDavid du Colombier for(rp = mp->ar; rp != nil; rp = rp->next) 8894f8f669cSDavid du Colombier dnslog("%d: rcvd %I ar %R", id, addr, rp); 8903e12c5d1SDavid du Colombier } 8917dd7cddfSDavid du Colombier 8927dd7cddfSDavid du Colombier void 8937dd7cddfSDavid du Colombier logsend(int id, int subid, uchar *addr, char *sname, char *rname, int type) 8947dd7cddfSDavid du Colombier { 8957dd7cddfSDavid du Colombier char buf[12]; 8967dd7cddfSDavid du Colombier 8974f8f669cSDavid du Colombier dnslog("[%d] %d.%d: sending to %I/%s %s %s", 8984f8f669cSDavid du Colombier getpid(), id, subid, addr, sname, rname, 8994f8f669cSDavid du Colombier rrname(type, buf, sizeof buf)); 9007dd7cddfSDavid du Colombier } 9017dd7cddfSDavid du Colombier 9027dd7cddfSDavid du Colombier RR* 9037dd7cddfSDavid du Colombier getdnsservers(int class) 9047dd7cddfSDavid du Colombier { 9057dd7cddfSDavid du Colombier return dnsservers(class); 9063e12c5d1SDavid du Colombier } 907