dblookup.c 25 KB

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