dns.c 9.3 KB

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