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