dns.c 10 KB

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