plan9port

fork of plan9port with libvec, libstr and libsdb
Log | Files | Refs | README | LICENSE

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 }