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