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>
36 #include <afs/afs_Admin.h>
37 #include <afs/afs_AdminErrors.h>
38 #include <afs/afs_utilAdmin.h>
40 #include <afs/dirpath.h>
41 #include <afs/cellconfig.h>
45 #include <WINNT/afsreg.h>
46 #include <WINNT/afssw.h>
47 #include <cellservdb.h>
50 #include "cfginternal.h"
51 #include "afs_cfgAdmin.h"
54 /* Local declarations and definitions */
56 #define CSDB_OP_ADD 0 /* add a client CellServDB entry */
57 #define CSDB_OP_REM 1 /* remove a client CellServDB entry */
60 ClientCellServDbUpdate(int updateOp,
67 CacheManagerStart(unsigned timeout,
71 CacheManagerStop(unsigned timeout,
77 /* ---------------- Exported AFS Client functions ------------------ */
81 * cfg_ClientQueryStatus() -- Query status of static client configuration
82 * on host, i.e., status of required configuration files, etc.
83 * Upon successful completion *configStP is set to the client
84 * configuration status, with a value of zero (0) indicating that
85 * the configuration is valid.
87 * If client configuration is not valid then *cellNameP is set to NULL;
88 * otherwise, *cellNameP is an allocated buffer containing client cell.
90 * If client software (cache-manager) is not installed then *versionP is
91 * undefined; otherwise *versionP is 34 for 3.4, 35 for 3.5, etc.
93 * Note: Client configuration is checked even if the client software
94 * is not installed. This is useful for tools that require
95 * client configuration information but NOT the actual
96 * client (cache-manager); for example, the AFS Server Manager.
99 cfg_ClientQueryStatus(const char *hostName, /* name of host */
100 short *isInstalledP, /* client software installed */
101 unsigned *versionP, /* client software version */
102 afs_status_p configStP, /* client config status */
103 char **cellNameP, /* client's cell */
104 afs_status_p st) /* completion status */
107 afs_status_t tst2, tst = 0;
108 afs_status_t clientSt = 0;
109 char *clientCellName = NULL;
110 short cmInstalled = 0;
113 /* validate parameters */
115 if (hostName == NULL || *hostName == '\0') {
116 tst = ADMCFGHOSTNAMENULL;
117 } else if (strlen(hostName) > (MAXHOSTCHARS - 1)) {
118 tst = ADMCFGHOSTNAMETOOLONG;
119 } else if (isInstalledP == NULL) {
120 tst = ADMCFGINSTALLEDFLAGPNULL;
121 } else if (versionP == NULL) {
122 tst = ADMCFGVERSIONPNULL;
123 } else if (configStP == NULL) {
124 tst = ADMCFGCONFIGSTATUSPNULL;
125 } else if (cellNameP == NULL) {
126 tst = ADMCFGCELLNAMEPNULL;
129 /* remote configuration not yet supported; hostName must be local host */
134 if (!cfgutil_HostNameIsLocal(hostName, &isLocal, &tst2)) {
136 } else if (!isLocal) {
137 tst = ADMCFGNOTSUPPORTED;
141 /* determine if client software (CM) is installed and if so what version */
144 /* Windows - cache manager is a service */
148 if (!cfgutil_WindowsServiceQuery(AFSREG_CLT_SVC_NAME,
151 /* CM not installed, or insufficient privilege to check */
152 if (tst2 == ADMNOPRIV) {
158 /* CM installed, get version */
159 unsigned major, minor, patch;
163 if (afssw_GetClientVersion(&major, &minor, &patch)) {
164 /* failed to retrieve version information */
165 if (errno == EACCES) {
168 tst = ADMCFGCLIENTVERSIONNOTREAD;
171 cmVersion = (major * 10) + minor;
177 /* function not yet implemented for Unix */
178 tst = ADMCFGNOTSUPPORTED;
180 #endif /* AFS_NT40_ENV */
183 /* check static client configuration; not necessary that client
184 * software (CM) be installed for this information to be valid and useable.
188 struct afsconf_dir *confdir;
190 if ((confdir = afsconf_Open(AFSDIR_CLIENT_ETC_DIRPATH)) == NULL) {
191 /* the client configuration appears to be missing/invalid */
192 clientSt = ADMCFGCLIENTBASICINFOINVALID;
194 struct afsconf_entry *cellentry;
196 if (confdir->cellName == NULL || *confdir->cellName == '\0') {
197 /* no cell set for client */
198 clientSt = ADMCFGCLIENTNOTINCELL;
200 for (cellentry = confdir->entries;
202 cellentry = cellentry->next) {
203 if (!strcasecmp(confdir->cellName,
204 cellentry->cellInfo.name)) {
209 if (cellentry == NULL) {
210 clientSt = ADMCFGCLIENTCELLNOTINDB;
211 } else if (cellentry->cellInfo.numServers <= 0) {
212 clientSt = ADMCFGCLIENTCELLHASNODBENTRIES;
216 if (tst == 0 && clientSt == 0) {
217 /* everything looks good; malloc cell name buffer to return */
219 (char *) malloc(strlen(cellentry->cellInfo.name) + 1);
220 if (clientCellName == NULL) {
223 strcpy(clientCellName, cellentry->cellInfo.name);
227 (void)afsconf_Close(confdir);
231 /* return result of query */
234 /* return client status and cell name */
235 *isInstalledP = cmInstalled;
236 *versionP = cmVersion;
237 *configStP = clientSt;
240 *cellNameP = clientCellName;
245 /* indicate failure */
248 /* free cell name if allocated before failure */
249 if (clientCellName != NULL) {
250 free(clientCellName);
261 * cfg_ClientSetCell() -- Define default client cell for host.
263 * The cellDbHosts argument is a multistring containing the names of
264 * the existing database servers already configured in the cell; this
265 * multistring list can be obtained via cfg_CellServDbEnumerate().
266 * If configuring the first server in a new cell then the cellDbHosts
267 * list contains only the name of that host.
269 * Warning: client (cache-manager) should be stopped prior to setting cell.
272 cfg_ClientSetCell(void *hostHandle, /* host config handle */
273 const char *cellName, /* cell name */
274 const char *cellDbHosts, /* cell database hosts */
275 afs_status_p st) /* completion status */
278 afs_status_t tst2, tst = 0;
279 cfg_host_p cfg_host = (cfg_host_p)hostHandle;
281 /* validate parameters */
283 if (!cfgutil_HostHandleValidate(cfg_host, &tst2)) {
285 } else if (cellName == NULL || *cellName == '\0') {
286 tst = ADMCFGCELLNAMENULL;
287 } else if (strlen(cellName) > (MAXCELLCHARS - 1)) {
288 tst = ADMCFGCELLNAMETOOLONG;
289 } else if (!cfgutil_HostHandleCellNameCompatible(cfg_host, cellName)) {
290 tst = ADMCFGCELLNAMECONFLICT;
291 } else if (cellDbHosts == NULL || *cellDbHosts == '\0') {
292 tst = ADMCFGCELLDBHOSTSNULL;
295 /* remote configuration not yet supported in this function */
298 if (!cfg_host->is_local) {
299 tst = ADMCFGNOTSUPPORTED;
303 /* define cell database hosts */
309 if (!CSDB_ReadFile(&clientDb, AFSDIR_CLIENT_CELLSERVDB_FILEPATH)) {
310 tst = ADMCFGCLIENTCELLSERVDBNOTREAD;
312 CELLDBLINE *cellLinep = CSDB_FindCell(&clientDb, cellName);
314 if (cellLinep != NULL) {
315 /* cell entry exists; remove host entries */
316 if (!CSDB_RemoveCellServers(&clientDb, cellLinep)) {
317 /* should never happen */
318 tst = ADMCFGCLIENTCELLSERVDBEDITFAILED;
321 /* cell entry does not exist; add it */
322 cellLinep = CSDB_AddCell(&clientDb, cellName, NULL, NULL);
324 if (cellLinep == NULL) {
330 /* add new host entries to cell */
331 const char *dbHost = cellDbHosts;
334 while (*dbHost != '\0' && tst == 0) {
335 size_t dbHostLen = strlen(dbHost);
336 const char *dbHostAddrStr;
338 if (dbHostLen > (MAXHOSTCHARS - 1)) {
339 tst = ADMCFGHOSTNAMETOOLONG;
340 } else if (dbHostCount >= MAXHOSTSPERCELL) {
341 tst = ADMCFGCELLDBHOSTCOUNTTOOLARGE;
342 } else if (!cfgutil_HostNameGetAddressString(dbHost,
346 } else if (CSDB_AddCellServer(&clientDb,
353 dbHost += dbHostLen + 1;
358 /* edit successful; write CellServDB */
359 if (!CSDB_WriteFile(&clientDb)) {
360 tst = ADMCFGCLIENTCELLSERVDBNOTWRITTEN;
365 CSDB_FreeFile(&clientDb);
370 /* function not yet implemented for Unix */
371 tst = ADMCFGNOTSUPPORTED;
373 #endif /* AFS_NT40_ENV */
376 /* define default client cell */
380 if (afssw_SetClientCellName(cellName)) {
381 /* failed to set cell name in registry (ThisCell equivalent) */
382 if (errno == EACCES) {
385 tst = ADMCFGCLIENTTHISCELLNOTWRITTEN;
391 /* function not yet implemented for Unix */
392 tst = ADMCFGNOTSUPPORTED;
394 #endif /* AFS_NT40_ENV */
397 /* help any underlying packages adjust to cell change */
402 if ((rc = ka_CellConfig(AFSDIR_CLIENT_ETC_DIRPATH)) != 0) {
418 * cfg_ClientCellServDbAdd() -- Add entry to client CellServDB on host.
421 cfg_ClientCellServDbAdd(void *hostHandle, /* host config handle */
422 const char *cellName, /* cell name */
423 const char *dbentry, /* cell database entry */
424 afs_status_p st) /* completion status */
426 return ClientCellServDbUpdate(CSDB_OP_ADD,
435 * cfg_ClientCellServDbRemove() -- Remove entry from client CellServDB
439 cfg_ClientCellServDbRemove(void *hostHandle, /* host config handle */
440 const char *cellName, /* cell name */
441 const char *dbentry, /* cell database entry */
442 afs_status_p st) /* completion status */
444 return ClientCellServDbUpdate(CSDB_OP_REM,
453 * cfg_ClientStop() -- Stop the client (cache manager) on host.
455 * Timeout is the maximum time (in seconds) to wait for client to stop.
458 cfg_ClientStop(void *hostHandle, /* host config handle */
459 unsigned int timeout, /* timeout in seconds */
460 afs_status_p st) /* completion status */
463 afs_status_t tst2, tst = 0;
464 cfg_host_p cfg_host = (cfg_host_p)hostHandle;
466 /* validate parameters */
468 if (!cfgutil_HostHandleValidate(cfg_host, &tst2)) {
472 /* remote configuration not yet supported in this function */
475 if (!cfg_host->is_local) {
476 tst = ADMCFGNOTSUPPORTED;
483 if (!CacheManagerStop(timeout, &tst2)) {
489 /* indicate failure */
500 * cfg_ClientStart() -- Start the client (cache manager) on host.
502 * Timeout is the maximum time (in seconds) to wait for client to start.
505 cfg_ClientStart(void *hostHandle, /* host config handle */
506 unsigned int timeout, /* timeout in seconds */
507 afs_status_p st) /* completion status */
510 afs_status_t tst2, tst = 0;
511 cfg_host_p cfg_host = (cfg_host_p)hostHandle;
513 /* validate parameters */
515 if (!cfgutil_HostHandleValidate(cfg_host, &tst2)) {
519 /* remote configuration not yet supported in this function */
522 if (!cfg_host->is_local) {
523 tst = ADMCFGNOTSUPPORTED;
530 if (!CacheManagerStart(timeout, &tst2)) {
536 /* indicate failure */
547 /* ---------------- Local functions ------------------ */
551 * ClientCellServDbUpdate() -- add or remove a client CellServDB entry.
553 * Common function implementing cfg_ClientCellServDb{Add/Remove}().
556 ClientCellServDbUpdate(int updateOp,
558 const char *cellName,
563 afs_status_t tst2, tst = 0;
564 cfg_host_p cfg_host = (cfg_host_p)hostHandle;
565 char dbentryFull[MAXHOSTCHARS];
567 /* validate parameters and resolve dbentry to fully qualified name */
569 if (!cfgutil_HostHandleValidate(cfg_host, &tst2)) {
571 } else if (cellName == NULL || *cellName == '\0') {
572 tst = ADMCFGCELLNAMENULL;
573 } else if (strlen(cellName) > (MAXCELLCHARS - 1)) {
574 tst = ADMCFGCELLNAMETOOLONG;
575 } else if (dbentry == NULL || *dbentry == '\0') {
576 tst = ADMCFGHOSTNAMENULL;
577 } else if (strlen(dbentry) > (MAXHOSTCHARS - 1)) {
578 tst = ADMCFGHOSTNAMETOOLONG;
579 } else if (!cfgutil_HostNameGetFull(dbentry, dbentryFull, &tst2)) {
583 /* remote configuration not yet supported in this function */
586 if (!cfg_host->is_local) {
587 tst = ADMCFGNOTSUPPORTED;
591 /* modify local client CellServDB entry for specified cell */
597 if (!CSDB_ReadFile(&clientDb, AFSDIR_CLIENT_CELLSERVDB_FILEPATH)) {
598 tst = ADMCFGCLIENTCELLSERVDBNOTREAD;
600 CELLDBLINE *cellLinep = CSDB_FindCell(&clientDb, cellName);
601 CELLDBLINE *serverLinep = NULL;
602 int serverLineCount = 0;
604 if (cellLinep != NULL) {
605 /* found cellName, now find server to add/remove */
606 CELLDBLINE *workingLinep;
608 for (workingLinep = cellLinep->pNext;
609 workingLinep != NULL;
610 workingLinep = workingLinep->pNext) {
611 CELLDBLINEINFO lineInfo;
613 if (!CSDB_CrackLine(&lineInfo, workingLinep->szLine)) {
614 /* not a server (or cell) line; perhaps a comment */
616 } else if (lineInfo.szCell[0] != '\0') {
617 /* hit a new cell line */
620 /* found a server line; check if is host of interest */
622 int dbentryAddr = ntohl(lineInfo.ipServer);
626 if (!cfgutil_HostAddressIsValid(dbentryFull,
632 } else if (isValid) {
633 /* found server of interest */
634 serverLinep = workingLinep;
642 if (updateOp == CSDB_OP_ADD && serverLinep == NULL) {
643 if (cellLinep == NULL) {
644 cellLinep = CSDB_AddCell(&clientDb,
645 cellName, NULL, NULL);
648 if (cellLinep == NULL) {
650 } else if (serverLineCount >= MAXHOSTSPERCELL) {
651 tst = ADMCFGCLIENTCELLSERVDBNOSPACE;
653 const char *dbentryAddrStr;
655 if (!cfgutil_HostNameGetAddressString(dbentryFull,
660 serverLinep = CSDB_AddCellServer(&clientDb,
664 if (serverLinep == NULL) {
669 } else if (updateOp == CSDB_OP_REM && serverLinep != NULL) {
670 (void)CSDB_RemoveLine(&clientDb, serverLinep);
674 if (!CSDB_WriteFile(&clientDb)) {
675 tst = ADMCFGCLIENTCELLSERVDBNOTWRITTEN;
680 CSDB_FreeFile(&clientDb);
685 /* function not yet implemented for Unix */
686 tst = ADMCFGNOTSUPPORTED;
688 #endif /* AFS_NT40_ENV */
691 /* indicate failure */
702 * CacheManagerStart() -- Start the local AFS cache manager.
704 * Timeout is the maximum time (in seconds) to wait for the CM to start.
706 * RETURN CODES: 1 success, 0 failure (st indicates why)
709 CacheManagerStart(unsigned timeout,
713 afs_status_t tst2, tst = 0;
716 /* Windows - cache manager is a service */
719 if (!cfgutil_WindowsServiceStart(AFSREG_CLT_SVC_NAME,
727 /* function not yet implemented for Unix */
728 tst = ADMCFGNOTSUPPORTED;
729 #endif /* AFS_NT40_ENV */
732 /* indicate failure */
743 * CacheManagerStop() -- Stop the local AFS cache manager.
745 * Timeout is the maximum time (in seconds) to wait for the CM to stop.
747 * RETURN CODES: 1 success, 0 failure (st indicates why)
750 CacheManagerStop(unsigned timeout,
754 afs_status_t tst2, tst = 0;
757 /* Windows - cache manager is a service */
760 if (!cfgutil_WindowsServiceStop(AFSREG_CLT_SVC_NAME,
767 /* function not yet implemented for Unix */
768 tst = ADMCFGNOTSUPPORTED;
769 #endif /* AFS_NT40_ENV */
772 /* indicate failure */