dblookup.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935
  1. #include <u.h>
  2. #include <libc.h>
  3. #include <bio.h>
  4. #include <ndb.h>
  5. #include <ip.h>
  6. #include "dns.h"
  7. static Ndb *db;
  8. static RR* dblookup1(char*, int, int, int);
  9. static RR* addrrr(Ndbtuple*, Ndbtuple*);
  10. static RR* nsrr(Ndbtuple*, Ndbtuple*);
  11. static RR* cnamerr(Ndbtuple*, Ndbtuple*);
  12. static RR* mxrr(Ndbtuple*, Ndbtuple*);
  13. static RR* soarr(Ndbtuple*, Ndbtuple*);
  14. static RR* ptrrr(Ndbtuple*, Ndbtuple*);
  15. static Ndbtuple* look(Ndbtuple*, Ndbtuple*, char*);
  16. static RR* doaxfr(Ndb*, char*);
  17. static RR* nullrr(Ndbtuple *entry, Ndbtuple *pair);
  18. static RR* txtrr(Ndbtuple *entry, Ndbtuple *pair);
  19. static Lock dblock;
  20. static void createptrs(void);
  21. static int implemented[Tall] =
  22. {
  23. [Ta] 1,
  24. [Tns] 1,
  25. [Tsoa] 1,
  26. [Tmx] 1,
  27. [Tptr] 1,
  28. [Tcname] 1,
  29. [Tnull] 1,
  30. [Ttxt] 1,
  31. };
  32. int
  33. opendatabase(void)
  34. {
  35. char buf[256];
  36. Ndb *xdb;
  37. if(db == nil){
  38. snprint(buf, sizeof(buf), "%s/ndb", mntpt);
  39. xdb = ndbopen(dbfile);
  40. if(xdb != nil)
  41. xdb->nohash = 1;
  42. db = ndbcat(ndbopen(buf), xdb);
  43. }
  44. if(db == nil)
  45. return -1;
  46. else
  47. return 0;
  48. }
  49. /*
  50. * lookup an RR in the network database, look for matches
  51. * against both the domain name and the wildcarded domain name.
  52. *
  53. * the lock makes sure only one process can be accessing the data
  54. * base at a time. This is important since there's a lot of
  55. * shared state there.
  56. *
  57. * e.g. for x.research.bell-labs.com, first look for a match against
  58. * the x.research.bell-labs.com. If nothing matches, try *.research.bell-labs.com.
  59. */
  60. RR*
  61. dblookup(char *name, int class, int type, int auth, int ttl)
  62. {
  63. RR *rp, *tp;
  64. char buf[256];
  65. char *wild, *cp;
  66. DN *dp, *ndp;
  67. int err;
  68. static int parallel;
  69. static int parfd[2];
  70. static char token[1];
  71. /* so far only internet lookups are implemented */
  72. if(class != Cin)
  73. return 0;
  74. err = Rname;
  75. if(type == Tall){
  76. rp = 0;
  77. for (type = Ta; type < Tall; type++)
  78. if(implemented[type])
  79. rrcat(&rp, dblookup(name, class, type, auth, ttl));
  80. return rp;
  81. }
  82. lock(&dblock);
  83. dp = dnlookup(name, class, 1);
  84. if(opendatabase() < 0)
  85. goto out;
  86. if(dp->rr)
  87. err = 0;
  88. /* first try the given name */
  89. rp = 0;
  90. if(cachedb)
  91. rp = rrlookup(dp, type, NOneg);
  92. else
  93. rp = dblookup1(name, type, auth, ttl);
  94. if(rp)
  95. goto out;
  96. /* try lower case version */
  97. for(cp = name; *cp; cp++)
  98. *cp = tolower(*cp);
  99. if(cachedb)
  100. rp = rrlookup(dp, type, NOneg);
  101. else
  102. rp = dblookup1(name, type, auth, ttl);
  103. if(rp)
  104. goto out;
  105. /* walk the domain name trying the wildcard '*' at each position */
  106. for(wild = strchr(name, '.'); wild; wild = strchr(wild+1, '.')){
  107. snprint(buf, sizeof(buf), "*%s", wild);
  108. ndp = dnlookup(buf, class, 1);
  109. if(ndp->rr)
  110. err = 0;
  111. if(cachedb)
  112. rp = rrlookup(ndp, type, NOneg);
  113. else
  114. rp = dblookup1(buf, type, auth, ttl);
  115. if(rp)
  116. break;
  117. }
  118. out:
  119. /* add owner to uncached records */
  120. if(rp){
  121. for(tp = rp; tp; tp = tp->next)
  122. tp->owner = dp;
  123. } else {
  124. /* don't call it non-existent if it's not ours */
  125. if(err == Rname && !inmyarea(name))
  126. err = Rserver;
  127. dp->nonexistent = err;
  128. }
  129. unlock(&dblock);
  130. return rp;
  131. }
  132. /*
  133. * lookup an RR in the network database
  134. */
  135. static RR*
  136. dblookup1(char *name, int type, int auth, int ttl)
  137. {
  138. Ndbtuple *t, *nt;
  139. RR *rp, *list, **l;
  140. Ndbs s;
  141. char val[Ndbvlen], dname[Ndbvlen];
  142. char *attr;
  143. DN *dp;
  144. RR *(*f)(Ndbtuple*, Ndbtuple*);
  145. int found, x;
  146. dp = 0;
  147. switch(type){
  148. case Tptr:
  149. attr = "ptr";
  150. f = ptrrr;
  151. break;
  152. case Ta:
  153. attr = "ip";
  154. f = addrrr;
  155. break;
  156. case Tnull:
  157. attr = "nullrr";
  158. f = nullrr;
  159. break;
  160. case Tns:
  161. attr = "ns";
  162. f = nsrr;
  163. break;
  164. case Tsoa:
  165. attr = "soa";
  166. f = soarr;
  167. break;
  168. case Tmx:
  169. attr = "mx";
  170. f = mxrr;
  171. break;
  172. case Tcname:
  173. attr = "cname";
  174. f = cnamerr;
  175. break;
  176. case Taxfr:
  177. case Tixfr:
  178. return doaxfr(db, name);
  179. default:
  180. return nil;
  181. }
  182. /*
  183. * find a matching entry in the database
  184. */
  185. t = ndbgetval(db, &s, "dom", name, attr, val);
  186. /*
  187. * hack for local names
  188. */
  189. if(t == 0 && strchr(name, '.') == 0)
  190. t = ndbgetval(db, &s, "sys", name, attr, val);
  191. if(t == 0)
  192. return nil;
  193. /* search whole entry for default domain name */
  194. strncpy(dname, name, Ndbvlen);
  195. for(nt = t; nt; nt = nt->entry)
  196. if(strcmp(nt->attr, "dom") == 0){
  197. strcpy(dname, nt->val);
  198. break;
  199. }
  200. /* ttl is maximum of soa minttl and entry's ttl ala rfc883 */
  201. nt = look(t, s.t, "ttl");
  202. if(nt){
  203. x = atoi(nt->val);
  204. if(x > ttl)
  205. ttl = x;
  206. }
  207. /* default ttl is one day */
  208. if(ttl < 0)
  209. ttl = DEFTTL;
  210. /*
  211. * The database has 2 levels of precedence; line and entry.
  212. * Pairs on the same line bind tighter than pairs in the
  213. * same entry, so we search the line first.
  214. */
  215. found = 0;
  216. list = 0;
  217. l = &list;
  218. for(nt = s.t;; ){
  219. if(found == 0 && strcmp(nt->attr, "dom") == 0){
  220. strcpy(dname, nt->val);
  221. found = 1;
  222. }
  223. if(cistrcmp(attr, nt->attr) == 0){
  224. rp = (*f)(t, nt);
  225. rp->auth = auth;
  226. rp->db = 1;
  227. if(ttl)
  228. rp->ttl = ttl;
  229. if(dp == 0)
  230. dp = dnlookup(dname, Cin, 1);
  231. rp->owner = dp;
  232. *l = rp;
  233. l = &rp->next;
  234. nt->ptr = 1;
  235. }
  236. nt = nt->line;
  237. if(nt == s.t)
  238. break;
  239. }
  240. /* search whole entry */
  241. for(nt = t; nt; nt = nt->entry)
  242. if(nt->ptr == 0 && cistrcmp(attr, nt->attr) == 0){
  243. rp = (*f)(t, nt);
  244. rp->db = 1;
  245. if(ttl)
  246. rp->ttl = ttl;
  247. rp->auth = auth;
  248. if(dp == 0)
  249. dp = dnlookup(dname, Cin, 1);
  250. rp->owner = dp;
  251. *l = rp;
  252. l = &rp->next;
  253. }
  254. ndbfree(t);
  255. return list;
  256. }
  257. /*
  258. * make various types of resource records from a database entry
  259. */
  260. static RR*
  261. addrrr(Ndbtuple *entry, Ndbtuple *pair)
  262. {
  263. RR *rp;
  264. uchar addr[IPaddrlen];
  265. USED(entry);
  266. parseip(addr, pair->val);
  267. if(isv4(addr))
  268. rp = rralloc(Ta);
  269. else
  270. rp = rralloc(Taaaa);
  271. rp->ip = dnlookup(pair->val, Cin, 1);
  272. return rp;
  273. }
  274. static RR*
  275. nullrr(Ndbtuple *entry, Ndbtuple *pair)
  276. {
  277. RR *rp;
  278. USED(entry);
  279. rp = rralloc(Tnull);
  280. rp->null->data = (uchar*)estrdup(pair->val);
  281. rp->null->dlen = strlen((char*)rp->null->data);
  282. return rp;
  283. }
  284. /*
  285. * txt rr strings are at most 255 bytes long. one
  286. * can represent longer strings by multiple concatenated
  287. * <= 255 byte ones.
  288. */
  289. static RR*
  290. txtrr(Ndbtuple *entry, Ndbtuple *pair)
  291. {
  292. RR *rp;
  293. Txt *t, **l;
  294. int i, len, sofar;
  295. USED(entry);
  296. rp = rralloc(Ttxt);
  297. l = &rp->txt;
  298. rp->txt = nil;
  299. len = strlen(pair->val);
  300. sofar = 0;
  301. while(len > sofar){
  302. t = emalloc(sizeof(*t));
  303. t->next = nil;
  304. i = len-sofar;
  305. if(i > 255)
  306. i = 255;
  307. t->p = emalloc(i+1);
  308. memmove(t->p, pair->val+sofar, i);
  309. t->p[i] = 0;
  310. sofar += i;
  311. *l = t;
  312. l = &t->next;
  313. }
  314. return rp;
  315. }
  316. static RR*
  317. cnamerr(Ndbtuple *entry, Ndbtuple *pair)
  318. {
  319. RR *rp;
  320. USED(entry);
  321. rp = rralloc(Tcname);
  322. rp->host = dnlookup(pair->val, Cin, 1);
  323. return rp;
  324. }
  325. static RR*
  326. mxrr(Ndbtuple *entry, Ndbtuple *pair)
  327. {
  328. RR * rp;
  329. rp = rralloc(Tmx);
  330. rp->host = dnlookup(pair->val, Cin, 1);
  331. pair = look(entry, pair, "pref");
  332. if(pair)
  333. rp->pref = atoi(pair->val);
  334. else
  335. rp->pref = 1;
  336. return rp;
  337. }
  338. static RR*
  339. nsrr(Ndbtuple *entry, Ndbtuple *pair)
  340. {
  341. RR *rp;
  342. Ndbtuple *t;
  343. rp = rralloc(Tns);
  344. rp->host = dnlookup(pair->val, Cin, 1);
  345. t = look(entry, pair, "soa");
  346. if(t && t->val[0] == 0)
  347. rp->local = 1;
  348. return rp;
  349. }
  350. static RR*
  351. ptrrr(Ndbtuple *entry, Ndbtuple *pair)
  352. {
  353. RR *rp;
  354. USED(entry);
  355. rp = rralloc(Tns);
  356. rp->ptr = dnlookup(pair->val, Cin, 1);
  357. return rp;
  358. }
  359. static RR*
  360. soarr(Ndbtuple *entry, Ndbtuple *pair)
  361. {
  362. RR *rp;
  363. Ndbtuple *ns, *mb, *t;
  364. char mailbox[Domlen];
  365. Ndb *ndb;
  366. char *p;
  367. rp = rralloc(Tsoa);
  368. rp->soa->serial = 1;
  369. for(ndb = db; ndb; ndb = ndb->next)
  370. if(ndb->mtime > rp->soa->serial)
  371. rp->soa->serial = ndb->mtime;
  372. rp->soa->refresh = Day;
  373. rp->soa->retry = Hour;
  374. rp->soa->expire = Day;
  375. rp->soa->minttl = Day;
  376. t = look(entry, pair, "ttl");
  377. if(t)
  378. rp->soa->minttl = atoi(t->val);
  379. t = look(entry, pair, "refresh");
  380. if(t)
  381. rp->soa->refresh = atoi(t->val);
  382. t = look(entry, pair, "serial");
  383. if(t)
  384. rp->soa->serial = strtoul(t->val, 0, 10);
  385. ns = look(entry, pair, "ns");
  386. if(ns == 0)
  387. ns = look(entry, pair, "dom");
  388. rp->host = dnlookup(ns->val, Cin, 1);
  389. /* accept all of:
  390. * mbox=person
  391. * mbox=person@machine.dom
  392. * mbox=person.machine.dom
  393. */
  394. mb = look(entry, pair, "mbox");
  395. if(mb == nil)
  396. mb = look(entry, pair, "mb");
  397. if(mb){
  398. if(strchr(mb->val, '.')) {
  399. p = strchr(mb->val, '@');
  400. if(p != nil)
  401. *p = '.';
  402. rp->rmb = dnlookup(mb->val, Cin, 1);
  403. } else {
  404. snprint(mailbox, sizeof(mailbox), "%s.%s",
  405. mb->val, ns->val);
  406. rp->rmb = dnlookup(mailbox, Cin, 1);
  407. }
  408. } else {
  409. snprint(mailbox, sizeof(mailbox), "postmaster.%s",
  410. ns->val);
  411. rp->rmb = dnlookup(mailbox, Cin, 1);
  412. }
  413. /* hang dns slaves off of the soa. this is
  414. * for managing the area.
  415. */
  416. for(t = entry; t != nil; t = t->entry)
  417. if(strcmp(t->attr, "dnsslave") == 0)
  418. addserver(&rp->soa->slaves, t->val);
  419. return rp;
  420. }
  421. /*
  422. * Look for a pair with the given attribute. look first on the same line,
  423. * then in the whole entry.
  424. */
  425. static Ndbtuple*
  426. look(Ndbtuple *entry, Ndbtuple *line, char *attr)
  427. {
  428. Ndbtuple *nt;
  429. /* first look on same line (closer binding) */
  430. for(nt = line;;){
  431. if(cistrcmp(attr, nt->attr) == 0)
  432. return nt;
  433. nt = nt->line;
  434. if(nt == line)
  435. break;
  436. }
  437. /* search whole tuple */
  438. for(nt = entry; nt; nt = nt->entry)
  439. if(cistrcmp(attr, nt->attr) == 0)
  440. return nt;
  441. return 0;
  442. }
  443. static RR**
  444. linkrr(RR *rp, DN *dp, RR **l)
  445. {
  446. rp->owner = dp;
  447. rp->auth = 1;
  448. rp->db = 1;
  449. *l = rp;
  450. return &rp->next;
  451. }
  452. /* these are answered specially by the tcp version */
  453. static RR*
  454. doaxfr(Ndb *db, char *name)
  455. {
  456. USED(db, name);
  457. return 0;
  458. }
  459. /*
  460. * read the all the soa's from the database to determine area's.
  461. * this is only used when we're not caching the database.
  462. */
  463. static void
  464. dbfile2area(Ndb *db)
  465. {
  466. Ndbtuple *t;
  467. if(debug)
  468. syslog(0, logfile, "rereading %s", db->file);
  469. Bseek(&db->b, 0, 0);
  470. while(t = ndbparse(db)){
  471. ndbfree(t);
  472. }
  473. }
  474. /*
  475. * read the database into the cache
  476. */
  477. static void
  478. dbpair2cache(DN *dp, Ndbtuple *entry, Ndbtuple *pair)
  479. {
  480. RR *rp;
  481. Ndbtuple *t;
  482. static ulong ord;
  483. rp = 0;
  484. if(cistrcmp(pair->attr, "ip") == 0){
  485. dp->ordinal = ord++;
  486. rp = addrrr(entry, pair);
  487. } else if(cistrcmp(pair->attr, "ns") == 0){
  488. rp = nsrr(entry, pair);
  489. } else if(cistrcmp(pair->attr, "soa") == 0){
  490. rp = soarr(entry, pair);
  491. addarea(dp, rp, pair);
  492. } else if(cistrcmp(pair->attr, "mx") == 0){
  493. rp = mxrr(entry, pair);
  494. } else if(cistrcmp(pair->attr, "cname") == 0){
  495. rp = cnamerr(entry, pair);
  496. } else if(cistrcmp(pair->attr, "nullrr") == 0){
  497. rp = nullrr(entry, pair);
  498. } else if(cistrcmp(pair->attr, "txtrr") == 0){
  499. rp = txtrr(entry, pair);
  500. }
  501. if(rp == 0)
  502. return;
  503. rp->owner = dp;
  504. rp->db = 1;
  505. t = look(entry, pair, "ttl");
  506. if(t)
  507. rp->ttl = atoi(t->val);
  508. rrattach(rp, 0);
  509. }
  510. static void
  511. dbtuple2cache(Ndbtuple *t)
  512. {
  513. Ndbtuple *et, *nt;
  514. DN *dp;
  515. for(et = t; et; et = et->entry){
  516. if(strcmp(et->attr, "dom") == 0){
  517. dp = dnlookup(et->val, Cin, 1);
  518. /* first same line */
  519. for(nt = et->line; nt != et; nt = nt->line){
  520. dbpair2cache(dp, t, nt);
  521. nt->ptr = 1;
  522. }
  523. /* then rest of entry */
  524. for(nt = t; nt; nt = nt->entry){
  525. if(nt->ptr == 0)
  526. dbpair2cache(dp, t, nt);
  527. nt->ptr = 0;
  528. }
  529. }
  530. }
  531. }
  532. static void
  533. dbfile2cache(Ndb *db)
  534. {
  535. Ndbtuple *t;
  536. if(debug)
  537. syslog(0, logfile, "rereading %s", db->file);
  538. Bseek(&db->b, 0, 0);
  539. while(t = ndbparse(db)){
  540. dbtuple2cache(t);
  541. ndbfree(t);
  542. }
  543. }
  544. void
  545. db2cache(int doit)
  546. {
  547. Ndb *ndb;
  548. Dir *d;
  549. ulong youngest, temp;
  550. static ulong lastcheck;
  551. static ulong lastyoungest;
  552. /* no faster than once every 2 minutes */
  553. if(now < lastcheck + 2*Min && !doit)
  554. return;
  555. refresh_areas(owned);
  556. lock(&dblock);
  557. if(opendatabase() < 0){
  558. unlock(&dblock);
  559. return;
  560. }
  561. /*
  562. * file may be changing as we are reading it, so loop till
  563. * mod times are consistent.
  564. *
  565. * we don't use the times in the ndb records because they may
  566. * change outside of refreshing our cached knowledge.
  567. */
  568. for(;;){
  569. lastcheck = now;
  570. youngest = 0;
  571. for(ndb = db; ndb; ndb = ndb->next){
  572. /* the dirfstat avoids walking the mount table each time */
  573. if((d = dirfstat(Bfildes(&ndb->b))) != nil ||
  574. (d = dirstat(ndb->file)) != nil){
  575. temp = d->mtime; /* ulong vs int crap */
  576. if(temp > youngest)
  577. youngest = temp;
  578. free(d);
  579. }
  580. }
  581. if(!doit && youngest == lastyoungest){
  582. unlock(&dblock);
  583. return;
  584. }
  585. /* forget our area definition */
  586. freearea(&owned);
  587. freearea(&delegated);
  588. /* reopen all the files (to get oldest for time stamp) */
  589. for(ndb = db; ndb; ndb = ndb->next)
  590. ndbreopen(ndb);
  591. if(cachedb){
  592. /* mark all db records as timed out */
  593. dnagedb();
  594. /* read in new entries */
  595. for(ndb = db; ndb; ndb = ndb->next)
  596. dbfile2cache(ndb);
  597. /* mark as authentic anything in our domain */
  598. dnauthdb();
  599. /* remove old entries */
  600. dnageall(1);
  601. } else {
  602. /* read all the soa's to get database defaults */
  603. for(ndb = db; ndb; ndb = ndb->next)
  604. dbfile2area(ndb);
  605. }
  606. doit = 0;
  607. lastyoungest = youngest;
  608. createptrs();
  609. }
  610. unlock(&dblock);
  611. }
  612. extern uchar ipaddr[IPaddrlen];
  613. /*
  614. * get all my xxx
  615. */
  616. Ndbtuple*
  617. lookupinfo(char *attr)
  618. {
  619. char buf[64];
  620. char *a[2];
  621. static Ndbtuple *t;
  622. snprint(buf, sizeof buf, "%I", ipaddr);
  623. a[0] = attr;
  624. lock(&dblock);
  625. if(opendatabase() < 0){
  626. unlock(&dblock);
  627. return nil;
  628. }
  629. t = ndbipinfo(db, "ip", buf, a, 1);
  630. unlock(&dblock);
  631. return t;
  632. }
  633. char *localservers = "local#dns#servers";
  634. char *localserverprefix = "local#dns#server";
  635. /*
  636. * return non-zero is this is a bad delegation
  637. */
  638. int
  639. baddelegation(RR *rp, RR *nsrp, uchar *addr)
  640. {
  641. Ndbtuple *nt;
  642. static Ndbtuple *t;
  643. if(t == nil)
  644. t = lookupinfo("dom");
  645. if(t == nil)
  646. return 0;
  647. for(; rp; rp = rp->next){
  648. if(rp->type != Tns)
  649. continue;
  650. /* see if delegation is looping */
  651. if(nsrp)
  652. if(rp->owner != nsrp->owner)
  653. if(subsume(rp->owner->name, nsrp->owner->name) &&
  654. strcmp(nsrp->owner->name, localservers) != 0){
  655. syslog(0, logfile, "delegation loop %R -> %R from %I", nsrp, rp, addr);
  656. return 1;
  657. }
  658. /* see if delegating to us what we don't own */
  659. for(nt = t; nt != nil; nt = nt->entry)
  660. if(rp->host && cistrcmp(rp->host->name, nt->val) == 0)
  661. break;
  662. if(nt != nil && !inmyarea(rp->owner->name)){
  663. syslog(0, logfile, "bad delegation %R from %I", rp, addr);
  664. return 1;
  665. }
  666. }
  667. return 0;
  668. }
  669. static void
  670. addlocaldnsserver(DN *dp, int class, char *ipaddr, int i)
  671. {
  672. DN *nsdp;
  673. RR *rp;
  674. char buf[32];
  675. /* ns record for name server, make up an impossible name */
  676. rp = rralloc(Tns);
  677. snprint(buf, sizeof(buf), "%s%d", localserverprefix, i);
  678. nsdp = dnlookup(buf, class, 1);
  679. rp->host = nsdp;
  680. rp->owner = dp;
  681. rp->local = 1;
  682. rp->db = 1;
  683. rp->ttl = 10*Min;
  684. rrattach(rp, 1);
  685. /* A record */
  686. rp = rralloc(Ta);
  687. rp->ip = dnlookup(ipaddr, class, 1);
  688. rp->owner = nsdp;
  689. rp->local = 1;
  690. rp->db = 1;
  691. rp->ttl = 10*Min;
  692. rrattach(rp, 1);
  693. }
  694. /*
  695. * return list of dns server addresses to use when
  696. * acting just as a resolver.
  697. */
  698. RR*
  699. dnsservers(int class)
  700. {
  701. Ndbtuple *t, *nt;
  702. RR *nsrp;
  703. DN *dp;
  704. char *p;
  705. int i, n;
  706. char *buf, *args[5];
  707. dp = dnlookup(localservers, class, 1);
  708. nsrp = rrlookup(dp, Tns, NOneg);
  709. if(nsrp != nil)
  710. return nsrp;
  711. p = getenv("DNSSERVER");
  712. if(p != nil){
  713. buf = estrdup(p);
  714. n = tokenize(buf, args, nelem(args));
  715. for(i = 0; i < n; i++)
  716. addlocaldnsserver(dp, class, args[i], i);
  717. free(buf);
  718. } else {
  719. t = lookupinfo("@dns");
  720. if(t == nil)
  721. return nil;
  722. i = 0;
  723. for(nt = t; nt != nil; nt = nt->entry){
  724. addlocaldnsserver(dp, class, nt->val, i);
  725. i++;
  726. }
  727. ndbfree(t);
  728. }
  729. return rrlookup(dp, Tns, NOneg);
  730. }
  731. static void
  732. addlocaldnsdomain(DN *dp, int class, char *domain)
  733. {
  734. RR *rp;
  735. /* A record */
  736. rp = rralloc(Tptr);
  737. rp->ptr = dnlookup(domain, class, 1);
  738. rp->owner = dp;
  739. rp->db = 1;
  740. rp->ttl = 10*Min;
  741. rrattach(rp, 1);
  742. }
  743. /*
  744. * return list of domains to use when resolving names without '.'s
  745. */
  746. RR*
  747. domainlist(int class)
  748. {
  749. Ndbtuple *t, *nt;
  750. RR *rp;
  751. DN *dp;
  752. dp = dnlookup("local#dns#domains", class, 1);
  753. rp = rrlookup(dp, Tptr, NOneg);
  754. if(rp != nil)
  755. return rp;
  756. t = lookupinfo("dnsdomain");
  757. if(t == nil)
  758. return nil;
  759. for(nt = t; nt != nil; nt = nt->entry)
  760. addlocaldnsdomain(dp, class, nt->val);
  761. ndbfree(t);
  762. return rrlookup(dp, Tptr, NOneg);
  763. }
  764. char *v4ptrdom = ".in-addr.arpa";
  765. char *v6ptrdom = ".ip6.int";
  766. char *attribs[] = {
  767. "ipmask",
  768. 0
  769. };
  770. /*
  771. * create ptrs that are in our areas
  772. */
  773. static void
  774. createptrs(void)
  775. {
  776. int len, dlen, n;
  777. Area *s;
  778. char *f[40];
  779. char buf[Domlen+1];
  780. uchar net[IPaddrlen];
  781. uchar mask[IPaddrlen];
  782. char ipa[48];
  783. Ndbtuple *t, *nt;
  784. dlen = strlen(v4ptrdom);
  785. for(s = owned; s; s = s->next){
  786. len = strlen(s->soarr->owner->name);
  787. if(len <= dlen)
  788. continue;
  789. if(cistrcmp(s->soarr->owner->name+len-dlen, v4ptrdom) != 0)
  790. continue;
  791. /* get mask and net value */
  792. strncpy(buf, s->soarr->owner->name, sizeof(buf));
  793. buf[sizeof(buf)-1] = 0;
  794. n = getfields(buf, f, nelem(f), 0, ".");
  795. memset(mask, 0xff, IPaddrlen);
  796. ipmove(net, v4prefix);
  797. switch(n){
  798. case 3: /* /8 */
  799. net[IPv4off] = atoi(f[0]);
  800. mask[IPv4off+1] = 0;
  801. mask[IPv4off+2] = 0;
  802. mask[IPv4off+3] = 0;
  803. break;
  804. case 4: /* /16 */
  805. net[IPv4off] = atoi(f[1]);
  806. net[IPv4off+1] = atoi(f[0]);
  807. mask[IPv4off+2] = 0;
  808. mask[IPv4off+3] = 0;
  809. break;
  810. case 5: /* /24 */
  811. net[IPv4off] = atoi(f[2]);
  812. net[IPv4off+1] = atoi(f[1]);
  813. net[IPv4off+2] = atoi(f[0]);
  814. mask[IPv4off+3] = 0;
  815. break;
  816. case 6: /* rfc2317 */
  817. net[IPv4off] = atoi(f[3]);
  818. net[IPv4off+1] = atoi(f[2]);
  819. net[IPv4off+2] = atoi(f[1]);
  820. net[IPv4off+3] = atoi(f[0]);
  821. sprint(ipa, "%I", net);
  822. t = ndbipinfo(db, "ip", ipa, attribs, 1);
  823. nt = look(t, t, "ipmask");
  824. if(nt == nil){ /* we're confused */
  825. ndbfree(t);
  826. continue;
  827. }
  828. parseipmask(mask, nt->val);
  829. n = 5;
  830. break;
  831. default:
  832. continue;
  833. }
  834. /* go through all domain entries looking for RR's in this network and create ptrs */
  835. dnptr(net, mask, s->soarr->owner->name, 6-n, 0);
  836. }
  837. }