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 #include <afsconfig.h>
11 #include <afs/param.h>
15 #include "afs_clientAdmin.h"
16 #include "../adminutil/afs_AdminInternal.h"
19 #include <sys/types.h>
20 #include <afs/cellconfig.h>
22 #include <afs/afssyscalls.h>
24 #include <afs/fs_utils.h>
25 #define close(x) closesocket(x)
27 #include <sys/socket.h>
28 #include <netinet/in.h>
29 #include <arpa/inet.h>
31 #include <afs/venus.h>
37 #include <afs/kautils.h>
39 #include <rx/rxstat.h>
40 #include <rx/rx_null.h>
42 #include <afs/dirpath.h>
43 #include <afs/afs_AdminErrors.h>
44 #include <afs/afs_vosAdmin.h>
45 #include <afs/afs_utilAdmin.h>
46 #include <afs/ptserver.h>
47 #include <afs/vlserver.h>
48 #include <afs/pthread_glock.h>
49 #include <afs/sys_prototypes.h>
52 * AFS client administration functions.
54 * Admin functions that are normally associated with the client.
56 * All of the functions related to authentication are here, plus
57 * some miscellaneous others.
61 static const unsigned long ADMIN_TICKET_LIFETIME = 24 * 3600;
63 static const unsigned long SERVER_TTL = 10 * 60;
66 * We need a way to track whether or not the client library has been
67 * initialized. We count on the fact that the other library initialization
68 * functions are protected by their own once mechanism. We only track
69 * our own internal status
72 static int client_init;
73 static pthread_once_t client_init_once = PTHREAD_ONCE_INIT;
82 * IsTokenValid - validate a token handle
86 * IN token - the token to be validated.
90 * No locks are obtained or released by this function
98 * Returns != 0 upon successful completion.
102 IsTokenValid(const afs_token_handle_p token, afs_status_p st)
105 afs_status_t tst = 0;
108 tst = ADMCLIENTTOKENHANDLENULL;
109 goto fail_IsTokenValid;
112 if (token->is_valid == 0) {
113 tst = ADMCLIENTTOKENHANDLEINVALID;
114 goto fail_IsTokenValid;
117 if ((token->begin_magic != BEGIN_MAGIC)
118 || (token->end_magic != END_MAGIC)) {
119 tst = ADMCLIENTTOKENHANDLEBADMAGIC;
120 goto fail_IsTokenValid;
133 * afsclient_TokenGetExisting - get tokens that already exist and
134 * are held by the cache manager.
138 * IN cellName - the name of the cell where the token originated.
140 * OUT tokenHandle - a handle to the tokens if they were obtained
145 * No locks are obtained or released by this function
149 * The tokenHandle returned by this function cannot be used for kas
150 * related operations, since kas tokens aren't stored in the kernel.
154 * Returns != 0 upon successful completion.
158 afsclient_TokenGetExisting(const char *cellName, void **tokenHandle,
162 afs_status_t tst = 0;
163 struct ktc_principal afs_server;
164 afs_token_handle_p t_handle =
165 (afs_token_handle_p) calloc(1, sizeof(afs_token_handle_t));
167 if (client_init == 0) {
168 tst = ADMCLIENTNOINIT;
169 goto fail_afsclient_TokenGetExisting;
172 if (cellName == NULL) {
173 tst = ADMCLIENTCELLNAMENULL;
174 goto fail_afsclient_TokenGetExisting;
177 if (tokenHandle == NULL) {
178 tst = ADMCLIENTTOKENHANDLENULL;
179 goto fail_afsclient_TokenGetExisting;
182 if (t_handle == NULL) {
184 goto fail_afsclient_TokenGetExisting;
187 strcpy(afs_server.name, "afs");
188 afs_server.instance[0] = 0;
189 strcpy(afs_server.cell, cellName);
193 ktc_GetToken(&afs_server, &t_handle->afs_token,
194 sizeof(t_handle->afs_token), &t_handle->client))) {
196 * The token has been retrieved successfully, initialize
197 * the rest of the token handle structure
199 strncpy(t_handle->cell, cellName, MAXCELLCHARS);
200 t_handle->cell[MAXCELLCHARS - 1] = '\0';
201 t_handle->afs_token_set = 1;
202 t_handle->from_kernel = 1;
203 t_handle->kas_token_set = 0;
204 t_handle->sc_index = 2;
205 t_handle->afs_sc[t_handle->sc_index] =
206 rxkad_NewClientSecurityObject(rxkad_clear,
207 &t_handle->afs_token.sessionKey,
208 t_handle->afs_token.kvno,
209 t_handle->afs_token.ticketLen,
210 t_handle->afs_token.ticket);
211 t_handle->afs_encrypt_sc[t_handle->sc_index] =
212 rxkad_NewClientSecurityObject(rxkad_crypt,
213 &t_handle->afs_token.sessionKey,
214 t_handle->afs_token.kvno,
215 t_handle->afs_token.ticketLen,
216 t_handle->afs_token.ticket);
217 if ((t_handle->afs_sc[t_handle->sc_index] == NULL)
218 || (t_handle->afs_sc[t_handle->sc_index] == NULL)) {
219 tst = ADMCLIENTTOKENHANDLENOSECURITY;
220 goto fail_afsclient_TokenGetExisting;
222 t_handle->begin_magic = BEGIN_MAGIC;
223 t_handle->is_valid = 1;
224 t_handle->end_magic = END_MAGIC;
225 *tokenHandle = (void *)t_handle;
228 goto fail_afsclient_TokenGetExisting;
232 fail_afsclient_TokenGetExisting:
234 if ((rc == 0) && (t_handle != NULL)) {
244 * afsclient_TokenSet - set the tokens represented by tokenHandle to be
245 * active in the kernel (aka ka_SetToken).
249 * IN cellName - the name of the cell where the token originated.
251 * OUT tokenHandle - a handle to the tokens if they were obtained
256 * No locks are obtained or released by this function
260 * The tokenHandle returned by this function cannot be used for kas
261 * related operations, since kas tokens aren't stored in the kernel.
265 * Returns != 0 upon successful completion.
269 afsclient_TokenSet(const void *tokenHandle, afs_status_p st)
272 afs_status_t tst = 0;
273 struct ktc_principal afs_server;
274 afs_token_handle_p t_handle = (afs_token_handle_p) tokenHandle;
276 if (!IsTokenValid(t_handle, &tst)) {
277 goto fail_afsclient_TokenSet;
280 strcpy(afs_server.name, "afs");
281 afs_server.instance[0] = 0;
282 strcpy(afs_server.cell, t_handle->cell);
285 ktc_SetToken(&afs_server, &t_handle->afs_token, &t_handle->client, 0);
291 fail_afsclient_TokenSet:
300 * GetKASToken - get a KAS token and store it in the tokenHandle.
304 * IN cellName - the name of the cell where the token should be obtained.
306 * IN principal - the name of the user of the token.
308 * IN password - the password for the principal.
310 * OUT tokenHandle - a handle to the tokens if they were obtained
315 * No locks are obtained or released by this function
323 * Returns != 0 upon successful completion.
327 GetKASToken(const char *cellName, const char *principal, const char *password,
328 afs_token_handle_p tokenHandle, afs_status_p st)
331 afs_status_t tst = 0;
332 struct ubik_client *unauth_conn;
334 struct ktc_encryptionKey key;
335 struct ktc_token *token;
336 unsigned long now = time(0);
337 char name[MAXKTCNAMELEN];
338 char inst[MAXKTCNAMELEN];
339 int have_server_conn = 0;
341 token = &tokenHandle->kas_token;
343 ka_StringToKey((char *)password, (char *)cellName, &key);
346 * Get an unauthenticated connection in the right cell to use for
347 * retrieving the token.
351 ka_AuthServerConn((char *)cellName, KA_AUTHENTICATION_SERVICE, 0,
354 goto fail_GetKASToken;
356 have_server_conn = 1;
358 tst = ka_ParseLoginName((char *)principal, name, inst, NULL);
360 goto fail_GetKASToken;
364 ka_Authenticate(name, inst, (char *)cellName, unauth_conn,
365 KA_MAINTENANCE_SERVICE, &key, now,
366 now + ADMIN_TICKET_LIFETIME, token, &expire);
368 goto fail_GetKASToken;
374 if (have_server_conn) {
375 ubik_ClientDestroy(unauth_conn);
385 * GetAFSToken - get a AFS token and store it in the tokenHandle.
389 * IN cellName - the name of the cell where the token should be obtained.
391 * IN principal - the name of the user of the token.
393 * IN password - the password for the principal.
395 * OUT tokenHandle - a handle to the tokens if they were obtained
400 * No locks are obtained or released by this function
408 * Returns != 0 upon successful completion.
412 GetAFSToken(const char *cellName, const char *principal, const char *password,
413 afs_token_handle_p tokenHandle, afs_status_p st)
416 afs_status_t tst = 0;
417 struct ubik_client *unauth_conn = NULL, *auth_conn = NULL;
419 struct ktc_encryptionKey key;
420 struct ktc_token auth_token;
421 struct ktc_token *token;
422 unsigned long now = time(0);
424 token = &tokenHandle->afs_token;
426 ka_StringToKey((char *)password, (char *)cellName, &key);
429 * Get an unauthenticated connection in the right cell to use for
430 * retrieving the token.
434 ka_AuthServerConn((char *)cellName, KA_AUTHENTICATION_SERVICE, 0,
437 goto fail_GetAFSToken;
441 ka_ParseLoginName((char *)principal, tokenHandle->client.name,
442 tokenHandle->client.instance, NULL);
444 goto fail_GetAFSToken;
448 ka_Authenticate(tokenHandle->client.name,
449 tokenHandle->client.instance, (char *)cellName,
450 unauth_conn, KA_TICKET_GRANTING_SERVICE, &key, now,
451 now + ADMIN_TICKET_LIFETIME, &auth_token, &expire);
453 goto fail_GetAFSToken;
457 ka_AuthServerConn((char *)cellName, KA_TICKET_GRANTING_SERVICE, 0,
460 goto fail_GetAFSToken;
464 ka_CellToRealm((char *)cellName, tokenHandle->client.cell, (int *)0);
466 goto fail_GetAFSToken;
470 ka_GetToken("afs", "", (char *)cellName, tokenHandle->client.name,
471 tokenHandle->client.instance, auth_conn, now,
472 now + ADMIN_TICKET_LIFETIME, &auth_token,
473 tokenHandle->client.cell, token);
475 goto fail_GetAFSToken;
482 ubik_ClientDestroy(auth_conn);
486 ubik_ClientDestroy(unauth_conn);
497 * afsclient_TokenGetNew - get new tokens for a user and store them
498 * in the tokenHandle.
502 * IN cellName - the name of the cell where the tokens should be obtained.
504 * IN principal - the name of the user of the tokens.
506 * IN password - the password for the principal.
508 * OUT tokenHandle - a handle to the tokens if they were obtained
513 * No locks are obtained or released by this function
521 * Returns != 0 upon successful completion.
525 afsclient_TokenGetNew(const char *cellName, const char *principal,
526 const char *password, void **tokenHandle,
530 afs_status_t tst = 0;
531 afs_token_handle_p t_handle =
532 (afs_token_handle_p) calloc(1, sizeof(afs_token_handle_t));
534 if (client_init == 0) {
535 tst = ADMCLIENTNOINIT;
536 goto fail_afsclient_TokenGetNew;
539 if (t_handle == NULL) {
541 goto fail_afsclient_TokenGetNew;
545 * Check to see if the principal or password is missing. If it is,
546 * get unauthenticated tokens for the cell
549 if ((principal == NULL) || (*principal == 0) || (password == NULL)
550 || (*password == 0)) {
551 t_handle->from_kernel = 0;
552 t_handle->afs_token_set = 1;
553 t_handle->kas_token_set = 1;
554 t_handle->sc_index = 0;
555 t_handle->afs_sc[t_handle->sc_index] =
556 rxnull_NewClientSecurityObject();
557 t_handle->afs_encrypt_sc[t_handle->sc_index] =
558 rxnull_NewClientSecurityObject();
559 t_handle->kas_sc[t_handle->sc_index] =
560 rxnull_NewClientSecurityObject();
561 t_handle->begin_magic = BEGIN_MAGIC;
562 t_handle->is_valid = 1;
563 t_handle->afs_token.endTime = 0;
564 t_handle->end_magic = END_MAGIC;
565 *tokenHandle = (void *)t_handle;
570 * create an authenticated token
573 if ((GetAFSToken(cellName, principal, password, t_handle, &tst))
574 && (GetKASToken(cellName, principal, password, t_handle, &tst))) {
575 strncpy(t_handle->cell, cellName, MAXCELLCHARS);
576 t_handle->cell[MAXCELLCHARS - 1] = '\0';
577 t_handle->from_kernel = 0;
578 t_handle->afs_token_set = 1;
579 t_handle->kas_token_set = 1;
580 t_handle->sc_index = 2;
581 t_handle->afs_sc[t_handle->sc_index] =
582 rxkad_NewClientSecurityObject(rxkad_clear,
583 &t_handle->afs_token.sessionKey,
584 t_handle->afs_token.kvno,
585 t_handle->afs_token.ticketLen,
586 t_handle->afs_token.ticket);
587 t_handle->afs_encrypt_sc[t_handle->sc_index] =
588 rxkad_NewClientSecurityObject(rxkad_crypt,
589 &t_handle->afs_token.sessionKey,
590 t_handle->afs_token.kvno,
591 t_handle->afs_token.ticketLen,
592 t_handle->afs_token.ticket);
593 t_handle->kas_sc[t_handle->sc_index] =
594 rxkad_NewClientSecurityObject(rxkad_crypt,
595 &t_handle->kas_token.sessionKey,
596 t_handle->kas_token.kvno,
597 t_handle->kas_token.ticketLen,
598 t_handle->kas_token.ticket);
599 if ((t_handle->afs_sc[t_handle->sc_index] != NULL)
600 && (t_handle->afs_encrypt_sc[t_handle->sc_index] != NULL)
601 && (t_handle->kas_sc[t_handle->sc_index] != NULL)) {
602 t_handle->begin_magic = BEGIN_MAGIC;
603 t_handle->is_valid = 1;
604 t_handle->end_magic = END_MAGIC;
605 *tokenHandle = (void *)t_handle;
607 tst = ADMCLIENTTOKENHANDLENOSECURITY;
608 goto fail_afsclient_TokenGetNew;
611 goto fail_afsclient_TokenGetNew;
616 fail_afsclient_TokenGetNew:
618 if ((rc == 0) && (t_handle != NULL)) {
629 * afsclient_TokenQuery - get the expiration time of the tokens.
633 * IN tokenHandle - a previously obtained valid token.
635 * OUT expirationDateP - the time at which the tokens expire.
637 * OUT principal - the owning principal
639 * OUT instance - principal instance if it exists.
641 * OUT cell - the principal's cell
643 * OUT hasKasTokens - set to 1 if the token handle contains kas tokens.
647 * No locks are obtained or released by this function
651 * We only check the AFS tokens since we always get these. The
652 * KAS tokens may expirer later than the AFS tokens, but this
653 * difference is minor and reporting an earlier time won't cause
658 * Returns != 0 upon successful completion.
662 afsclient_TokenQuery(void *tokenHandle, unsigned long *expirationDateP,
663 char *principal, char *instance, char *cell,
664 int *hasKasTokens, afs_status_p st)
667 afs_status_t tst = 0;
668 afs_token_handle_p t_handle = (afs_token_handle_p) tokenHandle;
670 if (client_init == 0) {
671 tst = ADMCLIENTNOINIT;
673 goto fail_afsclient_TokenQuery;
676 if (IsTokenValid(t_handle, &tst)) {
677 if (principal != NULL) {
678 strcpy(principal, t_handle->client.name);
680 if (instance != NULL) {
681 strcpy(instance, t_handle->client.instance);
684 strcpy(cell, t_handle->client.cell);
686 if (hasKasTokens != NULL) {
687 *hasKasTokens = t_handle->kas_token_set;
689 if (expirationDateP != NULL) {
690 *expirationDateP = t_handle->afs_token.endTime;
695 fail_afsclient_TokenQuery:
704 * afsclient_TokenClose - close an existing token.
708 * IN token - the token to be closed.
712 * No locks are obtained or released by this function
720 * Returns != 0 upon successful completion.
724 afsclient_TokenClose(const void *tokenHandle, afs_status_p st)
727 afs_status_t tst = 0;
728 afs_token_handle_p t_handle = (afs_token_handle_p) tokenHandle;
730 if (client_init == 0) {
731 tst = ADMCLIENTNOINIT;
732 goto fail_afsclient_TokenClose;
735 if (IsTokenValid(t_handle, &tst)) {
736 t_handle->is_valid = 0;
741 fail_afsclient_TokenClose:
749 #define NUM_SERVER_TYPES 3
751 /* must match NUM_SERVER_TYPES */
752 typedef enum { KAS, PTS, VOS } afs_server_list_t;
754 typedef struct afs_server {
757 struct ubik_client **ubik;
758 struct rx_securityClass *sc;
760 } afs_server_t, *afs_server_p;
763 * afsclient_CellOpen - Open a particular cell for work as a particular
768 * IN cellName - the cell where future admin calls will be made.
770 * IN tokenHandle - the tokens work will be done under.
772 * OUT cellHandleP - an opaque pointer that is the first parameter to
773 * almost all subsequent admin api calls.
777 * No locks are obtained or released by this function
785 * Returns != 0 upon successful completion.
789 afsclient_CellOpen(const char *cellName, const void *tokenHandle,
790 void **cellHandleP, afs_status_p st)
793 afs_status_t tst = 0;
794 afs_token_handle_p t_handle = (afs_token_handle_p) tokenHandle;
795 afs_cell_handle_p c_handle = (afs_cell_handle_p)
796 calloc(1, sizeof(afs_cell_handle_t));
797 struct afsconf_dir *tdir = NULL;
798 struct afsconf_cell info;
799 struct rx_connection *serverconns[MAXSERVERS];
801 struct rx_securityClass *sc[3];
803 char copyCell[MAXCELLCHARS];
805 afs_server_t servers[NUM_SERVER_TYPES]
806 = { {AFSCONF_KAUTHSERVICE, KA_MAINTENANCE_SERVICE, 0, 0, 0},
807 {AFSCONF_PROTSERVICE, PRSRV, 0, 0, 0},
808 {AFSCONF_VLDBSERVICE, USER_SERVICE_ID, 0, 0, 0}
811 if (client_init == 0) {
812 tst = ADMCLIENTNOINIT;
813 goto fail_afsclient_CellOpen;
816 if (c_handle == NULL) {
818 goto fail_afsclient_CellOpen;
821 if (t_handle == NULL) {
822 tst = ADMCLIENTTOKENHANDLENULL;
823 goto fail_afsclient_CellOpen;
826 if ((cellName == NULL) || (*cellName == 0)) {
827 tst = ADMCLIENTCELLNAMENULL;
828 goto fail_afsclient_CellOpen;
831 if (cellHandleP == NULL) {
832 tst = ADMCLIENTCELLHANDLEPNULL;
833 goto fail_afsclient_CellOpen;
837 * Check that the token handle contains valid data and the calloc
840 if (!t_handle->afs_token_set) {
841 tst = ADMCLIENTCELLOPENBADTOKEN;
842 goto fail_afsclient_CellOpen;
846 * Use a table to initialize the cell handle structure, since
847 * most of the steps are the same for all the servers.
849 * Start by creating rx_securityClass objects for each of the
850 * servers. A potential optimization is to do this in
851 * afsclient_TokenGetNew and just keep the expiration time of
853 * Also, initialize the ubik client pointers in the table
855 servers[KAS].sc = t_handle->kas_sc[t_handle->sc_index];
856 servers[PTS].sc = t_handle->afs_sc[t_handle->sc_index];
857 servers[VOS].sc = servers[PTS].sc;
858 servers[KAS].ubik = &c_handle->kas;
859 servers[PTS].ubik = &c_handle->pts;
860 servers[VOS].ubik = &c_handle->vos;
861 servers[KAS].valid = &c_handle->kas_valid;
862 servers[PTS].valid = &c_handle->pts_valid;
863 servers[VOS].valid = &c_handle->vos_valid;
864 c_handle->vos_new = 1;
866 if ((servers[PTS].sc == NULL) || (servers[VOS].sc == NULL)) {
867 tst = ADMCLIENTBADTOKENHANDLE;
868 goto fail_afsclient_CellOpen;
872 * If the initialization has succeeded so far, get the address
873 * information for each server in the cell
876 strncpy(c_handle->working_cell, cellName, MAXCELLCHARS);
877 c_handle->working_cell[MAXCELLCHARS - 1] = '\0';
878 if (!(tdir = afsconf_Open(AFSDIR_CLIENT_ETC_DIRPATH))) {
879 tst = ADMCLIENTBADCLIENTCONFIG;
880 goto fail_afsclient_CellOpen;
884 * We must copy the cellName here because afsconf_GetCellInfo
885 * actually writes over the cell name it is passed.
887 strncpy(copyCell, cellName, MAXCELLCHARS);
888 copyCell[MAXCELLCHARS - 1] ='\0';
889 for (i = 0; (i < NUM_SERVER_TYPES); i++) {
892 ka_AuthServerConn((char *)cellName, servers[i].serviceId,
893 ((t_handle->sc_index == 0)
895 kas_token_set)) ? 0 : &t_handle->
896 kas_token, servers[i].ubik);
898 goto fail_afsclient_CellOpen;
901 tst = afsconf_GetCellInfo(tdir, copyCell, servers[i].serv, &info);
903 /* create ubik client handles for each server */
904 scIndex = t_handle->sc_index;
905 sc[scIndex] = servers[i].sc;
906 for (j = 0; (j < info.numServers); j++) {
908 rx_GetCachedConnection(info.hostAddr[j].sin_addr.
910 info.hostAddr[j].sin_port,
911 servers[i].serviceId,
912 sc[scIndex], scIndex);
915 tst = ubik_ClientInit(serverconns, servers[i].ubik);
917 goto fail_afsclient_CellOpen;
920 goto fail_afsclient_CellOpen;
923 /* initialization complete, mark handle valid */
924 *servers[i].valid = 1;
926 c_handle->tokens = t_handle;
929 fail_afsclient_CellOpen:
936 * Upon error, free any obtained resources.
939 if (c_handle != NULL) {
940 if (c_handle->kas_valid)
941 ubik_ClientDestroy(c_handle->kas);
942 if (c_handle->pts_valid)
943 ubik_ClientDestroy(c_handle->pts);
944 if (c_handle->vos_valid)
945 ubik_ClientDestroy(c_handle->vos);
949 c_handle->begin_magic = BEGIN_MAGIC;
950 c_handle->is_valid = 1;
951 c_handle->is_null = 0;
952 c_handle->server_list = NULL;
953 c_handle->server_ttl = 0;
954 c_handle->end_magic = END_MAGIC;
955 *cellHandleP = (void *)c_handle;
965 * afsclient_NullCellOpen - open a null cell handle for access.
969 * OUT cellHandleP - an opaque pointer that is the first parameter to
970 * almost all subsequent admin api calls.
974 * No locks are obtained or released by this function
982 * Returns != 0 upon successful completion.
986 afsclient_NullCellOpen(void **cellHandleP, afs_status_p st)
989 afs_status_t tst = 0;
990 afs_cell_handle_p c_handle = (afs_cell_handle_p)
991 calloc(1, sizeof(afs_cell_handle_t));
995 * Validate parameters
998 if (cellHandleP == NULL) {
999 tst = ADMCLIENTCELLHANDLEPNULL;
1000 goto fail_afsclient_NullCellOpen;
1003 if (client_init == 0) {
1004 tst = ADMCLIENTNOINIT;
1005 goto fail_afsclient_NullCellOpen;
1008 if (c_handle == NULL) {
1010 goto fail_afsclient_NullCellOpen;
1014 * Get unauthenticated tokens for any cell
1017 if (!afsclient_TokenGetNew(0, 0, 0, (void *)&c_handle->tokens, &tst)) {
1018 goto fail_afsclient_NullCellOpen;
1021 c_handle->begin_magic = BEGIN_MAGIC;
1022 c_handle->is_valid = 1;
1023 c_handle->is_null = 1;
1024 c_handle->end_magic = END_MAGIC;
1025 c_handle->kas_valid = 0;
1026 c_handle->pts_valid = 0;
1027 c_handle->vos_valid = 0;
1028 c_handle->kas = NULL;
1029 c_handle->pts = NULL;
1030 c_handle->vos = NULL;
1031 c_handle->server_list = NULL;
1032 c_handle->server_ttl = 0;
1033 *cellHandleP = (void *)c_handle;
1036 fail_afsclient_NullCellOpen:
1045 * afsclient_CellClose - close a previously opened cellHandle.
1049 * IN cellHandle - a cellHandle created by afsclient_CellOpen.
1053 * No locks are obtained or released by this function
1061 * Returns != 0 upon successful completion.
1065 afsclient_CellClose(const void *cellHandle, afs_status_p st)
1068 afs_status_t tst = 0;
1069 afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
1071 if (client_init == 0) {
1072 tst = ADMCLIENTNOINIT;
1073 goto fail_afsclient_CellClose;
1076 if (c_handle == NULL) {
1077 tst = ADMCLIENTCELLHANDLENULL;
1078 goto fail_afsclient_CellClose;
1081 if (c_handle->server_list)
1082 free(c_handle->server_list);
1083 if (c_handle->kas_valid)
1084 ubik_ClientDestroy(c_handle->kas);
1085 if (c_handle->pts_valid)
1086 ubik_ClientDestroy(c_handle->pts);
1087 if (c_handle->vos_valid)
1088 ubik_ClientDestroy(c_handle->vos);
1089 if (c_handle->is_null)
1090 afsclient_TokenClose(c_handle->tokens, 0);
1091 c_handle->kas_valid = 0;
1092 c_handle->pts_valid = 0;
1093 c_handle->vos_valid = 0;
1094 c_handle->is_valid = 0;
1098 fail_afsclient_CellClose:
1108 * afsclient_CellNameGet() -- get a pointer to the cell name in a cell handle
1112 * IN cellHandle - a valid cell handle
1113 * OUT cellNameP - a pointer to the cell name in the cell handle.
1117 * No locks are obtained or released by this function
1121 * If cellHandle is closed then the pointer returned by this function
1122 * is no longer valid.
1126 * Returns != 0 upon successful completion.
1129 afsclient_CellNameGet(const void *cellHandle, const char **cellNameP,
1133 afs_status_t tst = 0;
1134 afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
1136 if (!CellHandleIsValid(cellHandle, &tst)) {
1137 goto fail_afsclient_CellNameGet;
1140 *cellNameP = c_handle->working_cell;
1143 fail_afsclient_CellNameGet:
1153 * afsclient_LocalCellGet - get the name of the cell the machine
1154 * belongs to where this process is running.
1158 * OUT cellName - an array of characters that must be MAXCELLCHARS
1163 * No locks are obtained or released by this function
1167 * If cellName is smaller than MAXCELLCHARS chars, this function won't
1172 * Returns != 0 upon successful completion.
1176 afsclient_LocalCellGet(char *cellName, afs_status_p st)
1179 afs_status_t tst = 0;
1180 struct afsconf_dir *tdir = NULL;
1182 if (client_init == 0) {
1183 tst = ADMCLIENTNOINIT;
1184 goto fail_afsclient_LocalCellGet;
1187 if (cellName == NULL) {
1188 tst = ADMCLIENTCELLNAMENULL;
1189 goto fail_afsclient_LocalCellGet;
1192 tdir = afsconf_Open(AFSDIR_CLIENT_ETC_DIRPATH);
1195 tst = ADMCLIENTBADCLIENTCONFIG;
1196 goto fail_afsclient_LocalCellGet;
1199 if ((tst = afsconf_GetLocalCell(tdir, cellName, MAXCELLCHARS))) {
1200 goto fail_afsclient_LocalCellGet;
1205 fail_afsclient_LocalCellGet:
1208 afsconf_Close(tdir);
1221 client_ExtractDriveLetter(char *path)
1225 if (path[0] != 0 && path[1] == ':') {
1234 * Determine the parent directory of a give directory
1238 Parent(char *directory, char *parentDirectory)
1243 strcpy(parentDirectory, directory);
1244 tp = strrchr(parentDirectory, '\\');
1246 /* lv trailing slash so Parent("k:\foo") is "k:\" not "k :" */
1250 if (client_ExtractDriveLetter(parentDirectory)) {
1251 strcat(parentDirectory, ".");
1261 * Determine the parent directory of a give directory
1264 Parent(const char *directory, char *parentDirectory)
1269 strcpy(parentDirectory, directory);
1270 tp = strrchr(parentDirectory, '/');
1275 strcpy(parentDirectory, ".");
1284 * afsclient_MountPointCreate - create a mount point for a volume.
1288 * IN cellHandle - a handle to the cell where volumeName resides.
1290 * IN directory - the directory where the mountpoint should be created.
1292 * IN volumeName - the name of the volume to mount.
1294 * IN volType - the type of mount point to create.
1296 * IN volCheck - indicates whether or not to check the VLDB to see if
1297 * volumeName exists.
1301 * No locks are obtained or released by this function
1305 * Returns != 0 upon successful completion.
1308 #define TMP_DATA_SIZE 2048
1311 afsclient_MountPointCreate(const void *cellHandle, const char *directory,
1312 const char *volumeName, vol_type_t volType,
1313 vol_check_t volCheck, afs_status_p st)
1316 afs_status_t tst = 0;
1317 afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
1318 char parent_dir[TMP_DATA_SIZE];
1319 char space[TMP_DATA_SIZE];
1320 char directoryCell[MAXCELLCHARS];
1321 struct ViceIoctl idata;
1323 vos_vldbEntry_t vldbEntry;
1326 * Validate arguments
1329 if (client_init == 0) {
1330 tst = ADMCLIENTNOINIT;
1331 goto fail_afsclient_MountPointCreate;
1334 if ((directory == NULL) || (*directory == 0)) {
1335 tst = ADMCLIENTDIRECTORYNULL;
1336 goto fail_afsclient_MountPointCreate;
1339 if ((volumeName == NULL) || (*volumeName == 0)) {
1340 tst = ADMCLIENTVOLUMENAME;
1341 goto fail_afsclient_MountPointCreate;
1345 * Extract the parent directory and make sure it is in AFS.
1348 if (!Parent(directory, parent_dir)) {
1349 tst = ADMCLIENTBADDIRECTORY;
1350 goto fail_afsclient_MountPointCreate;
1354 idata.out_size = TMP_DATA_SIZE;
1356 i = pioctl(parent_dir, VIOC_FILE_CELL_NAME, &idata, 1);
1358 if ((errno == EINVAL) || (errno == ENOENT)) {
1359 tst = ADMCLIENTNOAFSDIRECTORY;
1360 goto fail_afsclient_MountPointCreate;
1363 strcpy(directoryCell, space);
1366 * If the user requested, check that the volume exists
1369 if (volCheck == CHECK_VOLUME) {
1370 if (!vos_VLDBGet(cellHandle, 0, 0, (char *)volumeName, &vldbEntry,
1372 goto fail_afsclient_MountPointCreate;
1377 * Begin constructing the pioctl buffer
1380 if (volType == READ_WRITE) {
1387 * Append the cell to the mount point if the volume is in a different
1388 * cell than the directory
1391 if (strcmp(c_handle->working_cell, directoryCell)) {
1392 strcat(space, c_handle->working_cell);
1395 strcat(space, volumeName);
1402 idata.in_size = 1 + strlen(space);
1404 if (tst = pioctl(directory, VIOC_AFS_CREATE_MT_PT, &idata, 0)) {
1405 goto fail_afsclient_MountPointCreate;
1408 if ((tst = symlink(space, directory))) {
1409 goto fail_afsclient_MountPointCreate;
1415 fail_afsclient_MountPointCreate:
1423 typedef struct Acl {
1431 afsclient_ACLEntryAdd(const char *directory, const char *user,
1432 const acl_p acl, afs_status_p st)
1435 afs_status_t tst = 0;
1436 struct ViceIoctl idata;
1437 char old_acl_string[2048];
1438 char new_acl_string[2048];
1443 int cur_user_acl = 0;
1448 if (client_init == 0) {
1449 tst = ADMCLIENTNOINIT;
1450 goto fail_afsclient_ACLEntryAdd;
1453 if ((directory == NULL) || (*directory == 0)) {
1454 tst = ADMMISCDIRECTORYNULL;
1455 goto fail_afsclient_ACLEntryAdd;
1458 if ((user == NULL) || (*user == 0)) {
1459 tst = ADMMISCUSERNULL;
1460 goto fail_afsclient_ACLEntryAdd;
1464 tst = ADMMISCACLNULL;
1465 goto fail_afsclient_ACLEntryAdd;
1468 if (acl->read == READ) {
1472 if (acl->write == WRITE) {
1476 if (acl->insert == INSERT) {
1480 if (acl->lookup == LOOKUP) {
1484 if (acl->del == DELETE) {
1488 if (acl->lock == LOCK) {
1492 if (acl->admin == ADMIN) {
1497 * Get the current acl for the directory
1500 idata.out_size = 2048;
1502 idata.in = idata.out = old_acl_string;
1503 tst = pioctl((char *)directory, VIOCGETAL, &idata, 1);
1506 goto fail_afsclient_ACLEntryAdd;
1510 * The acl is presented to us in string format. The format of the
1513 * A header which contains the number of positive and negative entries
1514 * and a string indicating whether or not this is a dfs acl:
1516 * num_pos "\n" dfs_string "\n" num_neg
1518 * An entry for each acl that's of the form:
1522 * There are no blanks in the string between fields, but I use them here
1523 * to make the reading easier.
1525 * Since we are only going to add another entry to the acl, our approach
1526 * is simple. Get the num_pos dfs_string and num_neg from the current acl,
1527 * increment num_pos by one and create a new string. Concatenate the new
1528 * user and rights to the new string, and then concatenate the remaining
1529 * contents of the old acl to the new string.
1531 * Unfortunately, this approach doesn't work since the format the kernel
1532 * hands the acl back to us in, is NOT WHAT IT WANTS BACK!!!!
1533 * So instead we need to parse the entire freaking acl and put a space
1534 * between each user and their acl.
1536 * This is really ugly.
1540 * Parse the first few fields of the acl and see if this is a DFS
1545 sscanf(old_acl_string, "%d dfs:%d %s", &cur_acl.nplus, &cur_acl.dfs,
1547 ptr = strchr(old_acl_string, '\n');
1549 sscanf(ptr, "%d", &cur_acl.nminus);
1550 ptr = strchr(ptr, '\n');
1553 tst = ADMMISCNODFSACL;
1554 goto fail_afsclient_ACLEntryAdd;
1557 * It isn't a DFS file, so create the beginning of the string
1558 * we will hand back to the kernel
1560 sprintf(new_acl_string, "%d\n%d\n%s %d\n", (cur_acl.nplus + 1),
1561 cur_acl.nminus, user, newacl);
1565 * Finish scanning the old acl, parsing each user/acl pair and
1566 * adding a space in the new acl.
1569 for (i = 0; i < (cur_acl.nplus + cur_acl.nminus); i++) {
1570 sscanf(ptr, "%s%d\n", cur_user, &cur_user_acl);
1572 * Skip the entry for the user we are replacing/adding
1575 if (strcmp(cur_user, user)) {
1576 ptr = strchr(ptr, '\n');
1578 sprintf(tmp, "%s %d\n", cur_user, cur_user_acl);
1579 strcat(new_acl_string, tmp);
1583 strcat(new_acl_string, ptr);
1590 idata.in_size = strlen(new_acl_string) + 1;
1591 idata.in = idata.out = new_acl_string;
1592 tst = pioctl((char *) directory, VIOCSETAL, &idata, 1);
1595 goto fail_afsclient_ACLEntryAdd;
1599 fail_afsclient_ACLEntryAdd:
1608 * afsclient_Init - initialize AFS components before use.
1614 * No locks are obtained or released by this function
1622 * Returns != 0 upon successful completion.
1626 afsclient_Init(afs_status_p st)
1629 afs_status_t tst = 0;
1632 pthread_once(&client_init_once, client_once);
1635 if (afs_winsockInit() < 0) {
1636 tst = ADMCLIENTCANTINITWINSOCK;
1637 goto fail_afsclient_Init;
1641 if (!(initAFSDirPath() & AFSDIR_CLIENT_PATHS_OK)) {
1642 tst = ADMCLIENTCANTINITAFSLOCATION;
1643 goto fail_afsclient_Init;
1646 if (rx_Init(0) < 0) {
1647 tst = ADMCLIENTCANTINITRX;
1648 goto fail_afsclient_Init;
1651 if ((tst = ka_CellConfig((char *)AFSDIR_CLIENT_ETC_DIRPATH))) {
1652 goto fail_afsclient_Init;
1657 fail_afsclient_Init:
1666 * afsclient_AFSServerGet - determine what kind of server serverName
1667 * is and fill in serverEntryP accordingly.
1671 * IN cellHandle - a cellHandle previously returned by afsclient_CellOpen.
1673 * IN serverName - the hostname of the server of interest.
1675 * OUT serverEntryP - upon successful completion contains a description of
1680 * No locks are obtained or released by this function
1688 * Returns != 0 upon successful completion.
1692 afsclient_AFSServerGet(const void *cellHandle, const char *serverName,
1693 afs_serverEntry_p serverEntryP, afs_status_p st)
1696 afs_status_t tst = 0;
1698 int found_match = 0;
1700 if ((serverName == NULL) || (*serverName == 0)) {
1701 tst = ADMUTILSERVERNAMENULL;
1702 goto fail_afsclient_AFSServerGet;
1705 if (serverEntryP == NULL) {
1706 tst = ADMUTILSERVERENTRYPNULL;
1707 goto fail_afsclient_AFSServerGet;
1711 * Iterate over server entries and try to find a match for serverName
1714 if (!afsclient_AFSServerGetBegin(cellHandle, &iter, &tst)) {
1715 goto fail_afsclient_AFSServerGet;
1718 while (afsclient_AFSServerGetNext(iter, serverEntryP, &tst)) {
1719 if (!strcmp(serverName, serverEntryP->serverName)) {
1726 * If we didn't find a match, the iterator should have terminated
1727 * normally. If it didn't, return the error
1731 if (tst != ADMITERATORDONE) {
1732 afsclient_AFSServerGetDone(iter, 0);
1734 afsclient_AFSServerGetDone(iter, &tst);
1736 tst = ADMCLIENTNOMATCHINGSERVER;
1737 goto fail_afsclient_AFSServerGet;
1739 if (!afsclient_AFSServerGetDone(iter, &tst)) {
1740 goto fail_afsclient_AFSServerGet;
1745 fail_afsclient_AFSServerGet:
1754 * The iterator functions and data for the server retrieval functions
1757 typedef struct server_get {
1760 afs_serverEntry_t server[MAXHOSTSPERCELL + BADSERVERID];
1761 afs_serverEntry_t cache[CACHED_ITEMS];
1762 } server_get_t, *server_get_p;
1765 GetServerRPC(void *rpc_specific, int slot, int *last_item,
1766 int *last_item_contains_data, afs_status_p st)
1769 afs_status_t tst = 0;
1770 server_get_p serv = (server_get_p) rpc_specific;
1772 memcpy(&serv->cache[slot], &serv->server[serv->index],
1773 sizeof(afs_serverEntry_t));
1776 if (serv->index == serv->total) {
1778 *last_item_contains_data = 1;
1789 GetServerFromCache(void *rpc_specific, int slot, void *dest, afs_status_p st)
1792 afs_status_t tst = 0;
1793 server_get_p serv = (server_get_p) rpc_specific;
1795 memcpy(dest, (const void *)&serv->cache[slot], sizeof(afs_serverEntry_t));
1805 * afsclient_AFSServerGetBegin - start the process of iterating over
1806 * every server in the cell.
1810 * IN cellHandle - a cellHandle previously returned by afsclient_CellOpen.
1812 * OUT iterationIdP - - upon successful completion contains an iterator
1813 * that can be passed to afsclient_AFSServerGetNext.
1817 * No locks are obtained or released by this function
1825 * Returns != 0 upon successful completion.
1829 afsclient_AFSServerGetBegin(const void *cellHandle, void **iterationIdP,
1833 afs_status_t tst = 0;
1834 afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
1835 afs_admin_iterator_p iter =
1836 (afs_admin_iterator_p) malloc(sizeof(afs_admin_iterator_t));
1837 server_get_p serv = (server_get_p) calloc(1, sizeof(server_get_t));
1838 server_get_p serv_cache = NULL;
1839 const char *cellName = NULL;
1840 void *database_iter;
1841 util_databaseServerEntry_t database_entry;
1842 void *fileserver_iter;
1843 vos_fileServerEntry_t fileserver_entry;
1844 int iserv, iservaddr, ientryaddr, is_dup;
1845 struct hostent *host;
1847 if (!CellHandleIsValid(c_handle, &tst)) {
1848 goto fail_afsclient_AFSServerGetBegin;
1851 if (iterationIdP == NULL) {
1852 tst = ADMITERATIONIDPNULL;
1853 goto fail_afsclient_AFSServerGetBegin;
1856 if ((serv == NULL) || (iter == NULL)) {
1858 goto fail_afsclient_AFSServerGetBegin;
1863 if (c_handle->server_list != NULL && c_handle->server_ttl < time(NULL)) {
1864 serv_cache = c_handle->server_list;
1865 c_handle->server_list = NULL;
1867 UNLOCK_GLOBAL_MUTEX;
1869 if (c_handle->server_list == NULL) {
1870 if (serv_cache == NULL) {
1871 serv_cache = (server_get_p) calloc(1, sizeof(server_get_t));
1873 if (serv_cache == NULL) {
1875 goto fail_afsclient_AFSServerGetBegin;
1880 * Retrieve the list of database servers for this cell.
1883 if (!afsclient_CellNameGet(c_handle, &cellName, &tst)) {
1884 goto fail_afsclient_AFSServerGetBegin;
1887 if (!util_DatabaseServerGetBegin(cellName, &database_iter, &tst)) {
1888 goto fail_afsclient_AFSServerGetBegin;
1891 while (util_DatabaseServerGetNext(database_iter, &database_entry, &tst)) {
1892 serv->server[serv->total].serverAddress[0] =
1893 database_entry.serverAddress;
1894 serv->server[serv->total].serverType = DATABASE_SERVER;
1898 if (tst != ADMITERATORDONE) {
1899 util_DatabaseServerGetDone(database_iter, 0);
1900 goto fail_afsclient_AFSServerGetBegin;
1903 if (!util_DatabaseServerGetDone(database_iter, &tst)) {
1904 goto fail_afsclient_AFSServerGetBegin;
1908 * Retrieve the list of file servers for this cell.
1911 if (!vos_FileServerGetBegin(c_handle, 0, &fileserver_iter, &tst)) {
1912 goto fail_afsclient_AFSServerGetBegin;
1915 while (vos_FileServerGetNext(fileserver_iter, &fileserver_entry, &tst)) {
1917 * See if any of the addresses returned in this fileserver_entry
1918 * structure already exist in the list of servers we're building.
1919 * If not, create a new record for this server.
1922 for (iserv = 0; iserv < serv->total; iserv++) {
1923 for (ientryaddr = 0; ientryaddr < fileserver_entry.count; ientryaddr++) {
1924 for (iservaddr = 0; iservaddr < AFS_MAX_SERVER_ADDRESS; iservaddr++) {
1925 if (serv->server[iserv].serverAddress[iservaddr] ==
1926 fileserver_entry.serverAddress[ientryaddr]) {
1941 serv->server[iserv].serverType |= FILE_SERVER;
1943 iserv = serv->total++;
1944 serv->server[iserv].serverType = FILE_SERVER;
1948 * Add the addresses from the vldb list to the serv->server[iserv]
1949 * record. Remember that VLDB's list-of-addrs is not guaranteed
1950 * to be unique in a particular entry, or to return only one entry
1951 * per machine--so when we add addresses, always check for
1952 * duplicate entries.
1955 for (ientryaddr = 0; ientryaddr < fileserver_entry.count; ientryaddr++) {
1956 for (iservaddr = 0; iservaddr < AFS_MAX_SERVER_ADDRESS; iservaddr++) {
1957 if (serv->server[iserv].serverAddress[iservaddr] ==
1958 fileserver_entry.serverAddress[ientryaddr]) {
1962 if (iservaddr == AFS_MAX_SERVER_ADDRESS) {
1963 for (iservaddr = 0; iservaddr < AFS_MAX_SERVER_ADDRESS;
1965 if (!serv->server[iserv].serverAddress[iservaddr]) {
1966 serv->server[iserv].serverAddress[iservaddr] =
1967 fileserver_entry.serverAddress[ientryaddr];
1975 if (tst != ADMITERATORDONE) {
1976 vos_FileServerGetDone(fileserver_iter, 0);
1977 goto fail_afsclient_AFSServerGetBegin;
1980 if (!vos_FileServerGetDone(fileserver_iter, &tst)) {
1981 goto fail_afsclient_AFSServerGetBegin;
1985 * Iterate over the list and fill in the hostname of each of the servers
1988 for (iserv = 0; iserv < serv->total; iserv++) {
1989 int addr = htonl(serv->server[iserv].serverAddress[0]);
1991 host = gethostbyaddr((const char *)&addr, sizeof(int), AF_INET);
1993 strncpy(serv->server[iserv].serverName, host->h_name,
1994 AFS_MAX_SERVER_NAME_LEN);
1995 serv->server[iserv].serverName[AFS_MAX_SERVER_NAME_LEN - 1] = '\0';
1997 UNLOCK_GLOBAL_MUTEX;
2000 memcpy(serv_cache, serv, sizeof(server_get_t));
2004 if (c_handle->server_list == NULL)
2007 memcpy(serv, c_handle->server_list, sizeof(server_get_t));
2008 UNLOCK_GLOBAL_MUTEX;
2014 (iter, (void *)serv, GetServerRPC, GetServerFromCache, NULL, NULL,
2016 *iterationIdP = (void *)iter;
2020 fail_afsclient_AFSServerGetBegin:
2027 if (serv_cache != NULL)
2032 /* in case there was a race and we constructed the list twice */
2033 if (c_handle->server_list)
2034 free(c_handle->server_list);
2036 c_handle->server_list = serv_cache;
2037 c_handle->server_ttl = time(NULL) + SERVER_TTL;
2038 UNLOCK_GLOBAL_MUTEX;
2049 * afsclient_AFSServerGetNext - retrieve the next server in the cell.
2053 * IN iterationId - an iterator previously returned by
2054 * afsclient_AFSServerGetBegin.
2056 * OUT serverEntryP - upon successful completion contains the next server.
2060 * No locks are obtained or released by this function
2068 * Returns != 0 upon successful completion.
2072 afsclient_AFSServerGetNext(void *iterationId, afs_serverEntry_p serverEntryP,
2076 afs_status_t tst = 0;
2077 afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationId;
2079 if (iterationId == NULL) {
2080 tst = ADMITERATORNULL;
2081 goto fail_afsclient_AFSServerGetNext;
2084 if (serverEntryP == NULL) {
2085 tst = ADMUTILSERVERENTRYPNULL;
2086 goto fail_afsclient_AFSServerGetNext;
2089 rc = IteratorNext(iter, (void *)serverEntryP, &tst);
2091 fail_afsclient_AFSServerGetNext:
2100 * afsclient_AFSServerGetDone - finish using a server iterator.
2104 * IN iterationId - an iterator previously returned by
2105 * afsclient_AFSServerGetBegin.
2109 * No locks are obtained or released by this function
2117 * Returns != 0 upon successful completion.
2121 afsclient_AFSServerGetDone(void *iterationId, afs_status_p st)
2124 afs_status_t tst = 0;
2125 afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationId;
2127 if (iterationId == NULL) {
2128 tst = ADMITERATORNULL;
2129 goto fail_afsclient_AFSServerGetDone;
2132 rc = IteratorDone(iter, &tst);
2134 fail_afsclient_AFSServerGetDone:
2143 * afsclient_RPCStatOpen - open an rx connection to a server to retrieve
2148 * IN cellHandle - a cellHandle created by afsclient_CellOpen.
2150 * IN serverName - the host name where the server resides.
2152 * IN type - what type of process to query
2154 * OUT rpcStatHandleP - contains an rx connection to the server of interest
2158 * No locks are obtained or released by this function
2166 * Returns != 0 upon successful completion.
2170 afsclient_RPCStatOpen(const void *cellHandle, const char *serverName,
2171 afs_stat_source_t type,
2172 struct rx_connection **rpcStatHandleP, afs_status_p st)
2175 afs_status_t tst = 0;
2176 afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
2179 struct rx_securityClass *sc;
2181 if (!CellHandleIsValid(cellHandle, &tst)) {
2182 goto fail_afsclient_RPCStatOpen;
2185 if (!util_AdminServerAddressGetFromName(serverName, &servAddr, &tst)) {
2186 goto fail_afsclient_RPCStatOpen;
2189 if (rpcStatHandleP == NULL) {
2190 tst = ADMCLIENTRPCSTATHANDLEPNULL;
2191 goto fail_afsclient_RPCStatOpen;
2197 servPort = AFSCONF_NANNYPORT;
2200 case AFS_FILESERVER:
2201 servPort = AFSCONF_FILEPORT;
2205 servPort = AFSCONF_KAUTHPORT;
2209 servPort = AFSCONF_PROTPORT;
2213 servPort = AFSCONF_VOLUMEPORT;
2217 servPort = AFSCONF_VLDBPORT;
2221 servPort = AFSCONF_CALLBACKPORT;
2225 tst = ADMTYPEINVALID;
2226 goto fail_afsclient_RPCStatOpen;
2230 * special processing of tokens by server type
2233 if (type == AFS_KASERVER) {
2234 if (!c_handle->tokens->kas_token_set) {
2235 tst = ADMCLIENTNOKASTOKENS;
2236 goto fail_afsclient_RPCStatOpen;
2238 sc = c_handle->tokens->kas_sc[c_handle->tokens->sc_index];
2240 sc = c_handle->tokens->afs_sc[c_handle->tokens->sc_index];
2244 rx_GetCachedConnection(htonl(servAddr), htons(servPort),
2245 RX_STATS_SERVICE_ID, sc,
2246 c_handle->tokens->sc_index);
2248 if (*rpcStatHandleP == NULL) {
2249 tst = ADMCLIENTRPCSTATNOCONNECTION;
2250 goto fail_afsclient_RPCStatOpen;
2254 fail_afsclient_RPCStatOpen:
2263 * afsclient_RPCStatOpenPort - open an rx connection to a server to retrieve
2268 * IN cellHandle - a cellHandle created by afsclient_CellOpen.
2270 * IN serverName - the host name where the server resides.
2272 * IN port - the UDP port number where the server resides.
2274 * OUT rpcStatHandleP - contains an rx connection to the server of interest
2278 * No locks are obtained or released by this function
2286 * Returns != 0 upon successful completion.
2290 afsclient_RPCStatOpenPort(const void *cellHandle, const char *serverName,
2291 const int serverPort,
2292 struct rx_connection **rpcStatHandleP,
2296 afs_status_t tst = 0;
2297 afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
2299 struct rx_securityClass *sc;
2301 if (!CellHandleIsValid(cellHandle, &tst)) {
2302 goto fail_afsclient_RPCStatOpenPort;
2305 if (!util_AdminServerAddressGetFromName(serverName, &servAddr, &tst)) {
2306 goto fail_afsclient_RPCStatOpenPort;
2309 if (rpcStatHandleP == NULL) {
2310 tst = ADMCLIENTRPCSTATHANDLEPNULL;
2311 goto fail_afsclient_RPCStatOpenPort;
2315 * special processing of tokens by server type
2318 if (serverPort == AFSCONF_KAUTHPORT) {
2319 if (!c_handle->tokens->kas_token_set) {
2320 tst = ADMCLIENTNOKASTOKENS;
2321 goto fail_afsclient_RPCStatOpenPort;
2323 sc = c_handle->tokens->kas_sc[c_handle->tokens->sc_index];
2325 sc = c_handle->tokens->afs_sc[c_handle->tokens->sc_index];
2329 rx_GetCachedConnection(htonl(servAddr), htons(serverPort),
2330 RX_STATS_SERVICE_ID, sc,
2331 c_handle->tokens->sc_index);
2333 if (*rpcStatHandleP == NULL) {
2334 tst = ADMCLIENTRPCSTATNOCONNECTION;
2335 goto fail_afsclient_RPCStatOpenPort;
2339 fail_afsclient_RPCStatOpenPort:
2348 * afsclient_RPCStatClose - close a previously opened rx connection.
2352 * IN rpcStatHandle - an rx connection returned by afsclient_RPCStatOpen
2356 * No locks are obtained or released by this function
2364 * Returns != 0 upon successful completion.
2368 afsclient_RPCStatClose(struct rx_connection *rpcStatHandle, afs_status_p st)
2371 afs_status_t tst = 0;
2373 if (rpcStatHandle == NULL) {
2374 tst = ADMCLIENTRPCSTATHANDLEPNULL;
2375 goto fail_afsclient_RPCStatClose;
2378 rx_ReleaseCachedConnection(rpcStatHandle);
2380 fail_afsclient_RPCStatClose:
2389 * afsclient_CMStatOpen - open an rx connection to a server to retrieve
2394 * IN cellHandle - a cellHandle created by afsclient_CellOpen.
2396 * IN serverName - the host name where the server resides.
2398 * OUT cmStatHandleP - contains an rx connection to the server of interest
2402 * No locks are obtained or released by this function
2410 * Returns != 0 upon successful completion.
2414 afsclient_CMStatOpen(const void *cellHandle, const char *serverName,
2415 struct rx_connection **cmStatHandleP, afs_status_p st)
2418 afs_status_t tst = 0;
2419 afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
2421 struct rx_securityClass *sc;
2423 if (!CellHandleIsValid(cellHandle, &tst)) {
2424 goto fail_afsclient_CMStatOpen;
2427 if (!util_AdminServerAddressGetFromName(serverName, &servAddr, &tst)) {
2428 goto fail_afsclient_CMStatOpen;
2431 if (cmStatHandleP == NULL) {
2432 tst = ADMCLIENTCMSTATHANDLEPNULL;
2433 goto fail_afsclient_CMStatOpen;
2436 sc = c_handle->tokens->afs_sc[c_handle->tokens->sc_index];
2439 rx_GetCachedConnection(htonl(servAddr), htons(AFSCONF_CALLBACKPORT),
2440 1, sc, c_handle->tokens->sc_index);
2442 if (*cmStatHandleP == NULL) {
2443 tst = ADMCLIENTCMSTATNOCONNECTION;
2444 goto fail_afsclient_CMStatOpen;
2448 fail_afsclient_CMStatOpen:
2457 * afsclient_CMStatOpenPort - open an rx connection to a server to retrieve
2462 * IN cellHandle - a cellHandle created by afsclient_CellOpen.
2464 * IN serverName - the host name where the server resides.
2466 * IN port - the UDP port number where the server resides.
2468 * OUT cmStatHandleP - contains an rx connection to the server of interest
2472 * No locks are obtained or released by this function
2480 * Returns != 0 upon successful completion.
2484 afsclient_CMStatOpenPort(const void *cellHandle, const char *serverName,
2485 const int serverPort,
2486 struct rx_connection **cmStatHandleP,
2490 afs_status_t tst = 0;
2491 afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
2493 struct rx_securityClass *sc;
2495 if (!CellHandleIsValid(cellHandle, &tst)) {
2496 goto fail_afsclient_CMStatOpenPort;
2499 if (!util_AdminServerAddressGetFromName(serverName, &servAddr, &tst)) {
2500 goto fail_afsclient_CMStatOpenPort;
2503 if (cmStatHandleP == NULL) {
2504 tst = ADMCLIENTCMSTATHANDLEPNULL;
2505 goto fail_afsclient_CMStatOpenPort;
2508 sc = c_handle->tokens->afs_sc[c_handle->tokens->sc_index];
2511 rx_GetCachedConnection(htonl(servAddr), htons(serverPort), 1, sc,
2512 c_handle->tokens->sc_index);
2514 if (*cmStatHandleP == NULL) {
2515 tst = ADMCLIENTCMSTATNOCONNECTION;
2516 goto fail_afsclient_CMStatOpenPort;
2520 fail_afsclient_CMStatOpenPort:
2529 * afsclient_CMStatClose - close a previously opened rx connection.
2533 * IN cmStatHandle - an rx connection returned by afsclient_CMStatOpen
2537 * No locks are obtained or released by this function
2545 * Returns != 0 upon successful completion.
2549 afsclient_CMStatClose(struct rx_connection *cmStatHandle, afs_status_p st)
2552 afs_status_t tst = 0;
2554 if (cmStatHandle == NULL) {
2555 tst = ADMCLIENTCMSTATHANDLEPNULL;
2556 goto fail_afsclient_CMStatClose;
2559 rx_ReleaseCachedConnection(cmStatHandle);
2561 fail_afsclient_CMStatClose:
2570 * afsclient_RXDebugOpen - open an rxdebug handle to a server.
2574 * IN serverName - the host name where the server resides.
2576 * IN type - what type of process to query
2578 * OUT rxdebugHandle_p - contains an rxdebug handle for the server of interest
2582 * No locks are obtained or released by this function
2590 * Returns != 0 upon successful completion.
2594 afsclient_RXDebugOpen(const char *serverName, afs_stat_source_t type,
2595 rxdebugHandle_p * rxdebugHandleP, afs_status_p st)
2598 afs_status_t tst = 0;
2600 rxdebugHandle_p handle;
2601 rxdebugSocket_t sock;
2602 struct sockaddr_in taddr;
2606 if (rxdebugHandleP == NULL) {
2607 tst = ADMCLIENTRXDEBUGHANDLEPNULL;
2608 goto fail_afsclient_RXDebugOpen;
2614 serverPort = AFSCONF_NANNYPORT;
2617 case AFS_FILESERVER:
2618 serverPort = AFSCONF_FILEPORT;
2622 serverPort = AFSCONF_KAUTHPORT;
2626 serverPort = AFSCONF_PROTPORT;
2630 serverPort = AFSCONF_VOLUMEPORT;
2634 serverPort = AFSCONF_VLDBPORT;
2638 serverPort = AFSCONF_CALLBACKPORT;
2642 tst = ADMTYPEINVALID;
2643 goto fail_afsclient_RXDebugOpen;
2646 if (!util_AdminServerAddressGetFromName(serverName, &serverAddr, &tst)) {
2647 goto fail_afsclient_RXDebugOpen;
2650 sock = (rxdebugSocket_t) socket(AF_INET, SOCK_DGRAM, 0);
2651 if (sock == INVALID_RXDEBUG_SOCKET) {
2653 goto fail_afsclient_RXDebugOpen;
2656 memset(&taddr, 0, sizeof(taddr));
2657 taddr.sin_family = AF_INET;
2659 taddr.sin_addr.s_addr = INADDR_ANY;
2660 code = bind(sock, (struct sockaddr *)&taddr, sizeof(taddr));
2664 goto fail_afsclient_RXDebugOpen;
2667 handle = (rxdebugHandle_p) malloc(sizeof(rxdebugHandle_t));
2671 goto fail_afsclient_RXDebugOpen;
2674 handle->sock = sock;
2675 handle->ipAddr = serverAddr;
2676 handle->udpPort = serverPort;
2677 handle->firstFlag = 1;
2678 handle->supportedStats = 0;
2679 *rxdebugHandleP = handle;
2682 fail_afsclient_RXDebugOpen:
2691 * afsclient_RXDebugOpenPort - open an rxdebug handle to a server.
2695 * IN serverName - the host name where the server resides.
2697 * IN port - the UDP port number where the server resides.
2699 * OUT rxdebugHandle_p - contains an rxdebug handle for the server of interest
2703 * No locks are obtained or released by this function
2711 * Returns != 0 upon successful completion.
2715 afsclient_RXDebugOpenPort(const char *serverName, int serverPort,
2716 rxdebugHandle_p * rxdebugHandleP, afs_status_p st)
2719 afs_status_t tst = 0;
2721 rxdebugHandle_p handle;
2722 rxdebugSocket_t sock;
2723 struct sockaddr_in taddr;
2726 if (rxdebugHandleP == NULL) {
2727 tst = ADMCLIENTRXDEBUGHANDLEPNULL;
2728 goto fail_afsclient_RXDebugOpenPort;
2731 if (!util_AdminServerAddressGetFromName(serverName, &serverAddr, &tst)) {
2732 goto fail_afsclient_RXDebugOpenPort;
2735 sock = (rxdebugSocket_t) socket(AF_INET, SOCK_DGRAM, 0);
2736 if (sock == INVALID_RXDEBUG_SOCKET) {
2738 goto fail_afsclient_RXDebugOpenPort;
2741 memset(&taddr, 0, sizeof(taddr));
2742 taddr.sin_family = AF_INET;
2744 taddr.sin_addr.s_addr = INADDR_ANY;
2745 code = bind(sock, (struct sockaddr *)&taddr, sizeof(taddr));
2749 goto fail_afsclient_RXDebugOpenPort;
2752 handle = (rxdebugHandle_p) malloc(sizeof(rxdebugHandle_t));
2756 goto fail_afsclient_RXDebugOpenPort;
2759 handle->sock = sock;
2760 handle->ipAddr = serverAddr;
2761 handle->udpPort = serverPort;
2762 handle->firstFlag = 1;
2763 handle->supportedStats = 0;
2764 *rxdebugHandleP = handle;
2767 fail_afsclient_RXDebugOpenPort:
2776 * afsclient_RXDebugClose - close a previously opened rxdebug handle.
2780 * IN rxdebugHandle - an rxdebug handle returned by afsclient_RXDebugOpen
2784 * No locks are obtained or released by this function
2792 * Returns != 0 upon successful completion.
2796 afsclient_RXDebugClose(rxdebugHandle_p rxdebugHandle, afs_status_p st)
2799 afs_status_t tst = 0;
2801 if (rxdebugHandle == NULL) {
2802 tst = ADMCLIENTRXDEBUGHANDLEPNULL;
2803 goto fail_afsclient_RXDebugClose;
2806 close(rxdebugHandle->sock);
2807 free(rxdebugHandle);
2809 fail_afsclient_RXDebugClose: