xref: /plan9-contrib/sys/src/libndb/dnsquery.c (revision 5da35e229633a615173ae36c776db81807686a11)
17dd7cddfSDavid du Colombier #include <u.h>
27dd7cddfSDavid du Colombier #include <libc.h>
37dd7cddfSDavid du Colombier #include <bio.h>
47dd7cddfSDavid du Colombier #include <ndb.h>
57dd7cddfSDavid du Colombier #include <ndbhf.h>
67dd7cddfSDavid du Colombier 
795a264b3SDavid du Colombier static void nstrcpy(char*, char*, int);
895a264b3SDavid du Colombier static void mkptrname(char*, char*, int);
97dd7cddfSDavid du Colombier static Ndbtuple *doquery(int, char *dn, char *type);
107dd7cddfSDavid du Colombier 
117dd7cddfSDavid du Colombier /*
127dd7cddfSDavid du Colombier  *  search for a tuple that has the given 'attr=val' and also 'rattr=x'.
137dd7cddfSDavid du Colombier  *  copy 'x' into 'buf' and return the whole tuple.
147dd7cddfSDavid du Colombier  *
157dd7cddfSDavid du Colombier  *  return 0 if not found.
167dd7cddfSDavid du Colombier  */
177dd7cddfSDavid du Colombier Ndbtuple*
dnsquery(char * net,char * val,char * type)187dd7cddfSDavid du Colombier dnsquery(char *net, char *val, char *type)
197dd7cddfSDavid du Colombier {
2095a264b3SDavid du Colombier 	char rip[128];
217dd7cddfSDavid du Colombier 	char *p;
227dd7cddfSDavid du Colombier 	Ndbtuple *t;
237dd7cddfSDavid du Colombier 	int fd;
247dd7cddfSDavid du Colombier 
25ea58ad6fSDavid du Colombier 	/* if the address is V4 or V6 null address, give up early */
267dd7cddfSDavid du Colombier 	if(strcmp(val, "::") == 0 || strcmp(val, "0.0.0.0") == 0)
277dd7cddfSDavid du Colombier 		return nil;
287dd7cddfSDavid du Colombier 
297dd7cddfSDavid du Colombier 	if(net == nil)
307dd7cddfSDavid du Colombier 		net = "/net";
317dd7cddfSDavid du Colombier 	snprint(rip, sizeof(rip), "%s/dns", net);
327dd7cddfSDavid du Colombier 	fd = open(rip, ORDWR);
337dd7cddfSDavid du Colombier 	if(fd < 0){
347dd7cddfSDavid du Colombier 		if(strcmp(net, "/net") == 0)
357dd7cddfSDavid du Colombier 			snprint(rip, sizeof(rip), "/srv/dns");
367dd7cddfSDavid du Colombier 		else {
377dd7cddfSDavid du Colombier 			snprint(rip, sizeof(rip), "/srv/dns%s", net);
387dd7cddfSDavid du Colombier 			p = strrchr(rip, '/');
397dd7cddfSDavid du Colombier 			*p = '_';
407dd7cddfSDavid du Colombier 		}
417dd7cddfSDavid du Colombier 		fd = open(rip, ORDWR);
427dd7cddfSDavid du Colombier 		if(fd < 0)
437dd7cddfSDavid du Colombier 			return nil;
44dc5a79c1SDavid du Colombier 		if(mount(fd, -1, net, MBEFORE, "") < 0){
457dd7cddfSDavid du Colombier 			close(fd);
46dc5a79c1SDavid du Colombier 			return nil;
47dc5a79c1SDavid du Colombier 		}
48dc5a79c1SDavid du Colombier 		/* fd is now closed */
497dd7cddfSDavid du Colombier 		snprint(rip, sizeof(rip), "%s/dns", net);
507dd7cddfSDavid du Colombier 		fd = open(rip, ORDWR);
517dd7cddfSDavid du Colombier 		if(fd < 0)
527dd7cddfSDavid du Colombier 			return nil;
537dd7cddfSDavid du Colombier 	}
547dd7cddfSDavid du Colombier 
557dd7cddfSDavid du Colombier 	/* zero out the error string */
567dd7cddfSDavid du Colombier 	werrstr("");
577dd7cddfSDavid du Colombier 
587dd7cddfSDavid du Colombier 	/* if this is a reverse lookup, first lookup the domain name */
597dd7cddfSDavid du Colombier 	if(strcmp(type, "ptr") == 0){
6095a264b3SDavid du Colombier 		mkptrname(val, rip, sizeof rip);
617dd7cddfSDavid du Colombier 		t = doquery(fd, rip, "ptr");
627dd7cddfSDavid du Colombier 	} else
637dd7cddfSDavid du Colombier 		t = doquery(fd, val, type);
647dd7cddfSDavid du Colombier 
65ea58ad6fSDavid du Colombier 	/*
66ea58ad6fSDavid du Colombier 	 * TODO: make fd static and keep it open to reduce 9P traffic
678c055935SDavid du Colombier 	 * walking to /net*^/dns.  Must be prepared to re-open it on error.
68ea58ad6fSDavid du Colombier 	 */
697dd7cddfSDavid du Colombier 	close(fd);
701a4050f5SDavid du Colombier 	ndbsetmalloctag(t, getcallerpc(&net));
717dd7cddfSDavid du Colombier 	return t;
727dd7cddfSDavid du Colombier }
737dd7cddfSDavid du Colombier 
747dd7cddfSDavid du Colombier /*
757dd7cddfSDavid du Colombier  *  convert address into a reverse lookup address
767dd7cddfSDavid du Colombier  */
777dd7cddfSDavid du Colombier static void
mkptrname(char * ip,char * rip,int rlen)7895a264b3SDavid du Colombier mkptrname(char *ip, char *rip, int rlen)
797dd7cddfSDavid du Colombier {
8095a264b3SDavid du Colombier 	char buf[128];
817dd7cddfSDavid du Colombier 	char *p, *np;
827dd7cddfSDavid du Colombier 	int len;
837dd7cddfSDavid du Colombier 
84*5da35e22SDavid du Colombier 	if(cistrstr(ip, "in-addr.arpa") || cistrstr(ip, "ip6.arpa")){
8595a264b3SDavid du Colombier 		nstrcpy(rip, ip, rlen);
867dd7cddfSDavid du Colombier 		return;
877dd7cddfSDavid du Colombier 	}
887dd7cddfSDavid du Colombier 
8995a264b3SDavid du Colombier 	nstrcpy(buf, ip, sizeof buf);
907dd7cddfSDavid du Colombier 	for(p = buf; *p; p++)
917dd7cddfSDavid du Colombier 		;
927dd7cddfSDavid du Colombier 	*p = '.';
937dd7cddfSDavid du Colombier 	np = rip;
947dd7cddfSDavid du Colombier 	len = 0;
957dd7cddfSDavid du Colombier 	while(p >= buf){
967dd7cddfSDavid du Colombier 		len++;
977dd7cddfSDavid du Colombier 		p--;
987dd7cddfSDavid du Colombier 		if(*p == '.'){
997dd7cddfSDavid du Colombier 			memmove(np, p+1, len);
1007dd7cddfSDavid du Colombier 			np += len;
1017dd7cddfSDavid du Colombier 			len = 0;
1027dd7cddfSDavid du Colombier 		}
1037dd7cddfSDavid du Colombier 	}
1047dd7cddfSDavid du Colombier 	memmove(np, p+1, len);
1057dd7cddfSDavid du Colombier 	np += len;
1067dd7cddfSDavid du Colombier 	strcpy(np, "in-addr.arpa");
1077dd7cddfSDavid du Colombier }
1087dd7cddfSDavid du Colombier 
1097dd7cddfSDavid du Colombier static void
nstrcpy(char * to,char * from,int len)11095a264b3SDavid du Colombier nstrcpy(char *to, char *from, int len)
1117dd7cddfSDavid du Colombier {
11295a264b3SDavid du Colombier 	strncpy(to, from, len);
11395a264b3SDavid du Colombier 	to[len-1] = 0;
1147dd7cddfSDavid du Colombier }
1157dd7cddfSDavid du Colombier 
1167dd7cddfSDavid du Colombier static Ndbtuple*
doquery(int fd,char * dn,char * type)1177dd7cddfSDavid du Colombier doquery(int fd, char *dn, char *type)
1187dd7cddfSDavid du Colombier {
1197dd7cddfSDavid du Colombier 	char buf[1024];
1207dd7cddfSDavid du Colombier 	int n;
1217dd7cddfSDavid du Colombier 	Ndbtuple *t, *first, *last;
1227dd7cddfSDavid du Colombier 
1237dd7cddfSDavid du Colombier 	seek(fd, 0, 0);
1247dd7cddfSDavid du Colombier 	snprint(buf, sizeof(buf), "!%s %s", dn, type);
1257dd7cddfSDavid du Colombier 	if(write(fd, buf, strlen(buf)) < 0)
1267dd7cddfSDavid du Colombier 		return nil;
1277dd7cddfSDavid du Colombier 
1287dd7cddfSDavid du Colombier 	seek(fd, 0, 0);
1297dd7cddfSDavid du Colombier 
1307dd7cddfSDavid du Colombier 	first = last = nil;
1317dd7cddfSDavid du Colombier 
1327dd7cddfSDavid du Colombier 	for(;;){
1337dd7cddfSDavid du Colombier 		n = read(fd, buf, sizeof(buf)-2);
1347dd7cddfSDavid du Colombier 		if(n <= 0)
1357dd7cddfSDavid du Colombier 			break;
1367dd7cddfSDavid du Colombier 		if(buf[n-1] != '\n')
1377dd7cddfSDavid du Colombier 			buf[n++] = '\n';	/* ndbparsline needs a trailing new line */
1387dd7cddfSDavid du Colombier 		buf[n] = 0;
1397dd7cddfSDavid du Colombier 
1407dd7cddfSDavid du Colombier 		/* check for the error condition */
1417dd7cddfSDavid du Colombier 		if(buf[0] == '!'){
1427dd7cddfSDavid du Colombier 			werrstr("%s", buf+1);
1437dd7cddfSDavid du Colombier 			return nil;
1447dd7cddfSDavid du Colombier 		}
1457dd7cddfSDavid du Colombier 
1467dd7cddfSDavid du Colombier 		t = _ndbparseline(buf);
1477dd7cddfSDavid du Colombier 		if(t != nil){
1487dd7cddfSDavid du Colombier 			if(first)
1497dd7cddfSDavid du Colombier 				last->entry = t;
1507dd7cddfSDavid du Colombier 			else
1517dd7cddfSDavid du Colombier 				first = t;
1527dd7cddfSDavid du Colombier 			last = t;
1537dd7cddfSDavid du Colombier 
1547dd7cddfSDavid du Colombier 			while(last->entry)
1557dd7cddfSDavid du Colombier 				last = last->entry;
1567dd7cddfSDavid du Colombier 		}
1577dd7cddfSDavid du Colombier 	}
1587dd7cddfSDavid du Colombier 
1591a4050f5SDavid du Colombier 	ndbsetmalloctag(first, getcallerpc(&fd));
1607dd7cddfSDavid du Colombier 	return first;
1617dd7cddfSDavid du Colombier }
162