dblookup.c 25 KB

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