From 796bf409b0c286dd76e6ecd5c61d0d947d54b479 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Irene=20R=C3=BCngeler?= Date: Fri, 13 Dec 2013 07:25:30 +0000 Subject: Add dialogs and graphs to analyse SCTP behavior similar to the GTK version. svn path=/trunk/; revision=54026 --- epan/dissectors/packet-sctp.c | 7 +- epan/value_string.h | 9 +- ui/gtk/Makefile.common | 1 + ui/qt/CMakeLists.txt | 18 + ui/qt/Makefile.common | 24 ++ ui/qt/QtShark.pro | 24 ++ ui/qt/main_window.h | 5 +- ui/qt/main_window.ui | 18 + ui/qt/main_window_slots.cpp | 56 ++- ui/qt/packet_list.cpp | 20 +- ui/qt/sctp_all_assocs_dialog.cpp | 144 ++++++++ ui/qt/sctp_all_assocs_dialog.h | 52 +++ ui/qt/sctp_all_assocs_dialog.ui | 433 +++++++++++++++++++++++ ui/qt/sctp_assoc_analyse_dialog.cpp | 292 ++++++++++++++++ ui/qt/sctp_assoc_analyse_dialog.h | 66 ++++ ui/qt/sctp_assoc_analyse_dialog.ui | 607 +++++++++++++++++++++++++++++++++ ui/qt/sctp_chunk_statistics_dialog.cpp | 288 ++++++++++++++++ ui/qt/sctp_chunk_statistics_dialog.h | 75 ++++ ui/qt/sctp_chunk_statistics_dialog.ui | 160 +++++++++ ui/qt/sctp_graph_arwnd_dialog.cpp | 141 ++++++++ ui/qt/sctp_graph_arwnd_dialog.h | 57 ++++ ui/qt/sctp_graph_arwnd_dialog.ui | 129 +++++++ ui/qt/sctp_graph_byte_dialog.cpp | 145 ++++++++ ui/qt/sctp_graph_byte_dialog.h | 55 +++ ui/qt/sctp_graph_byte_dialog.ui | 129 +++++++ ui/qt/sctp_graph_dialog.cpp | 399 ++++++++++++++++++++++ ui/qt/sctp_graph_dialog.h | 114 +++++++ ui/qt/sctp_graph_dialog.ui | 177 ++++++++++ ui/tap-sctp-analysis.c | 216 +----------- ui/tap-sctp-analysis.h | 52 ++- 30 files changed, 3698 insertions(+), 215 deletions(-) create mode 100644 ui/qt/sctp_all_assocs_dialog.cpp create mode 100644 ui/qt/sctp_all_assocs_dialog.h create mode 100644 ui/qt/sctp_all_assocs_dialog.ui create mode 100644 ui/qt/sctp_assoc_analyse_dialog.cpp create mode 100644 ui/qt/sctp_assoc_analyse_dialog.h create mode 100644 ui/qt/sctp_assoc_analyse_dialog.ui create mode 100644 ui/qt/sctp_chunk_statistics_dialog.cpp create mode 100644 ui/qt/sctp_chunk_statistics_dialog.h create mode 100644 ui/qt/sctp_chunk_statistics_dialog.ui create mode 100644 ui/qt/sctp_graph_arwnd_dialog.cpp create mode 100644 ui/qt/sctp_graph_arwnd_dialog.h create mode 100644 ui/qt/sctp_graph_arwnd_dialog.ui create mode 100644 ui/qt/sctp_graph_byte_dialog.cpp create mode 100644 ui/qt/sctp_graph_byte_dialog.h create mode 100644 ui/qt/sctp_graph_byte_dialog.ui create mode 100644 ui/qt/sctp_graph_dialog.cpp create mode 100644 ui/qt/sctp_graph_dialog.h create mode 100644 ui/qt/sctp_graph_dialog.ui diff --git a/epan/dissectors/packet-sctp.c b/epan/dissectors/packet-sctp.c index edfa689660..717d132f8c 100644 --- a/epan/dissectors/packet-sctp.c +++ b/epan/dissectors/packet-sctp.c @@ -4671,11 +4671,11 @@ proto_register_sctp(void) UAT_FLD_VS(type_fields, type_enable, "Visibility", chunk_enabled, "Hide or show the type in the chunk statistics"), UAT_END_FIELDS }; - + module_t *sctp_module; expert_module_t* expert_sctp; uat_t* chunk_types_uat; - + chunk_types_uat = uat_new("Chunk types for the statistics dialog", sizeof(type_field_t), "statistics_chunk_types", @@ -4689,8 +4689,7 @@ proto_register_sctp(void) sctp_chunk_type_free_cb, NULL, custom_types_uat_fields - ); - +); /* Register the protocol name and description */ proto_sctp = proto_register_protocol("Stream Control Transmission Protocol", "SCTP", "sctp"); diff --git a/epan/value_string.h b/epan/value_string.h index d5326a2776..c83aa73b24 100644 --- a/epan/value_string.h +++ b/epan/value_string.h @@ -25,6 +25,10 @@ #ifndef __VALUE_STRING_H__ #define __VALUE_STRING_H__ +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + #include #include "ws_symbol_export.h" @@ -250,8 +254,11 @@ WS_DLL_LOCAL const gchar * value_string_ext_match_type_str(const value_string_ext *vse); -#endif /* __VALUE_STRING_H__ */ +#ifdef __cplusplus +} +#endif /* __cplusplus */ +#endif /* __VALUE_STRING_H__ */ /* * Editor modelines - http://www.wireshark.org/tools/modelines.html diff --git a/ui/gtk/Makefile.common b/ui/gtk/Makefile.common index 0012d17885..aa41da4518 100644 --- a/ui/gtk/Makefile.common +++ b/ui/gtk/Makefile.common @@ -220,6 +220,7 @@ WIRESHARK_TAP_SRC = \ sctp_assoc_analyse.c \ sctp_chunk_stat.c \ sctp_chunk_stat_dlg.c \ + sctp_stat.c \ sctp_stat_dlg.c \ sip_stat.c \ smb_stat.c \ diff --git a/ui/qt/CMakeLists.txt b/ui/qt/CMakeLists.txt index 7a3686fe34..807f7b775c 100644 --- a/ui/qt/CMakeLists.txt +++ b/ui/qt/CMakeLists.txt @@ -70,6 +70,12 @@ set(WIRESHARK_QT_HEADERS proto_tree.h qcustomplot.h recent_file_status.h + sctp_all_assocs_dialog.h + sctp_assoc_analyse_dialog.h + sctp_chunk_statistics_dialog.h + sctp_graph_dialog.h + sctp_graph_arwnd_dialog.h + sctp_graph_byte_dialog.h search_frame.h sequence_diagram.h sequence_dialog.h @@ -141,6 +147,12 @@ set(WIRESHARK_QT_SRC qt_ui_utils.cpp recent_file_status.cpp related_packet_delegate.cpp + sctp_all_assocs_dialog.cpp + sctp_assoc_analyse_dialog.cpp + sctp_chunk_statistics_dialog.cpp + sctp_graph_dialog.cpp + sctp_graph_arwnd_dialog.cpp + sctp_graph_byte_dialog.cpp search_frame.cpp sequence_diagram.cpp sequence_dialog.cpp @@ -190,6 +202,12 @@ set(WIRESHARK_QT_UI preferences_dialog.ui print_dialog.ui profile_dialog.ui + sctp_all_assocs_dialog.ui + sctp_assoc_analyse_dialog.ui + sctp_chunk_statistics_dialog.ui + sctp_graph_dialog.ui + sctp_graph_arwnd_dialog.ui + sctp_graph_byte_dialog.ui search_frame.ui sequence_dialog.ui splash_overlay.ui diff --git a/ui/qt/Makefile.common b/ui/qt/Makefile.common index 340f2feba6..0c2ed5d740 100644 --- a/ui/qt/Makefile.common +++ b/ui/qt/Makefile.common @@ -52,6 +52,12 @@ NODIST_GENERATED_HEADER_FILES = \ ui_preferences_dialog.h \ ui_print_dialog.h \ ui_profile_dialog.h \ + ui_sctp_all_assocs_dialog.h \ + ui_sctp_assoc_analyse_dialog.h \ + ui_sctp_chunk_statistics_dialog.h \ + ui_sctp_graph_dialog.h \ + ui_sctp_graph_arwnd_dialog.h \ + ui_sctp_graph_byte_dialog.h \ ui_stats_tree_dialog.h \ ui_search_frame.h \ ui_sequence_dialog.h \ @@ -143,6 +149,12 @@ MOC_HDRS = \ recent_file_status.h \ related_packet_delegate.h \ search_frame.h \ + sctp_all_assocs_dialog.h \ + sctp_assoc_analyse_dialog.h \ + sctp_chunk_statistics_dialog.h \ + sctp_graph_dialog.h \ + sctp_graph_arwnd_dialog.h \ + sctp_graph_byte_dialog.h \ sequence_diagram.h \ sequence_dialog.h \ simple_dialog_qt.h \ @@ -182,6 +194,12 @@ UI_FILES = \ preferences_dialog.ui \ print_dialog.ui \ profile_dialog.ui \ + sctp_all_assocs_dialog.ui \ + sctp_assoc_analyse_dialog.ui \ + sctp_chunk_statistics_dialog.ui \ + sctp_graph_dialog.ui \ + sctp_graph_arwnd_dialog.ui \ + sctp_graph_byte_dialog.ui \ search_frame.ui \ sequence_dialog.ui \ splash_overlay.ui \ @@ -291,6 +309,12 @@ WIRESHARK_QT_SRC = \ qt_ui_utils.cpp \ recent_file_status.cpp \ related_packet_delegate.cpp \ + sctp_all_assocs_dialog.cpp \ + sctp_assoc_analyse_dialog.cpp \ + sctp_chunk_statistics_dialog.cpp \ + sctp_graph_dialog.cpp \ + sctp_graph_arwnd_dialog.cpp \ + sctp_graph_byte_dialog.cpp \ search_frame.cpp \ sequence_diagram.cpp \ sequence_dialog.cpp \ diff --git a/ui/qt/QtShark.pro b/ui/qt/QtShark.pro index 5fc5f92492..fa4c05ee2d 100644 --- a/ui/qt/QtShark.pro +++ b/ui/qt/QtShark.pro @@ -242,6 +242,12 @@ FORMS += \ preferences_dialog.ui \ print_dialog.ui \ profile_dialog.ui \ + sctp_all_assocs_dialog.ui \ + sctp_assoc_analyse_dialog.ui \ + sctp_chunk_statistics_dialog.ui \ + sctp_graph_dialog.ui \ + sctp_graph_arwnd_dialog.ui \ + sctp_graph_byte_dialog.ui \ search_frame.ui \ sequence_dialog.ui \ splash_overlay.ui \ @@ -272,6 +278,12 @@ HEADERS += $$HEADERS_WS_C \ preferences_dialog.h \ print_dialog.h \ profile_dialog.h \ + sctp_all_assocs_dialog.h \ + sctp_assoc_analyse_dialog.h \ + sctp_chunk_statistics_dialog.h \ + sctp_graph_dialog.h \ + sctp_graph_arwnd_dialog.h \ + sctp_graph_byte_dialog.h \ search_frame.h \ splash_overlay.h \ stats_tree_dialog.h \ @@ -529,6 +541,12 @@ HEADERS += \ qcustomplot.h \ recent_file_status.h \ related_packet_delegate.h \ + sctp_all_assocs_dialog.h \ + sctp_assoc_analyse_dialog.h \ + sctp_chunk_statistics_dialog.h \ + sctp_graph_dialog.h \ + sctp_graph_arwnd_dialog.h \ + sctp_graph_byte_dialog.h \ sequence_diagram.h \ sequence_dialog.h \ simple_dialog_qt.h \ @@ -590,6 +608,12 @@ SOURCES += \ qt_ui_utils.cpp \ recent_file_status.cpp \ related_packet_delegate.cpp \ + sctp_all_assocs_dialog.cpp \ + sctp_assoc_analyse_dialog.cpp \ + sctp_chunk_statistics_dialog.cpp \ + sctp_graph_dialog.cpp \ + sctp_graph_arwnd_dialog.cpp \ + sctp_graph_byte_dialog.cpp \ search_frame.cpp \ sequence_diagram.cpp \ sequence_dialog.cpp \ diff --git a/ui/qt/main_window.h b/ui/qt/main_window.h index 2ecc38b3eb..448a592cb9 100644 --- a/ui/qt/main_window.h +++ b/ui/qt/main_window.h @@ -326,6 +326,9 @@ private slots: void on_actionStatisticsTcpStreamThroughput_triggered(); void on_actionStatisticsTcpStreamRoundTripTime_triggered(); void on_actionStatisticsTcpStreamWindowScaling_triggered(); + void openSCTPAllAssocsDialog(); + void on_actionSCTPShowAllAssociations_triggered(); + void on_actionSCTPAnalyseThisAssociation_triggered(); #ifdef HAVE_LIBPCAP void on_actionCaptureInterfaces_triggered(); @@ -349,9 +352,7 @@ private slots: void on_actionTelephonyRTSPPacketCounter_triggered(); void on_actionTelephonySMPPOperations_triggered(); void on_actionTelephonyUCPMessages_triggered(); - }; - #endif // MAINWINDOW_H /* diff --git a/ui/qt/main_window.ui b/ui/qt/main_window.ui index c6fcb5cb38..3f190a76e7 100644 --- a/ui/qt/main_window.ui +++ b/ui/qt/main_window.ui @@ -302,6 +302,13 @@ + + + SCTP + + + + @@ -311,6 +318,7 @@ + @@ -1360,6 +1368,16 @@ TCP time sequence graph (tcptrace) + + + Analyse this Association + + + + + Show All Associations + + Flow Graph diff --git a/ui/qt/main_window_slots.cpp b/ui/qt/main_window_slots.cpp index 9ece59cfbc..e352033769 100644 --- a/ui/qt/main_window_slots.cpp +++ b/ui/qt/main_window_slots.cpp @@ -77,6 +77,9 @@ #include "print_dialog.h" #include "profile_dialog.h" #include "qt_ui_utils.h" +#include "sctp_all_assocs_dialog.h" +#include "sctp_assoc_analyse_dialog.h" +#include "sctp_graph_dialog.h" #include "sequence_dialog.h" #include "stats_tree_dialog.h" #include "tcp_stream_dialog.h" @@ -729,7 +732,7 @@ void MainWindow::setMenusForSelectedPacket() #if 0 gboolean is_ip = FALSE, is_tcp = FALSE, is_udp = FALSE, is_sctp = FALSE; #else - gboolean is_tcp = FALSE; + gboolean is_tcp = FALSE, is_sctp = FALSE;; #endif // /* Making the menu context-sensitive allows for easier selection of the @@ -773,7 +776,7 @@ void MainWindow::setMenusForSelectedPacket() if (cap_file_->edt) { - proto_get_frame_protocols(cap_file_->edt->pi.layers, NULL, &is_tcp, NULL, NULL); + proto_get_frame_protocols(cap_file_->edt->pi.layers, NULL, &is_tcp, NULL, &is_sctp); } } // if (cfile.edt && cfile.edt->tree) { @@ -922,6 +925,9 @@ void MainWindow::setMenusForSelectedPacket() // set_menu_sensitivity(ui_manager_main_menubar, "/Menubar/ToolsMenu/FirewallACLRules", // frame_selected); main_ui_->menuTcpStreamGraphs->setEnabled(is_tcp); + main_ui_->menuSCTP->setEnabled(is_sctp); + main_ui_->actionSCTPAnalyseThisAssociation->setEnabled(is_sctp); + main_ui_->actionSCTPShowAllAssociations->setEnabled(is_sctp); // while (list_entry != NULL) { // dissector_filter_t *filter_entry; @@ -1743,6 +1749,52 @@ void MainWindow::on_actionAnalyzeFollowSSLStream_triggered() openFollowStreamDialog(FOLLOW_SSL); } +void MainWindow::openSCTPAllAssocsDialog() +{ + SCTPAllAssocsDialog *sctp_dialog = new SCTPAllAssocsDialog(this, cap_file_); + connect(sctp_dialog, SIGNAL(filterPackets(QString&,bool)), + this, SLOT(filterPackets(QString&,bool))); + connect(this, SIGNAL(setCaptureFile(capture_file*)), + sctp_dialog, SLOT(setCaptureFile(capture_file*))); + sctp_dialog->fillTable(); + + if (sctp_dialog->isMinimized() == true) + { + sctp_dialog->showNormal(); + } + else + { + sctp_dialog->show(); + } + + sctp_dialog->raise(); + sctp_dialog->activateWindow(); +} + +void MainWindow::on_actionSCTPShowAllAssociations_triggered() +{ + openSCTPAllAssocsDialog(); +} + +void MainWindow::on_actionSCTPAnalyseThisAssociation_triggered() +{ + SCTPAssocAnalyseDialog *sctp_analyse = new SCTPAssocAnalyseDialog(this, NULL, cap_file_); + connect(sctp_analyse, SIGNAL(filterPackets(QString&,bool)), + this, SLOT(filterPackets(QString&,bool))); + + if (sctp_analyse->isMinimized() == true) + { + sctp_analyse->showNormal(); + } + else + { + sctp_analyse->show(); + } + + sctp_analyse->raise(); + sctp_analyse->activateWindow(); +} + // Next / previous / first / last slots in packet_list // Statistics Menu diff --git a/ui/qt/packet_list.cpp b/ui/qt/packet_list.cpp index b98ebb31d4..987fdd294a 100644 --- a/ui/qt/packet_list.cpp +++ b/ui/qt/packet_list.cpp @@ -35,6 +35,7 @@ #include "packet_list.h" #include "proto_tree.h" #include "wireshark_application.h" +#include "epan/ipproto.h" #include "qt_ui_utils.h" @@ -258,7 +259,12 @@ PacketList::PacketList(QWidget *parent) : // " \n" // " \n" // " \n" - + submenu = new QMenu(tr("SCTP")); + ctx_menu_.addMenu(submenu); + submenu->addAction(window()->findChild("actionSCTPAnalyseThisAssociation")); + submenu->addAction(window()->findChild("actionSCTPShowAllAssociations")); + submenu->addAction(window()->findChild("actionSCTPChunkCounter")); + filter_actions_ << submenu->actions(); ctx_menu_.addSeparator(); // " \n" ctx_menu_.addSeparator(); @@ -473,6 +479,18 @@ void PacketList::contextMenuEvent(QContextMenuEvent *event) { act->setEnabled(true); + // check SCTP + if (act->objectName().contains("SCTP")) + { + if (cap_file_->edt->pi.ipproto == IP_PROTO_SCTP) + { + act->setEnabled(true); + } + else + { + act->setEnabled(false); + } + } // check follow stream if (act->text().contains("TCP")) diff --git a/ui/qt/sctp_all_assocs_dialog.cpp b/ui/qt/sctp_all_assocs_dialog.cpp new file mode 100644 index 0000000000..d51522c4fd --- /dev/null +++ b/ui/qt/sctp_all_assocs_dialog.cpp @@ -0,0 +1,144 @@ +#include "sctp_all_assocs_dialog.h" +#include "ui_sctp_all_assocs_dialog.h" +#include "sctp_assoc_analyse_dialog.h" + +#include "qt_ui_utils.h" +//#include "wireshark_application.h" +#include "file.h" +#include "ui/qt/main_window.h" + +#include +#include +#include +#include +#include + +//#include + +SCTPAllAssocsDialog::SCTPAllAssocsDialog(QWidget *parent, capture_file *cf) : + QDialog(parent), + ui(new Ui::SCTPAllAssocsDialog), + cap_file_(cf) +{ + ui->setupUi(this); + sctp_assocs = (sctp_allassocs_info_t *)g_malloc(sizeof(sctp_allassocs_info_t)); + fillTable(); +} + +SCTPAllAssocsDialog::~SCTPAllAssocsDialog() +{ + delete ui; +} + +void SCTPAllAssocsDialog::fillTable() +{ + QString output; + GList *list; + sctp_assoc_info_t* assinfo; + int numAssocs; + + ui->assocList->setColumnHidden(0, true); + ui->assocList->setColumnWidth(1, 85); + ui->assocList->setColumnWidth(2, 85); + ui->assocList->setColumnWidth(3, 150); + ui->assocList->setColumnWidth(4, 150); + + sctp_assocs = (sctp_allassocs_info_t*)sctp_stat_get_info(); + if (sctp_stat_get_info()->is_registered == FALSE) { + register_tap_listener_sctp_stat(); + } + /* (redissect all packets) */ + cf_retap_packets(cap_file_); + numAssocs = 0; + ui->assocList->setRowCount(g_list_length(sctp_assocs->assoc_info_list)); + + list = g_list_first(sctp_assocs->assoc_info_list); + + while (list) { + assinfo = (sctp_assoc_info_t*)(list->data); + ui->assocList->setItem(numAssocs, 0, new QTableWidgetItem(QString("%1").arg(assinfo->assoc_id))); + ui->assocList->setItem(numAssocs, 1, new QTableWidgetItem(QString("%1").arg(assinfo->port1))); + ui->assocList->setItem(numAssocs, 2, new QTableWidgetItem(QString("%1").arg(assinfo->port2))); + ui->assocList->setItem(numAssocs, 3, new QTableWidgetItem(QString("%1").arg(assinfo->n_packets))); + ui->assocList->setItem(numAssocs, 4, new QTableWidgetItem(QString("%1").arg(assinfo->n_data_chunks))); + ui->assocList->setItem(numAssocs, 5, new QTableWidgetItem(QString("%1").arg(assinfo->n_data_bytes))); + list = g_list_next(list); + numAssocs++; + } + ui->analyseButton->setEnabled(false); + ui->setFilterButton->setEnabled(false); + connect(ui->assocList, SIGNAL(itemSelectionChanged()), this, SLOT(getSelectedItem())); + } + +sctp_assoc_info_t* SCTPAllAssocsDialog::findSelectedAssoc() +{ + QTableWidgetItem *selection; + GList *list; + sctp_assoc_info_t* assinfo; + int row, id; + + selection = ui->assocList->selectedItems()[0]; + row = selection->row(); + selection = ui->assocList->item(row, 0); + id = (selection->data(0)).toInt(); + list = g_list_first(sctp_assocs->assoc_info_list); + + while (list) { + assinfo = (sctp_assoc_info_t*)(list->data); + if (assinfo->assoc_id == id) { + return assinfo; + } + list = g_list_next(list); + } + return NULL; +} + +void SCTPAllAssocsDialog::getSelectedItem() +{ + ui->analyseButton->setEnabled(true); + ui->setFilterButton->setEnabled(true); + ui->analyseButton->setFocus(Qt::OtherFocusReason); + selected_assoc = findSelectedAssoc(); + printf("selection changed assoc now %p with id %d\n", + selected_assoc, selected_assoc->assoc_id); +} + +void SCTPAllAssocsDialog::on_analyseButton_clicked() +{ + + if (!selected_assoc) { + selected_assoc = findSelectedAssoc(); + printf("on_analyseButton_clicked found assoc %p with id %d\n", + selected_assoc, selected_assoc->assoc_id); + } + + SCTPAssocAnalyseDialog *sctp_analyse = new SCTPAssocAnalyseDialog(this, selected_assoc, cap_file_, this); + connect(sctp_analyse, SIGNAL(filterPackets(QString&,bool)), + parent(), SLOT(filterPackets(QString&,bool))); + + if (sctp_analyse->isMinimized() == true) + { + sctp_analyse->showNormal(); + } + else + { + sctp_analyse->show(); + } + + sctp_analyse->raise(); + sctp_analyse->activateWindow(); +} + +void SCTPAllAssocsDialog::on_setFilterButton_clicked() +{ + + if (!selected_assoc){ + selected_assoc = findSelectedAssoc(); + printf("on_setFilterButton_clicked found assoc %p with id %d\n", + selected_assoc, selected_assoc->assoc_id); + } + + QString newFilter = QString("sctp.assoc_index==%1").arg(selected_assoc->assoc_id); + selected_assoc = NULL; + emit filterPackets(newFilter, false); +} diff --git a/ui/qt/sctp_all_assocs_dialog.h b/ui/qt/sctp_all_assocs_dialog.h new file mode 100644 index 0000000000..68650e1506 --- /dev/null +++ b/ui/qt/sctp_all_assocs_dialog.h @@ -0,0 +1,52 @@ +#ifndef SCTP_ALL_ASSOCS_DIALOG_H +#define SCTP_ALL_ASSOCS_DIALOG_H + +#include "config.h" + +#include + +#include + +#include + +#include "ui/tap-sctp-analysis.h" + +#include +#include + +namespace Ui { +class SCTPAllAssocsDialog; +} + +class SCTPAllAssocsDialog : public QDialog +{ + Q_OBJECT + +public: + explicit SCTPAllAssocsDialog(QWidget *parent = 0, capture_file *cf = NULL); + ~SCTPAllAssocsDialog(); + + void fillTable(); + sctp_assoc_info_t* getSelectedAssoc() { return selected_assoc; }; + sctp_assoc_info_t* findSelectedAssoc(); + +public slots: + void setCaptureFile(capture_file *cf) { cap_file_ = cf; } + +private slots: + void on_analyseButton_clicked(); + void on_setFilterButton_clicked(); + void getSelectedItem(); + +private: + Ui::SCTPAllAssocsDialog *ui; + capture_file *cap_file_; + sctp_allassocs_info_t *sctp_assocs; + sctp_assoc_info_t *selected_assoc; + + +signals: + void filterPackets(QString& new_filter, bool force); +}; + +#endif // SCTP_ALL_ASSOCS_DIALOG_H diff --git a/ui/qt/sctp_all_assocs_dialog.ui b/ui/qt/sctp_all_assocs_dialog.ui new file mode 100644 index 0000000000..d72c96ae00 --- /dev/null +++ b/ui/qt/sctp_all_assocs_dialog.ui @@ -0,0 +1,433 @@ + + + SCTPAllAssocsDialog + + + + 0 + 0 + 685 + 300 + + + + Wireshark - SCTP Associations + + + + + + QAbstractItemView::NoEditTriggers + + + false + + + false + + + true + + + QAbstractItemView::SingleSelection + + + QAbstractItemView::SelectRows + + + true + + + false + + + 2 + + + 6 + + + 120 + + + 50 + + + true + + + + + + ID + + + + + Port 1 + + + + + Port 2 + + + + + Number of Packets + + + + + Number of DATA Chunks + + + + + Number of Bytes + + + + + + + + + + + + + false + + + Qt::ClickFocus + + + Filter Selected Association + + + + + + + false + + + Qt::ClickFocus + + + Analyze + + + + + + + Qt::Horizontal + + + + 10 + 20 + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Close + + + + + + + + + Reset Graph + + + Reset the graph to its initial state. + + + 0 + + + + + Zoom In + + + Zoom in + + + + + + + + + Zoom Out + + + Zoom out + + + - + + + + + Move Up 10 Pixels + + + Move up 10 pixels + + + Up + + + + + Move Left 10 Pixels + + + Move left 10 pixels + + + Left + + + + + Move Right 10 Pixels + + + Move right 10 pixels + + + Right + + + + + Move Down 10 Pixels + + + Move down 10 pixels + + + Down + + + + + Move Up 1 Pixel + + + Move up 1 pixel + + + Shift+Up + + + + + Move Left 1 Pixel + + + Move left 1 pixel + + + Shift+Left + + + + + Move Right 1 Pixel + + + Move right 1 pixel + + + Shift+Right + + + + + Move Down 1 Pixel + + + Move down 1 pixel + + + Shift+Down + + + + + Next Stream + + + Go to the next stream in the capture + + + PgUp + + + + + Previous Stream + + + Go to the previous stream in the capture + + + PgDown + + + + + Switch Direction + + + Switch direction (swap TCP endpoints) + + + D + + + + + Go To Packet Under Cursor + + + Go to packet currently under the cursor + + + G + + + + + Drag / Zoom + + + Toggle mouse drag / zoom behavior + + + Z + + + + + Relative / Absolute Sequence Numbers + + + Toggle relative / absolute sequence numbers + + + S + + + + + Capture / Session Time Origin + + + Toggle capture / session time origin + + + T + + + + + Crosshairs + + + Toggle crosshairs + + + Space + + + + + Round Trip Time + + + Switch to the Round Trip Time graph + + + 1 + + + + + Throughput + + + Switch to the Throughput graph + + + 2 + + + + + Time / Sequence (Stevens) + + + Switch to the Stevens-style Time / Sequence graph + + + 3 + + + + + Window Scaling + + + Switch to the Window Scaling graph + + + 5 + + + + + Time / Sequence (tcptrace) + + + Switch to the tcptrace-style Time / Sequence graph + + + 4 + + + + + + + buttonBox + clicked(QAbstractButton*) + SCTPAllAssocsDialog + close() + + + 644 + 274 + + + 659 + 322 + + + + + diff --git a/ui/qt/sctp_assoc_analyse_dialog.cpp b/ui/qt/sctp_assoc_analyse_dialog.cpp new file mode 100644 index 0000000000..d27ec2ac48 --- /dev/null +++ b/ui/qt/sctp_assoc_analyse_dialog.cpp @@ -0,0 +1,292 @@ +#include "sctp_assoc_analyse_dialog.h" +#include "ui_sctp_assoc_analyse_dialog.h" +#include "sctp_graph_dialog.h" +#include "sctp_graph_arwnd_dialog.h" +#include "sctp_graph_byte_dialog.h" +#include "sctp_chunk_statistics_dialog.h" + + +SCTPAssocAnalyseDialog::SCTPAssocAnalyseDialog(QWidget *parent, sctp_assoc_info_t *assoc, capture_file *cf, SCTPAllAssocsDialog* caller) : + QDialog(parent), + ui(new Ui::SCTPAssocAnalyseDialog), + selected_assoc(assoc), + cap_file_(cf), + caller_(caller) +{ + ui->setupUi(this); + ui->SCTPAssocAnalyseTab->setCurrentWidget(ui->Statistics); + if (!selected_assoc) { + if (sctp_stat_get_info()->is_registered == FALSE) { + register_tap_listener_sctp_stat(); + } + /* (redissect all packets) */ + cf_retap_packets(cap_file_); + findAssocForPacket(); + } + this->setWindowTitle(QString("SCTP Analyse Association: %1 Port1 %2 Port2 %3").arg(cf_get_display_name(cap_file_)).arg(selected_assoc->port1).arg(selected_assoc->port2)); + fillTabs(); +} + +SCTPAssocAnalyseDialog::~SCTPAssocAnalyseDialog() +{ + delete ui; +} + +void SCTPAssocAnalyseDialog::findAssocForPacket() +{ + frame_data *fdata; + GList *list, *framelist; + sctp_assoc_info_t *assoc; + bool frame_found = false; + printf("findAssocForPacket\n"); + fdata = cap_file_->current_frame; + list = g_list_first(sctp_stat_get_info()->assoc_info_list); + + while (list) { + assoc = (sctp_assoc_info_t*)(list->data); + + framelist = g_list_first(assoc->frame_numbers); + while (framelist) { + guint32 *fn; + fn = (guint32 *)framelist->data; + if (*fn == fdata->num) { + frame_found = TRUE; + break; + } + framelist = g_list_next(framelist); + } + if (frame_found) { + selected_assoc = assoc; + printf("assoc_id =%d\n", selected_assoc->assoc_id); + return; + } else { + list = g_list_next(list); + } + } + + if (!frame_found) { + QMessageBox msgBox; + msgBox.setText("No Association found for this packet."); + msgBox.exec(); + } +} + +void SCTPAssocAnalyseDialog::fillTabs() +{ + /* Statistics Tab */ + + ui->checksumLabel->setText(selected_assoc->checksum_type); + ui->data12Label->setText(QString("%1").arg(selected_assoc->n_data_chunks_ep1)); + ui->bytes12Label->setText(QString("%1").arg(selected_assoc->n_data_bytes_ep1)); + ui->data21Label->setText(QString("%1").arg(selected_assoc->n_data_chunks_ep2)); + ui->bytes21Label->setText(QString("%1").arg(selected_assoc->n_data_bytes_ep2)); + + /* Tab Endpoint 1 */ + + if (selected_assoc->init == TRUE) + ui->labelEP1->setText(QString("Complete list of IP-Addresses as provided in the INIT-Chunk")); + else if ((selected_assoc->initack == TRUE) && (selected_assoc->initack_dir == 1)) + ui->labelEP1->setText(QString("Complete list of IP-Addresses as provided in the INITACK-Chunk")); + else + ui->labelEP1->setText(QString("List of used IP-Addresses")); + + if (selected_assoc->addr1 != NULL) { + GList *list; + + list = g_list_first(selected_assoc->addr1); + while (list) { + address *store; + + store = (address *)(list->data); + if (store->type != AT_NONE) { + if (store->type == AT_IPv4) { + ui->listWidgetEP1->addItem(QString("%1").arg(ip_to_str((const guint8 *)(store->data)))); + } else if (store->type == AT_IPv6) { + ui->listWidgetEP1->addItem(QString("%1").arg(ip6_to_str((const struct e_in6_addr *)(store->data)))); + } + } + list = g_list_next(list); + } + } else { + return; + } + + ui->label_221->setText(QString("%1").arg(selected_assoc->port1)); + ui->label_222->setText(QString("0x%1").arg(selected_assoc->verification_tag1, 0, 16)); + + if ((selected_assoc->init == TRUE) || + ((selected_assoc->initack == TRUE) && (selected_assoc->initack_dir == 1))) { + ui->label_213->setText(QString("Requested Number of Inbound Streams:")); + ui->label_223->setText(QString("%1").arg(selected_assoc->instream1)); + ui->label_214->setText(QString("Minimum Number of Inbound Streams:")); + ui->label_224->setText(QString("%1").arg(((selected_assoc->instream1 > selected_assoc->outstream2) ? + selected_assoc->outstream2 : selected_assoc->instream1))); + ui->label_215->setText(QString("Provided Number of Outbound Streams:")); + ui->label_225->setText(QString("%1").arg(selected_assoc->outstream1)); + ui->label_216->setText(QString("Minimum Number of Outbound Streams:")); + ui->label_226->setText(QString("%1").arg(((selected_assoc->outstream1 > selected_assoc->instream2) ? + selected_assoc->instream2 : selected_assoc->outstream1))); + } else { + ui->label_213->setText(QString("Used Number of Inbound Streams:")); + ui->label_223->setText(QString("%1").arg(selected_assoc->instream1)); + ui->label_214->setText(QString("Used Number of Outbound Streams:")); + ui->label_224->setText(QString("%1").arg(selected_assoc->outstream1)); + ui->label_215->setText(QString("")); + ui->label_225->setText(QString("")); + ui->label_216->setText(QString("")); + ui->label_226->setText(QString("")); + } + + /* Tab Endpoint 2 */ + + if ((selected_assoc->initack == TRUE) && (selected_assoc->initack_dir == 2)) + ui->labelEP2->setText(QString("Complete list of IP-Addresses as provided in the INITACK-Chunk")); + else + ui->labelEP2->setText(QString("List of used IP-Addresses")); + + if (selected_assoc->addr2 != NULL) { + GList *list; + + list = g_list_first(selected_assoc->addr2); + while (list) { + address *store; + + store = (address *)(list->data); + if (store->type != AT_NONE) { + if (store->type == AT_IPv4) { + ui->listWidgetEP2->addItem(QString("%1").arg(ip_to_str((const guint8 *)(store->data)))); + } else if (store->type == AT_IPv6) { + ui->listWidgetEP2->addItem(QString("%1").arg(ip6_to_str((const struct e_in6_addr *)(store->data)))); + } + } + list = g_list_next(list); + } + } else { + return; + } + + ui->label_321->setText(QString("%1").arg(selected_assoc->port2)); + ui->label_322->setText(QString("0x%1").arg(selected_assoc->verification_tag2, 0, 16)); + + if (selected_assoc->initack == TRUE) { + ui->label_313->setText(QString("Requested Number of Inbound Streams:")); + ui->label_323->setText(QString("%1").arg(selected_assoc->instream2)); + ui->label_314->setText(QString("Minimum Number of Inbound Streams:")); + ui->label_324->setText(QString("%1").arg(((selected_assoc->instream2 > selected_assoc->outstream1) ? + selected_assoc->outstream1 : selected_assoc->instream2))); + ui->label_315->setText(QString("Provided Number of Outbound Streams:")); + ui->label_325->setText(QString("%1").arg(selected_assoc->outstream2)); + ui->label_316->setText(QString("Minimum Number of Outbound Streams:")); + ui->label_326->setText(QString("%1").arg(((selected_assoc->outstream2 > selected_assoc->instream1) ? + selected_assoc->instream1 : selected_assoc->outstream2))); + } else { + ui->label_313->setText(QString("Used Number of Inbound Streams:")); + ui->label_323->setText(QString("%1").arg(selected_assoc->instream2)); + ui->label_314->setText(QString("Used Number of Outbound Streams:")); + ui->label_324->setText(QString("%1").arg(selected_assoc->outstream2)); + ui->label_315->setText(QString("")); + ui->label_325->setText(QString("")); + ui->label_316->setText(QString("")); + ui->label_326->setText(QString("")); + } +} + +void SCTPAssocAnalyseDialog::openGraphDialog(int direction) +{ + SCTPGraphDialog *sctp_dialog = new SCTPGraphDialog(this, selected_assoc, cap_file_, direction); + + if (sctp_dialog->isMinimized() == true) { + sctp_dialog->showNormal(); + } else { + sctp_dialog->show(); + } + + sctp_dialog->raise(); + sctp_dialog->activateWindow(); +} + +void SCTPAssocAnalyseDialog::on_GraphTSN_2_clicked() +{ + openGraphDialog(2); + + +} + +void SCTPAssocAnalyseDialog::on_GraphTSN_1_clicked() +{ + openGraphDialog(1); +} + +void SCTPAssocAnalyseDialog::on_chunkStatisticsButton_clicked() +{ + if (caller_ && !selected_assoc) { + selected_assoc = caller_->findSelectedAssoc(); + } else if (!caller_ && !selected_assoc) { + findAssocForPacket(); + } + SCTPChunkStatisticsDialog *sctp_dialog = new SCTPChunkStatisticsDialog(this, selected_assoc, cap_file_); + + if (sctp_dialog->isMinimized() == true) { + sctp_dialog->showNormal(); + } else { + sctp_dialog->show(); + } + + sctp_dialog->raise(); + sctp_dialog->activateWindow(); +} + +void SCTPAssocAnalyseDialog::on_setFilterButton_clicked() +{ + QString newFilter = QString("sctp.assoc_index==%1").arg(selected_assoc->assoc_id); + selected_assoc = NULL; + emit filterPackets(newFilter, false); +} + +void SCTPAssocAnalyseDialog::openGraphByteDialog(int direction) +{ + SCTPGraphByteDialog *sctp_dialog = new SCTPGraphByteDialog(this, selected_assoc, cap_file_, direction); + + if (sctp_dialog->isMinimized() == true) { + sctp_dialog->showNormal(); + } else { + sctp_dialog->show(); + } + + sctp_dialog->raise(); + sctp_dialog->activateWindow(); +} + +void SCTPAssocAnalyseDialog::on_GraphBytes_1_clicked() +{ + openGraphByteDialog(1); +} + +void SCTPAssocAnalyseDialog::on_GraphBytes_2_clicked() +{ + openGraphByteDialog(2); +} + +void SCTPAssocAnalyseDialog::openGraphArwndDialog(int direction) +{ + SCTPGraphArwndDialog *sctp_dialog = new SCTPGraphArwndDialog(this, selected_assoc, cap_file_, direction); + + if (sctp_dialog->isMinimized() == true) { + sctp_dialog->showNormal(); + } else { + sctp_dialog->show(); + } + + sctp_dialog->raise(); + sctp_dialog->activateWindow(); +} + +void SCTPAssocAnalyseDialog::on_GraphArwnd_1_clicked() +{ + openGraphArwndDialog(1); +} + +void SCTPAssocAnalyseDialog::on_GraphArwnd_2_clicked() +{ + openGraphArwndDialog(2); +} diff --git a/ui/qt/sctp_assoc_analyse_dialog.h b/ui/qt/sctp_assoc_analyse_dialog.h new file mode 100644 index 0000000000..31cd273e25 --- /dev/null +++ b/ui/qt/sctp_assoc_analyse_dialog.h @@ -0,0 +1,66 @@ +#ifndef SCTP_ASSOC_ANALYSE_DIALOG_H +#define SCTP_ASSOC_ANALYSE_DIALOG_H + +#include "config.h" + +#include + +#include + +#include + +#include "ui/tap-sctp-analysis.h" +#include "sctp_all_assocs_dialog.h" + +#include +#include +#include +#include +#include + + +namespace Ui { +class SCTPAssocAnalyseDialog; +} + +class SCTPAssocAnalyseDialog : public QDialog +{ + Q_OBJECT + +public: + explicit SCTPAssocAnalyseDialog(QWidget *parent = 0, sctp_assoc_info_t *assoc = NULL, capture_file *cf = NULL, SCTPAllAssocsDialog *caller = NULL); + ~SCTPAssocAnalyseDialog(); + + void fillTabs(); + +public slots: + void setCaptureFile(capture_file *cf) { cap_file_ = cf; } + +private slots: + void on_GraphTSN_2_clicked(); + void on_GraphTSN_1_clicked(); + void on_chunkStatisticsButton_clicked(); + void on_setFilterButton_clicked(); + + void on_GraphBytes_1_clicked(); + void on_GraphBytes_2_clicked(); + + void on_GraphArwnd_1_clicked(); + void on_GraphArwnd_2_clicked(); + +private: + Ui::SCTPAssocAnalyseDialog *ui; + sctp_assoc_info_t *selected_assoc; + capture_file *cap_file_; + SCTPAllAssocsDialog *caller_; + void findAssocForPacket(); + void openGraphDialog(int direction); + void openGraphByteDialog(int direction); + void openGraphArwndDialog(int direction); + + +signals: + void filterPackets(QString& new_filter, bool force); +}; + +#endif // SCTP_ASSOC_ANALYSE_DIALOG_H diff --git a/ui/qt/sctp_assoc_analyse_dialog.ui b/ui/qt/sctp_assoc_analyse_dialog.ui new file mode 100644 index 0000000000..b74af737d7 --- /dev/null +++ b/ui/qt/sctp_assoc_analyse_dialog.ui @@ -0,0 +1,607 @@ + + + SCTPAssocAnalyseDialog + + + + 0 + 0 + 537 + 385 + + + + + 0 + 0 + + + + Wireshark - Analyse Association + + + + :/menu/help/wsicon16.png:/menu/help/wsicon16.png + + + + + + + + 5 + 10 + 529 + 371 + + + + TabWidget + + + 2 + + + + Qt::NoFocus + + + Statistics + + + + + 0 + 310 + 131 + 32 + + + + Qt::NoFocus + + + Chunk Statistics + + + + + + 130 + 310 + 141 + 32 + + + + Qt::NoFocus + + + Filter Association + + + + + + 390 + 310 + 114 + 32 + + + + Qt::NoFocus + + + Schließen + + + + + + 20 + 40 + 481 + 201 + + + + + + + Number of Data Chunks from EP2 to EP1: + + + + + + + Checksum Type: + + + + + + + Number of Data Chunks from EP1 to EP2: + + + + + + + Number of Data Bytes from EP1 to EP2: + + + + + + + Number of Data Bytes from EP2 to EP1: + + + + + + + TextLabel + + + + + + + TextLabel + + + + + + + TextLabel + + + + + + + TextLabel + + + + + + + TextLabel + + + + + + + + + Endpoint 1 + + + + + 0 + 310 + 114 + 32 + + + + Qt::NoFocus + + + Graph TSN + + + + + + 110 + 310 + 114 + 32 + + + + Qt::NoFocus + + + Graph Bytes + + + + + + 10 + 10 + 441 + 16 + + + + Complete list of IP Addresses as provided in the INIT Chunk + + + + + + 10 + 170 + 520 + 138 + + + + + + + Requested Number of Inbound Streams: + + + + + + + Port: + + + + + + + TextLabel + + + + + + + Sent Verification Tag: + + + + + + + TextLabel + + + + + + + Minimum Number of Inbound Streams: + + + + + + + TextLabel + + + + + + + Minimum Number of Outbound Streams: + + + + + + + TextLabel + + + + + + + TextLabel + + + + + + + TextLabel + + + + + + + TextLabel + + + + + + + + + 390 + 310 + 114 + 32 + + + + Qt::NoFocus + + + Schließen + + + + + + 10 + 30 + 501 + 131 + + + + + + + 220 + 310 + 114 + 32 + + + + Graph Arwnd + + + + + + Endpoint 2 + + + + + 0 + 310 + 114 + 32 + + + + Qt::NoFocus + + + Graph TSN + + + + + + 110 + 310 + 114 + 32 + + + + Qt::NoFocus + + + Graph Bytes + + + + + + 10 + 170 + 511 + 141 + + + + + + + Requested Number of Inbound Streams: + + + + + + + TextLabel + + + + + + + TextLabel + + + + + + + Sent Verification Tag: + + + + + + + Minimum Number of Outbound Streams: + + + + + + + Port: + + + + + + + Minimum Number of Inbound Streams: + + + + + + + TextLabel + + + + + + + TextLabel + + + + + + + TextLabel + + + + + + + Provided Number of Outbound Streams: + + + + + + + TextLabel + + + + + + + + + 10 + 10 + 441 + 16 + + + + Complete list of IP Addresses as provided in the INIT-ACK Chunk + + + + + + 390 + 310 + 114 + 32 + + + + Qt::NoFocus + + + Schließen + + + + + + 10 + 30 + 501 + 131 + + + + + + + 220 + 310 + 121 + 32 + + + + Graph a_rwnd + + + + + + + + + + + pushButton_2 + clicked() + SCTPAssocAnalyseDialog + close() + + + 471 + 365 + + + 475 + 384 + + + + + pushButton + clicked() + SCTPAssocAnalyseDialog + close() + + + 494 + 361 + + + 523 + 433 + + + + + pushButton_3 + clicked() + SCTPAssocAnalyseDialog + close() + + + 502 + 362 + + + 520 + 459 + + + + + diff --git a/ui/qt/sctp_chunk_statistics_dialog.cpp b/ui/qt/sctp_chunk_statistics_dialog.cpp new file mode 100644 index 0000000000..b4a70f6d75 --- /dev/null +++ b/ui/qt/sctp_chunk_statistics_dialog.cpp @@ -0,0 +1,288 @@ +#include "sctp_chunk_statistics_dialog.h" +#include "ui_sctp_chunk_statistics_dialog.h" +#include "uat_dialog.h" + +#include + + +SCTPChunkStatisticsDialog::SCTPChunkStatisticsDialog(QWidget *parent, sctp_assoc_info_t *assoc, capture_file *cf) : + QDialog(parent), + ui(new Ui::SCTPChunkStatisticsDialog), + selected_assoc(assoc), + cap_file_(cf) +{ + ui->setupUi(this); + printf("selected_assoc id=%d\n", selected_assoc->assoc_id); + ui->tableWidget->verticalHeader()->setSectionsClickable(true); + ui->tableWidget->verticalHeader()->setSectionsMovable(true); + + ui->tableWidget->setSelectionBehavior(QAbstractItemView::SelectRows); + ui->tableWidget->setSelectionMode(QAbstractItemView::SingleSelection); + +#if (QT_VERSION < QT_VERSION_CHECK(5, 0, 0)) + ui->tableWidget->horizontalHeader()->setResizeMode(QHeaderView::ResizeToContents); +#else + ui->tableWidget->horizontalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents); +#endif + + this->setWindowTitle(QString("SCTP Chunk Statistics: %1 Port1 %2 Port2 %3").arg(cf_get_display_name(cap_file_)).arg(selected_assoc->port1).arg(selected_assoc->port2)); + // connect(ui->tableWidget->verticalHeader(), SIGNAL(sectionClicked(int)), this, SLOT(on_sectionClicked(int))); + connect(ui->tableWidget->verticalHeader(), SIGNAL(sectionMoved(int,int,int)), this, SLOT(on_sectionMoved(int, int, int))); + + ctx_menu_.addAction(ui->actionHideChunkType); + ctx_menu_.addAction(ui->actionChunkTypePreferences); + ctx_menu_.addAction(ui->actionShowAllChunkTypes); + initializeChunkMap(); + fillTable(); +} + +SCTPChunkStatisticsDialog::~SCTPChunkStatisticsDialog() +{ + delete ui; +} + +void SCTPChunkStatisticsDialog::initializeChunkMap() +{ + struct chunkTypes temp; + gchar buf[16]; + + for (int i = 0; i < 256; i++) { + temp.id = i; + temp.row = i; + sprintf(buf, "%d", i); + strcpy(temp.name, val_to_str_const(i, chunk_type_values, "NA")); + if (strcmp(temp.name, "NA") == 0) { + temp.hide = 1; + strcpy(temp.name, buf); + } else { + temp.hide = 0; + } + chunks.insert(i, temp); + } +} + +void SCTPChunkStatisticsDialog::fillTable(bool all) +{ + FILE* fp; + + pref_t *pref = prefs_find_preference(prefs_find_module("sctp"),"statistics_chunk_types"); + uat_t *uat = pref->varp.uat; + gchar* fname = uat_get_actual_filename(uat,TRUE); + bool init = false; + + if (!fname ) { + printf("no filename\n"); + init = true; + } else { + fp = ws_fopen(fname,"r"); + + if (!fp && errno == ENOENT) { + init = true; + } + } + g_free (fname); + + if (init || all) { + int j = 0; + printf("init set\n"); + for (int i = 0; i < chunks.size(); i++) { + if (!chunks.value(i).hide) { + ui->tableWidget->setRowCount(ui->tableWidget->rowCount()+1); + ui->tableWidget->setVerticalHeaderItem(j, new QTableWidgetItem(QString("%1").arg(chunks.value(i).name))); + ui->tableWidget->setItem(j,0, new QTableWidgetItem(QString("%1").arg(selected_assoc->chunk_count[chunks.value(i).id]))); + ui->tableWidget->setItem(j,1, new QTableWidgetItem(QString("%1").arg(selected_assoc->ep1_chunk_count[chunks.value(i).id]))); + ui->tableWidget->setItem(j,2, new QTableWidgetItem(QString("%1").arg(selected_assoc->ep2_chunk_count[chunks.value(i).id]))); + j++; + } + } + for (int i = 0; i < chunks.size(); i++) { + if (chunks.value(i).hide) { + ui->tableWidget->setRowCount(ui->tableWidget->rowCount()+1); + /* ui->tableWidget->setVerticalHeaderItem(j, new QTableWidgetItem(QString("%1").arg(chunks.value(i).name))); + ui->tableWidget->setItem(j,0, new QTableWidgetItem(QString("%1").arg(selected_assoc->chunk_count[chunks.value(i).id]))); + ui->tableWidget->setItem(j,1, new QTableWidgetItem(QString("%1").arg(selected_assoc->ep1_chunk_count[chunks.value(i).id]))); + ui->tableWidget->setItem(j,2, new QTableWidgetItem(QString("%1").arg(selected_assoc->ep2_chunk_count[chunks.value(i).id])));*/ + ui->tableWidget->hideRow(j); + j++; + } + } + } else { + char* line = NULL; + size_t cap = 0; + ssize_t len; + char *token, id[5]; + int i = 0, j = 0; + struct chunkTypes temp; + + getline(&line, &cap, fp); + while ((len = getline(&line, &cap, fp)) > 0 ) { + token = strtok(line, ","); + /* Get rid of the quotation marks */ + QString ch = QString(token).mid(1, (int)strlen(token)-2); + strcpy(id, qPrintable(ch)); + temp.id = atoi(id); + while(token != NULL) { + token = strtok(NULL, ","); + if (token) { + if ((strstr(token, "Hide"))) { + temp.hide = 1; + } else if ((strstr(token, "Show"))) { + temp.hide = 0; + } else { + QString ch = QString(token).mid(1, (int)strlen(token)-2); + strcpy(temp.name, qPrintable(ch)); + } + } + } + if (!temp.hide) { + ui->tableWidget->setRowCount(ui->tableWidget->rowCount()+1); + ui->tableWidget->setVerticalHeaderItem(j, new QTableWidgetItem(QString("%1").arg(temp.name))); + ui->tableWidget->setItem(j,0, new QTableWidgetItem(QString("%1").arg(selected_assoc->chunk_count[temp.id]))); + ui->tableWidget->setItem(j,1, new QTableWidgetItem(QString("%1").arg(selected_assoc->ep1_chunk_count[temp.id]))); + ui->tableWidget->setItem(j,2, new QTableWidgetItem(QString("%1").arg(selected_assoc->ep2_chunk_count[temp.id]))); + j++; + } + chunks.insert(i, temp); + i++; + } + j = ui->tableWidget->rowCount(); + for (int i = 0; i < chunks.size(); i++) { + if (chunks.value(i).hide) { + ui->tableWidget->setRowCount(ui->tableWidget->rowCount()+1); + /* ui->tableWidget->setVerticalHeaderItem(j, new QTableWidgetItem(QString("%1").arg(chunks.value(i).name))); + ui->tableWidget->setItem(j,0, new QTableWidgetItem(QString("%1").arg(selected_assoc->chunk_count[chunks.value(i).id]))); + ui->tableWidget->setItem(j,1, new QTableWidgetItem(QString("%1").arg(selected_assoc->ep1_chunk_count[chunks.value(i).id]))); + ui->tableWidget->setItem(j,2, new QTableWidgetItem(QString("%1").arg(selected_assoc->ep2_chunk_count[chunks.value(i).id])));*/ + ui->tableWidget->hideRow(j); + j++; + } + } + fclose(fp); + } +} + +void SCTPChunkStatisticsDialog::contextMenuEvent( QContextMenuEvent * event) +{ + selected_point = event->pos(); + QTableWidgetItem *item = ui->tableWidget->itemAt(selected_point.x(), selected_point.y()-60); + if (item) { + printf("clicked on row %d\n", item->row()); + printf("Inhalt von %d: %s\n", item->row(), ui->tableWidget->verticalHeaderItem(item->row())->text().toUtf8().constData()); + ctx_menu_.exec(event->globalPos()); + } + else + printf("nichts da\n"); + +} + + + +void SCTPChunkStatisticsDialog::on_pushButton_clicked() +{ + FILE* fp; + + pref_t *pref = prefs_find_preference(prefs_find_module("sctp"),"statistics_chunk_types"); + + uat_t *uat = pref->varp.uat; + + gchar* fname = uat_get_actual_filename(uat,TRUE); + + if (!fname ) { + printf("no filename\n"); + return; + } + fp = ws_fopen(fname,"w"); + + if (!fp && errno == ENOENT) { + gchar *pf_dir_path = NULL; + if (create_persconffile_dir(&pf_dir_path) != 0) { + printf("on_pushButton_clicked: error creating '%s'", pf_dir_path); + g_free (pf_dir_path); + return; + } + fp = ws_fopen(fname,"w"); + } + + if (!fp) { + printf("on_pushButton_clicked: error opening '%s': %s",fname,g_strerror(errno)); + return; + } + + g_free (fname); + + fprintf(fp,"# This file is automatically generated, DO NOT MODIFY.\n"); + char str[40]; + + for (int i = 0; i < chunks.size(); i++) { + sprintf(str, "\"%d\",\"%s\",\"%s\"\n", chunks.value(i).id, chunks.value(i).name, (chunks.value(i).hide==0?"Show":"Hide")); + fputs(str, fp); + void *rec = g_malloc0(uat->record_size); + uat_add_record(uat, rec, TRUE); + if (uat->free_cb) { + uat->free_cb(rec); + } + g_free(rec); + } + + fclose(fp); +} + +void SCTPChunkStatisticsDialog::on_sectionMoved(int logicalIndex, int oldVisualIndex, int newVisualIndex) +{ + printf("logicalIndex=%d, oldVisualIndex=%d, newVisualIndex=%d\n", logicalIndex, oldVisualIndex, newVisualIndex); +} + +void SCTPChunkStatisticsDialog::on_actionHideChunkType_triggered() +{ + int row; + + QTableWidgetItem *item = ui->tableWidget->itemAt(selected_point.x(), selected_point.y()-60); + if (item) { + row = item->row(); + ui->tableWidget->hideRow(row); + QTableWidgetItem *item = ui->tableWidget->verticalHeaderItem(row); + QMap::iterator iter; + for (iter = chunks.begin(); iter != chunks.end(); ++iter) { + if (strcmp(iter.value().name, item->text().toUtf8().constData()) == 0) { + iter.value().hide = true; + break; + } + } + } + +} + +void SCTPChunkStatisticsDialog::on_actionChunkTypePreferences_triggered() +{ + const gchar* err = NULL; + + pref_t *pref = prefs_find_preference(prefs_find_module("sctp"),"statistics_chunk_types"); + uat_t *uat = pref->varp.uat; + uat_clear(uat); + + uat_load(pref->varp.uat, &err); + if (err) { + printf("Error loading table '%s': %s",pref->varp.uat->name,err); + } + + UatDialog *uatdialog = new UatDialog(this, pref->varp.uat); + uatdialog->exec(); + ui->tableWidget->clear(); + ui->tableWidget->setRowCount(0); + ui->tableWidget->setHorizontalHeaderItem(0, new QTableWidgetItem(QString("Association"))); + ui->tableWidget->setHorizontalHeaderItem(1, new QTableWidgetItem(QString("Endpoint 1"))); + ui->tableWidget->setHorizontalHeaderItem(2, new QTableWidgetItem(QString("Endpoint 2"))); + fillTable(); +} + +void SCTPChunkStatisticsDialog::on_actionShowAllChunkTypes_triggered() +{ + ui->tableWidget->clear(); + ui->tableWidget->setRowCount(0); + ui->tableWidget->setHorizontalHeaderItem(0, new QTableWidgetItem(QString("Association"))); + ui->tableWidget->setHorizontalHeaderItem(1, new QTableWidgetItem(QString("Endpoint 1"))); + ui->tableWidget->setHorizontalHeaderItem(2, new QTableWidgetItem(QString("Endpoint 2"))); + printf ("on_actionShowAllChunkTypes_triggered: assoc=%d\n", selected_assoc->assoc_id); + initializeChunkMap(); + fillTable(true); +} diff --git a/ui/qt/sctp_chunk_statistics_dialog.h b/ui/qt/sctp_chunk_statistics_dialog.h new file mode 100644 index 0000000000..0392b8e8bc --- /dev/null +++ b/ui/qt/sctp_chunk_statistics_dialog.h @@ -0,0 +1,75 @@ +#ifndef SCTP_CHUNK_STATISTICS_DIALOG_H +#define SCTP_CHUNK_STATISTICS_DIALOG_H + +#include "config.h" +#include + +#include +#include +#include +#include "epan/packet.h" +#include "epan/value_string.h" +#include +#include +#include +#include +#include "wireshark_application.h" + +#include "ui/tap-sctp-analysis.h" + +#include +#include +#include +#include +#include + +namespace Ui { +class SCTPChunkStatisticsDialog; +} + +class SCTPChunkStatisticsDialog : public QDialog +{ + Q_OBJECT + +public: + explicit SCTPChunkStatisticsDialog(QWidget *parent = 0, sctp_assoc_info_t *assoc = NULL, capture_file *cf = NULL); + ~SCTPChunkStatisticsDialog(); + +public slots: + void setCaptureFile(capture_file *cf) { cap_file_ = cf; } + +private slots: + // void on_sectionClicked(int row); + void on_sectionMoved(int logicalIndex, int oldVisualIndex, int newVisualIndex); + void on_pushButton_clicked(); + void on_actionHideChunkType_triggered(); + void on_actionChunkTypePreferences_triggered(); + void contextMenuEvent(QContextMenuEvent * event); + + void on_actionShowAllChunkTypes_triggered(); + +signals: + // void sectionClicked(int); + void sectionMoved(int, int, int); + +private: + Ui::SCTPChunkStatisticsDialog *ui; + sctp_assoc_info_t *selected_assoc; + capture_file *cap_file_; + QMenu ctx_menu_; + QPoint selected_point; + + struct chunkTypes { + int row; + int id; + int hide; + char name[30]; + }; + + QMap chunks, tempChunks; + + void initializeChunkMap(); + void fillTable(bool all = false); +}; + +#endif // SCTP_CHUNK_STATISTICS_DIALOG_H diff --git a/ui/qt/sctp_chunk_statistics_dialog.ui b/ui/qt/sctp_chunk_statistics_dialog.ui new file mode 100644 index 0000000000..4165edc5ff --- /dev/null +++ b/ui/qt/sctp_chunk_statistics_dialog.ui @@ -0,0 +1,160 @@ + + + SCTPChunkStatisticsDialog + + + + 0 + 0 + 519 + 504 + + + + + 0 + 0 + + + + Dialog + + + + + 310 + 470 + 191 + 32 + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Close + + + + + + 30 + 30 + 471 + 431 + + + + QAbstractItemView::NoEditTriggers + + + true + + + QAbstractItemView::SingleSelection + + + QAbstractItemView::SelectRows + + + 0 + + + false + + + true + + + false + + + + Association + + + + + Endpoint 1 + + + + + Endpoint 2 + + + + + + + 130 + 470 + 181 + 32 + + + + Save Chunk Type Order + + + + + Hide Chunk Type + + + Remove the chunk type from the table + + + + + Chunk Type Preferences + + + Go to the chunk type preferences dialog to show or hide other chunk types + + + + + Show All Registered Chunk Types + + + Show all chunk types with defined names + + + + + + + buttonBox + clicked(QAbstractButton*) + SCTPChunkStatisticsDialog + close() + + + 456 + 483 + + + 445 + 563 + + + + + buttonBox + clicked(QAbstractButton*) + SCTPChunkStatisticsDialog + close() + + + 357 + 486 + + + 355 + 542 + + + + + diff --git a/ui/qt/sctp_graph_arwnd_dialog.cpp b/ui/qt/sctp_graph_arwnd_dialog.cpp new file mode 100644 index 0000000000..238b58e2d6 --- /dev/null +++ b/ui/qt/sctp_graph_arwnd_dialog.cpp @@ -0,0 +1,141 @@ +#include "sctp_graph_arwnd_dialog.h" +#include "ui_sctp_graph_arwnd_dialog.h" + +#include "sctp_graph_dialog.h" + +SCTPGraphArwndDialog::SCTPGraphArwndDialog(QWidget *parent, sctp_assoc_info_t *assoc, capture_file *cf, int dir) : + QDialog(parent), + ui(new Ui::SCTPGraphArwndDialog), + selected_assoc(assoc), + cap_file_(cf), + direction(dir) +{ + ui->setupUi(this); + this->setWindowTitle(QString("SCTP Data and Adv. Rec. Window over Time: %1 Port1 %2 Port2 %3").arg(cf_get_display_name(cap_file_)).arg(selected_assoc->port1).arg(selected_assoc->port2)); + if ((direction == 1 && selected_assoc->n_array_tsn1 == 0) || (direction == 2 && selected_assoc->n_array_tsn2 == 0)) { + QMessageBox msgBox; + msgBox.setText("No Data Chunks sent"); + msgBox.exec(); + return; + } else { + drawGraph(); + } +} + +SCTPGraphArwndDialog::~SCTPGraphArwndDialog() +{ + delete ui; +} + +void SCTPGraphArwndDialog::drawArwndGraph() +{ + GList *listSACK = NULL, *tlist; + struct sack_chunk_header *sack_header; + struct nr_sack_chunk_header *nr_sack_header; + tsn_t *tsn; + guint8 type; + guint32 arwnd=0; + + if (direction == 1) { + listSACK = g_list_last(selected_assoc->sack1); + startArwnd = selected_assoc->arwnd1; + } else { + listSACK = g_list_last(selected_assoc->sack2); + startArwnd = selected_assoc->arwnd2; + } + while (listSACK) { + tsn = (tsn_t*) (listSACK->data); + tlist = g_list_first(tsn->tsns); + while (tlist) { + type = ((struct chunk_header *)tlist->data)->type; + if (type == SCTP_SACK_CHUNK_ID) { + sack_header =(struct sack_chunk_header *)tlist->data; + arwnd = g_ntohl(sack_header->a_rwnd); + } else if (type == SCTP_NR_SACK_CHUNK_ID) { + nr_sack_header =(struct nr_sack_chunk_header *)tlist->data; + arwnd = g_ntohl(nr_sack_header->a_rwnd); + } + // printf("frame %d arwnd=%d\n", tsn->frame_number, arwnd); + ya.append(arwnd); + xa.append(tsn->secs + tsn->usecs/1000000.0); + fa.append(tsn->frame_number); + tlist = g_list_next(tlist); + } + listSACK = g_list_previous(listSACK); + } + + QCPScatterStyle myScatter; + myScatter.setShape(QCPScatterStyle::ssCircle); + myScatter.setSize(3); + + // create graph and assign data to it: + + // Add Arwnd graph + if (xa.size() > 0) { + QCPGraph *gr = ui->sctpPlot->addGraph(ui->sctpPlot->xAxis, ui->sctpPlot->yAxis); + gr->setName(QString("Arwnd")); + myScatter.setPen(QPen(Qt::red)); + myScatter.setBrush(Qt::red); + ui->sctpPlot->graph(0)->setScatterStyle(myScatter); + ui->sctpPlot->graph(0)->setLineStyle(QCPGraph::lsNone); + ui->sctpPlot->graph(0)->setData(xa, ya); + } + + ui->sctpPlot->xAxis->setLabel("time [secs]"); + ui->sctpPlot->yAxis->setLabel("Advertised Receiver Window [Bytes]"); + + // set axes ranges, so we see all data: + QCPRange myXArwndRange(0, (selected_assoc->max_secs+1)); + // QCPRange myXArwndRange(0, 1); + QCPRange myYArwndRange(0, startArwnd); + ui->sctpPlot->xAxis->setRange(myXArwndRange); + ui->sctpPlot->yAxis->setRange(myYArwndRange); +} + + +void SCTPGraphArwndDialog::drawGraph() +{ + ui->sctpPlot->clearGraphs(); + drawArwndGraph(); + ui->sctpPlot->setInteractions(QCP::iRangeZoom | QCP::iRangeDrag | QCP::iSelectPlottables); + ui->sctpPlot->axisRect(0)->setRangeZoomAxes(ui->sctpPlot->xAxis, ui->sctpPlot->yAxis); + ui->sctpPlot->axisRect(0)->setRangeZoom(Qt::Horizontal); + connect(ui->sctpPlot, SIGNAL(plottableClick(QCPAbstractPlottable*,QMouseEvent*)), this, SLOT(graphClicked(QCPAbstractPlottable*, QMouseEvent*))); + ui->sctpPlot->replot(); +} + + +void SCTPGraphArwndDialog::on_pushButton_4_clicked() +{ + ui->sctpPlot->xAxis->setRange(selected_assoc->min_secs+selected_assoc->min_usecs/1000000.0, selected_assoc->max_secs+selected_assoc->max_usecs/1000000.0); + ui->sctpPlot->yAxis->setRange(0, startArwnd); + ui->sctpPlot->replot(); +} + +void SCTPGraphArwndDialog::graphClicked(QCPAbstractPlottable* plottable, QMouseEvent* event) +{ + if (plottable->name().contains("Arwnd", Qt::CaseInsensitive)) { + double times = ui->sctpPlot->xAxis->pixelToCoord(event->pos().x()); + int i=0; + for (i = 0; i < xa.size(); i++) { + if (times <= xa.value(i)) { + frame_num = fa.at(i); + break; + } + } + if (cap_file_ && frame_num > 0) { + cf_goto_frame(cap_file_, frame_num); + } + + ui->hintLabel->setText(QString("Graph %1: arwnd=%2 Time=%3 secs ") + .arg(plottable->name()) + .arg(ya.value(i)) + .arg(xa.value(i))); + } +} + + +void SCTPGraphArwndDialog::on_saveButton_clicked() +{ + SCTPGraphDialog::save_graph(this, ui->sctpPlot); +} diff --git a/ui/qt/sctp_graph_arwnd_dialog.h b/ui/qt/sctp_graph_arwnd_dialog.h new file mode 100644 index 0000000000..8be8c34b58 --- /dev/null +++ b/ui/qt/sctp_graph_arwnd_dialog.h @@ -0,0 +1,57 @@ +#ifndef SCTP_GRAPH_ARWND_DIALOG_H +#define SCTP_GRAPH_ARWND_DIALOG_H + +#include "config.h" +#include "qcustomplot.h" +#include + +#include +#include +#include +#include "epan/packet.h" + +#include "ui/tap-sctp-analysis.h" + +#include +#include +#include + +namespace Ui { +class SCTPGraphArwndDialog; +} + + +class SCTPGraphArwndDialog : public QDialog +{ + Q_OBJECT + +public: + explicit SCTPGraphArwndDialog(QWidget *parent = 0, sctp_assoc_info_t *assoc = NULL, capture_file *cf = NULL, int dir = 0); + ~SCTPGraphArwndDialog(); + +public slots: + void setCaptureFile(capture_file *cf) { cap_file_ = cf; } + +private slots: + void on_pushButton_4_clicked(); + + void graphClicked(QCPAbstractPlottable* plottable, QMouseEvent* event); + + void on_saveButton_clicked(); + +private: + Ui::SCTPGraphArwndDialog *ui; + sctp_assoc_info_t *selected_assoc; + capture_file *cap_file_; + int frame_num; + int direction; + int startArwnd; + QVector xa, ya; + QVector fa; + // QVector typeStrings; + + void drawGraph(); + void drawArwndGraph(); +}; + +#endif // SCTP_GRAPH_DIALOG_H diff --git a/ui/qt/sctp_graph_arwnd_dialog.ui b/ui/qt/sctp_graph_arwnd_dialog.ui new file mode 100644 index 0000000000..3ae71cbe84 --- /dev/null +++ b/ui/qt/sctp_graph_arwnd_dialog.ui @@ -0,0 +1,129 @@ + + + SCTPGraphArwndDialog + + + + 0 + 0 + 800 + 546 + + + + SCTP Graph + + + + + 20 + 30 + 761 + 451 + + + + + 0 + 1 + + + + + + + 10 + 510 + 131 + 32 + + + + Qt::NoFocus + + + Reset to full size + + + + + + 680 + 510 + 120 + 32 + + + + Qt::NoFocus + + + Qt::Horizontal + + + QDialogButtonBox::Close + + + + + + 10 + 490 + 655 + 12 + + + + <html><head/><body><p><br/></p></body></html> + + + + + + 140 + 510 + 114 + 32 + + + + Save Graph + + + + + goToPacket + + + Go to Packet + + + + + + QCustomPlot + QWidget +
qcustomplot.h
+ 1 +
+
+ + + + buttonBox + clicked(QAbstractButton*) + SCTPGraphArwndDialog + close() + + + 706 + 530 + + + 703 + 574 + + + + +
diff --git a/ui/qt/sctp_graph_byte_dialog.cpp b/ui/qt/sctp_graph_byte_dialog.cpp new file mode 100644 index 0000000000..0574150010 --- /dev/null +++ b/ui/qt/sctp_graph_byte_dialog.cpp @@ -0,0 +1,145 @@ +#include "sctp_graph_byte_dialog.h" +#include "ui_sctp_graph_byte_dialog.h" + +#include "sctp_graph_dialog.h" + +SCTPGraphByteDialog::SCTPGraphByteDialog(QWidget *parent, sctp_assoc_info_t *assoc, capture_file *cf, int dir) : + QDialog(parent), + ui(new Ui::SCTPGraphByteDialog), + selected_assoc(assoc), + cap_file_(cf), + direction(dir) +{ + ui->setupUi(this); + this->setWindowTitle(QString("SCTP Data and Adv. Rec. Window over Time: %1 Port1 %2 Port2 %3").arg(cf_get_display_name(cap_file_)).arg(selected_assoc->port1).arg(selected_assoc->port2)); + if ((direction == 1 && selected_assoc->n_array_tsn1 == 0) || (direction == 2 && selected_assoc->n_array_tsn2 == 0)) { + QMessageBox msgBox; + msgBox.setText("No Data Chunks sent"); + msgBox.exec(); + return; + } else { + drawGraph(); + } +} + +SCTPGraphByteDialog::~SCTPGraphByteDialog() +{ + delete ui; +} + + +void SCTPGraphByteDialog::drawBytesGraph() +{ + GList *listTSN = NULL,*tlist; + tsn_t *tsn; + guint8 type; + guint32 minBytes, maxBytes; + long sumBytes = 0; + // printf("drawBytesGraph\n"); + if (direction == 1) { + minBytes = 0; //selected_assoc->min_tsn1; + maxBytes = selected_assoc->n_data_bytes_ep1; + listTSN = g_list_last(selected_assoc->tsn1); + } else { + minBytes = 0; //selected_assoc->min_tsn2; + maxBytes = selected_assoc->n_data_bytes_ep2; + listTSN = g_list_last(selected_assoc->tsn2); + } + + + while (listTSN) { + tsn = (tsn_t*) (listTSN->data); + tlist = g_list_first(tsn->tsns); + guint16 length; + while (tlist) + { + type = ((struct chunk_header *)tlist->data)->type; + if (type == SCTP_DATA_CHUNK_ID) { + length = g_ntohs(((struct data_chunk_header *)tlist->data)->length); + sumBytes += length; + yb.append(sumBytes); + xb.append(tsn->secs + tsn->usecs/1000000.0); + // printf("x=%f y=%ld\n", tsn->secs + tsn->usecs/1000000.0, sumBytes); + fb.append(tsn->frame_number); + } + tlist = g_list_next(tlist); + } + listTSN = g_list_previous(listTSN); + } + + + QCPScatterStyle myScatter; + myScatter.setShape(QCPScatterStyle::ssCircle); + myScatter.setSize(3); + + // create graph and assign data to it: + + // Add Bytes graph + if (xb.size() > 0) { + QCPGraph *gr = ui->sctpPlot->addGraph(ui->sctpPlot->xAxis, ui->sctpPlot->yAxis); + gr->setName(QString("Bytes")); + myScatter.setPen(QPen(Qt::red)); + myScatter.setBrush(Qt::red); + ui->sctpPlot->graph(0)->setScatterStyle(myScatter); + ui->sctpPlot->graph(0)->setLineStyle(QCPGraph::lsNone); + ui->sctpPlot->graph(0)->setData(xb, yb); + } + ui->sctpPlot->xAxis->setLabel("time [secs]"); + ui->sctpPlot->yAxis->setLabel("Received Bytes"); + + // set axes ranges, so we see all data: + QCPRange myXByteRange(0, (selected_assoc->max_secs+1)); + QCPRange myYByteRange(0, maxBytes); + ui->sctpPlot->xAxis->setRange(myXByteRange); + ui->sctpPlot->yAxis->setRange(myYByteRange); +} + + +void SCTPGraphByteDialog::drawGraph() +{ + ui->sctpPlot->clearGraphs(); + drawBytesGraph(); + ui->sctpPlot->setInteractions(QCP::iRangeZoom | QCP::iRangeDrag | QCP::iSelectPlottables); + connect(ui->sctpPlot, SIGNAL(plottableClick(QCPAbstractPlottable*,QMouseEvent*)), this, SLOT(graphClicked(QCPAbstractPlottable*, QMouseEvent*))); + ui->sctpPlot->replot(); +} + + +void SCTPGraphByteDialog::on_pushButton_4_clicked() +{ + ui->sctpPlot->xAxis->setRange(selected_assoc->min_secs+selected_assoc->min_usecs/1000000.0, selected_assoc->max_secs+selected_assoc->max_usecs/1000000.0); + if (direction == 1) { + ui->sctpPlot->yAxis->setRange(0, selected_assoc->n_data_bytes_ep1); + } else { + ui->sctpPlot->yAxis->setRange(0, selected_assoc->n_data_bytes_ep2); + } + ui->sctpPlot->replot(); +} + +void SCTPGraphByteDialog::graphClicked(QCPAbstractPlottable* plottable, QMouseEvent* event) +{ + if (plottable->name().contains("Bytes", Qt::CaseInsensitive)) { + double bytes = round(ui->sctpPlot->yAxis->pixelToCoord(event->pos().y())); + int i; + for (i = 0; i < yb.size(); i++) { + if (bytes <= yb.value(i)) { + frame_num = fb.at(i); + break; + } + } + if (cap_file_ && frame_num > 0) { + cf_goto_frame(cap_file_, frame_num); + } + + ui->hintLabel->setText(QString("Graph %1: Received bytes=%2 Time=%3 secs ") + .arg(plottable->name()) + .arg(yb.value(i)) + .arg(xb.value(i))); + } +} + + +void SCTPGraphByteDialog::on_saveButton_clicked() +{ + SCTPGraphDialog::save_graph(this, ui->sctpPlot); +} diff --git a/ui/qt/sctp_graph_byte_dialog.h b/ui/qt/sctp_graph_byte_dialog.h new file mode 100644 index 0000000000..4a8fa5d595 --- /dev/null +++ b/ui/qt/sctp_graph_byte_dialog.h @@ -0,0 +1,55 @@ +#ifndef SCTP_GRAPH_BYTE_DIALOG_H +#define SCTP_GRAPH_BYTE_DIALOG_H + +#include "config.h" +#include "qcustomplot.h" +#include + +#include +#include +#include +#include "epan/packet.h" + +#include "ui/tap-sctp-analysis.h" + +#include +#include +#include + +namespace Ui { +class SCTPGraphByteDialog; +} + + +class SCTPGraphByteDialog : public QDialog +{ + Q_OBJECT + +public: + explicit SCTPGraphByteDialog(QWidget *parent = 0, sctp_assoc_info_t *assoc = NULL, capture_file *cf = NULL, int dir = 0); + ~SCTPGraphByteDialog(); + +public slots: + void setCaptureFile(capture_file *cf) { cap_file_ = cf; } + +private slots: + void on_pushButton_4_clicked(); + + void graphClicked(QCPAbstractPlottable* plottable, QMouseEvent* event); + + void on_saveButton_clicked(); + +private: + Ui::SCTPGraphByteDialog *ui; + sctp_assoc_info_t *selected_assoc; + capture_file *cap_file_; + int frame_num; + int direction; + QVector xb, yb; + QVector fb; + + void drawGraph(); + void drawBytesGraph(); +}; + +#endif // SCTP_GRAPH_DIALOG_H diff --git a/ui/qt/sctp_graph_byte_dialog.ui b/ui/qt/sctp_graph_byte_dialog.ui new file mode 100644 index 0000000000..984397f93e --- /dev/null +++ b/ui/qt/sctp_graph_byte_dialog.ui @@ -0,0 +1,129 @@ + + + SCTPGraphByteDialog + + + + 0 + 0 + 800 + 546 + + + + SCTP Graph + + + + + 20 + 30 + 761 + 451 + + + + + 0 + 1 + + + + + + + 10 + 510 + 131 + 32 + + + + Qt::NoFocus + + + Reset to full size + + + + + + 680 + 510 + 120 + 32 + + + + Qt::NoFocus + + + Qt::Horizontal + + + QDialogButtonBox::Close + + + + + + 10 + 490 + 655 + 12 + + + + <html><head/><body><p><br/></p></body></html> + + + + + + 140 + 510 + 114 + 32 + + + + Save Graph + + + + + goToPacket + + + Go to Packet + + + + + + QCustomPlot + QWidget +
qcustomplot.h
+ 1 +
+
+ + + + buttonBox + clicked(QAbstractButton*) + SCTPGraphByteDialog + close() + + + 706 + 530 + + + 703 + 574 + + + + +
diff --git a/ui/qt/sctp_graph_dialog.cpp b/ui/qt/sctp_graph_dialog.cpp new file mode 100644 index 0000000000..83c7ff907e --- /dev/null +++ b/ui/qt/sctp_graph_dialog.cpp @@ -0,0 +1,399 @@ +#include "sctp_graph_dialog.h" +#include "ui_sctp_graph_dialog.h" + +#include "wireshark_application.h" + +SCTPGraphDialog::SCTPGraphDialog(QWidget *parent, sctp_assoc_info_t *assoc, capture_file *cf, int dir) : + QDialog(parent), + ui(new Ui::SCTPGraphDialog), + selected_assoc(assoc), + cap_file_(cf), + direction(dir) +{ + ui->setupUi(this); + this->setWindowTitle(QString("SCTP TSNs and SACKs over Time: %1 Port1 %2 Port2 %3").arg(cf_get_display_name(cap_file_)).arg(selected_assoc->port1).arg(selected_assoc->port2)); + if ((direction == 1 && selected_assoc->n_array_tsn1 == 0) || (direction == 2 && selected_assoc->n_array_tsn2 == 0)) { + QMessageBox msgBox; + msgBox.setText("No Data Chunks sent"); + msgBox.exec(); + return; + } else { + drawGraph(3); + } +} + +SCTPGraphDialog::~SCTPGraphDialog() +{ + delete ui; +} + +void SCTPGraphDialog::drawNRSACKGraph() +{ + tsn_t *sack; + GList *list=NULL, *tlist; + guint16 gap_start=0, gap_end=0, i, numberOf_gaps, numberOf_nr_gaps; + guint8 type; + guint32 tsnumber, j, min_tsn; + struct nr_sack_chunk_header *nr_sack_header; + struct gaps *nr_gap; + /* This holds the sum of gap acks and nr gap acks */ + guint16 total_gaps = 0; + + if (direction == 1) { + list = g_list_last(selected_assoc->sack1); + min_tsn = selected_assoc->min_tsn1; + } else { + list = g_list_last(selected_assoc->sack1); + min_tsn = selected_assoc->min_tsn1; + } + while (list) { + sack = (tsn_t*) (list->data); + tlist = g_list_first(sack->tsns); + while (tlist) { + type = ((struct chunk_header *)tlist->data)->type; + if (type == SCTP_NR_SACK_CHUNK_ID) { + gIsNRSackChunkPresent = 1; + nr_sack_header =(struct nr_sack_chunk_header *)tlist->data; + numberOf_nr_gaps=g_ntohs(nr_sack_header->nr_of_nr_gaps); + numberOf_gaps=g_ntohs(nr_sack_header->nr_of_gaps); + tsnumber = g_ntohl(nr_sack_header->cum_tsn_ack); + total_gaps = numberOf_gaps + numberOf_nr_gaps; + /* If the number of nr_gaps is greater than 0 */ + if ( total_gaps > 0 ) { + nr_gap = &nr_sack_header->gaps[0]; + for (i = 0; i < total_gaps; i++) { + gap_start = g_ntohs(nr_gap->start); + gap_end = g_ntohs(nr_gap->end); + for ( j = gap_start; j <= gap_end; j++) { + if (i >= numberOf_gaps) { + yn.append(j + tsnumber); + xn.append(sack->secs + sack->usecs/1000000.0); + fn.append(sack->frame_number); + } else { + yg.append(j + tsnumber); + xg.append(sack->secs + sack->usecs/1000000.0); + fg.append(sack->frame_number); + } + } + if (i < total_gaps-1) + nr_gap++; + } + + if (tsnumber>=min_tsn) { + ys.append(j + tsnumber); + xs.append(sack->secs + sack->usecs/1000000.0); + fs.append(sack->frame_number); + } + } + } + tlist = g_list_next(tlist); + } + list = g_list_previous(list); + } +} + +void SCTPGraphDialog::drawSACKGraph() +{ + GList *listSACK = NULL, *tlist; + guint16 gap_start=0, gap_end=0, nr, dup_nr; + struct sack_chunk_header *sack_header; + struct gaps *gap; + tsn_t *tsn; + guint8 type; + guint32 tsnumber=0; + guint32 minTSN; + guint32 *dup_list; + int i, j; + + if (direction == 1) { + minTSN = selected_assoc->min_tsn1; + listSACK = g_list_last(selected_assoc->sack1); + } else { + minTSN = selected_assoc->min_tsn2; + listSACK = g_list_last(selected_assoc->sack2); + } + while (listSACK) { + tsn = (tsn_t*) (listSACK->data); + tlist = g_list_first(tsn->tsns); + while (tlist) { + type = ((struct chunk_header *)tlist->data)->type; + if (type == SCTP_SACK_CHUNK_ID) { + gIsSackChunkPresent = 1; + sack_header =(struct sack_chunk_header *)tlist->data; + nr=g_ntohs(sack_header->nr_of_gaps); + tsnumber = g_ntohl(sack_header->cum_tsn_ack); + dup_nr=g_ntohs(sack_header->nr_of_dups); + if (nr>0) { // Gap Reports green + gap = &sack_header->gaps[0]; + for(i=0;istart); + gap_end = g_ntohs(gap->end); + for (j=gap_start; j<=gap_end; j++) { + yg.append(j+tsnumber); + xg.append(tsn->secs + tsn->usecs/1000000.0); + fg.append(tsn->frame_number); + } + if (i < nr-1) + gap++; + } + } + if (tsnumber>=minTSN) { // CumTSNAck red + ys.append(tsnumber); + xs.append(tsn->secs + tsn->usecs/1000000.0); + fs.append(tsn->frame_number); + } + if (dup_nr > 0) { // Duplicates cyan + dup_list = &sack_header->a_rwnd + 2 + nr; + for (i = 0; i < dup_nr; i++) { + tsnumber = g_ntohl(dup_list[i]); + if (tsnumber >= minTSN) { + yd.append(tsnumber); + xd.append(tsn->secs + tsn->usecs/1000000.0); + fd.append(tsn->frame_number); + } + } + } + } + tlist = g_list_next(tlist); + } + listSACK = g_list_previous(listSACK); + } + + QCPScatterStyle myScatter; + myScatter.setShape(QCPScatterStyle::ssCircle); + myScatter.setSize(3); + + int graphcount = ui->sctpPlot->graphCount(); + // create graph and assign data to it: + + // Add SACK graph + if (xs.size() > 0) { + ui->sctpPlot->addGraph(); + myScatter.setPen(QPen(Qt::red)); + myScatter.setBrush(Qt::red); + ui->sctpPlot->graph(graphcount)->setScatterStyle(myScatter); + ui->sctpPlot->graph(graphcount)->setLineStyle(QCPGraph::lsNone); + ui->sctpPlot->graph(graphcount)->setData(xs, ys); + typeStrings.insert(graphcount, QString("CumTSNAck")); + graphcount++; + } + + // Add Gap Acks + if (xg.size() > 0) { + ui->sctpPlot->addGraph(); + myScatter.setPen(QPen(Qt::green)); + myScatter.setBrush(Qt::green); + ui->sctpPlot->graph(graphcount)->setScatterStyle(myScatter); + ui->sctpPlot->graph(graphcount)->setLineStyle(QCPGraph::lsNone); + ui->sctpPlot->graph(graphcount)->setData(xg, yg); + typeStrings.insert(graphcount, QString("Gap Ack")); + graphcount++; + } + + // Add NR Gap Acks + if (xn.size() > 0) { + ui->sctpPlot->addGraph(); + myScatter.setPen(QPen(Qt::blue)); + myScatter.setBrush(Qt::blue); + ui->sctpPlot->graph(graphcount)->setScatterStyle(myScatter); + ui->sctpPlot->graph(graphcount)->setLineStyle(QCPGraph::lsNone); + ui->sctpPlot->graph(graphcount)->setData(xg, yg); + typeStrings.insert(graphcount, QString("NR Gap Ack")); + graphcount++; + } + + // Add Duplicates + if (xd.size() > 0) { + ui->sctpPlot->addGraph(); + myScatter.setPen(QPen(Qt::cyan)); + myScatter.setBrush(Qt::cyan); + ui->sctpPlot->graph(graphcount)->setScatterStyle(myScatter); + ui->sctpPlot->graph(graphcount)->setLineStyle(QCPGraph::lsNone); + ui->sctpPlot->graph(graphcount)->setData(xd, yd); + typeStrings.insert(graphcount, QString("Duplicate Ack")); + } +} + +void SCTPGraphDialog::drawTSNGraph() +{ + GList *listTSN = NULL,*tlist; + tsn_t *tsn; + guint8 type; + guint32 tsnumber=0; + guint32 minTSN; + + if (direction == 1) { + minTSN = selected_assoc->min_tsn1; + listTSN = g_list_last(selected_assoc->tsn1); + } else { + minTSN = selected_assoc->min_tsn2; + listTSN = g_list_last(selected_assoc->tsn2); + } + + + while (listTSN) { + tsn = (tsn_t*) (listTSN->data); + tlist = g_list_first(tsn->tsns); + while (tlist) + { + type = ((struct chunk_header *)tlist->data)->type; + if (type == SCTP_DATA_CHUNK_ID || type == SCTP_FORWARD_TSN_CHUNK_ID) { + tsnumber = g_ntohl(((struct data_chunk_header *)tlist->data)->tsn); + yt.append(tsnumber); + xt.append(tsn->secs + tsn->usecs/1000000.0); + ft.append(tsn->frame_number); + } + tlist = g_list_next(tlist); + } + listTSN = g_list_previous(listTSN); + } + + QCPScatterStyle myScatter; + myScatter.setShape(QCPScatterStyle::ssCircle); + myScatter.setSize(3); + + int graphcount = ui->sctpPlot->graphCount(); + // create graph and assign data to it: + + // Add TSN graph + if (xt.size() > 0) { + ui->sctpPlot->addGraph(); + myScatter.setPen(QPen(Qt::black)); + myScatter.setBrush(Qt::black); + ui->sctpPlot->graph(graphcount)->setScatterStyle(myScatter); + ui->sctpPlot->graph(graphcount)->setLineStyle(QCPGraph::lsNone); + ui->sctpPlot->graph(graphcount)->setData(xt, yt); + typeStrings.insert(graphcount, QString("TSN")); + } +} + +void SCTPGraphDialog::drawGraph(int which) +{ + guint32 minTSN, maxTSN; + + gIsSackChunkPresent = false; + gIsNRSackChunkPresent = false; + + if (direction == 1) { + minTSN = selected_assoc->min_tsn1; + maxTSN = selected_assoc->max_tsn1; + } else { + minTSN = selected_assoc->min_tsn2; + maxTSN = selected_assoc->max_tsn2; + } + + switch (which) { + case 1: drawSACKGraph(); + drawNRSACKGraph(); + break; + case 2: drawTSNGraph(); + break; + case 3: drawTSNGraph(); + drawSACKGraph(); + drawNRSACKGraph(); + break; + default: drawTSNGraph(); + drawSACKGraph(); + drawNRSACKGraph(); + } + + // give the axes some labels: + ui->sctpPlot->xAxis->setLabel("time [secs]"); + ui->sctpPlot->yAxis->setLabel("TSNs"); + ui->sctpPlot->setInteractions(QCP::iRangeZoom | QCP::iRangeDrag | QCP::iSelectPlottables); + connect(ui->sctpPlot, SIGNAL(plottableClick(QCPAbstractPlottable*,QMouseEvent*)), this, SLOT(graphClicked(QCPAbstractPlottable*, QMouseEvent*))); + // set axes ranges, so we see all data: + QCPRange myXRange(0, (selected_assoc->max_secs+1)); + QCPRange myYRange(0, maxTSN); + ui->sctpPlot->xAxis->setRange(myXRange); + ui->sctpPlot->yAxis->setRange(myYRange); + ui->sctpPlot->replot(); +} + +void SCTPGraphDialog::on_pushButton_clicked() +{ + drawGraph(1); +} + +void SCTPGraphDialog::on_pushButton_2_clicked() +{ + drawGraph(2); +} + +void SCTPGraphDialog::on_pushButton_3_clicked() +{ + drawGraph(3); +} + +void SCTPGraphDialog::on_pushButton_4_clicked() +{ + ui->sctpPlot->xAxis->setRange(selected_assoc->min_secs+selected_assoc->min_usecs/1000000.0, selected_assoc->max_secs+selected_assoc->max_usecs/1000000.0); + if (direction == 1) { + ui->sctpPlot->yAxis->setRange(selected_assoc->min_tsn1, selected_assoc->max_tsn1); + } else { + ui->sctpPlot->yAxis->setRange(selected_assoc->min_tsn2, selected_assoc->max_tsn2); + } + ui->sctpPlot->replot(); +} + +void SCTPGraphDialog::graphClicked(QCPAbstractPlottable* plottable, QMouseEvent* event) +{ + if (plottable->name().contains("Graph", Qt::CaseInsensitive)) { + // double tsn = round(ui->sctpPlot->yAxis->pixelToCoord(event->pos().y())); + int index = yt.indexOf(round(ui->sctpPlot->yAxis->pixelToCoord(event->pos().y()))); + // double time = xt.at(index); + frame_num = ft.at(index); + if (cap_file_ && frame_num > 0) { + cf_goto_frame(cap_file_, frame_num); + } + } + int num = plottable->name().remove("Graph ",Qt::CaseInsensitive).toInt(); + ui->hintLabel->setText(QString("%1: %2: %3 Time: %4 secs ") + .arg(plottable->name()) + .arg(typeStrings[num-1]) + .arg(round(ui->sctpPlot->yAxis->pixelToCoord(event->pos().y()))) + .arg(ui->sctpPlot->xAxis->pixelToCoord(event->pos().x()))); +} + +void SCTPGraphDialog::save_graph(QDialog *dlg, QCustomPlot *plot) +{ + QString file_name, extension; + QDir path(wsApp->lastOpenDir()); + QString pdf_filter = tr("Portable Document Format (*.pdf)"); + QString png_filter = tr("Portable Network Graphics (*.png)"); + QString bmp_filter = tr("Windows Bitmap (*.bmp)"); + // Gaze upon my beautiful graph with lossy artifacts! + QString jpeg_filter = tr("JPEG File Interchange Format (*.jpeg *.jpg)"); + QString filter = QString("%1;;%2;;%3;;%4") + .arg(pdf_filter) + .arg(png_filter) + .arg(bmp_filter) + .arg(jpeg_filter); + + file_name = QFileDialog::getSaveFileName(dlg, tr("Wireshark: Save Graph As..."), + path.canonicalPath(), filter, &extension); + + if (file_name.length() > 0) { + bool save_ok = false; + if (extension.compare(pdf_filter) == 0) { + save_ok = plot->savePdf(file_name); + } else if (extension.compare(png_filter) == 0) { + save_ok = plot->savePng(file_name); + } else if (extension.compare(bmp_filter) == 0) { + save_ok = plot->saveBmp(file_name); + } else if (extension.compare(jpeg_filter) == 0) { + save_ok = plot->saveJpg(file_name); + } + // else error dialog? + if (save_ok) { + path = QDir(file_name); + wsApp->setLastOpenDir(path.canonicalPath().toUtf8().constData()); + } + } +} + + +void SCTPGraphDialog::on_saveButton_clicked() +{ + save_graph(this, ui->sctpPlot); +} diff --git a/ui/qt/sctp_graph_dialog.h b/ui/qt/sctp_graph_dialog.h new file mode 100644 index 0000000000..29f7c0a089 --- /dev/null +++ b/ui/qt/sctp_graph_dialog.h @@ -0,0 +1,114 @@ +#ifndef SCTP_GRAPH_DIALOG_H +#define SCTP_GRAPH_DIALOG_H + +#include "config.h" +#include "qcustomplot.h" +#include + +#include +#include +#include +#include "epan/packet.h" + +#include "ui/tap-sctp-analysis.h" + +#include +#include +#include +#include +#include + +namespace Ui { +class SCTPGraphDialog; +} + +struct chunk_header { + guint8 type; + guint8 flags; + guint16 length; +}; + +struct data_chunk_header { + guint8 type; + guint8 flags; + guint16 length; + guint32 tsn; + guint16 sid; + guint16 ssn; + guint32 ppi; +}; + +struct gaps { + guint16 start; + guint16 end; +}; + +struct sack_chunk_header { + guint8 type; + guint8 flags; + guint16 length; + guint32 cum_tsn_ack; + guint32 a_rwnd; + guint16 nr_of_gaps; + guint16 nr_of_dups; + struct gaps gaps[1]; +}; + +struct nr_sack_chunk_header { + guint8 type; + guint8 flags; + guint16 length; + guint32 cum_tsn_ack; + guint32 a_rwnd; + guint16 nr_of_gaps; + guint16 nr_of_nr_gaps; + guint16 nr_of_dups; + guint16 reserved; + struct gaps gaps[1]; +}; + + +class SCTPGraphDialog : public QDialog +{ + Q_OBJECT + +public: + explicit SCTPGraphDialog(QWidget *parent = 0, sctp_assoc_info_t *assoc = NULL, capture_file *cf = NULL, int dir = 0); + ~SCTPGraphDialog(); + static void save_graph(QDialog *dlg, QCustomPlot *plot); + +public slots: + void setCaptureFile(capture_file *cf) { cap_file_ = cf; } + +private slots: + void on_pushButton_clicked(); + + void on_pushButton_2_clicked(); + + void on_pushButton_3_clicked(); + + void on_pushButton_4_clicked(); + + void graphClicked(QCPAbstractPlottable* plottable, QMouseEvent* event); + + void on_saveButton_clicked(); + +private: + Ui::SCTPGraphDialog *ui; + sctp_assoc_info_t *selected_assoc; + capture_file *cap_file_; + int frame_num; + int direction; + QVector xt, yt, xs, ys, xg, yg, xd, yd, xn, yn; + QVector ft, fs, fg, fd, fn; + QVector typeStrings; + bool gIsSackChunkPresent; + bool gIsNRSackChunkPresent; + + void drawGraph(int which); + void drawTSNGraph(); + void drawSACKGraph(); + void drawNRSACKGraph(); +}; + +#endif // SCTP_GRAPH_DIALOG_H diff --git a/ui/qt/sctp_graph_dialog.ui b/ui/qt/sctp_graph_dialog.ui new file mode 100644 index 0000000000..2a5a847bd6 --- /dev/null +++ b/ui/qt/sctp_graph_dialog.ui @@ -0,0 +1,177 @@ + + + SCTPGraphDialog + + + + 0 + 0 + 800 + 546 + + + + SCTP Graph + + + + + 20 + 30 + 761 + 451 + + + + + 0 + 1 + + + + + + + 0 + 510 + 120 + 32 + + + + Qt::NoFocus + + + Only SACKs + + + + + + 120 + 510 + 120 + 32 + + + + Qt::NoFocus + + + Only TSNs + + + + + + 240 + 510 + 120 + 32 + + + + Qt::NoFocus + + + Show both + + + + + + 360 + 510 + 131 + 32 + + + + Qt::NoFocus + + + Reset to full size + + + + + + 680 + 510 + 120 + 32 + + + + Qt::NoFocus + + + Qt::Horizontal + + + QDialogButtonBox::Close + + + + + + 10 + 490 + 655 + 12 + + + + <html><head/><body><p><br/></p></body></html> + + + + + + 490 + 510 + 114 + 32 + + + + Save Graph + + + + + goToPacket + + + Go to Packet + + + + + + QCustomPlot + QWidget +
qcustomplot.h
+ 1 +
+
+ + + + buttonBox + clicked(QAbstractButton*) + SCTPGraphDialog + close() + + + 706 + 530 + + + 703 + 574 + + + + +
diff --git a/ui/tap-sctp-analysis.c b/ui/tap-sctp-analysis.c index 77a64e615e..8344bce1cd 100644 --- a/ui/tap-sctp-analysis.c +++ b/ui/tap-sctp-analysis.c @@ -36,68 +36,6 @@ #include "ui/simple_dialog.h" -#define SCTP_ABORT_CHUNK_T_BIT 0x01 - -#define PARAMETER_TYPE_LENGTH 2 -#define PARAMETER_LENGTH_LENGTH 2 -#define PARAMETER_HEADER_LENGTH (PARAMETER_TYPE_LENGTH + PARAMETER_LENGTH_LENGTH) - -#define PARAMETER_HEADER_OFFSET 0 -#define PARAMETER_TYPE_OFFSET PARAMETER_HEADER_OFFSET -#define PARAMETER_LENGTH_OFFSET (PARAMETER_TYPE_OFFSET + PARAMETER_TYPE_LENGTH) -#define PARAMETER_VALUE_OFFSET (PARAMETER_LENGTH_OFFSET + PARAMETER_LENGTH_LENGTH) - -#define IPV6_ADDRESS_LENGTH 16 -#define IPV6_ADDRESS_OFFSET PARAMETER_VALUE_OFFSET -#define IPV4_ADDRESS_LENGTH 4 -#define IPV4_ADDRESS_OFFSET PARAMETER_VALUE_OFFSET -#define IPV4ADDRESS_PARAMETER_ID 0x0005 -#define IPV6ADDRESS_PARAMETER_ID 0x0006 - -#define SACK_CHUNK_CUMULATIVE_TSN_ACK_LENGTH 4 -#define SACK_CHUNK_CUMULATIVE_TSN_ACK_OFFSET (CHUNK_VALUE_OFFSET + 0) -#define SACK_CHUNK_ADV_REC_WINDOW_CREDIT_LENGTH 4 -#define SACK_CHUNK_ADV_REC_WINDOW_CREDIT_OFFSET (SACK_CHUNK_CUMULATIVE_TSN_ACK_OFFSET + \ - SACK_CHUNK_CUMULATIVE_TSN_ACK_LENGTH) - -#define INIT_CHUNK_INITIAL_TSN_LENGTH 4 -#define INIT_CHUNK_FIXED_PARAMTERS_LENGTH (INIT_CHUNK_INITIATE_TAG_LENGTH + \ - INIT_CHUNK_ADV_REC_WINDOW_CREDIT_LENGTH + \ - INIT_CHUNK_NUMBER_OF_OUTBOUND_STREAMS_LENGTH + \ - INIT_CHUNK_NUMBER_OF_INBOUND_STREAMS_LENGTH + \ - INIT_CHUNK_INITIAL_TSN_LENGTH) -#define CHUNK_HEADER_LENGTH (CHUNK_TYPE_LENGTH + \ - CHUNK_FLAGS_LENGTH + \ - CHUNK_LENGTH_LENGTH) -#define INIT_CHUNK_VARIABLE_LENGTH_PARAMETER_OFFSET (INIT_CHUNK_INITIAL_TSN_OFFSET + \ - INIT_CHUNK_INITIAL_TSN_LENGTH ) - -static const value_string chunk_type_values[] = { - { SCTP_DATA_CHUNK_ID, "DATA" }, - { SCTP_INIT_CHUNK_ID, "INIT" }, - { SCTP_INIT_ACK_CHUNK_ID, "INIT_ACK" }, - { SCTP_SACK_CHUNK_ID, "SACK" }, - { SCTP_HEARTBEAT_CHUNK_ID, "HEARTBEAT" }, - { SCTP_HEARTBEAT_ACK_CHUNK_ID, "HEARTBEAT_ACK" }, - { SCTP_ABORT_CHUNK_ID, "ABORT" }, - { SCTP_SHUTDOWN_CHUNK_ID, "SHUTDOWN" }, - { SCTP_SHUTDOWN_ACK_CHUNK_ID, "SHUTDOWN_ACK" }, - { SCTP_ERROR_CHUNK_ID, "ERROR" }, - { SCTP_COOKIE_ECHO_CHUNK_ID, "COOKIE_ECHO" }, - { SCTP_COOKIE_ACK_CHUNK_ID, "COOKIE_ACK" }, - { SCTP_ECNE_CHUNK_ID, "ECNE" }, - { SCTP_CWR_CHUNK_ID, "CWR" }, - { SCTP_SHUTDOWN_COMPLETE_CHUNK_ID, "SHUTDOWN_COMPLETE" }, - { SCTP_FORWARD_TSN_CHUNK_ID, "FORWARD TSN" }, - { SCTP_ASCONF_ACK_CHUNK_ID, "ASCONF_ACK" }, - { SCTP_PKTDROP_CHUNK_ID, "PKTDROP" }, - { SCTP_ASCONF_CHUNK_ID, "ASCONF" }, - { SCTP_IETF_EXT, "IETF_EXTENSION" }, - { SCTP_NR_SACK_CHUNK_ID, "NR_SACK" }, - { SCTP_AUTH_CHUNK_ID, "AUTH" }, - { 0, NULL } }; - - #define FORWARD_STREAM 0 #define BACKWARD_STREAM 1 #define FORWARD_ADD_FORWARD_VTAG 2 @@ -272,145 +210,20 @@ static sctp_assoc_info_t *calc_checksum(struct _sctp_info *check_data, sctp_asso } -static gint sctp_assoc_vtag_cmp(const sctp_tmp_info_t *a, const sctp_assoc_info_t *b) -{ - - if (a == NULL || b == NULL) - return(ASSOC_NOT_FOUND); - - if ((a->port1 == b->port1) && - (a->port2 == b->port2) && - (a->verification_tag1 == b->verification_tag1) && a->verification_tag1==0 && a->initiate_tag != 0 && - (a->initiate_tag != b->initiate_tag )) - return(ASSOC_NOT_FOUND); /* two INITs that belong to different assocs */ - - /* assoc known*/ - if ((a->port1 == b->port1) && - (a->port2 == b->port2) && - (a->verification_tag1 == b->verification_tag1) && - ((a->verification_tag1 != 0 || - (b->verification_tag2 != 0)))) - return(FORWARD_STREAM); - - /* ABORT, vtag reflected */ - if ((a->port1 == b->port1) && - (a->port2 == b->port2) && - (a->verification_tag2 == b->verification_tag2) && - (a->verification_tag1 == 0 && b->verification_tag1 != 0)) - return(FORWARD_STREAM); - - if ((a->port1 == b->port2) && - (a->port2 == b->port1) && - (a->verification_tag1 == b->verification_tag2) && - (a->verification_tag1 != 0)) - return(BACKWARD_STREAM); - - if ((a->port1 == b->port2) && - (a->port2 == b->port1) && - (a->verification_tag2 == b->verification_tag1) && - (a->verification_tag2 != 0)) - return(BACKWARD_STREAM); - - /* ABORT, vtag reflected */ - if ((a->port1 == b->port2) && - (a->port2 == b->port1) && - (a->verification_tag2 == b->verification_tag1) && - (a->verification_tag1 == 0 && b->verification_tag2 != 0)) - return(BACKWARD_STREAM); - - /*forward stream verifivation tag can be added*/ - if ((a->port1 == b->port1) && - (a->port2 == b->port2) && - (a->verification_tag1 != 0) && - (b->verification_tag1 == 0) && - (b->verification_tag2 !=0)) - return (FORWARD_ADD_FORWARD_VTAG); - - if ((a->port1 == b->port2) && - (a->port2 == b->port1) && - (a->verification_tag1 == b->verification_tag2) && - (b->verification_tag1 == 0)) - return (BACKWARD_ADD_FORWARD_VTAG); - - /*backward stream verification tag can be added */ - if ((a->port1 == b->port2) && - (a->port2 == b->port1) && - (a->verification_tag1 !=0) && - (b->verification_tag1 != 0) && - (b->verification_tag2 == 0)) - return(BACKWARD_ADD_BACKWARD_VTAG); - - return(ASSOC_NOT_FOUND); -} - static sctp_assoc_info_t * find_assoc(sctp_tmp_info_t * needle) { sctp_allassocs_info_t *assoc_info; sctp_assoc_info_t *info = NULL; GList* list; - guint8 cmp; assoc_info = &sctp_tapinfo_struct; if ((list = g_list_last(assoc_info->assoc_info_list))!=NULL) { while (list) { - cmp=sctp_assoc_vtag_cmp(needle, (sctp_assoc_info_t*)(list->data)); - - switch (cmp) - { - case FORWARD_STREAM: - info = (sctp_assoc_info_t*)(list->data); - info->direction = 1; - return info; - case BACKWARD_STREAM: - info = (sctp_assoc_info_t*)(list->data); - info->direction = 2; - return info; - case FORWARD_ADD_FORWARD_VTAG: - info = (sctp_assoc_info_t*)(list->data); - info->verification_tag1=needle->verification_tag1; - info->direction = 1; - return info; - case BACKWARD_ADD_FORWARD_VTAG: - info = (sctp_assoc_info_t*)(list->data); - info->verification_tag1=needle->verification_tag1; - info->direction = 2; - return info; - case BACKWARD_ADD_BACKWARD_VTAG: - info = (sctp_assoc_info_t*)(list->data); - info->verification_tag2=needle->verification_tag1; - info->direction = 2; - return info; - case ADDRESS_FORWARD_STREAM: - info = (sctp_assoc_info_t*)(list->data); - info->direction = 1; - info->check_address=TRUE; - return info; - case ADDRESS_BACKWARD_STREAM: - info = (sctp_assoc_info_t*)(list->data); - info->direction = 2; - info->check_address=TRUE; - return info; - case ADDRESS_FORWARD_ADD_FORWARD_VTAG: - info = (sctp_assoc_info_t*)(list->data); - info->verification_tag1=needle->verification_tag1; - info->direction = 1; - info->check_address=TRUE; - return info; - case ADDRESS_BACKWARD_ADD_FORWARD_VTAG: - info = (sctp_assoc_info_t*)(list->data); - info->verification_tag1=needle->verification_tag1; - info->direction = 2; - info->check_address=TRUE; - return info; - case ADDRESS_BACKWARD_ADD_BACKWARD_VTAG: - info = (sctp_assoc_info_t*)(list->data); - info->verification_tag2=needle->verification_tag1; - info->direction = 2; - info->check_address=TRUE; - return info; - } + info = (sctp_assoc_info_t*)(list->data); + if (needle->assoc_id == info->assoc_id) + return info; list = g_list_previous(list); } @@ -590,6 +403,8 @@ packet(void *tapdata _U_, packet_info *pinfo , epan_dissect_t *edt _U_ , const v tmp_info.initiate_tag = 0; } + tmp_info.direction = sctp_info->direction; + tmp_info.assoc_id = sctp_info->assoc_index; info = find_assoc(&tmp_info); if (!info) { @@ -600,6 +415,7 @@ packet(void *tapdata _U_, packet_info *pinfo , epan_dissect_t *edt _U_ , const v { info = (sctp_assoc_info_t *)g_malloc(sizeof(sctp_assoc_info_t)); memset(info, 0, sizeof(sctp_assoc_info_t)); + info->assoc_id = sctp_info->assoc_index; info->src.type = tmp_info.src.type; info->src.len = tmp_info.src.len; addr = (guint8 *)g_malloc(tmp_info.dst.len); @@ -651,6 +467,7 @@ packet(void *tapdata _U_, packet_info *pinfo , epan_dissect_t *edt _U_ , const v info->sort_tsn2 = g_ptr_array_new(); info->sort_sack1 = g_ptr_array_new(); info->sort_sack2 = g_ptr_array_new(); + for (i=0; i < NUM_CHUNKS; i++) { info->chunk_count[i] = 0; @@ -720,6 +537,7 @@ packet(void *tapdata _U_, packet_info *pinfo , epan_dissect_t *edt _U_ , const v info->verification_tag2 = tvb_get_ntohl(sctp_info->tvb[0], INIT_CHUNK_INITIATE_TAG_OFFSET); info->instream1 = tvb_get_ntohs(sctp_info->tvb[0],INIT_CHUNK_NUMBER_OF_INBOUND_STREAMS_OFFSET); info->outstream1 = tvb_get_ntohs(sctp_info->tvb[0],INIT_CHUNK_NUMBER_OF_OUTBOUND_STREAMS_OFFSET); + info->arwnd1 = tvb_get_ntohl(sctp_info->tvb[0], INIT_CHUNK_ADV_REC_WINDOW_CREDIT_OFFSET); for (chunk_number = 1; chunk_number < sctp_info->number_of_tvbs; chunk_number++) { type = tvb_get_ntohs(sctp_info->tvb[chunk_number],0); @@ -943,6 +761,13 @@ packet(void *tapdata _U_, packet_info *pinfo , epan_dissect_t *edt _U_ , const v } /* endif (!info) */ else { + info->direction = sctp_info->direction; + + if (info->verification_tag1 == 0 && info->verification_tag2 != sctp_info->verification_tag) { + info->verification_tag1 = sctp_info->verification_tag; + } else if (info->verification_tag2 == 0 && info->verification_tag1 != sctp_info->verification_tag) { + info->verification_tag2 = sctp_info->verification_tag; + } if (((tvb_get_guint8(sctp_info->tvb[0],0)) == SCTP_INIT_CHUNK_ID) || ((tvb_get_guint8(sctp_info->tvb[0],0)) == SCTP_INIT_ACK_CHUNK_ID) || ((tvb_get_guint8(sctp_info->tvb[0],0)) == SCTP_DATA_CHUNK_ID) || @@ -1037,7 +862,7 @@ packet(void *tapdata _U_, packet_info *pinfo , epan_dissect_t *edt _U_ , const v info->max_tsn2 = tsnumber; info->instream2 = tvb_get_ntohs(sctp_info->tvb[0],INIT_CHUNK_NUMBER_OF_INBOUND_STREAMS_OFFSET); info->outstream2 = tvb_get_ntohs(sctp_info->tvb[0],INIT_CHUNK_NUMBER_OF_OUTBOUND_STREAMS_OFFSET); - /*info->initack_dir=2;*/ + info->arwnd2 = tvb_get_ntohl(sctp_info->tvb[0],INIT_CHUNK_ADV_REC_WINDOW_CREDIT_OFFSET); info->tsn2 = g_list_prepend(info->tsn2, tsn); } else if (info->direction == 1) @@ -1048,7 +873,7 @@ packet(void *tapdata _U_, packet_info *pinfo , epan_dissect_t *edt _U_ , const v info->max_tsn1 = tsnumber; info->instream1 = tvb_get_ntohs(sctp_info->tvb[0],INIT_CHUNK_NUMBER_OF_INBOUND_STREAMS_OFFSET); info->outstream1 = tvb_get_ntohs(sctp_info->tvb[0],INIT_CHUNK_NUMBER_OF_OUTBOUND_STREAMS_OFFSET); - /*info->initack_dir=1;*/ + info->arwnd1 = tvb_get_ntohl(sctp_info->tvb[0],INIT_CHUNK_ADV_REC_WINDOW_CREDIT_OFFSET); info->tsn1 = g_list_prepend(info->tsn1, tsn); } @@ -1367,13 +1192,6 @@ const sctp_allassocs_info_t* sctp_stat_get_info(void) } -/*static void -sctp_update(void *dummy _U_) -{ - if (get_stat_dlg()!=NULL) - sctp_stat_dlg_update(); -}*/ - void register_tap_listener_sctp_stat(void) { diff --git a/ui/tap-sctp-analysis.h b/ui/tap-sctp-analysis.h index 5efc4c416e..2200bb8f4a 100644 --- a/ui/tap-sctp-analysis.h +++ b/ui/tap-sctp-analysis.h @@ -25,6 +25,10 @@ #ifndef __TAP_SCTP_ANALYSIS_H__ #define __TAP_SCTP_ANALYSIS_H__ +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + #include #include #ifndef _WIN32 @@ -54,11 +58,13 @@ #define SCTP_SHUTDOWN_COMPLETE_CHUNK_ID 14 #define SCTP_AUTH_CHUNK_ID 15 #define SCTP_NR_SACK_CHUNK_ID 16 -#define SCTP_FORWARD_TSN_CHUNK_ID 0xc0 #define SCTP_ASCONF_ACK_CHUNK_ID 0x80 #define SCTP_PKTDROP_CHUNK_ID 0x81 -#define SCTP_ASCONF_CHUNK_ID 0xc1 -#define SCTP_IETF_EXT 255 +#define SCTP_RE_CONFIG_CHUNK_ID 0x82 +#define SCTP_PAD_CHUNK_ID 0x84 +#define SCTP_FORWARD_TSN_CHUNK_ID 0xC0 +#define SCTP_ASCONF_CHUNK_ID 0xC1 +#define SCTP_IETF_EXT 0xFF #define IS_SCTP_CHUNK_TYPE(t) \ (((t) <= 16) || ((t) == 0xC0) || ((t) == 0xC1) || ((t) == 0x80) || ((t) == 0x81)) @@ -138,8 +144,35 @@ #define INIT_CHUNK_VARIABLE_LENGTH_PARAMETER_OFFSET (INIT_CHUNK_INITIAL_TSN_OFFSET + \ INIT_CHUNK_INITIAL_TSN_LENGTH ) -/* The below value is 256 */ -#define NUM_CHUNKS 0xff +static const value_string chunk_type_values[] = { + { SCTP_DATA_CHUNK_ID, "DATA" }, + { SCTP_INIT_CHUNK_ID, "INIT" }, + { SCTP_INIT_ACK_CHUNK_ID, "INIT_ACK" }, + { SCTP_SACK_CHUNK_ID, "SACK" }, + { SCTP_HEARTBEAT_CHUNK_ID, "HEARTBEAT" }, + { SCTP_HEARTBEAT_ACK_CHUNK_ID, "HEARTBEAT_ACK" }, + { SCTP_ABORT_CHUNK_ID, "ABORT" }, + { SCTP_SHUTDOWN_CHUNK_ID, "SHUTDOWN" }, + { SCTP_SHUTDOWN_ACK_CHUNK_ID, "SHUTDOWN_ACK" }, + { SCTP_ERROR_CHUNK_ID, "ERROR" }, + { SCTP_COOKIE_ECHO_CHUNK_ID, "COOKIE_ECHO" }, + { SCTP_COOKIE_ACK_CHUNK_ID, "COOKIE_ACK" }, + { SCTP_ECNE_CHUNK_ID, "ECNE" }, + { SCTP_CWR_CHUNK_ID, "CWR" }, + { SCTP_SHUTDOWN_COMPLETE_CHUNK_ID, "SHUTDOWN_COMPLETE" }, + { SCTP_AUTH_CHUNK_ID, "AUTH" }, + { SCTP_NR_SACK_CHUNK_ID, "NR-SACK" }, + { SCTP_ASCONF_ACK_CHUNK_ID, "ASCONF_ACK" }, + { SCTP_PKTDROP_CHUNK_ID, "PKTDROP" }, + { SCTP_RE_CONFIG_CHUNK_ID, "RE_CONFIG" }, + { SCTP_PAD_CHUNK_ID, "PAD" }, + { SCTP_FORWARD_TSN_CHUNK_ID, "FORWARD_TSN" }, + { SCTP_ASCONF_CHUNK_ID, "ASCONF" }, + { SCTP_IETF_EXT, "IETF_EXTENSION" }, + { 0, NULL } }; + +/* The below value is 255 */ +#define NUM_CHUNKS 0x100 /* This variable is used as an index into arrays * which store the cumulative information corresponding @@ -165,6 +198,8 @@ typedef struct _tsn { } tsn_t; typedef struct _sctp_tmp_info { + guint16 assoc_id; + guint16 direction; address src; address dst; guint16 port1; @@ -207,6 +242,7 @@ typedef struct _sctp_addr_chunk { } sctp_addr_chunk; typedef struct _sctp_assoc_info { + guint16 assoc_id; address src; address dst; guint16 port1; @@ -247,6 +283,8 @@ typedef struct _sctp_assoc_info { guint32 n_array_tsn2; guint32 max_window1; guint32 max_window2; + guint32 arwnd1; + guint32 arwnd2; gboolean init; gboolean initack; guint8 initack_dir; @@ -310,7 +348,9 @@ void remove_tap_listener_sctp_stat(void); const sctp_assoc_info_t* get_selected_assoc(void); - +#ifdef __cplusplus +} +#endif /* __cplusplus */ #endif /* __TAP_SCTP_ANALYSIS_H__ */ -- cgit v1.2.3