39 #include <arpa/nameser.h>
50 #if __BYTE_ORDER == __PDP_ENDIAN
51 #define DETERMINED_BYTE_ORDER __LITTLE_ENDIAN
54 #if __BYTE_ORDER == __BIG_ENDIAN
55 #define DETERMINED_BYTE_ORDER __BIG_ENDIAN
57 #if __BYTE_ORDER == __LITTLE_ENDIAN
58 #define DETERMINED_BYTE_ORDER __LITTLE_ENDIAN
61 #ifndef HAVE_RES_NINIT
62 AST_MUTEX_DEFINE_STATIC(res_lock);
126 #if DETERMINED_BYTE_ORDER == __BIG_ENDIAN
140 #if DETERMINED_BYTE_ORDER == __LITTLE_ENDIAN
163 unsigned short class;
166 } __attribute__((__packed__));
190 if ((*s & 0xc0) == 0xc0) {
225 if (dns_response == NULL || field_size < 0 || remaining_len < field_size) {
229 *dns_response += field_size;
230 remaining_len -= field_size;
232 return remaining_len;
235 #ifndef HAVE_RES_NINIT
250 static int dns_search_res(
const char *dname,
int rr_class,
int rr_type,
251 unsigned char *dns_response,
int dns_response_len)
256 ast_mutex_lock(&res_lock);
258 ret = res_search(dname,
264 #ifdef HAVE_RES_CLOSE
268 ast_mutex_unlock(&res_lock);
288 unsigned char *dns_response,
int dns_response_len)
292 struct __res_state dns_state;
294 memset(&dns_state, 0,
sizeof(dns_state));
295 res_ninit(&dns_state);
296 ret = res_nsearch(&dns_state,
303 #ifdef HAVE_RES_NDESTROY
304 res_ndestroy(&dns_state);
306 res_nclose(&dns_state);
330 int class,
int type,
unsigned char *answer,
int len,
331 int (*callback)(
void *context,
unsigned char *answer,
int len,
unsigned char *fullanswer))
333 unsigned char *fullanswer = answer;
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");
352 ast_log(LOG_WARNING,
"Strange query size\n");
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");
368 ast_log(LOG_WARNING,
"Length of DNS answer exceeds frame\n");
372 if (ntohs(ans->
class) ==
class && ntohs(ans->
rtype) == type) {
374 if ((res = callback(context, answer, ntohs(ans->
size), fullanswer)) < 0) {
375 ast_log(LOG_WARNING,
"Failed to parse result\n");
381 answer += ntohs(ans->
size);
382 len -= ntohs(ans->
size);
407 static 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))
411 unsigned char *dns_response = answer;
415 int res, x, pos, dns_response_len, ret;
417 dns_response_len = answer_len;
421 response_handler(context, dns_response, dns_response_len, ntohs(dns_header->rcode));
424 if (answer_len == 0) {
430 ast_log(LOG_WARNING,
"Length of DNS answer exceeds available search frames\n");
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");
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");
456 ast_log(LOG_WARNING,
"Length of DNS answer exceeds available search frames\n");
465 ast_log(LOG_WARNING,
"Length of DNS answer exceeds available search frames\n");
470 if (ntohs(ans->
class) == rr_class && ntohs(ans->
rtype) == rr_type) {
472 record_handler(context, answer, ntohs(ans->
size), ntohl(ans->
ttl));
492 const char *dname,
int class,
int type,
493 int (*callback)(
void *context,
unsigned char *answer,
int len,
unsigned char *fullanswer))
495 #ifdef HAVE_RES_NINIT
496 struct __res_state dnsstate;
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));
506 ast_mutex_lock(&res_lock);
508 res = res_search(dname,
class, type, answer,
sizeof(answer));
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);
514 }
else if (res == 0) {
515 ast_debug(1,
"No matches found in DNS for %s\n", dname);
520 #ifdef HAVE_RES_NINIT
521 #ifdef HAVE_RES_NDESTROY
522 res_ndestroy(&dnsstate);
524 res_nclose(&dnsstate);
527 #ifdef HAVE_RES_CLOSE
530 ast_mutex_unlock(&res_lock);
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))
540 int ret, dns_response_len;
541 unsigned char dns_response[
MAX_SIZE];
544 ast_assert(response_handler != NULL);
545 ast_assert(record_handler != NULL);
552 sizeof(dns_response));
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);
572 ast_log(LOG_WARNING,
"DNS Parse error for %s\n", dname);
575 ast_debug(1,
"DNS search yielded no results for %s\n", dname);
583 #ifdef HAVE_RES_NINIT
584 struct __res_state dnsstate;
586 struct __res_state *
state;
595 #ifdef HAVE_RES_NINIT
596 memset(&dnsstate, 0,
sizeof(dnsstate));
597 res_ninit(&dnsstate);
600 ast_mutex_lock(&res_lock);
605 for (i = 0; i < state->nscount; i++) {
606 char addr[INET6_ADDRSTRLEN];
607 const char *addrp = NULL;
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));
619 ast_debug(1,
"Discovered nameserver: %s\n", addrp);
624 #ifdef HAVE_RES_NINIT
625 #ifdef HAVE_RES_NDESTROY
626 res_ndestroy(&dnsstate);
628 res_nclose(&dnsstate);
631 #ifdef HAVE_RES_CLOSE
634 ast_mutex_unlock(&res_lock);
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.
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.
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.
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.
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.
ast_dns_search_result
DNS search return values.
Asterisk architecture endianess compatibility definitions.
#define ast_debug(level,...)
Log a DEBUG message.
Wrapper for network related headers, masking differences between various operating systems...
static int skip_name(unsigned char *s, int len)
Tries to find the position of the next field in the DNS response.
struct ao2_container * ast_dns_get_nameservers(void)
Retrieve the configured nameservers of the system.
#define MAX_SIZE
The maximum size permitted for the answer from the DNS server.
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.
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.
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.