akaros/user/ndblib/dnsquery.c
<<
>>
Prefs
   1/* 
   2 * This file is part of the UCB release of Plan 9. It is subject to the license
   3 * terms in the LICENSE file found in the top-level directory of this
   4 * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
   5 * part of the UCB release of Plan 9, including this file, may be copied,
   6 * modified, propagated, or distributed except according to the terms contained
   7 * in the LICENSE file.
   8 */
   9#include <stdlib.h>
  10
  11#include <stdio.h>
  12#include <parlib/parlib.h>
  13#include <unistd.h>
  14#include <signal.h>
  15#include <fcntl.h>
  16#include <iplib/iplib.h>
  17#include <ndblib/ndb.h>
  18
  19static void nstrcpy(char*, char*, int);
  20static void mkptrname(char*, char*, int);
  21static struct ndbtuple *doquery(int, char *dn, char *type);
  22
  23/*
  24 *  search for a tuple that has the given 'attr=val' and also 'rattr=x'.
  25 *  copy 'x' into 'buf' and return the whole tuple.
  26 *
  27 *  return 0 if not found.
  28 */
  29struct ndbtuple*
  30dnsquery(char *net, char *val, char *type)
  31{
  32        char rip[128];
  33        char *p;
  34        struct ndbtuple *t;
  35        int fd;
  36
  37        /* if the address is V4 or V6 null address, give up early */
  38        if(strcmp(val, "::") == 0 || strcmp(val, "0.0.0.0") == 0)
  39                return NULL;
  40
  41        if(net == NULL)
  42                net = "/net";
  43        snprintf(rip, sizeof(rip), "%s/dns", net);
  44        fd = open(rip, O_RDWR);
  45        if(fd < 0){
  46                if(strcmp(net, "/net") == 0)
  47                        snprintf(rip, sizeof(rip), "/srv/dns");
  48                else {
  49                        snprintf(rip, sizeof(rip), "/srv/dns%s", net);
  50                        p = strrchr(rip, '/');
  51                        *p = '_';
  52                }
  53                fd = open(rip, O_RDWR);
  54                if(fd < 0)
  55                        return NULL;
  56#if 0
  57                if(mount(fd, -1, net, MBEFORE, "") < 0){
  58                        close(fd);
  59                        return NULL;
  60                }
  61#else
  62#define MBEFORE 1
  63#define NOAUTHFD -1
  64                int ret;
  65                ret = syscall(SYS_nmount, fd, NOAUTHFD, net, MBEFORE, "");
  66                if (ret < 0){
  67                        close(fd);
  68                        return NULL;
  69                }
  70#endif
  71                /* fd is now closed */
  72                snprintf(rip, sizeof(rip), "%s/dns", net);
  73                fd = open(rip, O_RDWR);
  74                if(fd < 0)
  75                        return NULL;
  76        }
  77
  78        /* zero out the error string */
  79        werrstr("");
  80
  81        /* if this is a reverse lookup, first lookup the domain name */
  82        if(strcmp(type, "ptr") == 0){
  83                mkptrname(val, rip, sizeof rip);
  84                t = doquery(fd, rip, "ptr");
  85        } else
  86                t = doquery(fd, val, type);
  87
  88        /*
  89         * TODO: make fd static and keep it open to reduce 9P traffic
  90         * walking to /net*^/dns.  Must be prepared to re-open it on error.
  91         */
  92        close(fd);
  93        ndbsetmalloctag(t, getcallerpc(&net));
  94        return t;
  95}
  96
  97/*
  98 *  convert address into a reverse lookup address
  99 */
 100static void
 101mkptrname(char *ip, char *rip, int rlen)
 102{
 103        char buf[128];
 104        char *p, *np;
 105        int len;
 106
 107        if(strstr(ip, "in-addr.arpa") || strstr(ip, "IN-ADDR.ARPA")){
 108                nstrcpy(rip, ip, rlen);
 109                return;
 110        }
 111
 112        nstrcpy(buf, ip, sizeof buf);
 113        for(p = buf; *p; p++)
 114                ;
 115        *p = '.';
 116        np = rip;
 117        len = 0;
 118        while(p >= buf){
 119                len++;
 120                p--;
 121                if(*p == '.'){
 122                        memmove(np, p+1, len);
 123                        np += len;
 124                        len = 0;
 125                }
 126        }
 127        memmove(np, p+1, len);
 128        np += len;
 129        strcpy(np, "in-addr.arpa");
 130}
 131
 132static void
 133nstrcpy(char *to, char *from, int len)
 134{
 135        strncpy(to, from, len);
 136        to[len-1] = 0;
 137}
 138
 139static struct ndbtuple*
 140doquery(int fd, char *dn, char *type)
 141{
 142        char buf[1024];
 143        int n;
 144        struct ndbtuple *t, *first, *last;
 145
 146        lseek(fd, 0, 0);
 147        snprintf(buf, sizeof(buf), "!%s %s", dn, type);
 148        if(write(fd, buf, strlen(buf)) < 0)
 149                return NULL;
 150                
 151        lseek(fd, 0, 0);
 152
 153        first = last = NULL;
 154        
 155        for(;;){
 156                n = read(fd, buf, sizeof(buf)-2);
 157                if(n <= 0)
 158                        break;
 159                /* ndbparsline needs a trailing new line */
 160                if(buf[n-1] != '\n')
 161                        buf[n++] = '\n';
 162                buf[n] = 0;
 163
 164                /* check for the error condition */
 165                if(buf[0] == '!'){
 166                        werrstr("%s", buf+1);
 167                        return NULL;
 168                }
 169
 170                t = _ndbparseline(buf);
 171                if(t != NULL){
 172                        if(first)
 173                                last->entry = t;
 174                        else
 175                                first = t;
 176                        last = t;
 177
 178                        while(last->entry)
 179                                last = last->entry;
 180                }
 181        }
 182
 183        ndbsetmalloctag(first, getcallerpc(&fd));
 184        return first;
 185}
 186