rx-warning-cleanup-and-afsconfig-20010612
[openafs.git] / src / rx / rxdebug.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 <sys/types.h>
11 #include <afs/param.h>
12 #include <afsconfig.h>
13 #include <errno.h>
14 #ifdef AFS_NT40_ENV
15 #include <winsock2.h>
16 #else
17 #include <sys/socket.h>
18 #include <sys/file.h>
19 #include <netdb.h>
20 #endif
21 #ifdef HAVE_NETINET_IN_H
22 #include <netinet/in.h>
23 #endif
24 #ifdef HAVE_SYS_TIME_H
25 #include <sys/time.h>
26 #endif
27 #ifdef HAVE_UNISTD_H
28 #include <unistd.h>
29 #endif
30 #ifdef HAVE_STRING_H
31 #include <string.h>
32 #endif
33 #ifdef HAVE_STRINGS_H
34 #include <string.h>
35 #endif
36 #include <sys/stat.h>
37 #include <afs/stds.h>
38 #include <afs/cmd.h>
39
40 #include <stdio.h>
41
42 #include "rx_user.h"
43 #include "rx_clock.h"
44 #include "rx_queue.h"
45 #include "rx.h"
46 #include "rx_globals.h"
47
48
49 #define TIMEOUT     20
50
51 extern struct hostent *hostutil_GetHostByName();
52
53 static short PortNumber(aport)
54 register char *aport;
55 {
56     register int tc;
57     register short total;
58
59     total = 0;
60     while (tc = *aport++) {
61         if (tc < '0' || tc > '9') return -1;    /* bad port number */
62         total *= 10;
63         total += tc - (int) '0';
64     }
65     return htons(total);
66 }
67
68 static short PortName(aname)
69 register char *aname;
70 {
71     register struct servent *ts;
72     ts = getservbyname(aname, (char *) 0);
73     if (!ts) return -1;
74     return ts->s_port;  /* returns it in network byte order */
75 }
76
77 int MainCommand(as, arock)
78 char *arock;
79 struct cmd_syndesc *as;
80 {
81     register int i;
82     int s;
83     int j;
84     struct sockaddr_in taddr;
85     afs_int32 host;
86     struct in_addr hostAddr;
87     short port;
88     struct hostent *th;
89     register afs_int32 code;
90     int nodally;
91     int allconns;
92     int rxstats;
93     int onlyClient, onlyServer;
94     afs_int32 onlyHost;
95     short onlyPort;
96     int onlyAuth;
97     int flag;
98     int dallyCounter;
99     int withSecStats;
100     int withAllConn;
101     int withRxStats;
102     int withWaiters;
103     int withIdleThreads;
104     int withPeers;
105     struct rx_debugStats tstats;
106     char *portName, *hostName;
107     struct rx_debugConn tconn;
108     short noConns;
109     short showPeers;
110     int version_flag;
111     char version[64];
112     afs_int32 length=64;
113
114     afs_uint32 supportedDebugValues = 0;
115     afs_uint32 supportedStatValues = 0;
116     afs_uint32 supportedConnValues = 0;
117     afs_uint32 supportedPeerValues = 0;
118     afs_int32 nextconn = 0;
119     afs_int32 nextpeer = 0;
120     
121     nodally = (as->parms[2].items ? 1 : 0);
122     allconns = (as->parms[3].items ? 1 : 0);
123     rxstats = (as->parms[4].items ? 1 : 0);
124     onlyServer = (as->parms[5].items ? 1 : 0);
125     onlyClient = (as->parms[6].items ? 1 : 0);
126     version_flag=(as->parms[10].items ? 1 : 0);
127     noConns = (as->parms[11].items ? 1 : 0);
128     showPeers = (as->parms[12].items ? 1 : 0);
129
130     if (as->parms[0].items)
131         hostName = as->parms[0].items->data;
132     else
133         hostName = (char *) 0;
134
135     if (as->parms[1].items)
136         portName = as->parms[1].items->data;
137     else
138         portName = (char *) 0;
139
140     if (as->parms[7].items) {
141         char *name = as->parms[7].items->data;
142         if ((onlyPort = PortNumber(name)) == -1)
143             onlyPort = PortName(name);
144         if (onlyPort == -1) {
145             printf("rxdebug: can't resolve port name %s\n", name);
146             exit(1);
147         }
148     } else onlyPort = -1;
149
150     if (as->parms[8].items) {
151         char *name = as->parms[8].items->data;
152         struct hostent *th;
153         th = hostutil_GetHostByName(name);
154         if (!th) {
155             printf("rxdebug: host %s not found in host table\n", name);
156             exit(1);
157         }
158         bcopy(th->h_addr, &onlyHost, sizeof(afs_int32));
159     } else onlyHost = -1;
160
161     if (as->parms[9].items) {
162         char *name = as->parms[9].items->data;
163         if (strcmp (name, "clear") == 0) onlyAuth = 0;
164         else if (strcmp (name, "auth") == 0) onlyAuth = 1;
165         else if (strcmp (name, "crypt") == 0) onlyAuth = 2;
166         else if ((strcmp (name, "null") == 0) ||
167                  (strcmp (name, "none") == 0) ||
168                  (strncmp (name, "noauth", 6) == 0) ||
169                  (strncmp (name, "unauth", 6) == 0)) onlyAuth = -1;
170         else {
171             fprintf (stderr, "Unknown authentication level: %s\n", name);
172             exit (1);
173         }
174     } else onlyAuth = 999;
175
176     /* lookup host */
177     if (hostName) {
178         th = hostutil_GetHostByName(hostName);
179         if (!th) {
180             printf("rxdebug: host %s not found in host table\n", hostName);
181             exit(1);
182         }
183         bcopy(th->h_addr, &host, sizeof(afs_int32));
184     }
185     else host = htonl(0x7f000001);      /* IP localhost */
186
187     if (!portName)
188         port = htons(7000);             /* default is fileserver */
189     else {
190         if ((port = PortNumber(portName)) == -1)
191             port = PortName(portName);
192         if (port == -1) {
193             printf("rxdebug: can't resolve port name %s\n", portName);
194             exit(1);
195         }
196     }
197
198     dallyCounter = 0; 
199
200     hostAddr.s_addr = host;
201     printf("Trying %s (port %d):\n", inet_ntoa(hostAddr), ntohs(port));
202     s = socket(AF_INET, SOCK_DGRAM, 0);
203     taddr.sin_family = AF_INET;
204     taddr.sin_port = 0;
205     taddr.sin_addr.s_addr = 0;
206     code = bind(s, (struct sockaddr *) &taddr, sizeof(struct sockaddr_in));
207     if (code) {
208         perror("bind");
209         exit(1);
210     }
211
212         if(version_flag)
213         {
214     
215                 code = rx_GetServerVersion(s, host, port, length, version);
216                 if (code < 0)
217                 {
218                         printf("get version call failed with code %d, errno %d\n",
219                                 code,errno);
220                         exit(1);
221                 }
222                 printf("AFS version: %s\n",version);fflush(stdout);
223
224                 exit(0);
225
226         }
227
228     
229     code = rx_GetServerDebug(s, host, port, &tstats, &supportedDebugValues);
230     if (code < 0) {
231         printf("getstats call failed with code %d\n", code);
232         exit(1);
233     }
234
235     withSecStats = (supportedDebugValues & RX_SERVER_DEBUG_SEC_STATS);
236     withAllConn = (supportedDebugValues & RX_SERVER_DEBUG_ALL_CONN);
237     withRxStats = (supportedDebugValues & RX_SERVER_DEBUG_RX_STATS);
238     withWaiters = (supportedDebugValues & RX_SERVER_DEBUG_WAITER_CNT);
239     withIdleThreads = (supportedDebugValues & RX_SERVER_DEBUG_IDLE_THREADS);
240     withPeers = (supportedDebugValues & RX_SERVER_DEBUG_ALL_PEER);
241
242     printf("Free packets: %d, packet reclaims: %d, calls: %d, used FDs: %d\n",
243            tstats.nFreePackets, tstats.packetReclaims,
244            tstats.callsExecuted, tstats.usedFDs);
245     if (!tstats.waitingForPackets) printf("not ");
246     printf("waiting for packets.\n");
247     if (withWaiters)
248       printf("%d calls waiting for a thread\n",tstats.nWaiting);
249     if ( withIdleThreads )
250       printf("%d threads are idle\n", tstats.idleThreads);
251
252     if (rxstats) {
253         if (!withRxStats) {
254   noRxStats:
255             withRxStats = 0;
256             fprintf (stderr, "WARNING: Server doesn't support retrieval of Rx statistics\n");
257         }
258         else {
259             struct rx_stats rxstats;
260
261             /* should gracefully handle the case where rx_stats grows */
262             code = rx_GetServerStats(s, host, port, &rxstats, &supportedStatValues);
263             if (code < 0) {
264                 printf("rxstats call failed with code %d\n", code);
265                 exit(1);
266             }
267             if (code != sizeof(rxstats)) {
268                 if ((((struct rx_debugIn *)(&rxstats))->type ==
269                      RX_DEBUGI_BADTYPE)) goto noRxStats;
270                 printf ("WARNING: returned Rx statistics of unexpected size (got %d)\n",
271                         code);
272                 /* handle other versions?... */
273             }
274
275             rx_PrintTheseStats (stdout, &rxstats, sizeof(rxstats),
276                                 tstats.nFreePackets, tstats.version);
277         }
278     }
279
280     if (!noConns) {
281         if (allconns) {
282             if (!withAllConn) fprintf (stderr, "WARNING: Server doesn't support retrieval of all connections,\n         getting only interesting instead.\n");
283         }
284
285         if (onlyServer) printf ("Showing only server connections\n");
286         if (onlyClient) printf ("Showing only client connections\n");
287         if (onlyAuth != 999) {
288             static char *name[] =
289                 {"unauthenticated", "rxkad_clear", "rxkad_auth", "rxkad_crypt"};
290             printf ("Showing only %s connections\n", name[onlyAuth+1]);
291         }
292         if (onlyHost != -1) {
293             hostAddr.s_addr = onlyHost;
294             printf ("Showing only connections from host %s\n",
295                                     inet_ntoa(hostAddr));
296         }
297         if (onlyPort != -1)
298             printf ("Showing only connections on port %u\n", ntohs(onlyPort));
299
300         for(i=0;;i++) {
301             code = rx_GetServerConnections(s, host, port, &nextconn, allconns,
302                                            supportedDebugValues, &tconn,
303                                            &supportedConnValues);
304             if (code < 0) {
305                 printf("getconn call failed with code %d\n", code);
306                 break;
307             }
308             if (tconn.cid == 0xffffffff) {
309                 printf("Done.\n");
310                 break;
311             }
312
313             /* see if we're in nodally mode and all calls are dallying */
314             if (nodally) {
315                 flag = 0;
316                 for(j=0;j<RX_MAXCALLS;j++) {
317                     if (tconn.callState[j] != RX_STATE_NOTINIT &&
318                         tconn.callState[j] != RX_STATE_DALLY) {
319                         flag = 1;
320                         break;
321                     }
322                 }
323                 if (flag == 0) {
324                     /* this call looks too ordinary, bump skipped count and go
325                      * around again */
326                     dallyCounter++;
327                     continue;
328                 }
329             }
330             if ((onlyHost != -1) && (onlyHost != tconn.host)) continue;
331             if ((onlyPort != -1) && (onlyPort != tconn.port)) continue;
332             if (onlyServer && (tconn.type != RX_SERVER_CONNECTION)) continue;
333             if (onlyClient && (tconn.type != RX_CLIENT_CONNECTION)) continue;
334             if (onlyAuth != 999) {
335                 if (onlyAuth == -1) {
336                     if (tconn.securityIndex != 0) continue;
337                 } else {
338                     if (tconn.securityIndex != 2) continue;
339                     if (withSecStats && (tconn.secStats.type == 3) &&
340                         (tconn.secStats.level != onlyAuth)) continue;
341                 }
342             }
343
344             /* now display the connection */
345             hostAddr.s_addr = tconn.host;
346             printf("Connection from host %s, port %hu, ",
347                    inet_ntoa(hostAddr), ntohs(tconn.port));
348             if (tconn.epoch)
349                 printf ("Cuid %x/%x", tconn.epoch, tconn.cid);
350             else printf ("cid %x", tconn.cid);
351             if (tconn.error) printf (", error %d", tconn.error);
352             printf("\n  serial %d, ", tconn.serial);
353             printf(" natMTU %d, ", tconn.natMTU);
354
355             if (tconn.flags) {
356                 printf ("flags");
357                 if (tconn.flags & RX_CONN_MAKECALL_WAITING)
358                     printf(" MAKECALL_WAITING");
359                 if (tconn.flags & RX_CONN_DESTROY_ME) printf(" DESTROYED");
360                 if (tconn.flags & RX_CONN_USING_PACKET_CKSUM) printf(" pktCksum");
361                 printf (", ");
362             }
363             printf("security index %d, ", tconn.securityIndex);
364             if (tconn.type == RX_CLIENT_CONNECTION) printf("client conn\n");
365             else printf("server conn\n");
366
367             if (withSecStats) {
368                 switch ((int)tconn.secStats.type) {
369                   case 0:
370                     if (tconn.securityIndex == 2)
371                         printf ("  no GetStats procedure for security object\n");
372                     break;
373                   case 1:
374                     printf ("  rxnull level=%d, flags=%d\n",
375                             tconn.secStats.level, tconn.secStats.flags);
376                     break;
377                   case 2:
378                     printf ("  rxvab level=%d, flags=%d\n",
379                             tconn.secStats.level, tconn.secStats.flags);
380                     break;
381                   case 3: {
382                       char *level;
383                       char flags = tconn.secStats.flags;
384                       if (tconn.secStats.level == 0) level = "clear";
385                       else if (tconn.secStats.level == 1) level = "auth";
386                       else if (tconn.secStats.level == 2) level = "crypt";
387                       else level = "unknown";
388                       printf ("  rxkad: level %s", level);
389                       if (flags) printf (", flags");
390                       if (flags & 1) printf (" unalloc");
391                       if (flags & 2) printf (" authenticated");
392                       if (flags & 4) printf (" expired");
393                       if (flags & 8) printf (" pktCksum");
394                       if (tconn.secStats.expires)
395                           /* Apparently due to a bug in the RT compiler that
396                            * prevents (afs_uint32)0xffffffff => (double) from working,
397                            * this code produces negative lifetimes when run on the
398                            * RT. */
399                           printf (", expires in %.1f hours",
400                                   ((afs_uint32)tconn.secStats.expires -
401                                    time(0)) / 3600.0);
402                       if (!(flags & 1)) {
403                           printf ("\n  Received %d bytes in %d packets\n", 
404                                   tconn.secStats.bytesReceived,
405                                   tconn.secStats.packetsReceived);
406                           printf ("  Sent %d bytes in %d packets\n", 
407                                   tconn.secStats.bytesSent,
408                                   tconn.secStats.packetsSent);
409                       } else printf ("\n");
410                       break;
411                   }
412                       
413                   default: printf("  unknown\n");
414                 }
415             }
416
417             for(j=0;j<RX_MAXCALLS;j++) {
418                 printf("    call %d: # %d, state ", j, tconn.callNumber[j]);
419                 if (tconn.callState[j]==RX_STATE_NOTINIT) {
420                     printf("not initialized\n");
421                     continue;
422                 }
423                 else if (tconn.callState[j]==RX_STATE_PRECALL)
424                     printf("precall, ");
425                 else if (tconn.callState[j] == RX_STATE_ACTIVE)
426                     printf("active, ");
427                 else if (tconn.callState[j] == RX_STATE_DALLY)
428                     printf("dally, ");
429                 else if (tconn.callState[j] == RX_STATE_HOLD)
430                     printf("hold, ");
431                 printf("mode: ");
432                 if (tconn.callMode[j]==RX_MODE_SENDING)
433                     printf("sending");
434                 else if (tconn.callMode[j]==RX_MODE_RECEIVING)
435                     printf("receiving");
436                 else if (tconn.callMode[j]==RX_MODE_ERROR)
437                     printf("error");
438                 else if (tconn.callMode[j] == RX_MODE_EOF)
439                     printf("eof");
440                 else printf("unknown");
441                 if (tconn.callFlags[j]) {
442                     printf(", flags:");
443                     if (tconn.callFlags[j]&RX_CALL_READER_WAIT)
444                         printf(" reader_wait");
445                     if (tconn.callFlags[j]&RX_CALL_WAIT_WINDOW_ALLOC)
446                         printf(" window_alloc");
447                     if (tconn.callFlags[j]&RX_CALL_WAIT_WINDOW_SEND)
448                         printf(" window_send");
449                     if (tconn.callFlags[j]&RX_CALL_WAIT_PACKETS)
450                         printf(" wait_packets");
451                     if (tconn.callFlags[j]&RX_CALL_WAIT_PROC)
452                         printf(" waiting_for_process");
453                     if (tconn.callFlags[j]&RX_CALL_RECEIVE_DONE)
454                         printf(" receive_done");
455                     if (tconn.callFlags[j]&RX_CALL_CLEARED)
456                         printf(" call_cleared");
457                 }
458                 if (tconn.callOther[j] & RX_OTHER_IN)
459                     printf(", has_input_packets");
460                 if (tconn.callOther[j] & RX_OTHER_OUT)
461                     printf(", has_output_packets");
462                 printf("\n");
463             }
464         }
465         if (nodally) printf("Skipped %d dallying connections.\n", dallyCounter);
466     }
467     if (showPeers && withPeers) {
468         for(i=0;;i++) {
469             struct rx_debugPeer tpeer;
470             code = rx_GetServerPeers(s, host, port, &nextpeer, allconns, &tpeer, &supportedPeerValues);
471             if (code < 0) {
472                 printf("getpeer call failed with code %d\n", code);
473                 break;
474             }
475             if (tpeer.host == 0xffffffff) {
476                 printf("Done.\n");
477                 break;
478             }
479
480             if ((onlyHost != -1) && (onlyHost != tpeer.host)) continue;
481             if ((onlyPort != -1) && (onlyPort != tpeer.port)) continue;
482
483             /* now display the peer */
484             hostAddr.s_addr = tpeer.host;
485             printf("Peer at host %s, port %hu\n",
486                    inet_ntoa(hostAddr), ntohs(tpeer.port));
487             printf("\tifMTU %hu\tnatMTU %hu\tmaxMTU %hu\n",
488                    tpeer.ifMTU, tpeer.natMTU, tpeer.maxMTU);
489             printf("\tpackets sent %d\tpacket resends %d\n",
490                    tpeer.nSent, tpeer.reSends);
491             printf("\tbytes sent high %d low %d\n",
492                    tpeer.bytesSent.high, tpeer.bytesSent.low);
493             printf("\tbytes received high %d low %d\n",
494                    tpeer.bytesReceived.high, tpeer.bytesReceived.low);
495             printf("\trtt %d msec, rtt_dev %d msec\n",
496                    tpeer.rtt >> 3, tpeer.rtt_dev >> 2);
497             printf("\ttimeout %d.%03d sec\n",
498                    tpeer.timeout.sec, tpeer.timeout.usec / 1000);
499         }
500     }
501     exit(0);
502 }
503
504 /* simple main program */
505 #ifndef AFS_NT40_ENV
506 #include "AFS_component_version_number.c"
507 #endif
508 int main(argc, argv)
509 int argc;
510 char **argv;
511 {
512     struct cmd_syndesc *ts;
513
514 #ifdef AFS_NT40_ENV
515     if (afs_winsockInit()<0) {
516         printf("%s: Couldn't initialize winsock. Exiting...\n", argv[0]);
517         return 1;
518     }
519 #endif
520
521     ts = cmd_CreateSyntax((char *) 0, MainCommand, 0, "probe RX server");
522     cmd_AddParm(ts, "-servers", CMD_SINGLE, CMD_REQUIRED, "server machine");
523     cmd_AddParm(ts, "-port", CMD_SINGLE, CMD_OPTIONAL, "IP port");
524     cmd_AddParm(ts, "-nodally", CMD_FLAG, CMD_OPTIONAL,
525                 "don't show dallying conns");
526     cmd_AddParm(ts, "-allconnections", CMD_FLAG, CMD_OPTIONAL,
527                 "don't filter out uninteresting connections on server");
528     cmd_AddParm(ts, "-rxstats", CMD_FLAG, CMD_OPTIONAL, "show Rx statistics");
529     cmd_AddParm(ts, "-onlyserver", CMD_FLAG, CMD_OPTIONAL,
530                 "only show server conns");
531     cmd_AddParm(ts, "-onlyclient", CMD_FLAG, CMD_OPTIONAL,
532                 "only show client conns");
533     cmd_AddParm(ts, "-onlyport", CMD_SINGLE, CMD_OPTIONAL, "show only <port>");
534     cmd_AddParm(ts, "-onlyhost", CMD_SINGLE, CMD_OPTIONAL, "show only <host>");
535     cmd_AddParm(ts, "-onlyauth", CMD_SINGLE, CMD_OPTIONAL,
536                 "show only <auth level>");
537
538     cmd_AddParm(ts,"-version",CMD_FLAG,CMD_OPTIONAL,"show AFS version id");
539     cmd_AddParm(ts,"-noconns",CMD_FLAG,CMD_OPTIONAL,"show no connections");
540     cmd_AddParm(ts,"-peers",CMD_FLAG,CMD_OPTIONAL,"show peers");
541
542     cmd_Dispatch(argc, argv);
543     exit(0);
544 }