windows-cellservdb-lookup-20090525
[openafs.git] / src / WINNT / afsd / cm_dns.c
index 2cd822f..e5fdb13 100644 (file)
@@ -14,8 +14,8 @@
 #include <windows.h>
 #include <winsock2.h>
 #include "cm_dns_private.h"
-#include "cm_dns.h"
 #include "cm_nls.h"
+#include "cm_dns.h"
 #include <lwp.h>
 #include <afs/afsint.h>
 #if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0500)
@@ -23,6 +23,7 @@
 #define DNSAPI_ENV
 #endif
 #include <errno.h>
+#include <strsafe.h>
 
 /*extern void afsi_log(char *pattern, ...);*/
 
@@ -31,51 +32,56 @@ static int cm_dnsEnabled = -1;
 
 void DNSlowerCase(char *str)
 {
-  int i;
+    unsigned int i;
 
-  for (i=0; i<strlen(str); i++)
-    /*str[i] = tolower(str[i]);*/
-    if (str[i] >= 'A' && str[i] <= 'Z')
-      str[i] += 'a' - 'A';
+    for (i=0; i<strlen(str); i++)
+        /*str[i] = tolower(str[i]);*/
+        if (str[i] >= 'A' && str[i] <= 'Z')
+            str[i] += 'a' - 'A';
 }
 
 int cm_InitDNS(int enabled)
 {
 #ifndef DNSAPI_ENV
-  char configpath[100];
-  int len;
-  int code;
-  char *addr;
-  
-  if (!enabled) { fprintf(stderr, "DNS support disabled\n"); cm_dnsEnabled = 0; return 0; }
-
-  /* First try AFS_NS environment var. */
-  addr = getenv("AFS_NS");
-  if (addr && inet_addr(addr) != -1) {
-    strcpy(dns_addr, addr);
-  } else {
-    /* Now check for the AFSDNS.INI file */
-    code = GetWindowsDirectory(configpath, sizeof(configpath));
-    if (code == 0 || code > sizeof(configpath)) return -1;
-    strcat(configpath, "\\afsdns.ini");
-
-    /* Currently we only get (and query) the first nameserver.  Getting
-       list of mult. nameservers should be easy to do. */
-    len = GetPrivateProfileString("AFS Domain Name Servers", "ns1", NULL,
-                           dns_addr, sizeof(dns_addr),
-                           configpath);
-  
-    if (len == 0 || inet_addr(dns_addr) == -1) {
-      fprintf(stderr, "No valid name server addresses found, DNS lookup is "
-                      "disabled\n");
-      cm_dnsEnabled = 0;  /* failed */
-      return -1;     /* No name servers defined */
+    char configpath[100];
+    int len;
+    int code;
+    char *addr;
+  
+    if (!enabled) { 
+        fprintf(stderr, "DNS support disabled\n"); 
+        cm_dnsEnabled = 0; 
+        return 0; 
+    }
+
+    /* First try AFS_NS environment var. */
+    addr = getenv("AFS_NS");
+    if (addr && inet_addr(addr) != -1) {
+        strcpy(dns_addr, addr);
+    } else {
+        /* Now check for the AFSDNS.INI file */
+        code = GetWindowsDirectory(configpath, sizeof(configpath));
+        if (code == 0 || code > sizeof(configpath)) return -1;
+        strcat(configpath, "\\afsdns.ini");
+
+        /* Currently we only get (and query) the first nameserver.  Getting
+        list of mult. nameservers should be easy to do. */
+        len = GetPrivateProfileString("AFS Domain Name Servers", "ns1", NULL,
+                                       dns_addr, sizeof(dns_addr),
+                                       configpath);
+  
+        if (len == 0 || inet_addr(dns_addr) == -1) {
+            fprintf(stderr, "No valid name server addresses found, DNS lookup is "
+                     "disabled\n");
+            cm_dnsEnabled = 0;  /* failed */
+            return -1;     /* No name servers defined */
+        }
+        else 
+            fprintf(stderr, "Found DNS server %s\n", dns_addr);
     }
-    else fprintf(stderr, "Found DNS server %s\n", dns_addr);
-  }
 #endif /* DNSAPI_ENV */
-  cm_dnsEnabled = 1;
-  return 0;
+    cm_dnsEnabled = 1;
+    return 0;
 }
 
 #ifndef DNSAPI_ENV
@@ -476,7 +482,8 @@ void printReplyBuffer_AFSDB(PDNS_HDR replyBuff)
 
 };
 
-void processReplyBuffer_AFSDB(SOCKET commSock, PDNS_HDR replyBuff, int *cellHostAddrs, char cellHostNames[][MAXHOSTCHARS], int *numServers, int *ttl)
+void processReplyBuffer_AFSDB(SOCKET commSock, PDNS_HDR replyBuff, int *cellHostAddrs, char cellHostNames[][MAXHOSTCHARS], 
+                              unsigned short ipRanks[], int *numServers, int *ttl)
   /*PAFS_SRV_LIST (srvList)*/
 {
   u_char *ptr = (u_char *) replyBuff;
@@ -527,8 +534,9 @@ void processReplyBuffer_AFSDB(SOCKET commSock, PDNS_HDR replyBuff, int *cellHost
       fprintf(stderr, "processRep_AFSDB: resolved name %s to addr %x\n", hostName, addr);
 #endif /* DEBUG */
       memcpy(&cellHostAddrs[srvCount], &addr.s_addr, sizeof(addr.s_addr));
-         strncpy(cellHostNames[srvCount], hostName, MAXCELLCHARS);
-         cellHostNames[srvCount][MAXCELLCHARS-1] = '\0';
+         strncpy(cellHostNames[srvCount], hostName, CELL_MAXNAMELEN);
+         cellHostNames[srvCount][CELL_MAXNAMELEN-1] = '\0';
+      ipRanks[srvCount] = 0;
       srvCount++;
     }
     else {
@@ -615,75 +623,71 @@ int DNSgetAddr(SOCKET commSock, char *hostName, struct in_addr *iNet)
 #endif /* DNSAPI_ENV */
 
 int getAFSServer(char *cellName, int *cellHostAddrs, char cellHostNames[][MAXHOSTCHARS], 
-                 int *numServers, int *ttl)
+                 unsigned short ipRanks[], int *numServers, int *ttl)
 {
 #ifndef DNSAPI_ENV
-   /*static AFS_SRV_LIST srvList;
-    static int ans = 0;*/
-  SOCKET commSock;
-  SOCKADDR_IN sockAddr;
-  PDNS_HDR  pDNShdr;
-  char buffer[BUFSIZE];
-  char query[1024];
-  int rc;
+    SOCKET commSock;
+    SOCKADDR_IN sockAddr;
+    PDNS_HDR  pDNShdr;
+    char buffer[BUFSIZE];
+    char query[1024];
+    int rc;
 
 #ifdef DEBUG
-  fprintf(stderr, "getAFSServer: cell %s, cm_dnsEnabled=%d\n", cellName, cm_dnsEnabled);
+    fprintf(stderr, "getAFSServer: cell %s, cm_dnsEnabled=%d\n", cellName, cm_dnsEnabled);
 #endif
 
 #if !defined(_WIN32_WINNT) || (_WIN32_WINNT < 0x0500)
-  if (cm_dnsEnabled == -1) { /* not yet initialized, eg when called by klog */
-    cm_InitDNS(1);    /* assume enabled */
-  }
+    if (cm_dnsEnabled == -1) { /* not yet initialized, eg when called by klog */
+        cm_InitDNS(1);         /* assume enabled */
+    }
 #endif
-  if (cm_dnsEnabled == 0) {  /* possibly we failed in cm_InitDNS above */
-    fprintf(stderr, "DNS initialization failed, disabled\n");
-    *numServers = 0;
-    return -1;
-  }
+    if (cm_dnsEnabled == 0) {  /* possibly we failed in cm_InitDNS above */
+        fprintf(stderr, "DNS initialization failed, disabled\n");
+        *numServers = 0;
+        return -1;
+    }
   
-  sockAddr = setSockAddr(dns_addr, DNS_PORT);
+    sockAddr = setSockAddr(dns_addr, DNS_PORT);
   
-  commSock = socket( AF_INET, SOCK_DGRAM, 0 );
-  if ( commSock < 0 )
+    commSock = socket( AF_INET, SOCK_DGRAM, 0 );
+    if ( commSock < 0 )
     {
-      /*afsi_log("socket() failed\n");*/
-      fprintf(stderr, "getAFSServer: socket() failed, errno=%d\n", errno);
-      *numServers = 0;
-      return (-1);
+        /*afsi_log("socket() failed\n");*/
+        fprintf(stderr, "getAFSServer: socket() failed, errno=%d\n", errno);
+        *numServers = 0;
+        return (-1);
     } 
-  
-  strncpy(query, cellName, 1024);
-  query[1023] = 0;
-  if (query[strlen(query)-1] != '.') {
-    strncat(query,".",1024);
-    query[1023] = 0;
-  }
 
-  rc = send_DNS_AFSDB_Query(cellName,commSock,sockAddr, buffer);
-  if (rc < 0) {
-    fprintf(stderr,"getAFSServer: send_DNS_AFSDB_Query failed\n");
-    *numServers = 0;
-    return -1;
-  }
+    StringCbCopyA(query, sizeof(query), cellName);
+    if (query[strlen(query)-1] != '.') {
+        StringCbCatA(query, sizeof(query), ".");
+    }
+
+    rc = send_DNS_AFSDB_Query(cellName,commSock,sockAddr, buffer);
+    if (rc < 0) {
+        closesocket(commSock);
+        fprintf(stderr,"getAFSServer: send_DNS_AFSDB_Query failed\n");
+        *numServers = 0;
+        return -1;
+    }
     
-  pDNShdr = get_DNS_Response(commSock,sockAddr, buffer);
+    pDNShdr = get_DNS_Response(commSock,sockAddr, buffer);
   
-  /*printReplyBuffer_AFSDB(pDNShdr);*/
-  if (pDNShdr)
-    processReplyBuffer_AFSDB(commSock, pDNShdr, cellHostAddrs, cellHostNames, numServers, ttl);
-  else
-    *numServers = 0;
-  
-  closesocket(commSock);
-  if (*numServers == 0)
-    return(-1);
+    /*printReplyBuffer_AFSDB(pDNShdr);*/
+    if (pDNShdr)
+        processReplyBuffer_AFSDB(commSock, pDNShdr, cellHostAddrs, cellHostNames, ipRanks, numServers, ttl);
+    else
+        *numServers = 0;
 
-  else
-    return 0;
+    closesocket(commSock);
+    if (*numServers == 0)
+        return(-1);
+    else
+        return 0;
 #else /* DNSAPI_ENV */
-    PDNS_RECORD pDnsCell, pDnsIter, pDnsVol,pDnsVolIter, pDnsCIter;
-    DWORD i;
+    PDNS_RECORD pDnsCell, pDnsIter, pDnsVol, pDnsVolIter, pDnsCIter;
+    int i;
     struct sockaddr_in vlSockAddr;
     char query[1024];
 
@@ -696,22 +700,21 @@ int getAFSServer(char *cellName, int *cellHostAddrs, char cellHostNames[][MAXHOS
     *ttl = 0;
 
     /* query the AFSDB records of cell */
-    strncpy(query, cellName, 1024);
-    query[1023] = 0;
+    StringCbCopyA(query, sizeof(query), cellName);
     if (query[strlen(query)-1] != '.') {
-        strncat(query,".",1024);
-        query[1023] = 0;
+        StringCbCatA(query, sizeof(query), ".");
     }
 
     if (DnsQuery_A(query, DNS_TYPE_AFSDB, DNS_QUERY_STANDARD, NULL, &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 we find an AFSDB record with Preference set to 1, we found a afs3-vlserver */
             if (pDnsIter->wType == DNS_TYPE_AFSDB && pDnsIter->Data.Afsdb.wPreference == 1) {
-                strncpy(cellHostNames[*numServers], pDnsIter->Data.Afsdb.pNameExchange, MAXHOSTCHARS);
-                cellHostNames[*numServers][MAXHOSTCHARS-1]='\0';
+                StringCbCopyA(cellHostNames[*numServers], sizeof(cellHostNames[*numServers]),
+                              pDnsIter->Data.Afsdb.pNameExchange);
+                ipRanks[*numServers] = 0;
                 (*numServers)++;
                 
                 if (!*ttl) 
@@ -727,14 +730,14 @@ int getAFSServer(char *cellName, int *cellHostAddrs, char cellHostNames[][MAXHOS
         /* 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 */
+                /* check if its for one of the afs3-vlservers */
                 for (i=0;i<*numServers;i++)
                     if(cm_stricmp_utf8(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
+            /* if we don't have an IP yet, then we should try resolving the afs3-vlserver hostname
             in a separate query. */
             if (!cellHostAddrs[i]) {
                 if (DnsQuery_A(cellHostNames[i], DNS_TYPE_A, DNS_QUERY_STANDARD, NULL, &pDnsVol, NULL) == ERROR_SUCCESS) {
@@ -757,13 +760,83 @@ int getAFSServer(char *cellName, int *cellHostAddrs, char cellHostNames[][MAXHOS
                             /* TODO: if the additional section is missing, then do another lookup for the CNAME */
                         }
                     }
-                    /* we are done with the volserver lookup */
+                    /* we are done with the afs3-vlserver lookup */
                     DnsRecordListFree(pDnsVol, DnsFreeRecordListDeep);
                 }
             }
         }
         DnsRecordListFree(pDnsCell, DnsFreeRecordListDeep);
     }
+    else {
+        /* query the SRV _afs3-vlserver._udp records of cell */
+        StringCbPrintf(query, sizeof(query), "_afs3-vlserver._udp.%s", cellName);
+        if (query[strlen(query)-1] != '.') {
+            StringCbCatA(query, sizeof(query), ".");
+        }
+        
+        if (DnsQuery_A(query, DNS_TYPE_SRV, DNS_QUERY_STANDARD, NULL, &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 SRV record, we found a afs3-vlserver */
+                if (pDnsIter->wType == DNS_TYPE_SRV) {
+                    StringCbCopyA(cellHostNames[*numServers], sizeof(cellHostNames[*numServers]),
+                                   pDnsIter->Data.SRV.pNameTarget);
+                    ipRanks[*numServers] = pDnsIter->Data.SRV.wPriority;
+                    (*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 afs3-vlservers */
+                    for (i=0;i<*numServers;i++)
+                        if(cm_stricmp_utf8(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 afs3-vlserver hostname
+                in a separate query. */
+                if (!cellHostAddrs[i]) {
+                    if (DnsQuery_A(cellHostNames[i], DNS_TYPE_A, DNS_QUERY_STANDARD, NULL, &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_utf8(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_utf8(cellHostNames[i], pDnsVolIter->pName)==0) {
+                                for (pDnsCIter=pDnsVolIter; pDnsCIter; pDnsCIter=pDnsCIter->pNext) {
+                                    if (pDnsCIter->wType == DNS_TYPE_A && cm_stricmp_utf8(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 afs3-vlserver lookup */
+                        DnsRecordListFree(pDnsVol, DnsFreeRecordListDeep);
+                    }
+                }
+            }
+            DnsRecordListFree(pDnsCell, DnsFreeRecordListDeep);
+        }
+    }
 
     if ( *numServers > 0 )
         return 0;
@@ -771,4 +844,174 @@ int getAFSServer(char *cellName, int *cellHostAddrs, char cellHostNames[][MAXHOS
         return -1;
 #endif /* DNSAPI_ENV */
 }
+
+int getAFSServerW(cm_unichar_t *cellName, int *cellHostAddrs,
+                  cm_unichar_t cellHostNames[][MAXHOSTCHARS], 
+                  unsigned short ipRanks[],
+                  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 afs3-vlserver */
+            if (pDnsIter->wType == DNS_TYPE_AFSDB && pDnsIter->Data.Afsdb.wPreference == 1) {
+                StringCbCopyW(cellHostNames[*numServers], sizeof(cellHostNames[*numServers]),
+                              pDnsIter->Data.Afsdb.pNameExchange);
+                ipRanks[*numServers] = 0;
+                (*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 afs3-vlservers */
+                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 afs3-vlserver 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 afs3-vlserver lookup */
+                    DnsRecordListFree((PDNS_RECORD) pDnsVol, DnsFreeRecordListDeep);
+                }
+            }
+        }
+        DnsRecordListFree((PDNS_RECORD) pDnsCell, DnsFreeRecordListDeep);
+    }
+    else {
+        /* query the SRV _afs3-vlserver._udp records of cell */
+        StringCbPrintfW(query, sizeof(query), L"_afs3-vlserver._udp.%S", 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) {
+            memset((void*) &vlSockAddr, 0, sizeof(vlSockAddr));
+
+            /* go through the returned records */
+            for (pDnsIter = pDnsCell; pDnsIter; pDnsIter = pDnsIter->pNext) {
+                /* if we find an SRV record, we found a afs3-vlserver */
+                if (pDnsIter->wType == DNS_TYPE_SRV) {
+                    StringCbCopyW(cellHostNames[*numServers], sizeof(cellHostNames[*numServers]),
+                                   pDnsIter->Data.SRV.pNameTarget);
+                    ipRanks[*numServers] = pDnsIter->Data.SRV.wPriority;
+                    (*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 afs3-vlservers */
+                    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 afs3-vlserver 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 afs3-vlserver lookup */
+                        DnsRecordListFree((PDNS_RECORD) pDnsVol, DnsFreeRecordListDeep);
+                    }
+                }
+            }
+            DnsRecordListFree((PDNS_RECORD) pDnsCell, DnsFreeRecordListDeep);
+        }
+    }
+
+    if ( *numServers > 0 )
+        return 0;
+    else        
+#endif  /* DNSAPI_ENV */
+        return -1;
+}
 #endif /* AFS_AFSDB_ENV */
+