tdns.c - plan9port - [fork] Plan 9 from user space | |
git clone git://src.adamsgaard.dk/plan9port | |
Log | |
Files | |
Refs | |
README | |
LICENSE | |
--- | |
tdns.c (15204B) | |
--- | |
1 #include <u.h> | |
2 #include <libc.h> | |
3 #include <auth.h> | |
4 #include <fcall.h> | |
5 #include <bio.h> | |
6 #include <ctype.h> | |
7 #include <ip.h> | |
8 #include <ndb.h> | |
9 #include <thread.h> | |
10 #include "dns.h" | |
11 | |
12 enum | |
13 { | |
14 Maxrequest= 1024, | |
15 Ncache= 8, | |
16 Maxpath= 128, | |
17 Maxreply= 512, | |
18 Maxrrr= 16, | |
19 Maxfdata= 8192, | |
20 | |
21 Qdir= 0, | |
22 Qdns= 1 | |
23 }; | |
24 | |
25 typedef struct Mfile Mfile; | |
26 typedef struct Job Job; | |
27 typedef struct Network Network; | |
28 | |
29 int vers; /* incremented each clone/attach */ | |
30 | |
31 struct Mfile | |
32 { | |
33 Mfile *next; /* next free mfile */ | |
34 int ref; | |
35 | |
36 char *user; | |
37 Qid qid; | |
38 int fid; | |
39 | |
40 int type; /* reply type */ | |
41 char reply[Maxreply]; | |
42 ushort rr[Maxrrr]; /* offset of rr's */ | |
43 ushort nrr; /* number of rr's */ | |
44 }; | |
45 | |
46 /* | |
47 * active local requests | |
48 */ | |
49 struct Job | |
50 { | |
51 Job *next; | |
52 int flushed; | |
53 Fcall request; | |
54 Fcall reply; | |
55 }; | |
56 Lock joblock; | |
57 Job *joblist; | |
58 | |
59 struct { | |
60 Lock lk; | |
61 Mfile *inuse; /* active mfile's */ | |
62 } mfalloc; | |
63 | |
64 int mfd[2]; | |
65 int debug; | |
66 int traceactivity; | |
67 int cachedb; | |
68 ulong now; | |
69 int testing; | |
70 char *trace; | |
71 int needrefresh; | |
72 int resolver; | |
73 uchar ipaddr[IPaddrlen]; /* my ip address */ | |
74 int maxage; | |
75 char *zonerefreshprogram; | |
76 int sendnotifies; | |
77 | |
78 void rversion(Job*); | |
79 void rauth(Job*); | |
80 void rflush(Job*); | |
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*); | |
93 void io(void); | |
94 int fillreply(Mfile*, int); | |
95 Job* newjob(void); | |
96 void freejob(Job*); | |
97 void setext(char*, int, char*); | |
98 | |
99 char *tcpaddr = "tcp!*!domain"; | |
100 char *udpaddr = "udp!*!domain"; | |
101 char *logfile = "dns"; | |
102 char *dbfile; | |
103 char mntpt[Maxpath]; | |
104 char *LOG; | |
105 | |
106 void | |
107 usage(void) | |
108 { | |
109 fprint(2, "usage: dns [-dnrst] [-a maxage] [-f ndb-file] [-T tcp… | |
110 threadexitsall("usage"); | |
111 } | |
112 | |
113 void | |
114 checkaddress(void) | |
115 { | |
116 char *u, *t; | |
117 | |
118 u = strchr(udpaddr, '!'); | |
119 t = strchr(tcpaddr, '!'); | |
120 if(u && t && strcmp(u, t) != 0) | |
121 fprint(2, "warning: announce mismatch %s %s\n", udpaddr,… | |
122 } | |
123 | |
124 int | |
125 threadmaybackground(void) | |
126 { | |
127 return 1; | |
128 } | |
129 | |
130 void | |
131 threadmain(int argc, char *argv[]) | |
132 { | |
133 int serveudp, servetcp; | |
134 char *service; | |
135 | |
136 serveudp = 0; | |
137 servetcp = 0; | |
138 service = "dns"; | |
139 ARGBEGIN{ | |
140 case 'd': | |
141 debug = 1; | |
142 traceactivity = 1; | |
143 break; | |
144 case 'f': | |
145 dbfile = EARGF(usage()); | |
146 break; | |
147 case 'x': | |
148 service = EARGF(usage()); | |
149 break; | |
150 case 'r': | |
151 resolver = 1; | |
152 break; | |
153 case 's': | |
154 serveudp = 1; | |
155 cachedb = 1; | |
156 break; | |
157 case 't': | |
158 servetcp = 1; | |
159 cachedb = 1; | |
160 break; | |
161 case 'a': | |
162 maxage = atoi(EARGF(usage())); | |
163 break; | |
164 case 'z': | |
165 zonerefreshprogram = EARGF(usage()); | |
166 break; | |
167 case 'n': | |
168 sendnotifies = 1; | |
169 break; | |
170 case 'U': | |
171 udpaddr = estrdup(netmkaddr(EARGF(usage()), "udp", "doma… | |
172 break; | |
173 case 'T': | |
174 tcpaddr = estrdup(netmkaddr(EARGF(usage()), "tcp", "doma… | |
175 break; | |
176 default: | |
177 usage(); | |
178 }ARGEND | |
179 | |
180 if(argc) | |
181 usage(); | |
182 if(serveudp && servetcp) | |
183 checkaddress(); | |
184 | |
185 rfork(RFNOTEG); | |
186 | |
187 /* start syslog before we fork */ | |
188 fmtinstall('F', fcallfmt); | |
189 dninit(); | |
190 if(myipaddr(ipaddr, mntpt) < 0) | |
191 sysfatal("can't read my ip address"); | |
192 | |
193 syslog(0, logfile, "starting dns on %I", ipaddr); | |
194 | |
195 opendatabase(); | |
196 | |
197 mountinit(service); | |
198 | |
199 now = time(0); | |
200 srand(now*getpid()); | |
201 db2cache(1); | |
202 | |
203 if(serveudp) | |
204 proccreate(dnudpserver, nil, STACK); | |
205 if(servetcp) | |
206 proccreate(dntcpserver, nil, STACK); | |
207 if(sendnotifies) | |
208 proccreate(notifyproc, nil, STACK); | |
209 | |
210 io(); | |
211 } | |
212 | |
213 /* | |
214 * if a mount point is specified, set the cs extention to be the mount … | |
215 * with '_'s replacing '/'s | |
216 */ | |
217 void | |
218 setext(char *ext, int n, char *p) | |
219 { | |
220 int i, c; | |
221 | |
222 n--; | |
223 for(i = 0; i < n; i++){ | |
224 c = p[i]; | |
225 if(c == 0) | |
226 break; | |
227 if(c == '/') | |
228 c = '_'; | |
229 ext[i] = c; | |
230 } | |
231 ext[i] = 0; | |
232 } | |
233 | |
234 void | |
235 mountinit(char *service) | |
236 { | |
237 int p[2]; | |
238 | |
239 if(pipe(p) < 0) | |
240 abort(); /* "pipe failed" */; | |
241 if(post9pservice(p[1], service, nil) < 0) | |
242 fprint(2, "post9pservice dns: %r\n"); | |
243 close(p[1]); | |
244 mfd[0] = mfd[1] = p[0]; | |
245 } | |
246 | |
247 Mfile* | |
248 newfid(int fid, int needunused) | |
249 { | |
250 Mfile *mf; | |
251 | |
252 lock(&mfalloc.lk); | |
253 for(mf = mfalloc.inuse; mf != nil; mf = mf->next){ | |
254 if(mf->fid == fid){ | |
255 unlock(&mfalloc.lk); | |
256 if(needunused) | |
257 return nil; | |
258 return mf; | |
259 } | |
260 } | |
261 if(!needunused){ | |
262 unlock(&mfalloc.lk); | |
263 return nil; | |
264 } | |
265 mf = emalloc(sizeof(*mf)); | |
266 if(mf == nil) | |
267 sysfatal("out of memory"); | |
268 mf->fid = fid; | |
269 mf->next = mfalloc.inuse; | |
270 mfalloc.inuse = mf; | |
271 unlock(&mfalloc.lk); | |
272 return mf; | |
273 } | |
274 | |
275 void | |
276 freefid(Mfile *mf) | |
277 { | |
278 Mfile **l; | |
279 | |
280 lock(&mfalloc.lk); | |
281 for(l = &mfalloc.inuse; *l != nil; l = &(*l)->next){ | |
282 if(*l == mf){ | |
283 *l = mf->next; | |
284 if(mf->user) | |
285 free(mf->user); | |
286 free(mf); | |
287 unlock(&mfalloc.lk); | |
288 return; | |
289 } | |
290 } | |
291 sysfatal("freeing unused fid"); | |
292 } | |
293 | |
294 Mfile* | |
295 copyfid(Mfile *mf, int fid) | |
296 { | |
297 Mfile *nmf; | |
298 | |
299 nmf = newfid(fid, 1); | |
300 if(nmf == nil) | |
301 return nil; | |
302 nmf->fid = fid; | |
303 nmf->user = estrdup(mf->user); | |
304 nmf->qid.type = mf->qid.type; | |
305 nmf->qid.path = mf->qid.path; | |
306 nmf->qid.vers = vers++; | |
307 return nmf; | |
308 } | |
309 | |
310 Job* | |
311 newjob(void) | |
312 { | |
313 Job *job; | |
314 | |
315 job = emalloc(sizeof(*job)); | |
316 lock(&joblock); | |
317 job->next = joblist; | |
318 joblist = job; | |
319 job->request.tag = -1; | |
320 unlock(&joblock); | |
321 return job; | |
322 } | |
323 | |
324 void | |
325 freejob(Job *job) | |
326 { | |
327 Job **l; | |
328 | |
329 lock(&joblock); | |
330 for(l = &joblist; *l; l = &(*l)->next){ | |
331 if((*l) == job){ | |
332 *l = job->next; | |
333 free(job); | |
334 break; | |
335 } | |
336 } | |
337 unlock(&joblock); | |
338 } | |
339 | |
340 void | |
341 flushjob(int tag) | |
342 { | |
343 Job *job; | |
344 | |
345 lock(&joblock); | |
346 for(job = joblist; job; job = job->next){ | |
347 if(job->request.tag == tag && job->request.type != Tflus… | |
348 job->flushed = 1; | |
349 break; | |
350 } | |
351 } | |
352 unlock(&joblock); | |
353 } | |
354 | |
355 void | |
356 ioproc0(void *v) | |
357 { | |
358 long n; | |
359 Mfile *mf; | |
360 uchar mdata[IOHDRSZ + Maxfdata]; | |
361 Request req; | |
362 Job *job; | |
363 | |
364 USED(v); | |
365 | |
366 for(;;){ | |
367 n = read9pmsg(mfd[0], mdata, sizeof mdata); | |
368 if(n <= 0){ | |
369 syslog(0, logfile, "error reading mntpt: %r"); | |
370 break; | |
371 } | |
372 job = newjob(); | |
373 if(convM2S(mdata, n, &job->request) != n){ | |
374 freejob(job); | |
375 continue; | |
376 } | |
377 if(debug) | |
378 syslog(0, logfile, "%F", &job->request); | |
379 | |
380 getactivity(&req); | |
381 req.aborttime = now + 60; /* don't spend more tha… | |
382 | |
383 mf = nil; | |
384 switch(job->request.type){ | |
385 case Tversion: | |
386 case Tauth: | |
387 case Tflush: | |
388 break; | |
389 case Tattach: | |
390 mf = newfid(job->request.fid, 1); | |
391 if(mf == nil){ | |
392 sendmsg(job, "fid in use"); | |
393 goto skip; | |
394 } | |
395 break; | |
396 default: | |
397 mf = newfid(job->request.fid, 0); | |
398 if(mf == nil){ | |
399 sendmsg(job, "unknown fid"); | |
400 goto skip; | |
401 } | |
402 break; | |
403 } | |
404 | |
405 switch(job->request.type){ | |
406 default: | |
407 syslog(1, logfile, "unknown request type %d", jo… | |
408 break; | |
409 case Tversion: | |
410 rversion(job); | |
411 break; | |
412 case Tauth: | |
413 rauth(job); | |
414 break; | |
415 case Tflush: | |
416 rflush(job); | |
417 break; | |
418 case Tattach: | |
419 rattach(job, mf); | |
420 break; | |
421 case Twalk: | |
422 rwalk(job, mf); | |
423 break; | |
424 case Topen: | |
425 ropen(job, mf); | |
426 break; | |
427 case Tcreate: | |
428 rcreate(job, mf); | |
429 break; | |
430 case Tread: | |
431 rread(job, mf); | |
432 break; | |
433 case Twrite: | |
434 rwrite(job, mf, &req); | |
435 break; | |
436 case Tclunk: | |
437 rclunk(job, mf); | |
438 break; | |
439 case Tremove: | |
440 rremove(job, mf); | |
441 break; | |
442 case Tstat: | |
443 rstat(job, mf); | |
444 break; | |
445 case Twstat: | |
446 rwstat(job, mf); | |
447 break; | |
448 } | |
449 skip: | |
450 freejob(job); | |
451 putactivity(); | |
452 } | |
453 } | |
454 | |
455 void | |
456 io(void) | |
457 { | |
458 int i; | |
459 | |
460 for(i=0; i<Maxactive; i++) | |
461 proccreate(ioproc0, 0, STACK); | |
462 } | |
463 | |
464 void | |
465 rversion(Job *job) | |
466 { | |
467 if(job->request.msize > IOHDRSZ + Maxfdata) | |
468 job->reply.msize = IOHDRSZ + Maxfdata; | |
469 else | |
470 job->reply.msize = job->request.msize; | |
471 if(strncmp(job->request.version, "9P2000", 6) != 0) | |
472 sendmsg(job, "unknown 9P version"); | |
473 else{ | |
474 job->reply.version = "9P2000"; | |
475 sendmsg(job, 0); | |
476 } | |
477 } | |
478 | |
479 void | |
480 rauth(Job *job) | |
481 { | |
482 sendmsg(job, "dns: authentication not required"); | |
483 } | |
484 | |
485 /* | |
486 * don't flush till all the slaves are done | |
487 */ | |
488 void | |
489 rflush(Job *job) | |
490 { | |
491 flushjob(job->request.oldtag); | |
492 sendmsg(job, 0); | |
493 } | |
494 | |
495 void | |
496 rattach(Job *job, Mfile *mf) | |
497 { | |
498 if(mf->user != nil) | |
499 free(mf->user); | |
500 mf->user = estrdup(job->request.uname); | |
501 mf->qid.vers = vers++; | |
502 mf->qid.type = QTDIR; | |
503 mf->qid.path = 0LL; | |
504 job->reply.qid = mf->qid; | |
505 sendmsg(job, 0); | |
506 } | |
507 | |
508 char* | |
509 rwalk(Job *job, Mfile *mf) | |
510 { | |
511 char *err; | |
512 char **elems; | |
513 int nelems; | |
514 int i; | |
515 Mfile *nmf; | |
516 Qid qid; | |
517 | |
518 err = 0; | |
519 nmf = nil; | |
520 elems = job->request.wname; | |
521 nelems = job->request.nwname; | |
522 job->reply.nwqid = 0; | |
523 | |
524 if(job->request.newfid != job->request.fid){ | |
525 /* clone fid */ | |
526 nmf = copyfid(mf, job->request.newfid); | |
527 if(nmf == nil){ | |
528 err = "clone bad newfid"; | |
529 goto send; | |
530 } | |
531 mf = nmf; | |
532 } | |
533 /* else nmf will be nil */ | |
534 | |
535 qid = mf->qid; | |
536 if(nelems > 0){ | |
537 /* walk fid */ | |
538 for(i=0; i<nelems && i<MAXWELEM; i++){ | |
539 if((qid.type & QTDIR) == 0){ | |
540 err = "not a directory"; | |
541 break; | |
542 } | |
543 if(strcmp(elems[i], "..") == 0 || strcmp(elems[i… | |
544 qid.type = QTDIR; | |
545 qid.path = Qdir; | |
546 Found: | |
547 job->reply.wqid[i] = qid; | |
548 job->reply.nwqid++; | |
549 continue; | |
550 } | |
551 if(strcmp(elems[i], "dns") == 0){ | |
552 qid.type = QTFILE; | |
553 qid.path = Qdns; | |
554 goto Found; | |
555 } | |
556 err = "file does not exist"; | |
557 break; | |
558 } | |
559 } | |
560 | |
561 send: | |
562 if(nmf != nil && (err!=nil || job->reply.nwqid<nelems)) | |
563 freefid(nmf); | |
564 if(err == nil) | |
565 mf->qid = qid; | |
566 sendmsg(job, err); | |
567 return err; | |
568 } | |
569 | |
570 void | |
571 ropen(Job *job, Mfile *mf) | |
572 { | |
573 int mode; | |
574 char *err; | |
575 | |
576 err = 0; | |
577 mode = job->request.mode; | |
578 if(mf->qid.type & QTDIR){ | |
579 if(mode) | |
580 err = "permission denied"; | |
581 } | |
582 job->reply.qid = mf->qid; | |
583 job->reply.iounit = 0; | |
584 sendmsg(job, err); | |
585 } | |
586 | |
587 void | |
588 rcreate(Job *job, Mfile *mf) | |
589 { | |
590 USED(mf); | |
591 sendmsg(job, "creation permission denied"); | |
592 } | |
593 | |
594 void | |
595 rread(Job *job, Mfile *mf) | |
596 { | |
597 int i, n, cnt; | |
598 long off; | |
599 Dir dir; | |
600 uchar buf[Maxfdata]; | |
601 char *err; | |
602 long clock; | |
603 | |
604 n = 0; | |
605 err = 0; | |
606 off = job->request.offset; | |
607 cnt = job->request.count; | |
608 if(mf->qid.type & QTDIR){ | |
609 clock = time(0); | |
610 if(off == 0){ | |
611 dir.name = "dns"; | |
612 dir.qid.type = QTFILE; | |
613 dir.qid.vers = vers; | |
614 dir.qid.path = Qdns; | |
615 dir.mode = 0666; | |
616 dir.length = 0; | |
617 dir.uid = mf->user; | |
618 dir.gid = mf->user; | |
619 dir.muid = mf->user; | |
620 dir.atime = clock; /* wrong */ | |
621 dir.mtime = clock; /* wrong */ | |
622 n = convD2M(&dir, buf, sizeof buf); | |
623 } | |
624 job->reply.data = (char*)buf; | |
625 } else { | |
626 for(i = 1; i <= mf->nrr; i++) | |
627 if(mf->rr[i] > off) | |
628 break; | |
629 if(i > mf->nrr) | |
630 goto send; | |
631 if(off + cnt > mf->rr[i]) | |
632 n = mf->rr[i] - off; | |
633 else | |
634 n = cnt; | |
635 job->reply.data = mf->reply + off; | |
636 } | |
637 send: | |
638 job->reply.count = n; | |
639 sendmsg(job, err); | |
640 } | |
641 | |
642 void | |
643 rwrite(Job *job, Mfile *mf, Request *req) | |
644 { | |
645 int cnt, rooted, status; | |
646 long n; | |
647 char *err, *p, *atype; | |
648 RR *rp, *tp, *neg; | |
649 int wantsav; | |
650 static char *dumpfile; | |
651 | |
652 err = 0; | |
653 cnt = job->request.count; | |
654 if(mf->qid.type & QTDIR){ | |
655 err = "can't write directory"; | |
656 goto send; | |
657 } | |
658 if(cnt >= Maxrequest){ | |
659 err = "request too long"; | |
660 goto send; | |
661 } | |
662 job->request.data[cnt] = 0; | |
663 if(cnt > 0 && job->request.data[cnt-1] == '\n') | |
664 job->request.data[cnt-1] = 0; | |
665 | |
666 /* | |
667 * special commands | |
668 */ | |
669 p = job->request.data; | |
670 if(strcmp(p, "debug")==0){ | |
671 debug ^= 1; | |
672 goto send; | |
673 } else if(strcmp(p, "dump")==0){ | |
674 if(dumpfile == nil) | |
675 dumpfile = unsharp("#9/ndb/dnsdump"); | |
676 dndump(dumpfile); | |
677 goto send; | |
678 } else if(strncmp(p, "dump ", 5) == 0){ | |
679 if(*(p+5)) | |
680 dndump(p+5); | |
681 else | |
682 err = "bad filename"; | |
683 goto send; | |
684 } else if(strcmp(p, "refresh")==0){ | |
685 needrefresh = 1; | |
686 goto send; | |
687 } | |
688 | |
689 /* | |
690 * kill previous reply | |
691 */ | |
692 mf->nrr = 0; | |
693 mf->rr[0] = 0; | |
694 | |
695 /* | |
696 * break up request (into a name and a type) | |
697 */ | |
698 atype = strchr(job->request.data, ' '); | |
699 if(atype == 0){ | |
700 err = "illegal request"; | |
701 goto send; | |
702 } else | |
703 *atype++ = 0; | |
704 | |
705 /* | |
706 * tracing request | |
707 */ | |
708 if(strcmp(atype, "trace") == 0){ | |
709 if(trace) | |
710 free(trace); | |
711 if(*job->request.data) | |
712 trace = estrdup(job->request.data); | |
713 else | |
714 trace = 0; | |
715 goto send; | |
716 } | |
717 | |
718 mf->type = rrtype(atype); | |
719 if(mf->type < 0){ | |
720 err = "unknown type"; | |
721 goto send; | |
722 } | |
723 | |
724 p = atype - 2; | |
725 if(p >= job->request.data && *p == '.'){ | |
726 rooted = 1; | |
727 *p = 0; | |
728 } else | |
729 rooted = 0; | |
730 | |
731 p = job->request.data; | |
732 if(*p == '!'){ | |
733 wantsav = 1; | |
734 p++; | |
735 } else | |
736 wantsav = 0; | |
737 dncheck(0, 1); | |
738 rp = dnresolve(p, Cin, mf->type, req, 0, 0, Recurse, rooted, &st… | |
739 dncheck(0, 1); | |
740 neg = rrremneg(&rp); | |
741 if(neg){ | |
742 status = neg->negrcode; | |
743 rrfreelist(neg); | |
744 } | |
745 if(rp == 0){ | |
746 switch(status){ | |
747 case Rname: | |
748 err = "name does not exist"; | |
749 break; | |
750 case Rserver: | |
751 err = "dns failure"; | |
752 break; | |
753 default: | |
754 err = "resource does not exist"; | |
755 break; | |
756 } | |
757 } else { | |
758 lock(&joblock); | |
759 if(!job->flushed){ | |
760 /* format data to be read later */ | |
761 n = 0; | |
762 mf->nrr = 0; | |
763 for(tp = rp; mf->nrr < Maxrrr-1 && n < Maxreply … | |
764 tsame(mf->type, tp->type); tp = … | |
765 mf->rr[mf->nrr++] = n; | |
766 if(wantsav) | |
767 n += snprint(mf->reply+n, Maxrep… | |
768 else | |
769 n += snprint(mf->reply+n, Maxrep… | |
770 } | |
771 mf->rr[mf->nrr] = n; | |
772 } | |
773 unlock(&joblock); | |
774 rrfreelist(rp); | |
775 } | |
776 | |
777 send: | |
778 dncheck(0, 1); | |
779 job->reply.count = cnt; | |
780 sendmsg(job, err); | |
781 } | |
782 | |
783 void | |
784 rclunk(Job *job, Mfile *mf) | |
785 { | |
786 freefid(mf); | |
787 sendmsg(job, 0); | |
788 } | |
789 | |
790 void | |
791 rremove(Job *job, Mfile *mf) | |
792 { | |
793 USED(mf); | |
794 sendmsg(job, "remove permission denied"); | |
795 } | |
796 | |
797 void | |
798 rstat(Job *job, Mfile *mf) | |
799 { | |
800 Dir dir; | |
801 uchar buf[IOHDRSZ+Maxfdata]; | |
802 | |
803 if(mf->qid.type & QTDIR){ | |
804 dir.name = "."; | |
805 dir.mode = DMDIR|0555; | |
806 } else { | |
807 dir.name = "dns"; | |
808 dir.mode = 0666; | |
809 } | |
810 dir.qid = mf->qid; | |
811 dir.length = 0; | |
812 dir.uid = mf->user; | |
813 dir.gid = mf->user; | |
814 dir.muid = mf->user; | |
815 dir.atime = dir.mtime = time(0); | |
816 job->reply.nstat = convD2M(&dir, buf, sizeof buf); | |
817 job->reply.stat = buf; | |
818 sendmsg(job, 0); | |
819 } | |
820 | |
821 void | |
822 rwstat(Job *job, Mfile *mf) | |
823 { | |
824 USED(mf); | |
825 sendmsg(job, "wstat permission denied"); | |
826 } | |
827 | |
828 void | |
829 sendmsg(Job *job, char *err) | |
830 { | |
831 int n; | |
832 uchar mdata[IOHDRSZ + Maxfdata]; | |
833 char ename[ERRMAX]; | |
834 | |
835 if(err){ | |
836 job->reply.type = Rerror; | |
837 snprint(ename, sizeof(ename), "dns: %s", err); | |
838 job->reply.ename = ename; | |
839 }else{ | |
840 job->reply.type = job->request.type+1; | |
841 } | |
842 job->reply.tag = job->request.tag; | |
843 n = convS2M(&job->reply, mdata, sizeof mdata); | |
844 if(n == 0){ | |
845 syslog(1, logfile, "sendmsg convS2M of %F returns 0", &j… | |
846 abort(); | |
847 } | |
848 lock(&joblock); | |
849 if(job->flushed == 0) | |
850 if(write(mfd[1], mdata, n)!=n) | |
851 sysfatal("mount write"); | |
852 unlock(&joblock); | |
853 if(debug) | |
854 syslog(0, logfile, "%F %d", &job->reply, n); | |
855 } | |
856 | |
857 /* | |
858 * the following varies between dnsdebug and dns | |
859 */ | |
860 void | |
861 logreply(int id, uchar *addr, DNSmsg *mp) | |
862 { | |
863 RR *rp; | |
864 | |
865 syslog(0, LOG, "%d: rcvd %I flags:%s%s%s%s%s", id, addr, | |
866 mp->flags & Fauth ? " auth" : "", | |
867 mp->flags & Ftrunc ? " trunc" : "", | |
868 mp->flags & Frecurse ? " rd" : "", | |
869 mp->flags & Fcanrec ? " ra" : "", | |
870 mp->flags & (Fauth|Rname) == (Fauth|Rname) ? | |
871 " nx" : ""); | |
872 for(rp = mp->qd; rp != nil; rp = rp->next) | |
873 syslog(0, LOG, "%d: rcvd %I qd %s", id, addr, rp->owner-… | |
874 for(rp = mp->an; rp != nil; rp = rp->next) | |
875 syslog(0, LOG, "%d: rcvd %I an %R", id, addr, rp); | |
876 for(rp = mp->ns; rp != nil; rp = rp->next) | |
877 syslog(0, LOG, "%d: rcvd %I ns %R", id, addr, rp); | |
878 for(rp = mp->ar; rp != nil; rp = rp->next) | |
879 syslog(0, LOG, "%d: rcvd %I ar %R", id, addr, rp); | |
880 } | |
881 | |
882 void | |
883 logsend(int id, int subid, uchar *addr, char *sname, char *rname, int ty… | |
884 { | |
885 char buf[12]; | |
886 | |
887 syslog(0, LOG, "%d.%d: sending to %I/%s %s %s", | |
888 id, subid, addr, sname, rname, rrname(type, buf, sizeof … | |
889 } | |
890 | |
891 RR* | |
892 getdnsservers(int class) | |
893 { | |
894 return dnsservers(class); | |
895 } |