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 */ 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 /* 66 * TODO: make fd static and keep it open to reduce 9P traffic 67 * walking to /net*^/dns. 68 */ 69 close(fd); 70 ndbsetmalloctag(t, getcallerpc(&net)); 71 return t; 72 } 73 74 /* 75 * convert address into a reverse lookup address 76 */ 77 static void 78 mkptrname(char *ip, char *rip, int rlen) 79 { 80 char buf[128]; 81 char *p, *np; 82 int len; 83 84 if(strstr(ip, "in-addr.arpa") || strstr(ip, "IN-ADDR.ARPA")){ 85 nstrcpy(rip, ip, rlen); 86 return; 87 } 88 89 nstrcpy(buf, ip, sizeof buf); 90 for(p = buf; *p; p++) 91 ; 92 *p = '.'; 93 np = rip; 94 len = 0; 95 while(p >= buf){ 96 len++; 97 p--; 98 if(*p == '.'){ 99 memmove(np, p+1, len); 100 np += len; 101 len = 0; 102 } 103 } 104 memmove(np, p+1, len); 105 np += len; 106 strcpy(np, "in-addr.arpa"); 107 } 108 109 static void 110 nstrcpy(char *to, char *from, int len) 111 { 112 strncpy(to, from, len); 113 to[len-1] = 0; 114 } 115 116 static Ndbtuple* 117 doquery(int fd, char *dn, char *type) 118 { 119 char buf[1024]; 120 int n; 121 Ndbtuple *t, *first, *last; 122 123 seek(fd, 0, 0); 124 snprint(buf, sizeof(buf), "!%s %s", dn, type); 125 if(write(fd, buf, strlen(buf)) < 0) 126 return nil; 127 128 seek(fd, 0, 0); 129 130 first = last = nil; 131 132 for(;;){ 133 n = read(fd, buf, sizeof(buf)-2); 134 if(n <= 0) 135 break; 136 if(buf[n-1] != '\n') 137 buf[n++] = '\n'; /* ndbparsline needs a trailing new line */ 138 buf[n] = 0; 139 140 /* check for the error condition */ 141 if(buf[0] == '!'){ 142 werrstr("%s", buf+1); 143 return nil; 144 } 145 146 t = _ndbparseline(buf); 147 if(t != nil){ 148 if(first) 149 last->entry = t; 150 else 151 first = t; 152 last = t; 153 154 while(last->entry) 155 last = last->entry; 156 } 157 } 158 159 ndbsetmalloctag(first, getcallerpc(&fd)); 160 return first; 161 } 162