00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036 #include "asterisk.h"
00037
00038 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 369001 $")
00039
00040 #include "asterisk/network.h"
00041 #include <arpa/nameser.h>
00042 #include <resolv.h>
00043
00044 #include "asterisk/channel.h"
00045 #include "asterisk/dns.h"
00046 #include "asterisk/endian.h"
00047
00048 #define MAX_SIZE 4096
00049
00050 #ifdef __PDP_ENDIAN
00051 #if __BYTE_ORDER == __PDP_ENDIAN
00052 #define DETERMINED_BYTE_ORDER __LITTLE_ENDIAN
00053 #endif
00054 #endif
00055 #if __BYTE_ORDER == __BIG_ENDIAN
00056 #define DETERMINED_BYTE_ORDER __BIG_ENDIAN
00057 #endif
00058 #if __BYTE_ORDER == __LITTLE_ENDIAN
00059 #define DETERMINED_BYTE_ORDER __LITTLE_ENDIAN
00060 #endif
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121 typedef struct {
00122 unsigned id:16;
00123 #if DETERMINED_BYTE_ORDER == __BIG_ENDIAN
00124
00125 unsigned qr:1;
00126 unsigned opcode:4;
00127 unsigned aa:1;
00128 unsigned tc:1;
00129 unsigned rd:1;
00130
00131 unsigned ra:1;
00132 unsigned unused:1;
00133 unsigned ad:1;
00134 unsigned cd:1;
00135 unsigned rcode:4;
00136 #endif
00137 #if DETERMINED_BYTE_ORDER == __LITTLE_ENDIAN
00138
00139 unsigned rd:1;
00140 unsigned tc:1;
00141 unsigned aa:1;
00142 unsigned opcode:4;
00143 unsigned qr:1;
00144
00145 unsigned rcode:4;
00146 unsigned cd:1;
00147 unsigned ad:1;
00148 unsigned unused:1;
00149 unsigned ra:1;
00150 #endif
00151
00152 unsigned qdcount:16;
00153 unsigned ancount:16;
00154 unsigned nscount:16;
00155 unsigned arcount:16;
00156 } dns_HEADER;
00157
00158 struct dn_answer {
00159 unsigned short rtype;
00160 unsigned short class;
00161 unsigned int ttl;
00162 unsigned short size;
00163 } __attribute__((__packed__));
00164
00165 static int skip_name(unsigned char *s, int len)
00166 {
00167 int x = 0;
00168
00169 while (x < len) {
00170 if (*s == '\0') {
00171 s++;
00172 x++;
00173 break;
00174 }
00175 if ((*s & 0xc0) == 0xc0) {
00176 s += 2;
00177 x += 2;
00178 break;
00179 }
00180 x += *s + 1;
00181 s += *s + 1;
00182 }
00183 if (x >= len)
00184 return -1;
00185 return x;
00186 }
00187
00188
00189 static int dns_parse_answer(void *context,
00190 int class, int type, unsigned char *answer, int len,
00191 int (*callback)(void *context, unsigned char *answer, int len, unsigned char *fullanswer))
00192 {
00193 unsigned char *fullanswer = answer;
00194 struct dn_answer *ans;
00195 dns_HEADER *h;
00196 int ret = 0;
00197 int res;
00198 int x;
00199
00200 h = (dns_HEADER *)answer;
00201 answer += sizeof(dns_HEADER);
00202 len -= sizeof(dns_HEADER);
00203
00204 for (x = 0; x < ntohs(h->qdcount); x++) {
00205 if ((res = skip_name(answer, len)) < 0) {
00206 ast_log(LOG_WARNING, "Couldn't skip over name\n");
00207 return -1;
00208 }
00209 answer += res + 4;
00210 len -= res + 4;
00211 if (len < 0) {
00212 ast_log(LOG_WARNING, "Strange query size\n");
00213 return -1;
00214 }
00215 }
00216
00217 for (x = 0; x < ntohs(h->ancount); x++) {
00218 if ((res = skip_name(answer, len)) < 0) {
00219 ast_log(LOG_WARNING, "Failed skipping name\n");
00220 return -1;
00221 }
00222 answer += res;
00223 len -= res;
00224 ans = (struct dn_answer *)answer;
00225 answer += sizeof(struct dn_answer);
00226 len -= sizeof(struct dn_answer);
00227 if (len < 0) {
00228 ast_log(LOG_WARNING, "Strange result size\n");
00229 return -1;
00230 }
00231 if (len < 0) {
00232 ast_log(LOG_WARNING, "Length exceeds frame\n");
00233 return -1;
00234 }
00235
00236 if (ntohs(ans->class) == class && ntohs(ans->rtype) == type) {
00237 if (callback) {
00238 if ((res = callback(context, answer, ntohs(ans->size), fullanswer)) < 0) {
00239 ast_log(LOG_WARNING, "Failed to parse result\n");
00240 return -1;
00241 }
00242 ret = 1;
00243 }
00244 }
00245 answer += ntohs(ans->size);
00246 len -= ntohs(ans->size);
00247 }
00248 return ret;
00249 }
00250
00251 #ifndef HAVE_RES_NINIT
00252 AST_MUTEX_DEFINE_STATIC(res_lock);
00253 #endif
00254
00255
00256
00257
00258
00259 int ast_search_dns(void *context,
00260 const char *dname, int class, int type,
00261 int (*callback)(void *context, unsigned char *answer, int len, unsigned char *fullanswer))
00262 {
00263 #ifdef HAVE_RES_NINIT
00264 struct __res_state dnsstate;
00265 #endif
00266 unsigned char answer[MAX_SIZE];
00267 int res, ret = -1;
00268
00269 #ifdef HAVE_RES_NINIT
00270 memset(&dnsstate, 0, sizeof(dnsstate));
00271 res_ninit(&dnsstate);
00272 res = res_nsearch(&dnsstate, dname, class, type, answer, sizeof(answer));
00273 #else
00274 ast_mutex_lock(&res_lock);
00275 res_init();
00276 res = res_search(dname, class, type, answer, sizeof(answer));
00277 #endif
00278 if (res > 0) {
00279 if ((res = dns_parse_answer(context, class, type, answer, res, callback)) < 0) {
00280 ast_log(LOG_WARNING, "DNS Parse error for %s\n", dname);
00281 ret = -1;
00282 } else if (res == 0) {
00283 ast_debug(1, "No matches found in DNS for %s\n", dname);
00284 ret = 0;
00285 } else
00286 ret = 1;
00287 }
00288 #ifdef HAVE_RES_NINIT
00289 #ifdef HAVE_RES_NDESTROY
00290 res_ndestroy(&dnsstate);
00291 #else
00292 res_nclose(&dnsstate);
00293 #endif
00294 #else
00295 #ifdef HAVE_RES_CLOSE
00296 res_close();
00297 #endif
00298 ast_mutex_unlock(&res_lock);
00299 #endif
00300
00301 return ret;
00302 }