dns.c 15 KB

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