1dc5a79c1SDavid du Colombier #include <u.h> 2dc5a79c1SDavid du Colombier #include <libc.h> 3dc5a79c1SDavid du Colombier #include <ip.h> 4dc5a79c1SDavid du Colombier #include <bio.h> 5dc5a79c1SDavid du Colombier #include <ndb.h> 6dc5a79c1SDavid du Colombier #include "dns.h" 7dc5a79c1SDavid du Colombier 8dc5a79c1SDavid du Colombier /* get a notification from another system of a changed zone */ 9dc5a79c1SDavid du Colombier void 10dc5a79c1SDavid du Colombier dnnotify(DNSmsg *reqp, DNSmsg *repp, Request *) 11dc5a79c1SDavid du Colombier { 12dc5a79c1SDavid du Colombier RR *tp; 13dc5a79c1SDavid du Colombier Area *a; 14dc5a79c1SDavid du Colombier 15dc5a79c1SDavid du Colombier /* move one question from reqp to repp */ 16dc5a79c1SDavid du Colombier memset(repp, 0, sizeof(*repp)); 17dc5a79c1SDavid du Colombier tp = reqp->qd; 18dc5a79c1SDavid du Colombier reqp->qd = tp->next; 19dc5a79c1SDavid du Colombier tp->next = 0; 20dc5a79c1SDavid du Colombier repp->qd = tp; 21dc5a79c1SDavid du Colombier repp->id = reqp->id; 22dc5a79c1SDavid du Colombier repp->flags = Fresp | Onotify | Fauth; 23dc5a79c1SDavid du Colombier 24dc5a79c1SDavid du Colombier /* anything to do? */ 25dc5a79c1SDavid du Colombier if(zonerefreshprogram == nil) 26dc5a79c1SDavid du Colombier return; 27dc5a79c1SDavid du Colombier 28dc5a79c1SDavid du Colombier /* make sure its the right type */ 29dc5a79c1SDavid du Colombier if(repp->qd->type != Tsoa) 30dc5a79c1SDavid du Colombier return; 31dc5a79c1SDavid du Colombier 324f8f669cSDavid du Colombier dnslog("notification for %s", repp->qd->owner->name); 33dc5a79c1SDavid du Colombier 34dc5a79c1SDavid du Colombier /* is it something we care about? */ 35dc5a79c1SDavid du Colombier a = inmyarea(repp->qd->owner->name); 36dc5a79c1SDavid du Colombier if(a == nil) 37dc5a79c1SDavid du Colombier return; 38dc5a79c1SDavid du Colombier 39f46c709fSDavid du Colombier dnslog("serial old %lud new %lud", a->soarr->soa->serial, 40f46c709fSDavid du Colombier repp->qd->soa->serial); 41dc5a79c1SDavid du Colombier 42dc5a79c1SDavid du Colombier /* do nothing if it didn't change */ 434f8f669cSDavid du Colombier if(a->soarr->soa->serial != repp->qd->soa->serial) 44dc5a79c1SDavid du Colombier a->needrefresh = 1; 45dc5a79c1SDavid du Colombier } 46dc5a79c1SDavid du Colombier 47dc5a79c1SDavid du Colombier /* notify a slave that an area has changed. */ 48dc5a79c1SDavid du Colombier static void 49dc5a79c1SDavid du Colombier send_notify(char *slave, RR *soa, Request *req) 50dc5a79c1SDavid du Colombier { 51dc5a79c1SDavid du Colombier int i, len, n, reqno, status, fd; 524f8f669cSDavid du Colombier char *err; 53f27a9a5aSDavid du Colombier uchar ibuf[Maxudp+Udphdrsize], obuf[Maxudp+Udphdrsize]; 54dc5a79c1SDavid du Colombier RR *rp; 55f27a9a5aSDavid du Colombier Udphdr *up = (Udphdr*)obuf; 56dc5a79c1SDavid du Colombier DNSmsg repmsg; 57dc5a79c1SDavid du Colombier 58dc5a79c1SDavid du Colombier /* create the request */ 59dc5a79c1SDavid du Colombier reqno = rand(); 60dc5a79c1SDavid du Colombier n = mkreq(soa->owner, Cin, obuf, Fauth | Onotify, reqno); 61dc5a79c1SDavid du Colombier 62dc5a79c1SDavid du Colombier /* get an address */ 63ea58ad6fSDavid du Colombier if(strcmp(ipattr(slave), "ip") == 0) { 64ea58ad6fSDavid du Colombier if (parseip(up->raddr, slave) == -1) 65ea58ad6fSDavid du Colombier dnslog("bad address %s to notify", slave); 66ea58ad6fSDavid du Colombier } else { 67dc5a79c1SDavid du Colombier rp = dnresolve(slave, Cin, Ta, req, nil, 0, 1, 1, &status); 68dc5a79c1SDavid du Colombier if(rp == nil) 69*d9924332SDavid du Colombier rp = dnresolve(slave, Cin, Taaaa, req, nil, 0, 1, 1, &status); 70*d9924332SDavid du Colombier if(rp == nil) 71dc5a79c1SDavid du Colombier return; 72dc5a79c1SDavid du Colombier parseip(up->raddr, rp->ip->name); 730319257bSDavid du Colombier rrfreelist(rp); /* was rrfree */ 74dc5a79c1SDavid du Colombier } 75dc5a79c1SDavid du Colombier 764f8f669cSDavid du Colombier fd = udpport(nil); 77dc5a79c1SDavid du Colombier if(fd < 0) 78dc5a79c1SDavid du Colombier return; 79dc5a79c1SDavid du Colombier 80dc5a79c1SDavid du Colombier /* send 3 times or until we get anything back */ 81f27a9a5aSDavid du Colombier n += Udphdrsize; 82f46c709fSDavid du Colombier for(i = 0; i < 3; i++, freeanswers(&repmsg)){ 8376783259SDavid du Colombier dnslog("sending %d byte notify to %s/%I.%d about %s", n, slave, 8476783259SDavid du Colombier up->raddr, nhgets(up->rport), soa->owner->name); 85f46c709fSDavid du Colombier memset(&repmsg, 0, sizeof repmsg); 86dc5a79c1SDavid du Colombier if(write(fd, obuf, n) != n) 87dc5a79c1SDavid du Colombier break; 88dc5a79c1SDavid du Colombier alarm(2*1000); 89dc5a79c1SDavid du Colombier len = read(fd, ibuf, sizeof ibuf); 90dc5a79c1SDavid du Colombier alarm(0); 91f27a9a5aSDavid du Colombier if(len <= Udphdrsize) 92dc5a79c1SDavid du Colombier continue; 93f27a9a5aSDavid du Colombier err = convM2DNS(&ibuf[Udphdrsize], len, &repmsg, nil); 94186d659cSDavid du Colombier if(err != nil) { 95186d659cSDavid du Colombier free(err); 96dc5a79c1SDavid du Colombier continue; 97186d659cSDavid du Colombier } 98dc5a79c1SDavid du Colombier if(repmsg.id == reqno && (repmsg.flags & Omask) == Onotify) 99dc5a79c1SDavid du Colombier break; 100dc5a79c1SDavid du Colombier } 101adb31a62SDavid du Colombier if (i < 3) 102f46c709fSDavid du Colombier freeanswers(&repmsg); 103dc5a79c1SDavid du Colombier close(fd); 104dc5a79c1SDavid du Colombier } 105dc5a79c1SDavid du Colombier 106dc5a79c1SDavid du Colombier /* send notifies for any updated areas */ 107dc5a79c1SDavid du Colombier static void 108dc5a79c1SDavid du Colombier notify_areas(Area *a, Request *req) 109dc5a79c1SDavid du Colombier { 110dc5a79c1SDavid du Colombier Server *s; 111dc5a79c1SDavid du Colombier 112dc5a79c1SDavid du Colombier for(; a != nil; a = a->next){ 113dc5a79c1SDavid du Colombier if(!a->neednotify) 114dc5a79c1SDavid du Colombier continue; 115dc5a79c1SDavid du Colombier 116dc5a79c1SDavid du Colombier /* send notifies to all slaves */ 117dc5a79c1SDavid du Colombier for(s = a->soarr->soa->slaves; s != nil; s = s->next) 118dc5a79c1SDavid du Colombier send_notify(s->name, a->soarr, req); 119dc5a79c1SDavid du Colombier a->neednotify = 0; 120dc5a79c1SDavid du Colombier } 121dc5a79c1SDavid du Colombier } 122dc5a79c1SDavid du Colombier 123dc5a79c1SDavid du Colombier /* 124dc5a79c1SDavid du Colombier * process to notify other servers of changes 125dc5a79c1SDavid du Colombier * (also reads in new databases) 126dc5a79c1SDavid du Colombier */ 127dc5a79c1SDavid du Colombier void 128dc5a79c1SDavid du Colombier notifyproc(void) 129dc5a79c1SDavid du Colombier { 130dc5a79c1SDavid du Colombier Request req; 131dc5a79c1SDavid du Colombier 132dc5a79c1SDavid du Colombier switch(rfork(RFPROC|RFNOTEG|RFMEM|RFNOWAIT)){ 133dc5a79c1SDavid du Colombier case -1: 134dc5a79c1SDavid du Colombier return; 135dc5a79c1SDavid du Colombier case 0: 136dc5a79c1SDavid du Colombier break; 137dc5a79c1SDavid du Colombier default: 138dc5a79c1SDavid du Colombier return; 139dc5a79c1SDavid du Colombier } 140dc5a79c1SDavid du Colombier 1414f8f669cSDavid du Colombier procsetname("notify slaves"); 1424f8f669cSDavid du Colombier memset(&req, 0, sizeof req); 1434f8f669cSDavid du Colombier req.isslave = 1; /* don't fork off subprocesses */ 144dc5a79c1SDavid du Colombier 145dc5a79c1SDavid du Colombier for(;;){ 146b4b9fc2fSDavid du Colombier getactivity(&req, 0); 147dc5a79c1SDavid du Colombier notify_areas(owned, &req); 148b4b9fc2fSDavid du Colombier putactivity(0); 149dc5a79c1SDavid du Colombier sleep(60*1000); 150dc5a79c1SDavid du Colombier } 151dc5a79c1SDavid du Colombier } 152