dns.c 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295
  1. /*
  2. * Asterisk -- An open source telephony toolkit.
  3. *
  4. * Copyright (C) 1999 - 2005 Thorsten Lockert
  5. *
  6. * Written by Thorsten Lockert <tholo@trollphone.org>
  7. *
  8. * Funding provided by Troll Phone Networks AS
  9. *
  10. * See http://www.asterisk.org for more information about
  11. * the Asterisk project. Please do not directly contact
  12. * any of the maintainers of this project for assistance;
  13. * the project provides a web site, mailing lists and IRC
  14. * channels for your use.
  15. *
  16. * This program is free software, distributed under the terms of
  17. * the GNU General Public License Version 2. See the LICENSE file
  18. * at the top of the source tree.
  19. */
  20. /*! \file
  21. *
  22. * \brief DNS Support for Asterisk
  23. *
  24. * \author Thorsten Lockert <tholo@trollphone.org>
  25. */
  26. #include <sys/types.h>
  27. #include <sys/socket.h>
  28. #include <netinet/in.h>
  29. #include <arpa/nameser.h>
  30. #include <resolv.h>
  31. #include <unistd.h>
  32. #include "asterisk.h"
  33. ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
  34. #include "asterisk/logger.h"
  35. #include "asterisk/channel.h"
  36. #include "asterisk/dns.h"
  37. #include "asterisk/endian.h"
  38. #define MAX_SIZE 4096
  39. /* The dns_HEADER structure definition below originated
  40. in the arpa/nameser.h header file distributed with ISC
  41. BIND, which contains the following copyright and license
  42. notices:
  43. * ++Copyright++ 1983, 1989, 1993
  44. * -
  45. * Copyright (c) 1983, 1989, 1993
  46. * The Regents of the University of California. All rights reserved.
  47. *
  48. * Redistribution and use in source and binary forms, with or without
  49. * modification, are permitted provided that the following conditions
  50. * are met:
  51. * 1. Redistributions of source code must retain the above copyright
  52. * notice, this list of conditions and the following disclaimer.
  53. * 2. Redistributions in binary form must reproduce the above copyright
  54. * notice, this list of conditions and the following disclaimer in the
  55. * documentation and/or other materials provided with the distribution.
  56. * 3. All advertising materials mentioning features or use of this software
  57. * must display the following acknowledgement:
  58. * This product includes software developed by the University of
  59. * California, Berkeley and its contributors.
  60. * 4. Neither the name of the University nor the names of its contributors
  61. * may be used to endorse or promote products derived from this software
  62. * without specific prior written permission.
  63. *
  64. * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  65. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  66. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  67. * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  68. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  69. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  70. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  71. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  72. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  73. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  74. * SUCH DAMAGE.
  75. * -
  76. * Portions Copyright (c) 1993 by Digital Equipment Corporation.
  77. *
  78. * Permission to use, copy, modify, and distribute this software for any
  79. * purpose with or without fee is hereby granted, provided that the above
  80. * copyright notice and this permission notice appear in all copies, and that
  81. * the name of Digital Equipment Corporation not be used in advertising or
  82. * publicity pertaining to distribution of the document or software without
  83. * specific, written prior permission.
  84. *
  85. * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
  86. * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
  87. * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
  88. * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
  89. * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
  90. * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
  91. * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
  92. * SOFTWARE.
  93. * -
  94. * --Copyright--
  95. */
  96. typedef struct {
  97. unsigned id :16; /* query identification number */
  98. #if __BYTE_ORDER == __BIG_ENDIAN
  99. /* fields in third byte */
  100. unsigned qr: 1; /* response flag */
  101. unsigned opcode: 4; /* purpose of message */
  102. unsigned aa: 1; /* authoritive answer */
  103. unsigned tc: 1; /* truncated message */
  104. unsigned rd: 1; /* recursion desired */
  105. /* fields in fourth byte */
  106. unsigned ra: 1; /* recursion available */
  107. unsigned unused :1; /* unused bits (MBZ as of 4.9.3a3) */
  108. unsigned ad: 1; /* authentic data from named */
  109. unsigned cd: 1; /* checking disabled by resolver */
  110. unsigned rcode :4; /* response code */
  111. #endif
  112. #if __BYTE_ORDER == __LITTLE_ENDIAN || __BYTE_ORDER == __PDP_ENDIAN
  113. /* fields in third byte */
  114. unsigned rd :1; /* recursion desired */
  115. unsigned tc :1; /* truncated message */
  116. unsigned aa :1; /* authoritive answer */
  117. unsigned opcode :4; /* purpose of message */
  118. unsigned qr :1; /* response flag */
  119. /* fields in fourth byte */
  120. unsigned rcode :4; /* response code */
  121. unsigned cd: 1; /* checking disabled by resolver */
  122. unsigned ad: 1; /* authentic data from named */
  123. unsigned unused :1; /* unused bits (MBZ as of 4.9.3a3) */
  124. unsigned ra :1; /* recursion available */
  125. #endif
  126. /* remaining bytes */
  127. unsigned qdcount :16; /* number of question entries */
  128. unsigned ancount :16; /* number of answer entries */
  129. unsigned nscount :16; /* number of authority entries */
  130. unsigned arcount :16; /* number of resource entries */
  131. } dns_HEADER;
  132. struct dn_answer {
  133. unsigned short rtype;
  134. unsigned short class;
  135. unsigned int ttl;
  136. unsigned short size;
  137. } __attribute__ ((__packed__));
  138. static int skip_name(char *s, int len)
  139. {
  140. int x = 0;
  141. while (x < len) {
  142. if (*s == '\0') {
  143. s++;
  144. x++;
  145. break;
  146. }
  147. if ((*s & 0xc0) == 0xc0) {
  148. s += 2;
  149. x += 2;
  150. break;
  151. }
  152. x += *s + 1;
  153. s += *s + 1;
  154. }
  155. if (x >= len)
  156. return -1;
  157. return x;
  158. }
  159. /*--- dns_parse_answer: Parse DNS lookup result, call callback */
  160. static int dns_parse_answer(void *context,
  161. int class, int type, char *answer, int len,
  162. int (*callback)(void *context, char *answer, int len, char *fullanswer))
  163. {
  164. char *fullanswer = answer;
  165. struct dn_answer *ans;
  166. dns_HEADER *h;
  167. int res;
  168. int x;
  169. h = (dns_HEADER *)answer;
  170. answer += sizeof(dns_HEADER);
  171. len -= sizeof(dns_HEADER);
  172. for (x = 0; x < ntohs(h->qdcount); x++) {
  173. if ((res = skip_name(answer, len)) < 0) {
  174. ast_log(LOG_WARNING, "Couldn't skip over name\n");
  175. return -1;
  176. }
  177. answer += res + 4; /* Skip name and QCODE / QCLASS */
  178. len -= res + 4;
  179. if (len < 0) {
  180. ast_log(LOG_WARNING, "Strange query size\n");
  181. return -1;
  182. }
  183. }
  184. for (x = 0; x < ntohs(h->ancount); x++) {
  185. if ((res = skip_name(answer, len)) < 0) {
  186. ast_log(LOG_WARNING, "Failed skipping name\n");
  187. return -1;
  188. }
  189. answer += res;
  190. len -= res;
  191. ans = (struct dn_answer *)answer;
  192. answer += sizeof(struct dn_answer);
  193. len -= sizeof(struct dn_answer);
  194. if (len < 0) {
  195. ast_log(LOG_WARNING, "Strange result size\n");
  196. return -1;
  197. }
  198. if (len < 0) {
  199. ast_log(LOG_WARNING, "Length exceeds frame\n");
  200. return -1;
  201. }
  202. if (ntohs(ans->class) == class && ntohs(ans->rtype) == type) {
  203. if (callback) {
  204. if ((res = callback(context, answer, ntohs(ans->size), fullanswer)) < 0) {
  205. ast_log(LOG_WARNING, "Failed to parse result\n");
  206. return -1;
  207. }
  208. if (res > 0)
  209. return 1;
  210. }
  211. }
  212. answer += ntohs(ans->size);
  213. len -= ntohs(ans->size);
  214. }
  215. return 0;
  216. }
  217. #if defined(res_ninit)
  218. #define HAS_RES_NINIT
  219. #if defined(res_ndestroy)
  220. #define HAS_RES_NDESTROY
  221. #endif
  222. #else
  223. AST_MUTEX_DEFINE_STATIC(res_lock);
  224. #if 0
  225. #warning "Warning, res_ninit is missing... Could have reentrancy issues"
  226. #endif
  227. #endif
  228. /*--- ast_search_dns: Lookup record in DNS */
  229. int ast_search_dns(void *context,
  230. const char *dname, int class, int type,
  231. int (*callback)(void *context, char *answer, int len, char *fullanswer))
  232. {
  233. #ifdef HAS_RES_NINIT
  234. struct __res_state dnsstate;
  235. #endif
  236. char answer[MAX_SIZE];
  237. int res, ret = -1;
  238. #ifdef HAS_RES_NINIT
  239. #ifdef MAKE_VALGRIND_HAPPY
  240. memset(&dnsstate, 0, sizeof(dnsstate));
  241. #endif
  242. res_ninit(&dnsstate);
  243. res = res_nsearch(&dnsstate, dname, class, type, (unsigned char *)answer, sizeof(answer));
  244. #else
  245. ast_mutex_lock(&res_lock);
  246. res_init();
  247. res = res_search(dname, class, type, answer, sizeof(answer));
  248. #endif
  249. if (res > 0) {
  250. if ((res = dns_parse_answer(context, class, type, answer, res, callback)) < 0) {
  251. ast_log(LOG_WARNING, "DNS Parse error for %s\n", dname);
  252. ret = -1;
  253. }
  254. else if (ret == 0) {
  255. ast_log(LOG_DEBUG, "No matches found in DNS for %s\n", dname);
  256. ret = 0;
  257. }
  258. else
  259. ret = 1;
  260. }
  261. #ifdef HAS_RES_NINIT
  262. #ifdef HAS_RES_NDESTROY
  263. res_ndestroy(&dnsstate);
  264. #else
  265. res_nclose(&dnsstate);
  266. #endif
  267. #else
  268. #ifndef __APPLE__
  269. res_close();
  270. #endif
  271. ast_mutex_unlock(&res_lock);
  272. #endif
  273. return ret;
  274. }