Make typedefs of AFS_UCRED and AFS_PROC with renaming
[openafs.git] / src / libadmin / test / client.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 /*
11  * This file implements the client related funtions for afscp
12  */
13
14 #include <afsconfig.h>
15 #include <afs/param.h>
16
17
18 #include "client.h"
19 #include <afs/cellconfig.h>
20 #include <afs/bosint.h>
21 #include <rx/rxstat.h>
22 #include <afs/afsint.h>
23 #define FSINT_COMMON_XG
24 #include <afs/afscbint.h>
25 #include <afs/kauth.h>
26 #include <afs/kautils.h>
27 #include <afs/ptint.h>
28 #include <afs/ptserver.h>
29 #include <afs/vldbint.h>
30 #include <afs/volint.h>
31 #include <afs/volser.h>
32 #include <ubik.h>
33 #include <ubik_int.h>
34 #ifdef AFS_NT40_ENV
35 #include <winsock2.h>
36 #include <pthread.h>
37 #endif
38
39 /*
40  * This structure stores the client and server function lists.
41  * This is kept separate from the actual interface definitions
42  * since an rpc interface can be offered by several servers
43  * (e.g. ubik and rxstat)
44  *
45  * The purpose of these functions is to allow a mapping from interfaceId
46  * to text representations of server process names and function names.
47  */
48
49 typedef struct {
50     const char **functionList;
51     size_t functionListLen;
52 } interface_function_list_t, *interface_function_list_p;
53
54 #ifdef AFS_NT40_ENV
55
56 /*
57  * On NT, you cannot define an array of character pointers in a dll
58  * and then access this array outside the dll via a global initialization
59  * because the msvc compiler will complain that the initializer is not
60  * a constant (i.e. C2099: initializer is not a constant).  This is because
61  * the dllimport and dllexport c language extensions cause references
62  * to the character array to go through another level of indirection -
63  * and this indirection is unknown at compilation time.
64  *
65  * To get around this problem I hand initialize this array on NT only
66  */
67
68 static interface_function_list_t afs_server;
69 static interface_function_list_t afscb_server;
70 static interface_function_list_t bos_server;
71 static interface_function_list_t kauth_kaa_server;
72 static interface_function_list_t kauth_kam_server;
73 static interface_function_list_t kauth_kat_server;
74 static interface_function_list_t pts_server;
75 static interface_function_list_t rxstat_server;
76 static interface_function_list_t ubik_disk_server;
77 static interface_function_list_t ubik_vote_server;
78 static interface_function_list_t vl_server;
79 static interface_function_list_t vol_server;
80 static pthread_once_t pthread_func_list_once = PTHREAD_ONCE_INIT;
81 static int pthread_func_list_done;
82
83 static void
84 cr_list(void)
85 {
86     afs_server.functionList = RXAFS_function_names;
87     afs_server.functionListLen = RXAFS_NO_OF_STAT_FUNCS;
88     afscb_server.functionList = RXAFSCB_function_names;
89     afscb_server.functionListLen = RXAFSCB_NO_OF_STAT_FUNCS;
90     bos_server.functionList = BOZO_function_names;
91     bos_server.functionListLen = BOZO_NO_OF_STAT_FUNCS;
92     kauth_kaa_server.functionList = KAA_function_names;
93     kauth_kaa_server.functionListLen = KAA_NO_OF_STAT_FUNCS;
94     kauth_kam_server.functionList = KAM_function_names;
95     kauth_kam_server.functionListLen = KAM_NO_OF_STAT_FUNCS;
96     kauth_kat_server.functionList = KAT_function_names;
97     kauth_kat_server.functionListLen = KAT_NO_OF_STAT_FUNCS;
98     pts_server.functionList = PR_function_names;
99     pts_server.functionListLen = PR_NO_OF_STAT_FUNCS;
100     rxstat_server.functionList = RXSTATS_function_names;
101     rxstat_server.functionListLen = RXSTATS_NO_OF_STAT_FUNCS;
102     ubik_disk_server.functionList = DISK_function_names;
103     ubik_disk_server.functionListLen = DISK_NO_OF_STAT_FUNCS;
104     ubik_vote_server.functionList = VOTE_function_names;
105     ubik_vote_server.functionListLen = VOTE_NO_OF_STAT_FUNCS;
106     vl_server.functionList = VL_function_names;
107     vl_server.functionListLen = VL_NO_OF_STAT_FUNCS;
108     vol_server.functionList = AFSVolfunction_names;
109     vol_server.functionListLen = AFSVolNO_OF_STAT_FUNCS;
110     pthread_func_list_done = 1;
111 }
112
113 #else
114
115 static interface_function_list_t afs_server = {
116     RXAFS_function_names,
117     RXAFS_NO_OF_STAT_FUNCS
118 };
119
120 static interface_function_list_t afscb_server = {
121     RXAFSCB_function_names,
122     RXAFSCB_NO_OF_STAT_FUNCS
123 };
124
125 static interface_function_list_t bos_server = {
126     BOZO_function_names,
127     BOZO_NO_OF_STAT_FUNCS
128 };
129
130 static interface_function_list_t kauth_kaa_server = {
131     KAA_function_names,
132     KAA_NO_OF_STAT_FUNCS
133 };
134
135 static interface_function_list_t kauth_kam_server = {
136     KAM_function_names,
137     KAM_NO_OF_STAT_FUNCS
138 };
139
140 static interface_function_list_t kauth_kat_server = {
141     KAT_function_names,
142     KAT_NO_OF_STAT_FUNCS
143 };
144
145 static interface_function_list_t pts_server = {
146     PR_function_names,
147     PR_NO_OF_STAT_FUNCS
148 };
149
150 static interface_function_list_t rxstat_server = {
151     RXSTATS_function_names,
152     RXSTATS_NO_OF_STAT_FUNCS
153 };
154
155 static interface_function_list_t ubik_disk_server = {
156     DISK_function_names,
157     DISK_NO_OF_STAT_FUNCS,
158 };
159
160 static interface_function_list_t ubik_vote_server = {
161     VOTE_function_names,
162     VOTE_NO_OF_STAT_FUNCS,
163 };
164
165 static interface_function_list_t vl_server = {
166     VL_function_names,
167     VL_NO_OF_STAT_FUNCS
168 };
169
170 static interface_function_list_t vol_server = {
171     AFSVolfunction_names,
172     AFSVolNO_OF_STAT_FUNCS
173 };
174
175 #endif /* AFS_NT40_ENV */
176
177 static interface_function_list_t unknown_server = {
178     0,
179     0
180 };
181
182 typedef struct {
183     afs_uint32 interfaceId;
184     const char *interfaceName;
185     interface_function_list_p functionList;
186 } interface_t, *interface_p;
187
188 interface_t int_list[] = {
189     {RXAFS_STATINDEX,
190      "file server",
191      &afs_server},
192
193     {RXSTATS_STATINDEX,
194      "rx stats",
195      &rxstat_server},
196
197     {RXAFSCB_STATINDEX,
198      "cache manager",
199      &afscb_server},
200
201     {PR_STATINDEX,
202      "pts server",
203      &pts_server},
204
205     {DISK_STATINDEX,
206      "ubik disk server",
207      &ubik_disk_server},
208
209     {VOTE_STATINDEX,
210      "ubik vote server",
211      &ubik_vote_server},
212
213     {VL_STATINDEX,
214      "vldb server",
215      &vl_server},
216
217     {AFSVolSTATINDEX,
218      "vol server",
219      &vol_server},
220
221     {BOZO_STATINDEX,
222      "bos server",
223      &bos_server},
224
225     {KAA_STATINDEX,
226      "kas kaa server",
227      &kauth_kaa_server},
228
229     {KAM_STATINDEX,
230      "kas kam server",
231      &kauth_kam_server},
232
233     {KAT_STATINDEX,
234      "kas kat server",
235      &kauth_kat_server},
236
237     /*
238      * Note the code below assumes that the following entry is the last entry
239      * in this array
240      */
241
242     {0, "unknown", &unknown_server}
243 };
244
245 /*
246  * Utility functions
247  */
248
249 int
250 DoClientLocalCellGet(struct cmd_syndesc *as, void *arock)
251 {
252     afs_status_t st = 0;
253     char cellName[MAXCELLCHARS];
254
255     if (!afsclient_LocalCellGet(cellName, &st)) {
256         ERR_ST_EXT("afsclient_LocalCellGet", st);
257     }
258
259     printf("This machine belongs to cell: %s\n", cellName);
260
261     return 0;
262 }
263
264 int
265 DoClientMountPointCreate(struct cmd_syndesc *as, void *arock)
266 {
267     typedef enum { DIRECTORY, VOLUME, READWRITE,
268         CHECK
269     } DoClientMountPointCreate_parm_t;
270     afs_status_t st = 0;
271     const char *directory = NULL;
272     const char *volume = NULL;
273     vol_type_t vol_type = READ_ONLY;
274     vol_check_t vol_check = DONT_CHECK_VOLUME;
275
276     if (as->parms[DIRECTORY].items) {
277         directory = as->parms[DIRECTORY].items->data;
278     }
279
280     if (as->parms[VOLUME].items) {
281         volume = as->parms[VOLUME].items->data;
282     }
283
284     if (as->parms[READWRITE].items) {
285         vol_type = READ_WRITE;
286     }
287
288     if (as->parms[CHECK].items) {
289         vol_check = CHECK_VOLUME;
290     }
291
292     if (!afsclient_MountPointCreate
293         (cellHandle, directory, volume, vol_type, vol_check, &st)) {
294         ERR_ST_EXT("afsclient_MountPointCreate", st);
295     }
296
297     return 0;
298 }
299
300 static void
301 Print_afs_serverEntry_p(afs_serverEntry_p serv, const char *prefix)
302 {
303     int i = 0;
304
305     printf("%sInformation for server %s\n", prefix, serv->serverName);
306     if (serv->serverType & DATABASE_SERVER) {
307         printf("%s\tIt is a database server\n", prefix);
308     }
309     if (serv->serverType & FILE_SERVER) {
310         printf("%s\tIt is a file server\n", prefix);
311     }
312     printf("%s\tServer addresses:%s\n", prefix, serv->serverName);
313     while (serv->serverAddress[i] != 0) {
314         printf("\t\t%s%x\n", prefix, serv->serverAddress[i++]);
315     }
316 }
317
318 int
319 DoClientAFSServerGet(struct cmd_syndesc *as, void *arock)
320 {
321     typedef enum { SERVER } DoClientAFSServerGet_parm_t;
322     afs_status_t st = 0;
323     const char *server = NULL;
324     afs_serverEntry_t entry;
325
326     if (as->parms[SERVER].items) {
327         server = as->parms[SERVER].items->data;
328     }
329
330     if (!afsclient_AFSServerGet(cellHandle, server, &entry, &st)) {
331         ERR_ST_EXT("afsclient_AFSServerGet", st);
332     }
333
334     Print_afs_serverEntry_p(&entry, "");
335
336     return 0;
337 }
338
339 int
340 DoClientAFSServerList(struct cmd_syndesc *as, void *arock)
341 {
342     afs_status_t st = 0;
343     afs_serverEntry_t entry;
344     void *iter = NULL;
345
346     if (!afsclient_AFSServerGetBegin(cellHandle, &iter, &st)) {
347         ERR_ST_EXT("afsclient_AFSServerGetBegin", st);
348     }
349
350     while (afsclient_AFSServerGetNext(iter, &entry, &st)) {
351         Print_afs_serverEntry_p(&entry, "");
352     }
353
354     if (st != ADMITERATORDONE) {
355         ERR_ST_EXT("afsclient_AFSServerGetNext", st);
356     }
357
358     if (!afsclient_AFSServerGetDone(iter, &st)) {
359         ERR_ST_EXT("afsclient_AFSServerGetDone", st);
360     }
361
362
363     return 0;
364 }
365
366 static void
367 Print_afs_RPCStatsState_p(afs_RPCStatsState_p state, const char *prefix)
368 {
369     printf("%sThe rpc stats state is: ", prefix);
370     switch (*state) {
371     case AFS_RPC_STATS_DISABLED:
372         printf("disabled\n");
373         break;
374     case AFS_RPC_STATS_ENABLED:
375         printf("enabled\n");
376         break;
377     }
378 }
379
380 typedef struct {
381     const char *tag;
382     afs_stat_source_t value;
383 } afs_type_map_t, *afs_type_map_p;
384
385 static afs_type_map_t map[] = {
386     {"bosserver", AFS_BOSSERVER},
387     {"fileserver", AFS_FILESERVER},
388     {"kaserver", AFS_KASERVER},
389     {"ptserver", AFS_PTSERVER},
390     {"volserver", AFS_VOLSERVER},
391     {"vlserver", AFS_VLSERVER},
392     {"client", AFS_CLIENT},
393     {0, 0}
394 };
395
396 static int
397 GetStatPortFromString(const char *type, int *port)
398 {
399     char *end;
400     long tport;
401
402     errno = 0;
403     tport = strtol(type, &end, 0);
404     if (tport == 0 || end == type || *end != '\0') {
405         return 0;
406     }
407
408     *port = (int)tport;
409     return 1;
410 }
411
412 static int
413 GetStatSourceFromString(const char *type, afs_stat_source_t * src, int *port)
414 {
415     int i;
416     size_t type_len = strlen(type);
417
418     for (i = 0; (map[i].tag) && strncasecmp(type, map[i].tag, type_len); i++);
419
420     if (map[i].tag == 0) {
421         /*
422          * Try to convert string to port number
423          */
424         if (GetStatPortFromString(type, port)) {
425             return 0;
426         }
427
428         fprintf(stderr,
429                 "couldn't convert server to type, try one of the "
430                 "following:\n");
431         for (i = 0; map[i].tag; i++) {
432             fprintf(stderr, "%s ", map[i].tag);
433         }
434
435         ERR_EXT("");
436     } else {
437         *src = map[i].value;
438         return 1;
439     }
440 }
441
442 typedef enum {
443     AFS_PEER_STATS,
444     afs_proc_tESS_STATS
445 } afs_stat_type_t, *afs_stat_type_p;
446
447 static afs_stat_type_t
448 GetStatTypeFromString(const char *type)
449 {
450     afs_stat_type_t rc;
451
452     if (!strcmp(type, "peer")) {
453         rc = AFS_PEER_STATS;
454     } else if (!strcmp(type, "process")) {
455         rc = afs_proc_tESS_STATS;
456     } else {
457         ERR_EXT("stat_type must be process or peer");
458     }
459
460     return rc;
461 }
462
463 int
464 DoClientRPCStatsStateGet(struct cmd_syndesc *as, void *arock)
465 {
466     typedef enum { SERVER, PROCESS,
467         STAT_TYPE
468     } DoClientRPCStatsStateGet_parm_t;
469     afs_status_t st = 0;
470     struct rx_connection *conn;
471     afs_stat_source_t type;
472     int srvrPort;
473     int typeIsValid = 0;
474     afs_stat_type_t which = 0;
475     afs_RPCStatsState_t state;
476
477     if (as->parms[PROCESS].items) {
478         typeIsValid =
479             GetStatSourceFromString(as->parms[PROCESS].items->data, &type,
480                                     &srvrPort);
481     }
482
483     if (as->parms[STAT_TYPE].items) {
484         which = GetStatTypeFromString(as->parms[STAT_TYPE].items->data);
485     }
486
487     if (as->parms[SERVER].items) {
488         if (typeIsValid) {
489             if (!afsclient_RPCStatOpen
490                 (cellHandle, as->parms[SERVER].items->data, type, &conn,
491                  &st)) {
492                 ERR_ST_EXT("afsclient_RPCStatOpen", st);
493             }
494         } else {
495             if (!afsclient_RPCStatOpenPort
496                 (cellHandle, as->parms[SERVER].items->data, srvrPort, &conn,
497                  &st)) {
498                 ERR_ST_EXT("afsclient_RPCStatOpenPort", st);
499             }
500         }
501     }
502
503     if (which == AFS_PEER_STATS) {
504         if (!util_RPCStatsStateGet
505             (conn, RXSTATS_QueryPeerRPCStats, &state, &st)) {
506             ERR_ST_EXT("util_RPCStatsStateGet", st);
507         }
508     } else {
509         if (!util_RPCStatsStateGet
510             (conn, RXSTATS_QueryProcessRPCStats, &state, &st)) {
511             ERR_ST_EXT("util_RPCStatsStateGet", st);
512         }
513     }
514
515     Print_afs_RPCStatsState_p(&state, "");
516
517     afsclient_RPCStatClose(conn, 0);
518
519     return 0;
520 }
521
522 int
523 DoClientRPCStatsStateEnable(struct cmd_syndesc *as, void *arock)
524 {
525     typedef enum { SERVER, PROCESS, STAT_TYPE } DoClientRPCStatsEnable_parm_t;
526     afs_status_t st = 0;
527     struct rx_connection *conn;
528     afs_stat_source_t type;
529     int srvrPort;
530     int typeIsValid = 0;
531     afs_stat_type_t which = 0;
532
533     if (as->parms[PROCESS].items) {
534         typeIsValid =
535             GetStatSourceFromString(as->parms[PROCESS].items->data, &type,
536                                     &srvrPort);
537     }
538
539     if (as->parms[STAT_TYPE].items) {
540         which = GetStatTypeFromString(as->parms[STAT_TYPE].items->data);
541     }
542
543     if (as->parms[SERVER].items) {
544         if (typeIsValid) {
545             if (!afsclient_RPCStatOpen
546                 (cellHandle, as->parms[SERVER].items->data, type, &conn,
547                  &st)) {
548                 ERR_ST_EXT("afsclient_RPCStatOpen", st);
549             }
550         } else {
551             if (!afsclient_RPCStatOpenPort
552                 (cellHandle, as->parms[SERVER].items->data, srvrPort, &conn,
553                  &st)) {
554                 ERR_ST_EXT("afsclient_RPCStatOpenPort", st);
555             }
556         }
557     }
558
559     if (which == AFS_PEER_STATS) {
560         if (!util_RPCStatsStateEnable(conn, RXSTATS_EnablePeerRPCStats, &st)) {
561             ERR_ST_EXT("util_RPCStatsStateEnable", st);
562         }
563     } else {
564         if (!util_RPCStatsStateEnable
565             (conn, RXSTATS_EnableProcessRPCStats, &st)) {
566             ERR_ST_EXT("util_RPCStatsStateEnable", st);
567         }
568     }
569
570     afsclient_RPCStatClose(conn, 0);
571
572     return 0;
573 }
574
575 int
576 DoClientRPCStatsStateDisable(struct cmd_syndesc *as, void *arock)
577 {
578     typedef enum { SERVER, PROCESS,
579         STAT_TYPE
580     } DoClientRPCStatsDisable_parm_t;
581     afs_status_t st = 0;
582     struct rx_connection *conn;
583     afs_stat_source_t type;
584     int srvrPort;
585     int typeIsValid = 0;
586     afs_stat_type_t which = 0;
587
588     if (as->parms[PROCESS].items) {
589         typeIsValid =
590             GetStatSourceFromString(as->parms[PROCESS].items->data, &type,
591                                     &srvrPort);
592     }
593
594     if (as->parms[STAT_TYPE].items) {
595         which = GetStatTypeFromString(as->parms[STAT_TYPE].items->data);
596     }
597
598     if (as->parms[SERVER].items) {
599         if (typeIsValid) {
600             if (!afsclient_RPCStatOpen
601                 (cellHandle, as->parms[SERVER].items->data, type, &conn,
602                  &st)) {
603                 ERR_ST_EXT("afsclient_RPCStatOpen", st);
604             }
605         } else {
606             if (!afsclient_RPCStatOpenPort
607                 (cellHandle, as->parms[SERVER].items->data, srvrPort, &conn,
608                  &st)) {
609                 ERR_ST_EXT("afsclient_RPCStatOpenPort", st);
610             }
611         }
612     }
613
614     if (which == AFS_PEER_STATS) {
615         if (!util_RPCStatsStateDisable
616             (conn, RXSTATS_DisablePeerRPCStats, &st)) {
617             ERR_ST_EXT("util_RPCStatsStateDisable", st);
618         }
619     } else {
620         if (!util_RPCStatsStateDisable
621             (conn, RXSTATS_DisableProcessRPCStats, &st)) {
622             ERR_ST_EXT("util_RPCStatsStateDisable", st);
623         }
624     }
625
626     afsclient_RPCStatClose(conn, 0);
627
628     return 0;
629 }
630
631 static void
632 Print_afs_RPCStats_p(afs_RPCStats_p stat, interface_function_list_p f_list,
633                      const char *prefix)
634 {
635     afs_int32 index = stat->s.stats_v1.func_index;
636
637     if (index > ((afs_int32) f_list->functionListLen - 1)) {
638         printf("%sUnknown function ", prefix);
639     } else {
640         printf("%s%s ", prefix,
641                f_list->functionList[stat->s.stats_v1.func_index]);
642     }
643
644     if (!hiszero(stat->s.stats_v1.invocations)) {
645         printf("%sinvoc (%u.%u) bytes_sent (%u.%u) bytes_rcvd (%u.%u)\n",
646                prefix, hgethi(stat->s.stats_v1.invocations),
647                hgetlo(stat->s.stats_v1.invocations),
648                hgethi(stat->s.stats_v1.bytes_sent),
649                hgetlo(stat->s.stats_v1.bytes_sent),
650                hgethi(stat->s.stats_v1.bytes_rcvd),
651                hgetlo(stat->s.stats_v1.bytes_rcvd)
652             );
653         printf("\tqsum %d.%06d\tqsqr %d.%06d"
654                "\tqmin %d.%06d\tqmax %d.%06d\n",
655                stat->s.stats_v1.queue_time_sum.sec,
656                stat->s.stats_v1.queue_time_sum.usec,
657                stat->s.stats_v1.queue_time_sum_sqr.sec,
658                stat->s.stats_v1.queue_time_sum_sqr.usec,
659                stat->s.stats_v1.queue_time_min.sec,
660                stat->s.stats_v1.queue_time_min.usec,
661                stat->s.stats_v1.queue_time_max.sec,
662                stat->s.stats_v1.queue_time_max.usec);
663         printf("\txsum %d.%06d\txsqr %d.%06d"
664                "\txmin %d.%06d\txmax %d.%06d\n",
665                stat->s.stats_v1.execution_time_sum.sec,
666                stat->s.stats_v1.execution_time_sum.usec,
667                stat->s.stats_v1.execution_time_sum_sqr.sec,
668                stat->s.stats_v1.execution_time_sum_sqr.usec,
669                stat->s.stats_v1.execution_time_min.sec,
670                stat->s.stats_v1.execution_time_min.usec,
671                stat->s.stats_v1.execution_time_max.sec,
672                stat->s.stats_v1.execution_time_max.usec);
673     } else {
674         printf("never invoked\n");
675     }
676 }
677
678 int
679 DoClientRPCStatsList(struct cmd_syndesc *as, void *arock)
680 {
681     typedef enum { SERVER, PROCESS, STAT_TYPE } DoClientRPCStatsList_parm_t;
682     afs_status_t st = 0;
683     struct rx_connection *conn;
684     afs_stat_source_t type;
685     int srvrPort;
686     int typeIsValid = 0;
687     afs_stat_type_t which = 0;
688     afs_RPCStats_t stats;
689     void *iter;
690     int i = 0;
691
692 #ifdef AFS_NT40_ENV
693     (pthread_func_list_done
694      || pthread_once(&pthread_func_list_once, cr_list));
695 #endif
696
697     if (as->parms[PROCESS].items) {
698         typeIsValid =
699             GetStatSourceFromString(as->parms[PROCESS].items->data, &type,
700                                     &srvrPort);
701     }
702
703     if (as->parms[STAT_TYPE].items) {
704         which = GetStatTypeFromString(as->parms[STAT_TYPE].items->data);
705     }
706
707     if (as->parms[SERVER].items) {
708         if (typeIsValid) {
709             if (!afsclient_RPCStatOpen
710                 (cellHandle, as->parms[SERVER].items->data, type, &conn,
711                  &st)) {
712                 ERR_ST_EXT("afsclient_RPCStatOpen", st);
713             }
714         } else {
715             if (!afsclient_RPCStatOpenPort
716                 (cellHandle, as->parms[SERVER].items->data, srvrPort, &conn,
717                  &st)) {
718                 ERR_ST_EXT("afsclient_RPCStatOpenPort", st);
719             }
720         }
721     }
722
723     if (which == AFS_PEER_STATS) {
724         if (!util_RPCStatsGetBegin
725             (conn, RXSTATS_RetrievePeerRPCStats, &iter, &st)) {
726             ERR_ST_EXT("util_RPCStatsGetBegin", st);
727         }
728     } else {
729         if (!util_RPCStatsGetBegin
730             (conn, RXSTATS_RetrieveProcessRPCStats, &iter, &st)) {
731             ERR_ST_EXT("util_RPCStatsGetBegin", st);
732         }
733     }
734
735     printf("Listing rpc stats at server %s process %s:\n",
736            as->parms[SERVER].items->data, as->parms[PROCESS].items->data);
737
738     while (util_RPCStatsGetNext(iter, &stats, &st)) {
739
740         /*
741          * Print a new heading for each stat collection
742          */
743
744         if (stats.s.stats_v1.func_index == 0) {
745
746             printf("\n\n");
747
748             /*
749              * Look up the interface in our list
750              */
751
752             for (i = 0; i < ((sizeof(int_list) - 1) / sizeof(interface_t));
753                  i++) {
754                 if (stats.s.stats_v1.interfaceId == int_list[i].interfaceId) {
755                     break;
756                 }
757             }
758
759             /*
760              * Print out a meaningful header for each stat collection
761              */
762
763             if (which == AFS_PEER_STATS) {
764                 struct in_addr ina;
765                 ina.s_addr = htonl(stats.s.stats_v1.remote_peer);
766
767                 printf("%s stats for remote peer located at %s port %u "
768                        "%s %s as a %s via the %s interface\n",
769                        as->parms[PROCESS].items->data, inet_ntoa(ina),
770                        stats.s.stats_v1.remote_port,
771                        ((stats.s.stats_v1.
772                          remote_is_server) ? "accessed by" : "accessing"),
773                        as->parms[PROCESS].items->data,
774                        ((stats.s.stats_v1.
775                          remote_is_server) ? "client" : "server"),
776                        int_list[i].interfaceName);
777             } else {
778                 printf("%s stats for the %s interface " "accessed as a %s\n",
779                        as->parms[PROCESS].items->data,
780                        int_list[i].interfaceName,
781                        ((stats.s.stats_v1.
782                          remote_is_server) ? "client" : "server")
783                     );
784             }
785         }
786         Print_afs_RPCStats_p(&stats, int_list[i].functionList, "    ");
787     }
788
789     if (st != ADMITERATORDONE) {
790         ERR_ST_EXT("util_RPCStatsGetNext", st);
791     }
792
793     if (!util_RPCStatsGetDone(iter, &st)) {
794         ERR_ST_EXT("util_RPCStatsGetDone", st);
795     }
796
797     afsclient_RPCStatClose(conn, 0);
798
799     return 0;
800 }
801
802 int
803 DoClientRPCStatsClear(struct cmd_syndesc *as, void *arock)
804 {
805     typedef enum { SERVER, PROCESS, STAT_TYPE, CLEAR_ALL, CLEAR_INVOCATIONS,
806         CLEAR_BYTES_SENT, CLEAR_BYTES_RCVD,
807         CLEAR_QUEUE_TIME_SUM, CLEAR_QUEUE_TIME_SQUARE,
808         CLEAR_QUEUE_TIME_MIN, CLEAR_QUEUE_TIME_MAX,
809         CLEAR_EXEC_TIME_SUM, CLEAR_EXEC_TIME_SQUARE,
810         CLEAR_EXEC_TIME_MIN, CLEAR_EXEC_TIME_MAX
811     } DoClientRPCStatsClear_parm_t;
812     afs_status_t st = 0;
813     struct rx_connection *conn;
814     afs_stat_source_t type;
815     int srvrPort;
816     int typeIsValid = 0;
817     afs_stat_type_t which = 0;
818     afs_RPCStatsClearFlag_t flag = 0;
819     int seen_all = 0;
820     int seen_any = 0;
821
822     if (as->parms[PROCESS].items) {
823         typeIsValid =
824             GetStatSourceFromString(as->parms[PROCESS].items->data, &type,
825                                     &srvrPort);
826     }
827
828     if (as->parms[STAT_TYPE].items) {
829         which = GetStatTypeFromString(as->parms[STAT_TYPE].items->data);
830     }
831
832     if (as->parms[SERVER].items) {
833         if (typeIsValid) {
834             if (!afsclient_RPCStatOpen
835                 (cellHandle, as->parms[SERVER].items->data, type, &conn,
836                  &st)) {
837                 ERR_ST_EXT("afsclient_RPCStatOpen", st);
838             }
839         } else {
840             if (!afsclient_RPCStatOpenPort
841                 (cellHandle, as->parms[SERVER].items->data, srvrPort, &conn,
842                  &st)) {
843                 ERR_ST_EXT("afsclient_RPCStatOpenPort", st);
844             }
845         }
846     }
847
848     if (as->parms[CLEAR_ALL].items) {
849         seen_all = 1;
850         seen_any = 1;
851         flag = AFS_RX_STATS_CLEAR_ALL;
852     }
853
854     if (as->parms[CLEAR_INVOCATIONS].items) {
855         if (seen_all) {
856             ERR_EXT("cannot specify additional flags when "
857                     "specifying clear_all");
858         }
859         seen_any = 1;
860         flag |= AFS_RX_STATS_CLEAR_INVOCATIONS;
861     }
862
863     if (as->parms[CLEAR_BYTES_SENT].items) {
864         if (seen_all) {
865             ERR_EXT("cannot specify additional flags when "
866                     "specifying clear_all");
867         }
868         seen_any = 1;
869         flag |= AFS_RX_STATS_CLEAR_BYTES_SENT;
870     }
871
872     if (as->parms[CLEAR_BYTES_RCVD].items) {
873         if (seen_all) {
874             ERR_EXT("cannot specify additional flags when "
875                     "specifying clear_all");
876         }
877         seen_any = 1;
878         flag |= AFS_RX_STATS_CLEAR_BYTES_RCVD;
879     }
880
881     if (as->parms[CLEAR_QUEUE_TIME_SUM].items) {
882         if (seen_all) {
883             ERR_EXT("cannot specify additional flags when "
884                     "specifying clear_all");
885         }
886         seen_any = 1;
887         flag |= AFS_RX_STATS_CLEAR_QUEUE_TIME_SUM;
888     }
889
890     if (as->parms[CLEAR_QUEUE_TIME_SQUARE].items) {
891         if (seen_all) {
892             ERR_EXT("cannot specify additional flags when "
893                     "specifying clear_all");
894         }
895         seen_any = 1;
896         flag |= AFS_RX_STATS_CLEAR_QUEUE_TIME_SQUARE;
897     }
898
899     if (as->parms[CLEAR_QUEUE_TIME_MIN].items) {
900         if (seen_all) {
901             ERR_EXT("cannot specify additional flags when "
902                     "specifying clear_all");
903         }
904         seen_any = 1;
905         flag |= AFS_RX_STATS_CLEAR_QUEUE_TIME_MIN;
906     }
907
908     if (as->parms[CLEAR_QUEUE_TIME_MAX].items) {
909         if (seen_all) {
910             ERR_EXT("cannot specify additional flags when "
911                     "specifying clear_all");
912         }
913         seen_any = 1;
914         flag |= AFS_RX_STATS_CLEAR_QUEUE_TIME_MAX;
915     }
916
917     if (as->parms[CLEAR_EXEC_TIME_SUM].items) {
918         if (seen_all) {
919             ERR_EXT("cannot specify additional flags when "
920                     "specifying clear_all");
921         }
922         seen_any = 1;
923         flag |= AFS_RX_STATS_CLEAR_EXEC_TIME_SUM;
924     }
925
926     if (as->parms[CLEAR_EXEC_TIME_SQUARE].items) {
927         if (seen_all) {
928             ERR_EXT("cannot specify additional flags when "
929                     "specifying clear_all");
930         }
931         seen_any = 1;
932         flag |= AFS_RX_STATS_CLEAR_EXEC_TIME_SQUARE;
933     }
934
935     if (as->parms[CLEAR_EXEC_TIME_MIN].items) {
936         if (seen_all) {
937             ERR_EXT("cannot specify additional flags when "
938                     "specifying clear_all");
939         }
940         seen_any = 1;
941         flag |= AFS_RX_STATS_CLEAR_EXEC_TIME_MIN;
942     }
943
944     if (as->parms[CLEAR_EXEC_TIME_MAX].items) {
945         if (seen_all) {
946             ERR_EXT("cannot specify additional flags when "
947                     "specifying clear_all");
948         }
949         seen_any = 1;
950         flag |= AFS_RX_STATS_CLEAR_EXEC_TIME_MAX;
951     }
952
953     if (!seen_any) {
954         ERR_EXT("you must specify something to clear");
955     }
956
957     if (which == AFS_PEER_STATS) {
958         if (!util_RPCStatsClear(conn, RXSTATS_ClearPeerRPCStats, flag, &st)) {
959             ERR_ST_EXT("util_RPCStatsClear", st);
960         }
961     } else {
962         if (!util_RPCStatsClear
963             (conn, RXSTATS_ClearProcessRPCStats, flag, &st)) {
964             ERR_ST_EXT("util_RPCStatsClear", st);
965         }
966     }
967
968     afsclient_RPCStatClose(conn, 0);
969
970     return 0;
971 }
972
973 int
974 DoClientRPCStatsVersionGet(struct cmd_syndesc *as, void *arock)
975 {
976     typedef enum { SERVER, PROCESS } DoClientRPCStatsVersionGet_parm_t;
977     afs_status_t st = 0;
978     struct rx_connection *conn;
979     afs_stat_source_t type;
980     int srvrPort;
981     int typeIsValid = 0;
982     afs_RPCStatsVersion_t version;
983
984     if (as->parms[PROCESS].items) {
985         typeIsValid =
986             GetStatSourceFromString(as->parms[PROCESS].items->data, &type,
987                                     &srvrPort);
988     }
989
990     if (as->parms[SERVER].items) {
991         if (typeIsValid) {
992             if (!afsclient_RPCStatOpen
993                 (cellHandle, as->parms[SERVER].items->data, type, &conn,
994                  &st)) {
995                 ERR_ST_EXT("afsclient_RPCStatOpen", st);
996             }
997         } else {
998             if (!afsclient_RPCStatOpenPort
999                 (cellHandle, as->parms[SERVER].items->data, srvrPort, &conn,
1000                  &st)) {
1001                 ERR_ST_EXT("afsclient_RPCStatOpenPort", st);
1002             }
1003         }
1004     }
1005
1006     if (!util_RPCStatsVersionGet(conn, &version, &st)) {
1007         ERR_ST_EXT("util_RPCStatsVersionGet", st);
1008     }
1009
1010     printf("the rpc stat version number is %u\n", version);
1011
1012     afsclient_RPCStatClose(conn, 0);
1013
1014     return 0;
1015 }
1016
1017 static void
1018 Print_afs_CMServerPref_p(afs_CMServerPref_p pref)
1019 {
1020     afs_uint32 taddr;
1021
1022     taddr = pref->ipAddr;
1023     printf("%d.%d.%d.%d\t\t\t%d\n", (taddr >> 24) & 0xff,
1024            (taddr >> 16) & 0xff, (taddr >> 8) & 0xff, taddr & 0xff,
1025            pref->ipRank);
1026 }
1027
1028 int
1029 DoClientCMGetServerPrefs(struct cmd_syndesc *as, void *arock)
1030 {
1031     afs_status_t st = 0;
1032     typedef enum { SERVER, PORT } DoClientCMGetServerPrefs_parm_t;
1033     struct rx_connection *conn;
1034     int srvrPort = AFSCONF_CALLBACKPORT;
1035     afs_CMServerPref_t prefs;
1036     void *iter;
1037
1038 #ifdef AFS_NT40_ENV
1039     (pthread_func_list_done
1040      || pthread_once(&pthread_func_list_once, cr_list));
1041 #endif
1042
1043     if (as->parms[PORT].items) {
1044         if (!GetStatPortFromString(as->parms[PORT].items->data, &srvrPort)) {
1045             ERR_EXT("Couldn't undertand port number");
1046         }
1047     }
1048
1049     if (as->parms[SERVER].items) {
1050         if (!afsclient_CMStatOpenPort
1051             (cellHandle, as->parms[SERVER].items->data, srvrPort, &conn,
1052              &st)) {
1053             ERR_ST_EXT("afsclient_CMStatOpenPort", st);
1054         }
1055     }
1056
1057     if (!util_CMGetServerPrefsBegin(conn, &iter, &st)) {
1058         ERR_ST_EXT("util_CMGetServerPrefsBegin", st);
1059     }
1060
1061     printf("Listing CellServDB for %s at port %s:\n",
1062            as->parms[SERVER].items->data, as->parms[PORT].items->data);
1063
1064     while (util_CMGetServerPrefsNext(iter, &prefs, &st)) {
1065
1066         Print_afs_CMServerPref_p(&prefs);
1067     }
1068
1069     if (st != ADMITERATORDONE) {
1070         ERR_ST_EXT("util_CMGetServerPrefsNext", st);
1071     }
1072
1073     if (!util_CMGetServerPrefsDone(iter, &st)) {
1074         ERR_ST_EXT("util_CMGetServerPrefsDone", st);
1075     }
1076
1077     afsclient_CMStatClose(conn, 0);
1078
1079     return 0;
1080 }
1081
1082 static void
1083 Print_afs_CMListCell_p(afs_CMListCell_p cellInfo)
1084 {
1085     int i;
1086     afs_uint32 taddr;
1087
1088     printf("Cell %s on hosts", cellInfo->cellname);
1089     for (i = 0; i < UTIL_MAX_CELL_HOSTS && cellInfo->serverAddr[i]; i++) {
1090         taddr = cellInfo->serverAddr[i];
1091         printf(" %d.%d.%d.%d", (taddr >> 24) & 0xff, (taddr >> 16) & 0xff,
1092                (taddr >> 8) & 0xff, taddr & 0xff);
1093     }
1094     printf("\n");
1095 }
1096
1097 int
1098 DoClientCMListCells(struct cmd_syndesc *as, void *arock)
1099 {
1100     afs_status_t st = 0;
1101     typedef enum { SERVER, PORT } DoClientCMListCells_parm_t;
1102     struct rx_connection *conn;
1103     int srvrPort = AFSCONF_CALLBACKPORT;
1104     afs_CMListCell_t cellInfo;
1105     void *iter;
1106
1107 #ifdef AFS_NT40_ENV
1108     (pthread_func_list_done
1109      || pthread_once(&pthread_func_list_once, cr_list));
1110 #endif
1111
1112     if (as->parms[PORT].items) {
1113         if (!GetStatPortFromString(as->parms[PORT].items->data, &srvrPort)) {
1114             ERR_EXT("Couldn't undertand port number");
1115         }
1116     }
1117
1118     if (as->parms[SERVER].items) {
1119         if (!afsclient_CMStatOpenPort
1120             (cellHandle, as->parms[SERVER].items->data, srvrPort, &conn,
1121              &st)) {
1122             ERR_ST_EXT("afsclient_CMStatOpenPort", st);
1123         }
1124     }
1125
1126     if (!util_CMListCellsBegin(conn, &iter, &st)) {
1127         ERR_ST_EXT("util_CMListCellsBegin", st);
1128     }
1129
1130     printf("Listing CellServDB for %s at port %s:\n",
1131            as->parms[SERVER].items->data, as->parms[PORT].items->data);
1132
1133     while (util_CMListCellsNext(iter, &cellInfo, &st)) {
1134
1135         Print_afs_CMListCell_p(&cellInfo);
1136     }
1137
1138     if (st != ADMITERATORDONE) {
1139         ERR_ST_EXT("util_CMListCellsNext", st);
1140     }
1141
1142     if (!util_CMListCellsDone(iter, &st)) {
1143         ERR_ST_EXT("util_CMListCellsDone", st);
1144     }
1145
1146     afsclient_CMStatClose(conn, 0);
1147
1148     return 0;
1149 }
1150
1151 int
1152 DoClientCMLocalCell(struct cmd_syndesc *as, void *arock)
1153 {
1154     afs_status_t st = 0;
1155     typedef enum { SERVER, PORT } DoClientCMLocalCell_parm_t;
1156     struct rx_connection *conn;
1157     int srvrPort = AFSCONF_CALLBACKPORT;
1158     afs_CMCellName_t cellname;
1159
1160 #ifdef AFS_NT40_ENV
1161     (pthread_func_list_done
1162      || pthread_once(&pthread_func_list_once, cr_list));
1163 #endif
1164
1165     if (as->parms[PORT].items) {
1166         if (!GetStatPortFromString(as->parms[PORT].items->data, &srvrPort)) {
1167             ERR_EXT("Couldn't undertand port number");
1168         }
1169     }
1170
1171     if (as->parms[SERVER].items) {
1172         if (!afsclient_CMStatOpenPort
1173             (cellHandle, as->parms[SERVER].items->data, srvrPort, &conn,
1174              &st)) {
1175             ERR_ST_EXT("afsclient_CMStatOpenPort", st);
1176         }
1177     }
1178
1179     if (!util_CMLocalCell(conn, cellname, &st)) {
1180         ERR_ST_EXT("util_CMLocalCell", st);
1181     }
1182
1183     printf("Client %s (port %s) is in cell %s\n",
1184            as->parms[SERVER].items->data, as->parms[PORT].items->data,
1185            cellname);
1186
1187     afsclient_CMStatClose(conn, 0);
1188
1189     return 0;
1190 }
1191
1192 static void
1193 Print_afs_ClientConfig_p(afs_ClientConfig_p config)
1194 {
1195     printf("    clientVersion:  %d\n", config->clientVersion);
1196     printf("    serverVersion:  %d\n", config->serverVersion);
1197     printf("    nChunkFiles:    %d\n", config->c.config_v1.nChunkFiles);
1198     printf("    nStatCaches:    %d\n", config->c.config_v1.nStatCaches);
1199     printf("    nDataCaches:    %d\n", config->c.config_v1.nDataCaches);
1200     printf("    nVolumeCaches:  %d\n", config->c.config_v1.nVolumeCaches);
1201     printf("    firstChunkSize: %d\n", config->c.config_v1.firstChunkSize);
1202     printf("    otherChunkSize: %d\n", config->c.config_v1.otherChunkSize);
1203     printf("    cacheSize:      %d\n", config->c.config_v1.cacheSize);
1204     printf("    setTime:        %d\n", config->c.config_v1.setTime);
1205     printf("    memCache:       %d\n", config->c.config_v1.memCache);
1206
1207 }
1208
1209 int
1210 DoClientCMClientConfig(struct cmd_syndesc *as, void *arock)
1211 {
1212     afs_status_t st = 0;
1213     typedef enum { SERVER, PORT } DoClientCMLocalCell_parm_t;
1214     struct rx_connection *conn;
1215     int srvrPort = AFSCONF_CALLBACKPORT;
1216     afs_ClientConfig_t config;
1217
1218 #ifdef AFS_NT40_ENV
1219     (pthread_func_list_done
1220      || pthread_once(&pthread_func_list_once, cr_list));
1221 #endif
1222
1223     if (as->parms[PORT].items) {
1224         if (!GetStatPortFromString(as->parms[PORT].items->data, &srvrPort)) {
1225             ERR_EXT("Couldn't undertand port number");
1226         }
1227     }
1228
1229     if (as->parms[SERVER].items) {
1230         if (!afsclient_CMStatOpenPort
1231             (cellHandle, as->parms[SERVER].items->data, srvrPort, &conn,
1232              &st)) {
1233             ERR_ST_EXT("afsclient_CMStatOpenPort", st);
1234         }
1235     }
1236
1237     if (!util_CMClientConfig(conn, &config, &st)) {
1238         ERR_ST_EXT("util_CMClientConfig", st);
1239     }
1240
1241     printf("Cache configuration for client %s (port %s):\n\n",
1242            as->parms[SERVER].items->data, as->parms[PORT].items->data);
1243
1244     Print_afs_ClientConfig_p(&config);
1245
1246     printf("\n");
1247
1248     afsclient_CMStatClose(conn, 0);
1249
1250     return 0;
1251 }
1252
1253 void
1254 SetupClientAdminCmd(void)
1255 {
1256     struct cmd_syndesc *ts;
1257
1258     ts = cmd_CreateSyntax("ClientLocalCellGet", DoClientLocalCellGet, NULL,
1259                           "get the name of this machine's cell");
1260     SetupCommonCmdArgs(ts);
1261
1262     ts = cmd_CreateSyntax("ClientMountPointCreate", DoClientMountPointCreate,
1263                           NULL, "create a mount point");
1264     cmd_AddParm(ts, "-directory", CMD_SINGLE, CMD_REQUIRED,
1265                 "directory where mount point will be created");
1266     cmd_AddParm(ts, "-volume", CMD_SINGLE, CMD_REQUIRED,
1267                 "the name of the volume to mount");
1268     cmd_AddParm(ts, "-readwrite", CMD_FLAG, CMD_OPTIONAL,
1269                 "mount a read write volume");
1270     cmd_AddParm(ts, "-check", CMD_FLAG, CMD_OPTIONAL,
1271                 "check that the volume exists before mounting");
1272     SetupCommonCmdArgs(ts);
1273
1274     ts = cmd_CreateSyntax("ClientAFSServerGet", DoClientAFSServerGet, NULL,
1275                           "retrieve information about an afs server");
1276     cmd_AddParm(ts, "-server", CMD_SINGLE, CMD_REQUIRED, "server to query");
1277     SetupCommonCmdArgs(ts);
1278
1279     ts = cmd_CreateSyntax("ClientAFSServerList", DoClientAFSServerList, NULL,
1280                           "retrieve information about all afs "
1281                           "servers in a cell");
1282     cmd_AddParm(ts, "-server", CMD_SINGLE, CMD_REQUIRED,
1283                 "server where command will execute");
1284     cmd_AddParm(ts, "-process", CMD_SINGLE, CMD_REQUIRED,
1285                 "process to query <bosserver fileserver ptserver "
1286                 "kaserver client vlserver volserver>");
1287     cmd_AddParm(ts, "-stat_type", CMD_SINGLE, CMD_REQUIRED,
1288                 "stats to retrieve <peer or process>");
1289     SetupCommonCmdArgs(ts);
1290
1291     ts = cmd_CreateSyntax("ClientRPCStatsStateGet", DoClientRPCStatsStateGet,
1292                           NULL, "retrieve the rpc stat collection state");
1293     cmd_AddParm(ts, "-server", CMD_SINGLE, CMD_REQUIRED,
1294                 "server where command will execute");
1295     cmd_AddParm(ts, "-process", CMD_SINGLE, CMD_REQUIRED,
1296                 "process to query <bosserver fileserver ptserver "
1297                 "kaserver client vlserver volserver>");
1298     cmd_AddParm(ts, "-stat_type", CMD_SINGLE, CMD_REQUIRED,
1299                 "stats to retrieve <peer or process>");
1300     SetupCommonCmdArgs(ts);
1301
1302     ts = cmd_CreateSyntax("ClientRPCStatsStateEnable",
1303                           DoClientRPCStatsStateEnable, NULL,
1304                           "set the rpc stat collection state to on");
1305     cmd_AddParm(ts, "-server", CMD_SINGLE, CMD_REQUIRED,
1306                 "server where command will execute");
1307     cmd_AddParm(ts, "-process", CMD_SINGLE, CMD_REQUIRED,
1308                 "process to query <bosserver fileserver ptserver "
1309                 "kaserver client vlserver volserver>");
1310     cmd_AddParm(ts, "-stat_type", CMD_SINGLE, CMD_REQUIRED,
1311                 "stats to retrieve <peer or process>");
1312     SetupCommonCmdArgs(ts);
1313
1314     ts = cmd_CreateSyntax("ClientRPCStatsStateDisable",
1315                           DoClientRPCStatsStateDisable, NULL,
1316                           "set the rpc stat collection state to off");
1317     cmd_AddParm(ts, "-server", CMD_SINGLE, CMD_REQUIRED,
1318                 "server where command will execute");
1319     cmd_AddParm(ts, "-process", CMD_SINGLE, CMD_REQUIRED,
1320                 "process to query <bosserver fileserver ptserver "
1321                 "kaserver client vlserver volserver>");
1322     cmd_AddParm(ts, "-stat_type", CMD_SINGLE, CMD_REQUIRED,
1323                 "stats to retrieve <peer or process>");
1324     SetupCommonCmdArgs(ts);
1325
1326     ts = cmd_CreateSyntax("ClientRPCStatsList", DoClientRPCStatsList, NULL,
1327                           "list the rpc stats");
1328     cmd_AddParm(ts, "-server", CMD_SINGLE, CMD_REQUIRED,
1329                 "server where command will execute");
1330     cmd_AddParm(ts, "-process", CMD_SINGLE, CMD_REQUIRED,
1331                 "process to query <bosserver fileserver ptserver "
1332                 "kaserver client vlserver volserver>");
1333     cmd_AddParm(ts, "-stat_type", CMD_SINGLE, CMD_REQUIRED,
1334                 "stats to retrieve <peer or process>");
1335     SetupCommonCmdArgs(ts);
1336
1337     ts = cmd_CreateSyntax("ClientRPCStatsClear", DoClientRPCStatsClear, NULL,
1338                           "reset rpc stat counters");
1339     cmd_AddParm(ts, "-server", CMD_SINGLE, CMD_REQUIRED,
1340                 "server where command will execute");
1341     cmd_AddParm(ts, "-process", CMD_SINGLE, CMD_REQUIRED,
1342                 "process to query <bosserver fileserver ptserver "
1343                 "kaserver client vlserver volserver>");
1344     cmd_AddParm(ts, "-stat_type", CMD_SINGLE, CMD_REQUIRED,
1345                 "stats to retrieve <peer or process>");
1346     cmd_AddParm(ts, "-clear_all", CMD_FLAG, CMD_OPTIONAL,
1347                 "clear all existing counters");
1348     cmd_AddParm(ts, "-clear_invocations", CMD_FLAG, CMD_OPTIONAL,
1349                 "clear invocation count");
1350     cmd_AddParm(ts, "-clear_bytes_sent", CMD_FLAG, CMD_OPTIONAL,
1351                 "clear bytes_sent count");
1352     cmd_AddParm(ts, "-clear_bytes_rcvd", CMD_FLAG, CMD_OPTIONAL,
1353                 "clear bytes_rcvd count");
1354     cmd_AddParm(ts, "-clear_queue_time_sum", CMD_FLAG, CMD_OPTIONAL,
1355                 "clear queue time sum");
1356     cmd_AddParm(ts, "-clear_queue_time_square", CMD_FLAG, CMD_OPTIONAL,
1357                 "clear queue time square");
1358     cmd_AddParm(ts, "-clear_queue_time_min", CMD_FLAG, CMD_OPTIONAL,
1359                 "clear queue time min");
1360     cmd_AddParm(ts, "-clear_queue_time_max", CMD_FLAG, CMD_OPTIONAL,
1361                 "clear queue time max");
1362     cmd_AddParm(ts, "-clear_exec_time_sum", CMD_FLAG, CMD_OPTIONAL,
1363                 "clear exec time sum");
1364     cmd_AddParm(ts, "-clear_exec_time_square", CMD_FLAG, CMD_OPTIONAL,
1365                 "clear exec time square");
1366     cmd_AddParm(ts, "-clear_exec_time_min", CMD_FLAG, CMD_OPTIONAL,
1367                 "clear exec time min");
1368     cmd_AddParm(ts, "-clear_exec_time_max", CMD_FLAG, CMD_OPTIONAL,
1369                 "clear exec time max");
1370     SetupCommonCmdArgs(ts);
1371
1372     ts = cmd_CreateSyntax("ClientRPCStatsVersionGet",
1373                           DoClientRPCStatsVersionGet, NULL,
1374                           "list the server's rpc stats version");
1375     cmd_AddParm(ts, "-server", CMD_SINGLE, CMD_REQUIRED,
1376                 "server where command will execute");
1377     cmd_AddParm(ts, "-process", CMD_SINGLE, CMD_REQUIRED,
1378                 "process to query <bosserver fileserver ptserver "
1379                 "kaserver client vlserver volserver>");
1380     SetupCommonCmdArgs(ts);
1381
1382     ts = cmd_CreateSyntax("ClientCMGetServerPrefs", DoClientCMGetServerPrefs,
1383                           NULL, "list a client's server preferences ");
1384     cmd_AddParm(ts, "-server", CMD_SINGLE, CMD_REQUIRED,
1385                 "server where command will execute");
1386     cmd_AddParm(ts, "-port", CMD_SINGLE, CMD_OPTIONAL, "UDP port to query");
1387     SetupCommonCmdArgs(ts);
1388
1389     ts = cmd_CreateSyntax("ClientCMListCells", DoClientCMListCells, NULL,
1390                           "list a client's CellServDB ");
1391     cmd_AddParm(ts, "-server", CMD_SINGLE, CMD_REQUIRED,
1392                 "server where command will execute");
1393     cmd_AddParm(ts, "-port", CMD_SINGLE, CMD_OPTIONAL, "UDP port to query");
1394     SetupCommonCmdArgs(ts);
1395
1396     ts = cmd_CreateSyntax("ClientCMLocalCell", DoClientCMLocalCell, NULL,
1397                           "get the name of the client's local cell");
1398     cmd_AddParm(ts, "-server", CMD_SINGLE, CMD_REQUIRED,
1399                 "server where command will execute");
1400     cmd_AddParm(ts, "-port", CMD_SINGLE, CMD_OPTIONAL, "UDP port to query");
1401     SetupCommonCmdArgs(ts);
1402
1403     ts = cmd_CreateSyntax("ClientCMClientConfig", DoClientCMClientConfig, NULL,
1404                           "get the client's cache configuration");
1405     cmd_AddParm(ts, "-server", CMD_SINGLE, CMD_REQUIRED,
1406                 "server where command will execute");
1407     cmd_AddParm(ts, "-port", CMD_SINGLE, CMD_OPTIONAL, "UDP port to query");
1408     SetupCommonCmdArgs(ts);
1409 }