2 * Copyright 2000, International Business Machines Corporation and others.
5 * This software has been released under the terms of the IBM Public
6 * License. For details, see the LICENSE file in the top-level source
7 * directory or online at http://www.openafs.org/dl/license10.html
10 /* This file implements configuration functions in the following categories:
11 * cfg_Client*() - perform minimally necessary client configuration.
14 #include <afsconfig.h>
15 #include <afs/param.h>
28 #include <rx/rxstat.h>
29 #include <afs/afs_Admin.h>
30 #include <afs/afs_AdminErrors.h>
31 #include <afs/afs_utilAdmin.h>
33 #include <afs/dirpath.h>
34 #include <afs/cellconfig.h>
35 #include <afs/kautils.h>
39 #include <WINNT/afsreg.h>
40 #include <WINNT/afssw.h>
41 #include <cellservdb.h>
44 #include "cfginternal.h"
45 #include "afs_cfgAdmin.h"
48 /* Local declarations and definitions */
50 #define CSDB_OP_ADD 0 /* add a client CellServDB entry */
51 #define CSDB_OP_REM 1 /* remove a client CellServDB entry */
54 ClientCellServDbUpdate(int updateOp, void *hostHandle, const char *cellName,
55 const char *dbentry, afs_status_p st);
58 CacheManagerStart(unsigned timeout, afs_status_p st);
61 CacheManagerStop(unsigned timeout, afs_status_p st);
66 /* ---------------- Exported AFS Client functions ------------------ */
70 * cfg_ClientQueryStatus() -- Query status of static client configuration
71 * on host, i.e., status of required configuration files, etc.
72 * Upon successful completion *configStP is set to the client
73 * configuration status, with a value of zero (0) indicating that
74 * the configuration is valid.
76 * If client configuration is not valid then *cellNameP is set to NULL;
77 * otherwise, *cellNameP is an allocated buffer containing client cell.
79 * If client software (cache-manager) is not installed then *versionP is
80 * undefined; otherwise *versionP is 34 for 3.4, 35 for 3.5, etc.
82 * Note: Client configuration is checked even if the client software
83 * is not installed. This is useful for tools that require
84 * client configuration information but NOT the actual
85 * client (cache-manager); for example, the AFS Server Manager.
88 cfg_ClientQueryStatus(const char *hostName, /* name of host */
89 short *isInstalledP, /* client software installed */
90 unsigned *versionP, /* client software version */
91 afs_status_p configStP, /* client config status */
92 char **cellNameP, /* client's cell */
94 { /* completion status */
96 afs_status_t tst2, tst = 0;
97 afs_status_t clientSt = 0;
98 char *clientCellName = NULL;
99 short cmInstalled = 0;
100 unsigned cmVersion = 0;
102 /* validate parameters */
104 if (hostName == NULL || *hostName == '\0') {
105 tst = ADMCFGHOSTNAMENULL;
106 } else if (strlen(hostName) > (MAXHOSTCHARS - 1)) {
107 tst = ADMCFGHOSTNAMETOOLONG;
108 } else if (isInstalledP == NULL) {
109 tst = ADMCFGINSTALLEDFLAGPNULL;
110 } else if (versionP == NULL) {
111 tst = ADMCFGVERSIONPNULL;
112 } else if (configStP == NULL) {
113 tst = ADMCFGCONFIGSTATUSPNULL;
114 } else if (cellNameP == NULL) {
115 tst = ADMCFGCELLNAMEPNULL;
118 /* remote configuration not yet supported; hostName must be local host */
123 if (!cfgutil_HostNameIsLocal(hostName, &isLocal, &tst2)) {
125 } else if (!isLocal) {
126 tst = ADMCFGNOTSUPPORTED;
130 /* determine if client software (CM) is installed and if so what version */
133 /* Windows - cache manager is a service */
137 if (!cfgutil_WindowsServiceQuery
138 (AFSREG_CLT_SVC_NAME, &svcState, &tst2)) {
139 /* CM not installed, or insufficient privilege to check */
140 if (tst2 == ADMNOPRIV) {
146 /* CM installed, get version */
147 unsigned major, minor, patch;
151 if (afssw_GetClientVersion(&major, &minor, &patch)) {
152 /* failed to retrieve version information */
153 if (errno == EACCES) {
156 tst = ADMCFGCLIENTVERSIONNOTREAD;
159 cmVersion = (major * 10) + minor;
165 /* function not yet implemented for Unix */
166 tst = ADMCFGNOTSUPPORTED;
168 #endif /* AFS_NT40_ENV */
171 /* check static client configuration; not necessary that client
172 * software (CM) be installed for this information to be valid and useable.
176 struct afsconf_dir *confdir;
178 if ((confdir = afsconf_Open(AFSDIR_CLIENT_ETC_DIRPATH)) == NULL) {
179 /* the client configuration appears to be missing/invalid */
180 clientSt = ADMCFGCLIENTBASICINFOINVALID;
182 struct afsconf_entry *cellentry;
184 if (confdir->cellName == NULL || *confdir->cellName == '\0') {
185 /* no cell set for client */
186 clientSt = ADMCFGCLIENTNOTINCELL;
188 for (cellentry = confdir->entries; cellentry != NULL;
189 cellentry = cellentry->next) {
191 (confdir->cellName, cellentry->cellInfo.name)) {
196 if (cellentry == NULL) {
197 clientSt = ADMCFGCLIENTCELLNOTINDB;
198 } else if (cellentry->cellInfo.numServers <= 0) {
199 clientSt = ADMCFGCLIENTCELLHASNODBENTRIES;
203 if (tst == 0 && clientSt == 0) {
204 /* everything looks good; malloc cell name buffer to return */
206 (char *)malloc(strlen(cellentry->cellInfo.name) + 1);
207 if (clientCellName == NULL) {
210 strcpy(clientCellName, cellentry->cellInfo.name);
214 (void)afsconf_Close(confdir);
218 /* return result of query */
221 /* return client status and cell name */
222 *isInstalledP = cmInstalled;
223 *versionP = cmVersion;
224 *configStP = clientSt;
227 *cellNameP = clientCellName;
232 /* indicate failure */
235 /* free cell name if allocated before failure */
236 if (clientCellName != NULL) {
237 free(clientCellName);
248 * cfg_ClientSetCell() -- Define default client cell for host.
250 * The cellDbHosts argument is a multistring containing the names of
251 * the existing database servers already configured in the cell; this
252 * multistring list can be obtained via cfg_CellServDbEnumerate().
253 * If configuring the first server in a new cell then the cellDbHosts
254 * list contains only the name of that host.
256 * Warning: client (cache-manager) should be stopped prior to setting cell.
259 cfg_ClientSetCell(void *hostHandle, /* host config handle */
260 const char *cellName, /* cell name */
261 const char *cellDbHosts, /* cell database hosts */
263 { /* completion status */
265 afs_status_t tst2, tst = 0;
266 cfg_host_p cfg_host = (cfg_host_p) hostHandle;
268 /* validate parameters */
270 if (!cfgutil_HostHandleValidate(cfg_host, &tst2)) {
272 } else if (cellName == NULL || *cellName == '\0') {
273 tst = ADMCFGCELLNAMENULL;
274 } else if (strlen(cellName) > (MAXCELLCHARS - 1)) {
275 tst = ADMCFGCELLNAMETOOLONG;
276 } else if (!cfgutil_HostHandleCellNameCompatible(cfg_host, cellName)) {
277 tst = ADMCFGCELLNAMECONFLICT;
278 } else if (cellDbHosts == NULL || *cellDbHosts == '\0') {
279 tst = ADMCFGCELLDBHOSTSNULL;
282 /* remote configuration not yet supported in this function */
285 if (!cfg_host->is_local) {
286 tst = ADMCFGNOTSUPPORTED;
290 /* define cell database hosts */
296 if (!CSDB_ReadFile(&clientDb, AFSDIR_CLIENT_CELLSERVDB_FILEPATH)) {
297 tst = ADMCFGCLIENTCELLSERVDBNOTREAD;
299 CELLDBLINE *cellLinep = CSDB_FindCell(&clientDb, cellName);
301 if (cellLinep != NULL) {
302 /* cell entry exists; remove host entries */
303 if (!CSDB_RemoveCellServers(&clientDb, cellLinep)) {
304 /* should never happen */
305 tst = ADMCFGCLIENTCELLSERVDBEDITFAILED;
308 /* cell entry does not exist; add it */
309 cellLinep = CSDB_AddCell(&clientDb, cellName, NULL, NULL);
311 if (cellLinep == NULL) {
317 /* add new host entries to cell */
318 const char *dbHost = cellDbHosts;
321 while (*dbHost != '\0' && tst == 0) {
322 size_t dbHostLen = strlen(dbHost);
323 const char *dbHostAddrStr;
325 if (dbHostLen > (MAXHOSTCHARS - 1)) {
326 tst = ADMCFGHOSTNAMETOOLONG;
327 } else if (dbHostCount >= MAXHOSTSPERCELL) {
328 tst = ADMCFGCELLDBHOSTCOUNTTOOLARGE;
330 if (!cfgutil_HostNameGetAddressString
331 (dbHost, &dbHostAddrStr, &tst2)) {
334 if (CSDB_AddCellServer
335 (&clientDb, cellLinep, dbHostAddrStr,
340 dbHost += dbHostLen + 1;
345 /* edit successful; write CellServDB */
346 if (!CSDB_WriteFile(&clientDb)) {
347 tst = ADMCFGCLIENTCELLSERVDBNOTWRITTEN;
352 CSDB_FreeFile(&clientDb);
357 /* function not yet implemented for Unix */
358 tst = ADMCFGNOTSUPPORTED;
360 #endif /* AFS_NT40_ENV */
363 /* define default client cell */
367 if (afssw_SetClientCellName(cellName)) {
368 /* failed to set cell name in registry (ThisCell equivalent) */
369 if (errno == EACCES) {
372 tst = ADMCFGCLIENTTHISCELLNOTWRITTEN;
378 /* function not yet implemented for Unix */
379 tst = ADMCFGNOTSUPPORTED;
381 #endif /* AFS_NT40_ENV */
384 /* help any underlying packages adjust to cell change */
389 if ((rc = ka_CellConfig(AFSDIR_CLIENT_ETC_DIRPATH)) != 0) {
405 * cfg_ClientCellServDbAdd() -- Add entry to client CellServDB on host.
408 cfg_ClientCellServDbAdd(void *hostHandle, /* host config handle */
409 const char *cellName, /* cell name */
410 const char *dbentry, /* cell database entry */
412 { /* completion status */
413 return ClientCellServDbUpdate(CSDB_OP_ADD, hostHandle, cellName, dbentry,
419 * cfg_ClientCellServDbRemove() -- Remove entry from client CellServDB
423 cfg_ClientCellServDbRemove(void *hostHandle, /* host config handle */
424 const char *cellName, /* cell name */
425 const char *dbentry, /* cell database entry */
427 { /* completion status */
428 return ClientCellServDbUpdate(CSDB_OP_REM, hostHandle, cellName, dbentry,
434 * cfg_ClientStop() -- Stop the client (cache manager) on host.
436 * Timeout is the maximum time (in seconds) to wait for client to stop.
439 cfg_ClientStop(void *hostHandle, /* host config handle */
440 unsigned int timeout, /* timeout in seconds */
442 { /* completion status */
444 afs_status_t tst2, tst = 0;
445 cfg_host_p cfg_host = (cfg_host_p) hostHandle;
447 /* validate parameters */
449 if (!cfgutil_HostHandleValidate(cfg_host, &tst2)) {
453 /* remote configuration not yet supported in this function */
456 if (!cfg_host->is_local) {
457 tst = ADMCFGNOTSUPPORTED;
464 if (!CacheManagerStop(timeout, &tst2)) {
470 /* indicate failure */
481 * cfg_ClientStart() -- Start the client (cache manager) on host.
483 * Timeout is the maximum time (in seconds) to wait for client to start.
486 cfg_ClientStart(void *hostHandle, /* host config handle */
487 unsigned int timeout, /* timeout in seconds */
489 { /* completion status */
491 afs_status_t tst2, tst = 0;
492 cfg_host_p cfg_host = (cfg_host_p) hostHandle;
494 /* validate parameters */
496 if (!cfgutil_HostHandleValidate(cfg_host, &tst2)) {
500 /* remote configuration not yet supported in this function */
503 if (!cfg_host->is_local) {
504 tst = ADMCFGNOTSUPPORTED;
511 if (!CacheManagerStart(timeout, &tst2)) {
517 /* indicate failure */
528 /* ---------------- Local functions ------------------ */
532 * ClientCellServDbUpdate() -- add or remove a client CellServDB entry.
534 * Common function implementing cfg_ClientCellServDb{Add/Remove}().
537 ClientCellServDbUpdate(int updateOp, void *hostHandle, const char *cellName,
538 const char *dbentry, afs_status_p st)
541 afs_status_t tst2, tst = 0;
542 cfg_host_p cfg_host = (cfg_host_p) hostHandle;
543 char dbentryFull[MAXHOSTCHARS];
545 /* validate parameters and resolve dbentry to fully qualified name */
547 if (!cfgutil_HostHandleValidate(cfg_host, &tst2)) {
549 } else if (cellName == NULL || *cellName == '\0') {
550 tst = ADMCFGCELLNAMENULL;
551 } else if (strlen(cellName) > (MAXCELLCHARS - 1)) {
552 tst = ADMCFGCELLNAMETOOLONG;
553 } else if (dbentry == NULL || *dbentry == '\0') {
554 tst = ADMCFGHOSTNAMENULL;
555 } else if (strlen(dbentry) > (MAXHOSTCHARS - 1)) {
556 tst = ADMCFGHOSTNAMETOOLONG;
557 } else if (!cfgutil_HostNameGetFull(dbentry, dbentryFull, &tst2)) {
561 /* remote configuration not yet supported in this function */
564 if (!cfg_host->is_local) {
565 tst = ADMCFGNOTSUPPORTED;
569 /* modify local client CellServDB entry for specified cell */
575 if (!CSDB_ReadFile(&clientDb, AFSDIR_CLIENT_CELLSERVDB_FILEPATH)) {
576 tst = ADMCFGCLIENTCELLSERVDBNOTREAD;
578 CELLDBLINE *cellLinep = CSDB_FindCell(&clientDb, cellName);
579 CELLDBLINE *serverLinep = NULL;
580 int serverLineCount = 0;
582 if (cellLinep != NULL) {
583 /* found cellName, now find server to add/remove */
584 CELLDBLINE *workingLinep;
586 for (workingLinep = cellLinep->pNext; workingLinep != NULL;
587 workingLinep = workingLinep->pNext) {
588 CELLDBLINEINFO lineInfo;
590 if (!CSDB_CrackLine(&lineInfo, workingLinep->szLine)) {
591 /* not a server (or cell) line; perhaps a comment */
593 } else if (lineInfo.szCell[0] != '\0') {
594 /* hit a new cell line */
597 /* found a server line; check if is host of interest */
599 int dbentryAddr = ntohl(lineInfo.ipServer);
603 if (!cfgutil_HostAddressIsValid
604 (dbentryFull, dbentryAddr, &isValid, &tst2)) {
607 } else if (isValid) {
608 /* found server of interest */
609 serverLinep = workingLinep;
617 if (updateOp == CSDB_OP_ADD && serverLinep == NULL) {
618 if (cellLinep == NULL) {
620 CSDB_AddCell(&clientDb, cellName, NULL, NULL);
623 if (cellLinep == NULL) {
625 } else if (serverLineCount >= MAXHOSTSPERCELL) {
626 tst = ADMCFGCLIENTCELLSERVDBNOSPACE;
628 const char *dbentryAddrStr;
630 if (!cfgutil_HostNameGetAddressString
631 (dbentryFull, &dbentryAddrStr, &tst2)) {
635 CSDB_AddCellServer(&clientDb, cellLinep,
638 if (serverLinep == NULL) {
643 } else if (updateOp == CSDB_OP_REM && serverLinep != NULL) {
644 (void)CSDB_RemoveLine(&clientDb, serverLinep);
648 if (!CSDB_WriteFile(&clientDb)) {
649 tst = ADMCFGCLIENTCELLSERVDBNOTWRITTEN;
654 CSDB_FreeFile(&clientDb);
659 /* function not yet implemented for Unix */
660 tst = ADMCFGNOTSUPPORTED;
662 #endif /* AFS_NT40_ENV */
665 /* indicate failure */
676 * CacheManagerStart() -- Start the local AFS cache manager.
678 * Timeout is the maximum time (in seconds) to wait for the CM to start.
680 * RETURN CODES: 1 success, 0 failure (st indicates why)
683 CacheManagerStart(unsigned timeout, afs_status_p st)
689 afs_status_t tst = 0;
692 /* Windows - cache manager is a service */
695 if (!cfgutil_WindowsServiceStart
696 (AFSREG_CLT_SVC_NAME, 0, NULL, timeout, &wasRunning, &tst2)) {
700 /* function not yet implemented for Unix */
701 tst = ADMCFGNOTSUPPORTED;
702 #endif /* AFS_NT40_ENV */
705 /* indicate failure */
716 * CacheManagerStop() -- Stop the local AFS cache manager.
718 * Timeout is the maximum time (in seconds) to wait for the CM to stop.
720 * RETURN CODES: 1 success, 0 failure (st indicates why)
723 CacheManagerStop(unsigned timeout, afs_status_p st)
729 afs_status_t tst = 0;
732 /* Windows - cache manager is a service */
735 if (!cfgutil_WindowsServiceStop
736 (AFSREG_CLT_SVC_NAME, timeout, &wasStopped, &tst2)) {
740 /* function not yet implemented for Unix */
741 tst = ADMCFGNOTSUPPORTED;
742 #endif /* AFS_NT40_ENV */
745 /* indicate failure */