Blob


1 #include <u.h>
2 #include <libc.h>
3 #include <bio.h>
4 #include <ndb.h>
5 #include <ip.h>
6 #include "dns.h"
8 static Ndb *db;
10 static RR* dblookup1(char*, int, int, int);
11 static RR* addrrr(Ndbtuple*, Ndbtuple*);
12 static RR* nsrr(Ndbtuple*, Ndbtuple*);
13 static RR* cnamerr(Ndbtuple*, Ndbtuple*);
14 static RR* mxrr(Ndbtuple*, Ndbtuple*);
15 static RR* soarr(Ndbtuple*, Ndbtuple*);
16 static RR* ptrrr(Ndbtuple*, Ndbtuple*);
17 static Ndbtuple* look(Ndbtuple*, Ndbtuple*, char*);
18 static RR* doaxfr(Ndb*, char*);
19 static RR* nullrr(Ndbtuple *entry, Ndbtuple *pair);
20 static RR* txtrr(Ndbtuple *entry, Ndbtuple *pair);
21 static Lock dblock;
22 static void createptrs(void);
24 static int implemented[Tall] =
25 {
26 0,
27 /* Ta */ 1,
28 /* Tns */ 1,
29 0,
30 0,
31 /* Tcname */ 1,
32 /* Tsoa */ 1,
33 0,
34 0,
35 0,
36 /* Tnull */ 1,
37 0,
38 /* Tptr */ 1,
39 0,
40 0,
41 /* Tmx */ 1,
42 /* Ttxt */ 1
43 };
45 static void
46 nstrcpy(char *to, char *from, int len)
47 {
48 strncpy(to, from, len);
49 to[len-1] = 0;
50 }
52 int
53 opendatabase(void)
54 {
55 char buf[256];
56 Ndb *xdb;
58 if(db == nil){
59 snprint(buf, sizeof(buf), "%s/ndb", mntpt);
60 xdb = ndbopen(dbfile);
61 if(xdb != nil)
62 xdb->nohash = 1;
63 db = ndbcat(ndbopen(buf), xdb);
64 }
65 if(db == nil)
66 return -1;
67 else
68 return 0;
69 }
71 /*
72 * lookup an RR in the network database, look for matches
73 * against both the domain name and the wildcarded domain name.
74 *
75 * the lock makes sure only one process can be accessing the data
76 * base at a time. This is important since there's a lot of
77 * shared state there.
78 *
79 * e.g. for x.research.bell-labs.com, first look for a match against
80 * the x.research.bell-labs.com. If nothing matches, try *.research.bell-labs.com.
81 */
82 RR*
83 dblookup(char *name, int class, int type, int auth, int ttl)
84 {
85 RR *rp, *tp;
86 char buf[256];
87 char *wild, *cp;
88 DN *dp, *ndp;
89 int err;
91 /* so far only internet lookups are implemented */
92 if(class != Cin)
93 return 0;
95 err = Rname;
97 if(type == Tall){
98 rp = 0;
99 for (type = Ta; type < Tall; type++)
100 if(implemented[type])
101 rrcat(&rp, dblookup(name, class, type, auth, ttl));
102 return rp;
105 lock(&dblock);
106 rp = nil;
107 dp = dnlookup(name, class, 1);
108 if(opendatabase() < 0)
109 goto out;
110 if(dp->rr)
111 err = 0;
113 /* first try the given name */
114 rp = 0;
115 if(cachedb)
116 rp = rrlookup(dp, type, NOneg);
117 else
118 rp = dblookup1(name, type, auth, ttl);
119 if(rp)
120 goto out;
122 /* try lower case version */
123 for(cp = name; *cp; cp++)
124 *cp = tolower((uchar)*cp);
125 if(cachedb)
126 rp = rrlookup(dp, type, NOneg);
127 else
128 rp = dblookup1(name, type, auth, ttl);
129 if(rp)
130 goto out;
132 /* walk the domain name trying the wildcard '*' at each position */
133 for(wild = strchr(name, '.'); wild; wild = strchr(wild+1, '.')){
134 snprint(buf, sizeof(buf), "*%s", wild);
135 ndp = dnlookup(buf, class, 1);
136 if(ndp->rr)
137 err = 0;
138 if(cachedb)
139 rp = rrlookup(ndp, type, NOneg);
140 else
141 rp = dblookup1(buf, type, auth, ttl);
142 if(rp)
143 break;
145 out:
146 /* add owner to uncached records */
147 if(rp){
148 for(tp = rp; tp; tp = tp->next)
149 tp->owner = dp;
150 } else {
151 /* don't call it non-existent if it's not ours */
152 if(err == Rname && !inmyarea(name))
153 err = Rserver;
154 dp->nonexistent = err;
157 unlock(&dblock);
158 return rp;
161 /*
162 * lookup an RR in the network database
163 */
164 static RR*
165 dblookup1(char *name, int type, int auth, int ttl)
167 Ndbtuple *t, *nt;
168 RR *rp, *list, **l;
169 Ndbs s;
170 char dname[Domlen];
171 char *attr;
172 DN *dp;
173 RR *(*f)(Ndbtuple*, Ndbtuple*);
174 int found, x;
176 dp = 0;
177 switch(type){
178 case Tptr:
179 attr = "ptr";
180 f = ptrrr;
181 break;
182 case Ta:
183 attr = "ip";
184 f = addrrr;
185 break;
186 case Tnull:
187 attr = "nullrr";
188 f = nullrr;
189 break;
190 case Tns:
191 attr = "ns";
192 f = nsrr;
193 break;
194 case Tsoa:
195 attr = "soa";
196 f = soarr;
197 break;
198 case Tmx:
199 attr = "mx";
200 f = mxrr;
201 break;
202 case Tcname:
203 attr = "cname";
204 f = cnamerr;
205 break;
206 case Taxfr:
207 case Tixfr:
208 return doaxfr(db, name);
209 default:
210 return nil;
213 /*
214 * find a matching entry in the database
215 */
216 free(ndbgetvalue(db, &s, "dom", name, attr, &t));
218 /*
219 * hack for local names
220 */
221 if(t == 0 && strchr(name, '.') == 0)
222 free(ndbgetvalue(db, &s, "sys", name, attr, &t));
223 if(t == 0)
224 return nil;
226 /* search whole entry for default domain name */
227 strncpy(dname, name, sizeof dname);
228 for(nt = t; nt; nt = nt->entry)
229 if(strcmp(nt->attr, "dom") == 0){
230 nstrcpy(dname, nt->val, sizeof dname);
231 break;
234 /* ttl is maximum of soa minttl and entry's ttl ala rfc883 */
235 nt = look(t, s.t, "ttl");
236 if(nt){
237 x = atoi(nt->val);
238 if(x > ttl)
239 ttl = x;
242 /* default ttl is one day */
243 if(ttl < 0)
244 ttl = DEFTTL;
246 /*
247 * The database has 2 levels of precedence; line and entry.
248 * Pairs on the same line bind tighter than pairs in the
249 * same entry, so we search the line first.
250 */
251 found = 0;
252 list = 0;
253 l = &list;
254 for(nt = s.t;; ){
255 if(found == 0 && strcmp(nt->attr, "dom") == 0){
256 nstrcpy(dname, nt->val, sizeof dname);
257 found = 1;
259 if(cistrcmp(attr, nt->attr) == 0){
260 rp = (*f)(t, nt);
261 rp->auth = auth;
262 rp->db = 1;
263 if(ttl)
264 rp->ttl = ttl;
265 if(dp == 0)
266 dp = dnlookup(dname, Cin, 1);
267 rp->owner = dp;
268 *l = rp;
269 l = &rp->next;
270 nt->ptr = 1;
272 nt = nt->line;
273 if(nt == s.t)
274 break;
277 /* search whole entry */
278 for(nt = t; nt; nt = nt->entry)
279 if(nt->ptr == 0 && cistrcmp(attr, nt->attr) == 0){
280 rp = (*f)(t, nt);
281 rp->db = 1;
282 if(ttl)
283 rp->ttl = ttl;
284 rp->auth = auth;
285 if(dp == 0)
286 dp = dnlookup(dname, Cin, 1);
287 rp->owner = dp;
288 *l = rp;
289 l = &rp->next;
291 ndbfree(t);
293 return list;
296 /*
297 * make various types of resource records from a database entry
298 */
299 static RR*
300 addrrr(Ndbtuple *entry, Ndbtuple *pair)
302 RR *rp;
303 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;
314 static RR*
315 nullrr(Ndbtuple *entry, Ndbtuple *pair)
317 RR *rp;
319 USED(entry);
320 rp = rralloc(Tnull);
321 rp->null->data = (uchar*)estrdup(pair->val);
322 rp->null->dlen = strlen((char*)rp->null->data);
323 return rp;
325 /*
326 * txt rr strings are at most 255 bytes long. one
327 * can represent longer strings by multiple concatenated
328 * <= 255 byte ones.
329 */
330 static RR*
331 txtrr(Ndbtuple *entry, Ndbtuple *pair)
333 RR *rp;
334 Txt *t, **l;
335 int i, len, sofar;
337 USED(entry);
338 rp = rralloc(Ttxt);
339 l = &rp->txt;
340 rp->txt = nil;
341 len = strlen(pair->val);
342 sofar = 0;
343 while(len > sofar){
344 t = emalloc(sizeof(*t));
345 t->next = nil;
347 i = len-sofar;
348 if(i > 255)
349 i = 255;
351 t->p = emalloc(i+1);
352 memmove(t->p, pair->val+sofar, i);
353 t->p[i] = 0;
354 sofar += i;
356 *l = t;
357 l = &t->next;
359 return rp;
361 static RR*
362 cnamerr(Ndbtuple *entry, Ndbtuple *pair)
364 RR *rp;
366 USED(entry);
367 rp = rralloc(Tcname);
368 rp->host = dnlookup(pair->val, Cin, 1);
369 return rp;
371 static RR*
372 mxrr(Ndbtuple *entry, Ndbtuple *pair)
374 RR * rp;
376 rp = rralloc(Tmx);
377 rp->host = dnlookup(pair->val, Cin, 1);
378 pair = look(entry, pair, "pref");
379 if(pair)
380 rp->pref = atoi(pair->val);
381 else
382 rp->pref = 1;
383 return rp;
385 static RR*
386 nsrr(Ndbtuple *entry, Ndbtuple *pair)
388 RR *rp;
389 Ndbtuple *t;
391 rp = rralloc(Tns);
392 rp->host = dnlookup(pair->val, Cin, 1);
393 t = look(entry, pair, "soa");
394 if(t && t->val[0] == 0)
395 rp->local = 1;
396 return rp;
398 static RR*
399 ptrrr(Ndbtuple *entry, Ndbtuple *pair)
401 RR *rp;
403 USED(entry);
404 rp = rralloc(Tns);
405 rp->ptr = dnlookup(pair->val, Cin, 1);
406 return rp;
408 static RR*
409 soarr(Ndbtuple *entry, Ndbtuple *pair)
411 RR *rp;
412 Ndbtuple *ns, *mb, *t;
413 char mailbox[Domlen];
414 Ndb *ndb;
415 char *p;
417 rp = rralloc(Tsoa);
418 rp->soa->serial = 1;
419 for(ndb = db; ndb; ndb = ndb->next)
420 if(ndb->mtime > rp->soa->serial)
421 rp->soa->serial = ndb->mtime;
422 rp->soa->refresh = Day;
423 rp->soa->retry = Hour;
424 rp->soa->expire = Day;
425 rp->soa->minttl = Day;
426 t = look(entry, pair, "ttl");
427 if(t)
428 rp->soa->minttl = atoi(t->val);
429 t = look(entry, pair, "refresh");
430 if(t)
431 rp->soa->refresh = atoi(t->val);
432 t = look(entry, pair, "serial");
433 if(t)
434 rp->soa->serial = strtoul(t->val, 0, 10);
436 ns = look(entry, pair, "ns");
437 if(ns == 0)
438 ns = look(entry, pair, "dom");
439 rp->host = dnlookup(ns->val, Cin, 1);
441 /* accept all of:
442 * mbox=person
443 * mbox=person@machine.dom
444 * mbox=person.machine.dom
445 */
446 mb = look(entry, pair, "mbox");
447 if(mb == nil)
448 mb = look(entry, pair, "mb");
449 if(mb){
450 if(strchr(mb->val, '.')) {
451 p = strchr(mb->val, '@');
452 if(p != nil)
453 *p = '.';
454 rp->rmb = dnlookup(mb->val, Cin, 1);
455 } else {
456 snprint(mailbox, sizeof(mailbox), "%s.%s",
457 mb->val, ns->val);
458 rp->rmb = dnlookup(mailbox, Cin, 1);
460 } else {
461 snprint(mailbox, sizeof(mailbox), "postmaster.%s",
462 ns->val);
463 rp->rmb = dnlookup(mailbox, Cin, 1);
466 /* hang dns slaves off of the soa. this is
467 * for managing the area.
468 */
469 for(t = entry; t != nil; t = t->entry)
470 if(strcmp(t->attr, "dnsslave") == 0)
471 addserver(&rp->soa->slaves, t->val);
473 return rp;
476 /*
477 * Look for a pair with the given attribute. look first on the same line,
478 * then in the whole entry.
479 */
480 static Ndbtuple*
481 look(Ndbtuple *entry, Ndbtuple *line, char *attr)
483 Ndbtuple *nt;
485 /* first look on same line (closer binding) */
486 for(nt = line;;){
487 if(cistrcmp(attr, nt->attr) == 0)
488 return nt;
489 nt = nt->line;
490 if(nt == line)
491 break;
493 /* search whole tuple */
494 for(nt = entry; nt; nt = nt->entry)
495 if(cistrcmp(attr, nt->attr) == 0)
496 return nt;
497 return 0;
500 /* these are answered specially by the tcp version */
501 static RR*
502 doaxfr(Ndb *db, char *name)
504 USED(db);
505 USED(name);
506 return 0;
510 /*
511 * read the all the soa's from the database to determine area's.
512 * this is only used when we're not caching the database.
513 */
514 static void
515 dbfile2area(Ndb *db)
517 Ndbtuple *t;
519 if(debug)
520 syslog(0, logfile, "rereading %s", db->file);
521 Bseek(&db->b, 0, 0);
522 while(t = ndbparse(db)){
523 ndbfree(t);
527 /*
528 * read the database into the cache
529 */
530 static void
531 dbpair2cache(DN *dp, Ndbtuple *entry, Ndbtuple *pair)
533 RR *rp;
534 Ndbtuple *t;
535 static ulong ord;
537 rp = 0;
538 if(cistrcmp(pair->attr, "ip") == 0){
539 dp->ordinal = ord++;
540 rp = addrrr(entry, pair);
541 } else if(cistrcmp(pair->attr, "ns") == 0){
542 rp = nsrr(entry, pair);
543 } else if(cistrcmp(pair->attr, "soa") == 0){
544 rp = soarr(entry, pair);
545 addarea(dp, rp, pair);
546 } else if(cistrcmp(pair->attr, "mx") == 0){
547 rp = mxrr(entry, pair);
548 } else if(cistrcmp(pair->attr, "cname") == 0){
549 rp = cnamerr(entry, pair);
550 } else if(cistrcmp(pair->attr, "nullrr") == 0){
551 rp = nullrr(entry, pair);
552 } else if(cistrcmp(pair->attr, "txtrr") == 0){
553 rp = txtrr(entry, pair);
556 if(rp == 0)
557 return;
559 rp->owner = dp;
560 rp->db = 1;
561 t = look(entry, pair, "ttl");
562 if(t)
563 rp->ttl = atoi(t->val);
564 rrattach(rp, 0);
566 static void
567 dbtuple2cache(Ndbtuple *t)
569 Ndbtuple *et, *nt;
570 DN *dp;
572 for(et = t; et; et = et->entry){
573 if(strcmp(et->attr, "dom") == 0){
574 dp = dnlookup(et->val, Cin, 1);
576 /* first same line */
577 for(nt = et->line; nt != et; nt = nt->line){
578 dbpair2cache(dp, t, nt);
579 nt->ptr = 1;
582 /* then rest of entry */
583 for(nt = t; nt; nt = nt->entry){
584 if(nt->ptr == 0)
585 dbpair2cache(dp, t, nt);
586 nt->ptr = 0;
591 static void
592 dbfile2cache(Ndb *db)
594 Ndbtuple *t;
596 if(debug)
597 syslog(0, logfile, "rereading %s", db->file);
598 Bseek(&db->b, 0, 0);
599 while(t = ndbparse(db)){
600 dbtuple2cache(t);
601 ndbfree(t);
604 void
605 db2cache(int doit)
607 Ndb *ndb;
608 Dir *d;
609 ulong youngest, temp;
610 static ulong lastcheck;
611 static ulong lastyoungest;
613 /* no faster than once every 2 minutes */
614 if(now < lastcheck + 2*Min && !doit)
615 return;
617 refresh_areas(owned);
619 lock(&dblock);
621 if(opendatabase() < 0){
622 unlock(&dblock);
623 return;
626 /*
627 * file may be changing as we are reading it, so loop till
628 * mod times are consistent.
630 * we don't use the times in the ndb records because they may
631 * change outside of refreshing our cached knowledge.
632 */
633 for(;;){
634 lastcheck = now;
635 youngest = 0;
636 for(ndb = db; ndb; ndb = ndb->next){
637 /* the dirfstat avoids walking the mount table each time */
638 if((d = dirfstat(Bfildes(&ndb->b))) != nil ||
639 (d = dirstat(ndb->file)) != nil){
640 temp = d->mtime; /* ulong vs int crap */
641 if(temp > youngest)
642 youngest = temp;
643 free(d);
646 if(!doit && youngest == lastyoungest){
647 unlock(&dblock);
648 return;
651 /* forget our area definition */
652 freearea(&owned);
653 freearea(&delegated);
655 /* reopen all the files (to get oldest for time stamp) */
656 for(ndb = db; ndb; ndb = ndb->next)
657 ndbreopen(ndb);
659 if(cachedb){
660 /* mark all db records as timed out */
661 dnagedb();
663 /* read in new entries */
664 for(ndb = db; ndb; ndb = ndb->next)
665 dbfile2cache(ndb);
667 /* mark as authentic anything in our domain */
668 dnauthdb();
670 /* remove old entries */
671 dnageall(1);
672 } else {
673 /* read all the soa's to get database defaults */
674 for(ndb = db; ndb; ndb = ndb->next)
675 dbfile2area(ndb);
678 doit = 0;
679 lastyoungest = youngest;
680 createptrs();
683 unlock(&dblock);
686 extern uchar ipaddr[IPaddrlen];
688 /*
689 * get all my xxx
690 */
691 Ndbtuple*
692 lookupinfo(char *attr)
694 char buf[64];
695 char *a[2];
696 static Ndbtuple *t;
698 snprint(buf, sizeof buf, "%I", ipaddr);
699 a[0] = attr;
701 lock(&dblock);
702 if(opendatabase() < 0){
703 unlock(&dblock);
704 return nil;
706 t = ndbipinfo(db, "ip", buf, a, 1);
707 unlock(&dblock);
708 return t;
711 char *localservers = "local#dns#servers";
712 char *localserverprefix = "local#dns#server";
714 /*
715 * return non-zero is this is a bad delegation
716 */
717 int
718 baddelegation(RR *rp, RR *nsrp, uchar *addr)
720 Ndbtuple *nt;
721 static Ndbtuple *t;
723 if(t == nil)
724 t = lookupinfo("dom");
725 if(t == nil)
726 return 0;
728 for(; rp; rp = rp->next){
729 if(rp->type != Tns)
730 continue;
732 /* see if delegation is looping */
733 if(nsrp)
734 if(rp->owner != nsrp->owner)
735 if(subsume(rp->owner->name, nsrp->owner->name) &&
736 strcmp(nsrp->owner->name, localservers) != 0){
737 syslog(0, logfile, "delegation loop %R -> %R from %I", nsrp, rp, addr);
738 return 1;
741 /* see if delegating to us what we don't own */
742 for(nt = t; nt != nil; nt = nt->entry)
743 if(rp->host && cistrcmp(rp->host->name, nt->val) == 0)
744 break;
745 if(nt != nil && !inmyarea(rp->owner->name)){
746 syslog(0, logfile, "bad delegation %R from %I", rp, addr);
747 return 1;
751 return 0;
754 static void
755 addlocaldnsserver(DN *dp, int class, char *ipaddr, int i)
757 DN *nsdp;
758 RR *rp;
759 char buf[32];
761 /* ns record for name server, make up an impossible name */
762 rp = rralloc(Tns);
763 snprint(buf, sizeof(buf), "%s%d", localserverprefix, i);
764 nsdp = dnlookup(buf, class, 1);
765 rp->host = nsdp;
766 rp->owner = dp;
767 rp->local = 1;
768 rp->db = 1;
769 rp->ttl = 10*Min;
770 rrattach(rp, 1);
772 print("dns %s\n", ipaddr);
773 /* A record */
774 rp = rralloc(Ta);
775 rp->ip = dnlookup(ipaddr, class, 1);
776 rp->owner = nsdp;
777 rp->local = 1;
778 rp->db = 1;
779 rp->ttl = 10*Min;
780 rrattach(rp, 1);
783 /*
784 * return list of dns server addresses to use when
785 * acting just as a resolver.
786 */
787 RR*
788 dnsservers(int class)
790 Ndbtuple *t, *nt;
791 RR *nsrp;
792 DN *dp;
793 char *p;
794 int i, n;
795 char *buf, *args[5];
797 dp = dnlookup(localservers, class, 1);
798 nsrp = rrlookup(dp, Tns, NOneg);
799 if(nsrp != nil)
800 return nsrp;
802 p = getenv("DNSSERVER");
803 if(p != nil){
804 buf = estrdup(p);
805 n = tokenize(buf, args, nelem(args));
806 for(i = 0; i < n; i++)
807 addlocaldnsserver(dp, class, args[i], i);
808 free(buf);
809 } else {
810 t = lookupinfo("@dns");
811 if(t == nil)
812 return nil;
813 i = 0;
814 for(nt = t; nt != nil; nt = nt->entry){
815 addlocaldnsserver(dp, class, nt->val, i);
816 i++;
818 ndbfree(t);
821 return rrlookup(dp, Tns, NOneg);
824 static void
825 addlocaldnsdomain(DN *dp, int class, char *domain)
827 RR *rp;
829 /* A record */
830 rp = rralloc(Tptr);
831 rp->ptr = dnlookup(domain, class, 1);
832 rp->owner = dp;
833 rp->db = 1;
834 rp->ttl = 10*Min;
835 rrattach(rp, 1);
838 /*
839 * return list of domains to use when resolving names without '.'s
840 */
841 RR*
842 domainlist(int class)
844 Ndbtuple *t, *nt;
845 RR *rp;
846 DN *dp;
848 dp = dnlookup("local#dns#domains", class, 1);
849 rp = rrlookup(dp, Tptr, NOneg);
850 if(rp != nil)
851 return rp;
853 t = lookupinfo("dnsdomain");
854 if(t == nil)
855 return nil;
856 for(nt = t; nt != nil; nt = nt->entry)
857 addlocaldnsdomain(dp, class, nt->val);
858 ndbfree(t);
860 return rrlookup(dp, Tptr, NOneg);
863 char *v4ptrdom = ".in-addr.arpa";
864 char *v6ptrdom = ".ip6.arpa"; /* ip6.int deprecated, rfc 3152 */
866 char *attribs[] = {
867 "ipmask",
869 };
871 /*
872 * create ptrs that are in our areas
873 */
874 static void
875 createptrs(void)
877 int len, dlen, n;
878 Area *s;
879 char *f[40];
880 char buf[Domlen+1];
881 uchar net[IPaddrlen];
882 uchar mask[IPaddrlen];
883 char ipa[48];
884 Ndbtuple *t, *nt;
886 dlen = strlen(v4ptrdom);
887 for(s = owned; s; s = s->next){
888 len = strlen(s->soarr->owner->name);
889 if(len <= dlen)
890 continue;
891 if(cistrcmp(s->soarr->owner->name+len-dlen, v4ptrdom) != 0)
892 continue;
894 /* get mask and net value */
895 strncpy(buf, s->soarr->owner->name, sizeof(buf));
896 buf[sizeof(buf)-1] = 0;
897 n = getfields(buf, f, nelem(f), 0, ".");
898 memset(mask, 0xff, IPaddrlen);
899 ipmove(net, v4prefix);
900 switch(n){
901 case 3: /* /8 */
902 net[IPv4off] = atoi(f[0]);
903 mask[IPv4off+1] = 0;
904 mask[IPv4off+2] = 0;
905 mask[IPv4off+3] = 0;
906 break;
907 case 4: /* /16 */
908 net[IPv4off] = atoi(f[1]);
909 net[IPv4off+1] = atoi(f[0]);
910 mask[IPv4off+2] = 0;
911 mask[IPv4off+3] = 0;
912 break;
913 case 5: /* /24 */
914 net[IPv4off] = atoi(f[2]);
915 net[IPv4off+1] = atoi(f[1]);
916 net[IPv4off+2] = atoi(f[0]);
917 mask[IPv4off+3] = 0;
918 break;
919 case 6: /* rfc2317 */
920 net[IPv4off] = atoi(f[3]);
921 net[IPv4off+1] = atoi(f[2]);
922 net[IPv4off+2] = atoi(f[1]);
923 net[IPv4off+3] = atoi(f[0]);
924 sprint(ipa, "%I", net);
925 t = ndbipinfo(db, "ip", ipa, attribs, 1);
926 if(t == nil) /* could be a reverse with no forward */
927 continue;
928 nt = look(t, t, "ipmask");
929 if(nt == nil){ /* we're confused */
930 ndbfree(t);
931 continue;
933 parseipmask(mask, nt->val);
934 n = 5;
935 break;
936 default:
937 continue;
940 /* go through all domain entries looking for RR's in this network and create ptrs */
941 dnptr(net, mask, s->soarr->owner->name, 6-n, 0);