24 typedef struct Mfile Mfile;
25 typedef struct Job Job;
26 typedef struct Network Network;
28 int vers; /* incremented each clone/attach */
32 Mfile *next; /* next free mfile */
39 int type; /* reply type */
41 ushort rr[Maxrrr]; /* offset of rr's */
42 ushort nrr; /* number of rr's */
46 // active local requests
60 Mfile *inuse; /* active mfile's */
73 uchar ipaddr[IPaddrlen]; /* my ip address */
75 char *zonerefreshprogram;
81 void rattach(Job*, Mfile*);
82 char* rwalk(Job*, Mfile*);
83 void ropen(Job*, Mfile*);
84 void rcreate(Job*, Mfile*);
85 void rread(Job*, Mfile*);
86 void rwrite(Job*, Mfile*, Request*);
87 void rclunk(Job*, Mfile*);
88 void rremove(Job*, Mfile*);
89 void rstat(Job*, Mfile*);
90 void rwstat(Job*, Mfile*);
91 void sendmsg(Job*, char*);
92 void mountinit(char*, char*);
94 int fillreply(Mfile*, int);
97 void setext(char*, int, char*);
99 char *logfile = "dns";
107 fprint(2, "usage: %s [-rs] [-f ndb-file] [-x netmtpt]\n", argv0);
112 main(int argc, char *argv[])
115 char servefile[Maxpath];
120 // setnetmtpt(mntpt, sizeof(mntpt), nil);
135 parseip(ipaddr, EARGF(usage()));
141 // setnetmtpt(mntpt, sizeof(mntpt), p);
142 // setext(ext, sizeof(ext), mntpt);
148 serve = 1; /* serve network */
161 zonerefreshprogram = ARGF();
170 //if(testing) mainmem->flags |= POOL_NOREUSE;
172 rfork(RFREND|RFNOTEG);
174 /* start syslog before we fork */
175 fmtinstall('F', fcallfmt);
177 if(!haveip && myipaddr(ipaddr, mntpt) < 0)
178 sysfatal("can't read my ip address");
180 syslog(0, logfile, "starting dns on %I", ipaddr);
185 snprint(servefile, sizeof(servefile), "#s/dns%s", ext);
186 unmount(servefile, mntpt);
189 mountinit(servefile, mntpt);
196 // proccreate(dnudpserver, mntpt, STACK);
201 syslog(0, logfile, "io returned, exiting");
206 myipaddr(uchar *ip, char *net)
213 * if a mount point is specified, set the cs extention to be the mount point
214 * with '_'s replacing '/'s
217 setext(char *ext, int n, char *p)
222 for(i = 0; i < n; i++){
234 mountinit(char *service, char *mntpt)
239 abort(); /* "pipe failed" */;
240 switch(rfork(RFFDG|RFPROC|RFNAMEG)){
245 abort(); /* "fork failed\n" */;
249 if(post9pservice(p[1], "dns") < 0)
250 fprint(2, "post9pservice dns: %r\n");
253 mfd[0] = mfd[1] = p[0];
257 newfid(int fid, int needunused)
262 for(mf = mfalloc.inuse; mf != nil; mf = mf->next){
274 mf = emalloc(sizeof(*mf));
276 sysfatal("out of memory");
278 mf->next = mfalloc.inuse;
289 fprint(2, "freefid %d\n", mf->fid);
291 for(l = &mfalloc.inuse; *l != nil; l = &(*l)->next){
301 sysfatal("freeing unused fid");
305 copyfid(Mfile *mf, int fid)
309 nmf = newfid(fid, 1);
313 nmf->user = estrdup(mf->user);
314 nmf->qid.type = mf->qid.type;
315 nmf->qid.path = mf->qid.path;
316 nmf->qid.vers = vers++;
325 job = emalloc(sizeof(*job));
329 job->request.tag = -1;
340 for(l = &joblist; *l; l = &(*l)->next){
356 for(job = joblist; job; job = job->next){
357 if(job->request.tag == tag && job->request.type != Tflush){
370 uchar mdata[IOHDRSZ + Maxfdata];
375 * a slave process is sometimes forked to wait for replies from other
376 * servers. The master process returns immediately via a longjmp
383 n = read9pmsg(mfd[0], mdata, sizeof mdata);
385 syslog(0, logfile, "error reading mntpt: %r");
389 if(convM2S(mdata, n, &job->request) != n){
394 syslog(0, logfile, "%F", &job->request);
397 req.aborttime = now + 60; /* don't spend more than 60 seconds */
400 switch(job->request.type){
406 mf = newfid(job->request.fid, 1);
408 sendmsg(job, "fid in use");
413 mf = newfid(job->request.fid, 0);
415 sendmsg(job, "unknown fid");
421 switch(job->request.type){
423 syslog(1, logfile, "unknown request type %d", job->request.type);
450 rwrite(job, mf, &req);
469 * slave processes die after replying
483 if(job->request.msize > IOHDRSZ + Maxfdata)
484 job->reply.msize = IOHDRSZ + Maxfdata;
486 job->reply.msize = job->request.msize;
487 if(strncmp(job->request.version, "9P2000", 6) != 0)
488 sendmsg(job, "unknown 9P version");
490 job->reply.version = "9P2000";
498 sendmsg(job, "dns: authentication not required");
502 * don't flush till all the slaves are done
507 flushjob(job->request.oldtag);
512 rattach(Job *job, Mfile *mf)
516 mf->user = estrdup(job->request.uname);
517 mf->qid.vers = vers++;
518 mf->qid.type = QTDIR;
520 job->reply.qid = mf->qid;
525 rwalk(Job *job, Mfile *mf)
536 elems = job->request.wname;
537 nelems = job->request.nwname;
538 job->reply.nwqid = 0;
540 if(job->request.newfid != job->request.fid){
542 if(job->request.newfid<0){
543 err = "clone newfid out of range";
546 nmf = copyfid(mf, job->request.newfid);
548 err = "clone bad newfid";
553 /* else nmf will be nil */
558 for(i=0; i<nelems && i<MAXWELEM; i++){
559 if((qid.type & QTDIR) == 0){
560 err = "not a directory";
563 if(strcmp(elems[i], "..") == 0 || strcmp(elems[i], ".") == 0){
567 job->reply.wqid[i] = qid;
571 if(strcmp(elems[i], "dns") == 0){
576 err = "file does not exist";
582 if(nmf != nil && (err!=nil || job->reply.nwqid<nelems))
591 ropen(Job *job, Mfile *mf)
597 mode = job->request.mode;
598 if(mf->qid.type & QTDIR){
600 err = "permission denied";
602 job->reply.qid = mf->qid;
603 job->reply.iounit = 0;
608 rcreate(Job *job, Mfile *mf)
611 sendmsg(job, "creation permission denied");
615 rread(Job *job, Mfile *mf)
626 off = job->request.offset;
627 cnt = job->request.count;
628 if(mf->qid.type & QTDIR){
632 dir.qid.type = QTFILE;
640 dir.atime = clock; /* wrong */
641 dir.mtime = clock; /* wrong */
642 n = convD2M(&dir, buf, sizeof buf);
644 job->reply.data = (char*)buf;
646 for(i = 1; i <= mf->nrr; i++)
651 if(off + cnt > mf->rr[i])
655 job->reply.data = mf->reply + off;
658 job->reply.count = n;
663 rwrite(Job *job, Mfile *mf, Request *req)
665 int cnt, rooted, status;
667 char *err, *p, *atype;
672 cnt = job->request.count;
673 if(mf->qid.type & QTDIR){
674 err = "can't write directory";
677 if(cnt >= Maxrequest){
678 err = "request too long";
681 job->request.data[cnt] = 0;
682 if(cnt > 0 && job->request.data[cnt-1] == '\n')
683 job->request.data[cnt-1] = 0;
688 if(strncmp(job->request.data, "debug", 5)==0 && job->request.data[5] == 0){
691 } else if(strncmp(job->request.data, "dump", 4)==0 && job->request.data[4] == 0){
692 dndump("/lib/ndb/dnsdump");
694 } else if(strncmp(job->request.data, "refresh", 7)==0 && job->request.data[7] == 0){
697 // } else if(strncmp(job->request.data, "poolcheck", 9)==0 && job->request.data[9] == 0){
698 // poolcheck(mainmem);
703 * kill previous reply
709 * break up request (into a name and a type)
711 atype = strchr(job->request.data, ' ');
713 err = "illegal request";
721 if(strcmp(atype, "trace") == 0){
724 if(*job->request.data)
725 trace = estrdup(job->request.data);
731 mf->type = rrtype(atype);
733 err = "unknown type";
738 if(p >= job->request.data && *p == '.'){
744 p = job->request.data;
751 rp = dnresolve(p, Cin, mf->type, req, 0, 0, Recurse, rooted, &status);
755 status = neg->negrcode;
761 err = "name does not exist";
767 err = "resource does not exist";
773 /* format data to be read later */
776 for(tp = rp; mf->nrr < Maxrrr-1 && n < Maxreply && tp &&
777 tsame(mf->type, tp->type); tp = tp->next){
778 mf->rr[mf->nrr++] = n;
780 n += snprint(mf->reply+n, Maxreply-n, "%Q", tp);
782 n += snprint(mf->reply+n, Maxreply-n, "%R", tp);
792 job->reply.count = cnt;
797 rclunk(Job *job, Mfile *mf)
804 rremove(Job *job, Mfile *mf)
807 sendmsg(job, "remove permission denied");
811 rstat(Job *job, Mfile *mf)
814 uchar buf[IOHDRSZ+Maxfdata];
816 if(mf->qid.type & QTDIR){
818 dir.mode = DMDIR|0555;
828 dir.atime = dir.mtime = time(0);
829 job->reply.nstat = convD2M(&dir, buf, sizeof buf);
830 job->reply.stat = buf;
835 rwstat(Job *job, Mfile *mf)
838 sendmsg(job, "wstat permission denied");
842 sendmsg(Job *job, char *err)
845 uchar mdata[IOHDRSZ + Maxfdata];
849 job->reply.type = Rerror;
850 snprint(ename, sizeof(ename), "dns: %s", err);
851 job->reply.ename = ename;
853 job->reply.type = job->request.type+1;
855 job->reply.tag = job->request.tag;
856 n = convS2M(&job->reply, mdata, sizeof mdata);
858 syslog(1, logfile, "sendmsg convS2M of %F returns 0", &job->reply);
862 if(job->flushed == 0)
863 if(write(mfd[1], mdata, n)!=n)
864 sysfatal("mount write");
867 syslog(0, logfile, "%F %d", &job->reply, n);
871 * the following varies between dnsdebug and dns
874 logreply(int id, uchar *addr, DNSmsg *mp)
878 syslog(0, LOG, "%d: rcvd %I flags:%s%s%s%s%s", id, addr,
879 mp->flags & Fauth ? " auth" : "",
880 mp->flags & Ftrunc ? " trunc" : "",
881 mp->flags & Frecurse ? " rd" : "",
882 mp->flags & Fcanrec ? " ra" : "",
883 mp->flags & (Fauth|Rname) == (Fauth|Rname) ?
885 for(rp = mp->qd; rp != nil; rp = rp->next)
886 syslog(0, LOG, "%d: rcvd %I qd %s", id, addr, rp->owner->name);
887 for(rp = mp->an; rp != nil; rp = rp->next)
888 syslog(0, LOG, "%d: rcvd %I an %R", id, addr, rp);
889 for(rp = mp->ns; rp != nil; rp = rp->next)
890 syslog(0, LOG, "%d: rcvd %I ns %R", id, addr, rp);
891 for(rp = mp->ar; rp != nil; rp = rp->next)
892 syslog(0, LOG, "%d: rcvd %I ar %R", id, addr, rp);
896 logsend(int id, int subid, uchar *addr, char *sname, char *rname, int type)
900 syslog(0, LOG, "%d.%d: sending to %I/%s %s %s",
901 id, subid, addr, sname, rname, rrname(type, buf, sizeof buf));
905 getdnsservers(int class)
907 return dnsservers(class);