Wed Jan 8 2020 09:49:46

Asterisk developer's documentation


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