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 [Ta] 1,
27 [Tns] 1,
28 [Tsoa] 1,
29 [Tmx] 1,
30 [Tptr] 1,
31 [Tcname] 1,
32 [Tnull] 1,
33 [Ttxt] 1,
34 };
36 static void
37 nstrcpy(char *to, char *from, int len)
38 {
39 strncpy(to, from, len);
40 to[len-1] = 0;
41 }
43 int
44 opendatabase(void)
45 {
46 char buf[256];
47 Ndb *xdb;
49 if(db == nil){
50 snprint(buf, sizeof(buf), "%s/ndb", mntpt);
51 xdb = ndbopen(dbfile);
52 if(xdb != nil)
53 xdb->nohash = 1;
54 db = ndbcat(ndbopen(buf), xdb);
55 }
56 if(db == nil)
57 return -1;
58 else
59 return 0;
60 }
62 /*
63 * lookup an RR in the network database, look for matches
64 * against both the domain name and the wildcarded domain name.
65 *
66 * the lock makes sure only one process can be accessing the data
67 * base at a time. This is important since there's a lot of
68 * shared state there.
69 *
70 * e.g. for x.research.bell-labs.com, first look for a match against
71 * the x.research.bell-labs.com. If nothing matches, try *.research.bell-labs.com.
72 */
73 RR*
74 dblookup(char *name, int class, int type, int auth, int ttl)
75 {
76 RR *rp, *tp;
77 char buf[256];
78 char *wild, *cp;
79 DN *dp, *ndp;
80 int err;
81 static int parallel;
82 static int parfd[2];
83 static char token[1];
85 /* so far only internet lookups are implemented */
86 if(class != Cin)
87 return 0;
89 err = Rname;
91 if(type == Tall){
92 rp = 0;
93 for (type = Ta; type < Tall; type++)
94 if(implemented[type])
95 rrcat(&rp, dblookup(name, class, type, auth, ttl));
96 return rp;
97 }
99 lock(&dblock);
100 dp = dnlookup(name, class, 1);
101 if(opendatabase() < 0)
102 goto out;
103 if(dp->rr)
104 err = 0;
106 /* first try the given name */
107 rp = 0;
108 if(cachedb)
109 rp = rrlookup(dp, type, NOneg);
110 else
111 rp = dblookup1(name, type, auth, ttl);
112 if(rp)
113 goto out;
115 /* try lower case version */
116 for(cp = name; *cp; cp++)
117 *cp = tolower(*cp);
118 if(cachedb)
119 rp = rrlookup(dp, type, NOneg);
120 else
121 rp = dblookup1(name, type, auth, ttl);
122 if(rp)
123 goto out;
125 /* walk the domain name trying the wildcard '*' at each position */
126 for(wild = strchr(name, '.'); wild; wild = strchr(wild+1, '.')){
127 snprint(buf, sizeof(buf), "*%s", wild);
128 ndp = dnlookup(buf, class, 1);
129 if(ndp->rr)
130 err = 0;
131 if(cachedb)
132 rp = rrlookup(ndp, type, NOneg);
133 else
134 rp = dblookup1(buf, type, auth, ttl);
135 if(rp)
136 break;
138 out:
139 /* add owner to uncached records */
140 if(rp){
141 for(tp = rp; tp; tp = tp->next)
142 tp->owner = dp;
143 } else {
144 /* don't call it non-existent if it's not ours */
145 if(err == Rname && !inmyarea(name))
146 err = Rserver;
147 dp->nonexistent = err;
150 unlock(&dblock);
151 return rp;
154 /*
155 * lookup an RR in the network database
156 */
157 static RR*
158 dblookup1(char *name, int type, int auth, int ttl)
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;
169 dp = 0;
170 switch(type){
171 case Tptr:
172 attr = "ptr";
173 f = ptrrr;
174 break;
175 case Ta:
176 attr = "ip";
177 f = addrrr;
178 break;
179 case Tnull:
180 attr = "nullrr";
181 f = nullrr;
182 break;
183 case Tns:
184 attr = "ns";
185 f = nsrr;
186 break;
187 case Tsoa:
188 attr = "soa";
189 f = soarr;
190 break;
191 case Tmx:
192 attr = "mx";
193 f = mxrr;
194 break;
195 case Tcname:
196 attr = "cname";
197 f = cnamerr;
198 break;
199 case Taxfr:
200 case Tixfr:
201 return doaxfr(db, name);
202 default:
203 return nil;
206 /*
207 * find a matching entry in the database
208 */
209 free(ndbgetvalue(db, &s, "dom", name, attr, &t));
211 /*
212 * hack for local names
213 */
214 if(t == 0 && strchr(name, '.') == 0)
215 free(ndbgetvalue(db, &s, "sys", name, attr, &t));
216 if(t == 0)
217 return nil;
219 /* search whole entry for default domain name */
220 strncpy(dname, name, sizeof dname);
221 for(nt = t; nt; nt = nt->entry)
222 if(strcmp(nt->attr, "dom") == 0){
223 nstrcpy(dname, nt->val, sizeof dname);
224 break;
227 /* ttl is maximum of soa minttl and entry's ttl ala rfc883 */
228 nt = look(t, s.t, "ttl");
229 if(nt){
230 x = atoi(nt->val);
231 if(x > ttl)
232 ttl = x;
235 /* default ttl is one day */
236 if(ttl < 0)
237 ttl = DEFTTL;
239 /*
240 * The database has 2 levels of precedence; line and entry.
241 * Pairs on the same line bind tighter than pairs in the
242 * same entry, so we search the line first.
243 */
244 found = 0;
245 list = 0;
246 l = &list;
247 for(nt = s.t;; ){
248 if(found == 0 && strcmp(nt->attr, "dom") == 0){
249 nstrcpy(dname, nt->val, sizeof dname);
250 found = 1;
252 if(cistrcmp(attr, nt->attr) == 0){
253 rp = (*f)(t, nt);
254 rp->auth = auth;
255 rp->db = 1;
256 if(ttl)
257 rp->ttl = ttl;
258 if(dp == 0)
259 dp = dnlookup(dname, Cin, 1);
260 rp->owner = dp;
261 *l = rp;
262 l = &rp->next;
263 nt->ptr = 1;
265 nt = nt->line;
266 if(nt == s.t)
267 break;
270 /* search whole entry */
271 for(nt = t; nt; nt = nt->entry)
272 if(nt->ptr == 0 && cistrcmp(attr, nt->attr) == 0){
273 rp = (*f)(t, nt);
274 rp->db = 1;
275 if(ttl)
276 rp->ttl = ttl;
277 rp->auth = auth;
278 if(dp == 0)
279 dp = dnlookup(dname, Cin, 1);
280 rp->owner = dp;
281 *l = rp;
282 l = &rp->next;
284 ndbfree(t);
286 return list;
289 /*
290 * make various types of resource records from a database entry
291 */
292 static RR*
293 addrrr(Ndbtuple *entry, Ndbtuple *pair)
295 RR *rp;
296 uchar addr[IPaddrlen];
298 USED(entry);
299 parseip(addr, pair->val);
300 if(isv4(addr))
301 rp = rralloc(Ta);
302 else
303 rp = rralloc(Taaaa);
304 rp->ip = dnlookup(pair->val, Cin, 1);
305 return rp;
307 static RR*
308 nullrr(Ndbtuple *entry, Ndbtuple *pair)
310 RR *rp;
312 USED(entry);
313 rp = rralloc(Tnull);
314 rp->null->data = (uchar*)estrdup(pair->val);
315 rp->null->dlen = strlen((char*)rp->null->data);
316 return rp;
318 /*
319 * txt rr strings are at most 255 bytes long. one
320 * can represent longer strings by multiple concatenated
321 * <= 255 byte ones.
322 */
323 static RR*
324 txtrr(Ndbtuple *entry, Ndbtuple *pair)
326 RR *rp;
327 Txt *t, **l;
328 int i, len, sofar;
330 USED(entry);
331 rp = rralloc(Ttxt);
332 l = &rp->txt;
333 rp->txt = nil;
334 len = strlen(pair->val);
335 sofar = 0;
336 while(len > sofar){
337 t = emalloc(sizeof(*t));
338 t->next = nil;
340 i = len-sofar;
341 if(i > 255)
342 i = 255;
344 t->p = emalloc(i+1);
345 memmove(t->p, pair->val+sofar, i);
346 t->p[i] = 0;
347 sofar += i;
349 *l = t;
350 l = &t->next;
352 return rp;
354 static RR*
355 cnamerr(Ndbtuple *entry, Ndbtuple *pair)
357 RR *rp;
359 USED(entry);
360 rp = rralloc(Tcname);
361 rp->host = dnlookup(pair->val, Cin, 1);
362 return rp;
364 static RR*
365 mxrr(Ndbtuple *entry, Ndbtuple *pair)
367 RR * rp;
369 rp = rralloc(Tmx);
370 rp->host = dnlookup(pair->val, Cin, 1);
371 pair = look(entry, pair, "pref");
372 if(pair)
373 rp->pref = atoi(pair->val);
374 else
375 rp->pref = 1;
376 return rp;
378 static RR*
379 nsrr(Ndbtuple *entry, Ndbtuple *pair)
381 RR *rp;
382 Ndbtuple *t;
384 rp = rralloc(Tns);
385 rp->host = dnlookup(pair->val, Cin, 1);
386 t = look(entry, pair, "soa");
387 if(t && t->val[0] == 0)
388 rp->local = 1;
389 return rp;
391 static RR*
392 ptrrr(Ndbtuple *entry, Ndbtuple *pair)
394 RR *rp;
396 USED(entry);
397 rp = rralloc(Tns);
398 rp->ptr = dnlookup(pair->val, Cin, 1);
399 return rp;
401 static RR*
402 soarr(Ndbtuple *entry, Ndbtuple *pair)
404 RR *rp;
405 Ndbtuple *ns, *mb, *t;
406 char mailbox[Domlen];
407 Ndb *ndb;
408 char *p;
410 rp = rralloc(Tsoa);
411 rp->soa->serial = 1;
412 for(ndb = db; ndb; ndb = ndb->next)
413 if(ndb->mtime > rp->soa->serial)
414 rp->soa->serial = ndb->mtime;
415 rp->soa->refresh = Day;
416 rp->soa->retry = Hour;
417 rp->soa->expire = Day;
418 rp->soa->minttl = Day;
419 t = look(entry, pair, "ttl");
420 if(t)
421 rp->soa->minttl = atoi(t->val);
422 t = look(entry, pair, "refresh");
423 if(t)
424 rp->soa->refresh = atoi(t->val);
425 t = look(entry, pair, "serial");
426 if(t)
427 rp->soa->serial = strtoul(t->val, 0, 10);
429 ns = look(entry, pair, "ns");
430 if(ns == 0)
431 ns = look(entry, pair, "dom");
432 rp->host = dnlookup(ns->val, Cin, 1);
434 /* accept all of:
435 * mbox=person
436 * mbox=person@machine.dom
437 * mbox=person.machine.dom
438 */
439 mb = look(entry, pair, "mbox");
440 if(mb == nil)
441 mb = look(entry, pair, "mb");
442 if(mb){
443 if(strchr(mb->val, '.')) {
444 p = strchr(mb->val, '@');
445 if(p != nil)
446 *p = '.';
447 rp->rmb = dnlookup(mb->val, Cin, 1);
448 } else {
449 snprint(mailbox, sizeof(mailbox), "%s.%s",
450 mb->val, ns->val);
451 rp->rmb = dnlookup(mailbox, Cin, 1);
453 } else {
454 snprint(mailbox, sizeof(mailbox), "postmaster.%s",
455 ns->val);
456 rp->rmb = dnlookup(mailbox, Cin, 1);
459 /* hang dns slaves off of the soa. this is
460 * for managing the area.
461 */
462 for(t = entry; t != nil; t = t->entry)
463 if(strcmp(t->attr, "dnsslave") == 0)
464 addserver(&rp->soa->slaves, t->val);
466 return rp;
469 /*
470 * Look for a pair with the given attribute. look first on the same line,
471 * then in the whole entry.
472 */
473 static Ndbtuple*
474 look(Ndbtuple *entry, Ndbtuple *line, char *attr)
476 Ndbtuple *nt;
478 /* first look on same line (closer binding) */
479 for(nt = line;;){
480 if(cistrcmp(attr, nt->attr) == 0)
481 return nt;
482 nt = nt->line;
483 if(nt == line)
484 break;
486 /* search whole tuple */
487 for(nt = entry; nt; nt = nt->entry)
488 if(cistrcmp(attr, nt->attr) == 0)
489 return nt;
490 return 0;
493 static RR**
494 linkrr(RR *rp, DN *dp, RR **l)
496 rp->owner = dp;
497 rp->auth = 1;
498 rp->db = 1;
499 *l = rp;
500 return &rp->next;
503 /* these are answered specially by the tcp version */
504 static RR*
505 doaxfr(Ndb *db, char *name)
507 USED(db);
508 USED(name);
509 return 0;
513 /*
514 * read the all the soa's from the database to determine area's.
515 * this is only used when we're not caching the database.
516 */
517 static void
518 dbfile2area(Ndb *db)
520 Ndbtuple *t;
522 if(debug)
523 syslog(0, logfile, "rereading %s", db->file);
524 Bseek(&db->b, 0, 0);
525 while(t = ndbparse(db)){
526 ndbfree(t);
530 /*
531 * read the database into the cache
532 */
533 static void
534 dbpair2cache(DN *dp, Ndbtuple *entry, Ndbtuple *pair)
536 RR *rp;
537 Ndbtuple *t;
538 static ulong ord;
540 rp = 0;
541 if(cistrcmp(pair->attr, "ip") == 0){
542 dp->ordinal = ord++;
543 rp = addrrr(entry, pair);
544 } else if(cistrcmp(pair->attr, "ns") == 0){
545 rp = nsrr(entry, pair);
546 } else if(cistrcmp(pair->attr, "soa") == 0){
547 rp = soarr(entry, pair);
548 addarea(dp, rp, pair);
549 } else if(cistrcmp(pair->attr, "mx") == 0){
550 rp = mxrr(entry, pair);
551 } else if(cistrcmp(pair->attr, "cname") == 0){
552 rp = cnamerr(entry, pair);
553 } else if(cistrcmp(pair->attr, "nullrr") == 0){
554 rp = nullrr(entry, pair);
555 } else if(cistrcmp(pair->attr, "txtrr") == 0){
556 rp = txtrr(entry, pair);
559 if(rp == 0)
560 return;
562 rp->owner = dp;
563 rp->db = 1;
564 t = look(entry, pair, "ttl");
565 if(t)
566 rp->ttl = atoi(t->val);
567 rrattach(rp, 0);
569 static void
570 dbtuple2cache(Ndbtuple *t)
572 Ndbtuple *et, *nt;
573 DN *dp;
575 for(et = t; et; et = et->entry){
576 if(strcmp(et->attr, "dom") == 0){
577 dp = dnlookup(et->val, Cin, 1);
579 /* first same line */
580 for(nt = et->line; nt != et; nt = nt->line){
581 dbpair2cache(dp, t, nt);
582 nt->ptr = 1;
585 /* then rest of entry */
586 for(nt = t; nt; nt = nt->entry){
587 if(nt->ptr == 0)
588 dbpair2cache(dp, t, nt);
589 nt->ptr = 0;
594 static void
595 dbfile2cache(Ndb *db)
597 Ndbtuple *t;
599 if(debug)
600 syslog(0, logfile, "rereading %s", db->file);
601 Bseek(&db->b, 0, 0);
602 while(t = ndbparse(db)){
603 dbtuple2cache(t);
604 ndbfree(t);
607 void
608 db2cache(int doit)
610 Ndb *ndb;
611 Dir *d;
612 ulong youngest, temp;
613 static ulong lastcheck;
614 static ulong lastyoungest;
616 /* no faster than once every 2 minutes */
617 if(now < lastcheck + 2*Min && !doit)
618 return;
620 refresh_areas(owned);
622 lock(&dblock);
624 if(opendatabase() < 0){
625 unlock(&dblock);
626 return;
629 /*
630 * file may be changing as we are reading it, so loop till
631 * mod times are consistent.
633 * we don't use the times in the ndb records because they may
634 * change outside of refreshing our cached knowledge.
635 */
636 for(;;){
637 lastcheck = now;
638 youngest = 0;
639 for(ndb = db; ndb; ndb = ndb->next){
640 /* the dirfstat avoids walking the mount table each time */
641 if((d = dirfstat(Bfildes(&ndb->b))) != nil ||
642 (d = dirstat(ndb->file)) != nil){
643 temp = d->mtime; /* ulong vs int crap */
644 if(temp > youngest)
645 youngest = temp;
646 free(d);
649 if(!doit && youngest == lastyoungest){
650 unlock(&dblock);
651 return;
654 /* forget our area definition */
655 freearea(&owned);
656 freearea(&delegated);
658 /* reopen all the files (to get oldest for time stamp) */
659 for(ndb = db; ndb; ndb = ndb->next)
660 ndbreopen(ndb);
662 if(cachedb){
663 /* mark all db records as timed out */
664 dnagedb();
666 /* read in new entries */
667 for(ndb = db; ndb; ndb = ndb->next)
668 dbfile2cache(ndb);
670 /* mark as authentic anything in our domain */
671 dnauthdb();
673 /* remove old entries */
674 dnageall(1);
675 } else {
676 /* read all the soa's to get database defaults */
677 for(ndb = db; ndb; ndb = ndb->next)
678 dbfile2area(ndb);
681 doit = 0;
682 lastyoungest = youngest;
683 createptrs();
686 unlock(&dblock);
689 extern uchar ipaddr[IPaddrlen];
691 /*
692 * get all my xxx
693 */
694 Ndbtuple*
695 lookupinfo(char *attr)
697 char buf[64];
698 char *a[2];
699 static Ndbtuple *t;
701 snprint(buf, sizeof buf, "%I", ipaddr);
702 a[0] = attr;
704 lock(&dblock);
705 if(opendatabase() < 0){
706 unlock(&dblock);
707 return nil;
709 t = ndbipinfo(db, "ip", buf, a, 1);
710 unlock(&dblock);
711 return t;
714 char *localservers = "local#dns#servers";
715 char *localserverprefix = "local#dns#server";
717 /*
718 * return non-zero is this is a bad delegation
719 */
720 int
721 baddelegation(RR *rp, RR *nsrp, uchar *addr)
723 Ndbtuple *nt;
724 static Ndbtuple *t;
726 if(t == nil)
727 t = lookupinfo("dom");
728 if(t == nil)
729 return 0;
731 for(; rp; rp = rp->next){
732 if(rp->type != Tns)
733 continue;
735 /* see if delegation is looping */
736 if(nsrp)
737 if(rp->owner != nsrp->owner)
738 if(subsume(rp->owner->name, nsrp->owner->name) &&
739 strcmp(nsrp->owner->name, localservers) != 0){
740 syslog(0, logfile, "delegation loop %R -> %R from %I", nsrp, rp, addr);
741 return 1;
744 /* see if delegating to us what we don't own */
745 for(nt = t; nt != nil; nt = nt->entry)
746 if(rp->host && cistrcmp(rp->host->name, nt->val) == 0)
747 break;
748 if(nt != nil && !inmyarea(rp->owner->name)){
749 syslog(0, logfile, "bad delegation %R from %I", rp, addr);
750 return 1;
754 return 0;
757 static void
758 addlocaldnsserver(DN *dp, int class, char *ipaddr, int i)
760 DN *nsdp;
761 RR *rp;
762 char buf[32];
764 /* ns record for name server, make up an impossible name */
765 rp = rralloc(Tns);
766 snprint(buf, sizeof(buf), "%s%d", localserverprefix, i);
767 nsdp = dnlookup(buf, class, 1);
768 rp->host = nsdp;
769 rp->owner = dp;
770 rp->local = 1;
771 rp->db = 1;
772 rp->ttl = 10*Min;
773 rrattach(rp, 1);
775 print("dns %s\n", ipaddr);
776 /* A record */
777 rp = rralloc(Ta);
778 rp->ip = dnlookup(ipaddr, class, 1);
779 rp->owner = nsdp;
780 rp->local = 1;
781 rp->db = 1;
782 rp->ttl = 10*Min;
783 rrattach(rp, 1);
786 /*
787 * return list of dns server addresses to use when
788 * acting just as a resolver.
789 */
790 RR*
791 dnsservers(int class)
793 Ndbtuple *t, *nt;
794 RR *nsrp;
795 DN *dp;
796 char *p;
797 int i, n;
798 char *buf, *args[5];
800 dp = dnlookup(localservers, class, 1);
801 nsrp = rrlookup(dp, Tns, NOneg);
802 if(nsrp != nil)
803 return nsrp;
805 p = getenv("DNSSERVER");
806 if(p != nil){
807 buf = estrdup(p);
808 n = tokenize(buf, args, nelem(args));
809 for(i = 0; i < n; i++)
810 addlocaldnsserver(dp, class, args[i], i);
811 free(buf);
812 } else {
813 t = lookupinfo("@dns");
814 if(t == nil)
815 return nil;
816 i = 0;
817 for(nt = t; nt != nil; nt = nt->entry){
818 addlocaldnsserver(dp, class, nt->val, i);
819 i++;
821 ndbfree(t);
824 return rrlookup(dp, Tns, NOneg);
827 static void
828 addlocaldnsdomain(DN *dp, int class, char *domain)
830 RR *rp;
832 /* A record */
833 rp = rralloc(Tptr);
834 rp->ptr = dnlookup(domain, class, 1);
835 rp->owner = dp;
836 rp->db = 1;
837 rp->ttl = 10*Min;
838 rrattach(rp, 1);
841 /*
842 * return list of domains to use when resolving names without '.'s
843 */
844 RR*
845 domainlist(int class)
847 Ndbtuple *t, *nt;
848 RR *rp;
849 DN *dp;
851 dp = dnlookup("local#dns#domains", class, 1);
852 rp = rrlookup(dp, Tptr, NOneg);
853 if(rp != nil)
854 return rp;
856 t = lookupinfo("dnsdomain");
857 if(t == nil)
858 return nil;
859 for(nt = t; nt != nil; nt = nt->entry)
860 addlocaldnsdomain(dp, class, nt->val);
861 ndbfree(t);
863 return rrlookup(dp, Tptr, NOneg);
866 char *v4ptrdom = ".in-addr.arpa";
867 char *v6ptrdom = ".ip6.arpa"; /* ip6.int deprecated, rfc 3152 */
869 char *attribs[] = {
870 "ipmask",
872 };
874 /*
875 * create ptrs that are in our areas
876 */
877 static void
878 createptrs(void)
880 int len, dlen, n;
881 Area *s;
882 char *f[40];
883 char buf[Domlen+1];
884 uchar net[IPaddrlen];
885 uchar mask[IPaddrlen];
886 char ipa[48];
887 Ndbtuple *t, *nt;
889 dlen = strlen(v4ptrdom);
890 for(s = owned; s; s = s->next){
891 len = strlen(s->soarr->owner->name);
892 if(len <= dlen)
893 continue;
894 if(cistrcmp(s->soarr->owner->name+len-dlen, v4ptrdom) != 0)
895 continue;
897 /* get mask and net value */
898 strncpy(buf, s->soarr->owner->name, sizeof(buf));
899 buf[sizeof(buf)-1] = 0;
900 n = getfields(buf, f, nelem(f), 0, ".");
901 memset(mask, 0xff, IPaddrlen);
902 ipmove(net, v4prefix);
903 switch(n){
904 case 3: /* /8 */
905 net[IPv4off] = atoi(f[0]);
906 mask[IPv4off+1] = 0;
907 mask[IPv4off+2] = 0;
908 mask[IPv4off+3] = 0;
909 break;
910 case 4: /* /16 */
911 net[IPv4off] = atoi(f[1]);
912 net[IPv4off+1] = atoi(f[0]);
913 mask[IPv4off+2] = 0;
914 mask[IPv4off+3] = 0;
915 break;
916 case 5: /* /24 */
917 net[IPv4off] = atoi(f[2]);
918 net[IPv4off+1] = atoi(f[1]);
919 net[IPv4off+2] = atoi(f[0]);
920 mask[IPv4off+3] = 0;
921 break;
922 case 6: /* rfc2317 */
923 net[IPv4off] = atoi(f[3]);
924 net[IPv4off+1] = atoi(f[2]);
925 net[IPv4off+2] = atoi(f[1]);
926 net[IPv4off+3] = atoi(f[0]);
927 sprint(ipa, "%I", net);
928 t = ndbipinfo(db, "ip", ipa, attribs, 1);
929 if(t == nil) /* could be a reverse with no forward */
930 continue;
931 nt = look(t, t, "ipmask");
932 if(nt == nil){ /* we're confused */
933 ndbfree(t);
934 continue;
936 parseipmask(mask, nt->val);
937 n = 5;
938 break;
939 default:
940 continue;
943 /* go through all domain entries looking for RR's in this network and create ptrs */
944 dnptr(net, mask, s->soarr->owner->name, 6-n, 0);