dnsquery.c 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  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. return t;
  60. }
  61. /*
  62. * convert address into a reverse lookup address
  63. */
  64. static void
  65. mkptrname(char *ip, char *rip, int rlen)
  66. {
  67. char buf[128];
  68. char *p, *np;
  69. int len;
  70. if(strstr(ip, "in-addr.arpa") || strstr(ip, "IN-ADDR.ARPA")){
  71. nstrcpy(rip, ip, rlen);
  72. return;
  73. }
  74. nstrcpy(buf, ip, sizeof buf);
  75. for(p = buf; *p; p++)
  76. ;
  77. *p = '.';
  78. np = rip;
  79. len = 0;
  80. while(p >= buf){
  81. len++;
  82. p--;
  83. if(*p == '.'){
  84. memmove(np, p+1, len);
  85. np += len;
  86. len = 0;
  87. }
  88. }
  89. memmove(np, p+1, len);
  90. np += len;
  91. strcpy(np, "in-addr.arpa");
  92. }
  93. static void
  94. nstrcpy(char *to, char *from, int len)
  95. {
  96. strncpy(to, from, len);
  97. to[len-1] = 0;
  98. }
  99. static Ndbtuple*
  100. doquery(int fd, char *dn, char *type)
  101. {
  102. char buf[1024];
  103. int n;
  104. Ndbtuple *t, *first, *last;
  105. seek(fd, 0, 0);
  106. snprint(buf, sizeof(buf), "!%s %s", dn, type);
  107. if(write(fd, buf, strlen(buf)) < 0)
  108. return nil;
  109. seek(fd, 0, 0);
  110. first = last = nil;
  111. for(;;){
  112. n = read(fd, buf, sizeof(buf)-2);
  113. if(n <= 0)
  114. break;
  115. if(buf[n-1] != '\n')
  116. buf[n++] = '\n'; /* ndbparsline needs a trailing new line */
  117. buf[n] = 0;
  118. /* check for the error condition */
  119. if(buf[0] == '!'){
  120. werrstr("%s", buf+1);
  121. return nil;
  122. }
  123. t = _ndbparseline(buf);
  124. if(t != nil){
  125. if(first)
  126. last->entry = t;
  127. else
  128. first = t;
  129. last = t;
  130. while(last->entry)
  131. last = last->entry;
  132. }
  133. }
  134. setmalloctag(first, getcallerpc(&fd));
  135. return first;
  136. }