dns.c 15 KB

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