dnsquery.c 2.8 KB

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