diff options
author | Irene RĂ¼ngeler <I.Ruengeler@fh-muenster.de> | 2013-12-13 07:25:30 +0000 |
---|---|---|
committer | Irene RĂ¼ngeler <I.Ruengeler@fh-muenster.de> | 2013-12-13 07:25:30 +0000 |
commit | 796bf409b0c286dd76e6ecd5c61d0d947d54b479 (patch) | |
tree | 42d21c7d8b1175adf0f155f5c0fb9f53feb795d5 /ui/qt | |
parent | 28e6aa4e8a06299895d7924508a32a895a5454ab (diff) |
Add dialogs and graphs to analyse SCTP behavior similar to the GTK version.
svn path=/trunk/; revision=54026
Diffstat (limited to 'ui/qt')
25 files changed, 3623 insertions, 5 deletions
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 @@ <addaction name="actionAnalyzePAFAndNotSelected"/> <addaction name="actionAnalyzePAFOrNotSelected"/> </widget> + <widget class="QMenu" name="menuSCTP"> + <property name="title"> + <string>SCTP</string> + </property> + <addaction name="actionSCTPAnalyseThisAssociation"/> + <addaction name="actionSCTPShowAllAssociations"/> + </widget> <addaction name="actionDisplayFilters"/> <addaction name="actionDisplayFilterMacros"/> <addaction name="separator"/> @@ -311,6 +318,7 @@ <addaction name="separator"/> <addaction name="actionAnalyzeDecodeAs"/> <addaction name="separator"/> + <addaction name="menuSCTP"/> <addaction name="actionAnalyzeFollowTCPStream"/> <addaction name="actionAnalyzeFollowUDPStream"/> <addaction name="actionAnalyzeFollowSSLStream"/> @@ -1360,6 +1368,16 @@ <string>TCP time sequence graph (tcptrace)</string> </property> </action> + <action name="actionSCTPAnalyseThisAssociation"> + <property name="text"> + <string>Analyse this Association</string> + </property> + </action> + <action name="actionSCTPShowAllAssociations"> + <property name="text"> + <string>Show All Associations</string> + </property> + </action> <action name="actionStatisticsFlowGraph"> <property name="text"> <string>Flow Graph</string> 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) : // " <menuitem name='FollowTCPStream' action='/Follow TCP Stream'/>\n" // " <menuitem name='FollowUDPStream' action='/Follow UDP Stream'/>\n" // " <menuitem name='FollowSSLStream' action='/Follow SSL Stream'/>\n" - + submenu = new QMenu(tr("SCTP")); + ctx_menu_.addMenu(submenu); + submenu->addAction(window()->findChild<QAction *>("actionSCTPAnalyseThisAssociation")); + submenu->addAction(window()->findChild<QAction *>("actionSCTPShowAllAssociations")); + submenu->addAction(window()->findChild<QAction *>("actionSCTPChunkCounter")); + filter_actions_ << submenu->actions(); ctx_menu_.addSeparator(); // " <menuitem name='ManuallyResolveAddress' action='/ManuallyResolveAddress'/>\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 <QWidget> +#include <QDir> +#include <QFileDialog> +#include <QIcon> +#include <QPushButton> + +//#include <QDebug> + +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 <glib.h> + +#include <file.h> + +#include <epan/dissectors/packet-sctp.h> + +#include "ui/tap-sctp-analysis.h" + +#include <QDialog> +#include <QObject> + +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 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>SCTPAllAssocsDialog</class> + <widget class="QDialog" name="SCTPAllAssocsDialog"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>685</width> + <height>300</height> + </rect> + </property> + <property name="windowTitle"> + <string>Wireshark - SCTP Associations</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout"> + <item> + <widget class="QTableWidget" name="assocList"> + <property name="editTriggers"> + <set>QAbstractItemView::NoEditTriggers</set> + </property> + <property name="showDropIndicator" stdset="0"> + <bool>false</bool> + </property> + <property name="dragDropOverwriteMode"> + <bool>false</bool> + </property> + <property name="alternatingRowColors"> + <bool>true</bool> + </property> + <property name="selectionMode"> + <enum>QAbstractItemView::SingleSelection</enum> + </property> + <property name="selectionBehavior"> + <enum>QAbstractItemView::SelectRows</enum> + </property> + <property name="sortingEnabled"> + <bool>true</bool> + </property> + <property name="wordWrap"> + <bool>false</bool> + </property> + <property name="rowCount"> + <number>2</number> + </property> + <property name="columnCount"> + <number>6</number> + </property> + <attribute name="horizontalHeaderDefaultSectionSize"> + <number>120</number> + </attribute> + <attribute name="horizontalHeaderMinimumSectionSize"> + <number>50</number> + </attribute> + <attribute name="horizontalHeaderStretchLastSection"> + <bool>true</bool> + </attribute> + <row/> + <row/> + <column> + <property name="text"> + <string>ID</string> + </property> + </column> + <column> + <property name="text"> + <string>Port 1</string> + </property> + </column> + <column> + <property name="text"> + <string>Port 2</string> + </property> + </column> + <column> + <property name="text"> + <string>Number of Packets</string> + </property> + </column> + <column> + <property name="text"> + <string>Number of DATA Chunks</string> + </property> + </column> + <column> + <property name="text"> + <string>Number of Bytes</string> + </property> + </column> + </widget> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout"/> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_2"> + <item> + <widget class="QPushButton" name="setFilterButton"> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="focusPolicy"> + <enum>Qt::ClickFocus</enum> + </property> + <property name="text"> + <string>Filter Selected Association</string> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="analyseButton"> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="focusPolicy"> + <enum>Qt::ClickFocus</enum> + </property> + <property name="text"> + <string>Analyze</string> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer_2"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>10</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QDialogButtonBox" name="buttonBox"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="standardButtons"> + <set>QDialogButtonBox::Close</set> + </property> + </widget> + </item> + </layout> + </item> + </layout> + <action name="actionReset"> + <property name="text"> + <string>Reset Graph</string> + </property> + <property name="toolTip"> + <string>Reset the graph to its initial state.</string> + </property> + <property name="shortcut"> + <string>0</string> + </property> + </action> + <action name="actionZoomIn"> + <property name="text"> + <string>Zoom In</string> + </property> + <property name="toolTip"> + <string>Zoom in</string> + </property> + <property name="shortcut"> + <string>+</string> + </property> + </action> + <action name="actionZoomOut"> + <property name="text"> + <string>Zoom Out</string> + </property> + <property name="toolTip"> + <string>Zoom out</string> + </property> + <property name="shortcut"> + <string>-</string> + </property> + </action> + <action name="actionMoveUp10"> + <property name="text"> + <string>Move Up 10 Pixels</string> + </property> + <property name="toolTip"> + <string>Move up 10 pixels</string> + </property> + <property name="shortcut"> + <string>Up</string> + </property> + </action> + <action name="actionMoveLeft10"> + <property name="text"> + <string>Move Left 10 Pixels</string> + </property> + <property name="toolTip"> + <string>Move left 10 pixels</string> + </property> + <property name="shortcut"> + <string>Left</string> + </property> + </action> + <action name="actionMoveRight10"> + <property name="text"> + <string>Move Right 10 Pixels</string> + </property> + <property name="toolTip"> + <string>Move right 10 pixels</string> + </property> + <property name="shortcut"> + <string>Right</string> + </property> + </action> + <action name="actionMoveDown10"> + <property name="text"> + <string>Move Down 10 Pixels</string> + </property> + <property name="toolTip"> + <string>Move down 10 pixels</string> + </property> + <property name="shortcut"> + <string>Down</string> + </property> + </action> + <action name="actionMoveUp1"> + <property name="text"> + <string>Move Up 1 Pixel</string> + </property> + <property name="toolTip"> + <string>Move up 1 pixel</string> + </property> + <property name="shortcut"> + <string>Shift+Up</string> + </property> + </action> + <action name="actionMoveLeft1"> + <property name="text"> + <string>Move Left 1 Pixel</string> + </property> + <property name="toolTip"> + <string>Move left 1 pixel</string> + </property> + <property name="shortcut"> + <string>Shift+Left</string> + </property> + </action> + <action name="actionMoveRight1"> + <property name="text"> + <string>Move Right 1 Pixel</string> + </property> + <property name="toolTip"> + <string>Move right 1 pixel</string> + </property> + <property name="shortcut"> + <string>Shift+Right</string> + </property> + </action> + <action name="actionMoveDown1"> + <property name="text"> + <string>Move Down 1 Pixel</string> + </property> + <property name="toolTip"> + <string>Move down 1 pixel</string> + </property> + <property name="shortcut"> + <string>Shift+Down</string> + </property> + </action> + <action name="actionNextStream"> + <property name="text"> + <string>Next Stream</string> + </property> + <property name="toolTip"> + <string>Go to the next stream in the capture</string> + </property> + <property name="shortcut"> + <string>PgUp</string> + </property> + </action> + <action name="actionPreviousStream"> + <property name="text"> + <string>Previous Stream</string> + </property> + <property name="toolTip"> + <string>Go to the previous stream in the capture</string> + </property> + <property name="shortcut"> + <string>PgDown</string> + </property> + </action> + <action name="actionSwitchDirection"> + <property name="text"> + <string>Switch Direction</string> + </property> + <property name="toolTip"> + <string>Switch direction (swap TCP endpoints)</string> + </property> + <property name="shortcut"> + <string>D</string> + </property> + </action> + <action name="actionGoToPacket"> + <property name="text"> + <string>Go To Packet Under Cursor</string> + </property> + <property name="toolTip"> + <string>Go to packet currently under the cursor</string> + </property> + <property name="shortcut"> + <string>G</string> + </property> + </action> + <action name="actionDragZoom"> + <property name="text"> + <string>Drag / Zoom</string> + </property> + <property name="toolTip"> + <string>Toggle mouse drag / zoom behavior</string> + </property> + <property name="shortcut"> + <string>Z</string> + </property> + </action> + <action name="actionToggleSequenceNumbers"> + <property name="text"> + <string>Relative / Absolute Sequence Numbers</string> + </property> + <property name="toolTip"> + <string>Toggle relative / absolute sequence numbers</string> + </property> + <property name="shortcut"> + <string>S</string> + </property> + </action> + <action name="actionToggleTimeOrigin"> + <property name="text"> + <string>Capture / Session Time Origin</string> + </property> + <property name="toolTip"> + <string>Toggle capture / session time origin</string> + </property> + <property name="shortcut"> + <string>T</string> + </property> + </action> + <action name="actionCrosshairs"> + <property name="text"> + <string>Crosshairs</string> + </property> + <property name="toolTip"> + <string>Toggle crosshairs</string> + </property> + <property name="shortcut"> + <string>Space</string> + </property> + </action> + <action name="actionRoundTripTime"> + <property name="text"> + <string>Round Trip Time</string> + </property> + <property name="toolTip"> + <string>Switch to the Round Trip Time graph</string> + </property> + <property name="shortcut"> + <string>1</string> + </property> + </action> + <action name="actionThroughput"> + <property name="text"> + <string>Throughput</string> + </property> + <property name="toolTip"> + <string>Switch to the Throughput graph</string> + </property> + <property name="shortcut"> + <string>2</string> + </property> + </action> + <action name="actionStevens"> + <property name="text"> + <string>Time / Sequence (Stevens)</string> + </property> + <property name="toolTip"> + <string>Switch to the Stevens-style Time / Sequence graph</string> + </property> + <property name="shortcut"> + <string>3</string> + </property> + </action> + <action name="actionWindowScaling"> + <property name="text"> + <string>Window Scaling</string> + </property> + <property name="toolTip"> + <string>Switch to the Window Scaling graph</string> + </property> + <property name="shortcut"> + <string>5</string> + </property> + </action> + <action name="actionTcptrace"> + <property name="text"> + <string>Time / Sequence (tcptrace)</string> + </property> + <property name="toolTip"> + <string>Switch to the tcptrace-style Time / Sequence graph</string> + </property> + <property name="shortcut"> + <string>4</string> + </property> + </action> + </widget> + <resources/> + <connections> + <connection> + <sender>buttonBox</sender> + <signal>clicked(QAbstractButton*)</signal> + <receiver>SCTPAllAssocsDialog</receiver> + <slot>close()</slot> + <hints> + <hint type="sourcelabel"> + <x>644</x> + <y>274</y> + </hint> + <hint type="destinationlabel"> + <x>659</x> + <y>322</y> + </hint> + </hints> + </connection> + </connections> +</ui> 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 <glib.h> + +#include <file.h> + +#include <epan/dissectors/packet-sctp.h> + +#include "ui/tap-sctp-analysis.h" +#include "sctp_all_assocs_dialog.h" + +#include <QDialog> +#include <QTabWidget> +#include <QObject> +#include <QGridLayout> +#include <QMessageBox> + + +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 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>SCTPAssocAnalyseDialog</class> + <widget class="QDialog" name="SCTPAssocAnalyseDialog"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>537</width> + <height>385</height> + </rect> + </property> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="windowTitle"> + <string>Wireshark - Analyse Association</string> + </property> + <property name="windowIcon"> + <iconset resource="../../image/toolbar.qrc"> + <normaloff>:/menu/help/wsicon16.png</normaloff>:/menu/help/wsicon16.png</iconset> + </property> + <property name="locale"> + <locale language="English" country="UnitedStates"/> + </property> + <widget class="QTabWidget" name="SCTPAssocAnalyseTab"> + <property name="geometry"> + <rect> + <x>5</x> + <y>10</y> + <width>529</width> + <height>371</height> + </rect> + </property> + <property name="windowTitle"> + <string>TabWidget</string> + </property> + <property name="currentIndex"> + <number>2</number> + </property> + <widget class="QWidget" name="Statistics"> + <property name="focusPolicy"> + <enum>Qt::NoFocus</enum> + </property> + <attribute name="title"> + <string>Statistics</string> + </attribute> + <widget class="QPushButton" name="chunkStatisticsButton"> + <property name="geometry"> + <rect> + <x>0</x> + <y>310</y> + <width>131</width> + <height>32</height> + </rect> + </property> + <property name="focusPolicy"> + <enum>Qt::NoFocus</enum> + </property> + <property name="text"> + <string>Chunk Statistics</string> + </property> + </widget> + <widget class="QPushButton" name="setFilterButton"> + <property name="geometry"> + <rect> + <x>130</x> + <y>310</y> + <width>141</width> + <height>32</height> + </rect> + </property> + <property name="focusPolicy"> + <enum>Qt::NoFocus</enum> + </property> + <property name="text"> + <string>Filter Association</string> + </property> + </widget> + <widget class="QPushButton" name="pushButton"> + <property name="geometry"> + <rect> + <x>390</x> + <y>310</y> + <width>114</width> + <height>32</height> + </rect> + </property> + <property name="focusPolicy"> + <enum>Qt::NoFocus</enum> + </property> + <property name="text"> + <string>SchlieĂŸen</string> + </property> + </widget> + <widget class="QWidget" name="gridLayoutWidget_3"> + <property name="geometry"> + <rect> + <x>20</x> + <y>40</y> + <width>481</width> + <height>201</height> + </rect> + </property> + <layout class="QGridLayout" name="gridLayout_3"> + <item row="3" column="0"> + <widget class="QLabel" name="label_17"> + <property name="text"> + <string>Number of Data Chunks from EP2 to EP1: </string> + </property> + </widget> + </item> + <item row="0" column="0"> + <widget class="QLabel" name="label_15"> + <property name="text"> + <string>Checksum Type:</string> + </property> + </widget> + </item> + <item row="1" column="0"> + <widget class="QLabel" name="label_16"> + <property name="text"> + <string>Number of Data Chunks from EP1 to EP2: </string> + </property> + </widget> + </item> + <item row="2" column="0"> + <widget class="QLabel" name="label_13"> + <property name="text"> + <string>Number of Data Bytes from EP1 to EP2:</string> + </property> + </widget> + </item> + <item row="4" column="0"> + <widget class="QLabel" name="label_18"> + <property name="text"> + <string>Number of Data Bytes from EP2 to EP1: </string> + </property> + </widget> + </item> + <item row="1" column="1"> + <widget class="QLabel" name="data12Label"> + <property name="text"> + <string>TextLabel</string> + </property> + </widget> + </item> + <item row="0" column="1"> + <widget class="QLabel" name="checksumLabel"> + <property name="text"> + <string>TextLabel</string> + </property> + </widget> + </item> + <item row="2" column="1"> + <widget class="QLabel" name="bytes12Label"> + <property name="text"> + <string>TextLabel</string> + </property> + </widget> + </item> + <item row="3" column="1"> + <widget class="QLabel" name="data21Label"> + <property name="text"> + <string>TextLabel</string> + </property> + </widget> + </item> + <item row="4" column="1"> + <widget class="QLabel" name="bytes21Label"> + <property name="text"> + <string>TextLabel</string> + </property> + </widget> + </item> + </layout> + </widget> + </widget> + <widget class="QWidget" name="Endpoint_1"> + <attribute name="title"> + <string>Endpoint 1</string> + </attribute> + <widget class="QPushButton" name="GraphTSN_1"> + <property name="geometry"> + <rect> + <x>0</x> + <y>310</y> + <width>114</width> + <height>32</height> + </rect> + </property> + <property name="focusPolicy"> + <enum>Qt::NoFocus</enum> + </property> + <property name="text"> + <string>Graph TSN</string> + </property> + </widget> + <widget class="QPushButton" name="GraphBytes_1"> + <property name="geometry"> + <rect> + <x>110</x> + <y>310</y> + <width>114</width> + <height>32</height> + </rect> + </property> + <property name="focusPolicy"> + <enum>Qt::NoFocus</enum> + </property> + <property name="text"> + <string>Graph Bytes</string> + </property> + </widget> + <widget class="QLabel" name="labelEP1"> + <property name="geometry"> + <rect> + <x>10</x> + <y>10</y> + <width>441</width> + <height>16</height> + </rect> + </property> + <property name="text"> + <string>Complete list of IP Addresses as provided in the INIT Chunk</string> + </property> + </widget> + <widget class="QWidget" name="gridLayoutWidget"> + <property name="geometry"> + <rect> + <x>10</x> + <y>170</y> + <width>520</width> + <height>138</height> + </rect> + </property> + <layout class="QGridLayout" name="gridLayout"> + <item row="2" column="0"> + <widget class="QLabel" name="label_213"> + <property name="text"> + <string>Requested Number of Inbound Streams:</string> + </property> + </widget> + </item> + <item row="0" column="0"> + <widget class="QLabel" name="label_211"> + <property name="text"> + <string>Port:</string> + </property> + </widget> + </item> + <item row="1" column="1"> + <widget class="QLabel" name="label_222"> + <property name="text"> + <string>TextLabel</string> + </property> + </widget> + </item> + <item row="1" column="0"> + <widget class="QLabel" name="label_212"> + <property name="text"> + <string>Sent Verification Tag:</string> + </property> + </widget> + </item> + <item row="3" column="1"> + <widget class="QLabel" name="label_224"> + <property name="text"> + <string>TextLabel</string> + </property> + </widget> + </item> + <item row="3" column="0"> + <widget class="QLabel" name="label_214"> + <property name="text"> + <string>Minimum Number of Inbound Streams:</string> + </property> + </widget> + </item> + <item row="0" column="1"> + <widget class="QLabel" name="label_221"> + <property name="text"> + <string>TextLabel</string> + </property> + </widget> + </item> + <item row="4" column="0"> + <widget class="QLabel" name="label_215"> + <property name="text"> + <string>Minimum Number of Outbound Streams:</string> + </property> + </widget> + </item> + <item row="2" column="1"> + <widget class="QLabel" name="label_223"> + <property name="text"> + <string>TextLabel</string> + </property> + </widget> + </item> + <item row="4" column="1"> + <widget class="QLabel" name="label_225"> + <property name="text"> + <string>TextLabel</string> + </property> + </widget> + </item> + <item row="5" column="0"> + <widget class="QLabel" name="label_216"> + <property name="text"> + <string>TextLabel</string> + </property> + </widget> + </item> + <item row="5" column="1"> + <widget class="QLabel" name="label_226"> + <property name="text"> + <string>TextLabel</string> + </property> + </widget> + </item> + </layout> + </widget> + <widget class="QPushButton" name="pushButton_2"> + <property name="geometry"> + <rect> + <x>390</x> + <y>310</y> + <width>114</width> + <height>32</height> + </rect> + </property> + <property name="focusPolicy"> + <enum>Qt::NoFocus</enum> + </property> + <property name="text"> + <string>SchlieĂŸen</string> + </property> + </widget> + <widget class="QListWidget" name="listWidgetEP1"> + <property name="geometry"> + <rect> + <x>10</x> + <y>30</y> + <width>501</width> + <height>131</height> + </rect> + </property> + </widget> + <widget class="QPushButton" name="GraphArwnd_1"> + <property name="geometry"> + <rect> + <x>220</x> + <y>310</y> + <width>114</width> + <height>32</height> + </rect> + </property> + <property name="text"> + <string>Graph Arwnd</string> + </property> + </widget> + </widget> + <widget class="QWidget" name="Endpoint_2"> + <attribute name="title"> + <string>Endpoint 2</string> + </attribute> + <widget class="QPushButton" name="GraphTSN_2"> + <property name="geometry"> + <rect> + <x>0</x> + <y>310</y> + <width>114</width> + <height>32</height> + </rect> + </property> + <property name="focusPolicy"> + <enum>Qt::NoFocus</enum> + </property> + <property name="text"> + <string>Graph TSN</string> + </property> + </widget> + <widget class="QPushButton" name="GraphBytes_2"> + <property name="geometry"> + <rect> + <x>110</x> + <y>310</y> + <width>114</width> + <height>32</height> + </rect> + </property> + <property name="focusPolicy"> + <enum>Qt::NoFocus</enum> + </property> + <property name="text"> + <string>Graph Bytes</string> + </property> + </widget> + <widget class="QWidget" name="gridLayoutWidget_2"> + <property name="geometry"> + <rect> + <x>10</x> + <y>170</y> + <width>511</width> + <height>141</height> + </rect> + </property> + <layout class="QGridLayout" name="gridLayout_2"> + <item row="2" column="0"> + <widget class="QLabel" name="label_313"> + <property name="text"> + <string>Requested Number of Inbound Streams:</string> + </property> + </widget> + </item> + <item row="3" column="1"> + <widget class="QLabel" name="label_324"> + <property name="text"> + <string>TextLabel</string> + </property> + </widget> + </item> + <item row="0" column="1"> + <widget class="QLabel" name="label_321"> + <property name="text"> + <string>TextLabel</string> + </property> + </widget> + </item> + <item row="1" column="0"> + <widget class="QLabel" name="label_312"> + <property name="text"> + <string>Sent Verification Tag:</string> + </property> + </widget> + </item> + <item row="5" column="0"> + <widget class="QLabel" name="label_316"> + <property name="text"> + <string>Minimum Number of Outbound Streams:</string> + </property> + </widget> + </item> + <item row="0" column="0"> + <widget class="QLabel" name="label_311"> + <property name="text"> + <string>Port:</string> + </property> + </widget> + </item> + <item row="3" column="0"> + <widget class="QLabel" name="label_314"> + <property name="text"> + <string>Minimum Number of Inbound Streams:</string> + </property> + </widget> + </item> + <item row="1" column="1"> + <widget class="QLabel" name="label_322"> + <property name="text"> + <string>TextLabel</string> + </property> + </widget> + </item> + <item row="2" column="1"> + <widget class="QLabel" name="label_323"> + <property name="text"> + <string>TextLabel</string> + </property> + </widget> + </item> + <item row="5" column="1"> + <widget class="QLabel" name="label_326"> + <property name="text"> + <string>TextLabel</string> + </property> + </widget> + </item> + <item row="4" column="0"> + <widget class="QLabel" name="label_315"> + <property name="text"> + <string>Provided Number of Outbound Streams:</string> + </property> + </widget> + </item> + <item row="4" column="1"> + <widget class="QLabel" name="label_325"> + <property name="text"> + <string>TextLabel</string> + </property> + </widget> + </item> + </layout> + </widget> + <widget class="QLabel" name="labelEP2"> + <property name="geometry"> + <rect> + <x>10</x> + <y>10</y> + <width>441</width> + <height>16</height> + </rect> + </property> + <property name="text"> + <string>Complete list of IP Addresses as provided in the INIT-ACK Chunk</string> + </property> + </widget> + <widget class="QPushButton" name="pushButton_3"> + <property name="geometry"> + <rect> + <x>390</x> + <y>310</y> + <width>114</width> + <height>32</height> + </rect> + </property> + <property name="focusPolicy"> + <enum>Qt::NoFocus</enum> + </property> + <property name="text"> + <string>SchlieĂŸen</string> + </property> + </widget> + <widget class="QListWidget" name="listWidgetEP2"> + <property name="geometry"> + <rect> + <x>10</x> + <y>30</y> + <width>501</width> + <height>131</height> + </rect> + </property> + </widget> + <widget class="QPushButton" name="GraphArwnd_2"> + <property name="geometry"> + <rect> + <x>220</x> + <y>310</y> + <width>121</width> + <height>32</height> + </rect> + </property> + <property name="text"> + <string>Graph a_rwnd</string> + </property> + </widget> + </widget> + </widget> + </widget> + <resources> + <include location="../../image/toolbar.qrc"/> + </resources> + <connections> + <connection> + <sender>pushButton_2</sender> + <signal>clicked()</signal> + <receiver>SCTPAssocAnalyseDialog</receiver> + <slot>close()</slot> + <hints> + <hint type="sourcelabel"> + <x>471</x> + <y>365</y> + </hint> + <hint type="destinationlabel"> + <x>475</x> + <y>384</y> + </hint> + </hints> + </connection> + <connection> + <sender>pushButton</sender> + <signal>clicked()</signal> + <receiver>SCTPAssocAnalyseDialog</receiver> + <slot>close()</slot> + <hints> + <hint type="sourcelabel"> + <x>494</x> + <y>361</y> + </hint> + <hint type="destinationlabel"> + <x>523</x> + <y>433</y> + </hint> + </hints> + </connection> + <connection> + <sender>pushButton_3</sender> + <signal>clicked()</signal> + <receiver>SCTPAssocAnalyseDialog</receiver> + <slot>close()</slot> + <hints> + <hint type="sourcelabel"> + <x>502</x> + <y>362</y> + </hint> + <hint type="destinationlabel"> + <x>520</x> + <y>459</y> + </hint> + </hints> + </connection> + </connections> +</ui> 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 <string> + + +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<int, struct chunkTypes>::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 <glib.h> + +#include <file.h> +#include <wsutil/file_util.h> +#include <epan/dissectors/packet-sctp.h> +#include "epan/packet.h" +#include "epan/value_string.h" +#include <epan/prefs.h> +#include <epan/uat-int.h> +#include <epan/prefs-int.h> +#include <wsutil/filesystem.h> +#include "wireshark_application.h" + +#include "ui/tap-sctp-analysis.h" + +#include <QTableWidgetItem> +#include <QDialog> +#include <QtGui> +#include <QMenu> +#include <QContextMenuEvent> + +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<int, struct chunkTypes> 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 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>SCTPChunkStatisticsDialog</class> + <widget class="QDialog" name="SCTPChunkStatisticsDialog"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>519</width> + <height>504</height> + </rect> + </property> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="windowTitle"> + <string>Dialog</string> + </property> + <widget class="QDialogButtonBox" name="buttonBox"> + <property name="geometry"> + <rect> + <x>310</x> + <y>470</y> + <width>191</width> + <height>32</height> + </rect> + </property> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="standardButtons"> + <set>QDialogButtonBox::Cancel|QDialogButtonBox::Close</set> + </property> + </widget> + <widget class="QTableWidget" name="tableWidget"> + <property name="geometry"> + <rect> + <x>30</x> + <y>30</y> + <width>471</width> + <height>431</height> + </rect> + </property> + <property name="editTriggers"> + <set>QAbstractItemView::NoEditTriggers</set> + </property> + <property name="alternatingRowColors"> + <bool>true</bool> + </property> + <property name="selectionMode"> + <enum>QAbstractItemView::SingleSelection</enum> + </property> + <property name="selectionBehavior"> + <enum>QAbstractItemView::SelectRows</enum> + </property> + <property name="rowCount"> + <number>0</number> + </property> + <attribute name="horizontalHeaderCascadingSectionResizes"> + <bool>false</bool> + </attribute> + <attribute name="horizontalHeaderStretchLastSection"> + <bool>true</bool> + </attribute> + <attribute name="verticalHeaderCascadingSectionResizes"> + <bool>false</bool> + </attribute> + <column> + <property name="text"> + <string>Association</string> + </property> + </column> + <column> + <property name="text"> + <string>Endpoint 1</string> + </property> + </column> + <column> + <property name="text"> + <string>Endpoint 2</string> + </property> + </column> + </widget> + <widget class="QPushButton" name="pushButton"> + <property name="geometry"> + <rect> + <x>130</x> + <y>470</y> + <width>181</width> + <height>32</height> + </rect> + </property> + <property name="text"> + <string>Save Chunk Type Order</string> + </property> + </widget> + <action name="actionHideChunkType"> + <property name="text"> + <string>Hide Chunk Type</string> + </property> + <property name="toolTip"> + <string>Remove the chunk type from the table</string> + </property> + </action> + <action name="actionChunkTypePreferences"> + <property name="text"> + <string>Chunk Type Preferences</string> + </property> + <property name="toolTip"> + <string>Go to the chunk type preferences dialog to show or hide other chunk types</string> + </property> + </action> + <action name="actionShowAllChunkTypes"> + <property name="text"> + <string>Show All Registered Chunk Types</string> + </property> + <property name="toolTip"> + <string>Show all chunk types with defined names</string> + </property> + </action> + </widget> + <resources/> + <connections> + <connection> + <sender>buttonBox</sender> + <signal>clicked(QAbstractButton*)</signal> + <receiver>SCTPChunkStatisticsDialog</receiver> + <slot>close()</slot> + <hints> + <hint type="sourcelabel"> + <x>456</x> + <y>483</y> + </hint> + <hint type="destinationlabel"> + <x>445</x> + <y>563</y> + </hint> + </hints> + </connection> + <connection> + <sender>buttonBox</sender> + <signal>clicked(QAbstractButton*)</signal> + <receiver>SCTPChunkStatisticsDialog</receiver> + <slot>close()</slot> + <hints> + <hint type="sourcelabel"> + <x>357</x> + <y>486</y> + </hint> + <hint type="destinationlabel"> + <x>355</x> + <y>542</y> + </hint> + </hints> + </connection> + </connections> +</ui> 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("<small><i>Graph %1: arwnd=%2 Time=%3 secs </i></small>") + .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 <glib.h> + +#include <file.h> +#include <math.h> +#include <epan/dissectors/packet-sctp.h> +#include "epan/packet.h" + +#include "ui/tap-sctp-analysis.h" + +#include <QDialog> +#include <QObject> +#include <QMessageBox> + +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<double> xa, ya; + QVector<guint32> fa; + // QVector<QString> 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 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>SCTPGraphArwndDialog</class> + <widget class="QDialog" name="SCTPGraphArwndDialog"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>800</width> + <height>546</height> + </rect> + </property> + <property name="windowTitle"> + <string>SCTP Graph</string> + </property> + <widget class="QCustomPlot" name="sctpPlot" native="true"> + <property name="geometry"> + <rect> + <x>20</x> + <y>30</y> + <width>761</width> + <height>451</height> + </rect> + </property> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>1</verstretch> + </sizepolicy> + </property> + </widget> + <widget class="QPushButton" name="pushButton_4"> + <property name="geometry"> + <rect> + <x>10</x> + <y>510</y> + <width>131</width> + <height>32</height> + </rect> + </property> + <property name="focusPolicy"> + <enum>Qt::NoFocus</enum> + </property> + <property name="text"> + <string>Reset to full size</string> + </property> + </widget> + <widget class="QDialogButtonBox" name="buttonBox"> + <property name="geometry"> + <rect> + <x>680</x> + <y>510</y> + <width>120</width> + <height>32</height> + </rect> + </property> + <property name="focusPolicy"> + <enum>Qt::NoFocus</enum> + </property> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="standardButtons"> + <set>QDialogButtonBox::Close</set> + </property> + </widget> + <widget class="QLabel" name="hintLabel"> + <property name="geometry"> + <rect> + <x>10</x> + <y>490</y> + <width>655</width> + <height>12</height> + </rect> + </property> + <property name="text"> + <string><html><head/><body><p><br/></p></body></html></string> + </property> + </widget> + <widget class="QPushButton" name="saveButton"> + <property name="geometry"> + <rect> + <x>140</x> + <y>510</y> + <width>114</width> + <height>32</height> + </rect> + </property> + <property name="text"> + <string>Save Graph</string> + </property> + </widget> + <action name="actionGoToPacket"> + <property name="text"> + <string>goToPacket</string> + </property> + <property name="toolTip"> + <string>Go to Packet</string> + </property> + </action> + </widget> + <customwidgets> + <customwidget> + <class>QCustomPlot</class> + <extends>QWidget</extends> + <header>qcustomplot.h</header> + <container>1</container> + </customwidget> + </customwidgets> + <resources/> + <connections> + <connection> + <sender>buttonBox</sender> + <signal>clicked(QAbstractButton*)</signal> + <receiver>SCTPGraphArwndDialog</receiver> + <slot>close()</slot> + <hints> + <hint type="sourcelabel"> + <x>706</x> + <y>530</y> + </hint> + <hint type="destinationlabel"> + <x>703</x> + <y>574</y> + </hint> + </hints> + </connection> + </connections> +</ui> 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("<small><i>Graph %1: Received bytes=%2 Time=%3 secs </i></small>") + .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 <glib.h> + +#include <file.h> +#include <math.h> +#include <epan/dissectors/packet-sctp.h> +#include "epan/packet.h" + +#include "ui/tap-sctp-analysis.h" + +#include <QDialog> +#include <QObject> +#include <QMessageBox> + +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<double> xb, yb; + QVector<guint32> 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 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>SCTPGraphByteDialog</class> + <widget class="QDialog" name="SCTPGraphByteDialog"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>800</width> + <height>546</height> + </rect> + </property> + <property name="windowTitle"> + <string>SCTP Graph</string> + </property> + <widget class="QCustomPlot" name="sctpPlot" native="true"> + <property name="geometry"> + <rect> + <x>20</x> + <y>30</y> + <width>761</width> + <height>451</height> + </rect> + </property> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>1</verstretch> + </sizepolicy> + </property> + </widget> + <widget class="QPushButton" name="pushButton_4"> + <property name="geometry"> + <rect> + <x>10</x> + <y>510</y> + <width>131</width> + <height>32</height> + </rect> + </property> + <property name="focusPolicy"> + <enum>Qt::NoFocus</enum> + </property> + <property name="text"> + <string>Reset to full size</string> + </property> + </widget> + <widget class="QDialogButtonBox" name="buttonBox"> + <property name="geometry"> + <rect> + <x>680</x> + <y>510</y> + <width>120</width> + <height>32</height> + </rect> + </property> + <property name="focusPolicy"> + <enum>Qt::NoFocus</enum> + </property> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="standardButtons"> + <set>QDialogButtonBox::Close</set> + </property> + </widget> + <widget class="QLabel" name="hintLabel"> + <property name="geometry"> + <rect> + <x>10</x> + <y>490</y> + <width>655</width> + <height>12</height> + </rect> + </property> + <property name="text"> + <string><html><head/><body><p><br/></p></body></html></string> + </property> + </widget> + <widget class="QPushButton" name="saveButton"> + <property name="geometry"> + <rect> + <x>140</x> + <y>510</y> + <width>114</width> + <height>32</height> + </rect> + </property> + <property name="text"> + <string>Save Graph</string> + </property> + </widget> + <action name="actionGoToPacket"> + <property name="text"> + <string>goToPacket</string> + </property> + <property name="toolTip"> + <string>Go to Packet</string> + </property> + </action> + </widget> + <customwidgets> + <customwidget> + <class>QCustomPlot</class> + <extends>QWidget</extends> + <header>qcustomplot.h</header> + <container>1</container> + </customwidget> + </customwidgets> + <resources/> + <connections> + <connection> + <sender>buttonBox</sender> + <signal>clicked(QAbstractButton*)</signal> + <receiver>SCTPGraphByteDialog</receiver> + <slot>close()</slot> + <hints> + <hint type="sourcelabel"> + <x>706</x> + <y>530</y> + </hint> + <hint type="destinationlabel"> + <x>703</x> + <y>574</y> + </hint> + </hints> + </connection> + </connections> +</ui> 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;i<nr; i++) { + gap_start=g_ntohs(gap->start); + 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("<small><i>%1: %2: %3 Time: %4 secs </i></small>") + .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 <glib.h> + +#include <file.h> +#include <math.h> +#include <epan/dissectors/packet-sctp.h> +#include "epan/packet.h" + +#include "ui/tap-sctp-analysis.h" + +#include <QDialog> +#include <QObject> +#include <QMessageBox> +#include <QDir> +#include <QFileDialog> + +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<double> xt, yt, xs, ys, xg, yg, xd, yd, xn, yn; + QVector<guint32> ft, fs, fg, fd, fn; + QVector<QString> 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 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>SCTPGraphDialog</class> + <widget class="QDialog" name="SCTPGraphDialog"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>800</width> + <height>546</height> + </rect> + </property> + <property name="windowTitle"> + <string>SCTP Graph</string> + </property> + <widget class="QCustomPlot" name="sctpPlot" native="true"> + <property name="geometry"> + <rect> + <x>20</x> + <y>30</y> + <width>761</width> + <height>451</height> + </rect> + </property> + <property name="sizePolicy"> + <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> + <horstretch>0</horstretch> + <verstretch>1</verstretch> + </sizepolicy> + </property> + </widget> + <widget class="QPushButton" name="pushButton"> + <property name="geometry"> + <rect> + <x>0</x> + <y>510</y> + <width>120</width> + <height>32</height> + </rect> + </property> + <property name="focusPolicy"> + <enum>Qt::NoFocus</enum> + </property> + <property name="text"> + <string>Only SACKs</string> + </property> + </widget> + <widget class="QPushButton" name="pushButton_2"> + <property name="geometry"> + <rect> + <x>120</x> + <y>510</y> + <width>120</width> + <height>32</height> + </rect> + </property> + <property name="focusPolicy"> + <enum>Qt::NoFocus</enum> + </property> + <property name="text"> + <string>Only TSNs</string> + </property> + </widget> + <widget class="QPushButton" name="pushButton_3"> + <property name="geometry"> + <rect> + <x>240</x> + <y>510</y> + <width>120</width> + <height>32</height> + </rect> + </property> + <property name="focusPolicy"> + <enum>Qt::NoFocus</enum> + </property> + <property name="text"> + <string>Show both</string> + </property> + </widget> + <widget class="QPushButton" name="pushButton_4"> + <property name="geometry"> + <rect> + <x>360</x> + <y>510</y> + <width>131</width> + <height>32</height> + </rect> + </property> + <property name="focusPolicy"> + <enum>Qt::NoFocus</enum> + </property> + <property name="text"> + <string>Reset to full size</string> + </property> + </widget> + <widget class="QDialogButtonBox" name="buttonBox"> + <property name="geometry"> + <rect> + <x>680</x> + <y>510</y> + <width>120</width> + <height>32</height> + </rect> + </property> + <property name="focusPolicy"> + <enum>Qt::NoFocus</enum> + </property> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="standardButtons"> + <set>QDialogButtonBox::Close</set> + </property> + </widget> + <widget class="QLabel" name="hintLabel"> + <property name="geometry"> + <rect> + <x>10</x> + <y>490</y> + <width>655</width> + <height>12</height> + </rect> + </property> + <property name="text"> + <string><html><head/><body><p><br/></p></body></html></string> + </property> + </widget> + <widget class="QPushButton" name="saveButton"> + <property name="geometry"> + <rect> + <x>490</x> + <y>510</y> + <width>114</width> + <height>32</height> + </rect> + </property> + <property name="text"> + <string>Save Graph</string> + </property> + </widget> + <action name="actionGoToPacket"> + <property name="text"> + <string>goToPacket</string> + </property> + <property name="toolTip"> + <string>Go to Packet</string> + </property> + </action> + </widget> + <customwidgets> + <customwidget> + <class>QCustomPlot</class> + <extends>QWidget</extends> + <header>qcustomplot.h</header> + <container>1</container> + </customwidget> + </customwidgets> + <resources/> + <connections> + <connection> + <sender>buttonBox</sender> + <signal>clicked(QAbstractButton*)</signal> + <receiver>SCTPGraphDialog</receiver> + <slot>close()</slot> + <hints> + <hint type="sourcelabel"> + <x>706</x> + <y>530</y> + </hint> + <hint type="destinationlabel"> + <x>703</x> + <y>574</y> + </hint> + </hints> + </connection> + </connections> +</ui> |