URI:
       tdnnotify.c - plan9port - [fork] Plan 9 from user space
  HTML git clone git://src.adamsgaard.dk/plan9port
   DIR Log
   DIR Files
   DIR Refs
   DIR README
   DIR LICENSE
       ---
       tdnnotify.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 }