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 */
197 clientCellName
= strdup(cellentry
->cellInfo
.name
);
198 if (clientCellName
== NULL
)
202 (void)afsconf_Close(confdir
);
206 /* return result of query */
209 /* return client status and cell name */
210 *isInstalledP
= cmInstalled
;
211 *versionP
= cmVersion
;
212 *configStP
= clientSt
;
215 *cellNameP
= clientCellName
;
220 /* indicate failure */
223 /* free cell name if allocated before failure */
224 if (clientCellName
!= NULL
) {
225 free(clientCellName
);
236 * cfg_ClientSetCell() -- Define default client cell for host.
238 * The cellDbHosts argument is a multistring containing the names of
239 * the existing database servers already configured in the cell; this
240 * multistring list can be obtained via cfg_CellServDbEnumerate().
241 * If configuring the first server in a new cell then the cellDbHosts
242 * list contains only the name of that host.
244 * Warning: client (cache-manager) should be stopped prior to setting cell.
247 cfg_ClientSetCell(void *hostHandle
, /* host config handle */
248 const char *cellName
, /* cell name */
249 const char *cellDbHosts
, /* cell database hosts */
251 { /* completion status */
253 afs_status_t tst2
, tst
= 0;
254 cfg_host_p cfg_host
= (cfg_host_p
) hostHandle
;
256 /* validate parameters */
258 if (!cfgutil_HostHandleValidate(cfg_host
, &tst2
)) {
260 } else if (cellName
== NULL
|| *cellName
== '\0') {
261 tst
= ADMCFGCELLNAMENULL
;
262 } else if (strlen(cellName
) > (MAXCELLCHARS
- 1)) {
263 tst
= ADMCFGCELLNAMETOOLONG
;
264 } else if (!cfgutil_HostHandleCellNameCompatible(cfg_host
, cellName
)) {
265 tst
= ADMCFGCELLNAMECONFLICT
;
266 } else if (cellDbHosts
== NULL
|| *cellDbHosts
== '\0') {
267 tst
= ADMCFGCELLDBHOSTSNULL
;
270 /* remote configuration not yet supported in this function */
273 if (!cfg_host
->is_local
) {
274 tst
= ADMCFGNOTSUPPORTED
;
278 /* define cell database hosts */
284 if (!CSDB_ReadFile(&clientDb
, AFSDIR_CLIENT_CELLSERVDB_FILEPATH
)) {
285 tst
= ADMCFGCLIENTCELLSERVDBNOTREAD
;
287 CELLDBLINE
*cellLinep
= CSDB_FindCell(&clientDb
, cellName
);
289 if (cellLinep
!= NULL
) {
290 /* cell entry exists; remove host entries */
291 if (!CSDB_RemoveCellServers(&clientDb
, cellLinep
)) {
292 /* should never happen */
293 tst
= ADMCFGCLIENTCELLSERVDBEDITFAILED
;
296 /* cell entry does not exist; add it */
297 cellLinep
= CSDB_AddCell(&clientDb
, cellName
, NULL
, NULL
);
299 if (cellLinep
== NULL
) {
305 /* add new host entries to cell */
306 const char *dbHost
= cellDbHosts
;
309 while (*dbHost
!= '\0' && tst
== 0) {
310 size_t dbHostLen
= strlen(dbHost
);
311 const char *dbHostAddrStr
;
313 if (dbHostLen
> (MAXHOSTCHARS
- 1)) {
314 tst
= ADMCFGHOSTNAMETOOLONG
;
315 } else if (dbHostCount
>= MAXHOSTSPERCELL
) {
316 tst
= ADMCFGCELLDBHOSTCOUNTTOOLARGE
;
318 if (!cfgutil_HostNameGetAddressString
319 (dbHost
, &dbHostAddrStr
, &tst2
)) {
322 if (CSDB_AddCellServer
323 (&clientDb
, cellLinep
, dbHostAddrStr
,
328 dbHost
+= dbHostLen
+ 1;
333 /* edit successful; write CellServDB */
334 if (!CSDB_WriteFile(&clientDb
)) {
335 tst
= ADMCFGCLIENTCELLSERVDBNOTWRITTEN
;
340 CSDB_FreeFile(&clientDb
);
345 /* function not yet implemented for Unix */
346 tst
= ADMCFGNOTSUPPORTED
;
348 #endif /* AFS_NT40_ENV */
351 /* define default client cell */
355 if (afssw_SetClientCellName(cellName
)) {
356 /* failed to set cell name in registry (ThisCell equivalent) */
357 if (errno
== EACCES
) {
360 tst
= ADMCFGCLIENTTHISCELLNOTWRITTEN
;
366 /* function not yet implemented for Unix */
367 tst
= ADMCFGNOTSUPPORTED
;
369 #endif /* AFS_NT40_ENV */
372 /* help any underlying packages adjust to cell change */
377 if ((rc
= ka_CellConfig(AFSDIR_CLIENT_ETC_DIRPATH
)) != 0) {
393 * cfg_ClientCellServDbAdd() -- Add entry to client CellServDB on host.
396 cfg_ClientCellServDbAdd(void *hostHandle
, /* host config handle */
397 const char *cellName
, /* cell name */
398 const char *dbentry
, /* cell database entry */
400 { /* completion status */
401 return ClientCellServDbUpdate(CSDB_OP_ADD
, hostHandle
, cellName
, dbentry
,
407 * cfg_ClientCellServDbRemove() -- Remove entry from client CellServDB
411 cfg_ClientCellServDbRemove(void *hostHandle
, /* host config handle */
412 const char *cellName
, /* cell name */
413 const char *dbentry
, /* cell database entry */
415 { /* completion status */
416 return ClientCellServDbUpdate(CSDB_OP_REM
, hostHandle
, cellName
, dbentry
,
422 * cfg_ClientStop() -- Stop the client (cache manager) on host.
424 * Timeout is the maximum time (in seconds) to wait for client to stop.
427 cfg_ClientStop(void *hostHandle
, /* host config handle */
428 unsigned int timeout
, /* timeout in seconds */
430 { /* completion status */
432 afs_status_t tst2
, tst
= 0;
433 cfg_host_p cfg_host
= (cfg_host_p
) hostHandle
;
435 /* validate parameters */
437 if (!cfgutil_HostHandleValidate(cfg_host
, &tst2
)) {
441 /* remote configuration not yet supported in this function */
444 if (!cfg_host
->is_local
) {
445 tst
= ADMCFGNOTSUPPORTED
;
452 if (!CacheManagerStop(timeout
, &tst2
)) {
458 /* indicate failure */
469 * cfg_ClientStart() -- Start the client (cache manager) on host.
471 * Timeout is the maximum time (in seconds) to wait for client to start.
474 cfg_ClientStart(void *hostHandle
, /* host config handle */
475 unsigned int timeout
, /* timeout in seconds */
477 { /* completion status */
479 afs_status_t tst2
, tst
= 0;
480 cfg_host_p cfg_host
= (cfg_host_p
) hostHandle
;
482 /* validate parameters */
484 if (!cfgutil_HostHandleValidate(cfg_host
, &tst2
)) {
488 /* remote configuration not yet supported in this function */
491 if (!cfg_host
->is_local
) {
492 tst
= ADMCFGNOTSUPPORTED
;
499 if (!CacheManagerStart(timeout
, &tst2
)) {
505 /* indicate failure */
516 /* ---------------- Local functions ------------------ */
520 * ClientCellServDbUpdate() -- add or remove a client CellServDB entry.
522 * Common function implementing cfg_ClientCellServDb{Add/Remove}().
525 ClientCellServDbUpdate(int updateOp
, void *hostHandle
, const char *cellName
,
526 const char *dbentry
, afs_status_p st
)
529 afs_status_t tst2
, tst
= 0;
530 cfg_host_p cfg_host
= (cfg_host_p
) hostHandle
;
531 char dbentryFull
[MAXHOSTCHARS
];
533 /* validate parameters and resolve dbentry to fully qualified name */
535 if (!cfgutil_HostHandleValidate(cfg_host
, &tst2
)) {
537 } else if (cellName
== NULL
|| *cellName
== '\0') {
538 tst
= ADMCFGCELLNAMENULL
;
539 } else if (strlen(cellName
) > (MAXCELLCHARS
- 1)) {
540 tst
= ADMCFGCELLNAMETOOLONG
;
541 } else if (dbentry
== NULL
|| *dbentry
== '\0') {
542 tst
= ADMCFGHOSTNAMENULL
;
543 } else if (strlen(dbentry
) > (MAXHOSTCHARS
- 1)) {
544 tst
= ADMCFGHOSTNAMETOOLONG
;
545 } else if (!cfgutil_HostNameGetFull(dbentry
, dbentryFull
, &tst2
)) {
549 /* remote configuration not yet supported in this function */
552 if (!cfg_host
->is_local
) {
553 tst
= ADMCFGNOTSUPPORTED
;
557 /* modify local client CellServDB entry for specified cell */
563 if (!CSDB_ReadFile(&clientDb
, AFSDIR_CLIENT_CELLSERVDB_FILEPATH
)) {
564 tst
= ADMCFGCLIENTCELLSERVDBNOTREAD
;
566 CELLDBLINE
*cellLinep
= CSDB_FindCell(&clientDb
, cellName
);
567 CELLDBLINE
*serverLinep
= NULL
;
568 int serverLineCount
= 0;
570 if (cellLinep
!= NULL
) {
571 /* found cellName, now find server to add/remove */
572 CELLDBLINE
*workingLinep
;
574 for (workingLinep
= cellLinep
->pNext
; workingLinep
!= NULL
;
575 workingLinep
= workingLinep
->pNext
) {
576 CELLDBLINEINFO lineInfo
;
578 if (!CSDB_CrackLine(&lineInfo
, workingLinep
->szLine
)) {
579 /* not a server (or cell) line; perhaps a comment */
581 } else if (lineInfo
.szCell
[0] != '\0') {
582 /* hit a new cell line */
585 /* found a server line; check if is host of interest */
587 int dbentryAddr
= ntohl(lineInfo
.ipServer
);
591 if (!cfgutil_HostAddressIsValid
592 (dbentryFull
, dbentryAddr
, &isValid
, &tst2
)) {
595 } else if (isValid
) {
596 /* found server of interest */
597 serverLinep
= workingLinep
;
605 if (updateOp
== CSDB_OP_ADD
&& serverLinep
== NULL
) {
606 if (cellLinep
== NULL
) {
608 CSDB_AddCell(&clientDb
, cellName
, NULL
, NULL
);
611 if (cellLinep
== NULL
) {
613 } else if (serverLineCount
>= MAXHOSTSPERCELL
) {
614 tst
= ADMCFGCLIENTCELLSERVDBNOSPACE
;
616 const char *dbentryAddrStr
;
618 if (!cfgutil_HostNameGetAddressString
619 (dbentryFull
, &dbentryAddrStr
, &tst2
)) {
623 CSDB_AddCellServer(&clientDb
, cellLinep
,
626 if (serverLinep
== NULL
) {
631 } else if (updateOp
== CSDB_OP_REM
&& serverLinep
!= NULL
) {
632 (void)CSDB_RemoveLine(&clientDb
, serverLinep
);
636 if (!CSDB_WriteFile(&clientDb
)) {
637 tst
= ADMCFGCLIENTCELLSERVDBNOTWRITTEN
;
642 CSDB_FreeFile(&clientDb
);
647 /* function not yet implemented for Unix */
648 tst
= ADMCFGNOTSUPPORTED
;
650 #endif /* AFS_NT40_ENV */
653 /* indicate failure */
664 * CacheManagerStart() -- Start the local AFS cache manager.
666 * Timeout is the maximum time (in seconds) to wait for the CM to start.
668 * RETURN CODES: 1 success, 0 failure (st indicates why)
671 CacheManagerStart(unsigned timeout
, afs_status_p st
)
677 afs_status_t tst
= 0;
680 /* Windows - cache manager is a service */
683 if (!cfgutil_WindowsServiceStart
684 (AFSREG_CLT_SVC_NAME
, 0, NULL
, timeout
, &wasRunning
, &tst2
)) {
688 /* function not yet implemented for Unix */
689 tst
= ADMCFGNOTSUPPORTED
;
690 #endif /* AFS_NT40_ENV */
693 /* indicate failure */
704 * CacheManagerStop() -- Stop the local AFS cache manager.
706 * Timeout is the maximum time (in seconds) to wait for the CM to stop.
708 * RETURN CODES: 1 success, 0 failure (st indicates why)
711 CacheManagerStop(unsigned timeout
, afs_status_p st
)
717 afs_status_t tst
= 0;
720 /* Windows - cache manager is a service */
723 if (!cfgutil_WindowsServiceStop
724 (AFSREG_CLT_SVC_NAME
, timeout
, &wasStopped
, &tst2
)) {
728 /* function not yet implemented for Unix */
729 tst
= ADMCFGNOTSUPPORTED
;
730 #endif /* AFS_NT40_ENV */
733 /* indicate failure */