dnresolve.c 25 KB

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