]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/ndb/dnarea.c
ndb/dns: fix netmkaddr() race, dnlock consistency, strcpy, cleanups
[plan9front.git] / sys / src / cmd / ndb / dnarea.c
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*
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
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
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
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 }