dns.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968
  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. Maxreply= 8192, /* was 512 */
  14. Maxrrr= 32, /* was 16 */
  15. Maxfdata= 8192,
  16. Defmaxage= 60*60, /* default domain name max. age */
  17. Qdir= 0,
  18. Qdns= 1,
  19. };
  20. typedef struct Mfile Mfile;
  21. typedef struct Job Job;
  22. typedef struct Network Network;
  23. int vers; /* incremented each clone/attach */
  24. static volatile int stop;
  25. /* holds data to be returned via read of /net/dns, perhaps multiple reads */
  26. struct Mfile
  27. {
  28. Mfile *next; /* next free mfile */
  29. int ref;
  30. char *user;
  31. Qid qid;
  32. int fid;
  33. int type; /* reply type */
  34. char reply[Maxreply];
  35. ushort rr[Maxrrr]; /* offset of rr's */
  36. ushort nrr; /* number of rr's */
  37. };
  38. /*
  39. * active local requests
  40. */
  41. struct Job
  42. {
  43. Job *next;
  44. int flushed;
  45. Fcall request;
  46. Fcall reply;
  47. };
  48. Lock joblock;
  49. Job *joblist;
  50. struct {
  51. Lock;
  52. Mfile *inuse; /* active mfile's */
  53. } mfalloc;
  54. Cfg cfg;
  55. int debug;
  56. uchar ipaddr[IPaddrlen]; /* my ip address */
  57. int maxage = Defmaxage;
  58. int mfd[2];
  59. int needrefresh;
  60. ulong now;
  61. vlong nowns;
  62. int sendnotifies;
  63. int testing;
  64. char *trace;
  65. int traceactivity;
  66. char *zonerefreshprogram;
  67. char *logfile = "dns"; /* or "dns.test" */
  68. char *dbfile;
  69. char mntpt[Maxpath];
  70. int fillreply(Mfile*, int);
  71. void freejob(Job*);
  72. void io(void);
  73. void mountinit(char*, char*);
  74. Job* newjob(void);
  75. void rattach(Job*, Mfile*);
  76. void rauth(Job*);
  77. void rclunk(Job*, Mfile*);
  78. void rcreate(Job*, Mfile*);
  79. void rflush(Job*);
  80. void ropen(Job*, Mfile*);
  81. void rread(Job*, Mfile*);
  82. void rremove(Job*, Mfile*);
  83. void rstat(Job*, Mfile*);
  84. void rversion(Job*);
  85. char* rwalk(Job*, Mfile*);
  86. void rwrite(Job*, Mfile*, Request*);
  87. void rwstat(Job*, Mfile*);
  88. void sendmsg(Job*, char*);
  89. void setext(char*, int, char*);
  90. void
  91. usage(void)
  92. {
  93. fprint(2, "usage: %s [-FnorRst] [-a maxage] [-f ndb-file] [-N target] "
  94. "[-T forwip] [-x netmtpt] [-z refreshprog]\n", argv0);
  95. exits("usage");
  96. }
  97. int addforwtarg(char *);
  98. void
  99. main(int argc, char *argv[])
  100. {
  101. int kid, pid;
  102. char servefile[Maxpath], ext[Maxpath];
  103. Dir *dir;
  104. setnetmtpt(mntpt, sizeof mntpt, nil);
  105. ext[0] = 0;
  106. ARGBEGIN{
  107. case 'a':
  108. maxage = atol(EARGF(usage()));
  109. if (maxage <= 0)
  110. maxage = Defmaxage;
  111. break;
  112. case 'd':
  113. debug = 1;
  114. traceactivity = 1;
  115. break;
  116. case 'f':
  117. dbfile = EARGF(usage());
  118. break;
  119. case 'F':
  120. cfg.justforw = cfg.resolver = 1;
  121. break;
  122. case 'n':
  123. sendnotifies = 1;
  124. break;
  125. case 'N':
  126. target = atol(EARGF(usage()));
  127. if (target < 1000)
  128. target = 1000;
  129. break;
  130. case 'o':
  131. cfg.straddle = 1; /* straddle inside & outside networks */
  132. break;
  133. case 'r':
  134. cfg.resolver = 1;
  135. break;
  136. case 'R':
  137. norecursion = 1;
  138. break;
  139. case 's':
  140. cfg.serve = 1; /* serve network */
  141. cfg.cachedb = 1;
  142. break;
  143. case 't':
  144. testing = 1;
  145. break;
  146. case 'T':
  147. addforwtarg(EARGF(usage()));
  148. break;
  149. case 'x':
  150. setnetmtpt(mntpt, sizeof mntpt, EARGF(usage()));
  151. setext(ext, sizeof ext, mntpt);
  152. break;
  153. case 'z':
  154. zonerefreshprogram = EARGF(usage());
  155. break;
  156. }ARGEND
  157. USED(argc);
  158. USED(argv);
  159. if(testing)
  160. mainmem->flags |= POOL_NOREUSE | POOL_ANTAGONISM;
  161. mainmem->flags |= POOL_ANTAGONISM;
  162. rfork(RFREND|RFNOTEG);
  163. cfg.inside = (*mntpt == '\0' || strcmp(mntpt, "/net") == 0);
  164. /* start syslog before we fork */
  165. fmtinstall('F', fcallfmt);
  166. dninit();
  167. /* this really shouldn't be fatal */
  168. if(myipaddr(ipaddr, mntpt) < 0)
  169. sysfatal("can't read my ip address");
  170. dnslog("starting %s%sdns %s%s%son %I's %s",
  171. (cfg.straddle? "straddling ": ""),
  172. (cfg.cachedb? "caching ": ""),
  173. (cfg.serve? "udp server ": ""),
  174. (cfg.justforw? "forwarding-only ": ""),
  175. (cfg.resolver? "resolver ": ""), ipaddr, mntpt);
  176. opendatabase();
  177. now = time(nil); /* open time files before we fork */
  178. nowns = nsec();
  179. snprint(servefile, sizeof servefile, "#s/dns%s", ext);
  180. dir = dirstat(servefile);
  181. if (dir)
  182. sysfatal("%s exists; another dns instance is running",
  183. servefile);
  184. free(dir);
  185. // unmount(servefile, mntpt);
  186. // remove(servefile);
  187. mountinit(servefile, mntpt); /* forks, parent exits */
  188. srand(now*getpid());
  189. db2cache(1);
  190. // dnageallnever();
  191. if (cfg.straddle && !seerootns())
  192. dnslog("straddle server misconfigured; can't see root name servers");
  193. /*
  194. * fork without sharing heap.
  195. * parent waits around for child to die, then forks & restarts.
  196. * child may spawn udp server, notify procs, etc.; when it gets too
  197. * big, it kills itself and any children.
  198. * /srv/dns and /net/dns remain open and valid.
  199. */
  200. for (;;) {
  201. kid = rfork(RFPROC|RFFDG|RFNOTEG);
  202. switch (kid) {
  203. case -1:
  204. sysfatal("fork failed: %r");
  205. case 0:
  206. if(cfg.serve)
  207. dnudpserver(mntpt);
  208. if(sendnotifies)
  209. notifyproc();
  210. io();
  211. _exits("restart");
  212. default:
  213. while ((pid = waitpid()) != kid && pid != -1)
  214. continue;
  215. break;
  216. }
  217. dnslog("dns restarting");
  218. }
  219. }
  220. /*
  221. * if a mount point is specified, set the cs extension to be the mount point
  222. * with '_'s replacing '/'s
  223. */
  224. void
  225. setext(char *ext, int n, char *p)
  226. {
  227. int i, c;
  228. n--;
  229. for(i = 0; i < n; i++){
  230. c = p[i];
  231. if(c == 0)
  232. break;
  233. if(c == '/')
  234. c = '_';
  235. ext[i] = c;
  236. }
  237. ext[i] = 0;
  238. }
  239. void
  240. mountinit(char *service, char *mntpt)
  241. {
  242. int f;
  243. int p[2];
  244. char buf[32];
  245. if(pipe(p) < 0)
  246. abort(); /* "pipe failed" */;
  247. /* copy namespace to avoid a deadlock */
  248. switch(rfork(RFFDG|RFPROC|RFNAMEG)){
  249. case 0: /* child: hang around and (re)start main proc */
  250. close(p[1]);
  251. procsetname("%s restarter", mntpt);
  252. break;
  253. case -1:
  254. abort(); /* "fork failed\n" */;
  255. default: /* parent: make /srv/dns, mount it, exit */
  256. close(p[0]);
  257. /*
  258. * make a /srv/dns
  259. */
  260. f = create(service, 1, 0666);
  261. if(f < 0)
  262. abort(); /* service */;
  263. snprint(buf, sizeof buf, "%d", p[1]);
  264. if(write(f, buf, strlen(buf)) != strlen(buf))
  265. abort(); /* "write %s", service */;
  266. close(f);
  267. /*
  268. * put ourselves into the file system
  269. */
  270. if(mount(p[1], -1, mntpt, MAFTER, "") < 0)
  271. fprint(2, "dns mount failed: %r\n");
  272. _exits(0);
  273. }
  274. mfd[0] = mfd[1] = p[0];
  275. }
  276. Mfile*
  277. newfid(int fid, int needunused)
  278. {
  279. Mfile *mf;
  280. lock(&mfalloc);
  281. for(mf = mfalloc.inuse; mf != nil; mf = mf->next)
  282. if(mf->fid == fid){
  283. unlock(&mfalloc);
  284. if(needunused)
  285. return nil;
  286. return mf;
  287. }
  288. mf = emalloc(sizeof(*mf));
  289. mf->fid = fid;
  290. mf->next = mfalloc.inuse;
  291. mf->user = estrdup("dummy");
  292. mfalloc.inuse = mf;
  293. unlock(&mfalloc);
  294. return mf;
  295. }
  296. void
  297. freefid(Mfile *mf)
  298. {
  299. Mfile **l;
  300. lock(&mfalloc);
  301. for(l = &mfalloc.inuse; *l != nil; l = &(*l)->next)
  302. if(*l == mf){
  303. *l = mf->next;
  304. if(mf->user)
  305. free(mf->user);
  306. memset(mf, 0, sizeof *mf); /* cause trouble */
  307. free(mf);
  308. unlock(&mfalloc);
  309. return;
  310. }
  311. sysfatal("freeing unused fid");
  312. }
  313. Mfile*
  314. copyfid(Mfile *mf, int fid)
  315. {
  316. Mfile *nmf;
  317. nmf = newfid(fid, 1);
  318. if(nmf == nil)
  319. return nil;
  320. nmf->fid = fid;
  321. nmf->user = estrdup(mf->user);
  322. nmf->qid.type = mf->qid.type;
  323. nmf->qid.path = mf->qid.path;
  324. nmf->qid.vers = vers++;
  325. return nmf;
  326. }
  327. Job*
  328. newjob(void)
  329. {
  330. Job *job;
  331. job = emalloc(sizeof *job);
  332. lock(&joblock);
  333. job->next = joblist;
  334. joblist = job;
  335. job->request.tag = -1;
  336. unlock(&joblock);
  337. return job;
  338. }
  339. void
  340. freejob(Job *job)
  341. {
  342. Job **l;
  343. lock(&joblock);
  344. for(l = &joblist; *l; l = &(*l)->next)
  345. if(*l == job){
  346. *l = job->next;
  347. memset(job, 0, sizeof *job); /* cause trouble */
  348. free(job);
  349. break;
  350. }
  351. unlock(&joblock);
  352. }
  353. void
  354. flushjob(int tag)
  355. {
  356. Job *job;
  357. lock(&joblock);
  358. for(job = joblist; job; job = job->next)
  359. if(job->request.tag == tag && job->request.type != Tflush){
  360. job->flushed = 1;
  361. break;
  362. }
  363. unlock(&joblock);
  364. }
  365. void
  366. io(void)
  367. {
  368. volatile long n;
  369. volatile uchar mdata[IOHDRSZ + Maxfdata];
  370. Job *volatile job;
  371. Mfile *volatile mf;
  372. volatile Request req;
  373. memset(&req, 0, sizeof req);
  374. /*
  375. * a slave process is sometimes forked to wait for replies from other
  376. * servers. The master process returns immediately via a longjmp
  377. * through 'mret'.
  378. */
  379. if(setjmp(req.mret))
  380. putactivity(0);
  381. // procsetname("9p server");
  382. req.isslave = 0;
  383. stop = 0;
  384. while(!stop){
  385. procsetname("%d %s/dns Twrites of %d 9p rpcs read; %d alarms",
  386. stats.qrecvd9p, mntpt, stats.qrecvd9prpc, stats.alarms);
  387. n = read9pmsg(mfd[0], mdata, sizeof mdata);
  388. if(n<=0){
  389. dnslog("error reading 9P from %s: %r", mntpt);
  390. sleep(2000); /* don't thrash */
  391. return;
  392. }
  393. stats.qrecvd9prpc++;
  394. job = newjob();
  395. if(convM2S(mdata, n, &job->request) != n){
  396. freejob(job);
  397. continue;
  398. }
  399. mf = newfid(job->request.fid, 0);
  400. if(debug)
  401. dnslog("%F", &job->request);
  402. getactivity(&req, 0);
  403. req.aborttime = time(nil) + Maxreqtm;
  404. req.from = "9p";
  405. switch(job->request.type){
  406. default:
  407. warning("unknown request type %d", job->request.type);
  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. /* &req is handed to dnresolve() */
  435. rwrite(job, mf, &req);
  436. break;
  437. case Tclunk:
  438. rclunk(job, mf);
  439. break;
  440. case Tremove:
  441. rremove(job, mf);
  442. break;
  443. case Tstat:
  444. rstat(job, mf);
  445. break;
  446. case Twstat:
  447. rwstat(job, mf);
  448. break;
  449. }
  450. freejob(job);
  451. /*
  452. * slave processes die after replying
  453. */
  454. if(req.isslave){
  455. putactivity(0);
  456. _exits(0);
  457. }
  458. putactivity(0);
  459. }
  460. /* kill any udp server, notifier, etc. processes */
  461. postnote(PNGROUP, getpid(), "die");
  462. sleep(1000);
  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. void
  479. rauth(Job *job)
  480. {
  481. sendmsg(job, "dns: authentication not required");
  482. }
  483. /*
  484. * don't flush till all the slaves are done
  485. */
  486. void
  487. rflush(Job *job)
  488. {
  489. flushjob(job->request.oldtag);
  490. sendmsg(job, 0);
  491. }
  492. void
  493. rattach(Job *job, Mfile *mf)
  494. {
  495. if(mf->user != nil)
  496. free(mf->user);
  497. mf->user = estrdup(job->request.uname);
  498. mf->qid.vers = vers++;
  499. mf->qid.type = QTDIR;
  500. mf->qid.path = 0LL;
  501. job->reply.qid = mf->qid;
  502. sendmsg(job, 0);
  503. }
  504. char*
  505. rwalk(Job *job, Mfile *mf)
  506. {
  507. int i, nelems;
  508. char *err;
  509. char **elems;
  510. Mfile *nmf;
  511. Qid qid;
  512. err = 0;
  513. nmf = nil;
  514. elems = job->request.wname;
  515. nelems = job->request.nwname;
  516. job->reply.nwqid = 0;
  517. if(job->request.newfid != job->request.fid){
  518. /* clone fid */
  519. nmf = copyfid(mf, job->request.newfid);
  520. if(nmf == nil){
  521. err = "clone bad newfid";
  522. goto send;
  523. }
  524. mf = nmf;
  525. }
  526. /* else nmf will be nil */
  527. qid = mf->qid;
  528. if(nelems > 0)
  529. /* walk fid */
  530. for(i=0; i<nelems && i<MAXWELEM; i++){
  531. if((qid.type & QTDIR) == 0){
  532. err = "not a directory";
  533. break;
  534. }
  535. if (strcmp(elems[i], "..") == 0 ||
  536. strcmp(elems[i], ".") == 0){
  537. qid.type = QTDIR;
  538. qid.path = Qdir;
  539. Found:
  540. job->reply.wqid[i] = qid;
  541. job->reply.nwqid++;
  542. continue;
  543. }
  544. if(strcmp(elems[i], "dns") == 0){
  545. qid.type = QTFILE;
  546. qid.path = Qdns;
  547. goto Found;
  548. }
  549. err = "file does not exist";
  550. break;
  551. }
  552. send:
  553. if(nmf != nil && (err!=nil || job->reply.nwqid<nelems))
  554. freefid(nmf);
  555. if(err == nil)
  556. mf->qid = qid;
  557. sendmsg(job, err);
  558. return err;
  559. }
  560. void
  561. ropen(Job *job, Mfile *mf)
  562. {
  563. int mode;
  564. char *err;
  565. err = 0;
  566. mode = job->request.mode;
  567. if(mf->qid.type & QTDIR)
  568. if(mode)
  569. err = "permission denied";
  570. job->reply.qid = mf->qid;
  571. job->reply.iounit = 0;
  572. sendmsg(job, err);
  573. }
  574. void
  575. rcreate(Job *job, Mfile *mf)
  576. {
  577. USED(mf);
  578. sendmsg(job, "creation permission denied");
  579. }
  580. void
  581. rread(Job *job, Mfile *mf)
  582. {
  583. int i, n;
  584. long clock;
  585. ulong cnt;
  586. vlong off;
  587. char *err;
  588. uchar buf[Maxfdata];
  589. Dir dir;
  590. n = 0;
  591. err = nil;
  592. off = job->request.offset;
  593. cnt = job->request.count;
  594. *buf = '\0';
  595. job->reply.data = (char*)buf;
  596. if(mf->qid.type & QTDIR){
  597. clock = time(nil);
  598. if(off == 0){
  599. memset(&dir, 0, sizeof dir);
  600. dir.name = "dns";
  601. dir.qid.type = QTFILE;
  602. dir.qid.vers = vers;
  603. dir.qid.path = Qdns;
  604. dir.mode = 0666;
  605. dir.length = 0;
  606. dir.uid = dir.gid = dir.muid = mf->user;
  607. dir.atime = dir.mtime = clock; /* wrong */
  608. n = convD2M(&dir, buf, sizeof buf);
  609. }
  610. } else if (off < 0)
  611. err = "negative read offset";
  612. else {
  613. /* first offset will always be zero */
  614. for(i = 1; i <= mf->nrr; i++)
  615. if(mf->rr[i] > off)
  616. break;
  617. if(i <= mf->nrr) {
  618. if(off + cnt > mf->rr[i])
  619. n = mf->rr[i] - off;
  620. else
  621. n = cnt;
  622. assert(n >= 0);
  623. job->reply.data = mf->reply + off;
  624. }
  625. }
  626. job->reply.count = n;
  627. sendmsg(job, err);
  628. }
  629. void
  630. rwrite(Job *job, Mfile *mf, Request *req)
  631. {
  632. int rooted, status, wantsav;
  633. long n;
  634. ulong cnt;
  635. char *err, *p, *atype;
  636. RR *rp, *tp, *neg;
  637. err = nil;
  638. cnt = job->request.count;
  639. if(mf->qid.type & QTDIR){
  640. err = "can't write directory";
  641. goto send;
  642. }
  643. if (job->request.offset != 0) {
  644. err = "writing at non-zero offset";
  645. goto send;
  646. }
  647. if(cnt >= Maxrequest){
  648. err = "request too long";
  649. goto send;
  650. }
  651. job->request.data[cnt] = 0;
  652. if(cnt > 0 && job->request.data[cnt-1] == '\n')
  653. job->request.data[cnt-1] = 0;
  654. /*
  655. * special commands
  656. */
  657. // dnslog("rwrite got: %s", job->request.data);
  658. if(strcmp(job->request.data, "debug")==0){
  659. debug ^= 1;
  660. goto send;
  661. } else if(strcmp(job->request.data, "dump")==0){
  662. dndump("/lib/ndb/dnsdump");
  663. goto send;
  664. } else if(strcmp(job->request.data, "poolcheck")==0){
  665. poolcheck(mainmem);
  666. goto send;
  667. } else if(strcmp(job->request.data, "refresh")==0){
  668. needrefresh = 1;
  669. goto send;
  670. } else if(strcmp(job->request.data, "restart")==0){
  671. stop = 1;
  672. goto send;
  673. } else if(strcmp(job->request.data, "stats")==0){
  674. dnstats("/lib/ndb/dnsstats");
  675. goto send;
  676. } else if(strncmp(job->request.data, "target ", 7)==0){
  677. target = atol(job->request.data + 7);
  678. dnslog("target set to %ld", target);
  679. goto send;
  680. } else if(strcmp(job->request.data, "age")==0){
  681. dnslog("dump, age & dump forced");
  682. dndump("/lib/ndb/dnsdump1");
  683. dnforceage();
  684. dndump("/lib/ndb/dnsdump2");
  685. goto send;
  686. }
  687. /*
  688. * kill previous reply
  689. */
  690. mf->nrr = 0;
  691. mf->rr[0] = 0;
  692. /*
  693. * break up request (into a name and a type)
  694. */
  695. atype = strchr(job->request.data, ' ');
  696. if(atype == 0){
  697. err = "illegal request";
  698. goto send;
  699. } else
  700. *atype++ = 0;
  701. /*
  702. * tracing request
  703. */
  704. if(strcmp(atype, "trace") == 0){
  705. if(trace)
  706. free(trace);
  707. if(*job->request.data)
  708. trace = estrdup(job->request.data);
  709. else
  710. trace = 0;
  711. goto send;
  712. }
  713. /* normal request: domain [type] */
  714. stats.qrecvd9p++;
  715. mf->type = rrtype(atype);
  716. if(mf->type < 0){
  717. err = "unknown type";
  718. goto send;
  719. }
  720. p = atype - 2;
  721. if(p >= job->request.data && *p == '.'){
  722. rooted = 1;
  723. *p = 0;
  724. } else
  725. rooted = 0;
  726. p = job->request.data;
  727. if(*p == '!'){
  728. wantsav = 1;
  729. p++;
  730. } else
  731. wantsav = 0;
  732. dncheck(0, 1);
  733. status = 0;
  734. rp = dnresolve(p, Cin, mf->type, req, 0, 0, Recurse, rooted, &status);
  735. dncheck(0, 1);
  736. neg = rrremneg(&rp);
  737. if(neg){
  738. status = neg->negrcode;
  739. rrfreelist(neg);
  740. }
  741. if(rp == nil)
  742. switch(status){
  743. case Rname:
  744. err = "name does not exist";
  745. break;
  746. case Rserver:
  747. err = "dns failure";
  748. break;
  749. default:
  750. err = "resource does not exist";
  751. break;
  752. }
  753. else {
  754. lock(&joblock);
  755. if(!job->flushed){
  756. /* format data to be read later */
  757. n = 0;
  758. mf->nrr = 0;
  759. for(tp = rp; mf->nrr < Maxrrr-1 && n < Maxreply && tp &&
  760. tsame(mf->type, tp->type); tp = tp->next){
  761. mf->rr[mf->nrr++] = n;
  762. if(wantsav)
  763. n += snprint(mf->reply+n, Maxreply-n,
  764. "%Q", tp);
  765. else
  766. n += snprint(mf->reply+n, Maxreply-n,
  767. "%R", tp);
  768. }
  769. mf->rr[mf->nrr] = n;
  770. }
  771. unlock(&joblock);
  772. rrfreelist(rp);
  773. }
  774. send:
  775. dncheck(0, 1);
  776. job->reply.count = cnt;
  777. sendmsg(job, err);
  778. }
  779. void
  780. rclunk(Job *job, Mfile *mf)
  781. {
  782. freefid(mf);
  783. sendmsg(job, 0);
  784. }
  785. void
  786. rremove(Job *job, Mfile *mf)
  787. {
  788. USED(mf);
  789. sendmsg(job, "remove permission denied");
  790. }
  791. void
  792. rstat(Job *job, Mfile *mf)
  793. {
  794. Dir dir;
  795. uchar buf[IOHDRSZ+Maxfdata];
  796. memset(&dir, 0, sizeof dir);
  797. if(mf->qid.type & QTDIR){
  798. dir.name = ".";
  799. dir.mode = DMDIR|0555;
  800. } else {
  801. dir.name = "dns";
  802. dir.mode = 0666;
  803. }
  804. dir.qid = mf->qid;
  805. dir.length = 0;
  806. dir.uid = dir.gid = dir.muid = mf->user;
  807. dir.atime = dir.mtime = time(nil);
  808. job->reply.nstat = convD2M(&dir, buf, sizeof buf);
  809. job->reply.stat = buf;
  810. sendmsg(job, 0);
  811. }
  812. void
  813. rwstat(Job *job, Mfile *mf)
  814. {
  815. USED(mf);
  816. sendmsg(job, "wstat permission denied");
  817. }
  818. void
  819. sendmsg(Job *job, char *err)
  820. {
  821. int n;
  822. uchar mdata[IOHDRSZ + Maxfdata];
  823. char ename[ERRMAX];
  824. if(err){
  825. job->reply.type = Rerror;
  826. snprint(ename, sizeof ename, "dns: %s", err);
  827. job->reply.ename = ename;
  828. }else
  829. job->reply.type = job->request.type+1;
  830. job->reply.tag = job->request.tag;
  831. n = convS2M(&job->reply, mdata, sizeof mdata);
  832. if(n == 0){
  833. warning("sendmsg convS2M of %F returns 0", &job->reply);
  834. abort();
  835. }
  836. lock(&joblock);
  837. if(job->flushed == 0)
  838. if(write(mfd[1], mdata, n)!=n)
  839. sysfatal("mount write");
  840. unlock(&joblock);
  841. if(debug)
  842. dnslog("%F %d", &job->reply, n);
  843. }
  844. /*
  845. * the following varies between dnsdebug and dns
  846. */
  847. void
  848. logreply(int id, uchar *addr, DNSmsg *mp)
  849. {
  850. RR *rp;
  851. dnslog("%d: rcvd %I flags:%s%s%s%s%s", id, addr,
  852. mp->flags & Fauth? " auth": "",
  853. mp->flags & Ftrunc? " trunc": "",
  854. mp->flags & Frecurse? " rd": "",
  855. mp->flags & Fcanrec? " ra": "",
  856. (mp->flags & (Fauth|Rmask)) == (Fauth|Rname)? " nx": "");
  857. for(rp = mp->qd; rp != nil; rp = rp->next)
  858. dnslog("%d: rcvd %I qd %s", id, addr, rp->owner->name);
  859. for(rp = mp->an; rp != nil; rp = rp->next)
  860. dnslog("%d: rcvd %I an %R", id, addr, rp);
  861. for(rp = mp->ns; rp != nil; rp = rp->next)
  862. dnslog("%d: rcvd %I ns %R", id, addr, rp);
  863. for(rp = mp->ar; rp != nil; rp = rp->next)
  864. dnslog("%d: rcvd %I ar %R", id, addr, rp);
  865. }
  866. void
  867. logsend(int id, int subid, uchar *addr, char *sname, char *rname, int type)
  868. {
  869. char buf[12];
  870. dnslog("[%d] %d.%d: sending to %I/%s %s %s",
  871. getpid(), id, subid, addr, sname, rname,
  872. rrname(type, buf, sizeof buf));
  873. }
  874. RR*
  875. getdnsservers(int class)
  876. {
  877. return dnsservers(class);
  878. }