Permit DNS SRV record lookups to be used by the Windows afsconf_GetAfsdbInfo
[openafs.git] / src / WINNT / afsd / cm_config.c
index e43df19..534bbde 100644 (file)
@@ -92,6 +92,7 @@ IsWindowsModule(const char * name)
     }
     p = strrchr(name, '.');
     if (p) {
+        /* as of 2009-09-04 these are not valid ICANN ccTLDs */
        if (i == 1 && 
            (!cm_stricmp_utf8N(p,".dll") ||
             !cm_stricmp_utf8N(p,".exe") ||
@@ -281,21 +282,40 @@ long cm_SearchCellFileEx(char *cellNamep, char *newCellNamep,
                 valuep[strlen(valuep) - 1] = '\0';
 
            if (inRightCell) {
+                char hostname[256];
+                int  i, isClone = 0;
+
+                isClone = (lineBuffer[0] == '[');
+
+                /* copy just the first word and ignore trailing white space */
+                for ( i=0; valuep[i] && !isspace(valuep[i]) && i<sizeof(hostname); i++)
+                    hostname[i] = valuep[i];
+                hostname[i] = '\0';
+
                /* add the server to the VLDB list */
                 WSASetLastError(0);
-                thp = gethostbyname(valuep);
+                thp = gethostbyname(hostname);
 #ifdef CELLSERV_DEBUG
                osi_Log3(afsd_logp,"cm_searchfile inRightCell thp[%p], valuep[%s], WSAGetLastError[%d]",
-                        thp, osi_LogSaveString(afsd_logp,valuep), WSAGetLastError());
+                        thp, osi_LogSaveString(afsd_logp,hostname), WSAGetLastError());
 #endif
                if (thp) {
-                   memcpy(&vlSockAddr.sin_addr.s_addr, thp->h_addr,
-                            sizeof(long));
-                    vlSockAddr.sin_family = AF_INET;
-                    /* sin_port supplied by connection code */
-                   if (procp)
-                       (*procp)(rockp, &vlSockAddr, valuep, 0);
-                    foundCell = 1;
+                    int foundAddr = 0;
+                    for (i=0 ; thp->h_addr_list[i]; i++) {
+                        if (thp->h_addrtype != AF_INET)
+                            continue;
+                        memcpy(&vlSockAddr.sin_addr.s_addr, thp->h_addr_list[i],
+                               sizeof(long));
+                        vlSockAddr.sin_port = htons(7003);
+                        vlSockAddr.sin_family = AF_INET;
+                        /* sin_port supplied by connection code */
+                        if (procp)
+                            (*procp)(rockp, &vlSockAddr, hostname, 0);
+                        foundAddr = 1;
+                    }
+                    /* if we didn't find a valid address, force the use of the specified one */
+                    if (!foundAddr)
+                        thp = NULL;
                }
                 if (!thp) {
                     afs_uint32 ip_addr;
@@ -305,8 +325,12 @@ long cm_SearchCellFileEx(char *cellNamep, char *newCellNamep,
                     * available we will read the IP address
                     * stored in the CellServDB file
                      */
-                    code = sscanf(lineBuffer, " %u.%u.%u.%u",
-                                   &c1, &c2, &c3, &c4);
+                    if (isClone)
+                        code = sscanf(lineBuffer, "[%u.%u.%u.%u]",
+                                      &c1, &c2, &c3, &c4);
+                    else
+                        code = sscanf(lineBuffer, " %u.%u.%u.%u",
+                                      &c1, &c2, &c3, &c4);
                     if (code == 4 && c1<256 && c2<256 && c3<256 && c4<256) {
                         tp = (unsigned char *) &ip_addr;
                         *tp++ = c1;
@@ -315,13 +339,14 @@ long cm_SearchCellFileEx(char *cellNamep, char *newCellNamep,
                         *tp++ = c4;
                         memcpy(&vlSockAddr.sin_addr.s_addr, &ip_addr,
                                 sizeof(long));
+                        vlSockAddr.sin_port = htons(7003);
                         vlSockAddr.sin_family = AF_INET;
                         /* sin_port supplied by connection code */
                         if (procp)
-                            (*procp)(rockp, &vlSockAddr, valuep, 0);
-                        foundCell = 1;
+                            (*procp)(rockp, &vlSockAddr, hostname, 0);
                     }
                 }
+                foundCell = 1;
             }
         }      /* a vldb line */
     }          /* while loop processing all lines */
@@ -346,7 +371,7 @@ long cm_SearchCellFileEx(char *cellNamep, char *newCellNamep,
  *   "Rank"          DWORD  "0..65535"
  *   "Clone"         DWORD  "{0,1}"
  *   "vlserver"      DWORD  "7003"        <future>
- *   "ptserver"      DWORD  ...           <future>
+ *   "ptserver"      DWORD  "7002"        <future>
  *
  * ForceDNS is implied non-zero if there are no [servername]
  * keys under the [cellname] key.  Otherwise, ForceDNS is zero.
@@ -362,8 +387,9 @@ long cm_SearchCellRegistry(afs_uint32 client,
     HKEY hkCellServDB = 0, hkCellName = 0, hkServerName = 0;
     DWORD dwType, dwSize;
     DWORD dwCells, dwServers, dwForceDNS;
-    DWORD dwIndex, dwRank;
+    DWORD dwIndex, dwRank, dwPort;
     unsigned short ipRank;
+    unsigned short vlPort;
     LONG code;
     FILETIME ftLastWriteTime;
     char szCellName[CELL_MAXNAMELEN];
@@ -553,10 +579,20 @@ long cm_SearchCellRegistry(afs_uint32 client,
             szAddr[0] = '\0';
         }
 
+        dwSize = sizeof(DWORD);
+        code = RegQueryValueEx(hkServerName, "vlserver", NULL, &dwType,
+                                (BYTE *) &dwPort, &dwSize);
+        if (code == ERROR_SUCCESS && dwType == REG_DWORD) {
+            vlPort = htons((unsigned short)dwPort);
+        } else {
+            vlPort = htons(7003);
+        }
+
         WSASetLastError(0);
         thp = gethostbyname(s);
         if (thp) {
             memcpy(&vlSockAddr.sin_addr.s_addr, thp->h_addr, sizeof(long));
+            vlSockAddr.sin_port = htons(7003);
             vlSockAddr.sin_family = AF_INET;
             /* sin_port supplied by connection code */
             if (procp)
@@ -579,6 +615,7 @@ long cm_SearchCellRegistry(afs_uint32 client,
                 *tp++ = c4;
                 memcpy(&vlSockAddr.sin_addr.s_addr, &ip_addr,
                         sizeof(long));
+                vlSockAddr.sin_port = vlPort;
                 vlSockAddr.sin_family = AF_INET;
                 /* sin_port supplied by connection code */
                 if (procp)
@@ -599,7 +636,7 @@ long cm_SearchCellRegistry(afs_uint32 client,
 long cm_EnumerateCellRegistry(afs_uint32 client, cm_enumCellRegistryProc_t *procp, void *rockp)
 {
     HKEY hkCellServDB = 0;
-    DWORD dwType, dwSize;
+    DWORD dwSize;
     DWORD dwCells;
     DWORD dwIndex;
     LONG code;
@@ -661,21 +698,33 @@ long cm_SearchCellByDNS(char *cellNamep, char *newCellNamep, int *ttl,
     int  cellHostAddrs[AFSMAXCELLHOSTS];
     char cellHostNames[AFSMAXCELLHOSTS][MAXHOSTCHARS];
     unsigned short ipRanks[AFSMAXCELLHOSTS];
+    unsigned short ports[AFSMAXCELLHOSTS];
     int numServers;
     int i;
     struct sockaddr_in vlSockAddr;
 #ifdef CELLSERV_DEBUG
     osi_Log1(afsd_logp,"SearchCellDNS-Doing search for [%s]", osi_LogSaveString(afsd_logp,cellNamep));
 #endif
-    if ( IsWindowsModule(cellNamep) )
+    /*
+     * Do not perform a DNS lookup if the name is
+     * either a well-known Windows DLL or directory,
+     * or if the name does not contain a top-level
+     * domain, or if the file prefix is the afs pioctl
+     * file name.
+     */
+    if ( IsWindowsModule(cellNamep) ||
+         cm_FsStrChr(cellNamep, '.') == NULL ||
+         strncasecmp(cellNamep, CM_IOCTL_FILENAME_NOSLASH, strlen(CM_IOCTL_FILENAME_NOSLASH)) == 0)
        return -1;
-    rc = getAFSServer(cellNamep, cellHostAddrs, cellHostNames, ipRanks, &numServers, ttl);
+
+    rc = getAFSServer("afs3-vlserver", "udp", cellNamep, 7003,
+                      cellHostAddrs, cellHostNames, ports, ipRanks, &numServers, ttl);
     if (rc == 0 && numServers > 0) {     /* found the cell */
         for (i = 0; i < numServers; i++) {
             memcpy(&vlSockAddr.sin_addr.s_addr, &cellHostAddrs[i],
                    sizeof(long));
+            vlSockAddr.sin_port = ports[i];
             vlSockAddr.sin_family = AF_INET;
-            /* sin_port supplied by connection code */
             if (procp)
                 (*procp)(rockp, &vlSockAddr, cellHostNames[i], ipRanks[i]);
         }