dnresolve.c 30 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375
  1. /*
  2. * domain name resolvers, see rfcs 1035 and 1123
  3. */
  4. #include <u.h>
  5. #include <libc.h>
  6. #include <ip.h>
  7. #include <bio.h>
  8. #include <ndb.h>
  9. #include "dns.h"
  10. typedef struct Dest Dest;
  11. typedef struct Ipaddr Ipaddr;
  12. typedef struct Query Query;
  13. typedef struct Sluggards Sluggards;
  14. enum
  15. {
  16. Udp, Tcp,
  17. Maxdest= 24, /* maximum destinations for a request message */
  18. Maxtrans= 3, /* maximum transmissions to a server */
  19. Destmagic= 0xcafebabe,
  20. Querymagic= 0xdeadbeef,
  21. };
  22. struct Ipaddr {
  23. Ipaddr *next;
  24. uchar ip[IPaddrlen];
  25. };
  26. struct Dest
  27. {
  28. uchar a[IPaddrlen]; /* ip address */
  29. DN *s; /* name server */
  30. int nx; /* number of transmissions */
  31. int code; /* response code; used to clear dp->respcode */
  32. ulong magic;
  33. };
  34. struct Query {
  35. DN *dp; /* domain */
  36. int type; /* and type to look up */
  37. Request *req;
  38. RR *nsrp; /* name servers to consult */
  39. Dest *dest; /* array of destinations */
  40. Dest *curdest; /* pointer to one of them */
  41. int ndest;
  42. int udpfd; /* can be shared by all udp users */
  43. QLock tcplock; /* only one tcp call at a time per query */
  44. int tcpset;
  45. int tcpfd; /* if Tcp, read replies from here */
  46. int tcpctlfd;
  47. uchar tcpip[IPaddrlen];
  48. ulong magic;
  49. };
  50. /* a list of sluggardly name servers */
  51. struct Sluggards {
  52. QLock;
  53. Ipaddr *head;
  54. Ipaddr *tail;
  55. };
  56. static Sluggards slugs;
  57. static RR* dnresolve1(char*, int, int, Request*, int, int);
  58. static int netquery(Query *, int);
  59. static Ipaddr *
  60. newslug(void)
  61. {
  62. return emalloc(sizeof(Ipaddr));
  63. }
  64. static void
  65. addslug(uchar nsip[])
  66. {
  67. Ipaddr *sp;
  68. static uchar zip[IPaddrlen];
  69. if (memcmp(nsip, zip, IPaddrlen) == 0)
  70. return;
  71. qlock(&slugs);
  72. for (sp = slugs.head; sp != nil; sp = sp->next)
  73. if (memcmp(sp->ip, nsip, IPaddrlen) == 0) {
  74. qunlock(&slugs); /* already know it */
  75. return;
  76. }
  77. if (slugs.head == nil)
  78. slugs.head = slugs.tail = newslug();
  79. else {
  80. slugs.tail->next = newslug();
  81. slugs.tail = slugs.tail->next;
  82. }
  83. memmove(slugs.tail->ip, nsip, IPaddrlen);
  84. qunlock(&slugs);
  85. dnslog("%I is a slug", nsip);
  86. }
  87. int
  88. isaslug(uchar nsip[])
  89. {
  90. Ipaddr *sp;
  91. qlock(&slugs);
  92. for (sp = slugs.head; sp != nil; sp = sp->next)
  93. if (memcmp(sp->ip, nsip, IPaddrlen) == 0) {
  94. qunlock(&slugs);
  95. return 1;
  96. }
  97. qunlock(&slugs);
  98. return 0;
  99. }
  100. /*
  101. * reading /proc/pid/args yields either "name" or "name [display args]",
  102. * so return only display args, if any.
  103. */
  104. static char *
  105. procgetname(void)
  106. {
  107. int fd, n;
  108. char *lp, *rp;
  109. char buf[256];
  110. snprint(buf, sizeof buf, "#p/%d/args", getpid());
  111. if((fd = open(buf, OREAD)) < 0)
  112. return strdup("");
  113. *buf = '\0';
  114. n = read(fd, buf, sizeof buf-1);
  115. close(fd);
  116. if (n >= 0)
  117. buf[n] = '\0';
  118. if ((lp = strchr(buf, '[')) == nil ||
  119. (rp = strrchr(buf, ']')) == nil)
  120. return strdup("");
  121. *rp = '\0';
  122. return strdup(lp+1);
  123. }
  124. /*
  125. * lookup 'type' info for domain name 'name'. If it doesn't exist, try
  126. * looking it up as a canonical name.
  127. */
  128. RR*
  129. dnresolve(char *name, int class, int type, Request *req, RR **cn, int depth,
  130. int recurse, int rooted, int *status)
  131. {
  132. RR *rp, *nrp, *drp;
  133. DN *dp;
  134. int loops;
  135. char *procname;
  136. char nname[Domlen];
  137. if(status)
  138. *status = 0;
  139. procname = procgetname();
  140. /*
  141. * hack for systems that don't have resolve search
  142. * lists. Just look up the simple name in the database.
  143. */
  144. if(!rooted && strchr(name, '.') == 0){
  145. rp = nil;
  146. drp = domainlist(class);
  147. for(nrp = drp; nrp != nil; nrp = nrp->next){
  148. snprint(nname, sizeof nname, "%s.%s", name,
  149. nrp->ptr->name);
  150. rp = dnresolve(nname, class, type, req, cn, depth,
  151. recurse, rooted, status);
  152. rrfreelist(rrremneg(&rp));
  153. if(rp != nil)
  154. break;
  155. }
  156. if(drp != nil)
  157. rrfree(drp);
  158. procsetname(procname);
  159. free(procname);
  160. return rp;
  161. }
  162. /*
  163. * try the name directly
  164. */
  165. rp = dnresolve1(name, class, type, req, depth, recurse);
  166. if(rp) {
  167. procsetname(procname);
  168. free(procname);
  169. return randomize(rp);
  170. }
  171. /* try it as a canonical name if we weren't told the name didn't exist */
  172. dp = dnlookup(name, class, 0);
  173. if(type != Tptr && dp->respcode != Rname)
  174. for(loops = 0; rp == nil && loops < 32; loops++){
  175. rp = dnresolve1(name, class, Tcname, req, depth, recurse);
  176. if(rp == nil)
  177. break;
  178. if(rp->negative){
  179. rrfreelist(rp);
  180. rp = nil;
  181. break;
  182. }
  183. name = rp->host->name;
  184. if(cn)
  185. rrcat(cn, rp);
  186. else
  187. rrfreelist(rp);
  188. rp = dnresolve1(name, class, type, req, depth, recurse);
  189. }
  190. /* distinction between not found and not good */
  191. if(rp == nil && status != nil && dp->respcode != 0)
  192. *status = dp->respcode;
  193. procsetname(procname);
  194. free(procname);
  195. return randomize(rp);
  196. }
  197. static void
  198. queryinit(Query *qp, DN *dp, int type, Request *req)
  199. {
  200. memset(qp, 0, sizeof *qp);
  201. qp->udpfd = qp->tcpfd = qp->tcpctlfd = -1;
  202. qp->dp = dp;
  203. qp->type = type;
  204. qp->req = req;
  205. qp->nsrp = nil;
  206. qp->dest = qp->curdest = nil;
  207. qp->magic = Querymagic;
  208. }
  209. static void
  210. queryck(Query *qp)
  211. {
  212. assert(qp);
  213. assert(qp->magic == Querymagic);
  214. }
  215. static void
  216. querydestroy(Query *qp)
  217. {
  218. queryck(qp);
  219. if (qp->udpfd > 0)
  220. close(qp->udpfd);
  221. if (qp->tcpfd > 0)
  222. close(qp->tcpfd);
  223. if (qp->tcpctlfd > 0) {
  224. hangup(qp->tcpctlfd);
  225. close(qp->tcpctlfd);
  226. }
  227. memset(qp, 0, sizeof *qp); /* prevent accidents */
  228. qp->udpfd = qp->tcpfd = qp->tcpctlfd = -1;
  229. }
  230. static void
  231. destinit(Dest *p)
  232. {
  233. memset(p, 0, sizeof *p);
  234. p->magic = Destmagic;
  235. }
  236. static void
  237. destck(Dest *p)
  238. {
  239. assert(p);
  240. assert(p->magic == Destmagic);
  241. }
  242. static RR*
  243. dnresolve1(char *name, int class, int type, Request *req, int depth,
  244. int recurse)
  245. {
  246. DN *dp, *nsdp;
  247. RR *rp, *nsrp, *dbnsrp;
  248. char *cp;
  249. Query query;
  250. if(debug)
  251. dnslog("[%d] dnresolve1 %s %d %d", getpid(), name, type, class);
  252. /* only class Cin implemented so far */
  253. if(class != Cin)
  254. return nil;
  255. dp = dnlookup(name, class, 1);
  256. /*
  257. * Try the cache first
  258. */
  259. rp = rrlookup(dp, type, OKneg);
  260. if(rp)
  261. if(rp->db){
  262. /* unauthoritative db entries are hints */
  263. if(rp->auth)
  264. return rp;
  265. } else
  266. /* cached entry must still be valid */
  267. if(rp->ttl > now)
  268. /* but Tall entries are special */
  269. if(type != Tall || rp->query == Tall)
  270. return rp;
  271. rrfreelist(rp);
  272. /*
  273. * try the cache for a canonical name. if found punt
  274. * since we'll find it during the canonical name search
  275. * in dnresolve().
  276. */
  277. if(type != Tcname){
  278. rp = rrlookup(dp, Tcname, NOneg);
  279. rrfreelist(rp);
  280. if(rp)
  281. return nil;
  282. }
  283. queryinit(&query, dp, type, req);
  284. /*
  285. * if we're running as just a resolver, query our
  286. * designated name servers
  287. */
  288. if(cfg.resolver){
  289. nsrp = randomize(getdnsservers(class));
  290. if(nsrp != nil) {
  291. query.nsrp = nsrp;
  292. if(netquery(&query, depth+1)){
  293. rrfreelist(nsrp);
  294. querydestroy(&query);
  295. return rrlookup(dp, type, OKneg);
  296. }
  297. rrfreelist(nsrp);
  298. }
  299. }
  300. /*
  301. * walk up the domain name looking for
  302. * a name server for the domain.
  303. */
  304. for(cp = name; cp; cp = walkup(cp)){
  305. /*
  306. * if this is a local (served by us) domain,
  307. * return answer
  308. */
  309. dbnsrp = randomize(dblookup(cp, class, Tns, 0, 0));
  310. if(dbnsrp && dbnsrp->local){
  311. rp = dblookup(name, class, type, 1, dbnsrp->ttl);
  312. rrfreelist(dbnsrp);
  313. querydestroy(&query);
  314. return rp;
  315. }
  316. /*
  317. * if recursion isn't set, just accept local
  318. * entries
  319. */
  320. if(recurse == Dontrecurse){
  321. if(dbnsrp)
  322. rrfreelist(dbnsrp);
  323. continue;
  324. }
  325. /* look for ns in cache */
  326. nsdp = dnlookup(cp, class, 0);
  327. nsrp = nil;
  328. if(nsdp)
  329. nsrp = randomize(rrlookup(nsdp, Tns, NOneg));
  330. /* if the entry timed out, ignore it */
  331. if(nsrp && nsrp->ttl < now){
  332. rrfreelist(nsrp);
  333. nsrp = nil;
  334. }
  335. if(nsrp){
  336. rrfreelist(dbnsrp);
  337. /* query the name servers found in cache */
  338. query.nsrp = nsrp;
  339. if(netquery(&query, depth+1)){
  340. rrfreelist(nsrp);
  341. querydestroy(&query);
  342. return rrlookup(dp, type, OKneg);
  343. }
  344. rrfreelist(nsrp);
  345. continue;
  346. }
  347. /* use ns from db */
  348. if(dbnsrp){
  349. /* try the name servers found in db */
  350. query.nsrp = dbnsrp;
  351. if(netquery(&query, depth+1)){
  352. /* we got an answer */
  353. rrfreelist(dbnsrp);
  354. querydestroy(&query);
  355. return rrlookup(dp, type, NOneg);
  356. }
  357. rrfreelist(dbnsrp);
  358. }
  359. }
  360. querydestroy(&query);
  361. /* settle for a non-authoritative answer */
  362. rp = rrlookup(dp, type, OKneg);
  363. if(rp)
  364. return rp;
  365. /* noone answered. try the database, we might have a chance. */
  366. return dblookup(name, class, type, 0, 0);
  367. }
  368. /*
  369. * walk a domain name one element to the right.
  370. * return a pointer to that element.
  371. * in other words, return a pointer to the parent domain name.
  372. */
  373. char*
  374. walkup(char *name)
  375. {
  376. char *cp;
  377. cp = strchr(name, '.');
  378. if(cp)
  379. return cp+1;
  380. else if(*name)
  381. return "";
  382. else
  383. return 0;
  384. }
  385. /*
  386. * Get a udpport for requests and replies. Put the port
  387. * into "headers" mode.
  388. */
  389. static char *hmsg = "headers";
  390. static char *ohmsg = "oldheaders";
  391. int
  392. udpport(char *mtpt)
  393. {
  394. int fd, ctl;
  395. char ds[64], adir[64];
  396. /* get a udp port */
  397. snprint(ds, sizeof ds, "%s/udp!*!0", (mtpt? mtpt: "/net"));
  398. ctl = announce(ds, adir);
  399. if(ctl < 0){
  400. /* warning("can't get udp port"); */
  401. return -1;
  402. }
  403. /* turn on header style interface */
  404. if(write(ctl, hmsg, strlen(hmsg)) , 0){
  405. close(ctl);
  406. warning(hmsg);
  407. return -1;
  408. }
  409. write(ctl, ohmsg, strlen(ohmsg));
  410. /* grab the data file */
  411. snprint(ds, sizeof ds, "%s/data", adir);
  412. fd = open(ds, ORDWR);
  413. close(ctl);
  414. if(fd < 0)
  415. warning("can't open udp port %s: %r", ds);
  416. return fd;
  417. }
  418. /* generate a DNS UDP query packet */
  419. int
  420. mkreq(DN *dp, int type, uchar *buf, int flags, ushort reqno)
  421. {
  422. DNSmsg m;
  423. int len;
  424. OUdphdr *uh = (OUdphdr*)buf;
  425. /* stuff port number into output buffer */
  426. memset(uh, 0, sizeof *uh);
  427. hnputs(uh->rport, 53);
  428. /* make request and convert it to output format */
  429. memset(&m, 0, sizeof m);
  430. m.flags = flags;
  431. m.id = reqno;
  432. m.qd = rralloc(type);
  433. m.qd->owner = dp;
  434. m.qd->type = type;
  435. len = convDNS2M(&m, &buf[OUdphdrsize], Maxudp);
  436. rrfree(m.qd);
  437. return len;
  438. }
  439. /* for alarms in readreply */
  440. static void
  441. ding(void *x, char *msg)
  442. {
  443. USED(x);
  444. if(strcmp(msg, "alarm") == 0)
  445. noted(NCONT);
  446. else
  447. noted(NDFLT);
  448. }
  449. static void
  450. freeanswers(DNSmsg *mp)
  451. {
  452. rrfreelist(mp->qd);
  453. rrfreelist(mp->an);
  454. rrfreelist(mp->ns);
  455. rrfreelist(mp->ar);
  456. mp->qd = mp->an = mp->ns = mp->ar = nil;
  457. }
  458. /* sets srcip */
  459. static int
  460. readnet(Query *qp, int medium, uchar *ibuf, ulong endtime, uchar **replyp,
  461. uchar *srcip)
  462. {
  463. int len, fd;
  464. uchar *reply;
  465. uchar lenbuf[2];
  466. /* timed read of reply */
  467. alarm((endtime - time(nil)) * 1000);
  468. reply = ibuf;
  469. len = -1; /* pessimism */
  470. memset(srcip, 0, IPaddrlen);
  471. if (medium == Udp) {
  472. if (qp->udpfd <= 0)
  473. dnslog("readnet: qp->udpfd closed");
  474. else {
  475. len = read(qp->udpfd, ibuf, OUdphdrsize+Maxudpin);
  476. if (len >= IPaddrlen)
  477. memmove(srcip, ibuf, IPaddrlen);
  478. if (len >= OUdphdrsize) {
  479. len -= OUdphdrsize;
  480. reply += OUdphdrsize;
  481. }
  482. }
  483. } else {
  484. if (!qp->tcpset)
  485. dnslog("readnet: tcp params not set");
  486. fd = qp->tcpfd;
  487. if (fd <= 0)
  488. dnslog("readnet: %s: tcp fd unset for dest %I",
  489. qp->dp->name, qp->tcpip);
  490. else if (readn(fd, lenbuf, 2) != 2) {
  491. dnslog("readnet: short read of tcp size from %I",
  492. qp->tcpip);
  493. /*
  494. * probably a time-out; demote the ns.
  495. * actually, the problem may be the query, not the ns.
  496. */
  497. addslug(qp->tcpip);
  498. } else {
  499. len = lenbuf[0]<<8 | lenbuf[1];
  500. if (readn(fd, ibuf, len) != len) {
  501. dnslog("readnet: short read of tcp data from %I",
  502. qp->tcpip);
  503. /* probably a time-out; demote the ns */
  504. addslug(qp->tcpip);
  505. len = -1;
  506. }
  507. }
  508. memmove(srcip, qp->tcpip, IPaddrlen);
  509. }
  510. alarm(0);
  511. *replyp = reply;
  512. return len;
  513. }
  514. /*
  515. * read replies to a request and remember the rrs in the answer(s).
  516. * ignore any of the wrong type.
  517. * wait at most until endtime.
  518. */
  519. static int
  520. readreply(Query *qp, int medium, ushort req, uchar *ibuf, DNSmsg *mp,
  521. ulong endtime)
  522. {
  523. int len = -1, rv;
  524. char *err;
  525. uchar *reply;
  526. uchar srcip[IPaddrlen];
  527. RR *rp;
  528. notify(ding);
  529. queryck(qp);
  530. rv = 0;
  531. memset(mp, 0, sizeof *mp);
  532. if (time(nil) >= endtime)
  533. return -1; /* timed out before we started */
  534. for (; time(nil) < endtime &&
  535. (len = readnet(qp, medium, ibuf, endtime, &reply, srcip)) >= 0;
  536. freeanswers(mp)){
  537. /* convert into internal format */
  538. memset(mp, 0, sizeof *mp);
  539. err = convM2DNS(reply, len, mp, nil);
  540. if (mp->flags & Ftrunc) {
  541. // dnslog("readreply: %s: truncated reply, len %d from %I",
  542. // qp->dp->name, len, srcip);
  543. /* notify the caller to retry the query via tcp. */
  544. return -1;
  545. } else if(err){
  546. dnslog("readreply: %s: input err, len %d: %s: %I",
  547. qp->dp->name, len, err, srcip);
  548. free(err);
  549. continue;
  550. }
  551. if (err)
  552. free(err);
  553. if(debug)
  554. logreply(qp->req->id, srcip, mp);
  555. /* answering the right question? */
  556. if(mp->id != req)
  557. dnslog("%d: id %d instead of %d: %I", qp->req->id,
  558. mp->id, req, srcip);
  559. else if(mp->qd == 0)
  560. dnslog("%d: no question RR: %I", qp->req->id, srcip);
  561. else if(mp->qd->owner != qp->dp)
  562. dnslog("%d: owner %s instead of %s: %I", qp->req->id,
  563. mp->qd->owner->name, qp->dp->name, srcip);
  564. else if(mp->qd->type != qp->type)
  565. dnslog("%d: qp->type %d instead of %d: %I",
  566. qp->req->id, mp->qd->type, qp->type, srcip);
  567. else {
  568. /* remember what request this is in answer to */
  569. for(rp = mp->an; rp; rp = rp->next)
  570. rp->query = qp->type;
  571. return rv;
  572. }
  573. }
  574. if (time(nil) >= endtime)
  575. addslug(srcip);
  576. else
  577. dnslog("readreply: %s: %I read error or eof (returned %d)",
  578. qp->dp->name, srcip, len);
  579. return -1;
  580. }
  581. /*
  582. * return non-0 if first list includes second list
  583. */
  584. int
  585. contains(RR *rp1, RR *rp2)
  586. {
  587. RR *trp1, *trp2;
  588. for(trp2 = rp2; trp2; trp2 = trp2->next){
  589. for(trp1 = rp1; trp1; trp1 = trp1->next)
  590. if(trp1->type == trp2->type)
  591. if(trp1->host == trp2->host)
  592. if(trp1->owner == trp2->owner)
  593. break;
  594. if(trp1 == nil)
  595. return 0;
  596. }
  597. return 1;
  598. }
  599. /*
  600. * return multicast version if any
  601. */
  602. int
  603. ipisbm(uchar *ip)
  604. {
  605. if(isv4(ip)){
  606. if (ip[IPv4off] >= 0xe0 && ip[IPv4off] < 0xf0 ||
  607. ipcmp(ip, IPv4bcast) == 0)
  608. return 4;
  609. } else
  610. if(ip[0] == 0xff)
  611. return 6;
  612. return 0;
  613. }
  614. /*
  615. * Get next server address
  616. */
  617. static int
  618. serveraddrs(Query *qp, int nd, int depth)
  619. {
  620. RR *rp, *arp, *trp;
  621. Dest *cur;
  622. if(nd >= Maxdest)
  623. return 0;
  624. /*
  625. * look for a server whose address we already know.
  626. * if we find one, mark it so we ignore this on
  627. * subsequent passes.
  628. */
  629. arp = 0;
  630. for(rp = qp->nsrp; rp; rp = rp->next){
  631. assert(rp->magic == RRmagic);
  632. if(rp->marker)
  633. continue;
  634. arp = rrlookup(rp->host, Ta, NOneg);
  635. if(arp){
  636. rp->marker = 1;
  637. break;
  638. }
  639. arp = dblookup(rp->host->name, Cin, Ta, 0, 0);
  640. if(arp){
  641. rp->marker = 1;
  642. break;
  643. }
  644. }
  645. /*
  646. * if the cache and database lookup didn't find any new
  647. * server addresses, try resolving one via the network.
  648. * Mark any we try to resolve so we don't try a second time.
  649. */
  650. if(arp == 0)
  651. for(rp = qp->nsrp; rp; rp = rp->next){
  652. if(rp->marker)
  653. continue;
  654. rp->marker = 1;
  655. /*
  656. * avoid loops looking up a server under itself
  657. */
  658. if(subsume(rp->owner->name, rp->host->name))
  659. continue;
  660. arp = dnresolve(rp->host->name, Cin, Ta, qp->req, 0,
  661. depth+1, Recurse, 1, 0);
  662. rrfreelist(rrremneg(&arp));
  663. if(arp)
  664. break;
  665. }
  666. /* use any addresses that we found */
  667. for(trp = arp; trp && nd < Maxdest; trp = trp->next){
  668. cur = &qp->dest[nd];
  669. parseip(cur->a, trp->ip->name);
  670. /*
  671. * straddling servers can reject all nameservers if they are all
  672. * inside, so be sure to list at least one outside ns at
  673. * the end of the ns list in /lib/ndb for `dom='.
  674. */
  675. if (ipisbm(cur->a) ||
  676. cfg.straddle && !insideaddr(qp->dp->name) && insidens(cur->a))
  677. continue;
  678. cur->nx = 0;
  679. cur->s = trp->owner;
  680. cur->code = Rtimeout;
  681. nd++;
  682. }
  683. rrfreelist(arp);
  684. return nd;
  685. }
  686. /*
  687. * cache negative responses
  688. */
  689. static void
  690. cacheneg(DN *dp, int type, int rcode, RR *soarr)
  691. {
  692. RR *rp;
  693. DN *soaowner;
  694. ulong ttl;
  695. /* no cache time specified, don't make anything up */
  696. if(soarr != nil){
  697. if(soarr->next != nil){
  698. rrfreelist(soarr->next);
  699. soarr->next = nil;
  700. }
  701. soaowner = soarr->owner;
  702. } else
  703. soaowner = nil;
  704. /* the attach can cause soarr to be freed so mine it now */
  705. if(soarr != nil && soarr->soa != nil)
  706. ttl = soarr->soa->minttl+now;
  707. else
  708. ttl = 5*Min;
  709. /* add soa and negative RR to the database */
  710. rrattach(soarr, 1);
  711. rp = rralloc(type);
  712. rp->owner = dp;
  713. rp->negative = 1;
  714. rp->negsoaowner = soaowner;
  715. rp->negrcode = rcode;
  716. rp->ttl = ttl;
  717. rrattach(rp, 1);
  718. }
  719. static int
  720. setdestoutns(Dest *p, int n)
  721. {
  722. uchar *outns = outsidens(n);
  723. destck(p);
  724. destinit(p);
  725. if (outns == nil) {
  726. if (n == 0)
  727. dnslog("[%d] no outside-ns in ndb", getpid());
  728. return -1;
  729. }
  730. memmove(p->a, outns, sizeof p->a);
  731. p->s = dnlookup("outside-ns-ips", Cin, 1);
  732. return 0;
  733. }
  734. /*
  735. * issue query via UDP or TCP as appropriate.
  736. * for TCP, returns with qp->tcpip set from udppkt header.
  737. */
  738. static int
  739. mydnsquery(Query *qp, int medium, uchar *udppkt, int len)
  740. {
  741. int rv = -1;
  742. char *domain;
  743. char conndir[40];
  744. NetConnInfo *nci;
  745. queryck(qp);
  746. switch (medium) {
  747. case Udp:
  748. if (qp->udpfd <= 0)
  749. dnslog("mydnsquery: qp->udpfd closed");
  750. else {
  751. if (write(qp->udpfd, udppkt, len+OUdphdrsize) !=
  752. len+OUdphdrsize)
  753. warning("sending udp msg %r");
  754. rv = 0;
  755. }
  756. break;
  757. case Tcp:
  758. /* send via TCP & keep fd around for reply */
  759. domain = smprint("%I", udppkt);
  760. alarm(10*1000);
  761. qp->tcpfd = rv = dial(netmkaddr(domain, "tcp", "dns"), nil,
  762. conndir, &qp->tcpctlfd);
  763. alarm(0);
  764. if (qp->tcpfd < 0) {
  765. dnslog("can't dial tcp!%s!dns: %r", domain);
  766. addslug(udppkt);
  767. } else {
  768. uchar belen[2];
  769. nci = getnetconninfo(conndir, qp->tcpfd);
  770. if (nci) {
  771. parseip(qp->tcpip, nci->rsys);
  772. freenetconninfo(nci);
  773. } else
  774. dnslog("mydnsquery: getnetconninfo failed");
  775. qp->tcpset = 1;
  776. belen[0] = len >> 8;
  777. belen[1] = len;
  778. if (write(qp->tcpfd, belen, 2) != 2 ||
  779. write(qp->tcpfd, udppkt + OUdphdrsize, len) != len)
  780. warning("sending tcp msg %r");
  781. }
  782. free(domain);
  783. break;
  784. default:
  785. sysfatal("mydnsquery: bad medium");
  786. }
  787. return rv;
  788. }
  789. /*
  790. * send query to all UDP destinations or one TCP destination,
  791. * taken from obuf (udp packet) header
  792. */
  793. static int
  794. xmitquery(Query *qp, int medium, int depth, uchar *obuf, int inns, int len)
  795. {
  796. int j, n;
  797. char buf[32];
  798. Dest *p;
  799. queryck(qp);
  800. if(time(nil) >= qp->req->aborttime)
  801. return -1;
  802. /*
  803. * get a nameserver address if we need one.
  804. * serveraddrs populates qp->dest.
  805. */
  806. p = qp->dest;
  807. destck(p);
  808. if (qp->ndest < 0 || qp->ndest > Maxdest)
  809. dnslog("qp->ndest %d out of range", qp->ndest);
  810. if (qp->ndest > qp->curdest - p)
  811. qp->curdest = &qp->dest[serveraddrs(qp, qp->curdest - p, depth)];
  812. destck(qp->curdest);
  813. /* no servers, punt */
  814. if (qp->curdest == qp->dest)
  815. if (cfg.straddle && cfg.inside) {
  816. /* get ips of "outside-ns-ips" */
  817. p = qp->curdest = qp->dest;
  818. for(n = 0; n < Maxdest; n++, qp->curdest++)
  819. if (setdestoutns(qp->curdest, n) < 0)
  820. break;
  821. } else {
  822. /* it's probably just a bogus domain, don't log it */
  823. // dnslog("xmitquery: %s: no nameservers", qp->dp->name);
  824. return -1;
  825. }
  826. /* send to first 'qp->ndest' destinations */
  827. j = 0;
  828. if (medium == Tcp) {
  829. j++;
  830. queryck(qp);
  831. assert(qp->dp);
  832. procsetname("tcp %sside query for %s %s", (inns? "in": "out"),
  833. qp->dp->name, rrname(qp->type, buf, sizeof buf));
  834. mydnsquery(qp, medium, obuf, len); /* sets qp->tcpip from obuf */
  835. if(debug)
  836. logsend(qp->req->id, depth, qp->tcpip, "", qp->dp->name,
  837. qp->type);
  838. } else
  839. for(; p < &qp->dest[qp->ndest] && p < qp->curdest; p++){
  840. /* skip destinations we've finished with */
  841. if(p->nx >= Maxtrans)
  842. continue;
  843. j++;
  844. /* exponential backoff of requests */
  845. if((1<<p->nx) > qp->ndest)
  846. continue;
  847. procsetname("udp %sside query to %I/%s %s %s",
  848. (inns? "in": "out"), p->a, p->s->name,
  849. qp->dp->name, rrname(qp->type, buf, sizeof buf));
  850. if(debug)
  851. logsend(qp->req->id, depth, p->a, p->s->name,
  852. qp->dp->name, qp->type);
  853. /* fill in UDP destination addr & send it */
  854. memmove(obuf, p->a, sizeof p->a);
  855. mydnsquery(qp, medium, obuf, len);
  856. p->nx++;
  857. }
  858. if(j == 0) {
  859. // dnslog("xmitquery: %s: no destinations left", qp->dp->name);
  860. return -1;
  861. }
  862. return 0;
  863. }
  864. static int
  865. procansw(Query *qp, DNSmsg *mp, uchar *srcip, int depth, Dest *p)
  866. {
  867. int rv;
  868. char buf[32];
  869. DN *ndp;
  870. Query nquery;
  871. RR *tp, *soarr;
  872. /* ignore any error replies */
  873. if((mp->flags & Rmask) == Rserver){
  874. rrfreelist(mp->qd);
  875. rrfreelist(mp->an);
  876. rrfreelist(mp->ar);
  877. rrfreelist(mp->ns);
  878. if(p != qp->curdest)
  879. p->code = Rserver;
  880. return -1;
  881. }
  882. /* ignore any bad delegations */
  883. if(mp->ns && baddelegation(mp->ns, qp->nsrp, srcip)){
  884. rrfreelist(mp->ns);
  885. mp->ns = nil;
  886. if(mp->an == nil){
  887. rrfreelist(mp->qd);
  888. rrfreelist(mp->ar);
  889. if(p != qp->curdest)
  890. p->code = Rserver;
  891. return -1;
  892. }
  893. }
  894. /* remove any soa's from the authority section */
  895. soarr = rrremtype(&mp->ns, Tsoa);
  896. /* incorporate answers */
  897. if(mp->an)
  898. rrattach(mp->an, (mp->flags & Fauth) != 0);
  899. if(mp->ar)
  900. rrattach(mp->ar, 0);
  901. if(mp->ns){
  902. ndp = mp->ns->owner;
  903. rrattach(mp->ns, 0);
  904. } else
  905. ndp = nil;
  906. /* free the question */
  907. if(mp->qd)
  908. rrfreelist(mp->qd);
  909. /*
  910. * Any reply from an authoritative server,
  911. * or a positive reply terminates the search
  912. */
  913. if(mp->an != nil || (mp->flags & Fauth)){
  914. if(mp->an == nil && (mp->flags & Rmask) == Rname)
  915. qp->dp->respcode = Rname;
  916. else
  917. qp->dp->respcode = 0;
  918. /*
  919. * cache any negative responses, free soarr
  920. */
  921. if((mp->flags & Fauth) && mp->an == nil)
  922. cacheneg(qp->dp, qp->type, (mp->flags & Rmask), soarr);
  923. else
  924. rrfreelist(soarr);
  925. return 1;
  926. }
  927. rrfreelist(soarr);
  928. /*
  929. * if we've been given better name servers,
  930. * recurse. we're called from udpquery, called from
  931. * netquery, which current holds qp->dp->querylck,
  932. * so release it now and acquire it upon return.
  933. */
  934. if(!mp->ns)
  935. return 0;
  936. tp = rrlookup(ndp, Tns, NOneg);
  937. if(contains(qp->nsrp, tp)){
  938. rrfreelist(tp);
  939. return 0;
  940. }
  941. procsetname("recursive query for %s %s", qp->dp->name,
  942. rrname(qp->type, buf, sizeof buf));
  943. // qunlock(&qp->dp->querylck);
  944. queryinit(&nquery, qp->dp, qp->type, qp->req);
  945. nquery.nsrp = tp;
  946. rv = netquery(&nquery, depth+1);
  947. // qlock(&qp->dp->querylck);
  948. rrfreelist(tp);
  949. querydestroy(&nquery);
  950. return rv;
  951. }
  952. /*
  953. * send a query via tcp to a single address (from ibuf's udp header)
  954. * and read the answer(s) into mp->an.
  955. */
  956. static int
  957. tcpquery(Query *qp, DNSmsg *mp, int depth, uchar *ibuf, uchar *obuf, int len,
  958. int waitsecs, int inns, ushort req)
  959. {
  960. int rv = 0;
  961. ulong endtime;
  962. endtime = time(nil) + waitsecs;
  963. if(endtime > qp->req->aborttime)
  964. endtime = qp->req->aborttime;
  965. dnslog("%s: udp reply truncated; retrying query via tcp to %I",
  966. qp->dp->name, qp->tcpip);
  967. qlock(&qp->tcplock);
  968. memmove(obuf, ibuf, IPaddrlen); /* send back to respondent */
  969. /* sets qp->tcpip from obuf's udp header */
  970. if (xmitquery(qp, Tcp, depth, obuf, inns, len) < 0 ||
  971. readreply(qp, Tcp, req, ibuf, mp, endtime) < 0)
  972. rv = -1;
  973. if (qp->tcpfd > 0) {
  974. hangup(qp->tcpctlfd);
  975. close(qp->tcpctlfd);
  976. close(qp->tcpfd);
  977. }
  978. qp->tcpfd = qp->tcpctlfd = -1;
  979. qunlock(&qp->tcplock);
  980. return rv;
  981. }
  982. /*
  983. * query name servers. If the name server returns a pointer to another
  984. * name server, recurse.
  985. */
  986. static int
  987. netquery1(Query *qp, int depth, uchar *ibuf, uchar *obuf, int waitsecs, int inns)
  988. {
  989. int ndest, len, replywaits, rv;
  990. ushort req;
  991. ulong endtime;
  992. char buf[12];
  993. uchar srcip[IPaddrlen];
  994. DNSmsg m;
  995. Dest *p, *np;
  996. Dest dest[Maxdest];
  997. /* pack request into a udp message */
  998. req = rand();
  999. len = mkreq(qp->dp, qp->type, obuf, Frecurse|Oquery, req);
  1000. /* no server addresses yet */
  1001. queryck(qp);
  1002. for (p = dest; p < dest + nelem(dest); p++)
  1003. destinit(p);
  1004. qp->curdest = qp->dest = dest;
  1005. /*
  1006. * transmit udp requests and wait for answers.
  1007. * at most Maxtrans attempts to each address.
  1008. * each cycle send one more message than the previous.
  1009. * retry a query via tcp if its response is truncated.
  1010. */
  1011. for(ndest = 1; ndest < Maxdest; ndest++){
  1012. qp->ndest = ndest;
  1013. qp->tcpset = 0;
  1014. if (xmitquery(qp, Udp, depth, obuf, inns, len) < 0)
  1015. break;
  1016. endtime = time(nil) + waitsecs;
  1017. if(endtime > qp->req->aborttime)
  1018. endtime = qp->req->aborttime;
  1019. for(replywaits = 0; replywaits < ndest; replywaits++){
  1020. procsetname("reading %sside reply from %s%I for %s %s",
  1021. (inns? "in": "out"),
  1022. (isaslug(qp->tcpip)? "sluggard ": ""), obuf,
  1023. qp->dp->name, rrname(qp->type, buf, sizeof buf));
  1024. /* read udp answer */
  1025. if (readreply(qp, Udp, req, ibuf, &m, endtime) >= 0)
  1026. memmove(srcip, ibuf, IPaddrlen);
  1027. else if (!(m.flags & Ftrunc)) {
  1028. addslug(ibuf);
  1029. break; /* timed out on this dest */
  1030. } else {
  1031. /* whoops, it was truncated! ask again via tcp */
  1032. rv = tcpquery(qp, &m, depth, ibuf, obuf, len,
  1033. waitsecs, inns, req);
  1034. if (rv < 0)
  1035. break; /* failed via tcp too */
  1036. memmove(srcip, qp->tcpip, IPaddrlen);
  1037. }
  1038. /* find responder */
  1039. // dnslog("netquery1 got reply from %I", srcip);
  1040. for(p = qp->dest; p < qp->curdest; p++)
  1041. if(memcmp(p->a, srcip, sizeof p->a) == 0)
  1042. break;
  1043. /* remove all addrs of responding server from list */
  1044. for(np = qp->dest; np < qp->curdest; np++)
  1045. if(np->s == p->s)
  1046. p->nx = Maxtrans;
  1047. rv = procansw(qp, &m, srcip, depth, p);
  1048. if (rv > 0)
  1049. return rv;
  1050. }
  1051. }
  1052. /* if all servers returned failure, propagate it */
  1053. qp->dp->respcode = Rserver;
  1054. for(p = dest; p < qp->curdest; p++) {
  1055. destck(p);
  1056. if(p->code != Rserver)
  1057. qp->dp->respcode = 0;
  1058. p->magic = 0; /* prevent accidents */
  1059. }
  1060. // if (qp->dp->respcode)
  1061. // dnslog("netquery1 setting Rserver for %s", qp->dp->name);
  1062. qp->dest = qp->curdest = nil; /* prevent accidents */
  1063. return 0;
  1064. }
  1065. /*
  1066. * run a command with a supplied fd as standard input
  1067. */
  1068. char *
  1069. system(int fd, char *cmd)
  1070. {
  1071. int pid, p, i;
  1072. static Waitmsg msg;
  1073. if((pid = fork()) == -1)
  1074. sysfatal("fork failed: %r");
  1075. else if(pid == 0){
  1076. dup(fd, 0);
  1077. close(fd);
  1078. for (i = 3; i < 200; i++)
  1079. close(i); /* don't leak fds */
  1080. execl("/bin/rc", "rc", "-c", cmd, nil);
  1081. sysfatal("exec rc: %r");
  1082. }
  1083. for(p = waitpid(); p >= 0; p = waitpid())
  1084. if(p == pid)
  1085. return msg.msg;
  1086. return "lost child";
  1087. }
  1088. enum { Hurry, Patient, };
  1089. enum { Outns, Inns, };
  1090. enum { Remntretry = 15, }; /* min. sec.s between remount attempts */
  1091. static int
  1092. udpquery(Query *qp, char *mntpt, int depth, int patient, int inns)
  1093. {
  1094. int fd, rv = 0;
  1095. long now;
  1096. char *msg;
  1097. uchar *obuf, *ibuf;
  1098. static QLock mntlck;
  1099. static ulong lastmount;
  1100. /* use alloced buffers rather than ones from the stack */
  1101. // ibuf = emalloc(Maxudpin+OUdphdrsize);
  1102. ibuf = emalloc(64*1024); /* max. tcp reply size */
  1103. obuf = emalloc(Maxudp+OUdphdrsize);
  1104. fd = udpport(mntpt);
  1105. while (fd < 0 && cfg.straddle && strcmp(mntpt, "/net.alt") == 0) {
  1106. /* HACK: remount /net.alt */
  1107. now = time(nil);
  1108. if (now < lastmount + Remntretry)
  1109. sleep((lastmount + Remntretry - now)*1000);
  1110. qlock(&mntlck);
  1111. fd = udpport(mntpt); /* try again under lock */
  1112. if (fd < 0) {
  1113. dnslog("[%d] remounting /net.alt", getpid());
  1114. unmount(nil, "/net.alt");
  1115. msg = system(open("/dev/null", ORDWR), "outside");
  1116. lastmount = time(nil);
  1117. if (msg && *msg) {
  1118. dnslog("[%d] can't remount /net.alt: %s",
  1119. getpid(), msg);
  1120. sleep(10*1000); /* don't spin wildly */
  1121. } else
  1122. fd = udpport(mntpt);
  1123. }
  1124. qunlock(&mntlck);
  1125. }
  1126. if(fd >= 0) {
  1127. qp->req->aborttime = time(nil) + (patient? Maxreqtm: Maxreqtm/2);
  1128. qp->udpfd = fd;
  1129. /* tune; was (patient? 15: 10) */
  1130. rv = netquery1(qp, depth, ibuf, obuf, (patient? 10: 5), inns);
  1131. close(fd);
  1132. } else
  1133. dnslog("can't get udpport for %s query of name %s: %r",
  1134. mntpt, qp->dp->name);
  1135. free(obuf);
  1136. free(ibuf);
  1137. return rv;
  1138. }
  1139. /* look up (dp->name,type) via *nsrp with results in *reqp */
  1140. static int
  1141. netquery(Query *qp, int depth)
  1142. {
  1143. int lock, rv, triedin, inname;
  1144. RR *rp;
  1145. if(depth > 12) /* in a recursive loop? */
  1146. return 0;
  1147. slave(qp->req);
  1148. /*
  1149. * slave might have forked. if so, the parent process longjmped to
  1150. * req->mret; we're usually the child slave, but if there are too
  1151. * many children already, we're still the same process.
  1152. */
  1153. /* don't lock before call to slave so only children can block */
  1154. if (0)
  1155. lock = qp->req->isslave != 0;
  1156. if(0 && lock) {
  1157. procsetname("query lock wait for %s", qp->dp->name);
  1158. /*
  1159. * don't make concurrent queries for this name.
  1160. *
  1161. * this seemed like a good idea, to avoid swamping
  1162. * an overloaded ns, but in practice, dns processes
  1163. * pile up quickly and dns becomes unresponsive for a while.
  1164. */
  1165. qlock(&qp->dp->querylck);
  1166. }
  1167. procsetname("netquery: %s", qp->dp->name);
  1168. /* prepare server RR's for incremental lookup */
  1169. for(rp = qp->nsrp; rp; rp = rp->next)
  1170. rp->marker = 0;
  1171. rv = 0; /* pessimism */
  1172. triedin = 0;
  1173. qp->nsrp = qp->nsrp;
  1174. /*
  1175. * normal resolvers and servers will just use mntpt for all addresses,
  1176. * even on the outside. straddling servers will use mntpt (/net)
  1177. * for inside addresses and /net.alt for outside addresses,
  1178. * thus bypassing other inside nameservers.
  1179. */
  1180. inname = insideaddr(qp->dp->name);
  1181. if (!cfg.straddle || inname) {
  1182. rv = udpquery(qp, mntpt, depth, Hurry, (cfg.inside? Inns: Outns));
  1183. triedin = 1;
  1184. }
  1185. /*
  1186. * if we're still looking, are inside, and have an outside domain,
  1187. * try it on our outside interface, if any.
  1188. */
  1189. if (rv == 0 && cfg.inside && !inname) {
  1190. if (triedin)
  1191. dnslog(
  1192. "[%d] netquery: internal nameservers failed for %s; trying external",
  1193. getpid(), qp->dp->name);
  1194. /* prepare server RR's for incremental lookup */
  1195. for(rp = qp->nsrp; rp; rp = rp->next)
  1196. rp->marker = 0;
  1197. rv = udpquery(qp, "/net.alt", depth, Patient, Outns);
  1198. }
  1199. // if (rv == 0) /* could ask /net.alt/dns directly */
  1200. // askoutdns(qp->dp, qp->type);
  1201. if(0 && lock)
  1202. qunlock(&qp->dp->querylck);
  1203. return rv;
  1204. }
  1205. int
  1206. seerootns(void)
  1207. {
  1208. int rv;
  1209. char root[] = "";
  1210. Request req;
  1211. Query query;
  1212. memset(&req, 0, sizeof req);
  1213. req.isslave = 1;
  1214. req.aborttime = now + Maxreqtm;
  1215. queryinit(&query, dnlookup(root, Cin, 1), Tns, &req);
  1216. query.nsrp = dblookup(root, Cin, Tns, 0, 0);
  1217. rv = netquery(&query, 0);
  1218. querydestroy(&query);
  1219. return rv;
  1220. }