xref: /plan9/sys/src/cmd/ndb/inform.c (revision ad6ca847b1a6a504acb0003cd6c5c6d92687369b)
125fc6993SDavid du Colombier /* RFC2136 DNS inform - necessary for Win2k3 DNS servers */
225fc6993SDavid du Colombier #include <u.h>
325fc6993SDavid du Colombier #include <libc.h>
425fc6993SDavid du Colombier #include <bio.h>
525fc6993SDavid du Colombier #include <ndb.h>
625fc6993SDavid du Colombier #include <ip.h>
76d0458a2SDavid du Colombier #include "dns.h"
825fc6993SDavid du Colombier 
925fc6993SDavid du Colombier enum {
1025fc6993SDavid du Colombier 	FQDNMAX	= 255,
1125fc6993SDavid du Colombier };
1225fc6993SDavid du Colombier 
1325fc6993SDavid du Colombier char *errmsgs[] = {
1425fc6993SDavid du Colombier 	[0]  "ok",
1525fc6993SDavid du Colombier 	[1]  "request format error",
1625fc6993SDavid du Colombier 	[2]  "internal server error",
1725fc6993SDavid du Colombier 	[3]  "domain name does not exist",
1825fc6993SDavid du Colombier 	[4]  "request not supported",
1925fc6993SDavid du Colombier 	[5]  "permission denied",
2025fc6993SDavid du Colombier 	[6]  "domain name already exists",
2125fc6993SDavid du Colombier 	[7]  "resource record already exists",
2225fc6993SDavid du Colombier 	[8]  "resource record does not exist",
2325fc6993SDavid du Colombier 	[9]  "server not authoritative",
2425fc6993SDavid du Colombier 	[10] "domain name not in zone",
2525fc6993SDavid du Colombier };
2625fc6993SDavid du Colombier 
2725fc6993SDavid du Colombier void
usage(void)2825fc6993SDavid du Colombier usage(void)
2925fc6993SDavid du Colombier {
3025fc6993SDavid du Colombier 	fprint(2, "usage: %s [-x netmtpt]\n", argv0);
3125fc6993SDavid du Colombier 	exits("usage");
3225fc6993SDavid du Colombier }
3325fc6993SDavid du Colombier 
3425fc6993SDavid du Colombier void
ding(void *,char * msg)3525fc6993SDavid du Colombier ding(void *, char *msg)
3625fc6993SDavid du Colombier {
3725fc6993SDavid du Colombier 	if(strstr(msg, "alarm") != nil)
3825fc6993SDavid du Colombier 		noted(NCONT);
3925fc6993SDavid du Colombier 	noted(NDFLT);
4025fc6993SDavid du Colombier }
4125fc6993SDavid du Colombier 
4225fc6993SDavid du Colombier int
g16(uchar ** p)4325fc6993SDavid du Colombier g16(uchar **p)
4425fc6993SDavid du Colombier {
4525fc6993SDavid du Colombier 	int n;
4625fc6993SDavid du Colombier 
4725fc6993SDavid du Colombier 	n  = *(*p)++ << 8;
4825fc6993SDavid du Colombier 	n |= *(*p)++;
4925fc6993SDavid du Colombier 	return n;
5025fc6993SDavid du Colombier }
5125fc6993SDavid du Colombier 
5225fc6993SDavid du Colombier void
p16(uchar ** p,int n)5325fc6993SDavid du Colombier p16(uchar **p, int n)
5425fc6993SDavid du Colombier {
5525fc6993SDavid du Colombier 	*(*p)++ = n >> 8;
5625fc6993SDavid du Colombier 	*(*p)++ = n;
5725fc6993SDavid du Colombier }
5825fc6993SDavid du Colombier 
5925fc6993SDavid du Colombier void
p32(uchar ** p,int n)6025fc6993SDavid du Colombier p32(uchar **p, int n)
6125fc6993SDavid du Colombier {
6225fc6993SDavid du Colombier 	*(*p)++ = n >> 24;
6325fc6993SDavid du Colombier 	*(*p)++ = n >> 16;
6425fc6993SDavid du Colombier 	*(*p)++ = n >> 8;
6525fc6993SDavid du Colombier 	*(*p)++ = n;
6625fc6993SDavid du Colombier }
6725fc6993SDavid du Colombier 
6825fc6993SDavid du Colombier void
pmem(uchar ** p,void * v,int len)6925fc6993SDavid du Colombier pmem(uchar **p, void *v, int len)
7025fc6993SDavid du Colombier {
7125fc6993SDavid du Colombier 	memmove(*p, v, len);
7225fc6993SDavid du Colombier 	*p += len;
7325fc6993SDavid du Colombier }
7425fc6993SDavid du Colombier 
7525fc6993SDavid du Colombier void
pname(uchar ** p,char * s)7625fc6993SDavid du Colombier pname(uchar **p, char *s)
7725fc6993SDavid du Colombier {
7825fc6993SDavid du Colombier 	uchar *len;
7925fc6993SDavid du Colombier 
8025fc6993SDavid du Colombier 	while (*s){
8125fc6993SDavid du Colombier 		len = (*p)++;
8225fc6993SDavid du Colombier 		while(*s && *s != '.')
8325fc6993SDavid du Colombier 			*(*p)++ = *s++;
8425fc6993SDavid du Colombier 		*len = *p - len - 1;
8525fc6993SDavid du Colombier 		if(*s == '.')
8625fc6993SDavid du Colombier 			s++;
8725fc6993SDavid du Colombier 	}
8825fc6993SDavid du Colombier 	*(*p)++ = 0;
8925fc6993SDavid du Colombier }
9025fc6993SDavid du Colombier 
9125fc6993SDavid du Colombier void
main(int argc,char * argv[])9225fc6993SDavid du Colombier main(int argc, char *argv[])
9325fc6993SDavid du Colombier {
9425fc6993SDavid du Colombier 	int debug, len, fd;
9525fc6993SDavid du Colombier 	uint err;
96*ad6ca847SDavid du Colombier 	char *sysname, *dnsdomain, *dom, *inform, *ns, net[32];
9725fc6993SDavid du Colombier 	uchar *p, buf[4096], addr[IPv4addrlen], v6addr[IPaddrlen];
9825fc6993SDavid du Colombier 	ushort txid;
9925fc6993SDavid du Colombier 	Ndb *db;
10025fc6993SDavid du Colombier 	Ndbtuple *t, *tt;
101*ad6ca847SDavid du Colombier 	static char *query[] = { "dom", "dnsdomain", "ns", "inform" };
10225fc6993SDavid du Colombier 
10325fc6993SDavid du Colombier 	fmtinstall('I', eipfmt);
10425fc6993SDavid du Colombier 	fmtinstall('V', eipfmt);
10525fc6993SDavid du Colombier 	setnetmtpt(net, sizeof net, nil);
10625fc6993SDavid du Colombier 
10725fc6993SDavid du Colombier 	debug = 0;
10825fc6993SDavid du Colombier 	ns = nil;
10925fc6993SDavid du Colombier 	dom = nil;
110*ad6ca847SDavid du Colombier 	inform = nil;
11125fc6993SDavid du Colombier 	dnsdomain = nil;
11225fc6993SDavid du Colombier 	ARGBEGIN{
11325fc6993SDavid du Colombier 	case 'd':
11425fc6993SDavid du Colombier 		debug = 1;
11525fc6993SDavid du Colombier 		break;
11625fc6993SDavid du Colombier 	case 'x':
11725fc6993SDavid du Colombier 		setnetmtpt(net, sizeof net, EARGF(usage()));
11825fc6993SDavid du Colombier 		break;
11925fc6993SDavid du Colombier 	default:
12025fc6993SDavid du Colombier 		usage();
12125fc6993SDavid du Colombier 	}ARGEND;
12225fc6993SDavid du Colombier 
12325fc6993SDavid du Colombier 	if(argc != 0)
12425fc6993SDavid du Colombier 		usage();
12525fc6993SDavid du Colombier 
12625fc6993SDavid du Colombier 	if((sysname = getenv("sysname")) == nil)
12725fc6993SDavid du Colombier 		sysfatal("$sysname not set");
12825fc6993SDavid du Colombier 
12925fc6993SDavid du Colombier 	if((db = ndbopen(nil)) == nil)
13025fc6993SDavid du Colombier 		sysfatal("can't open ndb: %r");
13125fc6993SDavid du Colombier 	tt = ndbipinfo(db, "sys", sysname, query, nelem(query));
132*ad6ca847SDavid du Colombier 	for(t = tt; t; t = t->entry){
13325fc6993SDavid du Colombier 		if(strcmp(t->attr, "ns") == 0)
13425fc6993SDavid du Colombier 			ns = t->val;
13525fc6993SDavid du Colombier 		else if(strcmp(t->attr, "dom") == 0)
13625fc6993SDavid du Colombier 			dom = t->val;
13725fc6993SDavid du Colombier 		else if(strcmp(t->attr, "dnsdomain") == 0)
13825fc6993SDavid du Colombier 			dnsdomain = t->val;
139*ad6ca847SDavid du Colombier 		else if(strcmp(t->attr, "inform") == 0)
140*ad6ca847SDavid du Colombier 			inform = t->val;
141*ad6ca847SDavid du Colombier 	}
142*ad6ca847SDavid du Colombier 
14325fc6993SDavid du Colombier 	ndbfree(tt);
14425fc6993SDavid du Colombier 	ndbclose(db);
14525fc6993SDavid du Colombier 
146*ad6ca847SDavid du Colombier 	if(inform)
147*ad6ca847SDavid du Colombier 		dom = inform;
14825fc6993SDavid du Colombier 	if(!ns)
14925fc6993SDavid du Colombier 		sysfatal("no relevant ns=");
15025fc6993SDavid du Colombier 	if(!dom)
15125fc6993SDavid du Colombier 		sysfatal("no relevant dom=");
15225fc6993SDavid du Colombier 	if(!dnsdomain)
15325fc6993SDavid du Colombier 		sysfatal("no relevant dnsdomain=");
15425fc6993SDavid du Colombier 
15525fc6993SDavid du Colombier 	myipaddr(v6addr, net);
15625fc6993SDavid du Colombier 	memmove(addr, v6addr + IPaddrlen - IPv4addrlen, IPv4addrlen);
15725fc6993SDavid du Colombier 
15825fc6993SDavid du Colombier 	if(debug){
15925fc6993SDavid du Colombier 		print("ip=%V\n", addr);
16025fc6993SDavid du Colombier 		print("ns=%s\n", ns);
16125fc6993SDavid du Colombier 		print("dnsdomain=%s\n", dnsdomain);
16225fc6993SDavid du Colombier 		print("dom=%s\n", dom);
16325fc6993SDavid du Colombier 	}
16425fc6993SDavid du Colombier 
16525fc6993SDavid du Colombier 	if((fd = dial(netmkaddr(ns, "udp", "dns"), 0, 0, 0)) < 0)
16625fc6993SDavid du Colombier 		sysfatal("can't dial %s: %r", ns);
16725fc6993SDavid du Colombier 
16825fc6993SDavid du Colombier 	txid = time(nil) + getpid();
16925fc6993SDavid du Colombier 
17025fc6993SDavid du Colombier 	p = buf;
17125fc6993SDavid du Colombier 	p16(&p, txid);		/* ID */
17225fc6993SDavid du Colombier 	p16(&p, 5<<11);		/* flags */
17325fc6993SDavid du Colombier 	p16(&p, 1);		/* # Zones */
17425fc6993SDavid du Colombier 	p16(&p, 0);		/* # prerequisites */
17525fc6993SDavid du Colombier 	p16(&p, 2);		/* # updates */
17625fc6993SDavid du Colombier 	p16(&p, 0);		/* # additionals */
17725fc6993SDavid du Colombier 
17825fc6993SDavid du Colombier         pname(&p, dnsdomain);	/* zone */
17925fc6993SDavid du Colombier 	p16(&p, Tsoa);		/* zone type */
18025fc6993SDavid du Colombier 	p16(&p, Cin);		/* zone class */
18125fc6993SDavid du Colombier 
18225fc6993SDavid du Colombier 	/* delete old name */
18325fc6993SDavid du Colombier         pname(&p, dom);		/* name */
18425fc6993SDavid du Colombier 	p16(&p, Ta);		/* type: v4 addr */
18525fc6993SDavid du Colombier 	p16(&p, Call);		/* class */
18625fc6993SDavid du Colombier 	p32(&p, 0);		/* TTL */
18725fc6993SDavid du Colombier 	p16(&p, 0);		/* data len */
18825fc6993SDavid du Colombier 
18925fc6993SDavid du Colombier 	/* add new A record */
19025fc6993SDavid du Colombier 	pname(&p, dom);		/* name */
19125fc6993SDavid du Colombier 	p16(&p, Ta);		/* type: v4 addr */
19225fc6993SDavid du Colombier 	p16(&p, Cin);		/* class */
19325fc6993SDavid du Colombier 	p32(&p, 60*60*25);	/* TTL (25 hours) */
19425fc6993SDavid du Colombier 	p16(&p, IPv4addrlen);	/* data len */
19525fc6993SDavid du Colombier 	pmem(&p, addr, IPv4addrlen);	/* v4 address */
19625fc6993SDavid du Colombier 
19725fc6993SDavid du Colombier 	len = p - buf;
19825fc6993SDavid du Colombier 	if(write(fd, buf, len) != len)
19925fc6993SDavid du Colombier 		sysfatal("write failed: %r");
20025fc6993SDavid du Colombier 
20125fc6993SDavid du Colombier 	notify(ding);
20225fc6993SDavid du Colombier 	alarm(3000);
20325fc6993SDavid du Colombier 	do{
20425fc6993SDavid du Colombier 		if(read(fd, buf, sizeof buf) < 0)
20525fc6993SDavid du Colombier 			sysfatal("timeout");
20625fc6993SDavid du Colombier 		p = buf;
20725fc6993SDavid du Colombier 	}while(g16(&p) != txid);
20825fc6993SDavid du Colombier 	alarm(0);
20925fc6993SDavid du Colombier 
21025fc6993SDavid du Colombier 	close(fd);
21125fc6993SDavid du Colombier 
21225fc6993SDavid du Colombier 	err = g16(&p) & 7;
21325fc6993SDavid du Colombier 	if(err != 0 && err != 7)	/* err==7 is just a "yes, I know" warning */
21425fc6993SDavid du Colombier 		if(err < nelem(errmsgs))
21525fc6993SDavid du Colombier 			sysfatal("%s", errmsgs[err]);
21625fc6993SDavid du Colombier 		else
21725fc6993SDavid du Colombier 			sysfatal("unknown dns server error %d", err);
21825fc6993SDavid du Colombier 	exits(0);
21925fc6993SDavid du Colombier }
220