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