PageRenderTime 35ms CodeModel.GetById 13ms RepoModel.GetById 1ms app.codeStats 0ms

/uClinux-dist/user/asterisk/main/dns.c

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