Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

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