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 #include "asterisk.h"
00033
00034 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 159808 $")
00035
00036 #include <sys/types.h>
00037 #include <sys/socket.h>
00038 #include <netinet/in.h>
00039 #include <arpa/nameser.h>
00040 #include <resolv.h>
00041 #include <unistd.h>
00042
00043 #include "asterisk/logger.h"
00044 #include "asterisk/channel.h"
00045 #include "asterisk/dns.h"
00046 #include "asterisk/endian.h"
00047
00048 #define MAX_SIZE 4096
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
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 typedef struct {
00110 unsigned id:16;
00111 #if __BYTE_ORDER == __BIG_ENDIAN
00112
00113 unsigned qr:1;
00114 unsigned opcode:4;
00115 unsigned aa:1;
00116 unsigned tc:1;
00117 unsigned rd:1;
00118
00119 unsigned ra:1;
00120 unsigned unused:1;
00121 unsigned ad:1;
00122 unsigned cd:1;
00123 unsigned rcode:4;
00124 #endif
00125 #if __BYTE_ORDER == __LITTLE_ENDIAN || __BYTE_ORDER == __PDP_ENDIAN
00126
00127 unsigned rd:1;
00128 unsigned tc:1;
00129 unsigned aa:1;
00130 unsigned opcode:4;
00131 unsigned qr:1;
00132
00133 unsigned rcode:4;
00134 unsigned cd:1;
00135 unsigned ad:1;
00136 unsigned unused:1;
00137 unsigned ra:1;
00138 #endif
00139
00140 unsigned qdcount:16;
00141 unsigned ancount:16;
00142 unsigned nscount:16;
00143 unsigned arcount:16;
00144 } dns_HEADER;
00145
00146 struct dn_answer {
00147 unsigned short rtype;
00148 unsigned short class;
00149 unsigned int ttl;
00150 unsigned short size;
00151 } __attribute__((__packed__));
00152
00153 static int skip_name(unsigned char *s, int len)
00154 {
00155 int x = 0;
00156
00157 while (x < len) {
00158 if (*s == '\0') {
00159 s++;
00160 x++;
00161 break;
00162 }
00163 if ((*s & 0xc0) == 0xc0) {
00164 s += 2;
00165 x += 2;
00166 break;
00167 }
00168 x += *s + 1;
00169 s += *s + 1;
00170 }
00171 if (x >= len)
00172 return -1;
00173 return x;
00174 }
00175
00176
00177 static int dns_parse_answer(void *context,
00178 int class, int type, unsigned char *answer, int len,
00179 int (*callback)(void *context, unsigned char *answer, int len, unsigned char *fullanswer))
00180 {
00181 unsigned char *fullanswer = answer;
00182 struct dn_answer *ans;
00183 dns_HEADER *h;
00184 int res;
00185 int x;
00186
00187 h = (dns_HEADER *)answer;
00188 answer += sizeof(dns_HEADER);
00189 len -= sizeof(dns_HEADER);
00190
00191 for (x = 0; x < ntohs(h->qdcount); x++) {
00192 if ((res = skip_name(answer, len)) < 0) {
00193 ast_log(LOG_WARNING, "Couldn't skip over name\n");
00194 return -1;
00195 }
00196 answer += res + 4;
00197 len -= res + 4;
00198 if (len < 0) {
00199 ast_log(LOG_WARNING, "Strange query size\n");
00200 return -1;
00201 }
00202 }
00203
00204 for (x = 0; x < ntohs(h->ancount); x++) {
00205 if ((res = skip_name(answer, len)) < 0) {
00206 ast_log(LOG_WARNING, "Failed skipping name\n");
00207 return -1;
00208 }
00209 answer += res;
00210 len -= res;
00211 ans = (struct dn_answer *)answer;
00212 answer += sizeof(struct dn_answer);
00213 len -= sizeof(struct dn_answer);
00214 if (len < 0) {
00215 ast_log(LOG_WARNING, "Strange result size\n");
00216 return -1;
00217 }
00218 if (len < 0) {
00219 ast_log(LOG_WARNING, "Length exceeds frame\n");
00220 return -1;
00221 }
00222
00223 if (ntohs(ans->class) == class && ntohs(ans->rtype) == type) {
00224 if (callback) {
00225 if ((res = callback(context, answer, ntohs(ans->size), fullanswer)) < 0) {
00226 ast_log(LOG_WARNING, "Failed to parse result\n");
00227 return -1;
00228 }
00229 if (res > 0)
00230 return 1;
00231 }
00232 }
00233 answer += ntohs(ans->size);
00234 len -= ntohs(ans->size);
00235 }
00236 return 0;
00237 }
00238
00239 #ifndef HAVE_RES_NINIT
00240 AST_MUTEX_DEFINE_STATIC(res_lock);
00241 #endif
00242
00243
00244
00245
00246
00247 int ast_search_dns(void *context,
00248 const char *dname, int class, int type,
00249 int (*callback)(void *context, unsigned char *answer, int len, unsigned char *fullanswer))
00250 {
00251 #ifdef HAVE_RES_NINIT
00252 struct __res_state dnsstate;
00253 #endif
00254 unsigned char answer[MAX_SIZE];
00255 int res, ret = -1;
00256
00257 #ifdef HAVE_RES_NINIT
00258 memset(&dnsstate, 0, sizeof(dnsstate));
00259 res_ninit(&dnsstate);
00260 res = res_nsearch(&dnsstate, dname, class, type, answer, sizeof(answer));
00261 #else
00262 ast_mutex_lock(&res_lock);
00263 res_init();
00264 res = res_search(dname, class, type, answer, sizeof(answer));
00265 #endif
00266 if (res > 0) {
00267 if ((res = dns_parse_answer(context, class, type, answer, res, callback)) < 0) {
00268 ast_log(LOG_WARNING, "DNS Parse error for %s\n", dname);
00269 ret = -1;
00270 }
00271 else if (res == 0) {
00272 ast_log(LOG_DEBUG, "No matches found in DNS for %s\n", dname);
00273 ret = 0;
00274 }
00275 else
00276 ret = 1;
00277 }
00278 #ifdef HAVE_RES_NINIT
00279 #ifdef HAVE_RES_NDESTROY
00280 res_ndestroy(&dnsstate);
00281 #else
00282 res_nclose(&dnsstate);
00283 #endif
00284 #else
00285 #ifndef __APPLE__
00286 res_close();
00287 #endif
00288 ast_mutex_unlock(&res_lock);
00289 #endif
00290
00291 return ret;
00292 }