dns.c 21 KB

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