2 * Copyright 2000, International Business Machines Corporation and others.
5 * This software has been released under the terms of the IBM Public
6 * License. For details, see the LICENSE file in the top-level source
7 * directory or online at http://www.openafs.org/dl/license10.html
10 #include <afsconfig.h>
11 #include <afs/param.h>
16 #include <sys/types.h>
21 #include <sys/socket.h>
25 #ifdef HAVE_NETINET_IN_H
26 #include <netinet/in.h>
28 #ifdef HAVE_SYS_TIME_H
51 #include "rx_globals.h"
56 extern struct hostent *hostutil_GetHostByName();
66 while (tc = *aport++) {
67 if (tc < '0' || tc > '9')
68 return -1; /* bad port number */
70 total += tc - (int)'0';
79 register struct servent *ts;
80 ts = getservbyname(aname, NULL);
83 return ts->s_port; /* returns it in network byte order */
87 MainCommand(as, arock)
89 struct cmd_syndesc *as;
94 struct sockaddr_in taddr;
96 struct in_addr hostAddr;
99 register afs_int32 code;
103 int onlyClient, onlyServer;
115 struct rx_debugStats tstats;
116 char *portName, *hostName;
117 struct rx_debugConn tconn;
122 afs_int32 length = 64;
124 afs_uint32 supportedDebugValues = 0;
125 afs_uint32 supportedStatValues = 0;
126 afs_uint32 supportedConnValues = 0;
127 afs_uint32 supportedPeerValues = 0;
128 afs_int32 nextconn = 0;
129 afs_int32 nextpeer = 0;
131 nodally = (as->parms[2].items ? 1 : 0);
132 allconns = (as->parms[3].items ? 1 : 0);
133 rxstats = (as->parms[4].items ? 1 : 0);
134 onlyServer = (as->parms[5].items ? 1 : 0);
135 onlyClient = (as->parms[6].items ? 1 : 0);
136 version_flag = (as->parms[10].items ? 1 : 0);
137 noConns = (as->parms[11].items ? 1 : 0);
138 showPeers = (as->parms[12].items ? 1 : 0);
140 if (as->parms[0].items)
141 hostName = as->parms[0].items->data;
145 if (as->parms[1].items)
146 portName = as->parms[1].items->data;
150 if (as->parms[7].items) {
151 char *name = as->parms[7].items->data;
152 if ((onlyPort = PortNumber(name)) == -1)
153 onlyPort = PortName(name);
154 if (onlyPort == -1) {
155 printf("rxdebug: can't resolve port name %s\n", name);
161 if (as->parms[8].items) {
162 char *name = as->parms[8].items->data;
164 th = hostutil_GetHostByName(name);
166 printf("rxdebug: host %s not found in host table\n", name);
169 memcpy(&onlyHost, th->h_addr, sizeof(afs_int32));
173 if (as->parms[9].items) {
174 char *name = as->parms[9].items->data;
175 if (strcmp(name, "clear") == 0)
177 else if (strcmp(name, "auth") == 0)
179 else if (strcmp(name, "crypt") == 0)
181 else if ((strcmp(name, "null") == 0) || (strcmp(name, "none") == 0)
182 || (strncmp(name, "noauth", 6) == 0)
183 || (strncmp(name, "unauth", 6) == 0))
186 fprintf(stderr, "Unknown authentication level: %s\n", name);
194 th = hostutil_GetHostByName(hostName);
196 printf("rxdebug: host %s not found in host table\n", hostName);
199 memcpy(&host, th->h_addr, sizeof(afs_int32));
201 host = htonl(0x7f000001); /* IP localhost */
204 port = htons(7000); /* default is fileserver */
206 if ((port = PortNumber(portName)) == -1)
207 port = PortName(portName);
209 printf("rxdebug: can't resolve port name %s\n", portName);
216 hostAddr.s_addr = host;
217 printf("Trying %s (port %d):\n", inet_ntoa(hostAddr), ntohs(port));
218 s = socket(AF_INET, SOCK_DGRAM, 0);
219 taddr.sin_family = AF_INET;
221 taddr.sin_addr.s_addr = 0;
222 #ifdef STRUCT_SOCKADDR_HAS_SA_LEN
223 taddr.sin_len = sizeof(struct sockaddr_in);
225 code = bind(s, (struct sockaddr *)&taddr, sizeof(struct sockaddr_in));
233 code = rx_GetServerVersion(s, host, port, length, version);
235 printf("get version call failed with code %d, errno %d\n", code,
239 printf("AFS version: %s\n", version);
247 code = rx_GetServerDebug(s, host, port, &tstats, &supportedDebugValues);
249 printf("getstats call failed with code %d\n", code);
253 withSecStats = (supportedDebugValues & RX_SERVER_DEBUG_SEC_STATS);
254 withAllConn = (supportedDebugValues & RX_SERVER_DEBUG_ALL_CONN);
255 withRxStats = (supportedDebugValues & RX_SERVER_DEBUG_RX_STATS);
256 withWaiters = (supportedDebugValues & RX_SERVER_DEBUG_WAITER_CNT);
257 withIdleThreads = (supportedDebugValues & RX_SERVER_DEBUG_IDLE_THREADS);
258 withPeers = (supportedDebugValues & RX_SERVER_DEBUG_ALL_PEER);
260 printf("Free packets: %d, packet reclaims: %d, calls: %d, used FDs: %d\n",
261 tstats.nFreePackets, tstats.packetReclaims, tstats.callsExecuted,
263 if (!tstats.waitingForPackets)
265 printf("waiting for packets.\n");
267 printf("%d calls waiting for a thread\n", tstats.nWaiting);
269 printf("%d threads are idle\n", tstats.idleThreads);
276 "WARNING: Server doesn't support retrieval of Rx statistics\n");
278 struct rx_stats rxstats;
280 /* should gracefully handle the case where rx_stats grows */
282 rx_GetServerStats(s, host, port, &rxstats,
283 &supportedStatValues);
285 printf("rxstats call failed with code %d\n", code);
288 if (code != sizeof(rxstats)) {
289 if ((((struct rx_debugIn *)(&rxstats))->type ==
293 ("WARNING: returned Rx statistics of unexpected size (got %d)\n",
295 /* handle other versions?... */
298 rx_PrintTheseStats(stdout, &rxstats, sizeof(rxstats),
299 tstats.nFreePackets, tstats.version);
307 "WARNING: Server doesn't support retrieval of all connections,\n getting only interesting instead.\n");
311 printf("Showing only server connections\n");
313 printf("Showing only client connections\n");
314 if (onlyAuth != 999) {
315 static char *name[] =
316 { "unauthenticated", "rxkad_clear", "rxkad_auth",
319 printf("Showing only %s connections\n", name[onlyAuth + 1]);
321 if (onlyHost != -1) {
322 hostAddr.s_addr = onlyHost;
323 printf("Showing only connections from host %s\n",
324 inet_ntoa(hostAddr));
327 printf("Showing only connections on port %u\n", ntohs(onlyPort));
331 rx_GetServerConnections(s, host, port, &nextconn, allconns,
332 supportedDebugValues, &tconn,
333 &supportedConnValues);
335 printf("getconn call failed with code %d\n", code);
338 if (tconn.cid == (afs_int32)0xffffffff) {
343 /* see if we're in nodally mode and all calls are dallying */
346 for (j = 0; j < RX_MAXCALLS; j++) {
347 if (tconn.callState[j] != RX_STATE_NOTINIT
348 && tconn.callState[j] != RX_STATE_DALLY) {
354 /* this call looks too ordinary, bump skipped count and go
360 if ((onlyHost != -1) && (onlyHost != tconn.host))
362 if ((onlyPort != -1) && (onlyPort != tconn.port))
364 if (onlyServer && (tconn.type != RX_SERVER_CONNECTION))
366 if (onlyClient && (tconn.type != RX_CLIENT_CONNECTION))
368 if (onlyAuth != 999) {
369 if (onlyAuth == -1) {
370 if (tconn.securityIndex != 0)
373 if (tconn.securityIndex != 2)
375 if (withSecStats && (tconn.secStats.type == 3)
376 && (tconn.secStats.level != onlyAuth))
381 /* now display the connection */
382 hostAddr.s_addr = tconn.host;
383 printf("Connection from host %s, port %hu, ", inet_ntoa(hostAddr),
386 printf("Cuid %x/%x", tconn.epoch, tconn.cid);
388 printf("cid %x", tconn.cid);
390 printf(", error %d", tconn.error);
391 printf("\n serial %d, ", tconn.serial);
392 printf(" natMTU %d, ", tconn.natMTU);
396 if (tconn.flags & RX_CONN_MAKECALL_WAITING)
397 printf(" MAKECALL_WAITING");
398 if (tconn.flags & RX_CONN_DESTROY_ME)
399 printf(" DESTROYED");
400 if (tconn.flags & RX_CONN_USING_PACKET_CKSUM)
404 printf("security index %d, ", tconn.securityIndex);
405 if (tconn.type == RX_CLIENT_CONNECTION)
406 printf("client conn\n");
408 printf("server conn\n");
411 switch ((int)tconn.secStats.type) {
413 if (tconn.securityIndex == 2)
415 (" no GetStats procedure for security object\n");
418 printf(" rxnull level=%d, flags=%d\n",
419 tconn.secStats.level, tconn.secStats.flags);
422 printf(" rxvab level=%d, flags=%d\n",
423 tconn.secStats.level, tconn.secStats.flags);
427 char flags = tconn.secStats.flags;
428 if (tconn.secStats.level == 0)
430 else if (tconn.secStats.level == 1)
432 else if (tconn.secStats.level == 2)
436 printf(" rxkad: level %s", level);
442 printf(" authenticated");
447 if (tconn.secStats.expires)
448 /* Apparently due to a bug in the RT compiler that
449 * prevents (afs_uint32)0xffffffff => (double) from working,
450 * this code produces negative lifetimes when run on the
452 printf(", expires in %.1f hours",
453 ((afs_uint32) tconn.secStats.expires -
456 printf("\n Received %d bytes in %d packets\n",
457 tconn.secStats.bytesReceived,
458 tconn.secStats.packetsReceived);
459 printf(" Sent %d bytes in %d packets\n",
460 tconn.secStats.bytesSent,
461 tconn.secStats.packetsSent);
468 printf(" unknown\n");
472 for (j = 0; j < RX_MAXCALLS; j++) {
473 printf(" call %d: # %d, state ", j, tconn.callNumber[j]);
474 if (tconn.callState[j] == RX_STATE_NOTINIT) {
475 printf("not initialized\n");
477 } else if (tconn.callState[j] == RX_STATE_PRECALL)
479 else if (tconn.callState[j] == RX_STATE_ACTIVE)
481 else if (tconn.callState[j] == RX_STATE_DALLY)
483 else if (tconn.callState[j] == RX_STATE_HOLD)
486 if (tconn.callMode[j] == RX_MODE_SENDING)
488 else if (tconn.callMode[j] == RX_MODE_RECEIVING)
490 else if (tconn.callMode[j] == RX_MODE_ERROR)
492 else if (tconn.callMode[j] == RX_MODE_EOF)
496 if (tconn.callFlags[j]) {
498 if (tconn.callFlags[j] & RX_CALL_READER_WAIT)
499 printf(" reader_wait");
500 if (tconn.callFlags[j] & RX_CALL_WAIT_WINDOW_ALLOC)
501 printf(" window_alloc");
502 if (tconn.callFlags[j] & RX_CALL_WAIT_WINDOW_SEND)
503 printf(" window_send");
504 if (tconn.callFlags[j] & RX_CALL_WAIT_PACKETS)
505 printf(" wait_packets");
506 if (tconn.callFlags[j] & RX_CALL_WAIT_PROC)
507 printf(" waiting_for_process");
508 if (tconn.callFlags[j] & RX_CALL_RECEIVE_DONE)
509 printf(" receive_done");
510 if (tconn.callFlags[j] & RX_CALL_CLEARED)
511 printf(" call_cleared");
513 if (tconn.callOther[j] & RX_OTHER_IN)
514 printf(", has_input_packets");
515 if (tconn.callOther[j] & RX_OTHER_OUT)
516 printf(", has_output_packets");
521 printf("Skipped %d dallying connections.\n", dallyCounter);
523 if (showPeers && withPeers) {
525 struct rx_debugPeer tpeer;
527 rx_GetServerPeers(s, host, port, &nextpeer, allconns, &tpeer,
528 &supportedPeerValues);
530 printf("getpeer call failed with code %d\n", code);
533 if (tpeer.host == 0xffffffff) {
538 if ((onlyHost != -1) && (onlyHost != tpeer.host))
540 if ((onlyPort != -1) && (onlyPort != tpeer.port))
543 /* now display the peer */
544 hostAddr.s_addr = tpeer.host;
545 printf("Peer at host %s, port %hu\n", inet_ntoa(hostAddr),
547 printf("\tifMTU %hu\tnatMTU %hu\tmaxMTU %hu\n", tpeer.ifMTU,
548 tpeer.natMTU, tpeer.maxMTU);
549 printf("\tpackets sent %d\tpacket resends %d\n", tpeer.nSent,
551 printf("\tbytes sent high %d low %d\n", tpeer.bytesSent.high,
552 tpeer.bytesSent.low);
553 printf("\tbytes received high %d low %d\n",
554 tpeer.bytesReceived.high, tpeer.bytesReceived.low);
555 printf("\trtt %d msec, rtt_dev %d msec\n", tpeer.rtt >> 3,
557 printf("\ttimeout %d.%03d sec\n", tpeer.timeout.sec,
558 tpeer.timeout.usec / 1000);
564 /* simple main program */
566 #include "AFS_component_version_number.c"
573 struct cmd_syndesc *ts;
576 if (afs_winsockInit() < 0) {
577 printf("%s: Couldn't initialize winsock. Exiting...\n", argv[0]);
582 ts = cmd_CreateSyntax(NULL, MainCommand, 0, "probe RX server");
583 cmd_AddParm(ts, "-servers", CMD_SINGLE, CMD_REQUIRED, "server machine");
584 cmd_AddParm(ts, "-port", CMD_SINGLE, CMD_OPTIONAL, "IP port");
585 cmd_AddParm(ts, "-nodally", CMD_FLAG, CMD_OPTIONAL,
586 "don't show dallying conns");
587 cmd_AddParm(ts, "-allconnections", CMD_FLAG, CMD_OPTIONAL,
588 "don't filter out uninteresting connections on server");
589 cmd_AddParm(ts, "-rxstats", CMD_FLAG, CMD_OPTIONAL, "show Rx statistics");
590 cmd_AddParm(ts, "-onlyserver", CMD_FLAG, CMD_OPTIONAL,
591 "only show server conns");
592 cmd_AddParm(ts, "-onlyclient", CMD_FLAG, CMD_OPTIONAL,
593 "only show client conns");
594 cmd_AddParm(ts, "-onlyport", CMD_SINGLE, CMD_OPTIONAL,
596 cmd_AddParm(ts, "-onlyhost", CMD_SINGLE, CMD_OPTIONAL,
598 cmd_AddParm(ts, "-onlyauth", CMD_SINGLE, CMD_OPTIONAL,
599 "show only <auth level>");
601 cmd_AddParm(ts, "-version", CMD_FLAG, CMD_OPTIONAL,
602 "show AFS version id");
603 cmd_AddParm(ts, "-noconns", CMD_FLAG, CMD_OPTIONAL,
604 "show no connections");
605 cmd_AddParm(ts, "-peers", CMD_FLAG, CMD_OPTIONAL, "show peers");
607 cmd_Dispatch(argc, argv);