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.
23 * \brief DNS Support for Asterisk
25 * \author Thorsten Lockert <tholo@trollphone.org>
28 * - DNR SRV records http://www.ietf.org/rfc/rfc2782.txt
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>
43 #include "asterisk/logger.h"
44 #include "asterisk/channel.h"
45 #include "asterisk/dns.h"
46 #include "asterisk/endian.h"
51 unsigned id
:16; /*!< query identification number */
52 #if __BYTE_ORDER == __BIG_ENDIAN
53 /* fields in third byte */
54 unsigned qr
:1; /*!< response flag */
55 unsigned opcode
:4; /*!< purpose of message */
56 unsigned aa
:1; /*!< authoritive answer */
57 unsigned tc
:1; /*!< truncated message */
58 unsigned rd
:1; /*!< recursion desired */
59 /* fields in fourth byte */
60 unsigned ra
:1; /*!< recursion available */
61 unsigned unused
:1; /*!< unused bits (MBZ as of 4.9.3a3) */
62 unsigned ad
:1; /*!< authentic data from named */
63 unsigned cd
:1; /*!< checking disabled by resolver */
64 unsigned rcode
:4; /*!< response code */
66 #if __BYTE_ORDER == __LITTLE_ENDIAN || __BYTE_ORDER == __PDP_ENDIAN
67 /* fields in third byte */
68 unsigned rd
:1; /*!< recursion desired */
69 unsigned tc
:1; /*!< truncated message */
70 unsigned aa
:1; /*!< authoritive answer */
71 unsigned opcode
:4; /*!< purpose of message */
72 unsigned qr
:1; /*!< response flag */
73 /* fields in fourth byte */
74 unsigned rcode
:4; /*!< response code */
75 unsigned cd
:1; /*!< checking disabled by resolver */
76 unsigned ad
:1; /*!< authentic data from named */
77 unsigned unused
:1; /*!< unused bits (MBZ as of 4.9.3a3) */
78 unsigned ra
:1; /*!< recursion available */
81 unsigned qdcount
:16; /*!< number of question entries */
82 unsigned ancount
:16; /*!< number of answer entries */
83 unsigned nscount
:16; /*!< number of authority entries */
84 unsigned arcount
:16; /*!< number of resource entries */
92 } __attribute__ ((__packed__
));
94 static int skip_name(unsigned char *s
, int len
)
104 if ((*s
& 0xc0) == 0xc0) {
117 /*! \brief Parse DNS lookup result, call callback */
118 static int dns_parse_answer(void *context
,
119 int class, int type
, unsigned char *answer
, int len
,
120 int (*callback
)(void *context
, unsigned char *answer
, int len
, unsigned char *fullanswer
))
122 unsigned char *fullanswer
= answer
;
123 struct dn_answer
*ans
;
128 h
= (dns_HEADER
*)answer
;
129 answer
+= sizeof(dns_HEADER
);
130 len
-= sizeof(dns_HEADER
);
132 for (x
= 0; x
< ntohs(h
->qdcount
); x
++) {
133 if ((res
= skip_name(answer
, len
)) < 0) {
134 ast_log(LOG_WARNING
, "Couldn't skip over name\n");
137 answer
+= res
+ 4; /* Skip name and QCODE / QCLASS */
140 ast_log(LOG_WARNING
, "Strange query size\n");
145 for (x
= 0; x
< ntohs(h
->ancount
); x
++) {
146 if ((res
= skip_name(answer
, len
)) < 0) {
147 ast_log(LOG_WARNING
, "Failed skipping name\n");
152 ans
= (struct dn_answer
*)answer
;
153 answer
+= sizeof(struct dn_answer
);
154 len
-= sizeof(struct dn_answer
);
156 ast_log(LOG_WARNING
, "Strange result size\n");
160 ast_log(LOG_WARNING
, "Length exceeds frame\n");
164 if (ntohs(ans
->class) == class && ntohs(ans
->rtype
) == type
) {
166 if ((res
= callback(context
, answer
, ntohs(ans
->size
), fullanswer
)) < 0) {
167 ast_log(LOG_WARNING
, "Failed to parse result\n");
174 answer
+= ntohs(ans
->size
);
175 len
-= ntohs(ans
->size
);
181 AST_MUTEX_DEFINE_STATIC(res_lock
);
184 /*! \brief Lookup record in DNS
185 \note Asterisk DNS is synchronus at this time. This means that if your DNS does
186 not work properly, Asterisk might not start properly or a channel may lock.
188 int ast_search_dns(void *context
,
189 const char *dname
, int class, int type
,
190 int (*callback
)(void *context
, unsigned char *answer
, int len
, unsigned char *fullanswer
))
193 struct __res_state dnsstate
;
195 unsigned char answer
[MAX_SIZE
];
199 res_ninit(&dnsstate
);
200 res
= res_nsearch(&dnsstate
, dname
, class, type
, answer
, sizeof(answer
));
202 ast_mutex_lock(&res_lock
);
204 res
= res_search(dname
, class, type
, answer
, sizeof(answer
));
207 if ((res
= dns_parse_answer(context
, class, type
, answer
, res
, callback
)) < 0) {
208 ast_log(LOG_WARNING
, "DNS Parse error for %s\n", dname
);
212 ast_log(LOG_DEBUG
, "No matches found in DNS for %s\n", dname
);
219 res_nclose(&dnsstate
);
224 ast_mutex_unlock(&res_lock
);