dblookup.c 25 KB

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