dblookup.c 24 KB

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