static int GetCellNT(struct afsconf_dir *adir) { if (_afsconf_IsClientConfigDirectory(adir->name)) { /* NT client config dir; ThisCell is in registry (no file). */ return afssw_GetClientCellName(&adir->cellName); } else { /* NT server config dir; works just like Unix */ return GetCellUnix(adir); } }
static void _afsconf_CellServDBPath(struct afsconf_dir *adir, char **path) { char *p; /* NT client CellServDB has different file name than NT server or Unix */ if (_afsconf_IsClientConfigDirectory(adir->name)) { if (!afssw_GetClientCellServDBDir(&p)) { asprintf(path, "%s/%s", p, AFSDIR_CELLSERVDB_FILE_NTCLIENT); free(p); } else { asprintf(path, "%s/%s", adir->name, AFSDIR_CELLSERVDB_FILE_NTCLIENT); } } else { asprintf(path, "%s/%s", adir->name, AFSDIR_CELLSERVDB_FILE); } return; }
/** * Load the cell configuration into memory. * * Read the cell configuration into a newly allocated or cleared afsconf_dir * structure. Reads the CellServDB file, and if present, the cell alias file, * the key files, and kerberos related files. * * If the configuration cannot be loaded for any reason, any partial changes * are freed. The name member is preserved. * * @param[in,out] adir pointer to the cell configuration * the name member must be set to the pathname of the * cell configuration to be loaded. All other members * must be unassigned. * * @returns 0 on success */ static int LoadConfig(struct afsconf_dir *adir) { afsconf_FILE *tf; char *tp, *bp; struct afsconf_entry *curEntry; struct afsconf_aliasentry *curAlias; afs_int32 code; afs_int32 i; char tbuffer[256]; struct stat tstat; #ifdef AFS_NT40_ENV cm_enumCellRegistry_t enumCellRegistry = {0, 0}; #endif /* AFS_NT40_ENV */ /* init the keys queue before any call to UnloadConfig() */ _afsconf_InitKeys(adir); /* figure out the local cell name */ #ifdef AFS_NT40_ENV i = GetCellNT(adir); enumCellRegistry.adir = adir; #else i = GetCellUnix(adir); #endif #ifndef AFS_FREELANCE_CLIENT /* no local cell not fatal in freelance */ if (i) { return i; } #endif /* now parse the individual lines */ curEntry = 0; _afsconf_CellServDBPath(adir, &adir->cellservDB); #ifdef AFS_NT40_ENV if (_afsconf_IsClientConfigDirectory(adir->name)) enumCellRegistry.client = 1; #endif /* AFS_NT40_ENV */ if (!stat(adir->cellservDB, &tstat)) { adir->timeRead = tstat.st_mtime; } else { adir->timeRead = 0; } tf = fopen(adir->cellservDB, "r"); 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) break; TrimLine(tbuffer, sizeof tbuffer); /* remove white space */ if (tbuffer[0] == 0 || tbuffer[0] == '\n') continue; /* empty line */ if (tbuffer[0] == '>') { char linkedcell[MAXCELLCHARS]; /* start new cell item */ if (curEntry) { /* thread this guy on the list */ curEntry->next = adir->entries; adir->entries = curEntry; curEntry = 0; } curEntry = calloc(1, sizeof(struct afsconf_entry)); code = ParseCellLine(tbuffer, curEntry->cellInfo.name, linkedcell); if (code) { UnloadConfig(adir); fclose(tf); free(curEntry); return -1; } if (linkedcell[0] != '\0') curEntry->cellInfo.linkedCell = strdup(linkedcell); } else { /* new host in the current cell */ if (!curEntry) { UnloadConfig(adir); fclose(tf); return -1; } i = curEntry->cellInfo.numServers; if (i < MAXHOSTSPERCELL) { code = ParseHostLine(tbuffer, &curEntry->cellInfo.hostAddr[i], curEntry->cellInfo.hostName[i], &curEntry->cellInfo.clone[i]); if (code) { if (code == AFSCONF_SYNTAX) { for (bp = tbuffer; *bp != '\n'; bp++) { /* Take out the <cr> from the buffer */ if (!*bp) break; } *bp = '\0'; fprintf(stderr, "Can't properly parse host line \"%s\" in configuration file %s\n", tbuffer, adir->cellservDB); } free(curEntry); fclose(tf); UnloadConfig(adir); return -1; } curEntry->cellInfo.numServers = ++i; } else { fprintf(stderr, "Too many hosts for cell %s in configuration file %s\n", curEntry->cellInfo.name, adir->cellservDB); } } } fclose(tf); /* close the file now */ /* end the last partially-completed cell */ if (curEntry) { curEntry->next = adir->entries; 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, (char *)NULL); tf = fopen(tbuffer, "r"); while (tf) { char *aliasPtr; tp = fgets(tbuffer, sizeof(tbuffer), tf); if (!tp) break; TrimLine(tbuffer, sizeof tbuffer); /* remove white space */ if (tbuffer[0] == '\0' || tbuffer[0] == '\n' || tbuffer[0] == '#') continue; /* empty line */ tp = tbuffer; while (tp[0] != '\0' && tp[0] != ' ' && tp[0] != '\t') tp++; if (tp[0] == '\0') continue; /* invalid line */ while (tp[0] != '\0' && (tp[0] == ' ' || tp[0] == '\t')) 0[tp++] = '\0'; if (tp[0] == '\0') continue; /* invalid line */ aliasPtr = tp; while (tp[0] != '\0' && tp[0] != ' ' && tp[0] != '\t' && tp[0] != '\r' && tp[0] != '\n') tp++; tp[0] = '\0'; curAlias = calloc(1, sizeof(*curAlias)); strlcpy(curAlias->aliasInfo.aliasName, aliasPtr, sizeof curAlias->aliasInfo.aliasName); strlcpy(curAlias->aliasInfo.realName, tbuffer, sizeof curAlias->aliasInfo.realName); curAlias->next = adir->alias_entries; adir->alias_entries = curAlias; } if (tf != NULL) fclose(tf); /* now read the fs keys, if possible */ code = _afsconf_LoadKeys(adir); if (code) { return code; } code = _afsconf_LoadRealms(adir); return code; }
int afsconf_GetCellInfo(struct afsconf_dir *adir, char *acellName, char *aservice, struct afsconf_cell *acellInfo) { struct afsconf_entry *tce; struct afsconf_aliasentry *tcae; struct afsconf_entry *bestce; afs_int32 i; int tservice; char *tcell; int cnLen; int ambig; char tbuffer[64]; LOCK_GLOBAL_MUTEX; if (adir) _afsconf_Check(adir); if (acellName) { tcell = acellName; cnLen = (int)(strlen(tcell) + 1); lcstring(tcell, tcell, cnLen); afsconf_SawCell = 1; /* will ignore the AFSCELL switch on future */ /* call to afsconf_GetLocalCell: like klog */ } else { i = afsconf_GetLocalCell(adir, tbuffer, sizeof(tbuffer)); if (i) { UNLOCK_GLOBAL_MUTEX; return i; } tcell = tbuffer; } cnLen = strlen(tcell); bestce = (struct afsconf_entry *)0; ambig = 0; if (!adir) { UNLOCK_GLOBAL_MUTEX; return 0; } /* Look through the list of aliases */ for (tcae = adir->alias_entries; tcae; tcae = tcae->next) { if (strcasecmp(tcae->aliasInfo.aliasName, tcell) == 0) { tcell = tcae->aliasInfo.realName; break; } } for (tce = adir->entries; tce; tce = tce->next) { if (strcasecmp(tce->cellInfo.name, tcell) == 0) { /* found our cell */ bestce = tce; ambig = 0; break; } if (strlen(tce->cellInfo.name) < cnLen) continue; /* clearly wrong */ if (strncasecmp(tce->cellInfo.name, tcell, cnLen) == 0) { if (bestce) ambig = 1; /* ambiguous unless we get exact match */ bestce = tce; } } if (!ambig && bestce && bestce->cellInfo.numServers) { *acellInfo = bestce->cellInfo; /* structure assignment */ if (aservice) { tservice = afsconf_FindService(aservice); if (tservice < 0) { UNLOCK_GLOBAL_MUTEX; return AFSCONF_NOTFOUND; /* service not found */ } for (i = 0; i < acellInfo->numServers; i++) { acellInfo->hostAddr[i].sin_port = tservice; } } acellInfo->timeout = 0; /* * Until we figure out how to separate out ubik server * queries from other server queries, only perform gethostbyname() * lookup on the specified hostnames for the client CellServDB files. */ if (_afsconf_IsClientConfigDirectory(adir->name) && !(acellInfo->flags & AFSCONF_CELL_FLAG_DNS_QUERIED)) { int j; short numServers=0; /*Num active servers for the cell */ struct sockaddr_in hostAddr[MAXHOSTSPERCELL]; /*IP addresses for cell's servers */ char hostName[MAXHOSTSPERCELL][MAXHOSTCHARS]; /*Names for cell's servers */ char clone[MAXHOSTSPERCELL]; /*Indicates which ones are clones. */ memset(&hostAddr, 0, sizeof(hostAddr)); memset(&hostName, 0, sizeof(hostName)); memset(&clone, 0, sizeof(clone)); for ( j=0; j<acellInfo->numServers && numServers < MAXHOSTSPERCELL; j++ ) { struct hostent *he = gethostbyname(acellInfo->hostName[j]); int foundAddr = 0; if (he && he->h_addrtype == AF_INET) { int i; /* obtain all the valid address from the list */ for (i=0 ; he->h_addr_list[i] && numServers < MAXHOSTSPERCELL; i++) { /* check to see if this is a new address; if so insert it into the list */ int k, dup; afs_uint32 addr; memcpy(&addr, he->h_addr_list[i], sizeof(addr)); for (k=0, dup=0; !dup && k < numServers; k++) { if (hostAddr[k].sin_addr.s_addr == addr) { dup = 1; } } if (dup) continue; hostAddr[numServers].sin_family = AF_INET; hostAddr[numServers].sin_port = acellInfo->hostAddr[0].sin_port; #ifdef STRUCT_SOCKADDR_HAS_SA_LEN hostAddr[numServers].sin_len = sizeof(struct sockaddr_in); #endif memcpy(&hostAddr[numServers].sin_addr.s_addr, he->h_addr_list[i], sizeof(afs_uint32)); strcpy(hostName[numServers], acellInfo->hostName[j]); clone[numServers] = acellInfo->clone[j]; foundAddr = 1; numServers++; } } if (!foundAddr) { hostAddr[numServers] = acellInfo->hostAddr[j]; strcpy(hostName[numServers], acellInfo->hostName[j]); clone[numServers] = acellInfo->clone[j]; numServers++; } } for (i=0; i<numServers; i++) { acellInfo->hostAddr[i] = hostAddr[i]; strcpy(acellInfo->hostName[i], hostName[i]); acellInfo->clone[i] = clone[i]; } acellInfo->numServers = numServers; acellInfo->flags |= AFSCONF_CELL_FLAG_DNS_QUERIED; } UNLOCK_GLOBAL_MUTEX; return 0; } else { UNLOCK_GLOBAL_MUTEX; return afsconf_GetAfsdbInfo(tcell, aservice, acellInfo); } }