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 <sys/types.h>
11 #include <afs/param.h>
16 #include <sys/socket.h>
19 #include <netinet/in.h>
32 #include "rx_globals.h"
37 extern struct hostent *hostutil_GetHostByName();
39 static short PortNumber(aport)
46 while (tc = *aport++) {
47 if (tc < '0' || tc > '9') return -1; /* bad port number */
49 total += tc - (int) '0';
54 static short PortName(aname)
57 register struct servent *ts;
58 ts = getservbyname(aname, (char *) 0);
60 return ts->s_port; /* returns it in network byte order */
63 MainCommand(as, arock)
65 struct cmd_syndesc *as;
70 struct sockaddr_in taddr;
72 struct in_addr hostAddr;
75 register afs_int32 code;
79 int onlyClient, onlyServer;
91 struct rx_debugStats tstats;
92 char *portName, *hostName;
93 struct rx_debugConn tconn;
100 afs_uint32 supportedDebugValues = 0;
101 afs_uint32 supportedStatValues = 0;
102 afs_uint32 supportedConnValues = 0;
103 afs_uint32 supportedPeerValues = 0;
104 afs_int32 nextconn = 0;
105 afs_int32 nextpeer = 0;
107 nodally = (as->parms[2].items ? 1 : 0);
108 allconns = (as->parms[3].items ? 1 : 0);
109 rxstats = (as->parms[4].items ? 1 : 0);
110 onlyServer = (as->parms[5].items ? 1 : 0);
111 onlyClient = (as->parms[6].items ? 1 : 0);
112 version_flag=(as->parms[10].items ? 1 : 0);
113 noConns = (as->parms[11].items ? 1 : 0);
114 showPeers = (as->parms[12].items ? 1 : 0);
116 if (as->parms[0].items)
117 hostName = as->parms[0].items->data;
119 hostName = (char *) 0;
121 if (as->parms[1].items)
122 portName = as->parms[1].items->data;
124 portName = (char *) 0;
126 if (as->parms[7].items) {
127 char *name = as->parms[7].items->data;
128 if ((onlyPort = PortNumber(name)) == -1)
129 onlyPort = PortName(name);
130 if (onlyPort == -1) {
131 printf("rxdebug: can't resolve port name %s\n", name);
134 } else onlyPort = -1;
136 if (as->parms[8].items) {
137 char *name = as->parms[8].items->data;
139 th = hostutil_GetHostByName(name);
141 printf("rxdebug: host %s not found in host table\n", name);
144 bcopy(th->h_addr, &onlyHost, sizeof(afs_int32));
145 } else onlyHost = -1;
147 if (as->parms[9].items) {
148 char *name = as->parms[9].items->data;
149 if (strcmp (name, "clear") == 0) onlyAuth = 0;
150 else if (strcmp (name, "auth") == 0) onlyAuth = 1;
151 else if (strcmp (name, "crypt") == 0) onlyAuth = 2;
152 else if ((strcmp (name, "null") == 0) ||
153 (strcmp (name, "none") == 0) ||
154 (strncmp (name, "noauth", 6) == 0) ||
155 (strncmp (name, "unauth", 6) == 0)) onlyAuth = -1;
157 fprintf (stderr, "Unknown authentication level: %s\n", name);
160 } else onlyAuth = 999;
164 th = hostutil_GetHostByName(hostName);
166 printf("rxdebug: host %s not found in host table\n", hostName);
169 bcopy(th->h_addr, &host, sizeof(afs_int32));
171 else host = htonl(0x7f000001); /* IP localhost */
174 port = htons(7000); /* default is fileserver */
176 if ((port = PortNumber(portName)) == -1)
177 port = PortName(portName);
179 printf("rxdebug: can't resolve port name %s\n", portName);
186 hostAddr.s_addr = host;
187 printf("Trying %s (port %d):\n", inet_ntoa(hostAddr), ntohs(port));
188 s = socket(AF_INET, SOCK_DGRAM, 0);
189 taddr.sin_family = AF_INET;
191 taddr.sin_addr.s_addr = 0;
192 code = bind(s, (struct sockaddr *) &taddr, sizeof(struct sockaddr_in));
201 code = rx_GetServerVersion(s, host, port, length, version);
204 printf("get version call failed with code %d, errno %d\n",
208 printf("AFS version: %s\n",version);fflush(stdout);
215 code = rx_GetServerDebug(s, host, port, &tstats, &supportedDebugValues);
217 printf("getstats call failed with code %d\n", code);
221 withSecStats = (supportedDebugValues & RX_SERVER_DEBUG_SEC_STATS);
222 withAllConn = (supportedDebugValues & RX_SERVER_DEBUG_ALL_CONN);
223 withRxStats = (supportedDebugValues & RX_SERVER_DEBUG_RX_STATS);
224 withWaiters = (supportedDebugValues & RX_SERVER_DEBUG_WAITER_CNT);
225 withIdleThreads = (supportedDebugValues & RX_SERVER_DEBUG_IDLE_THREADS);
226 withPeers = (supportedDebugValues & RX_SERVER_DEBUG_ALL_PEER);
228 printf("Free packets: %d, packet reclaims: %d, calls: %d, used FDs: %d\n",
229 tstats.nFreePackets, tstats.packetReclaims,
230 tstats.callsExecuted, tstats.usedFDs);
231 if (!tstats.waitingForPackets) printf("not ");
232 printf("waiting for packets.\n");
234 printf("%d calls waiting for a thread\n",tstats.nWaiting);
235 if ( withIdleThreads )
236 printf("%d threads are idle\n", tstats.idleThreads);
242 fprintf (stderr, "WARNING: Server doesn't support retrieval of Rx statistics\n");
245 struct rx_stats rxstats;
247 /* should gracefully handle the case where rx_stats grows */
248 code = rx_GetServerStats(s, host, port, &rxstats, &supportedStatValues);
250 printf("rxstats call failed with code %d\n", code);
253 if (code != sizeof(rxstats)) {
254 if ((((struct rx_debugIn *)(&rxstats))->type ==
255 RX_DEBUGI_BADTYPE)) goto noRxStats;
256 printf ("WARNING: returned Rx statistics of unexpected size (got %d)\n",
258 /* handle other versions?... */
261 rx_PrintTheseStats (stdout, &rxstats, sizeof(rxstats),
262 tstats.nFreePackets, tstats.version);
268 if (!withAllConn) fprintf (stderr, "WARNING: Server doesn't support retrieval of all connections,\n getting only interesting instead.\n");
271 if (onlyServer) printf ("Showing only server connections\n");
272 if (onlyClient) printf ("Showing only client connections\n");
273 if (onlyAuth != 999) {
274 static char *name[] =
275 {"unauthenticated", "rxkad_clear", "rxkad_auth", "rxkad_crypt"};
276 printf ("Showing only %s connections\n", name[onlyAuth+1]);
278 if (onlyHost != -1) {
279 hostAddr.s_addr = onlyHost;
280 printf ("Showing only connections from host %s\n",
281 inet_ntoa(hostAddr));
284 printf ("Showing only connections on port %u\n", ntohs(onlyPort));
287 code = rx_GetServerConnections(s, host, port, &nextconn, allconns,
288 supportedDebugValues, &tconn,
289 &supportedConnValues);
291 printf("getconn call failed with code %d\n", code);
294 if (tconn.cid == 0xffffffff) {
299 /* see if we're in nodally mode and all calls are dallying */
302 for(j=0;j<RX_MAXCALLS;j++) {
303 if (tconn.callState[j] != RX_STATE_NOTINIT &&
304 tconn.callState[j] != RX_STATE_DALLY) {
310 /* this call looks too ordinary, bump skipped count and go
316 if ((onlyHost != -1) && (onlyHost != tconn.host)) continue;
317 if ((onlyPort != -1) && (onlyPort != tconn.port)) continue;
318 if (onlyServer && (tconn.type != RX_SERVER_CONNECTION)) continue;
319 if (onlyClient && (tconn.type != RX_CLIENT_CONNECTION)) continue;
320 if (onlyAuth != 999) {
321 if (onlyAuth == -1) {
322 if (tconn.securityIndex != 0) continue;
324 if (tconn.securityIndex != 2) continue;
325 if (withSecStats && (tconn.secStats.type == 3) &&
326 (tconn.secStats.level != onlyAuth)) continue;
330 /* now display the connection */
331 hostAddr.s_addr = tconn.host;
332 printf("Connection from host %s, port %hu, ",
333 inet_ntoa(hostAddr), ntohs(tconn.port));
335 printf ("Cuid %x/%x", tconn.epoch, tconn.cid);
336 else printf ("cid %x", tconn.cid);
337 if (tconn.error) printf (", error %d", tconn.error);
338 printf("\n serial %d, ", tconn.serial);
339 printf(" natMTU %d, ", tconn.natMTU);
343 if (tconn.flags & RX_CONN_MAKECALL_WAITING)
344 printf(" MAKECALL_WAITING");
345 if (tconn.flags & RX_CONN_DESTROY_ME) printf(" DESTROYED");
346 if (tconn.flags & RX_CONN_USING_PACKET_CKSUM) printf(" pktCksum");
349 printf("security index %d, ", tconn.securityIndex);
350 if (tconn.type == RX_CLIENT_CONNECTION) printf("client conn\n");
351 else printf("server conn\n");
354 switch ((int)tconn.secStats.type) {
356 if (tconn.securityIndex == 2)
357 printf (" no GetStats procedure for security object\n");
360 printf (" rxnull level=%d, flags=%d\n",
361 tconn.secStats.level, tconn.secStats.flags);
364 printf (" rxvab level=%d, flags=%d\n",
365 tconn.secStats.level, tconn.secStats.flags);
369 char flags = tconn.secStats.flags;
370 if (tconn.secStats.level == 0) level = "clear";
371 else if (tconn.secStats.level == 1) level = "auth";
372 else if (tconn.secStats.level == 2) level = "crypt";
373 else level = "unknown";
374 printf (" rxkad: level %s", level);
375 if (flags) printf (", flags");
376 if (flags & 1) printf (" unalloc");
377 if (flags & 2) printf (" authenticated");
378 if (flags & 4) printf (" expired");
379 if (flags & 8) printf (" pktCksum");
380 if (tconn.secStats.expires)
381 /* Apparently due to a bug in the RT compiler that
382 * prevents (afs_uint32)0xffffffff => (double) from working,
383 * this code produces negative lifetimes when run on the
385 printf (", expires in %.1f hours",
386 ((afs_uint32)tconn.secStats.expires -
389 printf ("\n Received %d bytes in %d packets\n",
390 tconn.secStats.bytesReceived,
391 tconn.secStats.packetsReceived);
392 printf (" Sent %d bytes in %d packets\n",
393 tconn.secStats.bytesSent,
394 tconn.secStats.packetsSent);
395 } else printf ("\n");
399 default: printf(" unknown\n");
403 for(j=0;j<RX_MAXCALLS;j++) {
404 printf(" call %d: # %d, state ", j, tconn.callNumber[j]);
405 if (tconn.callState[j]==RX_STATE_NOTINIT) {
406 printf("not initialized\n");
409 else if (tconn.callState[j]==RX_STATE_PRECALL)
411 else if (tconn.callState[j] == RX_STATE_ACTIVE)
413 else if (tconn.callState[j] == RX_STATE_DALLY)
415 else if (tconn.callState[j] == RX_STATE_HOLD)
418 if (tconn.callMode[j]==RX_MODE_SENDING)
420 else if (tconn.callMode[j]==RX_MODE_RECEIVING)
422 else if (tconn.callMode[j]==RX_MODE_ERROR)
424 else if (tconn.callMode[j] == RX_MODE_EOF)
426 else printf("unknown");
427 if (tconn.callFlags[j]) {
429 if (tconn.callFlags[j]&RX_CALL_READER_WAIT)
430 printf(" reader_wait");
431 if (tconn.callFlags[j]&RX_CALL_WAIT_WINDOW_ALLOC)
432 printf(" window_alloc");
433 if (tconn.callFlags[j]&RX_CALL_WAIT_WINDOW_SEND)
434 printf(" window_send");
435 if (tconn.callFlags[j]&RX_CALL_WAIT_PACKETS)
436 printf(" wait_packets");
437 if (tconn.callFlags[j]&RX_CALL_WAIT_PROC)
438 printf(" waiting_for_process");
439 if (tconn.callFlags[j]&RX_CALL_RECEIVE_DONE)
440 printf(" receive_done");
441 if (tconn.callFlags[j]&RX_CALL_CLEARED)
442 printf(" call_cleared");
444 if (tconn.callOther[j] & RX_OTHER_IN)
445 printf(", has_input_packets");
446 if (tconn.callOther[j] & RX_OTHER_OUT)
447 printf(", has_output_packets");
451 if (nodally) printf("Skipped %d dallying connections.\n", dallyCounter);
453 if (showPeers && withPeers) {
455 struct rx_debugPeer tpeer;
456 code = rx_GetServerPeers(s, host, port, &nextpeer, allconns, &tpeer, &supportedPeerValues);
458 printf("getpeer call failed with code %d\n", code);
461 if (tpeer.host == 0xffffffff) {
466 /* now display the peer */
467 hostAddr.s_addr = tpeer.host;
468 printf("Peer at host %s, port %hu\n",
469 inet_ntoa(hostAddr), ntohs(tpeer.port));
470 printf("\tifMTU %hu\tnatMTU %hu\tmaxMTU %hu\n",
471 tpeer.ifMTU, tpeer.natMTU, tpeer.maxMTU);
472 printf("\tpackets sent %d\tpacket resends %d\n",
473 tpeer.nSent, tpeer.reSends);
474 printf("\tbytes sent high %d low %d\n",
475 tpeer.bytesSent.high, tpeer.bytesSent.low);
476 printf("\tbytes received high %d low %d\n",
477 tpeer.bytesReceived.high, tpeer.bytesReceived.low);
483 /* simple main program */
485 #include "AFS_component_version_number.c"
491 struct cmd_syndesc *ts;
494 if (afs_winsockInit()<0) {
495 printf("%s: Couldn't initialize winsock. Exiting...\n", argv[0]);
500 ts = cmd_CreateSyntax((char *) 0, MainCommand, 0, "probe RX server");
501 cmd_AddParm(ts, "-servers", CMD_SINGLE, CMD_REQUIRED, "server machine");
502 cmd_AddParm(ts, "-port", CMD_SINGLE, CMD_OPTIONAL, "IP port");
503 cmd_AddParm(ts, "-nodally", CMD_FLAG, CMD_OPTIONAL,
504 "don't show dallying conns");
505 cmd_AddParm(ts, "-allconnections", CMD_FLAG, CMD_OPTIONAL,
506 "don't filter out uninteresting connections on server");
507 cmd_AddParm(ts, "-rxstats", CMD_FLAG, CMD_OPTIONAL, "show Rx statistics");
508 cmd_AddParm(ts, "-onlyserver", CMD_FLAG, CMD_OPTIONAL,
509 "only show server conns");
510 cmd_AddParm(ts, "-onlyclient", CMD_FLAG, CMD_OPTIONAL,
511 "only show client conns");
512 cmd_AddParm(ts, "-onlyport", CMD_SINGLE, CMD_OPTIONAL, "show only <port>");
513 cmd_AddParm(ts, "-onlyhost", CMD_SINGLE, CMD_OPTIONAL, "show only <host>");
514 cmd_AddParm(ts, "-onlyauth", CMD_SINGLE, CMD_OPTIONAL,
515 "show only <auth level>");
517 cmd_AddParm(ts,"-version",CMD_FLAG,CMD_OPTIONAL,"show AFS version id");
518 cmd_AddParm(ts,"-noconns",CMD_FLAG,CMD_OPTIONAL,"show no connections");
519 cmd_AddParm(ts,"-peers",CMD_FLAG,CMD_OPTIONAL,"show peers");
521 cmd_Dispatch(argc, argv);