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 }