Subversion Repositories planix.SVN

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
/* RFC2136 DNS inform - necessary for Win2k3 DNS servers */
2
#include <u.h>
3
#include <libc.h>
4
#include <bio.h>
5
#include <ndb.h>
6
#include <ip.h>
7
#include "dns.h"
8
 
9
enum {
10
	FQDNMAX	= 255,
11
};
12
 
13
char *errmsgs[] = {
14
	[0]  "ok",
15
	[1]  "request format error",
16
	[2]  "internal server error",
17
	[3]  "domain name does not exist",
18
	[4]  "request not supported",
19
	[5]  "permission denied",
20
	[6]  "domain name already exists",
21
	[7]  "resource record already exists",
22
	[8]  "resource record does not exist",
23
	[9]  "server not authoritative",
24
	[10] "domain name not in zone",
25
};
26
 
27
void
28
usage(void)
29
{
30
	fprint(2, "usage: %s [-x netmtpt]\n", argv0);
31
	exits("usage");
32
}
33
 
34
void
35
ding(void *, char *msg)
36
{
37
	if(strstr(msg, "alarm") != nil)
38
		noted(NCONT);
39
	noted(NDFLT);
40
}
41
 
42
int
43
g16(uchar **p)
44
{
45
	int n;
46
 
47
	n  = *(*p)++ << 8;
48
	n |= *(*p)++;
49
	return n;
50
}
51
 
52
void
53
p16(uchar **p, int n)
54
{
55
	*(*p)++ = n >> 8;
56
	*(*p)++ = n;
57
}
58
 
59
void
60
p32(uchar **p, int n)
61
{
62
	*(*p)++ = n >> 24;
63
	*(*p)++ = n >> 16;
64
	*(*p)++ = n >> 8;
65
	*(*p)++ = n;
66
}
67
 
68
void
69
pmem(uchar **p, void *v, int len)
70
{
71
	memmove(*p, v, len);
72
	*p += len;
73
}
74
 
75
void
76
pname(uchar **p, char *s)
77
{
78
	uchar *len;
79
 
80
	while (*s){
81
		len = (*p)++;
82
		while(*s && *s != '.')
83
			*(*p)++ = *s++;
84
		*len = *p - len - 1;
85
		if(*s == '.')
86
			s++;
87
	}
88
	*(*p)++ = 0;
89
}
90
 
91
void
92
main(int argc, char *argv[])
93
{
94
	int debug, len, fd;
95
	uint err;
96
	char *sysname, *dnsdomain, *dom, *inform, *ns, net[32];
97
	uchar *p, buf[4096], addr[IPv4addrlen], v6addr[IPaddrlen];
98
	ushort txid;
99
	Ndb *db;
100
	Ndbtuple *t, *tt;
101
	static char *query[] = { "dom", "dnsdomain", "ns", "inform" };
102
 
103
	fmtinstall('I', eipfmt);
104
	fmtinstall('V', eipfmt);
105
	setnetmtpt(net, sizeof net, nil);
106
 
107
	debug = 0;
108
	ns = nil;
109
	dom = nil;
110
	inform = nil;
111
	dnsdomain = nil;
112
	ARGBEGIN{
113
	case 'd':
114
		debug = 1;
115
		break;
116
	case 'x':
117
		setnetmtpt(net, sizeof net, EARGF(usage()));
118
		break;
119
	default:
120
		usage();
121
	}ARGEND;
122
 
123
	if(argc != 0)
124
		usage();
125
 
126
	if((sysname = getenv("sysname")) == nil)
127
		sysfatal("$sysname not set");
128
 
129
	if((db = ndbopen(nil)) == nil)
130
		sysfatal("can't open ndb: %r");
131
	tt = ndbipinfo(db, "sys", sysname, query, nelem(query));
132
	for(t = tt; t; t = t->entry){
133
		if(strcmp(t->attr, "ns") == 0)
134
			ns = t->val;
135
		else if(strcmp(t->attr, "dom") == 0)
136
			dom = t->val;
137
		else if(strcmp(t->attr, "dnsdomain") == 0)
138
			dnsdomain = t->val;
139
		else if(strcmp(t->attr, "inform") == 0)
140
			inform = t->val;
141
	}
142
 
143
	ndbfree(tt);
144
	ndbclose(db);
145
 
146
	if(inform)
147
		dom = inform;
148
	if(!ns)
149
		sysfatal("no relevant ns=");
150
	if(!dom)
151
		sysfatal("no relevant dom=");
152
	if(!dnsdomain)
153
		sysfatal("no relevant dnsdomain=");
154
 
155
	myipaddr(v6addr, net);
156
	memmove(addr, v6addr + IPaddrlen - IPv4addrlen, IPv4addrlen);
157
 
158
	if(debug){
159
		print("ip=%V\n", addr);
160
		print("ns=%s\n", ns);
161
		print("dnsdomain=%s\n", dnsdomain);
162
		print("dom=%s\n", dom);
163
	}
164
 
165
	if((fd = dial(netmkaddr(ns, "udp", "dns"), 0, 0, 0)) < 0)
166
		sysfatal("can't dial %s: %r", ns);
167
 
168
	txid = time(nil) + getpid();
169
 
170
	p = buf;
171
	p16(&p, txid);		/* ID */
172
	p16(&p, 5<<11);		/* flags */
173
	p16(&p, 1);		/* # Zones */
174
	p16(&p, 0);		/* # prerequisites */
175
	p16(&p, 2);		/* # updates */
176
	p16(&p, 0);		/* # additionals */
177
 
178
        pname(&p, dnsdomain);	/* zone */
179
	p16(&p, Tsoa);		/* zone type */
180
	p16(&p, Cin);		/* zone class */
181
 
182
	/* delete old name */
183
        pname(&p, dom);		/* name */
184
	p16(&p, Ta);		/* type: v4 addr */
185
	p16(&p, Call);		/* class */
186
	p32(&p, 0);		/* TTL */
187
	p16(&p, 0);		/* data len */
188
 
189
	/* add new A record */
190
	pname(&p, dom);		/* name */
191
	p16(&p, Ta);		/* type: v4 addr */
192
	p16(&p, Cin);		/* class */
193
	p32(&p, 60*60*25);	/* TTL (25 hours) */
194
	p16(&p, IPv4addrlen);	/* data len */
195
	pmem(&p, addr, IPv4addrlen);	/* v4 address */
196
 
197
	len = p - buf;
198
	if(write(fd, buf, len) != len)
199
		sysfatal("write failed: %r");
200
 
201
	notify(ding);
202
	alarm(3000);
203
	do{
204
		if(read(fd, buf, sizeof buf) < 0)
205
			sysfatal("timeout");
206
		p = buf;
207
	}while(g16(&p) != txid);
208
	alarm(0);
209
 
210
	close(fd);
211
 
212
	err = g16(&p) & 7;
213
	if(err != 0 && err != 7)	/* err==7 is just a "yes, I know" warning */
214
		if(err < nelem(errmsgs))
215
			sysfatal("%s", errmsgs[err]);
216
		else
217
			sysfatal("unknown dns server error %d", err);
218
	exits(0);
219
}