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 dp = dnlookup(name, class, 1);
107 if(opendatabase() < 0)
108 goto out;
109 if(dp->rr)
110 err = 0;
112 /* first try the given name */
113 rp = 0;
114 if(cachedb)
115 rp = rrlookup(dp, type, NOneg);
116 else
117 rp = dblookup1(name, type, auth, ttl);
118 if(rp)
119 goto out;
121 /* try lower case version */
122 for(cp = name; *cp; cp++)
123 *cp = tolower((uchar)*cp);
124 if(cachedb)
125 rp = rrlookup(dp, type, NOneg);
126 else
127 rp = dblookup1(name, type, auth, ttl);
128 if(rp)
129 goto out;
131 /* walk the domain name trying the wildcard '*' at each position */
132 for(wild = strchr(name, '.'); wild; wild = strchr(wild+1, '.')){
133 snprint(buf, sizeof(buf), "*%s", wild);
134 ndp = dnlookup(buf, class, 1);
135 if(ndp->rr)
136 err = 0;
137 if(cachedb)
138 rp = rrlookup(ndp, type, NOneg);
139 else
140 rp = dblookup1(buf, type, auth, ttl);
141 if(rp)
142 break;
144 out:
145 /* add owner to uncached records */
146 if(rp){
147 for(tp = rp; tp; tp = tp->next)
148 tp->owner = dp;
149 } else {
150 /* don't call it non-existent if it's not ours */
151 if(err == Rname && !inmyarea(name))
152 err = Rserver;
153 dp->nonexistent = err;
156 unlock(&dblock);
157 return rp;
160 /*
161 * lookup an RR in the network database
162 */
163 static RR*
164 dblookup1(char *name, int type, int auth, int ttl)
166 Ndbtuple *t, *nt;
167 RR *rp, *list, **l;
168 Ndbs s;
169 char dname[Domlen];
170 char *attr;
171 DN *dp;
172 RR *(*f)(Ndbtuple*, Ndbtuple*);
173 int found, x;
175 dp = 0;
176 switch(type){
177 case Tptr:
178 attr = "ptr";
179 f = ptrrr;
180 break;
181 case Ta:
182 attr = "ip";
183 f = addrrr;
184 break;
185 case Tnull:
186 attr = "nullrr";
187 f = nullrr;
188 break;
189 case Tns:
190 attr = "ns";
191 f = nsrr;
192 break;
193 case Tsoa:
194 attr = "soa";
195 f = soarr;
196 break;
197 case Tmx:
198 attr = "mx";
199 f = mxrr;
200 break;
201 case Tcname:
202 attr = "cname";
203 f = cnamerr;
204 break;
205 case Taxfr:
206 case Tixfr:
207 return doaxfr(db, name);
208 default:
209 return nil;
212 /*
213 * find a matching entry in the database
214 */
215 free(ndbgetvalue(db, &s, "dom", name, attr, &t));
217 /*
218 * hack for local names
219 */
220 if(t == 0 && strchr(name, '.') == 0)
221 free(ndbgetvalue(db, &s, "sys", name, attr, &t));
222 if(t == 0)
223 return nil;
225 /* search whole entry for default domain name */
226 strncpy(dname, name, sizeof dname);
227 for(nt = t; nt; nt = nt->entry)
228 if(strcmp(nt->attr, "dom") == 0){
229 nstrcpy(dname, nt->val, sizeof dname);
230 break;
233 /* ttl is maximum of soa minttl and entry's ttl ala rfc883 */
234 nt = look(t, s.t, "ttl");
235 if(nt){
236 x = atoi(nt->val);
237 if(x > ttl)
238 ttl = x;
241 /* default ttl is one day */
242 if(ttl < 0)
243 ttl = DEFTTL;
245 /*
246 * The database has 2 levels of precedence; line and entry.
247 * Pairs on the same line bind tighter than pairs in the
248 * same entry, so we search the line first.
249 */
250 found = 0;
251 list = 0;
252 l = &list;
253 for(nt = s.t;; ){
254 if(found == 0 && strcmp(nt->attr, "dom") == 0){
255 nstrcpy(dname, nt->val, sizeof dname);
256 found = 1;
258 if(cistrcmp(attr, nt->attr) == 0){
259 rp = (*f)(t, nt);
260 rp->auth = auth;
261 rp->db = 1;
262 if(ttl)
263 rp->ttl = ttl;
264 if(dp == 0)
265 dp = dnlookup(dname, Cin, 1);
266 rp->owner = dp;
267 *l = rp;
268 l = &rp->next;
269 nt->ptr = 1;
271 nt = nt->line;
272 if(nt == s.t)
273 break;
276 /* search whole entry */
277 for(nt = t; nt; nt = nt->entry)
278 if(nt->ptr == 0 && cistrcmp(attr, nt->attr) == 0){
279 rp = (*f)(t, nt);
280 rp->db = 1;
281 if(ttl)
282 rp->ttl = ttl;
283 rp->auth = auth;
284 if(dp == 0)
285 dp = dnlookup(dname, Cin, 1);
286 rp->owner = dp;
287 *l = rp;
288 l = &rp->next;
290 ndbfree(t);
292 return list;
295 /*
296 * make various types of resource records from a database entry
297 */
298 static RR*
299 addrrr(Ndbtuple *entry, Ndbtuple *pair)
301 RR *rp;
302 uchar addr[IPaddrlen];
304 USED(entry);
305 parseip(addr, pair->val);
306 if(isv4(addr))
307 rp = rralloc(Ta);
308 else
309 rp = rralloc(Taaaa);
310 rp->ip = dnlookup(pair->val, Cin, 1);
311 return rp;
313 static RR*
314 nullrr(Ndbtuple *entry, Ndbtuple *pair)
316 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;
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)
332 RR *rp;
333 Txt *t, **l;
334 int i, len, sofar;
336 USED(entry);
337 rp = rralloc(Ttxt);
338 l = &rp->txt;
339 rp->txt = nil;
340 len = strlen(pair->val);
341 sofar = 0;
342 while(len > sofar){
343 t = emalloc(sizeof(*t));
344 t->next = nil;
346 i = len-sofar;
347 if(i > 255)
348 i = 255;
350 t->p = emalloc(i+1);
351 memmove(t->p, pair->val+sofar, i);
352 t->p[i] = 0;
353 sofar += i;
355 *l = t;
356 l = &t->next;
358 return rp;
360 static RR*
361 cnamerr(Ndbtuple *entry, Ndbtuple *pair)
363 RR *rp;
365 USED(entry);
366 rp = rralloc(Tcname);
367 rp->host = dnlookup(pair->val, Cin, 1);
368 return rp;
370 static RR*
371 mxrr(Ndbtuple *entry, Ndbtuple *pair)
373 RR * rp;
375 rp = rralloc(Tmx);
376 rp->host = dnlookup(pair->val, Cin, 1);
377 pair = look(entry, pair, "pref");
378 if(pair)
379 rp->pref = atoi(pair->val);
380 else
381 rp->pref = 1;
382 return rp;
384 static RR*
385 nsrr(Ndbtuple *entry, Ndbtuple *pair)
387 RR *rp;
388 Ndbtuple *t;
390 rp = rralloc(Tns);
391 rp->host = dnlookup(pair->val, Cin, 1);
392 t = look(entry, pair, "soa");
393 if(t && t->val[0] == 0)
394 rp->local = 1;
395 return rp;
397 static RR*
398 ptrrr(Ndbtuple *entry, Ndbtuple *pair)
400 RR *rp;
402 USED(entry);
403 rp = rralloc(Tns);
404 rp->ptr = dnlookup(pair->val, Cin, 1);
405 return rp;
407 static RR*
408 soarr(Ndbtuple *entry, Ndbtuple *pair)
410 RR *rp;
411 Ndbtuple *ns, *mb, *t;
412 char mailbox[Domlen];
413 Ndb *ndb;
414 char *p;
416 rp = rralloc(Tsoa);
417 rp->soa->serial = 1;
418 for(ndb = db; ndb; ndb = ndb->next)
419 if(ndb->mtime > rp->soa->serial)
420 rp->soa->serial = ndb->mtime;
421 rp->soa->refresh = Day;
422 rp->soa->retry = Hour;
423 rp->soa->expire = Day;
424 rp->soa->minttl = Day;
425 t = look(entry, pair, "ttl");
426 if(t)
427 rp->soa->minttl = atoi(t->val);
428 t = look(entry, pair, "refresh");
429 if(t)
430 rp->soa->refresh = atoi(t->val);
431 t = look(entry, pair, "serial");
432 if(t)
433 rp->soa->serial = strtoul(t->val, 0, 10);
435 ns = look(entry, pair, "ns");
436 if(ns == 0)
437 ns = look(entry, pair, "dom");
438 rp->host = dnlookup(ns->val, Cin, 1);
440 /* accept all of:
441 * mbox=person
442 * mbox=person@machine.dom
443 * mbox=person.machine.dom
444 */
445 mb = look(entry, pair, "mbox");
446 if(mb == nil)
447 mb = look(entry, pair, "mb");
448 if(mb){
449 if(strchr(mb->val, '.')) {
450 p = strchr(mb->val, '@');
451 if(p != nil)
452 *p = '.';
453 rp->rmb = dnlookup(mb->val, Cin, 1);
454 } else {
455 snprint(mailbox, sizeof(mailbox), "%s.%s",
456 mb->val, ns->val);
457 rp->rmb = dnlookup(mailbox, Cin, 1);
459 } else {
460 snprint(mailbox, sizeof(mailbox), "postmaster.%s",
461 ns->val);
462 rp->rmb = dnlookup(mailbox, Cin, 1);
465 /* hang dns slaves off of the soa. this is
466 * for managing the area.
467 */
468 for(t = entry; t != nil; t = t->entry)
469 if(strcmp(t->attr, "dnsslave") == 0)
470 addserver(&rp->soa->slaves, t->val);
472 return rp;
475 /*
476 * Look for a pair with the given attribute. look first on the same line,
477 * then in the whole entry.
478 */
479 static Ndbtuple*
480 look(Ndbtuple *entry, Ndbtuple *line, char *attr)
482 Ndbtuple *nt;
484 /* first look on same line (closer binding) */
485 for(nt = line;;){
486 if(cistrcmp(attr, nt->attr) == 0)
487 return nt;
488 nt = nt->line;
489 if(nt == line)
490 break;
492 /* search whole tuple */
493 for(nt = entry; nt; nt = nt->entry)
494 if(cistrcmp(attr, nt->attr) == 0)
495 return nt;
496 return 0;
499 /* these are answered specially by the tcp version */
500 static RR*
501 doaxfr(Ndb *db, char *name)
503 USED(db);
504 USED(name);
505 return 0;
509 /*
510 * read the all the soa's from the database to determine area's.
511 * this is only used when we're not caching the database.
512 */
513 static void
514 dbfile2area(Ndb *db)
516 Ndbtuple *t;
518 if(debug)
519 syslog(0, logfile, "rereading %s", db->file);
520 Bseek(&db->b, 0, 0);
521 while(t = ndbparse(db)){
522 ndbfree(t);
526 /*
527 * read the database into the cache
528 */
529 static void
530 dbpair2cache(DN *dp, Ndbtuple *entry, Ndbtuple *pair)
532 RR *rp;
533 Ndbtuple *t;
534 static ulong ord;
536 rp = 0;
537 if(cistrcmp(pair->attr, "ip") == 0){
538 dp->ordinal = ord++;
539 rp = addrrr(entry, pair);
540 } else if(cistrcmp(pair->attr, "ns") == 0){
541 rp = nsrr(entry, pair);
542 } else if(cistrcmp(pair->attr, "soa") == 0){
543 rp = soarr(entry, pair);
544 addarea(dp, rp, pair);
545 } else if(cistrcmp(pair->attr, "mx") == 0){
546 rp = mxrr(entry, pair);
547 } else if(cistrcmp(pair->attr, "cname") == 0){
548 rp = cnamerr(entry, pair);
549 } else if(cistrcmp(pair->attr, "nullrr") == 0){
550 rp = nullrr(entry, pair);
551 } else if(cistrcmp(pair->attr, "txtrr") == 0){
552 rp = txtrr(entry, pair);
555 if(rp == 0)
556 return;
558 rp->owner = dp;
559 rp->db = 1;
560 t = look(entry, pair, "ttl");
561 if(t)
562 rp->ttl = atoi(t->val);
563 rrattach(rp, 0);
565 static void
566 dbtuple2cache(Ndbtuple *t)
568 Ndbtuple *et, *nt;
569 DN *dp;
571 for(et = t; et; et = et->entry){
572 if(strcmp(et->attr, "dom") == 0){
573 dp = dnlookup(et->val, Cin, 1);
575 /* first same line */
576 for(nt = et->line; nt != et; nt = nt->line){
577 dbpair2cache(dp, t, nt);
578 nt->ptr = 1;
581 /* then rest of entry */
582 for(nt = t; nt; nt = nt->entry){
583 if(nt->ptr == 0)
584 dbpair2cache(dp, t, nt);
585 nt->ptr = 0;
590 static void
591 dbfile2cache(Ndb *db)
593 Ndbtuple *t;
595 if(debug)
596 syslog(0, logfile, "rereading %s", db->file);
597 Bseek(&db->b, 0, 0);
598 while(t = ndbparse(db)){
599 dbtuple2cache(t);
600 ndbfree(t);
603 void
604 db2cache(int doit)
606 Ndb *ndb;
607 Dir *d;
608 ulong youngest, temp;
609 static ulong lastcheck;
610 static ulong lastyoungest;
612 /* no faster than once every 2 minutes */
613 if(now < lastcheck + 2*Min && !doit)
614 return;
616 refresh_areas(owned);
618 lock(&dblock);
620 if(opendatabase() < 0){
621 unlock(&dblock);
622 return;
625 /*
626 * file may be changing as we are reading it, so loop till
627 * mod times are consistent.
629 * we don't use the times in the ndb records because they may
630 * change outside of refreshing our cached knowledge.
631 */
632 for(;;){
633 lastcheck = now;
634 youngest = 0;
635 for(ndb = db; ndb; ndb = ndb->next){
636 /* the dirfstat avoids walking the mount table each time */
637 if((d = dirfstat(Bfildes(&ndb->b))) != nil ||
638 (d = dirstat(ndb->file)) != nil){
639 temp = d->mtime; /* ulong vs int crap */
640 if(temp > youngest)
641 youngest = temp;
642 free(d);
645 if(!doit && youngest == lastyoungest){
646 unlock(&dblock);
647 return;
650 /* forget our area definition */
651 freearea(&owned);
652 freearea(&delegated);
654 /* reopen all the files (to get oldest for time stamp) */
655 for(ndb = db; ndb; ndb = ndb->next)
656 ndbreopen(ndb);
658 if(cachedb){
659 /* mark all db records as timed out */
660 dnagedb();
662 /* read in new entries */
663 for(ndb = db; ndb; ndb = ndb->next)
664 dbfile2cache(ndb);
666 /* mark as authentic anything in our domain */
667 dnauthdb();
669 /* remove old entries */
670 dnageall(1);
671 } else {
672 /* read all the soa's to get database defaults */
673 for(ndb = db; ndb; ndb = ndb->next)
674 dbfile2area(ndb);
677 doit = 0;
678 lastyoungest = youngest;
679 createptrs();
682 unlock(&dblock);
685 extern uchar ipaddr[IPaddrlen];
687 /*
688 * get all my xxx
689 */
690 Ndbtuple*
691 lookupinfo(char *attr)
693 char buf[64];
694 char *a[2];
695 static Ndbtuple *t;
697 snprint(buf, sizeof buf, "%I", ipaddr);
698 a[0] = attr;
700 lock(&dblock);
701 if(opendatabase() < 0){
702 unlock(&dblock);
703 return nil;
705 t = ndbipinfo(db, "ip", buf, a, 1);
706 unlock(&dblock);
707 return t;
710 char *localservers = "local#dns#servers";
711 char *localserverprefix = "local#dns#server";
713 /*
714 * return non-zero is this is a bad delegation
715 */
716 int
717 baddelegation(RR *rp, RR *nsrp, uchar *addr)
719 Ndbtuple *nt;
720 static Ndbtuple *t;
722 if(t == nil)
723 t = lookupinfo("dom");
724 if(t == nil)
725 return 0;
727 for(; rp; rp = rp->next){
728 if(rp->type != Tns)
729 continue;
731 /* see if delegation is looping */
732 if(nsrp)
733 if(rp->owner != nsrp->owner)
734 if(subsume(rp->owner->name, nsrp->owner->name) &&
735 strcmp(nsrp->owner->name, localservers) != 0){
736 syslog(0, logfile, "delegation loop %R -> %R from %I", nsrp, rp, addr);
737 return 1;
740 /* see if delegating to us what we don't own */
741 for(nt = t; nt != nil; nt = nt->entry)
742 if(rp->host && cistrcmp(rp->host->name, nt->val) == 0)
743 break;
744 if(nt != nil && !inmyarea(rp->owner->name)){
745 syslog(0, logfile, "bad delegation %R from %I", rp, addr);
746 return 1;
750 return 0;
753 static void
754 addlocaldnsserver(DN *dp, int class, char *ipaddr, int i)
756 DN *nsdp;
757 RR *rp;
758 char buf[32];
760 /* ns record for name server, make up an impossible name */
761 rp = rralloc(Tns);
762 snprint(buf, sizeof(buf), "%s%d", localserverprefix, i);
763 nsdp = dnlookup(buf, class, 1);
764 rp->host = nsdp;
765 rp->owner = dp;
766 rp->local = 1;
767 rp->db = 1;
768 rp->ttl = 10*Min;
769 rrattach(rp, 1);
771 print("dns %s\n", ipaddr);
772 /* A record */
773 rp = rralloc(Ta);
774 rp->ip = dnlookup(ipaddr, class, 1);
775 rp->owner = nsdp;
776 rp->local = 1;
777 rp->db = 1;
778 rp->ttl = 10*Min;
779 rrattach(rp, 1);
782 /*
783 * return list of dns server addresses to use when
784 * acting just as a resolver.
785 */
786 RR*
787 dnsservers(int class)
789 Ndbtuple *t, *nt;
790 RR *nsrp;
791 DN *dp;
792 char *p;
793 int i, n;
794 char *buf, *args[5];
796 dp = dnlookup(localservers, class, 1);
797 nsrp = rrlookup(dp, Tns, NOneg);
798 if(nsrp != nil)
799 return nsrp;
801 p = getenv("DNSSERVER");
802 if(p != nil){
803 buf = estrdup(p);
804 n = tokenize(buf, args, nelem(args));
805 for(i = 0; i < n; i++)
806 addlocaldnsserver(dp, class, args[i], i);
807 free(buf);
808 } else {
809 t = lookupinfo("@dns");
810 if(t == nil)
811 return nil;
812 i = 0;
813 for(nt = t; nt != nil; nt = nt->entry){
814 addlocaldnsserver(dp, class, nt->val, i);
815 i++;
817 ndbfree(t);
820 return rrlookup(dp, Tns, NOneg);
823 static void
824 addlocaldnsdomain(DN *dp, int class, char *domain)
826 RR *rp;
828 /* A record */
829 rp = rralloc(Tptr);
830 rp->ptr = dnlookup(domain, class, 1);
831 rp->owner = dp;
832 rp->db = 1;
833 rp->ttl = 10*Min;
834 rrattach(rp, 1);
837 /*
838 * return list of domains to use when resolving names without '.'s
839 */
840 RR*
841 domainlist(int class)
843 Ndbtuple *t, *nt;
844 RR *rp;
845 DN *dp;
847 dp = dnlookup("local#dns#domains", class, 1);
848 rp = rrlookup(dp, Tptr, NOneg);
849 if(rp != nil)
850 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);
859 return rrlookup(dp, Tptr, NOneg);
862 char *v4ptrdom = ".in-addr.arpa";
863 char *v6ptrdom = ".ip6.arpa"; /* ip6.int deprecated, rfc 3152 */
865 char *attribs[] = {
866 "ipmask",
868 };
870 /*
871 * create ptrs that are in our areas
872 */
873 static void
874 createptrs(void)
876 int len, dlen, n;
877 Area *s;
878 char *f[40];
879 char buf[Domlen+1];
880 uchar net[IPaddrlen];
881 uchar mask[IPaddrlen];
882 char ipa[48];
883 Ndbtuple *t, *nt;
885 dlen = strlen(v4ptrdom);
886 for(s = owned; s; s = s->next){
887 len = strlen(s->soarr->owner->name);
888 if(len <= dlen)
889 continue;
890 if(cistrcmp(s->soarr->owner->name+len-dlen, v4ptrdom) != 0)
891 continue;
893 /* get mask and net value */
894 strncpy(buf, s->soarr->owner->name, sizeof(buf));
895 buf[sizeof(buf)-1] = 0;
896 n = getfields(buf, f, nelem(f), 0, ".");
897 memset(mask, 0xff, IPaddrlen);
898 ipmove(net, v4prefix);
899 switch(n){
900 case 3: /* /8 */
901 net[IPv4off] = atoi(f[0]);
902 mask[IPv4off+1] = 0;
903 mask[IPv4off+2] = 0;
904 mask[IPv4off+3] = 0;
905 break;
906 case 4: /* /16 */
907 net[IPv4off] = atoi(f[1]);
908 net[IPv4off+1] = atoi(f[0]);
909 mask[IPv4off+2] = 0;
910 mask[IPv4off+3] = 0;
911 break;
912 case 5: /* /24 */
913 net[IPv4off] = atoi(f[2]);
914 net[IPv4off+1] = atoi(f[1]);
915 net[IPv4off+2] = atoi(f[0]);
916 mask[IPv4off+3] = 0;
917 break;
918 case 6: /* rfc2317 */
919 net[IPv4off] = atoi(f[3]);
920 net[IPv4off+1] = atoi(f[2]);
921 net[IPv4off+2] = atoi(f[1]);
922 net[IPv4off+3] = atoi(f[0]);
923 sprint(ipa, "%I", net);
924 t = ndbipinfo(db, "ip", ipa, attribs, 1);
925 if(t == nil) /* could be a reverse with no forward */
926 continue;
927 nt = look(t, t, "ipmask");
928 if(nt == nil){ /* we're confused */
929 ndbfree(t);
930 continue;
932 parseipmask(mask, nt->val);
933 n = 5;
934 break;
935 default:
936 continue;
939 /* go through all domain entries looking for RR's in this network and create ptrs */
940 dnptr(net, mask, s->soarr->owner->name, 6-n, 0);