plan9port

fork of plan9port with libvec, libstr and libsdb
Log | Files | Refs | README | LICENSE

dnsquery.c (2837B)


      1 #include <u.h>
      2 #include <libc.h>
      3 #include <bio.h>
      4 #include <ndb.h>
      5 #include <ndbhf.h>
      6 
      7 static void nstrcpy(char*, char*, int);
      8 static void mkptrname(char*, char*, int);
      9 static Ndbtuple *doquery(int, char *dn, char *type);
     10 
     11 /*
     12  *  search for a tuple that has the given 'attr=val' and also 'rattr=x'.
     13  *  copy 'x' into 'buf' and return the whole tuple.
     14  *
     15  *  return 0 if not found.
     16  */
     17 Ndbtuple*
     18 dnsquery(char *net, char *val, char *type)
     19 {
     20 	char rip[128];
     21 	char *p;
     22 	Ndbtuple *t;
     23 	int fd;
     24 
     25 	/* if the address is V4 or V6 null address, give up early vwhoi*/
     26 	if(strcmp(val, "::") == 0 || strcmp(val, "0.0.0.0") == 0)
     27 		return nil;
     28 
     29 	if(net == nil)
     30 		net = "/net";
     31 	snprint(rip, sizeof(rip), "%s/dns", net);
     32 	fd = open(rip, ORDWR);
     33 	if(fd < 0){
     34 		if(strcmp(net, "/net") == 0)
     35 			snprint(rip, sizeof(rip), "/srv/dns");
     36 		else {
     37 			snprint(rip, sizeof(rip), "/srv/dns%s", net);
     38 			p = strrchr(rip, '/');
     39 			*p = '_';
     40 		}
     41 		fd = open(rip, ORDWR);
     42 		if(fd < 0)
     43 			return nil;
     44 		if(mount(fd, -1, net, MBEFORE, "") < 0){
     45 			close(fd);
     46 			return nil;
     47 		}
     48 		/* fd is now closed */
     49 		snprint(rip, sizeof(rip), "%s/dns", net);
     50 		fd = open(rip, ORDWR);
     51 		if(fd < 0)
     52 			return nil;
     53 	}
     54 
     55 	/* zero out the error string */
     56 	werrstr("");
     57 
     58 	/* if this is a reverse lookup, first lookup the domain name */
     59 	if(strcmp(type, "ptr") == 0){
     60 		mkptrname(val, rip, sizeof rip);
     61 		t = doquery(fd, rip, "ptr");
     62 	} else
     63 		t = doquery(fd, val, type);
     64 
     65 	close(fd);
     66 	return t;
     67 }
     68 
     69 /*
     70  *  convert address into a reverse lookup address
     71  */
     72 static void
     73 mkptrname(char *ip, char *rip, int rlen)
     74 {
     75 	char buf[128];
     76 	char *p, *np;
     77 	int len;
     78 
     79 	if(strstr(ip, "in-addr.arpa") || strstr(ip, "IN-ADDR.ARPA")){
     80 		nstrcpy(rip, ip, rlen);
     81 		return;
     82 	}
     83 
     84 	nstrcpy(buf, ip, sizeof buf);
     85 	for(p = buf; *p; p++)
     86 		;
     87 	*p = '.';
     88 	np = rip;
     89 	len = 0;
     90 	while(p >= buf){
     91 		len++;
     92 		p--;
     93 		if(*p == '.'){
     94 			memmove(np, p+1, len);
     95 			np += len;
     96 			len = 0;
     97 		}
     98 	}
     99 	memmove(np, p+1, len);
    100 	np += len;
    101 	strcpy(np, "in-addr.arpa");
    102 }
    103 
    104 static void
    105 nstrcpy(char *to, char *from, int len)
    106 {
    107 	strncpy(to, from, len);
    108 	to[len-1] = 0;
    109 }
    110 
    111 static Ndbtuple*
    112 doquery(int fd, char *dn, char *type)
    113 {
    114 	char buf[1024];
    115 	int n;
    116 	Ndbtuple *t, *first, *last;
    117 
    118 	seek(fd, 0, 0);
    119 	snprint(buf, sizeof(buf), "!%s %s", dn, type);
    120 	if(write(fd, buf, strlen(buf)) < 0)
    121 		return nil;
    122 
    123 	seek(fd, 0, 0);
    124 
    125 	first = last = nil;
    126 
    127 	for(;;){
    128 		n = read(fd, buf, sizeof(buf)-2);
    129 		if(n <= 0)
    130 			break;
    131 		if(buf[n-1] != '\n')
    132 			buf[n++] = '\n';	/* ndbparsline needs a trailing new line */
    133 		buf[n] = 0;
    134 
    135 		/* check for the error condition */
    136 		if(buf[0] == '!'){
    137 			werrstr("%s", buf+1);
    138 			return nil;
    139 		}
    140 
    141 		t = _ndbparseline(buf);
    142 		if(t != nil){
    143 			if(first)
    144 				last->entry = t;
    145 			else
    146 				first = t;
    147 			last = t;
    148 
    149 			while(last->entry)
    150 				last = last->entry;
    151 		}
    152 	}
    153 
    154 	setmalloctag(first, getcallerpc(&fd));
    155 	return first;
    156 }