Use WinDNS on Windows for DNS

This commit is contained in:
Asanka Herath
2010-05-26 10:17:28 -04:00
parent a750f29cda
commit 884f5ac627

View File

@@ -98,7 +98,7 @@ rk_dns_type_to_string(int type)
return NULL;
}
#if (defined(HAVE_RES_SEARCH) || defined(HAVE_RES_NSEARCH)) && defined(HAVE_DN_EXPAND)
#if ((defined(HAVE_RES_SEARCH) || defined(HAVE_RES_NSEARCH)) && defined(HAVE_DN_EXPAND)) || defined(HAVE_WINDNS)
static void
dns_free_rr(struct rk_resource_record *rr)
@@ -124,6 +124,8 @@ rk_dns_free_data(struct rk_dns_reply *r)
free (r);
}
#ifndef HAVE_WINDNS
static int
parse_record(const unsigned char *data, const unsigned char *end_data,
const unsigned char **pp, struct rk_resource_record **ret_rr)
@@ -605,6 +607,8 @@ rk_dns_lookup(const char *domain, const char *type_name)
return dns_lookup_int(domain, rk_ns_c_in, type);
}
#endif /* !HAVE_WINDNS */
static int
compare_srv(const void *a, const void *b)
{
@@ -708,6 +712,216 @@ rk_dns_srv_order(struct rk_dns_reply *r)
return;
}
#ifdef HAVE_WINDNS
#include <WinDNS.h>
static struct rk_resource_record *
parse_dns_record(PDNS_RECORD pRec)
{
struct rk_resource_record * rr;
if (pRec == NULL)
return NULL;
rr = calloc(1, sizeof(*rr));
rr->domain = strdup(pRec->pName);
rr->type = pRec->wType;
rr->class = 0;
rr->ttl = pRec->dwTtl;
rr->size = 0;
switch (rr->type) {
case rk_ns_t_ns:
case rk_ns_t_cname:
case rk_ns_t_ptr:
rr->u.txt = strdup(pRec->Data.NS.pNameHost);
if(rr->u.txt == NULL) {
dns_free_rr(rr);
return NULL;
}
break;
case rk_ns_t_mx:
case rk_ns_t_afsdb:{
size_t hostlen = strnlen(pRec->Data.MX.pNameExchange, DNS_MAX_NAME_LENGTH);
rr->u.mx = (struct mx_record *)malloc(sizeof(struct mx_record) +
hostlen);
if (rr->u.mx == NULL) {
dns_free_rr(rr);
return NULL;
}
strcpy_s(rr->u.mx->domain, hostlen + 1, pRec->Data.MX.pNameExchange);
rr->u.mx->preference = pRec->Data.MX.wPreference;
break;
}
case rk_ns_t_srv:{
size_t hostlen = strnlen(pRec->Data.SRV.pNameTarget, DNS_MAX_NAME_LENGTH);
rr->u.srv =
(struct srv_record*)malloc(sizeof(struct srv_record) +
hostlen);
if(rr->u.srv == NULL) {
dns_free_rr(rr);
return NULL;
}
rr->u.srv->priority = pRec->Data.SRV.wPriority;
rr->u.srv->weight = pRec->Data.SRV.wWeight;
rr->u.srv->port = pRec->Data.SRV.wPort;
strcpy_s(rr->u.srv->target, hostlen + 1, pRec->Data.SRV.pNameTarget);
break;
}
case rk_ns_t_txt:{
size_t len;
if (pRec->Data.TXT.dwStringCount == 0) {
rr->u.txt = strdup("");
break;
}
len = strnlen(pRec->Data.TXT.pStringArray[0], DNS_MAX_TEXT_STRING_LENGTH);
rr->u.txt = (char *)malloc(len + 1);
strcpy_s(rr->u.txt, len + 1, pRec->Data.TXT.pStringArray[0]);
break;
}
case rk_ns_t_key : {
size_t key_len;
if (pRec->wDataLength < 4) {
dns_free_rr(rr);
return NULL;
}
key_len = pRec->wDataLength - 4;
rr->u.key = malloc (sizeof(*rr->u.key) + key_len - 1);
if (rr->u.key == NULL) {
dns_free_rr(rr);
return NULL;
}
rr->u.key->flags = pRec->Data.KEY.wFlags;
rr->u.key->protocol = pRec->Data.KEY.chProtocol;
rr->u.key->algorithm = pRec->Data.KEY.chAlgorithm;
rr->u.key->key_len = key_len;
memcpy_s (rr->u.key->key_data, key_len,
pRec->Data.KEY.Key, key_len);
break;
}
case rk_ns_t_sig : {
size_t sig_len, hostlen;
if(pRec->wDataLength <= 18) {
dns_free_rr(rr);
return NULL;
}
sig_len = pRec->wDataLength;
hostlen = strnlen(pRec->Data.SIG.pNameSigner, DNS_MAX_NAME_LENGTH);
rr->u.sig = malloc(sizeof(*rr->u.sig)
+ hostlen + sig_len);
if (rr->u.sig == NULL) {
dns_free_rr(rr);
return NULL;
}
rr->u.sig->type = pRec->Data.SIG.wTypeCovered;
rr->u.sig->algorithm = pRec->Data.SIG.chAlgorithm;
rr->u.sig->labels = pRec->Data.SIG.chLabelCount;
rr->u.sig->orig_ttl = pRec->Data.SIG.dwOriginalTtl;
rr->u.sig->sig_expiration = pRec->Data.SIG.dwExpiration;
rr->u.sig->sig_inception = pRec->Data.SIG.dwTimeSigned;
rr->u.sig->key_tag = pRec->Data.SIG.wKeyTag;
rr->u.sig->sig_len = sig_len;
memcpy_s (rr->u.sig->sig_data, sig_len,
pRec->Data.SIG.Signature, sig_len);
rr->u.sig->signer = &rr->u.sig->sig_data[sig_len];
strcpy_s(rr->u.sig->signer, hostlen + 1, pRec->Data.SIG.pNameSigner);
break;
}
case rk_ns_t_ds: {
rr->u.ds = malloc (sizeof(*rr->u.ds) + pRec->Data.DS.wDigestLength - 1);
if (rr->u.ds == NULL) {
dns_free_rr(rr);
return NULL;
}
rr->u.ds->key_tag = pRec->Data.DS.wKeyTag;
rr->u.ds->algorithm = pRec->Data.DS.chAlgorithm;
rr->u.ds->digest_type = pRec->Data.DS.chDigestType;
rr->u.ds->digest_len = pRec->Data.DS.wDigestLength;
memcpy_s (rr->u.ds->digest_data, pRec->Data.DS.wDigestLength,
pRec->Data.DS.Digest, pRec->Data.DS.wDigestLength);
break;
}
default:
dns_free_rr(rr);
return NULL;
}
rr->next = parse_dns_record(pRec->pNext);
return rr;
}
ROKEN_LIB_FUNCTION struct rk_dns_reply * ROKEN_LIB_CALL
rk_dns_lookup(const char *domain, const char *type_name)
{
DNS_STATUS status;
int type;
PDNS_RECORD pRec = NULL;
struct rk_dns_reply * r = NULL;
__try {
type = rk_dns_string_to_type(type_name);
if(type == -1) {
if(_resolve_debug)
fprintf(stderr, "dns_lookup: unknown resource type: `%s'\n",
type_name);
return NULL;
}
status = DnsQuery_UTF8(domain, type, DNS_QUERY_STANDARD, NULL,
&pRec, NULL);
if (status != ERROR_SUCCESS)
return NULL;
r = calloc(1, sizeof(*r));
r->q.domain = strdup(domain);
r->q.type = type;
r->q.class = 0;
r->head = parse_dns_record(pRec);
if (r->head == NULL) {
rk_dns_free_data(r);
return NULL;
} else {
return r;
}
} __finally {
if (pRec)
DnsRecordListFree(pRec, DnsFreeRecordList);
}
}
#endif /* HAVE_WINDNS */
#else /* NOT defined(HAVE_RES_SEARCH) && defined(HAVE_DN_EXPAND) */
ROKEN_LIB_FUNCTION struct rk_dns_reply * ROKEN_LIB_CALL