#include <rx/rxkad.h>
#include <WINNT\afsreg.h>
+#include "cm.h"
/*
* TIMING _____________________________________________________________________
/* Static Prototypes */
char *afs_realm_of_cell(krb5_context, struct afsconf_cell *);
-static long get_cellconfig_callback(void *, struct sockaddr_in *, char *);
+static long get_cellconfig_callback(void *, struct sockaddr_in *, char *, unsigned short);
int KFW_AFS_get_cellconfig(char *, struct afsconf_cell *, char *);
static krb5_error_code KRB5_CALLCONV KRB5_prompter( krb5_context context,
void *data, const char *name, const char *banner, int num_prompts,
/**************************************/
/* KFW_AFS_get_cellconfig(): */
/**************************************/
-int
+int
KFW_AFS_get_cellconfig(char *cell, struct afsconf_cell *cellconfig, char *local_cell)
{
int rc;
if (strlen(cell) == 0)
strcpy(cell, local_cell);
- /* WIN32: cm_SearchCellFile(cell, pcallback, pdata) */
- rc = cm_SearchCellFileEx(cell, newcell, linkedcell, get_cellconfig_callback, (void*)cellconfig);
+ rc = cm_SearchCellRegistry(1, cell, newcell, linkedcell, get_cellconfig_callback, (void*)cellconfig);
+ if (rc && rc != CM_ERROR_FORCE_DNS_LOOKUP)
+ rc = cm_SearchCellFileEx(cell, newcell, linkedcell, get_cellconfig_callback, (void*)cellconfig);
#ifdef AFS_AFSDB_ENV
if (rc != 0) {
int ttl;
/* get_cellconfig_callback(): */
/**************************************/
static long
-get_cellconfig_callback(void *cellconfig, struct sockaddr_in *addrp, char *namep)
+get_cellconfig_callback(void *cellconfig, struct sockaddr_in *addrp, char *namep, unsigned short ipRank)
{
struct afsconf_cell *cc = (struct afsconf_cell *)cellconfig;
#define CM_ERROR_NOSUCHDEVICE (CM_ERROR_BASE+58)
#define CM_ERROR_LOCK_NOT_GRANTED (CM_ERROR_BASE+59)
#define CM_ERROR_NOTINCACHE (CM_ERROR_BASE+60)
+#define CM_ERROR_FORCE_DNS_LOOKUP (CM_ERROR_BASE+61)
/* Used by cm_FollowMountPoint and cm_FindVolumeByName */
/* And as an index in cm_volume_t */
*
* At the present time the return value is ignored by the caller.
*/
-long cm_AddCellProc(void *rockp, struct sockaddr_in *addrp, char *hostnamep)
+long cm_AddCellProc(void *rockp, struct sockaddr_in *addrp, char *hostnamep, unsigned short ipRank)
{
cm_server_t *tsp;
cm_serverRef_t *tsrp;
else
tsp = cm_NewServer(addrp, CM_SERVER_VLDB, cellp, NULL, probe ? 0 : CM_FLAG_NOPROBE);
+ tsp->ipRank = ipRank;
+
/* Insert the vlserver into a sorted list, sorted by server rank */
tsrp = cm_NewServerRef(tsp, 0);
cm_InsertServerList(&cellp->vlServersp, tsrp);
rock.cellp = cp;
rock.flags = flags;
- code = cm_SearchCellFileEx(cp->name, NULL, cp->linkedName, cm_AddCellProc, &rock);
+ code = cm_SearchCellRegistry(1, cp->name, NULL, cp->linkedName, cm_AddCellProc, &rock);
+ if (code && code != CM_ERROR_FORCE_DNS_LOOKUP)
+ code = cm_SearchCellFileEx(cp->name, NULL, cp->linkedName, cm_AddCellProc, &rock);
if (code == 0) {
lock_ObtainMutex(&cp->mx);
cp->timeout = time(0) + 7200;
rock.cellp = cp;
rock.flags = flags;
- code = cm_SearchCellFileEx(namep, fullname, linkedName, cm_AddCellProc, &rock);
+ code = cm_SearchCellRegistry(1, namep, fullname, linkedName, cm_AddCellProc, &rock);
+ if (code && code != CM_ERROR_FORCE_DNS_LOOKUP)
+ code = cm_SearchCellFileEx(namep, fullname, linkedName, cm_AddCellProc, &rock);
if (code) {
osi_Log4(afsd_logp,"in cm_GetCell_gen cm_SearchCellFileEx(%s) returns code= %d fullname= %s linkedName= %s",
osi_LogSaveString(afsd_logp,namep), code, osi_LogSaveString(afsd_logp,fullname),
extern void cm_AddCellToIDHashTable(cm_cell_t * cellp);
-extern long cm_AddCellProc(void *rockp, struct sockaddr_in *addrp, char *namep);
+extern long cm_AddCellProc(void *rockp, struct sockaddr_in *addrp, char *namep,
+ unsigned short ipRank);
extern cm_cell_t *cm_UpdateCell(cm_cell_t * cp, afs_uint32 flags);
vlSockAddr.sin_family = AF_INET;
/* sin_port supplied by connection code */
if (procp)
- (*procp)(rockp, &vlSockAddr, valuep);
+ (*procp)(rockp, &vlSockAddr, valuep, 0);
foundCell = 1;
}
if (!thp) {
vlSockAddr.sin_family = AF_INET;
/* sin_port supplied by connection code */
if (procp)
- (*procp)(rockp, &vlSockAddr, valuep);
+ (*procp)(rockp, &vlSockAddr, valuep, 0);
foundCell = 1;
}
}
return (foundCell) ? 0 : -11;
}
+/*
+ * The CellServDB registry schema is as follows:
+ *
+ * HKLM\SOFTWARE\OpenAFS\Client\CellServDB\[cellname]\
+ * "LinkedCell" REG_SZ "[cellname]"
+ * "Description" REG_SZ "[comment]"
+ * "ForceDNS" DWORD {0,1}
+ *
+ * HKLM\SOFTWARE\OpenAFS\Client\CellServDB\[cellname]\[servername]\
+ * "HostName" REG_SZ "[hostname]"
+ * "IPv4Address" REG_SZ "[address]"
+ * "IPv6Address" REG_SZ "[address]" <future>
+ * "Comment" REG_SZ "[comment]"
+ * "Rank" DWORD "0..65535"
+ * "Clone" DWORD "{0,1}"
+ * "vlserver" DWORD "7003" <future>
+ * "ptserver" DWORD ... <future>
+ *
+ * ForceDNS is implied non-zero if there are no [servername]
+ * keys under the [cellname] key. Otherwise, ForceDNS is zero.
+ * If [servername] keys are specified and none of them evaluate
+ * to a valid server configuration, the return code is success.
+ * This prevents failover to the CellServDB file or DNS.
+ */
+long cm_SearchCellRegistry(afs_uint32 client,
+ char *cellNamep, char *newCellNamep,
+ char *linkedNamep,
+ cm_configProc_t *procp, void *rockp)
+{
+ HKEY hkCellServDB = 0, hkCellName = 0, hkServerName = 0;
+ DWORD dwType, dwSize;
+ DWORD dwCells, dwServers, dwForceDNS;
+ DWORD dwIndex, dwRank;
+ unsigned short ipRank;
+ LONG code;
+ FILETIME ftLastWriteTime;
+ char szCellName[CELL_MAXNAMELEN];
+ char szServerName[MAXHOSTCHARS];
+ char szHostName[MAXHOSTCHARS];
+ char szAddr[64];
+ struct hostent *thp;
+ struct sockaddr_in vlSockAddr;
+ char * s;
+
+ if ( IsWindowsModule(cellNamep) )
+ return -1;
+
+ /* No Server CellServDB list (yet) */
+ if ( !client )
+ return CM_ERROR_NOSUCHCELL;
+
+ if (RegOpenKeyEx( HKEY_LOCAL_MACHINE,
+ AFSREG_CLT_OPENAFS_SUBKEY "\\CellServDB",
+ 0,
+ KEY_READ|KEY_WRITE|KEY_QUERY_VALUE,
+ &hkCellServDB) != ERROR_SUCCESS)
+ return CM_ERROR_NOSUCHCELL;
+
+ if (RegOpenKeyEx( hkCellServDB,
+ cellNamep,
+ 0,
+ KEY_READ|KEY_WRITE|KEY_QUERY_VALUE,
+ &hkCellName) != ERROR_SUCCESS) {
+ BOOL bFound = 0;
+
+ /* We did not find an exact match. Much search for partial matches. */
+
+ code = RegQueryInfoKey( hkCellServDB,
+ NULL, /* lpClass */
+ NULL, /* lpcClass */
+ NULL, /* lpReserved */
+ &dwCells, /* lpcSubKeys */
+ NULL, /* lpcMaxSubKeyLen */
+ NULL, /* lpcMaxClassLen */
+ NULL, /* lpcValues */
+ NULL, /* lpcMaxValueNameLen */
+ NULL, /* lpcMaxValueLen */
+ NULL, /* lpcbSecurityDescriptor */
+ &ftLastWriteTime /* lpftLastWriteTime */
+ );
+ if (code != ERROR_SUCCESS)
+ dwCells = 0;
+
+ /*
+ * We search the entire list to ensure that there is only
+ * one prefix match. If there is more than one, we return none.
+ */
+ for ( dwIndex = 0; dwIndex < dwCells; dwIndex++ ) {
+ dwSize = CELL_MAXNAMELEN;
+ code = RegEnumKeyEx( hkCellServDB, dwIndex, szCellName, &dwSize, NULL,
+ NULL, NULL, &ftLastWriteTime);
+ if (code != ERROR_SUCCESS)
+ continue;
+ szCellName[CELL_MAXNAMELEN-1] = '\0';
+ strlwr(szCellName);
+
+ /* if not a prefix match, try the next key */
+ if (strncmp(cellNamep, szCellName, strlen(cellNamep)))
+ continue;
+
+ /* If we have a prefix match and we already found another
+ * match, return neither */
+ if (hkCellName) {
+ bFound = 0;
+ RegCloseKey( hkCellName);
+ break;
+ }
+
+ if (RegOpenKeyEx( hkCellServDB,
+ szCellName,
+ 0,
+ KEY_READ|KEY_WRITE|KEY_QUERY_VALUE,
+ &hkCellName) != ERROR_SUCCESS)
+ continue;
+
+ if (newCellNamep) {
+ strncpy(newCellNamep, szCellName, CELL_MAXNAMELEN);
+ newCellNamep[CELL_MAXNAMELEN-1] = '\0';
+ }
+ bFound = 1;
+ }
+
+ if ( !bFound ) {
+ if (newCellNamep)
+ newCellNamep[0] = '\0';
+ RegCloseKey(hkCellServDB);
+ return CM_ERROR_NOSUCHCELL;
+ }
+ } else if (newCellNamep) {
+ strncpy(newCellNamep, cellNamep, CELL_MAXNAMELEN);
+ newCellNamep[CELL_MAXNAMELEN-1] = '\0';
+ strlwr(newCellNamep);
+ }
+
+ if (linkedNamep) {
+ dwSize = CELL_MAXNAMELEN;
+ code = RegQueryValueEx(hkCellName, "LinkedCell", NULL, &dwType,
+ (BYTE *) linkedNamep, &dwSize);
+ if (code == ERROR_SUCCESS && dwType == REG_SZ) {
+ linkedNamep[CELL_MAXNAMELEN-1] = '\0';
+ strlwr(linkedNamep);
+ } else {
+ linkedNamep[0] = '\0';
+ }
+ }
+
+ /* Check to see if DNS lookups are required */
+ dwSize = sizeof(DWORD);
+ code = RegQueryValueEx(hkCellName, "ForceDNS", NULL, &dwType,
+ (BYTE *) &dwForceDNS, &dwSize);
+ if (code == ERROR_SUCCESS && dwType == REG_DWORD) {
+ if (dwForceDNS)
+ goto done;
+ } else {
+ dwForceDNS = 0;
+ }
+
+ /*
+ * Using the defined server list. Enumerate and populate
+ * the server list for the cell.
+ */
+ code = RegQueryInfoKey( hkCellName,
+ NULL, /* lpClass */
+ NULL, /* lpcClass */
+ NULL, /* lpReserved */
+ &dwServers, /* lpcSubKeys */
+ NULL, /* lpcMaxSubKeyLen */
+ NULL, /* lpcMaxClassLen */
+ NULL, /* lpcValues */
+ NULL, /* lpcMaxValueNameLen */
+ NULL, /* lpcMaxValueLen */
+ NULL, /* lpcbSecurityDescriptor */
+ &ftLastWriteTime /* lpftLastWriteTime */
+ );
+ if (code != ERROR_SUCCESS)
+ dwServers = 0;
+
+ for ( dwIndex = 0; dwIndex < dwServers; dwIndex++ ) {
+ dwSize = MAXHOSTCHARS;
+ code = RegEnumKeyEx( hkCellName, dwIndex, szServerName, &dwSize, NULL,
+ NULL, NULL, &ftLastWriteTime);
+ if (code != ERROR_SUCCESS)
+ continue;
+
+ szServerName[MAXHOSTCHARS-1] = '\0';
+ if (RegOpenKeyEx( hkCellName,
+ szServerName,
+ 0,
+ KEY_READ|KEY_WRITE|KEY_QUERY_VALUE,
+ &hkServerName) != ERROR_SUCCESS)
+ continue;
+
+ /* We have a handle to a valid server key. Now we need
+ * to add the server to the cell */
+
+ /* First, see if there is an alternate hostname specified */
+ dwSize = MAXHOSTCHARS;
+ code = RegQueryValueEx(hkServerName, "HostName", NULL, &dwType,
+ (BYTE *) szHostName, &dwSize);
+ if (code == ERROR_SUCCESS && dwType == REG_SZ) {
+ szHostName[MAXHOSTCHARS-1] = '\0';
+ strlwr(szHostName);
+ s = szHostName;
+ } else {
+ s = szServerName;
+ }
+
+ dwSize = sizeof(DWORD);
+ code = RegQueryValueEx(hkServerName, "Rank", NULL, &dwType,
+ (BYTE *) &dwRank, &dwSize);
+ if (code == ERROR_SUCCESS && dwType == REG_DWORD) {
+ ipRank = (unsigned short)(dwRank <= 65535 ? dwRank : 65535);
+ } else {
+ ipRank = 0;
+ }
+
+ dwSize = sizeof(szAddr);
+ code = RegQueryValueEx(hkServerName, "IPv4Address", NULL, &dwType,
+ (BYTE *) szAddr, &dwSize);
+ if (code == ERROR_SUCCESS && dwType == REG_SZ) {
+ szAddr[63] = '\0';
+ } else {
+ szAddr[0] = '\0';
+ }
+
+ WSASetLastError(0);
+ thp = gethostbyname(s);
+ 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, s, ipRank);
+ } else if (szAddr[0]) {
+ afs_uint32 ip_addr;
+ unsigned int c1, c2, c3, c4;
+
+ /* Since there is no gethostbyname() data
+ * available we will read the IP address
+ * stored in the CellServDB file
+ */
+ code = sscanf(szAddr, " %u.%u.%u.%u",
+ &c1, &c2, &c3, &c4);
+ if (code == 4 && c1<256 && c2<256 && c3<256 && c4<256) {
+ unsigned char * tp = (unsigned char *) &ip_addr;
+ *tp++ = c1;
+ *tp++ = c2;
+ *tp++ = c3;
+ *tp++ = c4;
+ memcpy(&vlSockAddr.sin_addr.s_addr, &ip_addr,
+ sizeof(long));
+ vlSockAddr.sin_family = AF_INET;
+ /* sin_port supplied by connection code */
+ if (procp)
+ (*procp)(rockp, &vlSockAddr, s, ipRank);
+ }
+ }
+
+ RegCloseKey( hkServerName);
+ }
+
+ done:
+ RegCloseKey(hkCellName);
+ RegCloseKey(hkCellServDB);
+
+ return ((dwForceDNS || dwServers == 0) ? CM_ERROR_FORCE_DNS_LOOKUP : 0);
+}
+
+long cm_EnumerateCellRegistry(afs_uint32 client, cm_enumCellRegistryProc_t *procp, void *rockp)
+{
+ HKEY hkCellServDB = 0;
+ DWORD dwType, dwSize;
+ DWORD dwCells;
+ DWORD dwIndex;
+ LONG code;
+ FILETIME ftLastWriteTime;
+ char szCellName[CELL_MAXNAMELEN];
+
+ /* No server CellServDB in the registry. */
+ if (!client || procp == NULL)
+ return 0;
+
+ if (RegOpenKeyEx( HKEY_LOCAL_MACHINE,
+ AFSREG_CLT_OPENAFS_SUBKEY "\\CellServDB",
+ 0,
+ KEY_READ|KEY_WRITE|KEY_QUERY_VALUE,
+ &hkCellServDB) != ERROR_SUCCESS)
+ return 0;
+
+ code = RegQueryInfoKey( hkCellServDB,
+ NULL, /* lpClass */
+ NULL, /* lpcClass */
+ NULL, /* lpReserved */
+ &dwCells, /* lpcSubKeys */
+ NULL, /* lpcMaxSubKeyLen */
+ NULL, /* lpcMaxClassLen */
+ NULL, /* lpcValues */
+ NULL, /* lpcMaxValueNameLen */
+ NULL, /* lpcMaxValueLen */
+ NULL, /* lpcbSecurityDescriptor */
+ &ftLastWriteTime /* lpftLastWriteTime */
+ );
+ if (code != ERROR_SUCCESS)
+ dwCells = 0;
+
+ /*
+ * Enumerate each Cell and
+ */
+ for ( dwIndex = 0; dwIndex < dwCells; dwIndex++ ) {
+ dwSize = CELL_MAXNAMELEN;
+ code = RegEnumKeyEx( hkCellServDB, dwIndex, szCellName, &dwSize, NULL,
+ NULL, NULL, &ftLastWriteTime);
+ if (code != ERROR_SUCCESS)
+ continue;
+ szCellName[CELL_MAXNAMELEN-1] = '\0';
+ strlwr(szCellName);
+
+ (*procp)(rockp, szCellName);
+ }
+
+ RegCloseKey(hkCellServDB);
+ return 0;
+}
+
/* newCellNamep is required to be CELL_MAXNAMELEN in size */
long cm_SearchCellByDNS(char *cellNamep, char *newCellNamep, int *ttl,
- cm_configProc_t *procp, void *rockp)
+ cm_configProc_t *procp, void *rockp)
{
#ifdef AFS_AFSDB_ENV
int rc;
int cellHostAddrs[AFSMAXCELLHOSTS];
char cellHostNames[AFSMAXCELLHOSTS][MAXHOSTCHARS];
+ unsigned short ipRanks[AFSMAXCELLHOSTS];
int numServers;
int i;
struct sockaddr_in vlSockAddr;
#endif
if ( IsWindowsModule(cellNamep) )
return -1;
- rc = getAFSServer(cellNamep, cellHostAddrs, cellHostNames, &numServers, ttl);
+ rc = getAFSServer(cellNamep, cellHostAddrs, cellHostNames, 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],
vlSockAddr.sin_family = AF_INET;
/* sin_port supplied by connection code */
if (procp)
- (*procp)(rockp, &vlSockAddr, cellHostNames[i]);
- if (newCellNamep) {
- strncpy(newCellNamep,cellNamep,CELL_MAXNAMELEN);
- newCellNamep[CELL_MAXNAMELEN-1] = '\0';
- strlwr(newCellNamep);
- }
+ (*procp)(rockp, &vlSockAddr, cellHostNames[i], ipRanks[i]);
+ }
+ if (newCellNamep) {
+ strncpy(newCellNamep,cellNamep,CELL_MAXNAMELEN);
+ newCellNamep[CELL_MAXNAMELEN-1] = '\0';
+ strlwr(newCellNamep);
}
return 0; /* found cell */
}
typedef FILE cm_configFile_t;
-typedef long (cm_configProc_t)(void *rockp, struct sockaddr_in *addrp, char *namep);
+typedef long (cm_configProc_t)(void *rockp, struct sockaddr_in *addrp, char *namep, unsigned short);
+
+typedef long (cm_enumCellRegistryProc_t)(void *rockp, char *cellNamep);
extern long cm_GetRootCellName(char *namep);
char *linkedNamep,
cm_configProc_t *procp, void *rockp);
+extern long cm_SearchCellRegistry(afs_uint32 client,
+ char *cellNamep, char *newCellNamep,
+ char *linkedNamep,
+ cm_configProc_t *procp, void *rockp);
+
+extern long cm_EnumerateCellRegistry(afs_uint32 client,
+ cm_enumCellRegistryProc_t *procp,
+ void *rockp);
+
extern long cm_SearchCellByDNS(char *cellNamep, char *newCellNamep, int *ttl,
cm_configProc_t *procp, void *rockp);
};
-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;
memcpy(&cellHostAddrs[srvCount], &addr.s_addr, sizeof(addr.s_addr));
strncpy(cellHostNames[srvCount], hostName, CELL_MAXNAMELEN);
cellHostNames[srvCount][CELL_MAXNAMELEN-1] = '\0';
+ ipRanks[srvCount] = 0;
srvCount++;
}
else {
#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
SOCKET commSock;
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;
/*printReplyBuffer_AFSDB(pDNShdr);*/
if (pDNShdr)
- processReplyBuffer_AFSDB(commSock, pDNShdr, cellHostAddrs, cellHostNames, numServers, ttl);
+ processReplyBuffer_AFSDB(commSock, pDNShdr, cellHostAddrs, cellHostNames, ipRanks, numServers, ttl);
else
*numServers = 0;
else
return 0;
#else /* DNSAPI_ENV */
- PDNS_RECORD pDnsCell, pDnsIter, pDnsVol,pDnsVolIter, pDnsCIter;
+ PDNS_RECORD pDnsCell, pDnsIter, pDnsVol, pDnsVolIter, pDnsCIter;
int i;
struct sockaddr_in vlSockAddr;
char query[1024];
/* 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) {
StringCbCopyA(cellHostNames[*numServers], sizeof(cellHostNames[*numServers]),
pDnsIter->Data.Afsdb.pNameExchange);
+ ipRanks[*numServers] = 0;
(*numServers)++;
if (!*ttl)
/* 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) {
/* 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;
int getAFSServerW(cm_unichar_t *cellName, int *cellHostAddrs,
cm_unichar_t cellHostNames[][MAXHOSTCHARS],
+ unsigned short ipRanks[],
int *numServers, int *ttl)
{
#ifdef DNSAPI_ENV
/* 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) {
StringCbCopyW(cellHostNames[*numServers], sizeof(cellHostNames[*numServers]),
pDnsIter->Data.Afsdb.pNameExchange);
+ ipRanks[*numServers] = 0;
(*numServers)++;
if (!*ttl)
/* 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_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
+ /* 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,
/* 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((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;
/* this function will continue to return cell server
names for the given cell, ending in null */
-int getAFSServer(char *cellname, int *cellHostAddrs, char cellHostNames[][MAXHOSTCHARS], int *numServers, int *ttl);
+int getAFSServer(char *cellname, int *cellHostAddrs, char cellHostNames[][MAXHOSTCHARS],
+ unsigned short ipRanks[], int *numServers, int *ttl);
/* Same as above, but using cm_unichar_t. Note that this functon will
only be defined for DNSAPI_ENV. */
int getAFSServerW(cm_unichar_t *cellName, int *cellHostAddrs,
cm_unichar_t cellHostNames[][MAXHOSTCHARS],
+ unsigned short ipRanks[],
int *numServers, int *ttl);
/* a supplement for the DJGPP gethostbyname ... which
rock.cellp = cp;
rock.flags = 0;
- code = cm_SearchCellFileEx(cp->name, cp->name, cp->linkedName, cm_AddCellProc, &rock);
+ code = cm_SearchCellRegistry(1, cp->name, cp->name, cp->linkedName, cm_AddCellProc, &rock);
+ if (code && code != CM_ERROR_FORCE_DNS_LOOKUP)
+ code = cm_SearchCellFileEx(cp->name, cp->name, cp->linkedName, cm_AddCellProc, &rock);
#ifdef AFS_AFSDB_ENV
if (code) {
if (cm_dnsEnabled) {
afs_uuid_equal @18
cm_GetCellServDB @19
cm_SearchCellFileEx @20
+ cm_SearchCellRegistry @21
+ cm_EnumerateCellRegistry @22
}
/* Get the full name for this cell */
cellname = cm_ClientStringToFsStringAlloc(p, -1, NULL);
- code = cm_SearchCellFile(cellname, ftemp, 0, 0);
+ code = cm_SearchCellRegistry(1, cellname, ftemp, 0, 0, 0);
+ if (code && code != CM_ERROR_FORCE_DNS_LOOKUP)
+ code = cm_SearchCellFile(cellname, ftemp, 0, 0);
#ifdef AFS_AFSDB_ENV
if (code && cm_dnsEnabled) {
int ttl;
#include "keys.h"
#ifdef AFS_NT40_ENV
#ifdef AFS_AFSDB_ENV
+#include <cm.h>
+#include <cm_config.h>
/* cm_dns.h depends on cellconfig.h */
#include <cm_nls.h>
#include <cm_dns.h>
return GetCellUnix(adir);
}
}
+
+/* The following procedures and structs are used on Windows only
+ * to enumerate the Cell information distributed within the
+ * Windows registry. (See src/WINNT/afsd/cm_config.c)
+ */
+typedef struct _cm_enumCellRegistry {
+ afs_uint32 client; /* non-zero if client query */
+ struct afsconf_dir *adir;
+} cm_enumCellRegistry_t;
+
+static long
+cm_serverConfigProc(void *rockp, struct sockaddr_in *addrp,
+ char *hostNamep, unsigned short rank)
+{
+ struct afsconf_cell *cellInfop = (struct afsconf_cell *)rockp;
+
+ if (cellInfop->numServers == MAXHOSTSPERCELL)
+ return 0;
+
+ cellInfop->hostAddr[cellInfop->numServers] = *addrp;
+ strncpy(cellInfop->hostName[cellInfop->numServers], hostNamep, MAXHOSTCHARS);
+ cellInfop->hostName[cellInfop->numServers][MAXHOSTCHARS-1] = '\0';
+ cellInfop->numServers++;
+
+ return 0;
+}
+
+static long
+cm_enumCellRegistryProc(void *rockp, char * cellNamep)
+{
+ long code;
+ cm_enumCellRegistry_t *enump = (cm_enumCellRegistry_t *)rockp;
+ char linkedName[256] = "";
+ int timeout = 0;
+ struct afsconf_entry *newEntry;
+
+
+ newEntry = malloc(sizeof(struct afsconf_entry));
+ if (newEntry == NULL)
+ return ENOMEM;
+ newEntry->cellInfo.numServers = 0;
+
+ code = cm_SearchCellRegistry(enump->client, cellNamep, NULL, linkedName, cm_serverConfigProc, &newEntry->cellInfo);
+ if (code == CM_ERROR_FORCE_DNS_LOOKUP)
+ code = cm_SearchCellByDNS(cellNamep, NULL, &timeout, cm_serverConfigProc, &newEntry->cellInfo);
+
+ if (code == 0) {
+ strncpy(newEntry->cellInfo.name, cellNamep, MAXCELLCHARS);
+ newEntry->cellInfo.name[MAXCELLCHARS-1];
+ if (linkedName[0])
+ newEntry->cellInfo.linkedCell = strdup(linkedName);
+ else
+ newEntry->cellInfo.linkedCell = NULL;
+ newEntry->cellInfo.timeout = timeout;
+ newEntry->cellInfo.flags = 0;
+
+ newEntry->next = enump->adir->entries;
+ enump->adir->entries = newEntry;
+ } else {
+ free(newEntry);
+ }
+ return code;
+}
#endif /* AFS_NT40_ENV */
afs_int32 i;
char tbuffer[256], tbuf1[256];
struct stat tstat;
+#ifdef AFS_NT40_ENV
+ cm_enumCellRegistry_t enumCellRegistry = {0, 0};
+#endif /* AFS_NT40_ENV */
/* figure out the local cell name */
#ifdef AFS_NT40_ENV
i = GetCellNT(adir);
+ enumCellRegistry.adir = adir;
#else
i = GetCellUnix(adir);
#endif
if (IsClientConfigDirectory(adir->name)) {
/* NT client config dir */
char *p;
+
+ enumCellRegistry.client = 1;
+
if (!afssw_GetClientCellServDBDir(&p)) {
strcompose(tbuffer, sizeof(tbuffer), p, "/",
AFSDIR_CELLSERVDB_FILE_NTCLIENT, NULL);
if (!tf) {
return -1;
}
+
+ /* The CellServDB file is now open.
+ * The following code parses the contents of the
+ * file and creates a list with the first cell entry
+ * in the CellServDB file at the end of the list.
+ *
+ * No checking is performed for duplicates.
+ * The side effects of this process are that duplicate
+ * entries appended to the end of the CellServDB file
+ * take precedence and are found in a shorter period
+ * of time.
+ */
+
while (1) {
tp = fgets(tbuffer, sizeof(tbuffer), tf);
if (!tp)
adir->entries = curEntry;
}
+#ifdef AFS_NT40_ENV
+ /*
+ * Windows maintains a CellServDB list in the Registry
+ * that supercedes the contents of the CellServDB file.
+ * Prepending these entries to the head of the list
+ * is sufficient to enforce the precedence.
+ */
+ cm_EnumerateCellRegistry( enumCellRegistry.client,
+ cm_enumCellRegistryProc,
+ &enumCellRegistry);
+#endif /* AFS_NT40_ENV */
+
/* Read in the alias list */
strcompose(tbuffer, 256, adir->name, "/", AFSDIR_CELLALIAS_FILE, NULL);
struct afsconf_entry DNSce;
afs_int32 cellHostAddrs[AFSMAXCELLHOSTS];
char cellHostNames[AFSMAXCELLHOSTS][MAXHOSTCHARS];
+ unsigned short ipRanks[AFSMAXCELLHOSTS];
int numServers;
int rc;
int ttl;
DNSce.cellInfo.numServers = 0;
DNSce.next = NULL;
- rc = getAFSServer(acellName, cellHostAddrs, cellHostNames, &numServers,
+ rc = getAFSServer(acellName, cellHostAddrs, cellHostNames, ipRanks, &numServers,
&ttl);
/* ignore the ttl here since this code is only called by transitory programs
* like klog, etc. */