Blob


1 #include <u.h>
2 #include <libc.h>
3 #include <ip.h>
4 #include <bio.h>
5 #include <ndb.h>
6 #include "dns.h"
8 /* get a notification from another system of a changed zone */
9 void
10 dnnotify(DNSmsg *reqp, DNSmsg *repp, Request *r)
11 {
12 RR *tp;
13 Area *a;
15 USED(r);
16 /* move one question from reqp to repp */
17 memset(repp, 0, sizeof(*repp));
18 tp = reqp->qd;
19 reqp->qd = tp->next;
20 tp->next = 0;
21 repp->qd = tp;
22 repp->id = reqp->id;
23 repp->flags = Fresp | Onotify | Fauth;
25 /* anything to do? */
26 if(zonerefreshprogram == nil)
27 return;
29 /* make sure its the right type */
30 if(repp->qd->type != Tsoa)
31 return;
33 syslog(0, logfile, "notification for %s", repp->qd->owner->name);
35 /* is it something we care about? */
36 a = inmyarea(repp->qd->owner->name);
37 if(a == nil)
38 return;
40 syslog(0, logfile, "serial old %lud new %lud", a->soarr->soa->serial, repp->qd->soa->serial);
42 /* do nothing if it didn't change */
43 if(a->soarr->soa->serial== repp->qd->soa->serial)
44 return;
46 a->needrefresh = 1;
47 }
49 /*
50 * this isn't going to work as a thread!
51 */
53 static void
54 ding(void *u, char *msg)
55 {
56 USED(u);
58 if(strstr(msg, "alarm"))
59 noted(NCONT);
60 else
61 noted(NDFLT);
62 }
64 /* notify a slave that an area has changed. */
65 static void
66 send_notify(char *slave, RR *soa, Request *req)
67 {
68 int i, len, n, reqno, status, fd;
69 uchar obuf[Maxudp+Udphdrsize];
70 uchar ibuf[Maxudp+Udphdrsize];
71 RR *rp;
72 Udphdr *up = (Udphdr*)obuf;
73 char *err;
74 DNSmsg repmsg;
76 /* create the request */
77 reqno = rand();
78 n = mkreq(soa->owner, Cin, obuf, Fauth | Onotify, reqno);
80 /* get an address */
81 if(strcmp(ipattr(slave), "ip") == 0) {
82 parseip(up->raddr, slave);
83 } else {
84 rp = dnresolve(slave, Cin, Ta, req, nil, 0, 1, 1, &status);
85 if(rp == nil)
86 return;
87 parseip(up->raddr, rp->ip->name);
88 rrfree(rp);
89 }
91 fd = udpport();
92 if(fd < 0)
93 return;
95 notify(ding);
97 /* send 3 times or until we get anything back */
98 for(i = 0; i < 3; i++){
99 syslog(0, logfile, "sending %d byte notify to %s/%I.%d about %s", n, slave, up->raddr, nhgets(up->rport), soa->owner->name);
100 if(udpwrite(fd, (Udphdr*)obuf, obuf+Udphdrsize, n) != n)
101 break;
102 alarm(2*1000);
103 len = udpread(fd, (Udphdr*)ibuf, ibuf+Udphdrsize, Maxudp);
104 alarm(0);
105 if(len <= Udphdrsize)
106 continue;
107 err = convM2DNS(&ibuf[Udphdrsize], len, &repmsg);
108 if(err != nil)
109 continue;
110 if(repmsg.id == reqno && (repmsg.flags & Omask) == Onotify)
111 break;
114 close(fd);
117 /* send notifies for any updated areas */
118 static void
119 notify_areas(Area *a, Request *req)
121 Server *s;
123 for(; a != nil; a = a->next){
124 if(!a->neednotify)
125 continue;
127 /* send notifies to all slaves */
128 for(s = a->soarr->soa->slaves; s != nil; s = s->next)
129 send_notify(s->name, a->soarr, req);
130 a->neednotify = 0;
134 /*
135 * process to notify other servers of changes
136 * (also reads in new databases)
137 */
138 void
139 notifyproc(void *v)
141 Request req;
143 USED(v);
145 for(;;){
146 getactivity(&req);
147 notify_areas(owned, &req);
148 putactivity();
149 sleep(60*1000);