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 18f46c709fSDavid 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; 413f46c709fSDavid 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; 694*21abd8f2SDavid du Colombier } else if(strncmp(job->request.data, "target", 6)==0){ 695*21abd8f2SDavid du Colombier target = atol(job->request.data + 6); 696*21abd8f2SDavid du Colombier dnslog("target set to %ld", target); 697*21abd8f2SDavid du Colombier goto send; 698*21abd8f2SDavid du Colombier } else if(strcmp(job->request.data, "age")==0){ 699*21abd8f2SDavid du Colombier dnslog("dump, age & dump forced"); 700*21abd8f2SDavid du Colombier dndump("/lib/ndb/dnsdump1"); 701*21abd8f2SDavid du Colombier dnforceage(); 702*21abd8f2SDavid du Colombier dndump("/lib/ndb/dnsdump2"); 703*21abd8f2SDavid du Colombier goto send; 704219b2ee8SDavid du Colombier } 705219b2ee8SDavid du Colombier 706219b2ee8SDavid du Colombier /* 7077dd7cddfSDavid du Colombier * kill previous reply 7087dd7cddfSDavid du Colombier */ 7097dd7cddfSDavid du Colombier mf->nrr = 0; 7107dd7cddfSDavid du Colombier mf->rr[0] = 0; 7117dd7cddfSDavid du Colombier 7127dd7cddfSDavid du Colombier /* 7133e12c5d1SDavid du Colombier * break up request (into a name and a type) 7143e12c5d1SDavid du Colombier */ 7157dd7cddfSDavid du Colombier atype = strchr(job->request.data, ' '); 7163e12c5d1SDavid du Colombier if(atype == 0){ 7173e12c5d1SDavid du Colombier err = "illegal request"; 7183e12c5d1SDavid du Colombier goto send; 7193e12c5d1SDavid du Colombier } else 7203e12c5d1SDavid du Colombier *atype++ = 0; 7213e12c5d1SDavid du Colombier 7227dd7cddfSDavid du Colombier /* 7237dd7cddfSDavid du Colombier * tracing request 7247dd7cddfSDavid du Colombier */ 7257dd7cddfSDavid du Colombier if(strcmp(atype, "trace") == 0){ 7267dd7cddfSDavid du Colombier if(trace) 7277dd7cddfSDavid du Colombier free(trace); 7287dd7cddfSDavid du Colombier if(*job->request.data) 7299a747e4fSDavid du Colombier trace = estrdup(job->request.data); 7307dd7cddfSDavid du Colombier else 7317dd7cddfSDavid du Colombier trace = 0; 7327dd7cddfSDavid du Colombier goto send; 7337dd7cddfSDavid du Colombier } 7347dd7cddfSDavid du Colombier 7354f8f669cSDavid du Colombier /* normal request: domain [type] */ 736a41547ffSDavid du Colombier stats.qrecvd9p++; 7373e12c5d1SDavid du Colombier mf->type = rrtype(atype); 7383e12c5d1SDavid du Colombier if(mf->type < 0){ 7393e12c5d1SDavid du Colombier err = "unknown type"; 7403e12c5d1SDavid du Colombier goto send; 7413e12c5d1SDavid du Colombier } 7423e12c5d1SDavid du Colombier 7437dd7cddfSDavid du Colombier p = atype - 2; 7447dd7cddfSDavid du Colombier if(p >= job->request.data && *p == '.'){ 7457dd7cddfSDavid du Colombier rooted = 1; 7467dd7cddfSDavid du Colombier *p = 0; 7477dd7cddfSDavid du Colombier } else 7487dd7cddfSDavid du Colombier rooted = 0; 7493e12c5d1SDavid du Colombier 7507dd7cddfSDavid du Colombier p = job->request.data; 7517dd7cddfSDavid du Colombier if(*p == '!'){ 7527dd7cddfSDavid du Colombier wantsav = 1; 7537dd7cddfSDavid du Colombier p++; 7547dd7cddfSDavid du Colombier } else 7557dd7cddfSDavid du Colombier wantsav = 0; 7564f8f669cSDavid du Colombier 7579a747e4fSDavid du Colombier dncheck(0, 1); 7584f8f669cSDavid du Colombier status = 0; 7597dd7cddfSDavid du Colombier rp = dnresolve(p, Cin, mf->type, req, 0, 0, Recurse, rooted, &status); 7604f8f669cSDavid du Colombier 7619a747e4fSDavid du Colombier dncheck(0, 1); 7627dd7cddfSDavid du Colombier neg = rrremneg(&rp); 7637dd7cddfSDavid du Colombier if(neg){ 7647dd7cddfSDavid du Colombier status = neg->negrcode; 7657dd7cddfSDavid du Colombier rrfreelist(neg); 7667dd7cddfSDavid du Colombier } 7674f8f669cSDavid du Colombier 7684f8f669cSDavid du Colombier if(rp == nil) 769271b8d73SDavid du Colombier switch(status){ 770271b8d73SDavid du Colombier case Rname: 7717dd7cddfSDavid du Colombier err = "name does not exist"; 772271b8d73SDavid du Colombier break; 773271b8d73SDavid du Colombier case Rserver: 774271b8d73SDavid du Colombier err = "dns failure"; 775271b8d73SDavid du Colombier break; 776271b8d73SDavid du Colombier default: 777271b8d73SDavid du Colombier err = "resource does not exist"; 778271b8d73SDavid du Colombier break; 779271b8d73SDavid du Colombier } 7804f8f669cSDavid du Colombier else { 78134f77ae3SDavid du Colombier lock(&joblock); 78234f77ae3SDavid du Colombier if(!job->flushed){ 7837dd7cddfSDavid du Colombier /* format data to be read later */ 7847dd7cddfSDavid du Colombier n = 0; 7857dd7cddfSDavid du Colombier mf->nrr = 0; 7867dd7cddfSDavid du Colombier for(tp = rp; mf->nrr < Maxrrr-1 && n < Maxreply && tp && 7877dd7cddfSDavid du Colombier tsame(mf->type, tp->type); tp = tp->next){ 7887dd7cddfSDavid du Colombier mf->rr[mf->nrr++] = n; 7897dd7cddfSDavid du Colombier if(wantsav) 7904f8f669cSDavid du Colombier n += snprint(mf->reply+n, Maxreply-n, 7914f8f669cSDavid du Colombier "%Q", tp); 7927dd7cddfSDavid du Colombier else 7934f8f669cSDavid du Colombier n += snprint(mf->reply+n, Maxreply-n, 7944f8f669cSDavid du Colombier "%R", tp); 7957dd7cddfSDavid du Colombier } 7967dd7cddfSDavid du Colombier mf->rr[mf->nrr] = n; 79734f77ae3SDavid du Colombier } 79834f77ae3SDavid du Colombier unlock(&joblock); 7997dd7cddfSDavid du Colombier rrfreelist(rp); 8007dd7cddfSDavid du Colombier } 8013e12c5d1SDavid du Colombier send: 8029a747e4fSDavid du Colombier dncheck(0, 1); 8037dd7cddfSDavid du Colombier job->reply.count = cnt; 8047dd7cddfSDavid du Colombier sendmsg(job, err); 8053e12c5d1SDavid du Colombier } 8063e12c5d1SDavid du Colombier 8073e12c5d1SDavid du Colombier void 8087dd7cddfSDavid du Colombier rclunk(Job *job, Mfile *mf) 8093e12c5d1SDavid du Colombier { 8107dd7cddfSDavid du Colombier freefid(mf); 8117dd7cddfSDavid du Colombier sendmsg(job, 0); 8123e12c5d1SDavid du Colombier } 8133e12c5d1SDavid du Colombier 8143e12c5d1SDavid du Colombier void 8157dd7cddfSDavid du Colombier rremove(Job *job, Mfile *mf) 8163e12c5d1SDavid du Colombier { 8173e12c5d1SDavid du Colombier USED(mf); 8187dd7cddfSDavid du Colombier sendmsg(job, "remove permission denied"); 8193e12c5d1SDavid du Colombier } 8203e12c5d1SDavid du Colombier 8213e12c5d1SDavid du Colombier void 8227dd7cddfSDavid du Colombier rstat(Job *job, Mfile *mf) 8233e12c5d1SDavid du Colombier { 8243e12c5d1SDavid du Colombier Dir dir; 8259a747e4fSDavid du Colombier uchar buf[IOHDRSZ+Maxfdata]; 8263e12c5d1SDavid du Colombier 8279a747e4fSDavid du Colombier if(mf->qid.type & QTDIR){ 8289a747e4fSDavid du Colombier dir.name = "."; 8299a747e4fSDavid du Colombier dir.mode = DMDIR|0555; 830219b2ee8SDavid du Colombier } else { 8319a747e4fSDavid du Colombier dir.name = "dns"; 8323e12c5d1SDavid du Colombier dir.mode = 0666; 833219b2ee8SDavid du Colombier } 834219b2ee8SDavid du Colombier dir.qid = mf->qid; 8353e12c5d1SDavid du Colombier dir.length = 0; 8364f8f669cSDavid du Colombier dir.uid = dir.gid = dir.muid = mf->user; 8374f8f669cSDavid du Colombier dir.atime = dir.mtime = time(nil); 8389a747e4fSDavid du Colombier job->reply.nstat = convD2M(&dir, buf, sizeof buf); 8399a747e4fSDavid du Colombier job->reply.stat = buf; 8407dd7cddfSDavid du Colombier sendmsg(job, 0); 8413e12c5d1SDavid du Colombier } 8423e12c5d1SDavid du Colombier 8433e12c5d1SDavid du Colombier void 8447dd7cddfSDavid du Colombier rwstat(Job *job, Mfile *mf) 8453e12c5d1SDavid du Colombier { 8463e12c5d1SDavid du Colombier USED(mf); 8477dd7cddfSDavid du Colombier sendmsg(job, "wstat permission denied"); 8483e12c5d1SDavid du Colombier } 8493e12c5d1SDavid du Colombier 8503e12c5d1SDavid du Colombier void 8517dd7cddfSDavid du Colombier sendmsg(Job *job, char *err) 8523e12c5d1SDavid du Colombier { 8533e12c5d1SDavid du Colombier int n; 8549a747e4fSDavid du Colombier uchar mdata[IOHDRSZ + Maxfdata]; 8559a747e4fSDavid du Colombier char ename[ERRMAX]; 8563e12c5d1SDavid du Colombier 8573e12c5d1SDavid du Colombier if(err){ 8587dd7cddfSDavid du Colombier job->reply.type = Rerror; 8594f8f669cSDavid du Colombier snprint(ename, sizeof ename, "dns: %s", err); 8609a747e4fSDavid du Colombier job->reply.ename = ename; 8614f8f669cSDavid du Colombier }else 8627dd7cddfSDavid du Colombier job->reply.type = job->request.type+1; 8637dd7cddfSDavid du Colombier job->reply.tag = job->request.tag; 8649a747e4fSDavid du Colombier n = convS2M(&job->reply, mdata, sizeof mdata); 8659a747e4fSDavid du Colombier if(n == 0){ 8664f8f669cSDavid du Colombier warning("sendmsg convS2M of %F returns 0", &job->reply); 8679a747e4fSDavid du Colombier abort(); 8683e12c5d1SDavid du Colombier } 8699a747e4fSDavid du Colombier lock(&joblock); 8709a747e4fSDavid du Colombier if(job->flushed == 0) 8719a747e4fSDavid du Colombier if(write(mfd[1], mdata, n)!=n) 8729a747e4fSDavid du Colombier sysfatal("mount write"); 8737dd7cddfSDavid du Colombier unlock(&joblock); 8749a747e4fSDavid du Colombier if(debug) 8754f8f669cSDavid du Colombier dnslog("%F %d", &job->reply, n); 8763e12c5d1SDavid du Colombier } 8773e12c5d1SDavid du Colombier 8783e12c5d1SDavid du Colombier /* 8797dd7cddfSDavid du Colombier * the following varies between dnsdebug and dns 8803e12c5d1SDavid du Colombier */ 8813e12c5d1SDavid du Colombier void 8827dd7cddfSDavid du Colombier logreply(int id, uchar *addr, DNSmsg *mp) 8833e12c5d1SDavid du Colombier { 8847dd7cddfSDavid du Colombier RR *rp; 8853e12c5d1SDavid du Colombier 8864f8f669cSDavid du Colombier dnslog("%d: rcvd %I flags:%s%s%s%s%s", id, addr, 8877dd7cddfSDavid du Colombier mp->flags & Fauth? " auth": "", 8887dd7cddfSDavid du Colombier mp->flags & Ftrunc? " trunc": "", 8897dd7cddfSDavid du Colombier mp->flags & Frecurse? " rd": "", 8907dd7cddfSDavid du Colombier mp->flags & Fcanrec? " ra": "", 8914f8f669cSDavid du Colombier (mp->flags & (Fauth|Rmask)) == (Fauth|Rname)? " nx": ""); 8927dd7cddfSDavid du Colombier for(rp = mp->qd; rp != nil; rp = rp->next) 8934f8f669cSDavid du Colombier dnslog("%d: rcvd %I qd %s", id, addr, rp->owner->name); 8947dd7cddfSDavid du Colombier for(rp = mp->an; rp != nil; rp = rp->next) 8954f8f669cSDavid du Colombier dnslog("%d: rcvd %I an %R", id, addr, rp); 8967dd7cddfSDavid du Colombier for(rp = mp->ns; rp != nil; rp = rp->next) 8974f8f669cSDavid du Colombier dnslog("%d: rcvd %I ns %R", id, addr, rp); 8987dd7cddfSDavid du Colombier for(rp = mp->ar; rp != nil; rp = rp->next) 8994f8f669cSDavid du Colombier dnslog("%d: rcvd %I ar %R", id, addr, rp); 9003e12c5d1SDavid du Colombier } 9017dd7cddfSDavid du Colombier 9027dd7cddfSDavid du Colombier void 9037dd7cddfSDavid du Colombier logsend(int id, int subid, uchar *addr, char *sname, char *rname, int type) 9047dd7cddfSDavid du Colombier { 9057dd7cddfSDavid du Colombier char buf[12]; 9067dd7cddfSDavid du Colombier 9074f8f669cSDavid du Colombier dnslog("[%d] %d.%d: sending to %I/%s %s %s", 9084f8f669cSDavid du Colombier getpid(), id, subid, addr, sname, rname, 9094f8f669cSDavid du Colombier rrname(type, buf, sizeof buf)); 9107dd7cddfSDavid du Colombier } 9117dd7cddfSDavid du Colombier 9127dd7cddfSDavid du Colombier RR* 9137dd7cddfSDavid du Colombier getdnsservers(int class) 9147dd7cddfSDavid du Colombier { 9157dd7cddfSDavid du Colombier return dnsservers(class); 9163e12c5d1SDavid du Colombier } 917