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>
37 #include <afs/afs_Admin.h>
38 #include <afs/afs_AdminErrors.h>
39 #include <afs/afs_utilAdmin.h>
41 #include <afs/dirpath.h>
42 #include <afs/cellconfig.h>
46 #include <WINNT/afsreg.h>
47 #include <WINNT/afssw.h>
48 #include <cellservdb.h>
51 #include "cfginternal.h"
52 #include "afs_cfgAdmin.h"
55 /* Local declarations and definitions */
57 #define CSDB_OP_ADD 0 /* add a client CellServDB entry */
58 #define CSDB_OP_REM 1 /* remove a client CellServDB entry */
61 ClientCellServDbUpdate(int updateOp, void *hostHandle, const char *cellName,
62 const char *dbentry, afs_status_p st);
65 CacheManagerStart(unsigned timeout, afs_status_p st);
68 CacheManagerStop(unsigned timeout, afs_status_p st);
73 /* ---------------- Exported AFS Client functions ------------------ */
77 * cfg_ClientQueryStatus() -- Query status of static client configuration
78 * on host, i.e., status of required configuration files, etc.
79 * Upon successful completion *configStP is set to the client
80 * configuration status, with a value of zero (0) indicating that
81 * the configuration is valid.
83 * If client configuration is not valid then *cellNameP is set to NULL;
84 * otherwise, *cellNameP is an allocated buffer containing client cell.
86 * If client software (cache-manager) is not installed then *versionP is
87 * undefined; otherwise *versionP is 34 for 3.4, 35 for 3.5, etc.
89 * Note: Client configuration is checked even if the client software
90 * is not installed. This is useful for tools that require
91 * client configuration information but NOT the actual
92 * client (cache-manager); for example, the AFS Server Manager.
95 cfg_ClientQueryStatus(const char *hostName, /* name of host */
96 short *isInstalledP, /* client software installed */
97 unsigned *versionP, /* client software version */
98 afs_status_p configStP, /* client config status */
99 char **cellNameP, /* client's cell */
101 { /* completion status */
103 afs_status_t tst2, tst = 0;
104 afs_status_t clientSt = 0;
105 char *clientCellName = NULL;
106 short cmInstalled = 0;
109 /* validate parameters */
111 if (hostName == NULL || *hostName == '\0') {
112 tst = ADMCFGHOSTNAMENULL;
113 } else if (strlen(hostName) > (MAXHOSTCHARS - 1)) {
114 tst = ADMCFGHOSTNAMETOOLONG;
115 } else if (isInstalledP == NULL) {
116 tst = ADMCFGINSTALLEDFLAGPNULL;
117 } else if (versionP == NULL) {
118 tst = ADMCFGVERSIONPNULL;
119 } else if (configStP == NULL) {
120 tst = ADMCFGCONFIGSTATUSPNULL;
121 } else if (cellNameP == NULL) {
122 tst = ADMCFGCELLNAMEPNULL;
125 /* remote configuration not yet supported; hostName must be local host */
130 if (!cfgutil_HostNameIsLocal(hostName, &isLocal, &tst2)) {
132 } else if (!isLocal) {
133 tst = ADMCFGNOTSUPPORTED;
137 /* determine if client software (CM) is installed and if so what version */
140 /* Windows - cache manager is a service */
144 if (!cfgutil_WindowsServiceQuery
145 (AFSREG_CLT_SVC_NAME, &svcState, &tst2)) {
146 /* CM not installed, or insufficient privilege to check */
147 if (tst2 == ADMNOPRIV) {
153 /* CM installed, get version */
154 unsigned major, minor, patch;
158 if (afssw_GetClientVersion(&major, &minor, &patch)) {
159 /* failed to retrieve version information */
160 if (errno == EACCES) {
163 tst = ADMCFGCLIENTVERSIONNOTREAD;
166 cmVersion = (major * 10) + minor;
172 /* function not yet implemented for Unix */
173 tst = ADMCFGNOTSUPPORTED;
175 #endif /* AFS_NT40_ENV */
178 /* check static client configuration; not necessary that client
179 * software (CM) be installed for this information to be valid and useable.
183 struct afsconf_dir *confdir;
185 if ((confdir = afsconf_Open(AFSDIR_CLIENT_ETC_DIRPATH)) == NULL) {
186 /* the client configuration appears to be missing/invalid */
187 clientSt = ADMCFGCLIENTBASICINFOINVALID;
189 struct afsconf_entry *cellentry;
191 if (confdir->cellName == NULL || *confdir->cellName == '\0') {
192 /* no cell set for client */
193 clientSt = ADMCFGCLIENTNOTINCELL;
195 for (cellentry = confdir->entries; cellentry != NULL;
196 cellentry = cellentry->next) {
198 (confdir->cellName, cellentry->cellInfo.name)) {
203 if (cellentry == NULL) {
204 clientSt = ADMCFGCLIENTCELLNOTINDB;
205 } else if (cellentry->cellInfo.numServers <= 0) {
206 clientSt = ADMCFGCLIENTCELLHASNODBENTRIES;
210 if (tst == 0 && clientSt == 0) {
211 /* everything looks good; malloc cell name buffer to return */
213 (char *)malloc(strlen(cellentry->cellInfo.name) + 1);
214 if (clientCellName == NULL) {
217 strcpy(clientCellName, cellentry->cellInfo.name);
221 (void)afsconf_Close(confdir);
225 /* return result of query */
228 /* return client status and cell name */
229 *isInstalledP = cmInstalled;
230 *versionP = cmVersion;
231 *configStP = clientSt;
234 *cellNameP = clientCellName;
239 /* indicate failure */
242 /* free cell name if allocated before failure */
243 if (clientCellName != NULL) {
244 free(clientCellName);
255 * cfg_ClientSetCell() -- Define default client cell for host.
257 * The cellDbHosts argument is a multistring containing the names of
258 * the existing database servers already configured in the cell; this
259 * multistring list can be obtained via cfg_CellServDbEnumerate().
260 * If configuring the first server in a new cell then the cellDbHosts
261 * list contains only the name of that host.
263 * Warning: client (cache-manager) should be stopped prior to setting cell.
266 cfg_ClientSetCell(void *hostHandle, /* host config handle */
267 const char *cellName, /* cell name */
268 const char *cellDbHosts, /* cell database hosts */
270 { /* completion status */
272 afs_status_t tst2, tst = 0;
273 cfg_host_p cfg_host = (cfg_host_p) hostHandle;
275 /* validate parameters */
277 if (!cfgutil_HostHandleValidate(cfg_host, &tst2)) {
279 } else if (cellName == NULL || *cellName == '\0') {
280 tst = ADMCFGCELLNAMENULL;
281 } else if (strlen(cellName) > (MAXCELLCHARS - 1)) {
282 tst = ADMCFGCELLNAMETOOLONG;
283 } else if (!cfgutil_HostHandleCellNameCompatible(cfg_host, cellName)) {
284 tst = ADMCFGCELLNAMECONFLICT;
285 } else if (cellDbHosts == NULL || *cellDbHosts == '\0') {
286 tst = ADMCFGCELLDBHOSTSNULL;
289 /* remote configuration not yet supported in this function */
292 if (!cfg_host->is_local) {
293 tst = ADMCFGNOTSUPPORTED;
297 /* define cell database hosts */
303 if (!CSDB_ReadFile(&clientDb, AFSDIR_CLIENT_CELLSERVDB_FILEPATH)) {
304 tst = ADMCFGCLIENTCELLSERVDBNOTREAD;
306 CELLDBLINE *cellLinep = CSDB_FindCell(&clientDb, cellName);
308 if (cellLinep != NULL) {
309 /* cell entry exists; remove host entries */
310 if (!CSDB_RemoveCellServers(&clientDb, cellLinep)) {
311 /* should never happen */
312 tst = ADMCFGCLIENTCELLSERVDBEDITFAILED;
315 /* cell entry does not exist; add it */
316 cellLinep = CSDB_AddCell(&clientDb, cellName, NULL, NULL);
318 if (cellLinep == NULL) {
324 /* add new host entries to cell */
325 const char *dbHost = cellDbHosts;
328 while (*dbHost != '\0' && tst == 0) {
329 size_t dbHostLen = strlen(dbHost);
330 const char *dbHostAddrStr;
332 if (dbHostLen > (MAXHOSTCHARS - 1)) {
333 tst = ADMCFGHOSTNAMETOOLONG;
334 } else if (dbHostCount >= MAXHOSTSPERCELL) {
335 tst = ADMCFGCELLDBHOSTCOUNTTOOLARGE;
337 if (!cfgutil_HostNameGetAddressString
338 (dbHost, &dbHostAddrStr, &tst2)) {
341 if (CSDB_AddCellServer
342 (&clientDb, cellLinep, dbHostAddrStr,
347 dbHost += dbHostLen + 1;
352 /* edit successful; write CellServDB */
353 if (!CSDB_WriteFile(&clientDb)) {
354 tst = ADMCFGCLIENTCELLSERVDBNOTWRITTEN;
359 CSDB_FreeFile(&clientDb);
364 /* function not yet implemented for Unix */
365 tst = ADMCFGNOTSUPPORTED;
367 #endif /* AFS_NT40_ENV */
370 /* define default client cell */
374 if (afssw_SetClientCellName(cellName)) {
375 /* failed to set cell name in registry (ThisCell equivalent) */
376 if (errno == EACCES) {
379 tst = ADMCFGCLIENTTHISCELLNOTWRITTEN;
385 /* function not yet implemented for Unix */
386 tst = ADMCFGNOTSUPPORTED;
388 #endif /* AFS_NT40_ENV */
391 /* help any underlying packages adjust to cell change */
396 if ((rc = ka_CellConfig(AFSDIR_CLIENT_ETC_DIRPATH)) != 0) {
412 * cfg_ClientCellServDbAdd() -- Add entry to client CellServDB on host.
415 cfg_ClientCellServDbAdd(void *hostHandle, /* host config handle */
416 const char *cellName, /* cell name */
417 const char *dbentry, /* cell database entry */
419 { /* completion status */
420 return ClientCellServDbUpdate(CSDB_OP_ADD, hostHandle, cellName, dbentry,
426 * cfg_ClientCellServDbRemove() -- Remove entry from client CellServDB
430 cfg_ClientCellServDbRemove(void *hostHandle, /* host config handle */
431 const char *cellName, /* cell name */
432 const char *dbentry, /* cell database entry */
434 { /* completion status */
435 return ClientCellServDbUpdate(CSDB_OP_REM, hostHandle, cellName, dbentry,
441 * cfg_ClientStop() -- Stop the client (cache manager) on host.
443 * Timeout is the maximum time (in seconds) to wait for client to stop.
446 cfg_ClientStop(void *hostHandle, /* host config handle */
447 unsigned int timeout, /* timeout in seconds */
449 { /* completion status */
451 afs_status_t tst2, tst = 0;
452 cfg_host_p cfg_host = (cfg_host_p) hostHandle;
454 /* validate parameters */
456 if (!cfgutil_HostHandleValidate(cfg_host, &tst2)) {
460 /* remote configuration not yet supported in this function */
463 if (!cfg_host->is_local) {
464 tst = ADMCFGNOTSUPPORTED;
471 if (!CacheManagerStop(timeout, &tst2)) {
477 /* indicate failure */
488 * cfg_ClientStart() -- Start the client (cache manager) on host.
490 * Timeout is the maximum time (in seconds) to wait for client to start.
493 cfg_ClientStart(void *hostHandle, /* host config handle */
494 unsigned int timeout, /* timeout in seconds */
496 { /* completion status */
498 afs_status_t tst2, tst = 0;
499 cfg_host_p cfg_host = (cfg_host_p) hostHandle;
501 /* validate parameters */
503 if (!cfgutil_HostHandleValidate(cfg_host, &tst2)) {
507 /* remote configuration not yet supported in this function */
510 if (!cfg_host->is_local) {
511 tst = ADMCFGNOTSUPPORTED;
518 if (!CacheManagerStart(timeout, &tst2)) {
524 /* indicate failure */
535 /* ---------------- Local functions ------------------ */
539 * ClientCellServDbUpdate() -- add or remove a client CellServDB entry.
541 * Common function implementing cfg_ClientCellServDb{Add/Remove}().
544 ClientCellServDbUpdate(int updateOp, void *hostHandle, const char *cellName,
545 const char *dbentry, afs_status_p st)
548 afs_status_t tst2, tst = 0;
549 cfg_host_p cfg_host = (cfg_host_p) hostHandle;
550 char dbentryFull[MAXHOSTCHARS];
552 /* validate parameters and resolve dbentry to fully qualified name */
554 if (!cfgutil_HostHandleValidate(cfg_host, &tst2)) {
556 } else if (cellName == NULL || *cellName == '\0') {
557 tst = ADMCFGCELLNAMENULL;
558 } else if (strlen(cellName) > (MAXCELLCHARS - 1)) {
559 tst = ADMCFGCELLNAMETOOLONG;
560 } else if (dbentry == NULL || *dbentry == '\0') {
561 tst = ADMCFGHOSTNAMENULL;
562 } else if (strlen(dbentry) > (MAXHOSTCHARS - 1)) {
563 tst = ADMCFGHOSTNAMETOOLONG;
564 } else if (!cfgutil_HostNameGetFull(dbentry, dbentryFull, &tst2)) {
568 /* remote configuration not yet supported in this function */
571 if (!cfg_host->is_local) {
572 tst = ADMCFGNOTSUPPORTED;
576 /* modify local client CellServDB entry for specified cell */
582 if (!CSDB_ReadFile(&clientDb, AFSDIR_CLIENT_CELLSERVDB_FILEPATH)) {
583 tst = ADMCFGCLIENTCELLSERVDBNOTREAD;
585 CELLDBLINE *cellLinep = CSDB_FindCell(&clientDb, cellName);
586 CELLDBLINE *serverLinep = NULL;
587 int serverLineCount = 0;
589 if (cellLinep != NULL) {
590 /* found cellName, now find server to add/remove */
591 CELLDBLINE *workingLinep;
593 for (workingLinep = cellLinep->pNext; workingLinep != NULL;
594 workingLinep = workingLinep->pNext) {
595 CELLDBLINEINFO lineInfo;
597 if (!CSDB_CrackLine(&lineInfo, workingLinep->szLine)) {
598 /* not a server (or cell) line; perhaps a comment */
600 } else if (lineInfo.szCell[0] != '\0') {
601 /* hit a new cell line */
604 /* found a server line; check if is host of interest */
606 int dbentryAddr = ntohl(lineInfo.ipServer);
610 if (!cfgutil_HostAddressIsValid
611 (dbentryFull, dbentryAddr, &isValid, &tst2)) {
614 } else if (isValid) {
615 /* found server of interest */
616 serverLinep = workingLinep;
624 if (updateOp == CSDB_OP_ADD && serverLinep == NULL) {
625 if (cellLinep == NULL) {
627 CSDB_AddCell(&clientDb, cellName, NULL, NULL);
630 if (cellLinep == NULL) {
632 } else if (serverLineCount >= MAXHOSTSPERCELL) {
633 tst = ADMCFGCLIENTCELLSERVDBNOSPACE;
635 const char *dbentryAddrStr;
637 if (!cfgutil_HostNameGetAddressString
638 (dbentryFull, &dbentryAddrStr, &tst2)) {
642 CSDB_AddCellServer(&clientDb, cellLinep,
645 if (serverLinep == NULL) {
650 } else if (updateOp == CSDB_OP_REM && serverLinep != NULL) {
651 (void)CSDB_RemoveLine(&clientDb, serverLinep);
655 if (!CSDB_WriteFile(&clientDb)) {
656 tst = ADMCFGCLIENTCELLSERVDBNOTWRITTEN;
661 CSDB_FreeFile(&clientDb);
666 /* function not yet implemented for Unix */
667 tst = ADMCFGNOTSUPPORTED;
669 #endif /* AFS_NT40_ENV */
672 /* indicate failure */
683 * CacheManagerStart() -- Start the local AFS cache manager.
685 * Timeout is the maximum time (in seconds) to wait for the CM to start.
687 * RETURN CODES: 1 success, 0 failure (st indicates why)
690 CacheManagerStart(unsigned timeout, afs_status_p st)
693 afs_status_t tst2, tst = 0;
696 /* Windows - cache manager is a service */
699 if (!cfgutil_WindowsServiceStart
700 (AFSREG_CLT_SVC_NAME, 0, NULL, timeout, &wasRunning, &tst2)) {
704 /* function not yet implemented for Unix */
705 tst = ADMCFGNOTSUPPORTED;
706 #endif /* AFS_NT40_ENV */
709 /* indicate failure */
720 * CacheManagerStop() -- Stop the local AFS cache manager.
722 * Timeout is the maximum time (in seconds) to wait for the CM to stop.
724 * RETURN CODES: 1 success, 0 failure (st indicates why)
727 CacheManagerStop(unsigned timeout, afs_status_p st)
730 afs_status_t tst2, tst = 0;
733 /* Windows - cache manager is a service */
736 if (!cfgutil_WindowsServiceStop
737 (AFSREG_CLT_SVC_NAME, timeout, &wasStopped, &tst2)) {
741 /* function not yet implemented for Unix */
742 tst = ADMCFGNOTSUPPORTED;
743 #endif /* AFS_NT40_ENV */
746 /* indicate failure */