LATER... ei_kerberos_kdc_session_key ...
[wireshark-sm.git] / ui / cli / tap-rpcprogs.c
blob28ad353cd70d84b7babc6d0dad2521e725490cdc
1 /* tap-rpcprogs.c
2 * rpcstat 2002 Ronnie Sahlberg
4 * Wireshark - Network traffic analyzer
5 * By Gerald Combs <gerald@wireshark.org>
6 * Copyright 1998 Gerald Combs
8 * SPDX-License-Identifier: GPL-2.0-or-later
9 */
11 /* This module provides rpc call/reply SRT statistics to tshark.
12 * It is only used by tshark and not wireshark
15 #include "config.h"
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <string.h>
21 #include <glib.h>
23 #include <epan/packet_info.h>
24 #include <epan/tap.h>
25 #include <epan/stat_tap_ui.h>
26 #include <epan/dissectors/packet-rpc.h>
28 #include <wsutil/cmdarg_err.h>
30 #define MICROSECS_PER_SEC 1000000
31 #define NANOSECS_PER_SEC 1000000000
33 void register_tap_listener_rpcprogs(void);
35 /* used to keep track of statistics for a specific program/version */
36 typedef struct _rpc_program_t {
37 struct _rpc_program_t *next;
38 uint32_t program;
39 uint32_t version;
40 int num;
41 nstime_t min;
42 nstime_t max;
43 nstime_t tot;
44 } rpc_program_t;
46 static rpc_program_t *prog_list;
47 static int already_enabled;
49 static tap_packet_status
50 rpcprogs_packet(void *dummy1 _U_, packet_info *pinfo, epan_dissect_t *edt _U_, const void *pri, tap_flags_t flags _U_)
52 const rpc_call_info_value *ri = (const rpc_call_info_value *)pri;
53 nstime_t delta;
54 rpc_program_t *rp = NULL;
56 if (!prog_list) {
57 /* the list was empty */
58 rp = g_new(rpc_program_t, 1);
59 rp->next = NULL;
60 rp->program = ri->prog;
61 rp->version = ri->vers;
62 rp->num = 0;
63 rp->min.secs = 0;
64 rp->min.nsecs = 0;
65 rp->max.secs = 0;
66 rp->max.nsecs = 0;
67 rp->tot.secs = 0;
68 rp->tot.nsecs = 0;
69 prog_list = rp;
70 } else if ((ri->prog == prog_list->program)
71 && (ri->vers == prog_list->version)) {
72 rp = prog_list;
73 } else if ( (ri->prog < prog_list->program)
74 || ((ri->prog == prog_list->program) && (ri->vers < prog_list->version))) {
75 /* we should be first entry in list */
76 rp = g_new(rpc_program_t, 1);
77 rp->next = prog_list;
78 rp->program = ri->prog;
79 rp->version = ri->vers;
80 rp->num = 0;
81 rp->min.secs = 0;
82 rp->min.nsecs = 0;
83 rp->max.secs = 0;
84 rp->max.nsecs = 0;
85 rp->tot.secs = 0;
86 rp->tot.nsecs = 0;
87 prog_list = rp;
88 } else {
89 /* we go somewhere else in the list */
90 for (rp=prog_list; rp; rp=rp->next) {
91 if ((rp->next)
92 && (rp->next->program == ri->prog)
93 && (rp->next->version == ri->vers)) {
94 rp = rp->next;
95 break;
97 if ((!rp->next)
98 || (rp->next->program > ri->prog)
99 || ( (rp->next->program == ri->prog)
100 && (rp->next->version > ri->vers))) {
101 rpc_program_t *trp;
102 trp = g_new(rpc_program_t, 1);
103 trp->next = rp->next;
104 trp->program = ri->prog;
105 trp->version = ri->vers;
106 trp->num = 0;
107 trp->min.secs = 0;
108 trp->min.nsecs = 0;
109 trp->max.secs = 0;
110 trp->max.nsecs = 0;
111 trp->tot.secs = 0;
112 trp->tot.nsecs = 0;
113 rp->next = trp;
114 rp = trp;
115 break;
121 /* we are only interested in reply packets */
122 if (ri->request || !rp) {
123 return TAP_PACKET_DONT_REDRAW;
126 /* calculate time delta between request and reply */
127 nstime_delta(&delta, &pinfo->abs_ts, &ri->req_time);
129 if ((rp->max.secs == 0)
130 && (rp->max.nsecs == 0) ) {
131 rp->max.secs = delta.secs;
132 rp->max.nsecs = delta.nsecs;
135 if ((rp->min.secs == 0)
136 && (rp->min.nsecs == 0) ) {
137 rp->min.secs = delta.secs;
138 rp->min.nsecs = delta.nsecs;
141 if ( (delta.secs < rp->min.secs)
142 || ( (delta.secs == rp->min.secs)
143 && (delta.nsecs < rp->min.nsecs) ) ) {
144 rp->min.secs = delta.secs;
145 rp->min.nsecs = delta.nsecs;
148 if ( (delta.secs > rp->max.secs)
149 || ( (delta.secs == rp->max.secs)
150 && (delta.nsecs > rp->max.nsecs) ) ) {
151 rp->max.secs = delta.secs;
152 rp->max.nsecs = delta.nsecs;
155 rp->tot.secs += delta.secs;
156 rp->tot.nsecs += delta.nsecs;
157 if (rp->tot.nsecs > NANOSECS_PER_SEC) {
158 rp->tot.nsecs -= NANOSECS_PER_SEC;
159 rp->tot.secs++;
161 rp->num++;
163 return TAP_PACKET_REDRAW;
167 static void
168 rpcprogs_draw(void *dummy _U_)
170 uint64_t td;
171 rpc_program_t *rp;
172 char str[64];
174 printf("\n");
175 printf("==========================================================\n");
176 printf("ONC-RPC Program Statistics:\n");
177 printf("Program Version Calls Min SRT Max SRT Avg SRT\n");
178 for (rp = prog_list;rp;rp = rp->next) {
179 /* Only display procs with non-zero calls */
180 if (rp->num == 0) {
181 continue;
183 /* Scale the average SRT in units of 1us and round to the nearest us. */
184 td = ((uint64_t)(rp->tot.secs)) * NANOSECS_PER_SEC + rp->tot.nsecs;
185 td = ((td / rp->num) + 500) / 1000;
187 snprintf(str, sizeof(str), "%s(%d)", rpc_prog_name(rp->program), rp->program);
188 printf("%-15s %2u %6d %3d.%06d %3d.%06d %3" PRIu64 ".%06" PRIu64 "\n",
189 str,
190 rp->version,
191 rp->num,
192 (int)(rp->min.secs), (rp->min.nsecs+500)/1000,
193 (int)(rp->max.secs), (rp->max.nsecs+500)/1000,
194 td/MICROSECS_PER_SEC, td%MICROSECS_PER_SEC
197 printf("===================================================================\n");
201 static void
202 rpcprogs_init(const char *opt_arg _U_, void *userdata _U_)
204 GString *error_string;
206 if (already_enabled) {
207 return;
209 already_enabled = 1;
211 error_string = register_tap_listener("rpc", NULL, NULL, 0, NULL, rpcprogs_packet, rpcprogs_draw, NULL);
212 if (error_string) {
213 cmdarg_err("Couldn't register rpc,programs tap: %s",
214 error_string->str);
215 g_string_free(error_string, TRUE);
216 exit(1);
220 static stat_tap_ui rpcprogs_ui = {
221 REGISTER_STAT_GROUP_GENERIC,
222 NULL,
223 "rpc,programs",
224 rpcprogs_init,
226 NULL
229 void
230 register_tap_listener_rpcprogs(void)
232 register_stat_tap_ui(&rpcprogs_ui, NULL);
236 * Editor modelines - https://www.wireshark.org/tools/modelines.html
238 * Local variables:
239 * c-basic-offset: 8
240 * tab-width: 8
241 * indent-tabs-mode: t
242 * End:
244 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
245 * :indentSize=8:tabSize=8:noTabs=false: