Esempio n. 1
0
/******************************************************************************
 * DnsQuery_A           [DNSAPI.@]
 *
 */
DNS_STATUS WINAPI DnsQuery_A( PCSTR name, WORD type, DWORD options, PVOID servers,
                              PDNS_RECORDA *result, PVOID *reserved )
{
    WCHAR *nameW;
    DNS_RECORDW *resultW;
    DNS_STATUS status;

    TRACE( "(%s,%s,0x%08x,%p,%p,%p)\n", debugstr_a(name), dns_type_to_str( type ),
           options, servers, result, reserved );

    if (!name || !result)
        return ERROR_INVALID_PARAMETER;

    nameW = dns_strdup_aw( name );
    if (!nameW) return ERROR_NOT_ENOUGH_MEMORY;

    status = DnsQuery_W( nameW, type, options, servers, &resultW, reserved ); 

    if (status == ERROR_SUCCESS)
    {
        *result = (DNS_RECORDA *)DnsRecordSetCopyEx(
             (DNS_RECORD *)resultW, DnsCharSetUnicode, DnsCharSetAnsi );

        if (!*result) status = ERROR_NOT_ENOUGH_MEMORY;
        DnsRecordListFree( (DNS_RECORD *)resultW, DnsFreeRecordList );
    }

    dns_free( nameW );
    return status;
}
Esempio n. 2
0
QT_BEGIN_NAMESPACE

void QDnsLookupRunnable::query(const int requestType, const QByteArray &requestName, const QHostAddress &nameserver, QDnsLookupReply *reply)
{
    // Perform DNS query.
    PDNS_RECORD dns_records = 0;
    const QString requestNameUtf16 = QString::fromUtf8(requestName.data(), requestName.size());
    IP4_ARRAY srvList;
    memset(&srvList, 0, sizeof(IP4_ARRAY));
    if (!nameserver.isNull()) {
        if (nameserver.protocol() == QAbstractSocket::IPv4Protocol) {
            // The below code is referenced from: http://support.microsoft.com/kb/831226
            srvList.AddrCount = 1;
            srvList.AddrArray[0] = htonl(nameserver.toIPv4Address());
        } else if (nameserver.protocol() == QAbstractSocket::IPv6Protocol) {
            // For supoprting IPv6 nameserver addresses, we'll need to switch
            // from DnsQuey() to DnsQueryEx() as it supports passing an IPv6
            // address in the nameserver list
            qWarning() << Q_FUNC_INFO << "IPv6 addresses for nameservers is currently not supported";
            reply->error = QDnsLookup::ResolverError;
            reply->errorString = tr("IPv6 addresses for nameservers is currently not supported");
            return;
        }
    }
    const DNS_STATUS status = DnsQuery_W(reinterpret_cast<const wchar_t*>(requestNameUtf16.utf16()), requestType, DNS_QUERY_STANDARD, &srvList, &dns_records, NULL);
    switch (status) {
    case ERROR_SUCCESS:
        break;
    case DNS_ERROR_RCODE_FORMAT_ERROR:
        reply->error = QDnsLookup::InvalidRequestError;
        reply->errorString = tr("Server could not process query");
        return;
    case DNS_ERROR_RCODE_SERVER_FAILURE:
        reply->error = QDnsLookup::ServerFailureError;
        reply->errorString = tr("Server failure");
        return;
    case DNS_ERROR_RCODE_NAME_ERROR:
        reply->error = QDnsLookup::NotFoundError;
        reply->errorString = tr("Non existent domain");
        return;
    case DNS_ERROR_RCODE_REFUSED:
        reply->error = QDnsLookup::ServerRefusedError;
        reply->errorString = tr("Server refused to answer");
        return;
    default:
        reply->error = QDnsLookup::InvalidReplyError;
        reply->errorString = QSystemError(status, QSystemError::NativeError).toString();
        return;
    }

    // Extract results.
    for (PDNS_RECORD ptr = dns_records; ptr != NULL; ptr = ptr->pNext) {
        const QString name = QUrl::fromAce( QString::fromWCharArray( ptr->pName ).toLatin1() );
        if (ptr->wType == QDnsLookup::A) {
            QDnsHostAddressRecord record;
            record.d->name = name;
            record.d->timeToLive = ptr->dwTtl;
            record.d->value = QHostAddress(ntohl(ptr->Data.A.IpAddress));
            reply->hostAddressRecords.append(record);
        } else if (ptr->wType == QDnsLookup::AAAA) {
            Q_IPV6ADDR addr;
            memcpy(&addr, &ptr->Data.AAAA.Ip6Address, sizeof(Q_IPV6ADDR));

            QDnsHostAddressRecord record;
            record.d->name = name;
            record.d->timeToLive = ptr->dwTtl;
            record.d->value = QHostAddress(addr);
            reply->hostAddressRecords.append(record);
        } else if (ptr->wType == QDnsLookup::CNAME) {
            QDnsDomainNameRecord record;
            record.d->name = name;
            record.d->timeToLive = ptr->dwTtl;
            record.d->value = QUrl::fromAce(QString::fromWCharArray(ptr->Data.Cname.pNameHost).toLatin1());
            reply->canonicalNameRecords.append(record);
        } else if (ptr->wType == QDnsLookup::MX) {
            QDnsMailExchangeRecord record;
            record.d->name = name;
            record.d->exchange = QUrl::fromAce(QString::fromWCharArray(ptr->Data.Mx.pNameExchange).toLatin1());
            record.d->preference = ptr->Data.Mx.wPreference;
            record.d->timeToLive = ptr->dwTtl;
            reply->mailExchangeRecords.append(record);
        } else if (ptr->wType == QDnsLookup::NS) {
            QDnsDomainNameRecord record;
            record.d->name = name;
            record.d->timeToLive = ptr->dwTtl;
            record.d->value = QUrl::fromAce(QString::fromWCharArray(ptr->Data.Ns.pNameHost).toLatin1());
            reply->nameServerRecords.append(record);
        } else if (ptr->wType == QDnsLookup::PTR) {
            QDnsDomainNameRecord record;
            record.d->name = name;
            record.d->timeToLive = ptr->dwTtl;
            record.d->value = QUrl::fromAce(QString::fromWCharArray(ptr->Data.Ptr.pNameHost).toLatin1());
            reply->pointerRecords.append(record);
        } else if (ptr->wType == QDnsLookup::SRV) {
            QDnsServiceRecord record;
            record.d->name = name;
            record.d->target = QUrl::fromAce(QString::fromWCharArray(ptr->Data.Srv.pNameTarget).toLatin1());
            record.d->port = ptr->Data.Srv.wPort;
            record.d->priority = ptr->Data.Srv.wPriority;
            record.d->timeToLive = ptr->dwTtl;
            record.d->weight = ptr->Data.Srv.wWeight;
            reply->serviceRecords.append(record);
        } else if (ptr->wType == QDnsLookup::TXT) {
            QDnsTextRecord record;
            record.d->name = name;
            record.d->timeToLive = ptr->dwTtl;
            for (unsigned int i = 0; i < ptr->Data.Txt.dwStringCount; ++i) {
                record.d->values << QString::fromWCharArray((ptr->Data.Txt.pStringArray[i])).toLatin1();;
            }
            reply->textRecords.append(record);
        }
    }

    DnsRecordListFree(dns_records, DnsFreeRecordList);
}
Esempio n. 3
0
PDNS_BLOB
WINAPI
SaBlob_Query(IN LPWSTR Name,
             IN WORD DnsType,
             IN ULONG Flags,
             IN PVOID *Reserved,
             IN DWORD AddressFamily)
{
    PDNS_RECORD DnsRecord = NULL;
    INT ErrorCode;
    PDNS_BLOB DnsBlob = NULL;
    LPWSTR LocalName, LocalNameCopy;

    /* If they want reserved data back, clear it out in case we fail */
    if (Reserved) *Reserved = NULL;

    /* Query DNS */
    ErrorCode = DnsQuery_W(Name,
                           DnsType,
                           Flags,
                           NULL,
                           &DnsRecord,
                           Reserved);
    if (ErrorCode != ERROR_SUCCESS)
    {
        /* We failed... did the caller use reserved data? */
        if (Reserved && *Reserved)
        {
            /* He did, and it was valid. Free it */
            DnsApiFree(*Reserved);
            *Reserved = NULL;
        }

        /* Normalize error code */
        if (ErrorCode == RPC_S_SERVER_UNAVAILABLE) ErrorCode = WSATRY_AGAIN;
        goto Quickie;
    }

    /* Now create the Blob from the DNS Records */
    DnsBlob = SaBlob_CreateFromRecords(DnsRecord, TRUE, DnsType);
    if (!DnsBlob)
    {
        /* Failed, get error code */
        ErrorCode = GetLastError();
        goto Quickie;
    }

    /* Make sure it has a name */
    if (!DnsBlob->Name)
    {
        /* It doesn't, fail */
        ErrorCode = DNS_INFO_NO_RECORDS;
        goto Quickie;
    }

    /* Check if the name is local or loopback */
    if (!(DnsNameCompare_W(DnsBlob->Name, L"localhost")) &&
        !(DnsNameCompare_W(DnsBlob->Name, L"loopback")))
    {
        /* Nothing left to do, exit! */
        goto Quickie;
    }

    /* This is a local name...query it */
    LocalName = DnsQueryConfigAllocEx(DnsConfigFullHostName_W, NULL, NULL);
    if (LocalName)
    {
        /* Create a copy for the caller */
        LocalNameCopy = Dns_CreateStringCopy_W(LocalName);
        if (LocalNameCopy)
        {
            /* Overwrite the one in the blob */
            DnsBlob->Name = LocalNameCopy;
        }
        else
        {
            /* We failed to make a copy, free memory */
            DnsApiFree(LocalName);
        }
    }

Quickie:
    /* Free the DNS Record if we have one */
    if (DnsRecord) DnsRecordListFree(DnsRecord, DnsFreeRecordList);

    /* Check if this is a failure path with an active blob */
    if ((ErrorCode != ERROR_SUCCESS) && (DnsBlob))
    {
        /* Free the blob */
        SaBlob_Free(DnsBlob);
        DnsBlob = NULL;
    }

    /* Set the last error and return */
    SetLastError(ErrorCode);
    return DnsBlob;
}
Esempio n. 4
0
int getAFSServerW(const cm_unichar_t *service, const cm_unichar_t *protocol, const cm_unichar_t *cellName,
                  unsigned short afsdbPort, /* network byte order */
                  int *cellHostAddrs,
                  cm_unichar_t cellHostNames[][MAXHOSTCHARS], 
                  unsigned short ports[],   /* network byte order */
                  unsigned short ipRanks[],
                  int *numServers, int *ttl)
{
#ifdef DNSAPI_ENV
    PDNS_RECORDW pDnsCell, pDnsIter, pDnsVol,pDnsVolIter, pDnsCIter;
    int i;
    cm_unichar_t query[1024];

    *numServers = 0;
    *ttl = 0;

    if (service == NULL || protocol == NULL || cellName == NULL)
        return -1;

#ifdef AFS_FREELANCE_CLIENT
    if ( cm_stricmp_utf16(cellName, L"Freelance.Local.Root") == 0 )
        return -1;
#endif /* AFS_FREELANCE_CLIENT */

    /* query the SRV _afs3-vlserver._udp records of cell */
    StringCbPrintfW(query, sizeof(query), L"_%S._%S.%S", service, protocol, cellName);
    if (query[wcslen(query)-1] != L'.') {
        StringCbCatW(query, sizeof(query), L".");
    }

    if (DnsQuery_W(query, DNS_TYPE_SRV, DNS_QUERY_STANDARD, NULL, (PDNS_RECORD *) &pDnsCell,
                   NULL) == ERROR_SUCCESS) {
        /* go through the returned records */
        for (pDnsIter = pDnsCell; pDnsIter; pDnsIter = pDnsIter->pNext) {
            /* if we find an SRV record, we found a service instance */
            if (pDnsIter->wType == DNS_TYPE_SRV) {
                StringCbCopyW(cellHostNames[*numServers], sizeof(cellHostNames[*numServers]),
                              pDnsIter->Data.SRV.pNameTarget);
                ipRanks[*numServers] = pDnsIter->Data.SRV.wPriority;
                ports[*numServers] = htons(pDnsIter->Data.SRV.wPort);
                (*numServers)++;
                
                if (!*ttl) 
                    *ttl = pDnsIter->dwTtl;
                if (*numServers == AFSMAXCELLHOSTS) 
                    break;
            }
        }

        for (i=0;i<*numServers;i++) 
            cellHostAddrs[i] = 0;

        /* now check if there are any A records in the results */
        for (pDnsIter = pDnsCell; pDnsIter; pDnsIter = pDnsIter->pNext) {
            if(pDnsIter->wType == DNS_TYPE_A)
                /* check if its for one of the service instances */
                for (i=0;i<*numServers;i++)
                    if(cm_stricmp_utf16(pDnsIter->pName, cellHostNames[i]) == 0)
                        cellHostAddrs[i] = pDnsIter->Data.A.IpAddress;
        }

        for (i=0;i<*numServers;i++) {
            /* if we don't have an IP yet, then we should try resolving the service hostname
            in a separate query. */
            if (!cellHostAddrs[i]) {
                if (DnsQuery_W(cellHostNames[i], DNS_TYPE_A, DNS_QUERY_STANDARD, NULL,
                               (PDNS_RECORD *) &pDnsVol, NULL) == ERROR_SUCCESS) {
                    for (pDnsVolIter = pDnsVol; pDnsVolIter; pDnsVolIter=pDnsVolIter->pNext) {
                        /* if we get an A record, keep it */
                        if (pDnsVolIter->wType == DNS_TYPE_A && cm_stricmp_utf16(cellHostNames[i], pDnsVolIter->pName)==0) {
                            cellHostAddrs[i] = pDnsVolIter->Data.A.IpAddress;
                            break;
                        }
                        /* if we get a CNAME, look for a corresponding A record */
                        if (pDnsVolIter->wType == DNS_TYPE_CNAME && cm_stricmp_utf16(cellHostNames[i], pDnsVolIter->pName)==0) {
                            for (pDnsCIter=pDnsVolIter; pDnsCIter; pDnsCIter=pDnsCIter->pNext) {
                                if (pDnsCIter->wType == DNS_TYPE_A && cm_stricmp_utf16(pDnsVolIter->Data.CNAME.pNameHost, pDnsCIter->pName)==0) {
                                    cellHostAddrs[i] = pDnsCIter->Data.A.IpAddress;
                                    break;
                                }
                            }
                            if (cellHostAddrs[i]) 
                                break;
                            /* TODO: if the additional section is missing, then do another lookup for the CNAME */
                        }
                    }
                    /* we are done with the service lookup */
                    DnsRecordListFree((PDNS_RECORD) pDnsVol, DnsFreeRecordListDeep);
                }
            }
        }
        DnsRecordListFree((PDNS_RECORD) pDnsCell, DnsFreeRecordListDeep);
    }
    else {
        /* query the AFSDB records of cell */
        StringCbCopyW(query, sizeof(query), cellName);
        if (query[wcslen(query)-1] != L'.') {
            StringCbCatW(query, sizeof(query), L".");
        }

        if (DnsQuery_W(query, DNS_TYPE_AFSDB, DNS_QUERY_STANDARD, NULL, (PDNS_RECORD *) &pDnsCell,
                       NULL) == ERROR_SUCCESS) {
            /* go through the returned records */
            for (pDnsIter = pDnsCell;pDnsIter; pDnsIter = pDnsIter->pNext) {
                /* if we find an AFSDB record with Preference set to 1, we found a service instance */
                if (pDnsIter->wType == DNS_TYPE_AFSDB && pDnsIter->Data.Afsdb.wPreference == 1) {
                    StringCbCopyW(cellHostNames[*numServers], sizeof(cellHostNames[*numServers]),
                                  pDnsIter->Data.Afsdb.pNameExchange);
                    ipRanks[*numServers] = 0;
                    ports[*numServers] = afsdbPort;
                    (*numServers)++;
                
                    if (!*ttl) 
                        *ttl = pDnsIter->dwTtl;
                    if (*numServers == AFSMAXCELLHOSTS) 
                        break;
                }
            }

            for (i=0;i<*numServers;i++) 
                cellHostAddrs[i] = 0;

            /* now check if there are any A records in the results */
            for (pDnsIter = pDnsCell; pDnsIter; pDnsIter = pDnsIter->pNext) {
                if(pDnsIter->wType == DNS_TYPE_A)
                    /* check if its for one of the service instances */
                    for (i=0;i<*numServers;i++)
                        if(cm_stricmp_utf16(pDnsIter->pName, cellHostNames[i]) == 0)
                            cellHostAddrs[i] = pDnsIter->Data.A.IpAddress;
            }

            for (i=0;i<*numServers;i++) {
                /* if we don't have an IP yet, then we should try resolving the service hostname
                in a separate query. */
                if (!cellHostAddrs[i]) {
                    if (DnsQuery_W(cellHostNames[i], DNS_TYPE_A, DNS_QUERY_STANDARD, NULL,
                                   (PDNS_RECORD *) &pDnsVol, NULL) == ERROR_SUCCESS) {
                        for (pDnsVolIter = pDnsVol; pDnsVolIter; pDnsVolIter=pDnsVolIter->pNext) {
                            /* if we get an A record, keep it */
                            if (pDnsVolIter->wType == DNS_TYPE_A && cm_stricmp_utf16(cellHostNames[i], pDnsVolIter->pName)==0) {
                                cellHostAddrs[i] = pDnsVolIter->Data.A.IpAddress;
                                break;
                            }
                            /* if we get a CNAME, look for a corresponding A record */
                            if (pDnsVolIter->wType == DNS_TYPE_CNAME && cm_stricmp_utf16(cellHostNames[i], pDnsVolIter->pName)==0) {
                                for (pDnsCIter=pDnsVolIter; pDnsCIter; pDnsCIter=pDnsCIter->pNext) {
                                    if (pDnsCIter->wType == DNS_TYPE_A && cm_stricmp_utf16(pDnsVolIter->Data.CNAME.pNameHost, pDnsCIter->pName)==0) {
                                        cellHostAddrs[i] = pDnsCIter->Data.A.IpAddress;
                                        break;
                                    }
                                }
                                if (cellHostAddrs[i]) 
                                    break;
                                /* TODO: if the additional section is missing, then do another lookup for the CNAME */
                            }
                        }
                        /* we are done with the service lookup */
                        DnsRecordListFree((PDNS_RECORD) pDnsVol, DnsFreeRecordListDeep);
                    }
                }
            }
            DnsRecordListFree((PDNS_RECORD) pDnsCell, DnsFreeRecordListDeep);
        }
    }

    if ( *numServers > 0 )
        return 0;
    else        
#endif  /* DNSAPI_ENV */
        return -1;
}
Esempio n. 5
0
QT_BEGIN_NAMESPACE

void QDnsLookupRunnable::query(const int requestType, const QByteArray &requestName, QDnsLookupReply *reply)
{
    // Perform DNS query.
    PDNS_RECORD dns_records = 0;
    const QString requestNameUtf16 = QString::fromUtf8(requestName.data(), requestName.size());
    const DNS_STATUS status = DnsQuery_W(reinterpret_cast<const wchar_t*>(requestNameUtf16.utf16()), requestType, DNS_QUERY_STANDARD, NULL, &dns_records, NULL);
    switch (status) {
    case ERROR_SUCCESS:
        break;
    case DNS_ERROR_RCODE_FORMAT_ERROR:
        reply->error = QDnsLookup::InvalidRequestError;
        reply->errorString = tr("Server could not process query");
        return;
    case DNS_ERROR_RCODE_SERVER_FAILURE:
        reply->error = QDnsLookup::ServerFailureError;
        reply->errorString = tr("Server failure");
        return;
    case DNS_ERROR_RCODE_NAME_ERROR:
        reply->error = QDnsLookup::NotFoundError;
        reply->errorString = tr("Non existent domain");
        return;
    case DNS_ERROR_RCODE_REFUSED:
        reply->error = QDnsLookup::ServerRefusedError;
        reply->errorString = tr("Server refused to answer");
        return;
    default:
        reply->error = QDnsLookup::InvalidReplyError;
        reply->errorString = QSystemError(status, QSystemError::NativeError).toString();
        return;
    }

    // Extract results.
    for (PDNS_RECORD ptr = dns_records; ptr != NULL; ptr = ptr->pNext) {
        const QString name = QUrl::fromAce( QString::fromWCharArray( ptr->pName ).toLatin1() );
        if (ptr->wType == QDnsLookup::A) {
            QDnsHostAddressRecord record;
            record.d->name = name;
            record.d->timeToLive = ptr->dwTtl;
            record.d->value = QHostAddress(ntohl(ptr->Data.A.IpAddress));
            reply->hostAddressRecords.append(record);
        } else if (ptr->wType == QDnsLookup::AAAA) {
            Q_IPV6ADDR addr;
            memcpy(&addr, &ptr->Data.AAAA.Ip6Address, sizeof(Q_IPV6ADDR));

            QDnsHostAddressRecord record;
            record.d->name = name;
            record.d->timeToLive = ptr->dwTtl;
            record.d->value = QHostAddress(addr);
            reply->hostAddressRecords.append(record);
        } else if (ptr->wType == QDnsLookup::CNAME) {
            QDnsDomainNameRecord record;
            record.d->name = name;
            record.d->timeToLive = ptr->dwTtl;
            record.d->value = QUrl::fromAce(QString::fromWCharArray(ptr->Data.Cname.pNameHost).toLatin1());
            reply->canonicalNameRecords.append(record);
        } else if (ptr->wType == QDnsLookup::MX) {
            QDnsMailExchangeRecord record;
            record.d->name = name;
            record.d->exchange = QUrl::fromAce(QString::fromWCharArray(ptr->Data.Mx.pNameExchange).toLatin1());
            record.d->preference = ptr->Data.Mx.wPreference;
            record.d->timeToLive = ptr->dwTtl;
            reply->mailExchangeRecords.append(record);
        } else if (ptr->wType == QDnsLookup::NS) {
            QDnsDomainNameRecord record;
            record.d->name = name;
            record.d->timeToLive = ptr->dwTtl;
            record.d->value = QUrl::fromAce(QString::fromWCharArray(ptr->Data.Ns.pNameHost).toLatin1());
            reply->nameServerRecords.append(record);
        } else if (ptr->wType == QDnsLookup::PTR) {
            QDnsDomainNameRecord record;
            record.d->name = name;
            record.d->timeToLive = ptr->dwTtl;
            record.d->value = QUrl::fromAce(QString::fromWCharArray(ptr->Data.Ptr.pNameHost).toLatin1());
            reply->pointerRecords.append(record);
        } else if (ptr->wType == QDnsLookup::SRV) {
            QDnsServiceRecord record;
            record.d->name = name;
            record.d->target = QUrl::fromAce(QString::fromWCharArray(ptr->Data.Srv.pNameTarget).toLatin1());
            record.d->port = ptr->Data.Srv.wPort;
            record.d->priority = ptr->Data.Srv.wPriority;
            record.d->timeToLive = ptr->dwTtl;
            record.d->weight = ptr->Data.Srv.wWeight;
            reply->serviceRecords.append(record);
        } else if (ptr->wType == QDnsLookup::TXT) {
            QDnsTextRecord record;
            record.d->name = name;
            record.d->timeToLive = ptr->dwTtl;
            for (unsigned int i = 0; i < ptr->Data.Txt.dwStringCount; ++i) {
                record.d->values << QString::fromWCharArray((ptr->Data.Txt.pStringArray[i])).toLatin1();;
            }
            reply->textRecords.append(record);
        }
    }

    DnsRecordListFree(dns_records, DnsFreeRecordList);
}
Esempio n. 6
0
int getAFSServerW(cm_unichar_t *cellName, int *cellHostAddrs,
                  cm_unichar_t cellHostNames[][MAXHOSTCHARS], 
                  int *numServers, int *ttl)
{
#ifdef DNSAPI_ENV
    PDNS_RECORDW pDnsCell, pDnsIter, pDnsVol,pDnsVolIter, pDnsCIter;
    int i;
    struct sockaddr_in vlSockAddr;
    cm_unichar_t query[1024];

#ifdef AFS_FREELANCE_CLIENT
    if ( cm_stricmp_utf16(cellName, L"Freelance.Local.Root") == 0 )
        return -1;
#endif /* AFS_FREELANCE_CLIENT */

    *numServers = 0; 
    *ttl = 0;

    /* query the AFSDB records of cell */
    StringCbCopyW(query, sizeof(query), cellName);
    if (query[wcslen(query)-1] != L'.') {
        StringCbCatW(query, sizeof(query), L".");
    }

    if (DnsQuery_W(query, DNS_TYPE_AFSDB, DNS_QUERY_STANDARD, NULL, (PDNS_RECORD *) &pDnsCell,
                   NULL) == ERROR_SUCCESS) {
        memset((void*) &vlSockAddr, 0, sizeof(vlSockAddr));

        /* go through the returned records */
        for (pDnsIter = pDnsCell;pDnsIter; pDnsIter = pDnsIter->pNext) {
            /* if we find an AFSDB record with Preference set to 1, we found a volserver */
            if (pDnsIter->wType == DNS_TYPE_AFSDB && pDnsIter->Data.Afsdb.wPreference == 1) {
                StringCbCopyW(cellHostNames[*numServers], sizeof(cellHostNames[*numServers]),
                              pDnsIter->Data.Afsdb.pNameExchange);
                (*numServers)++;
                
                if (!*ttl) 
                    *ttl = pDnsIter->dwTtl;
                if (*numServers == AFSMAXCELLHOSTS) 
                    break;
            }
        }

        for (i=0;i<*numServers;i++) 
            cellHostAddrs[i] = 0;

        /* now check if there are any A records in the results */
        for (pDnsIter = pDnsCell; pDnsIter; pDnsIter = pDnsIter->pNext) {
            if(pDnsIter->wType == DNS_TYPE_A)
                /* check if its for one of the volservers */
                for (i=0;i<*numServers;i++)
                    if(cm_stricmp_utf16(pDnsIter->pName, cellHostNames[i]) == 0)
                        cellHostAddrs[i] = pDnsIter->Data.A.IpAddress;
        }

        for (i=0;i<*numServers;i++) {
            /* if we don't have an IP yet, then we should try resolving the volserver hostname
               in a separate query. */
            if (!cellHostAddrs[i]) {
                if (DnsQuery_W(cellHostNames[i], DNS_TYPE_A, DNS_QUERY_STANDARD, NULL,
                               (PDNS_RECORD *) &pDnsVol, NULL) == ERROR_SUCCESS) {
                    for (pDnsVolIter = pDnsVol; pDnsVolIter; pDnsVolIter=pDnsVolIter->pNext) {
                        /* if we get an A record, keep it */
                        if (pDnsVolIter->wType == DNS_TYPE_A && cm_stricmp_utf16(cellHostNames[i], pDnsVolIter->pName)==0) {
                            cellHostAddrs[i] = pDnsVolIter->Data.A.IpAddress;
                            break;
                        }
                        /* if we get a CNAME, look for a corresponding A record */
                        if (pDnsVolIter->wType == DNS_TYPE_CNAME && cm_stricmp_utf16(cellHostNames[i], pDnsVolIter->pName)==0) {
                            for (pDnsCIter=pDnsVolIter; pDnsCIter; pDnsCIter=pDnsCIter->pNext) {
                                if (pDnsCIter->wType == DNS_TYPE_A && cm_stricmp_utf16(pDnsVolIter->Data.CNAME.pNameHost, pDnsCIter->pName)==0) {
                                    cellHostAddrs[i] = pDnsCIter->Data.A.IpAddress;
                                    break;
                                }
                            }
                            if (cellHostAddrs[i]) 
                                break;
                            /* TODO: if the additional section is missing, then do another lookup for the CNAME */
                        }
                    }
                    /* we are done with the volserver lookup */
                    DnsRecordListFree((PDNS_RECORD) pDnsVol, DnsFreeRecordListDeep);
                }
            }
        }
        DnsRecordListFree((PDNS_RECORD) pDnsCell, DnsFreeRecordListDeep);
    }

    if ( *numServers > 0 )
        return 0;
    else        
#endif  /* DNSAPI_ENV */
        return -1;
}