Asterisk - The Open Source Telephony Project  18.5.0
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 <[email protected]>
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 <[email protected]>
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 #include "asterisk/network.h"
39 #include <arpa/nameser.h> /* res_* functions */
40 #include <resolv.h>
41 
42 #include "asterisk/channel.h"
43 #include "asterisk/dns.h"
44 #include "asterisk/endian.h"
45 
46 /*! \brief The maximum size permitted for the answer from the DNS server */
47 #define MAX_SIZE 4096
48 
49 #ifdef __PDP_ENDIAN
50 #if __BYTE_ORDER == __PDP_ENDIAN
51 #define DETERMINED_BYTE_ORDER __LITTLE_ENDIAN
52 #endif
53 #endif
54 #if __BYTE_ORDER == __BIG_ENDIAN
55 #define DETERMINED_BYTE_ORDER __BIG_ENDIAN
56 #endif
57 #if __BYTE_ORDER == __LITTLE_ENDIAN
58 #define DETERMINED_BYTE_ORDER __LITTLE_ENDIAN
59 #endif
60 
61 #ifndef HAVE_RES_NINIT
62 AST_MUTEX_DEFINE_STATIC(res_lock);
63 #endif
64 
65 /* The dns_HEADER structure definition below originated
66  in the arpa/nameser.h header file distributed with ISC
67  BIND, which contains the following copyright and license
68  notices:
69 
70  * ++Copyright++ 1983, 1989, 1993
71  * -
72  * Copyright (c) 1983, 1989, 1993
73  * The Regents of the University of California. All rights reserved.
74  *
75  * Redistribution and use in source and binary forms, with or without
76  * modification, are permitted provided that the following conditions
77  * are met:
78  * 1. Redistributions of source code must retain the above copyright
79  * notice, this list of conditions and the following disclaimer.
80  * 2. Redistributions in binary form must reproduce the above copyright
81  * notice, this list of conditions and the following disclaimer in the
82  * documentation and/or other materials provided with the distribution.
83  * 3. All advertising materials mentioning features or use of this software
84  * must display the following acknowledgement:
85  * This product includes software developed by the University of
86  * California, Berkeley and its contributors.
87  * 4. Neither the name of the University nor the names of its contributors
88  * may be used to endorse or promote products derived from this software
89  * without specific prior written permission.
90  *
91  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
92  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
93  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
94  * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
95  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
96  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
97  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
98  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
99  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
100  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
101  * SUCH DAMAGE.
102  * -
103  * Portions Copyright (c) 1993 by Digital Equipment Corporation.
104  *
105  * Permission to use, copy, modify, and distribute this software for any
106  * purpose with or without fee is hereby granted, provided that the above
107  * copyright notice and this permission notice appear in all copies, and that
108  * the name of Digital Equipment Corporation not be used in advertising or
109  * publicity pertaining to distribution of the document or software without
110  * specific, written prior permission.
111  *
112  * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
113  * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
114  * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
115  * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
116  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
117  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
118  * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
119  * SOFTWARE.
120  * -
121  * --Copyright--
122  */
123 
124 typedef struct {
125  unsigned id:16; /*!< query identification number */
126 #if DETERMINED_BYTE_ORDER == __BIG_ENDIAN
127  /* fields in third byte */
128  unsigned qr:1; /*!< response flag */
129  unsigned opcode:4; /*!< purpose of message */
130  unsigned aa:1; /*!< authoritive answer */
131  unsigned tc:1; /*!< truncated message */
132  unsigned rd:1; /*!< recursion desired */
133  /* fields in fourth byte */
134  unsigned ra:1; /*!< recursion available */
135  unsigned unused:1; /*!< unused bits (MBZ as of 4.9.3a3) */
136  unsigned ad:1; /*!< authentic data from named */
137  unsigned cd:1; /*!< checking disabled by resolver */
138  unsigned rcode:4; /*!< response code */
139 #endif
140 #if DETERMINED_BYTE_ORDER == __LITTLE_ENDIAN
141  /* fields in third byte */
142  unsigned rd:1; /*!< recursion desired */
143  unsigned tc:1; /*!< truncated message */
144  unsigned aa:1; /*!< authoritive answer */
145  unsigned opcode:4; /*!< purpose of message */
146  unsigned qr:1; /*!< response flag */
147  /* fields in fourth byte */
148  unsigned rcode:4; /*!< response code */
149  unsigned cd:1; /*!< checking disabled by resolver */
150  unsigned ad:1; /*!< authentic data from named */
151  unsigned unused:1; /*!< unused bits (MBZ as of 4.9.3a3) */
152  unsigned ra:1; /*!< recursion available */
153 #endif
154  /* remaining bytes */
155  unsigned qdcount:16; /*!< number of question entries */
156  unsigned ancount:16; /*!< number of answer entries */
157  unsigned nscount:16; /*!< number of authority entries */
158  unsigned arcount:16; /*!< number of resource entries */
159 } dns_HEADER;
160 
161 struct dn_answer {
162  unsigned short rtype; /*!< The resource record type. */
163  unsigned short class; /*!< The resource record class. */
164  unsigned int ttl; /*!< The resource record time to live. */
165  unsigned short size; /*!< The resource record size. */
166 } __attribute__((__packed__));
167 
168 /*!
169  * \brief Tries to find the position of the next field in the DNS response.
170  *
171  * \internal
172  *
173  * \param s A char pointer to the current frame in the DNS response.
174  * \param len The remaining available length of the DNS response.
175  *
176  * \retval The position of the next field
177  * \retval -1 if there are no remaining fields
178  */
179 static int skip_name(unsigned char *s, int len)
180 {
181  int x = 0;
182 
183  while (x < len) {
184  if (*s == '\0') {
185  s++;
186  x++;
187  break;
188  }
189 
190  if ((*s & 0xc0) == 0xc0) {
191  s += 2;
192  x += 2;
193  break;
194  }
195 
196  x += *s + 1;
197  s += *s + 1;
198  }
199 
200  /* If we are out of room to search, return failure. */
201  if (x >= len) {
202  return AST_DNS_SEARCH_FAILURE;
203  }
204 
205  /* Return the value for the current position in the DNS response. This is the start
206  position of the next field. */
207  return x;
208 }
209 
210 /*!
211  * \brief Advances the position of the DNS response pointer by the size of the current field.
212  *
213  * \internal
214  *
215  * \param dns_response A pointer to a char pointer to the current field in the DNS response.
216  * \param remaining_len The remaining available length in the DNS response to search.
217  * \param field_size A positive value representing the size of the current field
218  pointed to by the dns_response parameter.
219  *
220  * \retval The remaining length in the DNS response
221  * \retval -1 there are no frames remaining in the DNS response
222  */
223 static int dns_advance_field(unsigned char **dns_response, int remaining_len, int field_size)
224 {
225  if (dns_response == NULL || field_size < 0 || remaining_len < field_size) {
226  return AST_DNS_SEARCH_FAILURE;
227  }
228 
229  *dns_response += field_size;
230  remaining_len -= field_size;
231 
232  return remaining_len;
233 }
234 
235 #ifndef HAVE_RES_NINIT
236 /*!
237  * \brief Handles the DNS search if the system has RES_INIT.
238  *
239  * \internal
240  *
241  * \param dname Domain name to lookup (host, SRV domain, TXT record name).
242  * \param rr_class Record Class (see "man res_search").
243  * \param rr_type Record type (see "man res_search").
244  * \param dns_response The full DNS response.
245  * \param dns_response_len The length of the full DNS response.
246  *
247  * \retval The length of the DNS response
248  * \retval -1 on search failure
249  */
250 static int dns_search_res(const char *dname, int rr_class, int rr_type,
251  unsigned char *dns_response, int dns_response_len)
252 {
253 
254  int ret = AST_DNS_SEARCH_FAILURE;
255 
256  ast_mutex_lock(&res_lock);
257  res_init();
258  ret = res_search(dname,
259  rr_class,
260  rr_type,
261  dns_response,
262  dns_response_len);
263 
264 #ifdef HAVE_RES_CLOSE
265  res_close();
266 #endif
267 
268  ast_mutex_unlock(&res_lock);
269 
270  return ret;
271 }
272 #else
273 /*!
274  * \brief Handles the DNS search if the system has RES_NINIT.
275  *
276  * \internal
277  *
278  * \param dname Domain name to lookup (host, SRV domain, TXT record name).
279  * \param rr_class Record Class (see "man res_search").
280  * \param rr_type Record type (see "man res_search").
281  * \param dns_response The full DNS response.
282  * \param dns_response_len The length of the full DNS response.
283  *
284  * \retval The length of the DNS response
285  * \retval -1 on search failure
286  */
287 static int dns_search_res(const char *dname, int rr_class, int rr_type,
288  unsigned char *dns_response, int dns_response_len)
289 {
290 
291  int ret = AST_DNS_SEARCH_FAILURE;
292  struct __res_state dns_state;
293 
294  memset(&dns_state, 0, sizeof(dns_state));
295  res_ninit(&dns_state);
296  ret = res_nsearch(&dns_state,
297  dname,
298  rr_class,
299  rr_type,
300  dns_response,
301  dns_response_len);
302 
303 #ifdef HAVE_RES_NDESTROY
304  res_ndestroy(&dns_state);
305 #else
306  res_nclose(&dns_state);
307 #endif
308 
309  return ret;
310 }
311 #endif
312 
313 /*!
314  * \brief Parse DNS lookup result, call callback
315  *
316  * \internal
317  *
318  * \param context Void pointer containing data to use in the callback functions.
319  * \param dname Domain name to lookup (host, SRV domain, TXT record name).
320  * \param class Record Class (see "man res_search").
321  * \param type Record type (see "man res_search").
322  * \param answer The full DNS response.
323  * \param len The length of the full DNS response.
324  * \param callback Callback function for handling the discovered resource records from the DNS search.
325  *
326  * \retval -1 on search failure
327  * \retval 0 on no records found
328  * \retval 1 on success
329  */
330 static int dns_parse_answer(void *context,
331  int class, int type, unsigned char *answer, int len,
332  int (*callback)(void *context, unsigned char *answer, int len, unsigned char *fullanswer))
333 {
334  unsigned char *fullanswer = answer;
335  struct dn_answer *ans;
336  dns_HEADER *h;
337  int ret = 0;
338  int res;
339  int x;
340 
341  h = (dns_HEADER *)answer;
342  answer += sizeof(dns_HEADER);
343  len -= sizeof(dns_HEADER);
344 
345  for (x = 0; x < ntohs(h->qdcount); x++) {
346  if ((res = skip_name(answer, len)) < 0) {
347  ast_log(LOG_WARNING, "Couldn't skip over name\n");
348  return -1;
349  }
350  answer += res + 4; /* Skip name and QCODE / QCLASS */
351  len -= res + 4;
352  if (len < 0) {
353  ast_log(LOG_WARNING, "Strange query size\n");
354  return -1;
355  }
356  }
357 
358  for (x = 0; x < ntohs(h->ancount); x++) {
359  if ((res = skip_name(answer, len)) < 0) {
360  ast_log(LOG_WARNING, "Failed skipping name\n");
361  return -1;
362  }
363  answer += res;
364  len -= res;
365  ans = (struct dn_answer *)answer;
366  answer += sizeof(struct dn_answer);
367  len -= sizeof(struct dn_answer);
368  if (len < 0) {
369  ast_log(LOG_WARNING, "Length of DNS answer exceeds frame\n");
370  return -1;
371  }
372 
373  if (ntohs(ans->class) == class && ntohs(ans->rtype) == type) {
374  if (callback) {
375  if ((res = callback(context, answer, ntohs(ans->size), fullanswer)) < 0) {
376  ast_log(LOG_WARNING, "Failed to parse result\n");
377  return -1;
378  }
379  ret = 1;
380  }
381  }
382  answer += ntohs(ans->size);
383  len -= ntohs(ans->size);
384  }
385  return ret;
386 }
387 
388 /*!
389  * \brief Extended version of the DNS Parsing function.
390  *
391  * \details Parses the DNS lookup result and notifies the observer of each discovered
392  * resource record with the provided callback.
393  *
394  * \internal
395  *
396  * \param context Void pointer containing data to use in the callback functions.
397  * \param dname Domain name to lookup (host, SRV domain, TXT record name).
398  * \param rr_class Record Class (see "man res_search").
399  * \param rr_type Record type (see "man res_search").
400  * \param answer The full DNS response.
401  * \param answer_len The length of the full DNS response.
402  * \param response_handler Callback function for handling the DNS response.
403  * \param record_handler Callback function for handling the discovered resource records from the DNS search.
404  *
405  * \retval -1 on search failure
406  * \retval 0 on no records found
407  * \retval 1 on success
408  */
409 static int dns_parse_answer_ex(void *context, int rr_class, int rr_type, unsigned char *answer, int answer_len,
410  int (*response_handler)(void *context, unsigned char *dns_response, int dns_response_len, int rcode),
411  int (*record_handler)(void *context, unsigned char *record, int record_len, int ttl))
412 {
413  unsigned char *dns_response = answer;
414  dns_HEADER *dns_header = (dns_HEADER *)answer;
415 
416  struct dn_answer *ans;
417  int res, x, pos, dns_response_len, ret;
418 
419  dns_response_len = answer_len;
421 
422  /* Invoke the response_handler callback to notify the observer of the raw DNS response */
423  response_handler(context, dns_response, dns_response_len, ntohs(dns_header->rcode));
424 
425  /* Verify there is something to parse */
426  if (answer_len == 0) {
427  return ret;
428  }
429 
430  /* Try advancing the cursor for the dns header */
431  if ((pos = dns_advance_field(&answer, answer_len, sizeof(dns_HEADER))) < 0) {
432  ast_log(LOG_WARNING, "Length of DNS answer exceeds available search frames\n");
433  return AST_DNS_SEARCH_FAILURE;
434  }
435 
436  /* Skip domain name and QCODE / QCLASS */
437  for (x = 0; x < ntohs(dns_header->qdcount); x++) {
438  if ((res = skip_name(answer, pos)) < 0) {
439  ast_log(LOG_WARNING, "Failed skipping name\n");
440  return AST_DNS_SEARCH_FAILURE;
441  }
442 
443  /* Try advancing the cursor for the name and QCODE / QCLASS fields */
444  if ((pos = dns_advance_field(&answer, pos, res + 4)) < 0) {
445  return AST_DNS_SEARCH_FAILURE;
446  }
447  }
448 
449  /* Extract the individual records */
450  for (x = 0; x < ntohs(dns_header->ancount); x++) {
451  if ((res = skip_name(answer, pos)) < 0) {
452  ast_log(LOG_WARNING, "Failed skipping name\n");
453  return AST_DNS_SEARCH_FAILURE;
454  }
455 
456  /* Try advancing the cursor to the current record */
457  if ((pos = dns_advance_field(&answer, pos, res)) < 0) {
458  ast_log(LOG_WARNING, "Length of DNS answer exceeds available search frames\n");
459  return AST_DNS_SEARCH_FAILURE;
460  }
461 
462  /* Cast the current value for the answer pointer as a dn_answer struct */
463  ans = (struct dn_answer *) answer;
464 
465  /* Try advancing the cursor to the end of the current record */
466  if ((pos = dns_advance_field(&answer, pos, sizeof(struct dn_answer))) < 0) {
467  ast_log(LOG_WARNING, "Length of DNS answer exceeds available search frames\n");
468  return AST_DNS_SEARCH_FAILURE;
469  }
470 
471  /* Skip over the records that do not have the same resource record class and type we care about */
472  if (ntohs(ans->class) == rr_class && ntohs(ans->rtype) == rr_type) {
473  /* Invoke the record handler callback to deliver the discovered record */
474  record_handler(context, answer, ntohs(ans->size), ntohl(ans->ttl));
475  /*At least one record was found */
477  }
478 
479  /* Try and update the field to the next record, but ignore any errors that come
480  * back because this may be the end of the line. */
481  pos = dns_advance_field(&answer, pos, ntohs(ans->size));
482  }
483 
484  return ret;
485 }
486 
487 /*!
488  * \brief Lookup record in DNS
489  *
490  * \note Asterisk DNS is synchronus at this time. This means that if your DNS does not
491  * work properly, Asterisk might not start properly or a channel may lock.
492 */
493 int ast_search_dns(void *context,
494  const char *dname, int class, int type,
495  int (*callback)(void *context, unsigned char *answer, int len, unsigned char *fullanswer))
496 {
497 #ifdef HAVE_RES_NINIT
498  struct __res_state dnsstate;
499 #endif
500  unsigned char answer[MAX_SIZE];
501  int res, ret = -1;
502 
503 #ifdef HAVE_RES_NINIT
504  memset(&dnsstate, 0, sizeof(dnsstate));
505  res_ninit(&dnsstate);
506  res = res_nsearch(&dnsstate, dname, class, type, answer, sizeof(answer));
507 #else
508  ast_mutex_lock(&res_lock);
509  res_init();
510  res = res_search(dname, class, type, answer, sizeof(answer));
511 #endif
512  if (res > 0) {
513  if ((res = dns_parse_answer(context, class, type, answer, res, callback)) < 0) {
514  ast_log(LOG_WARNING, "DNS Parse error for %s\n", dname);
515  ret = -1;
516  } else if (res == 0) {
517  ast_debug(1, "No matches found in DNS for %s\n", dname);
518  ret = 0;
519  } else
520  ret = 1;
521  }
522 #ifdef HAVE_RES_NINIT
523 #ifdef HAVE_RES_NDESTROY
524  res_ndestroy(&dnsstate);
525 #else
526  res_nclose(&dnsstate);
527 #endif
528 #else
529 #ifdef HAVE_RES_CLOSE
530  res_close();
531 #endif
532  ast_mutex_unlock(&res_lock);
533 #endif
534 
535  return ret;
536 }
537 
538 enum ast_dns_search_result ast_search_dns_ex(void *context, const char *dname, int rr_class, int rr_type,
539  int (*response_handler)(void *context, unsigned char *dns_response, int dns_response_len, int rcode),
540  int (*record_handler)(void *context, unsigned char *record, int record_len, int ttl))
541 {
542  int ret, dns_response_len;
543  unsigned char dns_response[MAX_SIZE];
544 
545  /* Assert that the callbacks are not NULL */
546  ast_assert(response_handler != NULL);
547  ast_assert(record_handler != NULL);
548 
549  /* Try the DNS search. */
550  dns_response_len = dns_search_res(dname,
551  rr_class,
552  rr_type,
553  dns_response,
554  sizeof(dns_response));
555 
556  if (dns_response_len < 0) {
557  ast_debug(1, "DNS search failed for %s\n", dname);
558  response_handler(context, (unsigned char *)"", 0, NXDOMAIN);
559  return AST_DNS_SEARCH_FAILURE;
560  }
561 
562  /* Parse records from DNS response */
563  ret = dns_parse_answer_ex(context,
564  rr_class,
565  rr_type,
566  dns_response,
567  dns_response_len,
568  response_handler,
569  record_handler);
570 
571  /* Handle the return code from parsing the DNS response */
572  if (ret == AST_DNS_SEARCH_FAILURE) {
573  /* Parsing Error */
574  ast_log(LOG_WARNING, "DNS Parse error for %s\n", dname);
575  } else if (ret == AST_DNS_SEARCH_NO_RECORDS) {
576  /* No results found */
577  ast_debug(1, "DNS search yielded no results for %s\n", dname);
578  }
579 
580  return ret;
581 }
582 
584 {
585 #ifdef HAVE_RES_NINIT
586  struct __res_state dnsstate;
587 #endif
588  struct __res_state *state;
589  struct ao2_container *nameservers;
590  int i;
591 
593  if (!nameservers) {
594  return NULL;
595  }
596 
597 #ifdef HAVE_RES_NINIT
598  memset(&dnsstate, 0, sizeof(dnsstate));
599  res_ninit(&dnsstate);
600  state = &dnsstate;
601 #else
602  ast_mutex_lock(&res_lock);
603  res_init();
604  state = &_res;
605 #endif
606 
607  for (i = 0; i < state->nscount; i++) {
608  ast_str_container_add(nameservers, ast_inet_ntoa(state->nsaddr_list[i].sin_addr));
609  }
610 
611 #ifdef HAVE_RES_NINIT
612 #ifdef HAVE_RES_NDESTROY
613  res_ndestroy(&dnsstate);
614 #else
615  res_nclose(&dnsstate);
616 #endif
617 #else
618 #ifdef HAVE_RES_CLOSE
619  res_close();
620 #endif
621  ast_mutex_unlock(&res_lock);
622 #endif
623 
624  return nameservers;
625 }
unsigned ancount
Definition: dns.c:156
static const char type[]
Definition: chan_ooh323.c:109
enum sip_cc_notify_state state
Definition: chan_sip.c:959
unsigned arcount
Definition: dns.c:158
Asterisk main include file. File version handling, generic pbx functions.
static int dns_parse_answer_ex(void *context, int rr_class, int rr_type, unsigned char *answer, int answer_len, int(*response_handler)(void *context, unsigned char *dns_response, int dns_response_len, int rcode), int(*record_handler)(void *context, unsigned char *record, int record_len, int ttl))
Extended version of the DNS Parsing function.
Definition: dns.c:409
#define LOG_WARNING
Definition: logger.h:274
unsigned short size
Definition: dns.c:165
unsigned id
Definition: dns.c:125
#define ast_assert(a)
Definition: utils.h:695
#define ast_mutex_lock(a)
Definition: lock.h:187
#define NULL
Definition: resample.c:96
enum ast_dns_search_result ast_search_dns_ex(void *context, const char *dname, int rr_class, int rr_type, int(*response_handler)(void *context, unsigned char *dns_response, int dns_response_len, int rcode), int(*record_handler)(void *context, unsigned char *record, int record_len, int ttl))
Extended version of the DNS search function.
Definition: dns.c:538
static int dns_advance_field(unsigned char **dns_response, int remaining_len, int field_size)
Advances the position of the DNS response pointer by the size of the current field.
Definition: dns.c:223
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_log
Definition: astobj2.c:42
static int dns_search_res(const char *dname, int rr_class, int rr_type, unsigned char *dns_response, int dns_response_len)
Handles the DNS search if the system has RES_NINIT.
Definition: dns.c:287
General Asterisk PBX channel definitions.
struct ao2_container * ast_str_container_alloc_options(enum ao2_alloc_opts opts, int buckets)
Allocates a hash container for bare strings.
Definition: strings.c:201
ast_dns_search_result
DNS search return values.
Definition: dns.h:28
Asterisk architecture endianess compatibility definitions.
unsigned nscount
Definition: dns.c:157
static int answer(void *data)
Definition: chan_pjsip.c:682
Wrapper for network related headers, masking differences between various operating systems...
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
const char * ast_inet_ntoa(struct in_addr ia)
thread-safe replacement for inet_ntoa().
Definition: main/utils.c:782
unsigned short class
Definition: dns.c:163
unsigned int ttl
Definition: dns.c:164
static int skip_name(unsigned char *s, int len)
Tries to find the position of the next field in the DNS response.
Definition: dns.c:179
struct ao2_container * ast_dns_get_nameservers(void)
Retrieve the configured nameservers of the system.
Definition: dns.c:583
unsigned short rtype
Definition: dns.c:162
#define MAX_SIZE
The maximum size permitted for the answer from the DNS server.
Definition: dns.c:47
Generic container type.
unsigned qdcount
Definition: dns.c:155
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116
Definition: dns.c:161
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))
Lookup record in DNS.
Definition: dns.c:493
int ast_str_container_add(struct ao2_container *str_container, const char *add)
Adds a string to a string container allocated by ast_str_container_alloc.
Definition: strings.c:206
#define AST_MUTEX_DEFINE_STATIC(mutex)
Definition: lock.h:518
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:330
#define ast_mutex_unlock(a)
Definition: lock.h:188