aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/ndb/dnnotify.c
diff options
context:
space:
mode:
authorrsc <devnull@localhost>2005-12-27 04:30:05 +0000
committerrsc <devnull@localhost>2005-12-27 04:30:05 +0000
commit3e0d8fb3ea83b2b65a6425c65beda887140f9349 (patch)
treece1579f6999c0e4adad35b75c498ddc714b40c1e /src/cmd/ndb/dnnotify.c
parentcff43a06f21a674b2b16e72f8853aac5fd24f48d (diff)
downloadplan9port-3e0d8fb3ea83b2b65a6425c65beda887140f9349.tar.gz
plan9port-3e0d8fb3ea83b2b65a6425c65beda887140f9349.tar.bz2
plan9port-3e0d8fb3ea83b2b65a6425c65beda887140f9349.zip
add dns
Diffstat (limited to 'src/cmd/ndb/dnnotify.c')
-rwxr-xr-xsrc/cmd/ndb/dnnotify.c160
1 files changed, 160 insertions, 0 deletions
diff --git a/src/cmd/ndb/dnnotify.c b/src/cmd/ndb/dnnotify.c
new file mode 100755
index 00000000..a5d91005
--- /dev/null
+++ b/src/cmd/ndb/dnnotify.c
@@ -0,0 +1,160 @@
+#include <u.h>
+#include <libc.h>
+#include <ip.h>
+#include <bio.h>
+#include <ndb.h>
+#include "dns.h"
+
+/* get a notification from another system of a changed zone */
+void
+dnnotify(DNSmsg *reqp, DNSmsg *repp, Request *r)
+{
+ RR *tp;
+ Area *a;
+
+ USED(r);
+ /* move one question from reqp to repp */
+ memset(repp, 0, sizeof(*repp));
+ tp = reqp->qd;
+ reqp->qd = tp->next;
+ tp->next = 0;
+ repp->qd = tp;
+ repp->id = reqp->id;
+ repp->flags = Fresp | Onotify | Fauth;
+
+ /* anything to do? */
+ if(zonerefreshprogram == nil)
+ return;
+
+ /* make sure its the right type */
+ if(repp->qd->type != Tsoa)
+ return;
+
+syslog(0, logfile, "notification for %s", repp->qd->owner->name);
+
+ /* is it something we care about? */
+ a = inmyarea(repp->qd->owner->name);
+ if(a == nil)
+ return;
+
+syslog(0, logfile, "serial old %lud new %lud", a->soarr->soa->serial, repp->qd->soa->serial);
+
+ /* do nothing if it didn't change */
+ if(a->soarr->soa->serial== repp->qd->soa->serial)
+ return;
+
+ a->needrefresh = 1;
+}
+
+static void
+ding(void *u, char *msg)
+{
+ USED(u);
+
+ if(strstr(msg, "alarm"))
+ noted(NCONT);
+ else
+ noted(NDFLT);
+}
+
+/* notify a slave that an area has changed. */
+static void
+send_notify(char *slave, RR *soa, Request *req)
+{
+ int i, len, n, reqno, status, fd;
+ uchar obuf[Maxudp+OUdphdrsize];
+ uchar ibuf[Maxudp+OUdphdrsize];
+ RR *rp;
+ OUdphdr *up = (OUdphdr*)obuf;
+ char *err;
+ DNSmsg repmsg;
+
+ /* create the request */
+ reqno = rand();
+ n = mkreq(soa->owner, Cin, obuf, Fauth | Onotify, reqno);
+
+ /* get an address */
+ if(strcmp(ipattr(slave), "ip") == 0) {
+ parseip(up->raddr, slave);
+ } else {
+ rp = dnresolve(slave, Cin, Ta, req, nil, 0, 1, 1, &status);
+ if(rp == nil)
+ return;
+ parseip(up->raddr, rp->ip->name);
+ rrfree(rp);
+ }
+
+ fd = udpport();
+ if(fd < 0)
+ return;
+
+ notify(ding);
+
+ /* send 3 times or until we get anything back */
+ for(i = 0; i < 3; i++){
+syslog(0, logfile, "sending %d byte notify to %s/%I.%d about %s", n, slave, up->raddr, nhgets(up->rport), soa->owner->name);
+ if(udpwrite(fd, (OUdphdr*)obuf, obuf+OUdphdrsize, n) != n)
+ break;
+ alarm(2*1000);
+ len = udpread(fd, (Udphdr*)ibuf, ibuf+OUdphdrsize, Maxudp);
+ alarm(0);
+ if(len <= OUdphdrsize)
+ continue;
+ err = convM2DNS(&ibuf[OUdphdrsize], len, &repmsg);
+ if(err != nil)
+ continue;
+ if(repmsg.id == reqno && (repmsg.flags & Omask) == Onotify)
+ break;
+ }
+
+ close(fd);
+}
+
+/* send notifies for any updated areas */
+static void
+notify_areas(Area *a, Request *req)
+{
+ Server *s;
+
+ for(; a != nil; a = a->next){
+ if(!a->neednotify)
+ continue;
+
+ /* send notifies to all slaves */
+ for(s = a->soarr->soa->slaves; s != nil; s = s->next)
+ send_notify(s->name, a->soarr, req);
+ a->neednotify = 0;
+ }
+}
+
+/*
+ * process to notify other servers of changes
+ * (also reads in new databases)
+ */
+void
+notifyproc(void)
+{
+ Request req;
+ static int already;
+
+ if(already)
+ return;
+
+ switch(rfork(RFPROC|RFNOTEG|RFMEM|RFNOWAIT)){
+ case -1:
+ return;
+ case 0:
+ break;
+ default:
+ return;
+ }
+
+ req.isslave = 1; /* son't fork off subprocesses */
+
+ for(;;){
+ getactivity(&req);
+ notify_areas(owned, &req);
+ putactivity();
+ sleep(60*1000);
+ }
+}