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