Kerberos: add kerberos_inject_longterm_key() helper function
[wireshark-sm.git] / ui / qt / rpc_service_response_time_dialog.cpp
blobfa5caf30fdf05eb6cf488404a3d9c2e05be52cc9
1 /* rpc_service_response_time_dialog.cpp
3 * Wireshark - Network traffic analyzer
4 * By Gerald Combs <gerald@wireshark.org>
5 * Copyright 1998 Gerald Combs
7 * SPDX-License-Identifier: GPL-2.0-or-later
8 */
10 // warning C4267: 'argument' : conversion from 'size_t' to 'int', possible loss of data
11 #ifdef _MSC_VER
12 #pragma warning(push)
13 #pragma warning(disable : 4267)
14 #endif
16 #include "rpc_service_response_time_dialog.h"
18 #include <algorithm>
19 #include <stdio.h>
21 #include <epan/dissectors/packet-dcerpc.h>
22 #include <epan/dissectors/packet-rpc.h>
23 #include <epan/guid-utils.h>
24 #include <epan/srt_table.h>
26 #include <ui/qt/utils/qt_ui_utils.h>
28 #include <QComboBox>
29 #include <QHBoxLayout>
30 #include <QLabel>
32 #ifdef _MSC_VER
33 #pragma warning(pop)
34 #endif
36 // To do:
37 // - Don't assume that the user knows what programs+versions are in the
38 // capture. I.e. combine this dialog with the ONC-RPC Programs dialog,
39 // with two lists: programs on top, procedures on the bottom.
40 // - Allow the display of multiple programs and versions.
41 // - Expose the DCE-RPC UUIDs and ONC-RPC program numbers e.g. in an extra
42 // column.
43 // - Make the version in the command-line args optional?
45 extern "C" {
46 static void
47 dce_rpc_add_program(void *key_ptr, void *value_ptr, void *rsrtd_ptr)
49 RpcServiceResponseTimeDialog *rsrt_dlg = dynamic_cast<RpcServiceResponseTimeDialog *>((RpcServiceResponseTimeDialog *)rsrtd_ptr);
50 if (!rsrt_dlg) return;
52 guid_key *key = (guid_key *)key_ptr;
53 dcerpc_uuid_value *value = (dcerpc_uuid_value *)value_ptr;
55 rsrt_dlg->addDceRpcProgram(key, value);
58 static void
59 dce_rpc_find_versions(void *key_ptr, void *, void *rsrtd_ptr)
61 RpcServiceResponseTimeDialog *rsrt_dlg = dynamic_cast<RpcServiceResponseTimeDialog *>((RpcServiceResponseTimeDialog *)rsrtd_ptr);
62 if (!rsrt_dlg) return;
64 guid_key *key = (guid_key *)key_ptr;
65 rsrt_dlg->addDceRpcProgramVersion(key);
68 static void
69 onc_rpc_add_program(void *prog_ptr, void *value_ptr, void *rsrtd_ptr)
71 RpcServiceResponseTimeDialog *rsrt_dlg = dynamic_cast<RpcServiceResponseTimeDialog *>((RpcServiceResponseTimeDialog *)rsrtd_ptr);
72 if (!rsrt_dlg) return;
74 uint32_t program = GPOINTER_TO_UINT(prog_ptr);
75 rpc_prog_info_value *value = (rpc_prog_info_value *) value_ptr;
77 rsrt_dlg->addOncRpcProgram(program, value);
80 static void
81 onc_rpc_find_versions(const char *, ftenum_t , void *rpik_ptr, void *, void *rsrtd_ptr)
83 RpcServiceResponseTimeDialog *rsrt_dlg = dynamic_cast<RpcServiceResponseTimeDialog *>((RpcServiceResponseTimeDialog *)rsrtd_ptr);
84 if (!rsrt_dlg) return;
86 rpc_proc_info_key *rpik = (rpc_proc_info_key *)rpik_ptr;
88 rsrt_dlg->addOncRpcProgramVersion(rpik->prog, rpik->vers);
91 static void
92 onc_rpc_count_procedures(const char *, ftenum_t , void *rpik_ptr, void *, void *rsrtd_ptr)
94 RpcServiceResponseTimeDialog *rsrt_dlg = dynamic_cast<RpcServiceResponseTimeDialog *>((RpcServiceResponseTimeDialog *)rsrtd_ptr);
95 if (!rsrt_dlg) return;
97 rpc_proc_info_key *rpik = (rpc_proc_info_key *)rpik_ptr;
99 rsrt_dlg->updateOncRpcProcedureCount(rpik->prog, rpik->vers, rpik->proc);
102 } // extern "C"
104 RpcServiceResponseTimeDialog::RpcServiceResponseTimeDialog(QWidget &parent, CaptureFile &cf, struct register_srt *srt, RpcFamily dlg_type, const QString filter) :
105 ServiceResponseTimeDialog(parent, cf, srt, filter),
106 dlg_type_(dlg_type)
108 setRetapOnShow(false);
109 setHint(tr("<small><i>Select a program and version and enter a filter if desired, then press Apply.</i></small>"));
111 QHBoxLayout *filter_layout = filterLayout();
112 program_combo_ = new QComboBox(this);
113 version_combo_ = new QComboBox(this);
115 filter_layout->insertStretch(0, 1);
116 filter_layout->insertWidget(0, version_combo_);
117 filter_layout->insertWidget(0, new QLabel(tr("Version:")));
118 filter_layout->insertWidget(0, program_combo_);
119 filter_layout->insertWidget(0, new QLabel(tr("Program:")));
121 if (dlg_type == DceRpc) {
122 setWindowSubtitle(tr("DCE-RPC Service Response Times"));
123 g_hash_table_foreach(dcerpc_uuids, dce_rpc_add_program, this);
124 // This is a loooooong list. The GTK+ UI addresses this by making
125 // the program combo a tree instead of a list. We might want to add a
126 // full-height list to the left of the stats tree instead.
127 QStringList programs = dce_name_to_uuid_key_.keys();
128 std::sort(programs.begin(), programs.end(), qStringCaseLessThan);
129 connect(program_combo_, SIGNAL(currentTextChanged(const QString)),
130 this, SLOT(dceRpcProgramChanged(const QString)));
131 program_combo_->addItems(programs);
132 } else {
133 setWindowSubtitle(tr("ONC-RPC Service Response Times"));
134 g_hash_table_foreach(rpc_progs, onc_rpc_add_program, this);
135 QStringList programs = onc_name_to_program_.keys();
136 std::sort(programs.begin(), programs.end(), qStringCaseLessThan);
137 connect(program_combo_, SIGNAL(currentTextChanged(const QString)),
138 this, SLOT(oncRpcProgramChanged(const QString)));
139 program_combo_->addItems(programs);
143 TapParameterDialog *RpcServiceResponseTimeDialog::createDceRpcSrtDialog(QWidget &parent, const QString, const QString opt_arg, CaptureFile &cf)
145 QString filter;
146 bool have_args = false;
147 QString program_name;
148 e_guid_t uuid;
149 int version = 0;
151 // dcerpc,srt,<uuid>,<major version>.<minor version>[,<filter>]
152 QStringList args_l = QString(opt_arg).split(',');
153 if (args_l.length() > 1) {
154 // XXX Switch to QUuid.
155 unsigned d1, d2, d3, d4_0, d4_1, d4_2, d4_3, d4_4, d4_5, d4_6, d4_7;
156 if (sscanf(args_l[0].toUtf8().constData(),
157 "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
158 &d1, &d2, &d3,
159 &d4_0, &d4_1, &d4_2, &d4_3, &d4_4, &d4_5, &d4_6, &d4_7) == 11) {
160 uuid.data1 = d1;
161 uuid.data2 = d2;
162 uuid.data3 = d3;
163 uuid.data4[0] = d4_0;
164 uuid.data4[1] = d4_1;
165 uuid.data4[2] = d4_2;
166 uuid.data4[3] = d4_3;
167 uuid.data4[4] = d4_4;
168 uuid.data4[5] = d4_5;
169 uuid.data4[6] = d4_6;
170 uuid.data4[7] = d4_7;
171 } else {
172 program_name = args_l[0];
174 version = args_l[1].split('.')[0].toInt();
175 if (args_l.length() > 2) {
176 filter = QStringList(args_l.mid(2)).join(",");
178 have_args = true;
180 RpcServiceResponseTimeDialog *dce_rpc_dlg = new RpcServiceResponseTimeDialog(parent, cf, get_srt_table_by_name("dcerpc"), DceRpc, filter);
182 if (have_args) {
183 if (program_name.isEmpty()) {
184 dce_rpc_dlg->setDceRpcUuidAndVersion(&uuid, version);
185 } else {
186 dce_rpc_dlg->setRpcNameAndVersion(program_name, version);
189 // Else the GTK+ UI throws an error.
191 return dce_rpc_dlg;
194 TapParameterDialog *RpcServiceResponseTimeDialog::createOncRpcSrtDialog(QWidget &parent, const QString, const QString opt_arg, CaptureFile &cf)
196 QString filter;
197 bool have_args = false;
198 QString program_name;
199 int program_num = 0;
200 int version = 0;
202 // rpc,srt,<program>,<version>[,<filter>
203 QStringList args_l = QString(opt_arg).split(',');
204 if (args_l.length() > 1) {
205 bool ok = false;
206 program_num = args_l[0].toInt(&ok);
207 if (!ok) {
208 program_name = args_l[0];
210 version = args_l[1].toInt();
211 if (args_l.length() > 2) {
212 filter = QStringList(args_l.mid(2)).join(",");
214 have_args = true;
217 RpcServiceResponseTimeDialog *onc_rpc_dlg = new RpcServiceResponseTimeDialog(parent, cf, get_srt_table_by_name("rpc"), OncRpc, filter);
219 if (have_args) {
220 if (program_name.isEmpty()) {
221 onc_rpc_dlg->setOncRpcProgramAndVersion(program_num, version);
222 } else {
223 onc_rpc_dlg->setRpcNameAndVersion(program_name, version);
226 // Else the GTK+ UI throws an error.
228 return onc_rpc_dlg;
231 void RpcServiceResponseTimeDialog::addDceRpcProgram(_guid_key *key, _dcerpc_uuid_value *value)
233 dce_name_to_uuid_key_.insert(value->name, key);
236 void RpcServiceResponseTimeDialog::addDceRpcProgramVersion(_guid_key *key)
238 if (guid_cmp(&(dce_name_to_uuid_key_[program_combo_->currentText()]->guid), &(key->guid))) return;
240 versions_ << key->ver;
241 std::sort(versions_.begin(), versions_.end());
244 void RpcServiceResponseTimeDialog::addOncRpcProgram(uint32_t program, _rpc_prog_info_value *value)
246 onc_name_to_program_.insert(value->progname, program);
249 void RpcServiceResponseTimeDialog::addOncRpcProgramVersion(uint32_t program, uint32_t version)
251 if (onc_name_to_program_[program_combo_->currentText()] != program) return;
253 if (versions_.isEmpty()) {
254 versions_ << version;
255 return;
257 while (version < versions_.first()) {
258 versions_.prepend(versions_.first() - 1);
260 while (version > versions_.last()) {
261 versions_.append(versions_.last() + 1);
265 void RpcServiceResponseTimeDialog::updateOncRpcProcedureCount(uint32_t program, uint32_t version, int procedure)
267 if (onc_name_to_program_[program_combo_->currentText()] != program) return;
268 if (version_combo_->itemData(version_combo_->currentIndex()).toUInt() != version) return;
270 if (procedure > onc_rpc_num_procedures_) onc_rpc_num_procedures_ = procedure;
273 void RpcServiceResponseTimeDialog::setDceRpcUuidAndVersion(_e_guid_t *uuid, int version)
275 bool found = false;
276 for (int pi = 0; pi < program_combo_->count(); pi++) {
277 if (guid_cmp(uuid, &(dce_name_to_uuid_key_[program_combo_->itemText(pi)]->guid)) == 0) {
278 program_combo_->setCurrentIndex(pi);
280 for (int vi = 0; vi < version_combo_->count(); vi++) {
281 if (version == (int) version_combo_->itemData(vi).toUInt()) {
282 version_combo_->setCurrentIndex(vi);
283 found = true;
284 break;
287 break;
290 if (found) fillTree();
293 void RpcServiceResponseTimeDialog::setOncRpcProgramAndVersion(int program, int version)
295 bool found = false;
296 for (int pi = 0; pi < program_combo_->count(); pi++) {
297 if (program == (int) onc_name_to_program_[program_combo_->itemText(pi)]) {
298 program_combo_->setCurrentIndex(pi);
300 for (int vi = 0; vi < version_combo_->count(); vi++) {
301 if (version == (int) version_combo_->itemData(vi).toUInt()) {
302 version_combo_->setCurrentIndex(vi);
303 found = true;
304 break;
307 break;
310 if (found) fillTree();
313 void RpcServiceResponseTimeDialog::setRpcNameAndVersion(const QString &program_name, int version)
315 bool found = false;
316 for (int pi = 0; pi < program_combo_->count(); pi++) {
317 if (program_name.compare(program_combo_->itemText(pi), Qt::CaseInsensitive) == 0) {
318 program_combo_->setCurrentIndex(pi);
320 for (int vi = 0; vi < version_combo_->count(); vi++) {
321 if (version == (int) version_combo_->itemData(vi).toUInt()) {
322 version_combo_->setCurrentIndex(vi);
323 found = true;
324 break;
327 break;
330 if (found) fillTree();
333 void RpcServiceResponseTimeDialog::dceRpcProgramChanged(const QString &program_name)
335 clearVersionCombo();
337 if (!dce_name_to_uuid_key_.contains(program_name)) return;
339 g_hash_table_foreach(dcerpc_uuids, dce_rpc_find_versions, this);
341 fillVersionCombo();
344 void RpcServiceResponseTimeDialog::oncRpcProgramChanged(const QString &program_name)
346 clearVersionCombo();
348 if (!onc_name_to_program_.contains(program_name)) return;
350 dissector_table_foreach ("rpc.call", onc_rpc_find_versions, this);
351 dissector_table_foreach ("rpc.reply", onc_rpc_find_versions, this);
353 fillVersionCombo();
356 void RpcServiceResponseTimeDialog::clearVersionCombo()
358 version_combo_->clear();
359 versions_.clear();
362 void RpcServiceResponseTimeDialog::fillVersionCombo()
364 foreach (unsigned version, versions_) {
365 version_combo_->addItem(QString::number(version), version);
367 if (versions_.count() > 0) {
368 // Select the highest-numbered version.
369 version_combo_->setCurrentIndex(static_cast<int>(versions_.count()) - 1);
373 void RpcServiceResponseTimeDialog::provideParameterData()
375 void *tap_data = NULL;
376 const QString program_name = program_combo_->currentText();
377 uint32_t max_procs = 0;
379 switch (dlg_type_) {
380 case DceRpc:
382 if (!dce_name_to_uuid_key_.contains(program_name)) return;
384 guid_key *dkey = dce_name_to_uuid_key_[program_name];
385 uint16_t version = (uint16_t) version_combo_->itemData(version_combo_->currentIndex()).toUInt();
386 const dcerpc_sub_dissector *procs = dcerpc_get_proto_sub_dissector(&(dkey->guid), version);
387 if (!procs) return;
389 dcerpcstat_tap_data_t *dtap_data = g_new0(dcerpcstat_tap_data_t, 1);
390 dtap_data->uuid = dkey->guid;
391 dtap_data->ver = version;
392 dtap_data->prog = dcerpc_get_proto_name(&dtap_data->uuid, dtap_data->ver);
394 for (int i = 0; procs[i].name; i++) {
395 if (procs[i].num > max_procs) max_procs = procs[i].num;
397 dtap_data->num_procedures = max_procs + 1;
399 tap_data = dtap_data;
400 break;
402 case OncRpc:
404 if (!onc_name_to_program_.contains(program_name)) return;
406 rpcstat_tap_data_t *otap_data = g_new0(rpcstat_tap_data_t, 1);
407 otap_data->program = onc_name_to_program_[program_name];
408 otap_data->prog = rpc_prog_name(otap_data->program);
409 otap_data->version = (uint32_t) version_combo_->itemData(version_combo_->currentIndex()).toUInt();
411 onc_rpc_num_procedures_ = -1;
412 dissector_table_foreach ("rpc.call", onc_rpc_count_procedures, this);
413 dissector_table_foreach ("rpc.reply", onc_rpc_count_procedures, this);
414 otap_data->num_procedures = onc_rpc_num_procedures_ + 1;
416 tap_data = otap_data;
417 break;
421 set_srt_table_param_data(srt_, tap_data);