Asterisk - The Open Source Telephony Project GIT-master-7e7a603
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#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
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
124typedef 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; /*!< authoritative 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; /*!< authoritative 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
161struct 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 * \return The position of the next field
177 * \retval -1 if there are no remaining fields
178 */
179static 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) {
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 * \return The remaining length in the DNS response
221 * \retval -1 there are no frames remaining in the DNS response
222 */
223static 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) {
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 * \return The length of the DNS response
248 * \retval -1 on search failure
249 */
250static 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 * \return The length of the DNS response
285 * \retval -1 on search failure
286 */
287static 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 class Record Class (see "man res_search").
320 * \param type Record type (see "man res_search").
321 * \param answer The full DNS response.
322 * \param len The length of the full DNS response.
323 * \param callback Callback function for handling the discovered resource records from the DNS search.
324 *
325 * \retval -1 on search failure
326 * \retval 0 on no records found
327 * \retval 1 on success
328 */
329static int dns_parse_answer(void *context,
330 int class, int type, unsigned char *answer, int len,
331 int (*callback)(void *context, unsigned char *answer, int len, unsigned char *fullanswer))
332{
333 unsigned char *fullanswer = answer;
334 struct dn_answer *ans;
335 dns_HEADER *h;
336 int ret = 0;
337 int res;
338 int x;
339
340 h = (dns_HEADER *)answer;
341 answer += sizeof(dns_HEADER);
342 len -= sizeof(dns_HEADER);
343
344 for (x = 0; x < ntohs(h->qdcount); x++) {
345 if ((res = skip_name(answer, len)) < 0) {
346 ast_log(LOG_WARNING, "Couldn't skip over name\n");
347 return -1;
348 }
349 answer += res + 4; /* Skip name and QCODE / QCLASS */
350 len -= res + 4;
351 if (len < 0) {
352 ast_log(LOG_WARNING, "Strange query size\n");
353 return -1;
354 }
355 }
356
357 for (x = 0; x < ntohs(h->ancount); x++) {
358 if ((res = skip_name(answer, len)) < 0) {
359 ast_log(LOG_WARNING, "Failed skipping name\n");
360 return -1;
361 }
362 answer += res;
363 len -= res;
364 ans = (struct dn_answer *)answer;
365 answer += sizeof(struct dn_answer);
366 len -= sizeof(struct dn_answer);
367 if (len < 0) {
368 ast_log(LOG_WARNING, "Length of DNS answer exceeds frame\n");
369 return -1;
370 }
371
372 if (ntohs(ans->class) == class && ntohs(ans->rtype) == type) {
373 if (callback) {
374 if ((res = callback(context, answer, ntohs(ans->size), fullanswer)) < 0) {
375 ast_log(LOG_WARNING, "Failed to parse result\n");
376 return -1;
377 }
378 ret = 1;
379 }
380 }
381 answer += ntohs(ans->size);
382 len -= ntohs(ans->size);
383 }
384 return ret;
385}
386
387/*!
388 * \brief Extended version of the DNS Parsing function.
389 *
390 * \details Parses the DNS lookup result and notifies the observer of each discovered
391 * resource record with the provided callback.
392 *
393 * \internal
394 *
395 * \param context Void pointer containing data to use in the callback functions.
396 * \param rr_class Record Class (see "man res_search").
397 * \param rr_type Record type (see "man res_search").
398 * \param answer The full DNS response.
399 * \param answer_len The length of the full DNS response.
400 * \param response_handler Callback function for handling the DNS response.
401 * \param record_handler Callback function for handling the discovered resource records from the DNS search.
402 *
403 * \retval -1 on search failure
404 * \retval 0 on no records found
405 * \retval 1 on success
406 */
407static int dns_parse_answer_ex(void *context, int rr_class, int rr_type, unsigned char *answer, int answer_len,
408 int (*response_handler)(void *context, unsigned char *dns_response, int dns_response_len, int rcode),
409 int (*record_handler)(void *context, unsigned char *record, int record_len, int ttl))
410{
411 unsigned char *dns_response = answer;
412 dns_HEADER *dns_header = (dns_HEADER *)answer;
413
414 struct dn_answer *ans;
415 int res, x, pos, dns_response_len, ret;
416
417 dns_response_len = answer_len;
419
420 /* Invoke the response_handler callback to notify the observer of the raw DNS response */
421 response_handler(context, dns_response, dns_response_len, ntohs(dns_header->rcode));
422
423 /* Verify there is something to parse */
424 if (answer_len == 0) {
425 return ret;
426 }
427
428 /* Try advancing the cursor for the dns header */
429 if ((pos = dns_advance_field(&answer, answer_len, sizeof(dns_HEADER))) < 0) {
430 ast_log(LOG_WARNING, "Length of DNS answer exceeds available search frames\n");
432 }
433
434 /* Skip domain name and QCODE / QCLASS */
435 for (x = 0; x < ntohs(dns_header->qdcount); x++) {
436 if ((res = skip_name(answer, pos)) < 0) {
437 ast_log(LOG_WARNING, "Failed skipping name\n");
439 }
440
441 /* Try advancing the cursor for the name and QCODE / QCLASS fields */
442 if ((pos = dns_advance_field(&answer, pos, res + 4)) < 0) {
444 }
445 }
446
447 /* Extract the individual records */
448 for (x = 0; x < ntohs(dns_header->ancount); x++) {
449 if ((res = skip_name(answer, pos)) < 0) {
450 ast_log(LOG_WARNING, "Failed skipping name\n");
452 }
453
454 /* Try advancing the cursor to the current record */
455 if ((pos = dns_advance_field(&answer, pos, res)) < 0) {
456 ast_log(LOG_WARNING, "Length of DNS answer exceeds available search frames\n");
458 }
459
460 /* Cast the current value for the answer pointer as a dn_answer struct */
461 ans = (struct dn_answer *) answer;
462
463 /* Try advancing the cursor to the end of the current record */
464 if ((pos = dns_advance_field(&answer, pos, sizeof(struct dn_answer))) < 0) {
465 ast_log(LOG_WARNING, "Length of DNS answer exceeds available search frames\n");
467 }
468
469 /* Skip over the records that do not have the same resource record class and type we care about */
470 if (ntohs(ans->class) == rr_class && ntohs(ans->rtype) == rr_type) {
471 /* Invoke the record handler callback to deliver the discovered record */
472 record_handler(context, answer, ntohs(ans->size), ntohl(ans->ttl));
473 /*At least one record was found */
475 }
476
477 /* Try and update the field to the next record, but ignore any errors that come
478 * back because this may be the end of the line. */
479 pos = dns_advance_field(&answer, pos, ntohs(ans->size));
480 }
481
482 return ret;
483}
484
485/*!
486 * \brief Lookup record in DNS
487 *
488 * \note Asterisk DNS is synchronus at this time. This means that if your DNS does not
489 * work properly, Asterisk might not start properly or a channel may lock.
490*/
492 const char *dname, int class, int type,
493 int (*callback)(void *context, unsigned char *answer, int len, unsigned char *fullanswer))
494{
495#ifdef HAVE_RES_NINIT
496 struct __res_state dnsstate;
497#endif
498 unsigned char answer[MAX_SIZE];
499 int res, ret = -1;
500
501#ifdef HAVE_RES_NINIT
502 memset(&dnsstate, 0, sizeof(dnsstate));
503 res_ninit(&dnsstate);
504 res = res_nsearch(&dnsstate, dname, class, type, answer, sizeof(answer));
505#else
506 ast_mutex_lock(&res_lock);
507 res_init();
508 res = res_search(dname, class, type, answer, sizeof(answer));
509#endif
510 if (res > 0) {
511 if ((res = dns_parse_answer(context, class, type, answer, res, callback)) < 0) {
512 ast_log(LOG_WARNING, "DNS Parse error for %s\n", dname);
513 ret = -1;
514 } else if (res == 0) {
515 ast_debug(1, "No matches found in DNS for %s\n", dname);
516 ret = 0;
517 } else
518 ret = 1;
519 }
520#ifdef HAVE_RES_NINIT
521#ifdef HAVE_RES_NDESTROY
522 res_ndestroy(&dnsstate);
523#else
524 res_nclose(&dnsstate);
525#endif
526#else
527#ifdef HAVE_RES_CLOSE
528 res_close();
529#endif
530 ast_mutex_unlock(&res_lock);
531#endif
532
533 return ret;
534}
535
536enum ast_dns_search_result ast_search_dns_ex(void *context, const char *dname, int rr_class, int rr_type,
537 int (*response_handler)(void *context, unsigned char *dns_response, int dns_response_len, int rcode),
538 int (*record_handler)(void *context, unsigned char *record, int record_len, int ttl))
539{
540 int ret, dns_response_len;
541 unsigned char dns_response[MAX_SIZE];
542
543 /* Assert that the callbacks are not NULL */
544 ast_assert(response_handler != NULL);
545 ast_assert(record_handler != NULL);
546
547 /* Try the DNS search. */
548 dns_response_len = dns_search_res(dname,
549 rr_class,
550 rr_type,
551 dns_response,
552 sizeof(dns_response));
553
554 if (dns_response_len < 0) {
555 ast_debug(1, "DNS search failed for %s\n", dname);
556 response_handler(context, (unsigned char *)"", 0, NXDOMAIN);
558 }
559
560 /* Parse records from DNS response */
562 rr_class,
563 rr_type,
564 dns_response,
565 dns_response_len,
566 response_handler,
567 record_handler);
568
569 /* Handle the return code from parsing the DNS response */
570 if (ret == AST_DNS_SEARCH_FAILURE) {
571 /* Parsing Error */
572 ast_log(LOG_WARNING, "DNS Parse error for %s\n", dname);
573 } else if (ret == AST_DNS_SEARCH_NO_RECORDS) {
574 /* No results found */
575 ast_debug(1, "DNS search yielded no results for %s\n", dname);
576 }
577
578 return ret;
579}
580
582{
583#ifdef HAVE_RES_NINIT
584 struct __res_state dnsstate;
585#endif
586 struct __res_state *state;
587 struct ao2_container *nameservers;
588 int i;
589
591 if (!nameservers) {
592 return NULL;
593 }
594
595#ifdef HAVE_RES_NINIT
596 memset(&dnsstate, 0, sizeof(dnsstate));
597 res_ninit(&dnsstate);
598 state = &dnsstate;
599#else
600 ast_mutex_lock(&res_lock);
601 res_init();
602 state = &_res;
603#endif
604
605 for (i = 0; i < state->nscount; i++) {
606 char addr[INET6_ADDRSTRLEN];
607 const char *addrp = NULL;
608
609 /* glibc sets sin_family to 0 when the nameserver is an IPv6 address */
610 if (state->nsaddr_list[i].sin_family) {
611 addrp = inet_ntop(AF_INET, &state->nsaddr_list[i].sin_addr, addr, sizeof(addr));
612#if defined(HAVE_RES_NINIT) && defined(HAVE_STRUCT___RES_STATE__U__EXT_NSADDRS)
613 } else if (state->_u._ext.nsaddrs[i]) {
614 addrp = inet_ntop(AF_INET6, &state->_u._ext.nsaddrs[i]->sin6_addr, addr, sizeof(addr));
615#endif
616 }
617
618 if (addrp) {
619 ast_debug(1, "Discovered nameserver: %s\n", addrp);
620 ast_str_container_add(nameservers, addrp);
621 }
622 }
623
624#ifdef HAVE_RES_NINIT
625#ifdef HAVE_RES_NDESTROY
626 res_ndestroy(&dnsstate);
627#else
628 res_nclose(&dnsstate);
629#endif
630#else
631#ifdef HAVE_RES_CLOSE
632 res_close();
633#endif
634 ast_mutex_unlock(&res_lock);
635#endif
636
637 return nameservers;
638}
Asterisk main include file. File version handling, generic pbx functions.
#define ast_log
Definition: astobj2.c:42
@ AO2_ALLOC_OPT_LOCK_NOLOCK
Definition: astobj2.h:367
enum cc_state state
Definition: ccss.c:393
static const char type[]
Definition: chan_ooh323.c:109
static int answer(void *data)
Definition: chan_pjsip.c:683
General Asterisk PBX channel definitions.
#define MAX_SIZE
The maximum size permitted for the answer from the DNS server.
Definition: dns.c:47
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
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:536
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
struct ao2_container * ast_dns_get_nameservers(void)
Retrieve the configured nameservers of the system.
Definition: dns.c:581
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:407
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:329
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:491
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
DNS support for Asterisk.
ast_dns_search_result
DNS search return values.
Definition: dns.h:28
@ AST_DNS_SEARCH_SUCCESS
Definition: dns.h:31
@ AST_DNS_SEARCH_FAILURE
Definition: dns.h:29
@ AST_DNS_SEARCH_NO_RECORDS
Definition: dns.h:30
Asterisk architecture endianess compatibility definitions.
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
#define ast_debug(level,...)
Log a DEBUG message.
#define LOG_WARNING
#define ast_mutex_unlock(a)
Definition: lock.h:190
#define ast_mutex_lock(a)
Definition: lock.h:189
#define AST_MUTEX_DEFINE_STATIC(mutex)
Definition: lock.h:520
Wrapper for network related headers, masking differences between various operating systems....
#define NULL
Definition: resample.c:96
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:200
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:205
Generic container type.
Definition: dns.c:161
unsigned short class
Definition: dns.c:163
unsigned int ttl
Definition: dns.c:164
unsigned short size
Definition: dns.c:165
unsigned short rtype
Definition: dns.c:162
unsigned nscount
Definition: dns.c:157
unsigned ancount
Definition: dns.c:156
unsigned id
Definition: dns.c:125
unsigned arcount
Definition: dns.c:158
unsigned qdcount
Definition: dns.c:155
#define ast_assert(a)
Definition: utils.h:739