xref: /plan9/sys/src/cmd/ndb/dnarea.c (revision c361718002866812b3dd559475f979bcacdb2c1e)
1 #include <u.h>
2 #include <libc.h>
3 #include <bio.h>
4 #include <ndb.h>
5 #include <ip.h>
6 #include "dns.h"
7 
8 Area *owned, *delegated;
9 
10 /*
11  *  true if a name is in our area
12  */
13 Area*
inmyarea(char * name)14 inmyarea(char *name)
15 {
16 	int len;
17 	Area *s, *d;
18 
19 	len = strlen(name);
20 	for(s = owned; s; s = s->next){
21 		if(s->len > len)
22 			continue;
23 		if(cistrcmp(s->soarr->owner->name, name + len - s->len) == 0)
24 			if(len == s->len || name[len - s->len - 1] == '.')
25 				break;
26 	}
27 	if(s == nil)
28 		return nil;
29 
30 	/* name is in area `s' */
31 	for(d = delegated; d; d = d->next){
32 		if(d->len > len)
33 			continue;
34 		if(cistrcmp(d->soarr->owner->name, name + len - d->len) == 0)
35 			if(len == d->len || name[len - d->len - 1] == '.')
36 				return nil; /* name is in a delegated subarea */
37 	}
38 
39 	return s;	/* name is in area `s' and not in a delegated subarea */
40 }
41 
42 /*
43  *  our area is the part of the domain tree that
44  *  we serve
45  */
46 void
addarea(DN * dp,RR * rp,Ndbtuple * t)47 addarea(DN *dp, RR *rp, Ndbtuple *t)
48 {
49 	Area *s;
50 	Area **l;
51 
52 	lock(&dnlock);
53 	if(t->val[0])
54 		l = &delegated;
55 	else
56 		l = &owned;
57 
58 	for (s = *l; s != nil; s = s->next)
59 		if (strcmp(dp->name, s->soarr->owner->name) == 0) {
60 			unlock(&dnlock);
61 			return;		/* we've already got one */
62 		}
63 
64 	/*
65 	 *  The area contains a copy of the soa rr that created it.
66 	 *  The owner of the the soa rr should stick around as long
67 	 *  as the area does.
68 	 */
69 	s = emalloc(sizeof(*s));
70 	s->len = strlen(dp->name);
71 	rrcopy(rp, &s->soarr);
72 	s->soarr->owner = dp;
73 	s->soarr->db = 1;
74 	s->soarr->ttl = Hour;
75 	s->neednotify = 1;
76 	s->needrefresh = 0;
77 
78 	if (debug)
79 		dnslog("new area %s %s", dp->name,
80 			l == &delegated? "delegated": "owned");
81 
82 	s->next = *l;
83 	*l = s;
84 	unlock(&dnlock);
85 }
86 
87 void
freearea(Area ** l)88 freearea(Area **l)
89 {
90 	Area *s;
91 
92 	while(s = *l){
93 		*l = s->next;
94 		lock(&dnlock);
95 		rrfree(s->soarr);
96 		memset(s, 0, sizeof *s);	/* cause trouble */
97 		unlock(&dnlock);
98 		free(s);
99 	}
100 }
101 
102 /*
103  * refresh all areas that need it
104  *  this entails running a command 'zonerefreshprogram'.  This could
105  *  copy over databases from elsewhere or just do a zone transfer.
106  */
107 void
refresh_areas(Area * s)108 refresh_areas(Area *s)
109 {
110 	int pid;
111 	Waitmsg *w;
112 
113 	for(; s != nil; s = s->next){
114 		if(!s->needrefresh)
115 			continue;
116 
117 		if(zonerefreshprogram == nil){
118 			s->needrefresh = 0;
119 			continue;
120 		}
121 
122 		pid = fork();
123 		if (pid == -1) {
124 			sleep(1000);	/* don't fork again immediately */
125 			continue;
126 		}
127 		if (pid == 0){
128 			execl(zonerefreshprogram, "zonerefresh",
129 				s->soarr->owner->name, nil);
130 			exits("exec zonerefresh failed");
131 		}
132 		while ((w = wait()) != nil && w->pid != pid)
133 			free(w);
134 		if (w && w->pid == pid)
135 			if(w->msg == nil || *w->msg == '\0')
136 				s->needrefresh = 0;
137 		free(w);
138 	}
139 }
140