dblookup.c 25 KB

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