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>
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>
38 #include <WINNT/afsreg.h>
39 #include <WINNT/afssw.h>
40 #include <cellservdb.h>
43 #include "cfginternal.h"
44 #include "afs_cfgAdmin.h"
47 /* Local declarations and definitions */
49 #define CSDB_OP_ADD 0 /* add a client CellServDB entry */
50 #define CSDB_OP_REM 1 /* remove a client CellServDB entry */
53 ClientCellServDbUpdate(int updateOp, void *hostHandle, const char *cellName,
54 const char *dbentry, afs_status_p st);
57 CacheManagerStart(unsigned timeout, afs_status_p st);
60 CacheManagerStop(unsigned timeout, afs_status_p st);
65 /* ---------------- Exported AFS Client functions ------------------ */
69 * cfg_ClientQueryStatus() -- Query status of static client configuration
70 * on host, i.e., status of required configuration files, etc.
71 * Upon successful completion *configStP is set to the client
72 * configuration status, with a value of zero (0) indicating that
73 * the configuration is valid.
75 * If client configuration is not valid then *cellNameP is set to NULL;
76 * otherwise, *cellNameP is an allocated buffer containing client cell.
78 * If client software (cache-manager) is not installed then *versionP is
79 * undefined; otherwise *versionP is 34 for 3.4, 35 for 3.5, etc.
81 * Note: Client configuration is checked even if the client software
82 * is not installed. This is useful for tools that require
83 * client configuration information but NOT the actual
84 * client (cache-manager); for example, the AFS Server Manager.
87 cfg_ClientQueryStatus(const char *hostName, /* name of host */
88 short *isInstalledP, /* client software installed */
89 unsigned *versionP, /* client software version */
90 afs_status_p configStP, /* client config status */
91 char **cellNameP, /* client's cell */
93 { /* completion status */
95 afs_status_t tst2, tst = 0;
96 afs_status_t clientSt = 0;
97 char *clientCellName = NULL;
98 short cmInstalled = 0;
101 /* validate parameters */
103 if (hostName == NULL || *hostName == '\0') {
104 tst = ADMCFGHOSTNAMENULL;
105 } else if (strlen(hostName) > (MAXHOSTCHARS - 1)) {
106 tst = ADMCFGHOSTNAMETOOLONG;
107 } else if (isInstalledP == NULL) {
108 tst = ADMCFGINSTALLEDFLAGPNULL;
109 } else if (versionP == NULL) {
110 tst = ADMCFGVERSIONPNULL;
111 } else if (configStP == NULL) {
112 tst = ADMCFGCONFIGSTATUSPNULL;
113 } else if (cellNameP == NULL) {
114 tst = ADMCFGCELLNAMEPNULL;
117 /* remote configuration not yet supported; hostName must be local host */
122 if (!cfgutil_HostNameIsLocal(hostName, &isLocal, &tst2)) {
124 } else if (!isLocal) {
125 tst = ADMCFGNOTSUPPORTED;
129 /* determine if client software (CM) is installed and if so what version */
132 /* Windows - cache manager is a service */
136 if (!cfgutil_WindowsServiceQuery
137 (AFSREG_CLT_SVC_NAME, &svcState, &tst2)) {
138 /* CM not installed, or insufficient privilege to check */
139 if (tst2 == ADMNOPRIV) {
145 /* CM installed, get version */
146 unsigned major, minor, patch;
150 if (afssw_GetClientVersion(&major, &minor, &patch)) {
151 /* failed to retrieve version information */
152 if (errno == EACCES) {
155 tst = ADMCFGCLIENTVERSIONNOTREAD;
158 cmVersion = (major * 10) + minor;
164 /* function not yet implemented for Unix */
165 tst = ADMCFGNOTSUPPORTED;
167 #endif /* AFS_NT40_ENV */
170 /* check static client configuration; not necessary that client
171 * software (CM) be installed for this information to be valid and useable.
175 struct afsconf_dir *confdir;
177 if ((confdir = afsconf_Open(AFSDIR_CLIENT_ETC_DIRPATH)) == NULL) {
178 /* the client configuration appears to be missing/invalid */
179 clientSt = ADMCFGCLIENTBASICINFOINVALID;
181 struct afsconf_entry *cellentry;
183 if (confdir->cellName == NULL || *confdir->cellName == '\0') {
184 /* no cell set for client */
185 clientSt = ADMCFGCLIENTNOTINCELL;
187 for (cellentry = confdir->entries; cellentry != NULL;
188 cellentry = cellentry->next) {
190 (confdir->cellName, cellentry->cellInfo.name)) {
195 if (cellentry == NULL) {
196 clientSt = ADMCFGCLIENTCELLNOTINDB;
197 } else if (cellentry->cellInfo.numServers <= 0) {
198 clientSt = ADMCFGCLIENTCELLHASNODBENTRIES;
202 if (tst == 0 && clientSt == 0) {
203 /* everything looks good; malloc cell name buffer to return */
205 (char *)malloc(strlen(cellentry->cellInfo.name) + 1);
206 if (clientCellName == NULL) {
209 strcpy(clientCellName, cellentry->cellInfo.name);
213 (void)afsconf_Close(confdir);
217 /* return result of query */
220 /* return client status and cell name */
221 *isInstalledP = cmInstalled;
222 *versionP = cmVersion;
223 *configStP = clientSt;
226 *cellNameP = clientCellName;
231 /* indicate failure */
234 /* free cell name if allocated before failure */
235 if (clientCellName != NULL) {
236 free(clientCellName);
247 * cfg_ClientSetCell() -- Define default client cell for host.
249 * The cellDbHosts argument is a multistring containing the names of
250 * the existing database servers already configured in the cell; this
251 * multistring list can be obtained via cfg_CellServDbEnumerate().
252 * If configuring the first server in a new cell then the cellDbHosts
253 * list contains only the name of that host.
255 * Warning: client (cache-manager) should be stopped prior to setting cell.
258 cfg_ClientSetCell(void *hostHandle, /* host config handle */
259 const char *cellName, /* cell name */
260 const char *cellDbHosts, /* cell database hosts */
262 { /* completion status */
264 afs_status_t tst2, tst = 0;
265 cfg_host_p cfg_host = (cfg_host_p) hostHandle;
267 /* validate parameters */
269 if (!cfgutil_HostHandleValidate(cfg_host, &tst2)) {
271 } else if (cellName == NULL || *cellName == '\0') {
272 tst = ADMCFGCELLNAMENULL;
273 } else if (strlen(cellName) > (MAXCELLCHARS - 1)) {
274 tst = ADMCFGCELLNAMETOOLONG;
275 } else if (!cfgutil_HostHandleCellNameCompatible(cfg_host, cellName)) {
276 tst = ADMCFGCELLNAMECONFLICT;
277 } else if (cellDbHosts == NULL || *cellDbHosts == '\0') {
278 tst = ADMCFGCELLDBHOSTSNULL;
281 /* remote configuration not yet supported in this function */
284 if (!cfg_host->is_local) {
285 tst = ADMCFGNOTSUPPORTED;
289 /* define cell database hosts */
295 if (!CSDB_ReadFile(&clientDb, AFSDIR_CLIENT_CELLSERVDB_FILEPATH)) {
296 tst = ADMCFGCLIENTCELLSERVDBNOTREAD;
298 CELLDBLINE *cellLinep = CSDB_FindCell(&clientDb, cellName);
300 if (cellLinep != NULL) {
301 /* cell entry exists; remove host entries */
302 if (!CSDB_RemoveCellServers(&clientDb, cellLinep)) {
303 /* should never happen */
304 tst = ADMCFGCLIENTCELLSERVDBEDITFAILED;
307 /* cell entry does not exist; add it */
308 cellLinep = CSDB_AddCell(&clientDb, cellName, NULL, NULL);
310 if (cellLinep == NULL) {
316 /* add new host entries to cell */
317 const char *dbHost = cellDbHosts;
320 while (*dbHost != '\0' && tst == 0) {
321 size_t dbHostLen = strlen(dbHost);
322 const char *dbHostAddrStr;
324 if (dbHostLen > (MAXHOSTCHARS - 1)) {
325 tst = ADMCFGHOSTNAMETOOLONG;
326 } else if (dbHostCount >= MAXHOSTSPERCELL) {
327 tst = ADMCFGCELLDBHOSTCOUNTTOOLARGE;
329 if (!cfgutil_HostNameGetAddressString
330 (dbHost, &dbHostAddrStr, &tst2)) {
333 if (CSDB_AddCellServer
334 (&clientDb, cellLinep, dbHostAddrStr,
339 dbHost += dbHostLen + 1;
344 /* edit successful; write CellServDB */
345 if (!CSDB_WriteFile(&clientDb)) {
346 tst = ADMCFGCLIENTCELLSERVDBNOTWRITTEN;
351 CSDB_FreeFile(&clientDb);
356 /* function not yet implemented for Unix */
357 tst = ADMCFGNOTSUPPORTED;
359 #endif /* AFS_NT40_ENV */
362 /* define default client cell */
366 if (afssw_SetClientCellName(cellName)) {
367 /* failed to set cell name in registry (ThisCell equivalent) */
368 if (errno == EACCES) {
371 tst = ADMCFGCLIENTTHISCELLNOTWRITTEN;
377 /* function not yet implemented for Unix */
378 tst = ADMCFGNOTSUPPORTED;
380 #endif /* AFS_NT40_ENV */
383 /* help any underlying packages adjust to cell change */
388 if ((rc = ka_CellConfig(AFSDIR_CLIENT_ETC_DIRPATH)) != 0) {
404 * cfg_ClientCellServDbAdd() -- Add entry to client CellServDB on host.
407 cfg_ClientCellServDbAdd(void *hostHandle, /* host config handle */
408 const char *cellName, /* cell name */
409 const char *dbentry, /* cell database entry */
411 { /* completion status */
412 return ClientCellServDbUpdate(CSDB_OP_ADD, hostHandle, cellName, dbentry,
418 * cfg_ClientCellServDbRemove() -- Remove entry from client CellServDB
422 cfg_ClientCellServDbRemove(void *hostHandle, /* host config handle */
423 const char *cellName, /* cell name */
424 const char *dbentry, /* cell database entry */
426 { /* completion status */
427 return ClientCellServDbUpdate(CSDB_OP_REM, hostHandle, cellName, dbentry,
433 * cfg_ClientStop() -- Stop the client (cache manager) on host.
435 * Timeout is the maximum time (in seconds) to wait for client to stop.
438 cfg_ClientStop(void *hostHandle, /* host config handle */
439 unsigned int timeout, /* timeout in seconds */
441 { /* completion status */
443 afs_status_t tst2, tst = 0;
444 cfg_host_p cfg_host = (cfg_host_p) hostHandle;
446 /* validate parameters */
448 if (!cfgutil_HostHandleValidate(cfg_host, &tst2)) {
452 /* remote configuration not yet supported in this function */
455 if (!cfg_host->is_local) {
456 tst = ADMCFGNOTSUPPORTED;
463 if (!CacheManagerStop(timeout, &tst2)) {
469 /* indicate failure */
480 * cfg_ClientStart() -- Start the client (cache manager) on host.
482 * Timeout is the maximum time (in seconds) to wait for client to start.
485 cfg_ClientStart(void *hostHandle, /* host config handle */
486 unsigned int timeout, /* timeout in seconds */
488 { /* completion status */
490 afs_status_t tst2, tst = 0;
491 cfg_host_p cfg_host = (cfg_host_p) hostHandle;
493 /* validate parameters */
495 if (!cfgutil_HostHandleValidate(cfg_host, &tst2)) {
499 /* remote configuration not yet supported in this function */
502 if (!cfg_host->is_local) {
503 tst = ADMCFGNOTSUPPORTED;
510 if (!CacheManagerStart(timeout, &tst2)) {
516 /* indicate failure */
527 /* ---------------- Local functions ------------------ */
531 * ClientCellServDbUpdate() -- add or remove a client CellServDB entry.
533 * Common function implementing cfg_ClientCellServDb{Add/Remove}().
536 ClientCellServDbUpdate(int updateOp, void *hostHandle, const char *cellName,
537 const char *dbentry, afs_status_p st)
540 afs_status_t tst2, tst = 0;
541 cfg_host_p cfg_host = (cfg_host_p) hostHandle;
542 char dbentryFull[MAXHOSTCHARS];
544 /* validate parameters and resolve dbentry to fully qualified name */
546 if (!cfgutil_HostHandleValidate(cfg_host, &tst2)) {
548 } else if (cellName == NULL || *cellName == '\0') {
549 tst = ADMCFGCELLNAMENULL;
550 } else if (strlen(cellName) > (MAXCELLCHARS - 1)) {
551 tst = ADMCFGCELLNAMETOOLONG;
552 } else if (dbentry == NULL || *dbentry == '\0') {
553 tst = ADMCFGHOSTNAMENULL;
554 } else if (strlen(dbentry) > (MAXHOSTCHARS - 1)) {
555 tst = ADMCFGHOSTNAMETOOLONG;
556 } else if (!cfgutil_HostNameGetFull(dbentry, dbentryFull, &tst2)) {
560 /* remote configuration not yet supported in this function */
563 if (!cfg_host->is_local) {
564 tst = ADMCFGNOTSUPPORTED;
568 /* modify local client CellServDB entry for specified cell */
574 if (!CSDB_ReadFile(&clientDb, AFSDIR_CLIENT_CELLSERVDB_FILEPATH)) {
575 tst = ADMCFGCLIENTCELLSERVDBNOTREAD;
577 CELLDBLINE *cellLinep = CSDB_FindCell(&clientDb, cellName);
578 CELLDBLINE *serverLinep = NULL;
579 int serverLineCount = 0;
581 if (cellLinep != NULL) {
582 /* found cellName, now find server to add/remove */
583 CELLDBLINE *workingLinep;
585 for (workingLinep = cellLinep->pNext; workingLinep != NULL;
586 workingLinep = workingLinep->pNext) {
587 CELLDBLINEINFO lineInfo;
589 if (!CSDB_CrackLine(&lineInfo, workingLinep->szLine)) {
590 /* not a server (or cell) line; perhaps a comment */
592 } else if (lineInfo.szCell[0] != '\0') {
593 /* hit a new cell line */
596 /* found a server line; check if is host of interest */
598 int dbentryAddr = ntohl(lineInfo.ipServer);
602 if (!cfgutil_HostAddressIsValid
603 (dbentryFull, dbentryAddr, &isValid, &tst2)) {
606 } else if (isValid) {
607 /* found server of interest */
608 serverLinep = workingLinep;
616 if (updateOp == CSDB_OP_ADD && serverLinep == NULL) {
617 if (cellLinep == NULL) {
619 CSDB_AddCell(&clientDb, cellName, NULL, NULL);
622 if (cellLinep == NULL) {
624 } else if (serverLineCount >= MAXHOSTSPERCELL) {
625 tst = ADMCFGCLIENTCELLSERVDBNOSPACE;
627 const char *dbentryAddrStr;
629 if (!cfgutil_HostNameGetAddressString
630 (dbentryFull, &dbentryAddrStr, &tst2)) {
634 CSDB_AddCellServer(&clientDb, cellLinep,
637 if (serverLinep == NULL) {
642 } else if (updateOp == CSDB_OP_REM && serverLinep != NULL) {
643 (void)CSDB_RemoveLine(&clientDb, serverLinep);
647 if (!CSDB_WriteFile(&clientDb)) {
648 tst = ADMCFGCLIENTCELLSERVDBNOTWRITTEN;
653 CSDB_FreeFile(&clientDb);
658 /* function not yet implemented for Unix */
659 tst = ADMCFGNOTSUPPORTED;
661 #endif /* AFS_NT40_ENV */
664 /* indicate failure */
675 * CacheManagerStart() -- Start the local AFS cache manager.
677 * Timeout is the maximum time (in seconds) to wait for the CM to start.
679 * RETURN CODES: 1 success, 0 failure (st indicates why)
682 CacheManagerStart(unsigned timeout, afs_status_p st)
685 afs_status_t tst2, tst = 0;
688 /* Windows - cache manager is a service */
691 if (!cfgutil_WindowsServiceStart
692 (AFSREG_CLT_SVC_NAME, 0, NULL, timeout, &wasRunning, &tst2)) {
696 /* function not yet implemented for Unix */
697 tst = ADMCFGNOTSUPPORTED;
698 #endif /* AFS_NT40_ENV */
701 /* indicate failure */
712 * CacheManagerStop() -- Stop the local AFS cache manager.
714 * Timeout is the maximum time (in seconds) to wait for the CM to stop.
716 * RETURN CODES: 1 success, 0 failure (st indicates why)
719 CacheManagerStop(unsigned timeout, afs_status_p st)
722 afs_status_t tst2, tst = 0;
725 /* Windows - cache manager is a service */
728 if (!cfgutil_WindowsServiceStop
729 (AFSREG_CLT_SVC_NAME, timeout, &wasStopped, &tst2)) {
733 /* function not yet implemented for Unix */
734 tst = ADMCFGNOTSUPPORTED;
735 #endif /* AFS_NT40_ENV */
738 /* indicate failure */