Posted: Sat Sep 27, 2003 12:35 am Post subject: [Asterisk-cvs] asterisk dns.c,NONE,1.1
Update of /usr/cvsroot/asterisk
In directory mongoose.digium.com:/tmp/cvs-serv18700
Added Files:
dns.c
Log Message:
Add missing files
--- NEW FILE: dns.c ---
/*
* DNS Support for Asterisk
*
* Written by Thorsten Lockert <tholo@trollphone.org>
*
* Funding provided by Troll Phone Networks AS
*
* This program is free software, distributed under the terms of
* the GNU General Public License
*/
typedef struct {
unsigned id :16; /* query identification number */
#if BYTE_ORDER == BIG_ENDIAN
/* fields in third byte */
unsigned qr: 1; /* response flag */
unsigned opcode: 4; /* purpose of message */
unsigned aa: 1; /* authoritive answer */
unsigned tc: 1; /* truncated message */
unsigned rd: 1; /* recursion desired */
/* fields in fourth byte */
unsigned ra: 1; /* recursion available */
unsigned unused :1; /* unused bits (MBZ as of 4.9.3a3) */
unsigned ad: 1; /* authentic data from named */
unsigned cd: 1; /* checking disabled by resolver */
unsigned rcode :4; /* response code */
#endif
#if BYTE_ORDER == LITTLE_ENDIAN || BYTE_ORDER == PDP_ENDIAN
/* fields in third byte */
unsigned rd :1; /* recursion desired */
unsigned tc :1; /* truncated message */
unsigned aa :1; /* authoritive answer */
unsigned opcode :4; /* purpose of message */
unsigned qr :1; /* response flag */
/* fields in fourth byte */
unsigned rcode :4; /* response code */
unsigned cd: 1; /* checking disabled by resolver */
unsigned ad: 1; /* authentic data from named */
unsigned unused :1; /* unused bits (MBZ as of 4.9.3a3) */
unsigned ra :1; /* recursion available */
#endif
/* remaining bytes */
unsigned qdcount :16; /* number of question entries */
unsigned ancount :16; /* number of answer entries */
unsigned nscount :16; /* number of authority entries */
unsigned arcount :16; /* number of resource entries */
} dns_HEADER;
struct dn_answer {
unsigned short rtype;
unsigned short class;
unsigned int ttl;
unsigned short size;
} __attribute__ ((__packed__));
static int skip_name(u_char *s, int len)
{
int x = 0;
while (x < len) {
if (*s == '\0') {
s++;
x++;
break;
}
if ((*s & 0xc0) == 0xc0) {
s += 2;
x += 2;
break;
}
x += *s + 1;
s += *s + 1;
}
if (x >= len)
return -1;
return x;
}
static int dns_parse_answer(void *context,
int class, int type, u_char *answer, int len,
int (*callback)(void *context, u_char *answer, int len, u_char *fullanswer))
{
u_char *fullanswer = answer;
struct dn_answer *ans;
dns_HEADER *h;
int res;
int x;
h = (dns_HEADER *)answer;
answer += sizeof(dns_HEADER);
len -= sizeof(dns_HEADER);
for (x = 0; x < ntohs(h->qdcount); x++) {
if ((res = skip_name(answer, len)) < 0) {
ast_log(LOG_WARNING, "Couldn't skip over name\n");
return -1;
}
answer += res + 4; /* Skip name and QCODE / QCLASS */
len -= res + 4;
if (len < 0) {
ast_log(LOG_WARNING, "Strange query size\n");
return -1;
}
}
for (x = 0; x < ntohs(h->ancount); x++) {
if ((res = skip_name(answer, len)) < 0) {
ast_log(LOG_WARNING, "Failed skipping name\n");
return -1;
}
answer += res;
len -= res;
ans = (struct dn_answer *)answer;
answer += sizeof(struct dn_answer);
len -= sizeof(struct dn_answer);
if (len < 0) {
ast_log(LOG_WARNING, "Strange result size\n");
return -1;
}
if (len < 0) {
ast_log(LOG_WARNING, "Length exceeds frame\n");
return -1;
}
if (ntohs(ans->class) == class && ntohs(ans->rtype) == type) {
if (callback) {
if ((res = callback(context, answer, ntohs(ans->size), fullanswer)) < 0)
ast_log(LOG_WARNING, "Failed to parse result\n");
if (res > 0)
return 1;
}
}
answer += ntohs(ans->size);
len -= ntohs(ans->size);
}
return 0;
}
int ast_search_dns(void *context,
const char *dname, int class, int type,
int (*callback)(void *context, u_char *answer, int len, u_char *fullanswer))
{
#ifdef __Linux__
struct __res_state dnsstate;
#endif
char answer[MAX_SIZE];
int res, ret = -1;
#ifdef __Linux__
res_ninit(&dnsstate);
res = res_nsearch(&dnsstate, dname, class, type, answer, sizeof(answer));
#else
res_init();
res = res_search(dname, class, type, answer, sizeof(answer));
#endif
if (res > 0) {
if ((res = dns_parse_answer(context, class, type, answer, res, callback)) < 0) {
ast_log(LOG_WARNING, "Parse error\n");
ret = -1;
}
else if (ret == 0) {
ast_log(LOG_DEBUG, "No matches found\n");
ret = 0;
}
else
ret = 1;
}
#ifdef __Linux__
res_nclose(&srvstate);
#else
res_close();
#endif
return ret;
}
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum