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>
21 #include <rx/rxstat.h>
22 #include <afs/afs_Admin.h>
23 #include <afs/afs_AdminErrors.h>
24 #include <afs/afs_utilAdmin.h>
25 #include <afs/dirpath.h>
26 #include <afs/cellconfig.h>
27 #include <afs/kautils.h>
31 #include <WINNT/afsreg.h>
32 #include <WINNT/afssw.h>
33 #include <cellservdb.h>
36 #include "cfginternal.h"
37 #include "afs_cfgAdmin.h"
40 /* Local declarations and definitions */
42 #define CSDB_OP_ADD 0 /* add a client CellServDB entry */
43 #define CSDB_OP_REM 1 /* remove a client CellServDB entry */
46 ClientCellServDbUpdate(int updateOp, void *hostHandle, const char *cellName,
47 const char *dbentry, afs_status_p st);
50 CacheManagerStart(unsigned timeout, afs_status_p st);
53 CacheManagerStop(unsigned timeout, afs_status_p st);
58 /* ---------------- Exported AFS Client functions ------------------ */
62 * cfg_ClientQueryStatus() -- Query status of static client configuration
63 * on host, i.e., status of required configuration files, etc.
64 * Upon successful completion *configStP is set to the client
65 * configuration status, with a value of zero (0) indicating that
66 * the configuration is valid.
68 * If client configuration is not valid then *cellNameP is set to NULL;
69 * otherwise, *cellNameP is an allocated buffer containing client cell.
71 * If client software (cache-manager) is not installed then *versionP is
72 * undefined; otherwise *versionP is 34 for 3.4, 35 for 3.5, etc.
74 * Note: Client configuration is checked even if the client software
75 * is not installed. This is useful for tools that require
76 * client configuration information but NOT the actual
77 * client (cache-manager); for example, the AFS Server Manager.
80 cfg_ClientQueryStatus(const char *hostName, /* name of host */
81 short *isInstalledP, /* client software installed */
82 unsigned *versionP, /* client software version */
83 afs_status_p configStP, /* client config status */
84 char **cellNameP, /* client's cell */
86 { /* completion status */
88 afs_status_t tst2, tst = 0;
89 afs_status_t clientSt = 0;
90 char *clientCellName = NULL;
91 short cmInstalled = 0;
92 unsigned cmVersion = 0;
94 /* validate parameters */
96 if (hostName == NULL || *hostName == '\0') {
97 tst = ADMCFGHOSTNAMENULL;
98 } else if (strlen(hostName) > (MAXHOSTCHARS - 1)) {
99 tst = ADMCFGHOSTNAMETOOLONG;
100 } else if (isInstalledP == NULL) {
101 tst = ADMCFGINSTALLEDFLAGPNULL;
102 } else if (versionP == NULL) {
103 tst = ADMCFGVERSIONPNULL;
104 } else if (configStP == NULL) {
105 tst = ADMCFGCONFIGSTATUSPNULL;
106 } else if (cellNameP == NULL) {
107 tst = ADMCFGCELLNAMEPNULL;
110 /* remote configuration not yet supported; hostName must be local host */
115 if (!cfgutil_HostNameIsLocal(hostName, &isLocal, &tst2)) {
117 } else if (!isLocal) {
118 tst = ADMCFGNOTSUPPORTED;
122 /* determine if client software (CM) is installed and if so what version */
125 /* Windows - cache manager is a service */
129 if (!cfgutil_WindowsServiceQuery
130 (AFSREG_CLT_SVC_NAME, &svcState, &tst2)) {
131 /* CM not installed, or insufficient privilege to check */
132 if (tst2 == ADMNOPRIV) {
138 /* CM installed, get version */
139 unsigned major, minor, patch;
143 if (afssw_GetClientVersion(&major, &minor, &patch)) {
144 /* failed to retrieve version information */
145 if (errno == EACCES) {
148 tst = ADMCFGCLIENTVERSIONNOTREAD;
151 cmVersion = (major * 10) + minor;
157 /* function not yet implemented for Unix */
158 tst = ADMCFGNOTSUPPORTED;
160 #endif /* AFS_NT40_ENV */
163 /* check static client configuration; not necessary that client
164 * software (CM) be installed for this information to be valid and useable.
168 struct afsconf_dir *confdir;
170 if ((confdir = afsconf_Open(AFSDIR_CLIENT_ETC_DIRPATH)) == NULL) {
171 /* the client configuration appears to be missing/invalid */
172 clientSt = ADMCFGCLIENTBASICINFOINVALID;
174 struct afsconf_entry *cellentry;
176 if (confdir->cellName == NULL || *confdir->cellName == '\0') {
177 /* no cell set for client */
178 clientSt = ADMCFGCLIENTNOTINCELL;
180 for (cellentry = confdir->entries; cellentry != NULL;
181 cellentry = cellentry->next) {
183 (confdir->cellName, cellentry->cellInfo.name)) {
188 if (cellentry == NULL) {
189 clientSt = ADMCFGCLIENTCELLNOTINDB;
190 } else if (cellentry->cellInfo.numServers <= 0) {
191 clientSt = ADMCFGCLIENTCELLHASNODBENTRIES;
195 if (tst == 0 && clientSt == 0) {
196 /* everything looks good; malloc cell name buffer to return */
198 (char *)malloc(strlen(cellentry->cellInfo.name) + 1);
199 if (clientCellName == NULL) {
202 strcpy(clientCellName, cellentry->cellInfo.name);
206 (void)afsconf_Close(confdir);
210 /* return result of query */
213 /* return client status and cell name */
214 *isInstalledP = cmInstalled;
215 *versionP = cmVersion;
216 *configStP = clientSt;
219 *cellNameP = clientCellName;
224 /* indicate failure */
227 /* free cell name if allocated before failure */
228 if (clientCellName != NULL) {
229 free(clientCellName);
240 * cfg_ClientSetCell() -- Define default client cell for host.
242 * The cellDbHosts argument is a multistring containing the names of
243 * the existing database servers already configured in the cell; this
244 * multistring list can be obtained via cfg_CellServDbEnumerate().
245 * If configuring the first server in a new cell then the cellDbHosts
246 * list contains only the name of that host.
248 * Warning: client (cache-manager) should be stopped prior to setting cell.
251 cfg_ClientSetCell(void *hostHandle, /* host config handle */
252 const char *cellName, /* cell name */
253 const char *cellDbHosts, /* cell database hosts */
255 { /* completion status */
257 afs_status_t tst2, tst = 0;
258 cfg_host_p cfg_host = (cfg_host_p) hostHandle;
260 /* validate parameters */
262 if (!cfgutil_HostHandleValidate(cfg_host, &tst2)) {
264 } else if (cellName == NULL || *cellName == '\0') {
265 tst = ADMCFGCELLNAMENULL;
266 } else if (strlen(cellName) > (MAXCELLCHARS - 1)) {
267 tst = ADMCFGCELLNAMETOOLONG;
268 } else if (!cfgutil_HostHandleCellNameCompatible(cfg_host, cellName)) {
269 tst = ADMCFGCELLNAMECONFLICT;
270 } else if (cellDbHosts == NULL || *cellDbHosts == '\0') {
271 tst = ADMCFGCELLDBHOSTSNULL;
274 /* remote configuration not yet supported in this function */
277 if (!cfg_host->is_local) {
278 tst = ADMCFGNOTSUPPORTED;
282 /* define cell database hosts */
288 if (!CSDB_ReadFile(&clientDb, AFSDIR_CLIENT_CELLSERVDB_FILEPATH)) {
289 tst = ADMCFGCLIENTCELLSERVDBNOTREAD;
291 CELLDBLINE *cellLinep = CSDB_FindCell(&clientDb, cellName);
293 if (cellLinep != NULL) {
294 /* cell entry exists; remove host entries */
295 if (!CSDB_RemoveCellServers(&clientDb, cellLinep)) {
296 /* should never happen */
297 tst = ADMCFGCLIENTCELLSERVDBEDITFAILED;
300 /* cell entry does not exist; add it */
301 cellLinep = CSDB_AddCell(&clientDb, cellName, NULL, NULL);
303 if (cellLinep == NULL) {
309 /* add new host entries to cell */
310 const char *dbHost = cellDbHosts;
313 while (*dbHost != '\0' && tst == 0) {
314 size_t dbHostLen = strlen(dbHost);
315 const char *dbHostAddrStr;
317 if (dbHostLen > (MAXHOSTCHARS - 1)) {
318 tst = ADMCFGHOSTNAMETOOLONG;
319 } else if (dbHostCount >= MAXHOSTSPERCELL) {
320 tst = ADMCFGCELLDBHOSTCOUNTTOOLARGE;
322 if (!cfgutil_HostNameGetAddressString
323 (dbHost, &dbHostAddrStr, &tst2)) {
326 if (CSDB_AddCellServer
327 (&clientDb, cellLinep, dbHostAddrStr,
332 dbHost += dbHostLen + 1;
337 /* edit successful; write CellServDB */
338 if (!CSDB_WriteFile(&clientDb)) {
339 tst = ADMCFGCLIENTCELLSERVDBNOTWRITTEN;
344 CSDB_FreeFile(&clientDb);
349 /* function not yet implemented for Unix */
350 tst = ADMCFGNOTSUPPORTED;
352 #endif /* AFS_NT40_ENV */
355 /* define default client cell */
359 if (afssw_SetClientCellName(cellName)) {
360 /* failed to set cell name in registry (ThisCell equivalent) */
361 if (errno == EACCES) {
364 tst = ADMCFGCLIENTTHISCELLNOTWRITTEN;
370 /* function not yet implemented for Unix */
371 tst = ADMCFGNOTSUPPORTED;
373 #endif /* AFS_NT40_ENV */
376 /* help any underlying packages adjust to cell change */
381 if ((rc = ka_CellConfig(AFSDIR_CLIENT_ETC_DIRPATH)) != 0) {
397 * cfg_ClientCellServDbAdd() -- Add entry to client CellServDB on host.
400 cfg_ClientCellServDbAdd(void *hostHandle, /* host config handle */
401 const char *cellName, /* cell name */
402 const char *dbentry, /* cell database entry */
404 { /* completion status */
405 return ClientCellServDbUpdate(CSDB_OP_ADD, hostHandle, cellName, dbentry,
411 * cfg_ClientCellServDbRemove() -- Remove entry from client CellServDB
415 cfg_ClientCellServDbRemove(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_REM, hostHandle, cellName, dbentry,
426 * cfg_ClientStop() -- Stop the client (cache manager) on host.
428 * Timeout is the maximum time (in seconds) to wait for client to stop.
431 cfg_ClientStop(void *hostHandle, /* host config handle */
432 unsigned int timeout, /* timeout in seconds */
434 { /* completion status */
436 afs_status_t tst2, tst = 0;
437 cfg_host_p cfg_host = (cfg_host_p) hostHandle;
439 /* validate parameters */
441 if (!cfgutil_HostHandleValidate(cfg_host, &tst2)) {
445 /* remote configuration not yet supported in this function */
448 if (!cfg_host->is_local) {
449 tst = ADMCFGNOTSUPPORTED;
456 if (!CacheManagerStop(timeout, &tst2)) {
462 /* indicate failure */
473 * cfg_ClientStart() -- Start the client (cache manager) on host.
475 * Timeout is the maximum time (in seconds) to wait for client to start.
478 cfg_ClientStart(void *hostHandle, /* host config handle */
479 unsigned int timeout, /* timeout in seconds */
481 { /* completion status */
483 afs_status_t tst2, tst = 0;
484 cfg_host_p cfg_host = (cfg_host_p) hostHandle;
486 /* validate parameters */
488 if (!cfgutil_HostHandleValidate(cfg_host, &tst2)) {
492 /* remote configuration not yet supported in this function */
495 if (!cfg_host->is_local) {
496 tst = ADMCFGNOTSUPPORTED;
503 if (!CacheManagerStart(timeout, &tst2)) {
509 /* indicate failure */
520 /* ---------------- Local functions ------------------ */
524 * ClientCellServDbUpdate() -- add or remove a client CellServDB entry.
526 * Common function implementing cfg_ClientCellServDb{Add/Remove}().
529 ClientCellServDbUpdate(int updateOp, void *hostHandle, const char *cellName,
530 const char *dbentry, afs_status_p st)
533 afs_status_t tst2, tst = 0;
534 cfg_host_p cfg_host = (cfg_host_p) hostHandle;
535 char dbentryFull[MAXHOSTCHARS];
537 /* validate parameters and resolve dbentry to fully qualified name */
539 if (!cfgutil_HostHandleValidate(cfg_host, &tst2)) {
541 } else if (cellName == NULL || *cellName == '\0') {
542 tst = ADMCFGCELLNAMENULL;
543 } else if (strlen(cellName) > (MAXCELLCHARS - 1)) {
544 tst = ADMCFGCELLNAMETOOLONG;
545 } else if (dbentry == NULL || *dbentry == '\0') {
546 tst = ADMCFGHOSTNAMENULL;
547 } else if (strlen(dbentry) > (MAXHOSTCHARS - 1)) {
548 tst = ADMCFGHOSTNAMETOOLONG;
549 } else if (!cfgutil_HostNameGetFull(dbentry, dbentryFull, &tst2)) {
553 /* remote configuration not yet supported in this function */
556 if (!cfg_host->is_local) {
557 tst = ADMCFGNOTSUPPORTED;
561 /* modify local client CellServDB entry for specified cell */
567 if (!CSDB_ReadFile(&clientDb, AFSDIR_CLIENT_CELLSERVDB_FILEPATH)) {
568 tst = ADMCFGCLIENTCELLSERVDBNOTREAD;
570 CELLDBLINE *cellLinep = CSDB_FindCell(&clientDb, cellName);
571 CELLDBLINE *serverLinep = NULL;
572 int serverLineCount = 0;
574 if (cellLinep != NULL) {
575 /* found cellName, now find server to add/remove */
576 CELLDBLINE *workingLinep;
578 for (workingLinep = cellLinep->pNext; workingLinep != NULL;
579 workingLinep = workingLinep->pNext) {
580 CELLDBLINEINFO lineInfo;
582 if (!CSDB_CrackLine(&lineInfo, workingLinep->szLine)) {
583 /* not a server (or cell) line; perhaps a comment */
585 } else if (lineInfo.szCell[0] != '\0') {
586 /* hit a new cell line */
589 /* found a server line; check if is host of interest */
591 int dbentryAddr = ntohl(lineInfo.ipServer);
595 if (!cfgutil_HostAddressIsValid
596 (dbentryFull, dbentryAddr, &isValid, &tst2)) {
599 } else if (isValid) {
600 /* found server of interest */
601 serverLinep = workingLinep;
609 if (updateOp == CSDB_OP_ADD && serverLinep == NULL) {
610 if (cellLinep == NULL) {
612 CSDB_AddCell(&clientDb, cellName, NULL, NULL);
615 if (cellLinep == NULL) {
617 } else if (serverLineCount >= MAXHOSTSPERCELL) {
618 tst = ADMCFGCLIENTCELLSERVDBNOSPACE;
620 const char *dbentryAddrStr;
622 if (!cfgutil_HostNameGetAddressString
623 (dbentryFull, &dbentryAddrStr, &tst2)) {
627 CSDB_AddCellServer(&clientDb, cellLinep,
630 if (serverLinep == NULL) {
635 } else if (updateOp == CSDB_OP_REM && serverLinep != NULL) {
636 (void)CSDB_RemoveLine(&clientDb, serverLinep);
640 if (!CSDB_WriteFile(&clientDb)) {
641 tst = ADMCFGCLIENTCELLSERVDBNOTWRITTEN;
646 CSDB_FreeFile(&clientDb);
651 /* function not yet implemented for Unix */
652 tst = ADMCFGNOTSUPPORTED;
654 #endif /* AFS_NT40_ENV */
657 /* indicate failure */
668 * CacheManagerStart() -- Start the local AFS cache manager.
670 * Timeout is the maximum time (in seconds) to wait for the CM to start.
672 * RETURN CODES: 1 success, 0 failure (st indicates why)
675 CacheManagerStart(unsigned timeout, afs_status_p st)
681 afs_status_t tst = 0;
684 /* Windows - cache manager is a service */
687 if (!cfgutil_WindowsServiceStart
688 (AFSREG_CLT_SVC_NAME, 0, NULL, timeout, &wasRunning, &tst2)) {
692 /* function not yet implemented for Unix */
693 tst = ADMCFGNOTSUPPORTED;
694 #endif /* AFS_NT40_ENV */
697 /* indicate failure */
708 * CacheManagerStop() -- Stop the local AFS cache manager.
710 * Timeout is the maximum time (in seconds) to wait for the CM to stop.
712 * RETURN CODES: 1 success, 0 failure (st indicates why)
715 CacheManagerStop(unsigned timeout, afs_status_p st)
721 afs_status_t tst = 0;
724 /* Windows - cache manager is a service */
727 if (!cfgutil_WindowsServiceStop
728 (AFSREG_CLT_SVC_NAME, timeout, &wasStopped, &tst2)) {
732 /* function not yet implemented for Unix */
733 tst = ADMCFGNOTSUPPORTED;
734 #endif /* AFS_NT40_ENV */
737 /* indicate failure */