2 * Copyright 2000, International Business Machines Corporation and others.
5 * This software has been released under the terms of the IBM Public
6 * License. For details, see the LICENSE file in the top-level source
7 * directory or online at http://www.openafs.org/dl/license10.html
10 #include <afsconfig.h>
11 #include <afs/param.h>
15 #include <sys/types.h>
20 #include <sys/socket.h>
24 #ifdef HAVE_NETINET_IN_H
25 #include <netinet/in.h>
27 #ifdef HAVE_SYS_TIME_H
50 #include "rx_globals.h"
55 extern struct hostent *hostutil_GetHostByName();
57 static short PortNumber(aport)
64 while (tc = *aport++) {
65 if (tc < '0' || tc > '9') return -1; /* bad port number */
67 total += tc - (int) '0';
72 static short PortName(aname)
75 register struct servent *ts;
76 ts = getservbyname(aname, (char *) 0);
78 return ts->s_port; /* returns it in network byte order */
81 int MainCommand(as, arock)
83 struct cmd_syndesc *as;
88 struct sockaddr_in taddr;
90 struct in_addr hostAddr;
93 register afs_int32 code;
97 int onlyClient, onlyServer;
109 struct rx_debugStats tstats;
110 char *portName, *hostName;
111 struct rx_debugConn tconn;
118 afs_uint32 supportedDebugValues = 0;
119 afs_uint32 supportedStatValues = 0;
120 afs_uint32 supportedConnValues = 0;
121 afs_uint32 supportedPeerValues = 0;
122 afs_int32 nextconn = 0;
123 afs_int32 nextpeer = 0;
125 nodally = (as->parms[2].items ? 1 : 0);
126 allconns = (as->parms[3].items ? 1 : 0);
127 rxstats = (as->parms[4].items ? 1 : 0);
128 onlyServer = (as->parms[5].items ? 1 : 0);
129 onlyClient = (as->parms[6].items ? 1 : 0);
130 version_flag=(as->parms[10].items ? 1 : 0);
131 noConns = (as->parms[11].items ? 1 : 0);
132 showPeers = (as->parms[12].items ? 1 : 0);
134 if (as->parms[0].items)
135 hostName = as->parms[0].items->data;
137 hostName = (char *) 0;
139 if (as->parms[1].items)
140 portName = as->parms[1].items->data;
142 portName = (char *) 0;
144 if (as->parms[7].items) {
145 char *name = as->parms[7].items->data;
146 if ((onlyPort = PortNumber(name)) == -1)
147 onlyPort = PortName(name);
148 if (onlyPort == -1) {
149 printf("rxdebug: can't resolve port name %s\n", name);
152 } else onlyPort = -1;
154 if (as->parms[8].items) {
155 char *name = as->parms[8].items->data;
157 th = hostutil_GetHostByName(name);
159 printf("rxdebug: host %s not found in host table\n", name);
162 memcpy(&onlyHost, th->h_addr, sizeof(afs_int32));
163 } else onlyHost = -1;
165 if (as->parms[9].items) {
166 char *name = as->parms[9].items->data;
167 if (strcmp (name, "clear") == 0) onlyAuth = 0;
168 else if (strcmp (name, "auth") == 0) onlyAuth = 1;
169 else if (strcmp (name, "crypt") == 0) onlyAuth = 2;
170 else if ((strcmp (name, "null") == 0) ||
171 (strcmp (name, "none") == 0) ||
172 (strncmp (name, "noauth", 6) == 0) ||
173 (strncmp (name, "unauth", 6) == 0)) onlyAuth = -1;
175 fprintf (stderr, "Unknown authentication level: %s\n", name);
178 } else onlyAuth = 999;
182 th = hostutil_GetHostByName(hostName);
184 printf("rxdebug: host %s not found in host table\n", hostName);
187 memcpy(&host, th->h_addr, sizeof(afs_int32));
189 else host = htonl(0x7f000001); /* IP localhost */
192 port = htons(7000); /* default is fileserver */
194 if ((port = PortNumber(portName)) == -1)
195 port = PortName(portName);
197 printf("rxdebug: can't resolve port name %s\n", portName);
204 hostAddr.s_addr = host;
205 printf("Trying %s (port %d):\n", inet_ntoa(hostAddr), ntohs(port));
206 s = socket(AF_INET, SOCK_DGRAM, 0);
207 taddr.sin_family = AF_INET;
209 taddr.sin_addr.s_addr = 0;
210 #ifdef STRUCT_SOCKADDR_HAS_SA_LEN
211 taddr.sin_len = sizeof(struct sockaddr_in);
213 code = bind(s, (struct sockaddr *) &taddr, sizeof(struct sockaddr_in));
222 code = rx_GetServerVersion(s, host, port, length, version);
225 printf("get version call failed with code %d, errno %d\n",
229 printf("AFS version: %s\n",version);fflush(stdout);
236 code = rx_GetServerDebug(s, host, port, &tstats, &supportedDebugValues);
238 printf("getstats call failed with code %d\n", code);
242 withSecStats = (supportedDebugValues & RX_SERVER_DEBUG_SEC_STATS);
243 withAllConn = (supportedDebugValues & RX_SERVER_DEBUG_ALL_CONN);
244 withRxStats = (supportedDebugValues & RX_SERVER_DEBUG_RX_STATS);
245 withWaiters = (supportedDebugValues & RX_SERVER_DEBUG_WAITER_CNT);
246 withIdleThreads = (supportedDebugValues & RX_SERVER_DEBUG_IDLE_THREADS);
247 withPeers = (supportedDebugValues & RX_SERVER_DEBUG_ALL_PEER);
249 printf("Free packets: %d, packet reclaims: %d, calls: %d, used FDs: %d\n",
250 tstats.nFreePackets, tstats.packetReclaims,
251 tstats.callsExecuted, tstats.usedFDs);
252 if (!tstats.waitingForPackets) printf("not ");
253 printf("waiting for packets.\n");
255 printf("%d calls waiting for a thread\n",tstats.nWaiting);
256 if ( withIdleThreads )
257 printf("%d threads are idle\n", tstats.idleThreads);
263 fprintf (stderr, "WARNING: Server doesn't support retrieval of Rx statistics\n");
266 struct rx_stats rxstats;
268 /* should gracefully handle the case where rx_stats grows */
269 code = rx_GetServerStats(s, host, port, &rxstats, &supportedStatValues);
271 printf("rxstats call failed with code %d\n", code);
274 if (code != sizeof(rxstats)) {
275 if ((((struct rx_debugIn *)(&rxstats))->type ==
276 RX_DEBUGI_BADTYPE)) goto noRxStats;
277 printf ("WARNING: returned Rx statistics of unexpected size (got %d)\n",
279 /* handle other versions?... */
282 rx_PrintTheseStats (stdout, &rxstats, sizeof(rxstats),
283 tstats.nFreePackets, tstats.version);
289 if (!withAllConn) fprintf (stderr, "WARNING: Server doesn't support retrieval of all connections,\n getting only interesting instead.\n");
292 if (onlyServer) printf ("Showing only server connections\n");
293 if (onlyClient) printf ("Showing only client connections\n");
294 if (onlyAuth != 999) {
295 static char *name[] =
296 {"unauthenticated", "rxkad_clear", "rxkad_auth", "rxkad_crypt"};
297 printf ("Showing only %s connections\n", name[onlyAuth+1]);
299 if (onlyHost != -1) {
300 hostAddr.s_addr = onlyHost;
301 printf ("Showing only connections from host %s\n",
302 inet_ntoa(hostAddr));
305 printf ("Showing only connections on port %u\n", ntohs(onlyPort));
308 code = rx_GetServerConnections(s, host, port, &nextconn, allconns,
309 supportedDebugValues, &tconn,
310 &supportedConnValues);
312 printf("getconn call failed with code %d\n", code);
315 if (tconn.cid == 0xffffffff) {
320 /* see if we're in nodally mode and all calls are dallying */
323 for(j=0;j<RX_MAXCALLS;j++) {
324 if (tconn.callState[j] != RX_STATE_NOTINIT &&
325 tconn.callState[j] != RX_STATE_DALLY) {
331 /* this call looks too ordinary, bump skipped count and go
337 if ((onlyHost != -1) && (onlyHost != tconn.host)) continue;
338 if ((onlyPort != -1) && (onlyPort != tconn.port)) continue;
339 if (onlyServer && (tconn.type != RX_SERVER_CONNECTION)) continue;
340 if (onlyClient && (tconn.type != RX_CLIENT_CONNECTION)) continue;
341 if (onlyAuth != 999) {
342 if (onlyAuth == -1) {
343 if (tconn.securityIndex != 0) continue;
345 if (tconn.securityIndex != 2) continue;
346 if (withSecStats && (tconn.secStats.type == 3) &&
347 (tconn.secStats.level != onlyAuth)) continue;
351 /* now display the connection */
352 hostAddr.s_addr = tconn.host;
353 printf("Connection from host %s, port %hu, ",
354 inet_ntoa(hostAddr), ntohs(tconn.port));
356 printf ("Cuid %x/%x", tconn.epoch, tconn.cid);
357 else printf ("cid %x", tconn.cid);
358 if (tconn.error) printf (", error %d", tconn.error);
359 printf("\n serial %d, ", tconn.serial);
360 printf(" natMTU %d, ", tconn.natMTU);
364 if (tconn.flags & RX_CONN_MAKECALL_WAITING)
365 printf(" MAKECALL_WAITING");
366 if (tconn.flags & RX_CONN_DESTROY_ME) printf(" DESTROYED");
367 if (tconn.flags & RX_CONN_USING_PACKET_CKSUM) printf(" pktCksum");
370 printf("security index %d, ", tconn.securityIndex);
371 if (tconn.type == RX_CLIENT_CONNECTION) printf("client conn\n");
372 else printf("server conn\n");
375 switch ((int)tconn.secStats.type) {
377 if (tconn.securityIndex == 2)
378 printf (" no GetStats procedure for security object\n");
381 printf (" rxnull level=%d, flags=%d\n",
382 tconn.secStats.level, tconn.secStats.flags);
385 printf (" rxvab level=%d, flags=%d\n",
386 tconn.secStats.level, tconn.secStats.flags);
390 char flags = tconn.secStats.flags;
391 if (tconn.secStats.level == 0) level = "clear";
392 else if (tconn.secStats.level == 1) level = "auth";
393 else if (tconn.secStats.level == 2) level = "crypt";
394 else level = "unknown";
395 printf (" rxkad: level %s", level);
396 if (flags) printf (", flags");
397 if (flags & 1) printf (" unalloc");
398 if (flags & 2) printf (" authenticated");
399 if (flags & 4) printf (" expired");
400 if (flags & 8) printf (" pktCksum");
401 if (tconn.secStats.expires)
402 /* Apparently due to a bug in the RT compiler that
403 * prevents (afs_uint32)0xffffffff => (double) from working,
404 * this code produces negative lifetimes when run on the
406 printf (", expires in %.1f hours",
407 ((afs_uint32)tconn.secStats.expires -
410 printf ("\n Received %d bytes in %d packets\n",
411 tconn.secStats.bytesReceived,
412 tconn.secStats.packetsReceived);
413 printf (" Sent %d bytes in %d packets\n",
414 tconn.secStats.bytesSent,
415 tconn.secStats.packetsSent);
416 } else printf ("\n");
420 default: printf(" unknown\n");
424 for(j=0;j<RX_MAXCALLS;j++) {
425 printf(" call %d: # %d, state ", j, tconn.callNumber[j]);
426 if (tconn.callState[j]==RX_STATE_NOTINIT) {
427 printf("not initialized\n");
430 else if (tconn.callState[j]==RX_STATE_PRECALL)
432 else if (tconn.callState[j] == RX_STATE_ACTIVE)
434 else if (tconn.callState[j] == RX_STATE_DALLY)
436 else if (tconn.callState[j] == RX_STATE_HOLD)
439 if (tconn.callMode[j]==RX_MODE_SENDING)
441 else if (tconn.callMode[j]==RX_MODE_RECEIVING)
443 else if (tconn.callMode[j]==RX_MODE_ERROR)
445 else if (tconn.callMode[j] == RX_MODE_EOF)
447 else printf("unknown");
448 if (tconn.callFlags[j]) {
450 if (tconn.callFlags[j]&RX_CALL_READER_WAIT)
451 printf(" reader_wait");
452 if (tconn.callFlags[j]&RX_CALL_WAIT_WINDOW_ALLOC)
453 printf(" window_alloc");
454 if (tconn.callFlags[j]&RX_CALL_WAIT_WINDOW_SEND)
455 printf(" window_send");
456 if (tconn.callFlags[j]&RX_CALL_WAIT_PACKETS)
457 printf(" wait_packets");
458 if (tconn.callFlags[j]&RX_CALL_WAIT_PROC)
459 printf(" waiting_for_process");
460 if (tconn.callFlags[j]&RX_CALL_RECEIVE_DONE)
461 printf(" receive_done");
462 if (tconn.callFlags[j]&RX_CALL_CLEARED)
463 printf(" call_cleared");
465 if (tconn.callOther[j] & RX_OTHER_IN)
466 printf(", has_input_packets");
467 if (tconn.callOther[j] & RX_OTHER_OUT)
468 printf(", has_output_packets");
472 if (nodally) printf("Skipped %d dallying connections.\n", dallyCounter);
474 if (showPeers && withPeers) {
476 struct rx_debugPeer tpeer;
477 code = rx_GetServerPeers(s, host, port, &nextpeer, allconns, &tpeer, &supportedPeerValues);
479 printf("getpeer call failed with code %d\n", code);
482 if (tpeer.host == 0xffffffff) {
487 if ((onlyHost != -1) && (onlyHost != tpeer.host)) continue;
488 if ((onlyPort != -1) && (onlyPort != tpeer.port)) continue;
490 /* now display the peer */
491 hostAddr.s_addr = tpeer.host;
492 printf("Peer at host %s, port %hu\n",
493 inet_ntoa(hostAddr), ntohs(tpeer.port));
494 printf("\tifMTU %hu\tnatMTU %hu\tmaxMTU %hu\n",
495 tpeer.ifMTU, tpeer.natMTU, tpeer.maxMTU);
496 printf("\tpackets sent %d\tpacket resends %d\n",
497 tpeer.nSent, tpeer.reSends);
498 printf("\tbytes sent high %d low %d\n",
499 tpeer.bytesSent.high, tpeer.bytesSent.low);
500 printf("\tbytes received high %d low %d\n",
501 tpeer.bytesReceived.high, tpeer.bytesReceived.low);
502 printf("\trtt %d msec, rtt_dev %d msec\n",
503 tpeer.rtt >> 3, tpeer.rtt_dev >> 2);
504 printf("\ttimeout %d.%03d sec\n",
505 tpeer.timeout.sec, tpeer.timeout.usec / 1000);
511 /* simple main program */
513 #include "AFS_component_version_number.c"
519 struct cmd_syndesc *ts;
522 if (afs_winsockInit()<0) {
523 printf("%s: Couldn't initialize winsock. Exiting...\n", argv[0]);
528 ts = cmd_CreateSyntax((char *) 0, MainCommand, 0, "probe RX server");
529 cmd_AddParm(ts, "-servers", CMD_SINGLE, CMD_REQUIRED, "server machine");
530 cmd_AddParm(ts, "-port", CMD_SINGLE, CMD_OPTIONAL, "IP port");
531 cmd_AddParm(ts, "-nodally", CMD_FLAG, CMD_OPTIONAL,
532 "don't show dallying conns");
533 cmd_AddParm(ts, "-allconnections", CMD_FLAG, CMD_OPTIONAL,
534 "don't filter out uninteresting connections on server");
535 cmd_AddParm(ts, "-rxstats", CMD_FLAG, CMD_OPTIONAL, "show Rx statistics");
536 cmd_AddParm(ts, "-onlyserver", CMD_FLAG, CMD_OPTIONAL,
537 "only show server conns");
538 cmd_AddParm(ts, "-onlyclient", CMD_FLAG, CMD_OPTIONAL,
539 "only show client conns");
540 cmd_AddParm(ts, "-onlyport", CMD_SINGLE, CMD_OPTIONAL, "show only <port>");
541 cmd_AddParm(ts, "-onlyhost", CMD_SINGLE, CMD_OPTIONAL, "show only <host>");
542 cmd_AddParm(ts, "-onlyauth", CMD_SINGLE, CMD_OPTIONAL,
543 "show only <auth level>");
545 cmd_AddParm(ts,"-version",CMD_FLAG,CMD_OPTIONAL,"show AFS version id");
546 cmd_AddParm(ts,"-noconns",CMD_FLAG,CMD_OPTIONAL,"show no connections");
547 cmd_AddParm(ts,"-peers",CMD_FLAG,CMD_OPTIONAL,"show peers");
549 cmd_Dispatch(argc, argv);