dns.c 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  1. /*
  2. * DNS Support for Asterisk
  3. *
  4. * Written by Thorsten Lockert <tholo@trollphone.org>
  5. *
  6. * Funding provided by Troll Phone Networks AS
  7. *
  8. * This program is free software, distributed under the terms of
  9. * the GNU General Public License
  10. */
  11. #include <sys/types.h>
  12. #include <sys/socket.h>
  13. #include <netinet/in.h>
  14. #include <arpa/nameser.h>
  15. #include <resolv.h>
  16. #include <unistd.h>
  17. #include <asterisk/logger.h>
  18. #include <asterisk/channel.h>
  19. #include <asterisk/dns.h>
  20. #include "asterisk/endian.h"
  21. #define MAX_SIZE 4096
  22. typedef struct {
  23. unsigned id :16; /* query identification number */
  24. #if BYTE_ORDER == BIG_ENDIAN
  25. /* fields in third byte */
  26. unsigned qr: 1; /* response flag */
  27. unsigned opcode: 4; /* purpose of message */
  28. unsigned aa: 1; /* authoritive answer */
  29. unsigned tc: 1; /* truncated message */
  30. unsigned rd: 1; /* recursion desired */
  31. /* fields in fourth byte */
  32. unsigned ra: 1; /* recursion available */
  33. unsigned unused :1; /* unused bits (MBZ as of 4.9.3a3) */
  34. unsigned ad: 1; /* authentic data from named */
  35. unsigned cd: 1; /* checking disabled by resolver */
  36. unsigned rcode :4; /* response code */
  37. #endif
  38. #if BYTE_ORDER == LITTLE_ENDIAN || BYTE_ORDER == PDP_ENDIAN
  39. /* fields in third byte */
  40. unsigned rd :1; /* recursion desired */
  41. unsigned tc :1; /* truncated message */
  42. unsigned aa :1; /* authoritive answer */
  43. unsigned opcode :4; /* purpose of message */
  44. unsigned qr :1; /* response flag */
  45. /* fields in fourth byte */
  46. unsigned rcode :4; /* response code */
  47. unsigned cd: 1; /* checking disabled by resolver */
  48. unsigned ad: 1; /* authentic data from named */
  49. unsigned unused :1; /* unused bits (MBZ as of 4.9.3a3) */
  50. unsigned ra :1; /* recursion available */
  51. #endif
  52. /* remaining bytes */
  53. unsigned qdcount :16; /* number of question entries */
  54. unsigned ancount :16; /* number of answer entries */
  55. unsigned nscount :16; /* number of authority entries */
  56. unsigned arcount :16; /* number of resource entries */
  57. } dns_HEADER;
  58. struct dn_answer {
  59. unsigned short rtype;
  60. unsigned short class;
  61. unsigned int ttl;
  62. unsigned short size;
  63. } __attribute__ ((__packed__));
  64. static int skip_name(u_char *s, int len)
  65. {
  66. int x = 0;
  67. while (x < len) {
  68. if (*s == '\0') {
  69. s++;
  70. x++;
  71. break;
  72. }
  73. if ((*s & 0xc0) == 0xc0) {
  74. s += 2;
  75. x += 2;
  76. break;
  77. }
  78. x += *s + 1;
  79. s += *s + 1;
  80. }
  81. if (x >= len)
  82. return -1;
  83. return x;
  84. }
  85. static int dns_parse_answer(void *context,
  86. int class, int type, u_char *answer, int len,
  87. int (*callback)(void *context, u_char *answer, int len, u_char *fullanswer))
  88. {
  89. u_char *fullanswer = answer;
  90. struct dn_answer *ans;
  91. dns_HEADER *h;
  92. int res;
  93. int x;
  94. h = (dns_HEADER *)answer;
  95. answer += sizeof(dns_HEADER);
  96. len -= sizeof(dns_HEADER);
  97. for (x = 0; x < ntohs(h->qdcount); x++) {
  98. if ((res = skip_name(answer, len)) < 0) {
  99. ast_log(LOG_WARNING, "Couldn't skip over name\n");
  100. return -1;
  101. }
  102. answer += res + 4; /* Skip name and QCODE / QCLASS */
  103. len -= res + 4;
  104. if (len < 0) {
  105. ast_log(LOG_WARNING, "Strange query size\n");
  106. return -1;
  107. }
  108. }
  109. for (x = 0; x < ntohs(h->ancount); x++) {
  110. if ((res = skip_name(answer, len)) < 0) {
  111. ast_log(LOG_WARNING, "Failed skipping name\n");
  112. return -1;
  113. }
  114. answer += res;
  115. len -= res;
  116. ans = (struct dn_answer *)answer;
  117. answer += sizeof(struct dn_answer);
  118. len -= sizeof(struct dn_answer);
  119. if (len < 0) {
  120. ast_log(LOG_WARNING, "Strange result size\n");
  121. return -1;
  122. }
  123. if (len < 0) {
  124. ast_log(LOG_WARNING, "Length exceeds frame\n");
  125. return -1;
  126. }
  127. if (ntohs(ans->class) == class && ntohs(ans->rtype) == type) {
  128. if (callback) {
  129. if ((res = callback(context, answer, ntohs(ans->size), fullanswer)) < 0) {
  130. ast_log(LOG_WARNING, "Failed to parse result\n");
  131. return -1;
  132. }
  133. if (res > 0)
  134. return 1;
  135. }
  136. }
  137. answer += ntohs(ans->size);
  138. len -= ntohs(ans->size);
  139. }
  140. return 0;
  141. }
  142. #if defined(res_ninit)
  143. #define HAS_RES_NINIT
  144. #else
  145. AST_MUTEX_DEFINE_STATIC(res_lock);
  146. #if 0
  147. #warning "Warning, res_ninit is missing... Could have reentrancy issues"
  148. #endif
  149. #endif
  150. int ast_search_dns(void *context,
  151. const char *dname, int class, int type,
  152. int (*callback)(void *context, u_char *answer, int len, u_char *fullanswer))
  153. {
  154. #ifdef HAS_RES_NINIT
  155. struct __res_state dnsstate;
  156. #endif
  157. char answer[MAX_SIZE];
  158. int res, ret = -1;
  159. #ifdef HAS_RES_NINIT
  160. res_ninit(&dnsstate);
  161. res = res_nsearch(&dnsstate, dname, class, type, answer, sizeof(answer));
  162. #else
  163. ast_mutex_lock(&res_lock);
  164. res_init();
  165. res = res_search(dname, class, type, answer, sizeof(answer));
  166. #endif
  167. if (res > 0) {
  168. if ((res = dns_parse_answer(context, class, type, answer, res, callback)) < 0) {
  169. ast_log(LOG_WARNING, "Parse error\n");
  170. ret = -1;
  171. }
  172. else if (ret == 0) {
  173. ast_log(LOG_DEBUG, "No matches found\n");
  174. ret = 0;
  175. }
  176. else
  177. ret = 1;
  178. }
  179. #ifdef HAS_RES_NINIT
  180. res_nclose(&dnsstate);
  181. #else
  182. #ifndef __APPLE__
  183. res_close();
  184. #endif
  185. ast_mutex_unlock(&res_lock);
  186. #endif
  187. return ret;
  188. }