dblookup.c 21 KB

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