dnnotify.c (2970B)
1 #include <u.h> 2 #include <libc.h> 3 #include <ip.h> 4 #include <bio.h> 5 #include <ndb.h> 6 #include "dns.h" 7 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; 14 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; 24 25 /* anything to do? */ 26 if(zonerefreshprogram == nil) 27 return; 28 29 /* make sure its the right type */ 30 if(repp->qd->type != Tsoa) 31 return; 32 33 syslog(0, logfile, "notification for %s", repp->qd->owner->name); 34 35 /* is it something we care about? */ 36 a = inmyarea(repp->qd->owner->name); 37 if(a == nil) 38 return; 39 40 syslog(0, logfile, "serial old %lud new %lud", a->soarr->soa->serial, repp->qd->soa->serial); 41 42 /* do nothing if it didn't change */ 43 if(a->soarr->soa->serial== repp->qd->soa->serial) 44 return; 45 46 a->needrefresh = 1; 47 } 48 49 /* 50 * this isn't going to work as a thread! 51 */ 52 53 static void 54 ding(void *u, char *msg) 55 { 56 USED(u); 57 58 if(strstr(msg, "alarm")) 59 noted(NCONT); 60 else 61 noted(NDFLT); 62 } 63 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; 75 76 /* create the request */ 77 reqno = rand(); 78 n = mkreq(soa->owner, Cin, obuf, Fauth | Onotify, reqno); 79 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 } 90 91 fd = udpport(); 92 if(fd < 0) 93 return; 94 95 notify(ding); 96 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; 112 } 113 114 close(fd); 115 } 116 117 /* send notifies for any updated areas */ 118 static void 119 notify_areas(Area *a, Request *req) 120 { 121 Server *s; 122 123 for(; a != nil; a = a->next){ 124 if(!a->neednotify) 125 continue; 126 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; 131 } 132 } 133 134 /* 135 * process to notify other servers of changes 136 * (also reads in new databases) 137 */ 138 void 139 notifyproc(void *v) 140 { 141 Request req; 142 143 USED(v); 144 145 for(;;){ 146 getactivity(&req); 147 notify_areas(owned, &req); 148 putactivity(); 149 sleep(60*1000); 150 } 151 }