8 /* get a notification from another system of a changed zone */
10 dnnotify(DNSmsg *reqp, DNSmsg *repp, Request *)
15 /* move one question from reqp to repp */
16 memset(repp, 0, sizeof(*repp));
22 repp->flags = Fresp | Onotify | Fauth;
25 if(zonerefreshprogram == nil)
28 /* make sure its the right type */
29 if(repp->qd->type != Tsoa)
32 dnslog("notification for %s", repp->qd->owner->name);
34 /* is it something we care about? */
35 a = inmyarea(repp->qd->owner->name);
39 dnslog("serial old %lud new %lud", a->soarr->soa->serial,
40 repp->qd->soa->serial);
42 /* do nothing if it didn't change */
43 if(a->soarr->soa->serial != repp->qd->soa->serial)
48 getips(char *name, uchar *ips, int maxips, Request *req)
56 if(strcmp(ipattr(name), "ip") == 0) {
57 if(parseip(ips, name) != -1 && !myip(ips))
61 list = dnresolve(name, Cin, Ta, req, nil, 0, Recurse, 0, nil);
62 rrcat(&list, dnresolve(name, Cin, Taaaa, req, nil, 0, Recurse, 0, nil));
63 rp = list = randomize(list);
64 while(rp != nil && nips < maxips){
65 uchar *ip = ips + nips*IPaddrlen;
66 if(parseip(ip, rp->ip->name) != -1 && !myip(ip))
74 /* notify a slave that an area has changed. */
76 send_notify(char *slave, RR *soa, Request *req)
78 int i, j, len, n, reqno, fd, nips, send;
79 uchar ips[8*IPaddrlen], ibuf[Maxudp+Udphdrsize], obuf[Maxudp+Udphdrsize];
80 Udphdr *up = (Udphdr*)obuf;
84 nips = getips(slave, ips, sizeof(ips)/IPaddrlen, req);
86 dnslog("no address %s to notify", slave);
90 /* create the request */
92 n = mkreq(soa->owner, Cin, obuf, Fauth | Onotify, reqno);
98 /* send 3 times or until we get anything back */
100 for(i = 0; i < 3; i++, freeanswers(&repmsg)){
101 memset(&repmsg, 0, sizeof repmsg);
103 for(j = 0; j < nips; j++){
104 ipmove(up->raddr, ips + j*IPaddrlen);
105 if(write(fd, obuf, n) == n){
106 dnslog("send %d bytes notify to %s/%I.%d about %s", n, slave,
107 up->raddr, nhgets(up->rport), soa->owner->name);
114 len = read(fd, ibuf, sizeof ibuf);
116 if(len <= Udphdrsize)
118 err = convM2DNS(&ibuf[Udphdrsize], len, &repmsg, nil);
123 if(repmsg.id == reqno && (repmsg.flags & Omask) == Onotify){
124 freeanswers(&repmsg);
131 /* send notifies for any updated areas */
133 notify_areas(Area *a, Request *req)
137 for(; a != nil; a = a->next){
141 /* send notifies to all slaves */
142 for(s = a->soarr->soa->slaves; s != nil; s = s->next)
143 send_notify(s->name, a->soarr, req);
149 * process to notify other servers of changes
150 * (also reads in new databases)
157 switch(rfork(RFPROC|RFNOTEG|RFMEM|RFNOWAIT)){
166 procsetname("notify slaves");
167 memset(&req, 0, sizeof req);
168 req.isslave = 1; /* don't fork off subprocesses */
171 getactivity(&req, 0);
172 notify_areas(owned, &req);