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