Import Upstream version 1.8.5
[hcoop/debian/openafs.git] / src / libadmin / client / afs_clientAdmin.c
1 /*
2 * Copyright 2000, International Business Machines Corporation and others.
3 * All Rights Reserved.
4 *
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
8 */
9
10 #include <afsconfig.h>
11 #include <afs/param.h>
12 #include <afs/stds.h>
13
14 #include <roken.h>
15
16 #ifdef AFS_NT40_ENV
17 #include <afs/afssyscalls.h>
18 #include <afs/fs_utils.h>
19 #define close(x) closesocket(x)
20 #else
21 #include <afs/venus.h>
22 #endif
23 #include <rx/rx.h>
24 #include <rx/rxstat.h>
25 #include <rx/rx_null.h>
26 #include <rx/rxkad.h>
27
28 #include <afs/kautils.h>
29 #include <afs/dirpath.h>
30 #include <afs/afs_AdminErrors.h>
31 #include <afs/afs_vosAdmin.h>
32 #include <afs/afs_utilAdmin.h>
33 #include <afs/ptserver.h>
34 #include <afs/vlserver.h>
35 #include <afs/pthread_glock.h>
36 #include <afs/sys_prototypes.h>
37
38 #include "afs_clientAdmin.h"
39 #include "../adminutil/afs_AdminInternal.h"
40
41 /*
42 * AFS client administration functions.
43 *
44 * Admin functions that are normally associated with the client.
45 *
46 * All of the functions related to authentication are here, plus
47 * some miscellaneous others.
48 *
49 */
50
51 static const unsigned long ADMIN_TICKET_LIFETIME = 24 * 3600;
52
53 static const unsigned long SERVER_TTL = 10 * 60;
54
55 /*
56 * We need a way to track whether or not the client library has been
57 * initialized. We count on the fact that the other library initialization
58 * functions are protected by their own once mechanism. We only track
59 * our own internal status
60 */
61
62 static int client_init;
63 static pthread_once_t client_init_once = PTHREAD_ONCE_INIT;
64
65 static void
66 client_once(void)
67 {
68 client_init = 1;
69 }
70
71 /*
72 * IsTokenValid - validate a token handle
73 *
74 * PARAMETERS
75 *
76 * IN token - the token to be validated.
77 *
78 * LOCKS
79 *
80 * No locks are obtained or released by this function
81 *
82 * CAUTIONS
83 *
84 * None.
85 *
86 * RETURN CODES
87 *
88 * Returns != 0 upon successful completion.
89 */
90
91 static int
92 IsTokenValid(const afs_token_handle_p token, afs_status_p st)
93 {
94 int rc = 0;
95 afs_status_t tst = 0;
96
97 if (token == NULL) {
98 tst = ADMCLIENTTOKENHANDLENULL;
99 goto fail_IsTokenValid;
100 }
101
102 if (token->is_valid == 0) {
103 tst = ADMCLIENTTOKENHANDLEINVALID;
104 goto fail_IsTokenValid;
105 }
106
107 if ((token->begin_magic != BEGIN_MAGIC)
108 || (token->end_magic != END_MAGIC)) {
109 tst = ADMCLIENTTOKENHANDLEBADMAGIC;
110 goto fail_IsTokenValid;
111 }
112 rc = 1;
113
114 fail_IsTokenValid:
115
116 if (st != NULL) {
117 *st = tst;
118 }
119 return rc;
120 }
121
122 /*
123 * afsclient_TokenGetExisting - get tokens that already exist and
124 * are held by the cache manager.
125 *
126 * PARAMETERS
127 *
128 * IN cellName - the name of the cell where the token originated.
129 *
130 * OUT tokenHandle - a handle to the tokens if they were obtained
131 * successfully.
132 *
133 * LOCKS
134 *
135 * No locks are obtained or released by this function
136 *
137 * CAUTIONS
138 *
139 * The tokenHandle returned by this function cannot be used for kas
140 * related operations, since kas tokens aren't stored in the kernel.
141 *
142 * RETURN CODES
143 *
144 * Returns != 0 upon successful completion.
145 */
146
147 int ADMINAPI
148 afsclient_TokenGetExisting(const char *cellName, void **tokenHandle,
149 afs_status_p st)
150 {
151 int rc = 0;
152 afs_status_t tst = 0;
153 struct ktc_principal afs_server;
154 afs_token_handle_p t_handle =
155 (afs_token_handle_p) calloc(1, sizeof(afs_token_handle_t));
156
157 if (client_init == 0) {
158 tst = ADMCLIENTNOINIT;
159 goto fail_afsclient_TokenGetExisting;
160 }
161
162 if (cellName == NULL) {
163 tst = ADMCLIENTCELLNAMENULL;
164 goto fail_afsclient_TokenGetExisting;
165 }
166
167 if (tokenHandle == NULL) {
168 tst = ADMCLIENTTOKENHANDLENULL;
169 goto fail_afsclient_TokenGetExisting;
170 }
171
172 if (t_handle == NULL) {
173 tst = ADMNOMEM;
174 goto fail_afsclient_TokenGetExisting;
175 }
176
177 strcpy(afs_server.name, "afs");
178 afs_server.instance[0] = 0;
179 strcpy(afs_server.cell, cellName);
180
181 if (!
182 (tst =
183 ktc_GetToken(&afs_server, &t_handle->afs_token,
184 sizeof(t_handle->afs_token), &t_handle->client))) {
185 /*
186 * The token has been retrieved successfully, initialize
187 * the rest of the token handle structure
188 */
189 strncpy(t_handle->cell, cellName, MAXCELLCHARS);
190 t_handle->cell[MAXCELLCHARS - 1] = '\0';
191 t_handle->afs_token_set = 1;
192 t_handle->from_kernel = 1;
193 t_handle->kas_token_set = 0;
194 t_handle->sc_index = 2;
195 t_handle->afs_sc[t_handle->sc_index] =
196 rxkad_NewClientSecurityObject(rxkad_clear,
197 &t_handle->afs_token.sessionKey,
198 t_handle->afs_token.kvno,
199 t_handle->afs_token.ticketLen,
200 t_handle->afs_token.ticket);
201 t_handle->afs_encrypt_sc[t_handle->sc_index] =
202 rxkad_NewClientSecurityObject(rxkad_crypt,
203 &t_handle->afs_token.sessionKey,
204 t_handle->afs_token.kvno,
205 t_handle->afs_token.ticketLen,
206 t_handle->afs_token.ticket);
207 if ((t_handle->afs_sc[t_handle->sc_index] == NULL)
208 || (t_handle->afs_sc[t_handle->sc_index] == NULL)) {
209 tst = ADMCLIENTTOKENHANDLENOSECURITY;
210 goto fail_afsclient_TokenGetExisting;
211 } else {
212 t_handle->begin_magic = BEGIN_MAGIC;
213 t_handle->is_valid = 1;
214 t_handle->end_magic = END_MAGIC;
215 *tokenHandle = (void *)t_handle;
216 }
217 } else {
218 goto fail_afsclient_TokenGetExisting;
219 }
220 rc = 1;
221
222 fail_afsclient_TokenGetExisting:
223
224 if ((rc == 0) && (t_handle != NULL)) {
225 free(t_handle);
226 }
227 if (st != NULL) {
228 *st = tst;
229 }
230 return rc;
231 }
232
233 /*
234 * afsclient_TokenSet - set the tokens represented by tokenHandle to be
235 * active in the kernel (aka ka_SetToken).
236 *
237 * PARAMETERS
238 *
239 * IN cellName - the name of the cell where the token originated.
240 *
241 * OUT tokenHandle - a handle to the tokens if they were obtained
242 * successfully.
243 *
244 * LOCKS
245 *
246 * No locks are obtained or released by this function
247 *
248 * CAUTIONS
249 *
250 * The tokenHandle returned by this function cannot be used for kas
251 * related operations, since kas tokens aren't stored in the kernel.
252 *
253 * RETURN CODES
254 *
255 * Returns != 0 upon successful completion.
256 */
257
258 int ADMINAPI
259 afsclient_TokenSet(const void *tokenHandle, afs_status_p st)
260 {
261 int rc = 0;
262 afs_status_t tst = 0;
263 struct ktc_principal afs_server;
264 afs_token_handle_p t_handle = (afs_token_handle_p) tokenHandle;
265
266 if (!IsTokenValid(t_handle, &tst)) {
267 goto fail_afsclient_TokenSet;
268 }
269
270 strcpy(afs_server.name, "afs");
271 afs_server.instance[0] = 0;
272 strcpy(afs_server.cell, t_handle->cell);
273
274 tst =
275 ktc_SetToken(&afs_server, &t_handle->afs_token, &t_handle->client, 0);
276
277 if (!tst) {
278 rc = 1;
279 }
280
281 fail_afsclient_TokenSet:
282
283 if (st != NULL) {
284 *st = tst;
285 }
286 return rc;
287 }
288
289 /*
290 * GetKASToken - get a KAS token and store it in the tokenHandle.
291 *
292 * PARAMETERS
293 *
294 * IN cellName - the name of the cell where the token should be obtained.
295 *
296 * IN principal - the name of the user of the token.
297 *
298 * IN password - the password for the principal.
299 *
300 * OUT tokenHandle - a handle to the tokens if they were obtained
301 * successfully.
302 *
303 * LOCKS
304 *
305 * No locks are obtained or released by this function
306 *
307 * CAUTIONS
308 *
309 * None.
310 *
311 * RETURN CODES
312 *
313 * Returns != 0 upon successful completion.
314 */
315
316 static int
317 GetKASToken(const char *cellName, const char *principal, const char *password,
318 afs_token_handle_p tokenHandle, afs_status_p st)
319 {
320 int rc = 0;
321 afs_status_t tst = 0;
322 struct ubik_client *unauth_conn;
323 afs_int32 expire;
324 struct ktc_encryptionKey key;
325 struct ktc_token *token;
326 unsigned long now = time(0);
327 char name[MAXKTCNAMELEN];
328 char inst[MAXKTCNAMELEN];
329 int have_server_conn = 0;
330
331 token = &tokenHandle->kas_token;
332
333 ka_StringToKey((char *)password, (char *)cellName, &key);
334
335 /*
336 * Get an unauthenticated connection in the right cell to use for
337 * retrieving the token.
338 */
339
340 tst =
341 ka_AuthServerConn((char *)cellName, KA_AUTHENTICATION_SERVICE, 0,
342 &unauth_conn);
343 if (tst != 0) {
344 goto fail_GetKASToken;
345 }
346 have_server_conn = 1;
347
348 tst = ka_ParseLoginName((char *)principal, name, inst, NULL);
349 if (tst != 0) {
350 goto fail_GetKASToken;
351 }
352
353 tst =
354 ka_Authenticate(name, inst, (char *)cellName, unauth_conn,
355 KA_MAINTENANCE_SERVICE, &key, now,
356 now + ADMIN_TICKET_LIFETIME, token, &expire);
357 if (tst != 0) {
358 goto fail_GetKASToken;
359 }
360 rc = 1;
361
362 fail_GetKASToken:
363
364 if (have_server_conn) {
365 ubik_ClientDestroy(unauth_conn);
366 }
367
368 if (st != NULL) {
369 *st = tst;
370 }
371 return rc;
372 }
373
374 /*
375 * GetAFSToken - get a AFS token and store it in the tokenHandle.
376 *
377 * PARAMETERS
378 *
379 * IN cellName - the name of the cell where the token should be obtained.
380 *
381 * IN principal - the name of the user of the token.
382 *
383 * IN password - the password for the principal.
384 *
385 * OUT tokenHandle - a handle to the tokens if they were obtained
386 * successfully.
387 *
388 * LOCKS
389 *
390 * No locks are obtained or released by this function
391 *
392 * CAUTIONS
393 *
394 * None.
395 *
396 * RETURN CODES
397 *
398 * Returns != 0 upon successful completion.
399 */
400
401 static int
402 GetAFSToken(const char *cellName, const char *principal, const char *password,
403 afs_token_handle_p tokenHandle, afs_status_p st)
404 {
405 int rc = 0;
406 afs_status_t tst = 0;
407 struct ubik_client *unauth_conn = NULL, *auth_conn = NULL;
408 afs_int32 expire;
409 struct ktc_encryptionKey key;
410 struct ktc_token auth_token;
411 struct ktc_token *token;
412 unsigned long now = time(0);
413
414 token = &tokenHandle->afs_token;
415
416 ka_StringToKey((char *)password, (char *)cellName, &key);
417
418 /*
419 * Get an unauthenticated connection in the right cell to use for
420 * retrieving the token.
421 */
422
423 tst =
424 ka_AuthServerConn((char *)cellName, KA_AUTHENTICATION_SERVICE, 0,
425 &unauth_conn);
426 if (tst) {
427 goto fail_GetAFSToken;
428 }
429
430 tst =
431 ka_ParseLoginName((char *)principal, tokenHandle->client.name,
432 tokenHandle->client.instance, NULL);
433 if (tst) {
434 goto fail_GetAFSToken;
435 }
436
437 tst =
438 ka_Authenticate(tokenHandle->client.name,
439 tokenHandle->client.instance, (char *)cellName,
440 unauth_conn, KA_TICKET_GRANTING_SERVICE, &key, now,
441 now + ADMIN_TICKET_LIFETIME, &auth_token, &expire);
442 if (tst) {
443 goto fail_GetAFSToken;
444 }
445
446 tst =
447 ka_AuthServerConn((char *)cellName, KA_TICKET_GRANTING_SERVICE, 0,
448 &auth_conn);
449 if (tst) {
450 goto fail_GetAFSToken;
451 }
452
453 tst =
454 ka_CellToRealm((char *)cellName, tokenHandle->client.cell, (int *)0);
455 if (tst) {
456 goto fail_GetAFSToken;
457 }
458
459 tst =
460 ka_GetToken("afs", "", (char *)cellName, tokenHandle->client.name,
461 tokenHandle->client.instance, auth_conn, now,
462 now + ADMIN_TICKET_LIFETIME, &auth_token,
463 tokenHandle->client.cell, token);
464 if (tst) {
465 goto fail_GetAFSToken;
466 }
467 rc = 1;
468
469 fail_GetAFSToken:
470
471 if (auth_conn) {
472 ubik_ClientDestroy(auth_conn);
473 }
474
475 if (unauth_conn) {
476 ubik_ClientDestroy(unauth_conn);
477 }
478
479 if (st != NULL) {
480 *st = tst;
481 }
482 return rc;
483 }
484
485
486 /*
487 * afsclient_TokenGetNew - get new tokens for a user and store them
488 * in the tokenHandle.
489 *
490 * PARAMETERS
491 *
492 * IN cellName - the name of the cell where the tokens should be obtained.
493 *
494 * IN principal - the name of the user of the tokens.
495 *
496 * IN password - the password for the principal.
497 *
498 * OUT tokenHandle - a handle to the tokens if they were obtained
499 * successfully.
500 *
501 * LOCKS
502 *
503 * No locks are obtained or released by this function
504 *
505 * CAUTIONS
506 *
507 * None.
508 *
509 * RETURN CODES
510 *
511 * Returns != 0 upon successful completion.
512 */
513
514 int ADMINAPI
515 afsclient_TokenGetNew(const char *cellName, const char *principal,
516 const char *password, void **tokenHandle,
517 afs_status_p st)
518 {
519 int rc = 0;
520 afs_status_t tst = 0;
521 afs_token_handle_p t_handle =
522 (afs_token_handle_p) calloc(1, sizeof(afs_token_handle_t));
523
524 if (client_init == 0) {
525 tst = ADMCLIENTNOINIT;
526 goto fail_afsclient_TokenGetNew;
527 }
528
529 if (t_handle == NULL) {
530 tst = ADMNOMEM;
531 goto fail_afsclient_TokenGetNew;
532 }
533
534 /*
535 * Check to see if the principal or password is missing. If it is,
536 * get unauthenticated tokens for the cell
537 */
538
539 if ((principal == NULL) || (*principal == 0) || (password == NULL)
540 || (*password == 0)) {
541 t_handle->from_kernel = 0;
542 t_handle->afs_token_set = 1;
543 t_handle->kas_token_set = 1;
544 t_handle->sc_index = 0;
545 t_handle->afs_sc[t_handle->sc_index] =
546 rxnull_NewClientSecurityObject();
547 t_handle->afs_encrypt_sc[t_handle->sc_index] =
548 rxnull_NewClientSecurityObject();
549 t_handle->kas_sc[t_handle->sc_index] =
550 rxnull_NewClientSecurityObject();
551 t_handle->begin_magic = BEGIN_MAGIC;
552 t_handle->is_valid = 1;
553 t_handle->afs_token.endTime = 0;
554 t_handle->end_magic = END_MAGIC;
555 *tokenHandle = (void *)t_handle;
556
557 } else {
558
559 /*
560 * create an authenticated token
561 */
562
563 if ((GetAFSToken(cellName, principal, password, t_handle, &tst))
564 && (GetKASToken(cellName, principal, password, t_handle, &tst))) {
565 strncpy(t_handle->cell, cellName, MAXCELLCHARS);
566 t_handle->cell[MAXCELLCHARS - 1] = '\0';
567 t_handle->from_kernel = 0;
568 t_handle->afs_token_set = 1;
569 t_handle->kas_token_set = 1;
570 t_handle->sc_index = 2;
571 t_handle->afs_sc[t_handle->sc_index] =
572 rxkad_NewClientSecurityObject(rxkad_clear,
573 &t_handle->afs_token.sessionKey,
574 t_handle->afs_token.kvno,
575 t_handle->afs_token.ticketLen,
576 t_handle->afs_token.ticket);
577 t_handle->afs_encrypt_sc[t_handle->sc_index] =
578 rxkad_NewClientSecurityObject(rxkad_crypt,
579 &t_handle->afs_token.sessionKey,
580 t_handle->afs_token.kvno,
581 t_handle->afs_token.ticketLen,
582 t_handle->afs_token.ticket);
583 t_handle->kas_sc[t_handle->sc_index] =
584 rxkad_NewClientSecurityObject(rxkad_crypt,
585 &t_handle->kas_token.sessionKey,
586 t_handle->kas_token.kvno,
587 t_handle->kas_token.ticketLen,
588 t_handle->kas_token.ticket);
589 if ((t_handle->afs_sc[t_handle->sc_index] != NULL)
590 && (t_handle->afs_encrypt_sc[t_handle->sc_index] != NULL)
591 && (t_handle->kas_sc[t_handle->sc_index] != NULL)) {
592 t_handle->begin_magic = BEGIN_MAGIC;
593 t_handle->is_valid = 1;
594 t_handle->end_magic = END_MAGIC;
595 *tokenHandle = (void *)t_handle;
596 } else {
597 tst = ADMCLIENTTOKENHANDLENOSECURITY;
598 goto fail_afsclient_TokenGetNew;
599 }
600 } else {
601 goto fail_afsclient_TokenGetNew;
602 }
603 }
604 rc = 1;
605
606 fail_afsclient_TokenGetNew:
607
608 if ((rc == 0) && (t_handle != NULL)) {
609 free(t_handle);
610 }
611
612 if (st != NULL) {
613 *st = tst;
614 }
615 return rc;
616 }
617
618 /*
619 * afsclient_TokenQuery - get the expiration time of the tokens.
620 *
621 * PARAMETERS
622 *
623 * IN tokenHandle - a previously obtained valid token.
624 *
625 * OUT expirationDateP - the time at which the tokens expire.
626 *
627 * OUT principal - the owning principal
628 *
629 * OUT instance - principal instance if it exists.
630 *
631 * OUT cell - the principal's cell
632 *
633 * OUT hasKasTokens - set to 1 if the token handle contains kas tokens.
634 *
635 * LOCKS
636 *
637 * No locks are obtained or released by this function
638 *
639 * CAUTIONS
640 *
641 * We only check the AFS tokens since we always get these. The
642 * KAS tokens may expirer later than the AFS tokens, but this
643 * difference is minor and reporting an earlier time won't cause
644 * the user problems.
645 *
646 * RETURN CODES
647 *
648 * Returns != 0 upon successful completion.
649 */
650
651 int ADMINAPI
652 afsclient_TokenQuery(void *tokenHandle, unsigned long *expirationDateP,
653 char *principal, char *instance, char *cell,
654 int *hasKasTokens, afs_status_p st)
655 {
656 int rc = 0;
657 afs_status_t tst = 0;
658 afs_token_handle_p t_handle = (afs_token_handle_p) tokenHandle;
659
660 if (client_init == 0) {
661 tst = ADMCLIENTNOINIT;
662 rc = 0;
663 goto fail_afsclient_TokenQuery;
664 }
665
666 if (IsTokenValid(t_handle, &tst)) {
667 if (principal != NULL) {
668 strcpy(principal, t_handle->client.name);
669 }
670 if (instance != NULL) {
671 strcpy(instance, t_handle->client.instance);
672 }
673 if (cell != NULL) {
674 strcpy(cell, t_handle->client.cell);
675 }
676 if (hasKasTokens != NULL) {
677 *hasKasTokens = t_handle->kas_token_set;
678 }
679 if (expirationDateP != NULL) {
680 *expirationDateP = t_handle->afs_token.endTime;
681 }
682 rc = 1;
683 }
684
685 fail_afsclient_TokenQuery:
686
687 if (st != NULL) {
688 *st = tst;
689 }
690 return rc;
691 }
692
693 /*
694 * afsclient_TokenClose - close an existing token.
695 *
696 * PARAMETERS
697 *
698 * IN token - the token to be closed.
699 *
700 * LOCKS
701 *
702 * No locks are obtained or released by this function
703 *
704 * CAUTIONS
705 *
706 * None.
707 *
708 * RETURN CODES
709 *
710 * Returns != 0 upon successful completion.
711 */
712
713 int ADMINAPI
714 afsclient_TokenClose(const void *tokenHandle, afs_status_p st)
715 {
716 int rc = 0;
717 afs_status_t tst = 0;
718 afs_token_handle_p t_handle = (afs_token_handle_p) tokenHandle;
719
720 if (client_init == 0) {
721 tst = ADMCLIENTNOINIT;
722 goto fail_afsclient_TokenClose;
723 }
724
725 if (IsTokenValid(t_handle, &tst)) {
726 t_handle->is_valid = 0;
727 free(t_handle);
728 rc = 1;
729 }
730
731 fail_afsclient_TokenClose:
732
733 if (st != NULL) {
734 *st = tst;
735 }
736 return rc;
737 }
738
739 #define NUM_SERVER_TYPES 3
740
741 /* must match NUM_SERVER_TYPES */
742 typedef enum { KAS, PTS, VOS } afs_server_list_t;
743
744 typedef struct afs_server {
745 char *serv;
746 int serviceId;
747 struct ubik_client **ubik;
748 struct rx_securityClass *sc;
749 int *valid;
750 } afs_server_t, *afs_server_p;
751
752 /*
753 * afsclient_CellOpen - Open a particular cell for work as a particular
754 * user.
755 *
756 * PARAMETERS
757 *
758 * IN cellName - the cell where future admin calls will be made.
759 *
760 * IN tokenHandle - the tokens work will be done under.
761 *
762 * OUT cellHandleP - an opaque pointer that is the first parameter to
763 * almost all subsequent admin api calls.
764 *
765 * LOCKS
766 *
767 * No locks are obtained or released by this function
768 *
769 * CAUTIONS
770 *
771 * None.
772 *
773 * RETURN CODES
774 *
775 * Returns != 0 upon successful completion.
776 */
777
778 int ADMINAPI
779 afsclient_CellOpen(const char *cellName, const void *tokenHandle,
780 void **cellHandleP, afs_status_p st)
781 {
782 int rc = 0;
783 afs_status_t tst = 0;
784 afs_token_handle_p t_handle = (afs_token_handle_p) tokenHandle;
785 afs_cell_handle_p c_handle = (afs_cell_handle_p)
786 calloc(1, sizeof(afs_cell_handle_t));
787 struct afsconf_dir *tdir = NULL;
788 struct afsconf_cell info;
789 struct rx_connection *serverconns[MAXSERVERS];
790 int i, j;
791 struct rx_securityClass *sc[3];
792 int scIndex;
793 char copyCell[MAXCELLCHARS];
794
795 afs_server_t servers[NUM_SERVER_TYPES]
796 = { {AFSCONF_KAUTHSERVICE, KA_MAINTENANCE_SERVICE, 0, 0, 0},
797 {AFSCONF_PROTSERVICE, PRSRV, 0, 0, 0},
798 {AFSCONF_VLDBSERVICE, USER_SERVICE_ID, 0, 0, 0}
799 };
800
801 if (client_init == 0) {
802 tst = ADMCLIENTNOINIT;
803 goto fail_afsclient_CellOpen;
804 }
805
806 if (c_handle == NULL) {
807 tst = ADMNOMEM;
808 goto fail_afsclient_CellOpen;
809 }
810
811 if (t_handle == NULL) {
812 tst = ADMCLIENTTOKENHANDLENULL;
813 goto fail_afsclient_CellOpen;
814 }
815
816 if ((cellName == NULL) || (*cellName == 0)) {
817 tst = ADMCLIENTCELLNAMENULL;
818 goto fail_afsclient_CellOpen;
819 }
820
821 if (cellHandleP == NULL) {
822 tst = ADMCLIENTCELLHANDLEPNULL;
823 goto fail_afsclient_CellOpen;
824 }
825
826 /*
827 * Check that the token handle contains valid data and the calloc
828 * succeeded
829 */
830 if (!t_handle->afs_token_set) {
831 tst = ADMCLIENTCELLOPENBADTOKEN;
832 goto fail_afsclient_CellOpen;
833 }
834
835 /*
836 * Use a table to initialize the cell handle structure, since
837 * most of the steps are the same for all the servers.
838 *
839 * Start by creating rx_securityClass objects for each of the
840 * servers. A potential optimization is to do this in
841 * afsclient_TokenGetNew and just keep the expiration time of
842 * the tokens around.
843 * Also, initialize the ubik client pointers in the table
844 */
845 servers[KAS].sc = t_handle->kas_sc[t_handle->sc_index];
846 servers[PTS].sc = t_handle->afs_sc[t_handle->sc_index];
847 servers[VOS].sc = servers[PTS].sc;
848 servers[KAS].ubik = &c_handle->kas;
849 servers[PTS].ubik = &c_handle->pts;
850 servers[VOS].ubik = &c_handle->vos;
851 servers[KAS].valid = &c_handle->kas_valid;
852 servers[PTS].valid = &c_handle->pts_valid;
853 servers[VOS].valid = &c_handle->vos_valid;
854 c_handle->vos_new = 1;
855
856 if ((servers[PTS].sc == NULL) || (servers[VOS].sc == NULL)) {
857 tst = ADMCLIENTBADTOKENHANDLE;
858 goto fail_afsclient_CellOpen;
859 }
860
861 /*
862 * If the initialization has succeeded so far, get the address
863 * information for each server in the cell
864 */
865
866 strncpy(c_handle->working_cell, cellName, MAXCELLCHARS);
867 c_handle->working_cell[MAXCELLCHARS - 1] = '\0';
868 if (!(tdir = afsconf_Open(AFSDIR_CLIENT_ETC_DIRPATH))) {
869 tst = ADMCLIENTBADCLIENTCONFIG;
870 goto fail_afsclient_CellOpen;
871 }
872
873 /*
874 * We must copy the cellName here because afsconf_GetCellInfo
875 * actually writes over the cell name it is passed.
876 */
877 strncpy(copyCell, cellName, MAXCELLCHARS);
878 copyCell[MAXCELLCHARS - 1] ='\0';
879 for (i = 0; (i < NUM_SERVER_TYPES); i++) {
880 if (i == KAS) {
881 tst =
882 ka_AuthServerConn((char *)cellName, servers[i].serviceId,
883 ((t_handle->sc_index == 0)
884 || (!t_handle->
885 kas_token_set)) ? 0 : &t_handle->
886 kas_token, servers[i].ubik);
887 if (tst) {
888 goto fail_afsclient_CellOpen;
889 }
890 } else {
891 tst = afsconf_GetCellInfo(tdir, copyCell, servers[i].serv, &info);
892 if (!tst) {
893 /* create ubik client handles for each server */
894 scIndex = t_handle->sc_index;
895 sc[scIndex] = servers[i].sc;
896 for (j = 0; (j < info.numServers); j++) {
897 serverconns[j] =
898 rx_GetCachedConnection(info.hostAddr[j].sin_addr.
899 s_addr,
900 info.hostAddr[j].sin_port,
901 servers[i].serviceId,
902 sc[scIndex], scIndex);
903 }
904 serverconns[j] = 0;
905 tst = ubik_ClientInit(serverconns, servers[i].ubik);
906 if (tst) {
907 goto fail_afsclient_CellOpen;
908 }
909 } else {
910 goto fail_afsclient_CellOpen;
911 }
912 }
913 /* initialization complete, mark handle valid */
914 *servers[i].valid = 1;
915 }
916 c_handle->tokens = t_handle;
917 rc = 1;
918
919 fail_afsclient_CellOpen:
920
921 if (tdir) {
922 afsconf_Close(tdir);
923 }
924
925 /*
926 * Upon error, free any obtained resources.
927 */
928 if (rc == 0) {
929 if (c_handle != NULL) {
930 if (c_handle->kas_valid)
931 ubik_ClientDestroy(c_handle->kas);
932 if (c_handle->pts_valid)
933 ubik_ClientDestroy(c_handle->pts);
934 if (c_handle->vos_valid)
935 ubik_ClientDestroy(c_handle->vos);
936 free(c_handle);
937 }
938 } else {
939 c_handle->begin_magic = BEGIN_MAGIC;
940 c_handle->is_valid = 1;
941 c_handle->is_null = 0;
942 c_handle->server_list = NULL;
943 c_handle->server_ttl = 0;
944 c_handle->end_magic = END_MAGIC;
945 *cellHandleP = (void *)c_handle;
946 }
947
948 if (st != NULL) {
949 *st = tst;
950 }
951 return rc;
952 }
953
954 /*
955 * afsclient_NullCellOpen - open a null cell handle for access.
956 *
957 * PARAMETERS
958 *
959 * OUT cellHandleP - an opaque pointer that is the first parameter to
960 * almost all subsequent admin api calls.
961 *
962 * LOCKS
963 *
964 * No locks are obtained or released by this function
965 *
966 * CAUTIONS
967 *
968 * None.
969 *
970 * RETURN CODES
971 *
972 * Returns != 0 upon successful completion.
973 */
974
975 int ADMINAPI
976 afsclient_NullCellOpen(void **cellHandleP, afs_status_p st)
977 {
978 int rc = 0;
979 afs_status_t tst = 0;
980 afs_cell_handle_p c_handle = (afs_cell_handle_p)
981 calloc(1, sizeof(afs_cell_handle_t));
982
983
984 /*
985 * Validate parameters
986 */
987
988 if (cellHandleP == NULL) {
989 tst = ADMCLIENTCELLHANDLEPNULL;
990 goto fail_afsclient_NullCellOpen;
991 }
992
993 if (client_init == 0) {
994 tst = ADMCLIENTNOINIT;
995 goto fail_afsclient_NullCellOpen;
996 }
997
998 if (c_handle == NULL) {
999 tst = ADMNOMEM;
1000 goto fail_afsclient_NullCellOpen;
1001 }
1002
1003 /*
1004 * Get unauthenticated tokens for any cell
1005 */
1006
1007 if (!afsclient_TokenGetNew(0, 0, 0, (void *)&c_handle->tokens, &tst)) {
1008 goto fail_afsclient_NullCellOpen;
1009 }
1010
1011 c_handle->begin_magic = BEGIN_MAGIC;
1012 c_handle->is_valid = 1;
1013 c_handle->is_null = 1;
1014 c_handle->end_magic = END_MAGIC;
1015 c_handle->kas_valid = 0;
1016 c_handle->pts_valid = 0;
1017 c_handle->vos_valid = 0;
1018 c_handle->kas = NULL;
1019 c_handle->pts = NULL;
1020 c_handle->vos = NULL;
1021 c_handle->server_list = NULL;
1022 c_handle->server_ttl = 0;
1023 *cellHandleP = (void *)c_handle;
1024 rc = 1;
1025
1026 fail_afsclient_NullCellOpen:
1027
1028 if (st != NULL) {
1029 *st = tst;
1030 }
1031 return rc;
1032 }
1033
1034 /*
1035 * afsclient_CellClose - close a previously opened cellHandle.
1036 *
1037 * PARAMETERS
1038 *
1039 * IN cellHandle - a cellHandle created by afsclient_CellOpen.
1040 *
1041 * LOCKS
1042 *
1043 * No locks are obtained or released by this function
1044 *
1045 * CAUTIONS
1046 *
1047 * None.
1048 *
1049 * RETURN CODES
1050 *
1051 * Returns != 0 upon successful completion.
1052 */
1053
1054 int ADMINAPI
1055 afsclient_CellClose(const void *cellHandle, afs_status_p st)
1056 {
1057 int rc = 0;
1058 afs_status_t tst = 0;
1059 afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
1060
1061 if (client_init == 0) {
1062 tst = ADMCLIENTNOINIT;
1063 goto fail_afsclient_CellClose;
1064 }
1065
1066 if (c_handle == NULL) {
1067 tst = ADMCLIENTCELLHANDLENULL;
1068 goto fail_afsclient_CellClose;
1069 }
1070
1071 if (c_handle->server_list)
1072 free(c_handle->server_list);
1073 if (c_handle->kas_valid)
1074 ubik_ClientDestroy(c_handle->kas);
1075 if (c_handle->pts_valid)
1076 ubik_ClientDestroy(c_handle->pts);
1077 if (c_handle->vos_valid)
1078 ubik_ClientDestroy(c_handle->vos);
1079 if (c_handle->is_null)
1080 afsclient_TokenClose(c_handle->tokens, 0);
1081 c_handle->kas_valid = 0;
1082 c_handle->pts_valid = 0;
1083 c_handle->vos_valid = 0;
1084 c_handle->is_valid = 0;
1085 free(c_handle);
1086 rc = 1;
1087
1088 fail_afsclient_CellClose:
1089
1090 if (st != NULL) {
1091 *st = tst;
1092 }
1093 return rc;
1094 }
1095
1096
1097 /*
1098 * afsclient_CellNameGet() -- get a pointer to the cell name in a cell handle
1099 *
1100 * PARAMETERS
1101 *
1102 * IN cellHandle - a valid cell handle
1103 * OUT cellNameP - a pointer to the cell name in the cell handle.
1104 *
1105 * LOCKS
1106 *
1107 * No locks are obtained or released by this function
1108 *
1109 * CAUTIONS
1110 *
1111 * If cellHandle is closed then the pointer returned by this function
1112 * is no longer valid.
1113 *
1114 * RETURN CODES
1115 *
1116 * Returns != 0 upon successful completion.
1117 */
1118 int ADMINAPI
1119 afsclient_CellNameGet(const void *cellHandle, const char **cellNameP,
1120 afs_status_p st)
1121 {
1122 int rc = 0;
1123 afs_status_t tst = 0;
1124 afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
1125
1126 if (!CellHandleIsValid(cellHandle, &tst)) {
1127 goto fail_afsclient_CellNameGet;
1128 }
1129
1130 *cellNameP = c_handle->working_cell;
1131 rc = 1;
1132
1133 fail_afsclient_CellNameGet:
1134
1135 if (st != NULL) {
1136 *st = tst;
1137 }
1138 return rc;
1139 }
1140
1141
1142 /*
1143 * afsclient_LocalCellGet - get the name of the cell the machine
1144 * belongs to where this process is running.
1145 *
1146 * PARAMETERS
1147 *
1148 * OUT cellName - an array of characters that must be MAXCELLCHARS
1149 * long.
1150 *
1151 * LOCKS
1152 *
1153 * No locks are obtained or released by this function
1154 *
1155 * CAUTIONS
1156 *
1157 * If cellName is smaller than MAXCELLCHARS chars, this function won't
1158 * detect it.
1159 *
1160 * RETURN CODES
1161 *
1162 * Returns != 0 upon successful completion.
1163 */
1164
1165 int ADMINAPI
1166 afsclient_LocalCellGet(char *cellName, afs_status_p st)
1167 {
1168 int rc = 0;
1169 afs_status_t tst = 0;
1170 struct afsconf_dir *tdir = NULL;
1171
1172 if (client_init == 0) {
1173 tst = ADMCLIENTNOINIT;
1174 goto fail_afsclient_LocalCellGet;
1175 }
1176
1177 if (cellName == NULL) {
1178 tst = ADMCLIENTCELLNAMENULL;
1179 goto fail_afsclient_LocalCellGet;
1180 }
1181
1182 tdir = afsconf_Open(AFSDIR_CLIENT_ETC_DIRPATH);
1183
1184 if (!tdir) {
1185 tst = ADMCLIENTBADCLIENTCONFIG;
1186 goto fail_afsclient_LocalCellGet;
1187 }
1188
1189 if ((tst = afsconf_GetLocalCell(tdir, cellName, MAXCELLCHARS))) {
1190 goto fail_afsclient_LocalCellGet;
1191 }
1192
1193 rc = 1;
1194
1195 fail_afsclient_LocalCellGet:
1196
1197 if (tdir != NULL) {
1198 afsconf_Close(tdir);
1199 }
1200
1201 if (st != NULL) {
1202 *st = tst;
1203 }
1204 return rc;
1205 }
1206
1207
1208 #ifdef AFS_NT40_ENV
1209
1210 static int
1211 client_ExtractDriveLetter(char *path)
1212 {
1213 int rc = 0;
1214
1215 if (path[0] != 0 && path[1] == ':') {
1216 path[2] = 0;
1217 rc = 1;
1218 }
1219
1220 return rc;
1221 }
1222
1223 /*
1224 * Determine the parent directory of a give directory
1225 */
1226
1227 static int
1228 Parent(char *directory, char *parentDirectory)
1229 {
1230 char *tp;
1231 int rc = 0;
1232
1233 strcpy(parentDirectory, directory);
1234 tp = strrchr(parentDirectory, '\\');
1235 if (tp) {
1236 /* lv trailing slash so Parent("k:\foo") is "k:\" not "k :" */
1237 *(tp + 1) = 0;
1238 rc = 1;
1239 } else {
1240 if (client_ExtractDriveLetter(parentDirectory)) {
1241 strcat(parentDirectory, ".");
1242 rc = 1;
1243 }
1244 }
1245
1246 return rc;
1247 }
1248
1249 #else
1250 /*
1251 * Determine the parent directory of a give directory
1252 */
1253 static int
1254 Parent(const char *directory, char *parentDirectory)
1255 {
1256 char *tp;
1257 int rc = 0;
1258
1259 strcpy(parentDirectory, directory);
1260 tp = strrchr(parentDirectory, '/');
1261 if (tp) {
1262 *tp = 0;
1263 rc = 1;
1264 } else {
1265 strcpy(parentDirectory, ".");
1266 rc = 1;
1267 }
1268
1269 return rc;
1270 }
1271 #endif
1272
1273 /*
1274 * afsclient_MountPointCreate - create a mount point for a volume.
1275 *
1276 * PARAMETERS
1277 *
1278 * IN cellHandle - a handle to the cell where volumeName resides.
1279 *
1280 * IN directory - the directory where the mountpoint should be created.
1281 *
1282 * IN volumeName - the name of the volume to mount.
1283 *
1284 * IN volType - the type of mount point to create.
1285 *
1286 * IN volCheck - indicates whether or not to check the VLDB to see if
1287 * volumeName exists.
1288 *
1289 * LOCKS
1290 *
1291 * No locks are obtained or released by this function
1292 *
1293 * RETURN CODES
1294 *
1295 * Returns != 0 upon successful completion.
1296 */
1297
1298 #define TMP_DATA_SIZE 2048
1299
1300 int ADMINAPI
1301 afsclient_MountPointCreate(const void *cellHandle, const char *directory,
1302 const char *volumeName, vol_type_t volType,
1303 vol_check_t volCheck, afs_status_p st)
1304 {
1305 int rc = 0;
1306 afs_status_t tst = 0;
1307 afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
1308 char parent_dir[TMP_DATA_SIZE];
1309 char space[TMP_DATA_SIZE];
1310 char directoryCell[MAXCELLCHARS];
1311 struct ViceIoctl idata;
1312 int i;
1313 vos_vldbEntry_t vldbEntry;
1314
1315 /*
1316 * Validate arguments
1317 */
1318
1319 if (client_init == 0) {
1320 tst = ADMCLIENTNOINIT;
1321 goto fail_afsclient_MountPointCreate;
1322 }
1323
1324 if ((directory == NULL) || (*directory == 0)) {
1325 tst = ADMCLIENTDIRECTORYNULL;
1326 goto fail_afsclient_MountPointCreate;
1327 }
1328
1329 if ((volumeName == NULL) || (*volumeName == 0)) {
1330 tst = ADMCLIENTVOLUMENAME;
1331 goto fail_afsclient_MountPointCreate;
1332 }
1333
1334 /*
1335 * Extract the parent directory and make sure it is in AFS.
1336 */
1337
1338 if (!Parent(directory, parent_dir)) {
1339 tst = ADMCLIENTBADDIRECTORY;
1340 goto fail_afsclient_MountPointCreate;
1341 }
1342
1343 idata.in_size = 0;
1344 idata.out_size = TMP_DATA_SIZE;
1345 idata.out = space;
1346 i = pioctl(parent_dir, VIOC_FILE_CELL_NAME, &idata, 1);
1347 if (i) {
1348 if ((errno == EINVAL) || (errno == ENOENT)) {
1349 tst = ADMCLIENTNOAFSDIRECTORY;
1350 goto fail_afsclient_MountPointCreate;
1351 }
1352 }
1353 strcpy(directoryCell, space);
1354
1355 /*
1356 * If the user requested, check that the volume exists
1357 */
1358
1359 if (volCheck == CHECK_VOLUME) {
1360 if (!vos_VLDBGet(cellHandle, 0, 0, (char *)volumeName, &vldbEntry,
1361 &tst)) {
1362 goto fail_afsclient_MountPointCreate;
1363 }
1364 }
1365
1366 /*
1367 * Begin constructing the pioctl buffer
1368 */
1369
1370 if (volType == READ_WRITE) {
1371 strcpy(space, "%");
1372 } else {
1373 strcpy(space, "#");
1374 }
1375
1376 /*
1377 * Append the cell to the mount point if the volume is in a different
1378 * cell than the directory
1379 */
1380
1381 if (strcmp(c_handle->working_cell, directoryCell)) {
1382 strcat(space, c_handle->working_cell);
1383 strcat(space, ":");
1384 }
1385 strcat(space, volumeName);
1386 strcat(space, ".");
1387
1388
1389 #ifdef AFS_NT40_ENV
1390 idata.out_size = 0;
1391 idata.out = NULL;
1392 idata.in_size = 1 + strlen(space);
1393 idata.in = space;
1394 if (tst = pioctl(directory, VIOC_AFS_CREATE_MT_PT, &idata, 0)) {
1395 goto fail_afsclient_MountPointCreate;
1396 }
1397 #else
1398 if ((tst = symlink(space, directory))) {
1399 goto fail_afsclient_MountPointCreate;
1400 }
1401 #endif
1402
1403 rc = 1;
1404
1405 fail_afsclient_MountPointCreate:
1406
1407 if (st != NULL) {
1408 *st = tst;
1409 }
1410 return rc;
1411 }
1412
1413 typedef struct Acl {
1414 int dfs;
1415 char cell[1025];
1416 int nplus;
1417 int nminus;
1418 } Acl_t, *Acl_p;
1419
1420 int ADMINAPI
1421 afsclient_ACLEntryAdd(const char *directory, const char *user,
1422 const acl_p acl, afs_status_p st)
1423 {
1424 int rc = 0;
1425 afs_status_t tst = 0;
1426 struct ViceIoctl idata;
1427 char old_acl_string[2048];
1428 char new_acl_string[2048];
1429 int newacl = 0;
1430 char *ptr;
1431 Acl_t cur_acl;
1432 char cur_user[64];
1433 int cur_user_acl = 0;
1434 int i;
1435 char tmp[64 + 35];
1436 int is_dfs;
1437
1438 if (client_init == 0) {
1439 tst = ADMCLIENTNOINIT;
1440 goto fail_afsclient_ACLEntryAdd;
1441 }
1442
1443 if ((directory == NULL) || (*directory == 0)) {
1444 tst = ADMMISCDIRECTORYNULL;
1445 goto fail_afsclient_ACLEntryAdd;
1446 }
1447
1448 if ((user == NULL) || (*user == 0)) {
1449 tst = ADMMISCUSERNULL;
1450 goto fail_afsclient_ACLEntryAdd;
1451 }
1452
1453 if (acl == NULL) {
1454 tst = ADMMISCACLNULL;
1455 goto fail_afsclient_ACLEntryAdd;
1456 }
1457
1458 if (acl->read == READ) {
1459 newacl |= 0x01;
1460 }
1461
1462 if (acl->write == WRITE) {
1463 newacl |= 0x02;
1464 }
1465
1466 if (acl->insert == INSERT) {
1467 newacl |= 0x04;
1468 }
1469
1470 if (acl->lookup == LOOKUP) {
1471 newacl |= 0x08;
1472 }
1473
1474 if (acl->del == DELETE) {
1475 newacl |= 0x10;
1476 }
1477
1478 if (acl->lock == LOCK) {
1479 newacl |= 0x20;
1480 }
1481
1482 if (acl->admin == ADMIN) {
1483 newacl |= 0x40;
1484 }
1485
1486 /*
1487 * Get the current acl for the directory
1488 */
1489
1490 idata.out_size = 2048;
1491 idata.in_size = 0;
1492 idata.in = idata.out = old_acl_string;
1493 tst = pioctl((char *)directory, VIOCGETAL, &idata, 1);
1494
1495 if (tst != 0) {
1496 goto fail_afsclient_ACLEntryAdd;
1497 }
1498
1499 /*
1500 * The acl is presented to us in string format. The format of the
1501 * string is:
1502 *
1503 * A header which contains the number of positive and negative entries
1504 * and a string indicating whether or not this is a dfs acl:
1505 *
1506 * num_pos "\n" dfs_string "\n" num_neg
1507 *
1508 * An entry for each acl that's of the form:
1509 *
1510 * name rights "\n"
1511 *
1512 * There are no blanks in the string between fields, but I use them here
1513 * to make the reading easier.
1514 *
1515 * Since we are only going to add another entry to the acl, our approach
1516 * is simple. Get the num_pos dfs_string and num_neg from the current acl,
1517 * increment num_pos by one and create a new string. Concatenate the new
1518 * user and rights to the new string, and then concatenate the remaining
1519 * contents of the old acl to the new string.
1520 *
1521 * Unfortunately, this approach doesn't work since the format the kernel
1522 * hands the acl back to us in, is NOT WHAT IT WANTS BACK!!!!
1523 * So instead we need to parse the entire freaking acl and put a space
1524 * between each user and their acl.
1525 *
1526 * This is really ugly.
1527 */
1528
1529 /*
1530 * Parse the first few fields of the acl and see if this is a DFS
1531 * file.
1532 */
1533
1534 is_dfs =
1535 sscanf(old_acl_string, "%d dfs:%d %1024s", &cur_acl.nplus, &cur_acl.dfs,
1536 cur_acl.cell);
1537 ptr = strchr(old_acl_string, '\n');
1538 ptr++;
1539 sscanf(ptr, "%d", &cur_acl.nminus);
1540 ptr = strchr(ptr, '\n');
1541 ptr++;
1542 if (is_dfs == 3) {
1543 tst = ADMMISCNODFSACL;
1544 goto fail_afsclient_ACLEntryAdd;
1545 } else {
1546 /*
1547 * It isn't a DFS file, so create the beginning of the string
1548 * we will hand back to the kernel
1549 */
1550 sprintf(new_acl_string, "%d\n%d\n%s %d\n", (cur_acl.nplus + 1),
1551 cur_acl.nminus, user, newacl);
1552 }
1553
1554 /*
1555 * Finish scanning the old acl, parsing each user/acl pair and
1556 * adding a space in the new acl.
1557 */
1558
1559 for (i = 0; i < (cur_acl.nplus + cur_acl.nminus); i++) {
1560 sscanf(ptr, "%63s%d\n", cur_user, &cur_user_acl);
1561 /*
1562 * Skip the entry for the user we are replacing/adding
1563 */
1564
1565 if (strcmp(cur_user, user)) {
1566 ptr = strchr(ptr, '\n');
1567 ptr++;
1568 sprintf(tmp, "%s %d\n", cur_user, cur_user_acl);
1569 strcat(new_acl_string, tmp);
1570 }
1571 }
1572
1573 strcat(new_acl_string, ptr);
1574
1575 /*
1576 * Set the acl
1577 */
1578
1579 idata.out_size = 0;
1580 idata.in_size = strlen(new_acl_string) + 1;
1581 idata.in = idata.out = new_acl_string;
1582 tst = pioctl((char *) directory, VIOCSETAL, &idata, 1);
1583
1584 if (tst != 0) {
1585 goto fail_afsclient_ACLEntryAdd;
1586 }
1587 rc = 1;
1588
1589 fail_afsclient_ACLEntryAdd:
1590
1591 if (st != NULL) {
1592 *st = tst;
1593 }
1594 return rc;
1595 }
1596
1597 /*
1598 * afsclient_Init - initialize AFS components before use.
1599 *
1600 * PARAMETERS
1601 *
1602 * LOCKS
1603 *
1604 * No locks are obtained or released by this function
1605 *
1606 * CAUTIONS
1607 *
1608 * None.
1609 *
1610 * RETURN CODES
1611 *
1612 * Returns != 0 upon successful completion.
1613 */
1614
1615 int ADMINAPI
1616 afsclient_Init(afs_status_p st)
1617 {
1618 int rc = 0;
1619 afs_status_t tst = 0;
1620
1621 if (!client_init)
1622 pthread_once(&client_init_once, client_once);
1623
1624 #ifdef AFS_NT40_ENV
1625 if (afs_winsockInit() < 0) {
1626 tst = ADMCLIENTCANTINITWINSOCK;
1627 goto fail_afsclient_Init;
1628 }
1629 #endif
1630
1631 if (!(initAFSDirPath() & AFSDIR_CLIENT_PATHS_OK)) {
1632 tst = ADMCLIENTCANTINITAFSLOCATION;
1633 goto fail_afsclient_Init;
1634 }
1635
1636 if (rx_Init(0) < 0) {
1637 tst = ADMCLIENTCANTINITRX;
1638 goto fail_afsclient_Init;
1639 }
1640
1641 if ((tst = ka_CellConfig((char *)AFSDIR_CLIENT_ETC_DIRPATH))) {
1642 goto fail_afsclient_Init;
1643 }
1644
1645 rc = 1;
1646
1647 fail_afsclient_Init:
1648
1649 if (st != NULL) {
1650 *st = tst;
1651 }
1652 return rc;
1653 }
1654
1655 /*
1656 * afsclient_AFSServerGet - determine what kind of server serverName
1657 * is and fill in serverEntryP accordingly.
1658 *
1659 * PARAMETERS
1660 *
1661 * IN cellHandle - a cellHandle previously returned by afsclient_CellOpen.
1662 *
1663 * IN serverName - the hostname of the server of interest.
1664 *
1665 * OUT serverEntryP - upon successful completion contains a description of
1666 * the server.
1667 *
1668 * LOCKS
1669 *
1670 * No locks are obtained or released by this function
1671 *
1672 * CAUTIONS
1673 *
1674 * None.
1675 *
1676 * RETURN CODES
1677 *
1678 * Returns != 0 upon successful completion.
1679 */
1680
1681 int ADMINAPI
1682 afsclient_AFSServerGet(const void *cellHandle, const char *serverName,
1683 afs_serverEntry_p serverEntryP, afs_status_p st)
1684 {
1685 int rc = 0;
1686 afs_status_t tst = 0;
1687 void *iter;
1688 int found_match = 0;
1689
1690 if ((serverName == NULL) || (*serverName == 0)) {
1691 tst = ADMUTILSERVERNAMENULL;
1692 goto fail_afsclient_AFSServerGet;
1693 }
1694
1695 if (serverEntryP == NULL) {
1696 tst = ADMUTILSERVERENTRYPNULL;
1697 goto fail_afsclient_AFSServerGet;
1698 }
1699
1700 /*
1701 * Iterate over server entries and try to find a match for serverName
1702 */
1703
1704 if (!afsclient_AFSServerGetBegin(cellHandle, &iter, &tst)) {
1705 goto fail_afsclient_AFSServerGet;
1706 }
1707
1708 while (afsclient_AFSServerGetNext(iter, serverEntryP, &tst)) {
1709 if (!strcmp(serverName, serverEntryP->serverName)) {
1710 found_match = 1;
1711 break;
1712 }
1713 }
1714
1715 /*
1716 * If we didn't find a match, the iterator should have terminated
1717 * normally. If it didn't, return the error
1718 */
1719
1720 if (!found_match) {
1721 if (tst != ADMITERATORDONE) {
1722 afsclient_AFSServerGetDone(iter, 0);
1723 } else {
1724 afsclient_AFSServerGetDone(iter, &tst);
1725 }
1726 tst = ADMCLIENTNOMATCHINGSERVER;
1727 goto fail_afsclient_AFSServerGet;
1728 } else {
1729 if (!afsclient_AFSServerGetDone(iter, &tst)) {
1730 goto fail_afsclient_AFSServerGet;
1731 }
1732 }
1733 rc = 1;
1734
1735 fail_afsclient_AFSServerGet:
1736
1737 if (st != NULL) {
1738 *st = tst;
1739 }
1740 return rc;
1741 }
1742
1743 /*
1744 * The iterator functions and data for the server retrieval functions
1745 */
1746
1747 typedef struct server_get {
1748 int total;
1749 int index;
1750 afs_serverEntry_t server[MAXHOSTSPERCELL + BADSERVERID];
1751 afs_serverEntry_t cache[CACHED_ITEMS];
1752 } server_get_t, *server_get_p;
1753
1754 static int
1755 GetServerRPC(void *rpc_specific, int slot, int *last_item,
1756 int *last_item_contains_data, afs_status_p st)
1757 {
1758 int rc = 0;
1759 afs_status_t tst = 0;
1760 server_get_p serv = (server_get_p) rpc_specific;
1761
1762 memcpy(&serv->cache[slot], &serv->server[serv->index],
1763 sizeof(afs_serverEntry_t));
1764
1765 serv->index++;
1766 if (serv->index == serv->total) {
1767 *last_item = 1;
1768 *last_item_contains_data = 1;
1769 }
1770 rc = 1;
1771
1772 if (st != NULL) {
1773 *st = tst;
1774 }
1775 return rc;
1776 }
1777
1778 static int
1779 GetServerFromCache(void *rpc_specific, int slot, void *dest, afs_status_p st)
1780 {
1781 int rc = 0;
1782 afs_status_t tst = 0;
1783 server_get_p serv = (server_get_p) rpc_specific;
1784
1785 memcpy(dest, (const void *)&serv->cache[slot], sizeof(afs_serverEntry_t));
1786 rc = 1;
1787
1788 if (st != NULL) {
1789 *st = tst;
1790 }
1791 return rc;
1792 }
1793
1794 /*
1795 * afsclient_AFSServerGetBegin - start the process of iterating over
1796 * every server in the cell.
1797 *
1798 * PARAMETERS
1799 *
1800 * IN cellHandle - a cellHandle previously returned by afsclient_CellOpen.
1801 *
1802 * OUT iterationIdP - - upon successful completion contains an iterator
1803 * that can be passed to afsclient_AFSServerGetNext.
1804 *
1805 * LOCKS
1806 *
1807 * No locks are obtained or released by this function
1808 *
1809 * CAUTIONS
1810 *
1811 * None.
1812 *
1813 * RETURN CODES
1814 *
1815 * Returns != 0 upon successful completion.
1816 */
1817
1818 int ADMINAPI
1819 afsclient_AFSServerGetBegin(const void *cellHandle, void **iterationIdP,
1820 afs_status_p st)
1821 {
1822 int rc = 0;
1823 afs_status_t tst = 0;
1824 afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
1825 afs_admin_iterator_p iter = malloc(sizeof(afs_admin_iterator_t));
1826 server_get_p serv = calloc(1, sizeof(server_get_t));
1827 server_get_p serv_cache = NULL;
1828 const char *cellName = NULL;
1829 void *database_iter;
1830 util_databaseServerEntry_t database_entry;
1831 void *fileserver_iter;
1832 vos_fileServerEntry_t fileserver_entry;
1833 int iserv, iservaddr, ientryaddr, is_dup;
1834 struct hostent *host;
1835
1836 if (!CellHandleIsValid(c_handle, &tst)) {
1837 goto fail_afsclient_AFSServerGetBegin;
1838 }
1839
1840 if (iterationIdP == NULL) {
1841 tst = ADMITERATIONIDPNULL;
1842 goto fail_afsclient_AFSServerGetBegin;
1843 }
1844
1845 if ((serv == NULL) || (iter == NULL)) {
1846 tst = ADMNOMEM;
1847 goto fail_afsclient_AFSServerGetBegin;
1848 }
1849
1850 restart:
1851 LOCK_GLOBAL_MUTEX;
1852 if (c_handle->server_list != NULL && c_handle->server_ttl < time(NULL)) {
1853 serv_cache = c_handle->server_list;
1854 c_handle->server_list = NULL;
1855 }
1856 UNLOCK_GLOBAL_MUTEX;
1857
1858 if (c_handle->server_list == NULL) {
1859 if (serv_cache == NULL) {
1860 serv_cache = (server_get_p) calloc(1, sizeof(server_get_t));
1861
1862 if (serv_cache == NULL) {
1863 tst = ADMNOMEM;
1864 goto fail_afsclient_AFSServerGetBegin;
1865 }
1866 }
1867
1868 /*
1869 * Retrieve the list of database servers for this cell.
1870 */
1871
1872 if (!afsclient_CellNameGet(c_handle, &cellName, &tst)) {
1873 goto fail_afsclient_AFSServerGetBegin;
1874 }
1875
1876 if (!util_DatabaseServerGetBegin(cellName, &database_iter, &tst)) {
1877 goto fail_afsclient_AFSServerGetBegin;
1878 }
1879
1880 while (util_DatabaseServerGetNext(database_iter, &database_entry, &tst)) {
1881 serv->server[serv->total].serverAddress[0] =
1882 database_entry.serverAddress;
1883 serv->server[serv->total].serverType = DATABASE_SERVER;
1884 serv->total++;
1885 }
1886
1887 if (tst != ADMITERATORDONE) {
1888 util_DatabaseServerGetDone(database_iter, 0);
1889 goto fail_afsclient_AFSServerGetBegin;
1890 }
1891
1892 if (!util_DatabaseServerGetDone(database_iter, &tst)) {
1893 goto fail_afsclient_AFSServerGetBegin;
1894 }
1895
1896 /*
1897 * Retrieve the list of file servers for this cell.
1898 */
1899
1900 if (!vos_FileServerGetBegin(c_handle, 0, &fileserver_iter, &tst)) {
1901 goto fail_afsclient_AFSServerGetBegin;
1902 }
1903
1904 while (vos_FileServerGetNext(fileserver_iter, &fileserver_entry, &tst)) {
1905 /*
1906 * See if any of the addresses returned in this fileserver_entry
1907 * structure already exist in the list of servers we're building.
1908 * If not, create a new record for this server.
1909 */
1910 is_dup = 0;
1911 for (iserv = 0; iserv < serv->total; iserv++) {
1912 for (ientryaddr = 0; ientryaddr < fileserver_entry.count; ientryaddr++) {
1913 for (iservaddr = 0; iservaddr < AFS_MAX_SERVER_ADDRESS; iservaddr++) {
1914 if (serv->server[iserv].serverAddress[iservaddr] ==
1915 fileserver_entry.serverAddress[ientryaddr]) {
1916 is_dup = 1;
1917 break;
1918 }
1919 }
1920 if (is_dup) {
1921 break;
1922 }
1923 }
1924 if (is_dup) {
1925 break;
1926 }
1927 }
1928
1929 if (is_dup) {
1930 serv->server[iserv].serverType |= FILE_SERVER;
1931 } else {
1932 iserv = serv->total++;
1933 serv->server[iserv].serverType = FILE_SERVER;
1934 }
1935
1936 /*
1937 * Add the addresses from the vldb list to the serv->server[iserv]
1938 * record. Remember that VLDB's list-of-addrs is not guaranteed
1939 * to be unique in a particular entry, or to return only one entry
1940 * per machine--so when we add addresses, always check for
1941 * duplicate entries.
1942 */
1943
1944 for (ientryaddr = 0; ientryaddr < fileserver_entry.count; ientryaddr++) {
1945 for (iservaddr = 0; iservaddr < AFS_MAX_SERVER_ADDRESS; iservaddr++) {
1946 if (serv->server[iserv].serverAddress[iservaddr] ==
1947 fileserver_entry.serverAddress[ientryaddr]) {
1948 break;
1949 }
1950 }
1951 if (iservaddr == AFS_MAX_SERVER_ADDRESS) {
1952 for (iservaddr = 0; iservaddr < AFS_MAX_SERVER_ADDRESS;
1953 iservaddr++) {
1954 if (!serv->server[iserv].serverAddress[iservaddr]) {
1955 serv->server[iserv].serverAddress[iservaddr] =
1956 fileserver_entry.serverAddress[ientryaddr];
1957 break;
1958 }
1959 }
1960 }
1961 }
1962 }
1963
1964 if (tst != ADMITERATORDONE) {
1965 vos_FileServerGetDone(fileserver_iter, 0);
1966 goto fail_afsclient_AFSServerGetBegin;
1967 }
1968
1969 if (!vos_FileServerGetDone(fileserver_iter, &tst)) {
1970 goto fail_afsclient_AFSServerGetBegin;
1971 }
1972
1973 /*
1974 * Iterate over the list and fill in the hostname of each of the servers
1975 */
1976
1977 for (iserv = 0; iserv < serv->total; iserv++) {
1978 int addr = htonl(serv->server[iserv].serverAddress[0]);
1979 LOCK_GLOBAL_MUTEX;
1980 host = gethostbyaddr((const char *)&addr, sizeof(int), AF_INET);
1981 if (host != NULL) {
1982 strncpy(serv->server[iserv].serverName, host->h_name,
1983 AFS_MAX_SERVER_NAME_LEN);
1984 serv->server[iserv].serverName[AFS_MAX_SERVER_NAME_LEN - 1] = '\0';
1985 }
1986 UNLOCK_GLOBAL_MUTEX;
1987 }
1988
1989 memcpy(serv_cache, serv, sizeof(server_get_t));
1990 } else {
1991 int race = 0;
1992 LOCK_GLOBAL_MUTEX;
1993 if (c_handle->server_list == NULL)
1994 race = 1;
1995 else
1996 memcpy(serv, c_handle->server_list, sizeof(server_get_t));
1997 UNLOCK_GLOBAL_MUTEX;
1998 if (race)
1999 goto restart;
2000 }
2001
2002 if (IteratorInit
2003 (iter, (void *)serv, GetServerRPC, GetServerFromCache, NULL, NULL,
2004 &tst)) {
2005 *iterationIdP = (void *)iter;
2006 rc = 1;
2007 }
2008
2009 fail_afsclient_AFSServerGetBegin:
2010
2011 if (rc == 0) {
2012 if (iter != NULL)
2013 free(iter);
2014 if (serv != NULL)
2015 free(serv);
2016 if (serv_cache != NULL)
2017 free(serv_cache);
2018 } else {
2019 if (serv_cache) {
2020 LOCK_GLOBAL_MUTEX;
2021 /* in case there was a race and we constructed the list twice */
2022 if (c_handle->server_list)
2023 free(c_handle->server_list);
2024
2025 c_handle->server_list = serv_cache;
2026 c_handle->server_ttl = time(NULL) + SERVER_TTL;
2027 UNLOCK_GLOBAL_MUTEX;
2028 }
2029 }
2030
2031 if (st != NULL)
2032 *st = tst;
2033
2034 return rc;
2035 }
2036
2037 /*
2038 * afsclient_AFSServerGetNext - retrieve the next server in the cell.
2039 *
2040 * PARAMETERS
2041 *
2042 * IN iterationId - an iterator previously returned by
2043 * afsclient_AFSServerGetBegin.
2044 *
2045 * OUT serverEntryP - upon successful completion contains the next server.
2046 *
2047 * LOCKS
2048 *
2049 * No locks are obtained or released by this function
2050 *
2051 * CAUTIONS
2052 *
2053 * None.
2054 *
2055 * RETURN CODES
2056 *
2057 * Returns != 0 upon successful completion.
2058 */
2059
2060 int ADMINAPI
2061 afsclient_AFSServerGetNext(void *iterationId, afs_serverEntry_p serverEntryP,
2062 afs_status_p st)
2063 {
2064 int rc = 0;
2065 afs_status_t tst = 0;
2066 afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationId;
2067
2068 if (iterationId == NULL) {
2069 tst = ADMITERATORNULL;
2070 goto fail_afsclient_AFSServerGetNext;
2071 }
2072
2073 if (serverEntryP == NULL) {
2074 tst = ADMUTILSERVERENTRYPNULL;
2075 goto fail_afsclient_AFSServerGetNext;
2076 }
2077
2078 rc = IteratorNext(iter, (void *)serverEntryP, &tst);
2079
2080 fail_afsclient_AFSServerGetNext:
2081
2082 if (st != NULL) {
2083 *st = tst;
2084 }
2085 return rc;
2086 }
2087
2088 /*
2089 * afsclient_AFSServerGetDone - finish using a server iterator.
2090 *
2091 * PARAMETERS
2092 *
2093 * IN iterationId - an iterator previously returned by
2094 * afsclient_AFSServerGetBegin.
2095 *
2096 * LOCKS
2097 *
2098 * No locks are obtained or released by this function
2099 *
2100 * CAUTIONS
2101 *
2102 * None.
2103 *
2104 * RETURN CODES
2105 *
2106 * Returns != 0 upon successful completion.
2107 */
2108
2109 int ADMINAPI
2110 afsclient_AFSServerGetDone(void *iterationId, afs_status_p st)
2111 {
2112 int rc = 0;
2113 afs_status_t tst = 0;
2114 afs_admin_iterator_p iter = (afs_admin_iterator_p) iterationId;
2115
2116 if (iterationId == NULL) {
2117 tst = ADMITERATORNULL;
2118 goto fail_afsclient_AFSServerGetDone;
2119 }
2120
2121 rc = IteratorDone(iter, &tst);
2122
2123 fail_afsclient_AFSServerGetDone:
2124
2125 if (st != NULL) {
2126 *st = tst;
2127 }
2128 return rc;
2129 }
2130
2131 /*
2132 * afsclient_RPCStatOpen - open an rx connection to a server to retrieve
2133 * statistics.
2134 *
2135 * PARAMETERS
2136 *
2137 * IN cellHandle - a cellHandle created by afsclient_CellOpen.
2138 *
2139 * IN serverName - the host name where the server resides.
2140 *
2141 * IN type - what type of process to query
2142 *
2143 * OUT rpcStatHandleP - contains an rx connection to the server of interest
2144 *
2145 * LOCKS
2146 *
2147 * No locks are obtained or released by this function
2148 *
2149 * CAUTIONS
2150 *
2151 * None.
2152 *
2153 * RETURN CODES
2154 *
2155 * Returns != 0 upon successful completion.
2156 */
2157
2158 int ADMINAPI
2159 afsclient_RPCStatOpen(const void *cellHandle, const char *serverName,
2160 afs_stat_source_t type,
2161 struct rx_connection **rpcStatHandleP, afs_status_p st)
2162 {
2163 int rc = 0;
2164 afs_status_t tst = 0;
2165 afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
2166 int servAddr = 0;
2167 int servPort;
2168 struct rx_securityClass *sc;
2169
2170 if (!CellHandleIsValid(cellHandle, &tst)) {
2171 goto fail_afsclient_RPCStatOpen;
2172 }
2173
2174 if (!util_AdminServerAddressGetFromName(serverName, &servAddr, &tst)) {
2175 goto fail_afsclient_RPCStatOpen;
2176 }
2177
2178 if (rpcStatHandleP == NULL) {
2179 tst = ADMCLIENTRPCSTATHANDLEPNULL;
2180 goto fail_afsclient_RPCStatOpen;
2181 }
2182
2183 switch (type) {
2184
2185 case AFS_BOSSERVER:
2186 servPort = AFSCONF_NANNYPORT;
2187 break;
2188
2189 case AFS_FILESERVER:
2190 servPort = AFSCONF_FILEPORT;
2191 break;
2192
2193 case AFS_KASERVER:
2194 servPort = AFSCONF_KAUTHPORT;
2195 break;
2196
2197 case AFS_PTSERVER:
2198 servPort = AFSCONF_PROTPORT;
2199 break;
2200
2201 case AFS_VOLSERVER:
2202 servPort = AFSCONF_VOLUMEPORT;
2203 break;
2204
2205 case AFS_VLSERVER:
2206 servPort = AFSCONF_VLDBPORT;
2207 break;
2208
2209 case AFS_CLIENT:
2210 servPort = AFSCONF_CALLBACKPORT;
2211 break;
2212
2213 default:
2214 tst = ADMTYPEINVALID;
2215 goto fail_afsclient_RPCStatOpen;
2216 }
2217
2218 /*
2219 * special processing of tokens by server type
2220 */
2221
2222 if (type == AFS_KASERVER) {
2223 if (!c_handle->tokens->kas_token_set) {
2224 tst = ADMCLIENTNOKASTOKENS;
2225 goto fail_afsclient_RPCStatOpen;
2226 }
2227 sc = c_handle->tokens->kas_sc[c_handle->tokens->sc_index];
2228 } else {
2229 sc = c_handle->tokens->afs_sc[c_handle->tokens->sc_index];
2230 }
2231
2232 *rpcStatHandleP =
2233 rx_GetCachedConnection(htonl(servAddr), htons(servPort),
2234 RX_STATS_SERVICE_ID, sc,
2235 c_handle->tokens->sc_index);
2236
2237 if (*rpcStatHandleP == NULL) {
2238 tst = ADMCLIENTRPCSTATNOCONNECTION;
2239 goto fail_afsclient_RPCStatOpen;
2240 }
2241 rc = 1;
2242
2243 fail_afsclient_RPCStatOpen:
2244
2245 if (st != NULL) {
2246 *st = tst;
2247 }
2248 return rc;
2249 }
2250
2251 /*
2252 * afsclient_RPCStatOpenPort - open an rx connection to a server to retrieve
2253 * statistics.
2254 *
2255 * PARAMETERS
2256 *
2257 * IN cellHandle - a cellHandle created by afsclient_CellOpen.
2258 *
2259 * IN serverName - the host name where the server resides.
2260 *
2261 * IN port - the UDP port number where the server resides.
2262 *
2263 * OUT rpcStatHandleP - contains an rx connection to the server of interest
2264 *
2265 * LOCKS
2266 *
2267 * No locks are obtained or released by this function
2268 *
2269 * CAUTIONS
2270 *
2271 * None.
2272 *
2273 * RETURN CODES
2274 *
2275 * Returns != 0 upon successful completion.
2276 */
2277
2278 int ADMINAPI
2279 afsclient_RPCStatOpenPort(const void *cellHandle, const char *serverName,
2280 const int serverPort,
2281 struct rx_connection **rpcStatHandleP,
2282 afs_status_p st)
2283 {
2284 int rc = 0;
2285 afs_status_t tst = 0;
2286 afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
2287 int servAddr = 0;
2288 struct rx_securityClass *sc;
2289
2290 if (!CellHandleIsValid(cellHandle, &tst)) {
2291 goto fail_afsclient_RPCStatOpenPort;
2292 }
2293
2294 if (!util_AdminServerAddressGetFromName(serverName, &servAddr, &tst)) {
2295 goto fail_afsclient_RPCStatOpenPort;
2296 }
2297
2298 if (rpcStatHandleP == NULL) {
2299 tst = ADMCLIENTRPCSTATHANDLEPNULL;
2300 goto fail_afsclient_RPCStatOpenPort;
2301 }
2302
2303 /*
2304 * special processing of tokens by server type
2305 */
2306
2307 if (serverPort == AFSCONF_KAUTHPORT) {
2308 if (!c_handle->tokens->kas_token_set) {
2309 tst = ADMCLIENTNOKASTOKENS;
2310 goto fail_afsclient_RPCStatOpenPort;
2311 }
2312 sc = c_handle->tokens->kas_sc[c_handle->tokens->sc_index];
2313 } else {
2314 sc = c_handle->tokens->afs_sc[c_handle->tokens->sc_index];
2315 }
2316
2317 *rpcStatHandleP =
2318 rx_GetCachedConnection(htonl(servAddr), htons(serverPort),
2319 RX_STATS_SERVICE_ID, sc,
2320 c_handle->tokens->sc_index);
2321
2322 if (*rpcStatHandleP == NULL) {
2323 tst = ADMCLIENTRPCSTATNOCONNECTION;
2324 goto fail_afsclient_RPCStatOpenPort;
2325 }
2326 rc = 1;
2327
2328 fail_afsclient_RPCStatOpenPort:
2329
2330 if (st != NULL) {
2331 *st = tst;
2332 }
2333 return rc;
2334 }
2335
2336 /*
2337 * afsclient_RPCStatClose - close a previously opened rx connection.
2338 *
2339 * PARAMETERS
2340 *
2341 * IN rpcStatHandle - an rx connection returned by afsclient_RPCStatOpen
2342 *
2343 * LOCKS
2344 *
2345 * No locks are obtained or released by this function
2346 *
2347 * CAUTIONS
2348 *
2349 * None.
2350 *
2351 * RETURN CODES
2352 *
2353 * Returns != 0 upon successful completion.
2354 */
2355
2356 int ADMINAPI
2357 afsclient_RPCStatClose(struct rx_connection *rpcStatHandle, afs_status_p st)
2358 {
2359 int rc = 0;
2360 afs_status_t tst = 0;
2361
2362 if (rpcStatHandle == NULL) {
2363 tst = ADMCLIENTRPCSTATHANDLEPNULL;
2364 goto fail_afsclient_RPCStatClose;
2365 }
2366
2367 rx_ReleaseCachedConnection(rpcStatHandle);
2368 rc = 1;
2369 fail_afsclient_RPCStatClose:
2370
2371 if (st != NULL) {
2372 *st = tst;
2373 }
2374 return rc;
2375 }
2376
2377 /*
2378 * afsclient_CMStatOpen - open an rx connection to a server to retrieve
2379 * statistics.
2380 *
2381 * PARAMETERS
2382 *
2383 * IN cellHandle - a cellHandle created by afsclient_CellOpen.
2384 *
2385 * IN serverName - the host name where the server resides.
2386 *
2387 * OUT cmStatHandleP - contains an rx connection to the server of interest
2388 *
2389 * LOCKS
2390 *
2391 * No locks are obtained or released by this function
2392 *
2393 * CAUTIONS
2394 *
2395 * None.
2396 *
2397 * RETURN CODES
2398 *
2399 * Returns != 0 upon successful completion.
2400 */
2401
2402 int ADMINAPI
2403 afsclient_CMStatOpen(const void *cellHandle, const char *serverName,
2404 struct rx_connection **cmStatHandleP, afs_status_p st)
2405 {
2406 int rc = 0;
2407 afs_status_t tst = 0;
2408 afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
2409 int servAddr = 0;
2410 struct rx_securityClass *sc;
2411
2412 if (!CellHandleIsValid(cellHandle, &tst)) {
2413 goto fail_afsclient_CMStatOpen;
2414 }
2415
2416 if (!util_AdminServerAddressGetFromName(serverName, &servAddr, &tst)) {
2417 goto fail_afsclient_CMStatOpen;
2418 }
2419
2420 if (cmStatHandleP == NULL) {
2421 tst = ADMCLIENTCMSTATHANDLEPNULL;
2422 goto fail_afsclient_CMStatOpen;
2423 }
2424
2425 sc = c_handle->tokens->afs_sc[c_handle->tokens->sc_index];
2426
2427 *cmStatHandleP =
2428 rx_GetCachedConnection(htonl(servAddr), htons(AFSCONF_CALLBACKPORT),
2429 1, sc, c_handle->tokens->sc_index);
2430
2431 if (*cmStatHandleP == NULL) {
2432 tst = ADMCLIENTCMSTATNOCONNECTION;
2433 goto fail_afsclient_CMStatOpen;
2434 }
2435 rc = 1;
2436
2437 fail_afsclient_CMStatOpen:
2438
2439 if (st != NULL) {
2440 *st = tst;
2441 }
2442 return rc;
2443 }
2444
2445 /*
2446 * afsclient_CMStatOpenPort - open an rx connection to a server to retrieve
2447 * statistics.
2448 *
2449 * PARAMETERS
2450 *
2451 * IN cellHandle - a cellHandle created by afsclient_CellOpen.
2452 *
2453 * IN serverName - the host name where the server resides.
2454 *
2455 * IN port - the UDP port number where the server resides.
2456 *
2457 * OUT cmStatHandleP - contains an rx connection to the server of interest
2458 *
2459 * LOCKS
2460 *
2461 * No locks are obtained or released by this function
2462 *
2463 * CAUTIONS
2464 *
2465 * None.
2466 *
2467 * RETURN CODES
2468 *
2469 * Returns != 0 upon successful completion.
2470 */
2471
2472 int ADMINAPI
2473 afsclient_CMStatOpenPort(const void *cellHandle, const char *serverName,
2474 const int serverPort,
2475 struct rx_connection **cmStatHandleP,
2476 afs_status_p st)
2477 {
2478 int rc = 0;
2479 afs_status_t tst = 0;
2480 afs_cell_handle_p c_handle = (afs_cell_handle_p) cellHandle;
2481 int servAddr = 0;
2482 struct rx_securityClass *sc;
2483
2484 if (!CellHandleIsValid(cellHandle, &tst)) {
2485 goto fail_afsclient_CMStatOpenPort;
2486 }
2487
2488 if (!util_AdminServerAddressGetFromName(serverName, &servAddr, &tst)) {
2489 goto fail_afsclient_CMStatOpenPort;
2490 }
2491
2492 if (cmStatHandleP == NULL) {
2493 tst = ADMCLIENTCMSTATHANDLEPNULL;
2494 goto fail_afsclient_CMStatOpenPort;
2495 }
2496
2497 sc = c_handle->tokens->afs_sc[c_handle->tokens->sc_index];
2498
2499 *cmStatHandleP =
2500 rx_GetCachedConnection(htonl(servAddr), htons(serverPort), 1, sc,
2501 c_handle->tokens->sc_index);
2502
2503 if (*cmStatHandleP == NULL) {
2504 tst = ADMCLIENTCMSTATNOCONNECTION;
2505 goto fail_afsclient_CMStatOpenPort;
2506 }
2507 rc = 1;
2508
2509 fail_afsclient_CMStatOpenPort:
2510
2511 if (st != NULL) {
2512 *st = tst;
2513 }
2514 return rc;
2515 }
2516
2517 /*
2518 * afsclient_CMStatClose - close a previously opened rx connection.
2519 *
2520 * PARAMETERS
2521 *
2522 * IN cmStatHandle - an rx connection returned by afsclient_CMStatOpen
2523 *
2524 * LOCKS
2525 *
2526 * No locks are obtained or released by this function
2527 *
2528 * CAUTIONS
2529 *
2530 * None.
2531 *
2532 * RETURN CODES
2533 *
2534 * Returns != 0 upon successful completion.
2535 */
2536
2537 int ADMINAPI
2538 afsclient_CMStatClose(struct rx_connection *cmStatHandle, afs_status_p st)
2539 {
2540 int rc = 0;
2541 afs_status_t tst = 0;
2542
2543 if (cmStatHandle == NULL) {
2544 tst = ADMCLIENTCMSTATHANDLEPNULL;
2545 goto fail_afsclient_CMStatClose;
2546 }
2547
2548 rx_ReleaseCachedConnection(cmStatHandle);
2549 rc = 1;
2550 fail_afsclient_CMStatClose:
2551
2552 if (st != NULL) {
2553 *st = tst;
2554 }
2555 return rc;
2556 }
2557
2558 /*
2559 * afsclient_RXDebugOpen - open an rxdebug handle to a server.
2560 *
2561 * PARAMETERS
2562 *
2563 * IN serverName - the host name where the server resides.
2564 *
2565 * IN type - what type of process to query
2566 *
2567 * OUT rxdebugHandle_p - contains an rxdebug handle for the server of interest
2568 *
2569 * LOCKS
2570 *
2571 * No locks are obtained or released by this function
2572 *
2573 * CAUTIONS
2574 *
2575 * None.
2576 *
2577 * RETURN CODES
2578 *
2579 * Returns != 0 upon successful completion.
2580 */
2581
2582 int ADMINAPI
2583 afsclient_RXDebugOpen(const char *serverName, afs_stat_source_t type,
2584 rxdebugHandle_p * rxdebugHandleP, afs_status_p st)
2585 {
2586 int rc = 0;
2587 afs_status_t tst = 0;
2588 int code;
2589 rxdebugHandle_p handle;
2590 rxdebugSocket_t sock;
2591 struct sockaddr_in taddr;
2592 int serverPort;
2593 int serverAddr;
2594
2595 if (rxdebugHandleP == NULL) {
2596 tst = ADMCLIENTRXDEBUGHANDLEPNULL;
2597 goto fail_afsclient_RXDebugOpen;
2598 }
2599
2600 switch (type) {
2601
2602 case AFS_BOSSERVER:
2603 serverPort = AFSCONF_NANNYPORT;
2604 break;
2605
2606 case AFS_FILESERVER:
2607 serverPort = AFSCONF_FILEPORT;
2608 break;
2609
2610 case AFS_KASERVER:
2611 serverPort = AFSCONF_KAUTHPORT;
2612 break;
2613
2614 case AFS_PTSERVER:
2615 serverPort = AFSCONF_PROTPORT;
2616 break;
2617
2618 case AFS_VOLSERVER:
2619 serverPort = AFSCONF_VOLUMEPORT;
2620 break;
2621
2622 case AFS_VLSERVER:
2623 serverPort = AFSCONF_VLDBPORT;
2624 break;
2625
2626 case AFS_CLIENT:
2627 serverPort = AFSCONF_CALLBACKPORT;
2628 break;
2629
2630 default:
2631 tst = ADMTYPEINVALID;
2632 goto fail_afsclient_RXDebugOpen;
2633 }
2634
2635 if (!util_AdminServerAddressGetFromName(serverName, &serverAddr, &tst)) {
2636 goto fail_afsclient_RXDebugOpen;
2637 }
2638
2639 sock = (rxdebugSocket_t) socket(AF_INET, SOCK_DGRAM, 0);
2640 if (sock == INVALID_RXDEBUG_SOCKET) {
2641 tst = ADMSOCKFAIL;
2642 goto fail_afsclient_RXDebugOpen;
2643 }
2644
2645 memset(&taddr, 0, sizeof(taddr));
2646 taddr.sin_family = AF_INET;
2647 taddr.sin_port = 0;
2648 taddr.sin_addr.s_addr = INADDR_ANY;
2649 code = bind(sock, (struct sockaddr *)&taddr, sizeof(taddr));
2650 if (code) {
2651 close(sock);
2652 tst = ADMSOCKFAIL;
2653 goto fail_afsclient_RXDebugOpen;
2654 }
2655
2656 handle = malloc(sizeof(rxdebugHandle_t));
2657 if (!handle) {
2658 close(sock);
2659 tst = ADMNOMEM;
2660 goto fail_afsclient_RXDebugOpen;
2661 }
2662
2663 handle->sock = sock;
2664 handle->ipAddr = serverAddr;
2665 handle->udpPort = serverPort;
2666 handle->firstFlag = 1;
2667 handle->supportedStats = 0;
2668 *rxdebugHandleP = handle;
2669 rc = 1;
2670
2671 fail_afsclient_RXDebugOpen:
2672
2673 if (st != NULL) {
2674 *st = tst;
2675 }
2676 return rc;
2677 }
2678
2679 /*
2680 * afsclient_RXDebugOpenPort - open an rxdebug handle to a server.
2681 *
2682 * PARAMETERS
2683 *
2684 * IN serverName - the host name where the server resides.
2685 *
2686 * IN port - the UDP port number where the server resides.
2687 *
2688 * OUT rxdebugHandle_p - contains an rxdebug handle for the server of interest
2689 *
2690 * LOCKS
2691 *
2692 * No locks are obtained or released by this function
2693 *
2694 * CAUTIONS
2695 *
2696 * None.
2697 *
2698 * RETURN CODES
2699 *
2700 * Returns != 0 upon successful completion.
2701 */
2702
2703 int ADMINAPI
2704 afsclient_RXDebugOpenPort(const char *serverName, int serverPort,
2705 rxdebugHandle_p * rxdebugHandleP, afs_status_p st)
2706 {
2707 int rc = 0;
2708 afs_status_t tst = 0;
2709 int code;
2710 rxdebugHandle_p handle;
2711 rxdebugSocket_t sock;
2712 struct sockaddr_in taddr;
2713 int serverAddr;
2714
2715 if (rxdebugHandleP == NULL) {
2716 tst = ADMCLIENTRXDEBUGHANDLEPNULL;
2717 goto fail_afsclient_RXDebugOpenPort;
2718 }
2719
2720 if (!util_AdminServerAddressGetFromName(serverName, &serverAddr, &tst)) {
2721 goto fail_afsclient_RXDebugOpenPort;
2722 }
2723
2724 sock = (rxdebugSocket_t) socket(AF_INET, SOCK_DGRAM, 0);
2725 if (sock == INVALID_RXDEBUG_SOCKET) {
2726 tst = ADMSOCKFAIL;
2727 goto fail_afsclient_RXDebugOpenPort;
2728 }
2729
2730 memset(&taddr, 0, sizeof(taddr));
2731 taddr.sin_family = AF_INET;
2732 taddr.sin_port = 0;
2733 taddr.sin_addr.s_addr = INADDR_ANY;
2734 code = bind(sock, (struct sockaddr *)&taddr, sizeof(taddr));
2735 if (code) {
2736 close(sock);
2737 tst = ADMSOCKFAIL;
2738 goto fail_afsclient_RXDebugOpenPort;
2739 }
2740
2741 handle = malloc(sizeof(rxdebugHandle_t));
2742 if (!handle) {
2743 close(sock);
2744 tst = ADMNOMEM;
2745 goto fail_afsclient_RXDebugOpenPort;
2746 }
2747
2748 handle->sock = sock;
2749 handle->ipAddr = serverAddr;
2750 handle->udpPort = serverPort;
2751 handle->firstFlag = 1;
2752 handle->supportedStats = 0;
2753 *rxdebugHandleP = handle;
2754 rc = 1;
2755
2756 fail_afsclient_RXDebugOpenPort:
2757
2758 if (st != NULL) {
2759 *st = tst;
2760 }
2761 return rc;
2762 }
2763
2764 /*
2765 * afsclient_RXDebugClose - close a previously opened rxdebug handle.
2766 *
2767 * PARAMETERS
2768 *
2769 * IN rxdebugHandle - an rxdebug handle returned by afsclient_RXDebugOpen
2770 *
2771 * LOCKS
2772 *
2773 * No locks are obtained or released by this function
2774 *
2775 * CAUTIONS
2776 *
2777 * None.
2778 *
2779 * RETURN CODES
2780 *
2781 * Returns != 0 upon successful completion.
2782 */
2783
2784 int ADMINAPI
2785 afsclient_RXDebugClose(rxdebugHandle_p rxdebugHandle, afs_status_p st)
2786 {
2787 int rc = 0;
2788 afs_status_t tst = 0;
2789
2790 if (rxdebugHandle == NULL) {
2791 tst = ADMCLIENTRXDEBUGHANDLEPNULL;
2792 goto fail_afsclient_RXDebugClose;
2793 }
2794
2795 close(rxdebugHandle->sock);
2796 free(rxdebugHandle);
2797 rc = 1;
2798 fail_afsclient_RXDebugClose:
2799
2800 if (st != NULL) {
2801 *st = tst;
2802 }
2803 return rc;
2804 }