diff options
-rw-r--r-- | CMakeLists.txt | 5 | ||||
-rw-r--r-- | mainwindow.cpp | 190 | ||||
-rw-r--r-- | mainwindow.h | 9 | ||||
-rw-r--r-- | mainwindow.ui | 93 | ||||
-rw-r--r-- | packetstablewidget.cpp | 146 | ||||
-rw-r--r-- | packetstablewidget.h | 47 | ||||
-rw-r--r-- | pcapplusplus.cpp | 9 | ||||
-rw-r--r-- | pcapplusplus.h | 4 |
8 files changed, 317 insertions, 186 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 5e47b74..aab7a9f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -69,6 +69,9 @@ set(PROJECT_SOURCES pcapplusplus.cpp pcapplusplus.h + packetstablewidget.cpp + packetstablewidget.h + qhexedit2/src/chunks.cpp qhexedit2/src/chunks.h qhexedit2/src/commands.cpp @@ -97,7 +100,7 @@ endif() add_dependencies(pcap-editor PcapPlusPlus) -target_include_directories(pcap-editor PRIVATE ${CMAKE_BINARY_DIR}/ppp-install/include/pcapplusplus) +target_include_directories(pcap-editor PRIVATE ${CMAKE_SOURCE_DIR} ${CMAKE_BINARY_DIR}/ppp-install/include/pcapplusplus) target_link_libraries(pcap-editor PRIVATE Qt${QT_VERSION_MAJOR}::Widgets ${CMAKE_BINARY_DIR}/ppp-install/lib/libPcap++.a ${CMAKE_BINARY_DIR}/ppp-install/lib/libPacket++.a diff --git a/mainwindow.cpp b/mainwindow.cpp index 7391403..9b6534d 100644 --- a/mainwindow.cpp +++ b/mainwindow.cpp @@ -1,10 +1,10 @@ -#include "mainwindow.h" -#include "ui_mainwindow.h" - #include <exception> #include <qfiledialog.h> #include <QMouseEvent> +#include "mainwindow.h" +#include "ui_mainwindow.h" + MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , tableContextMenu() @@ -42,25 +42,6 @@ MainWindow::MainWindow(QWidget *parent) enableMenuButtons(this, false); enableHexEditButtons(this, false); - const auto& isEthernetSrcColumn = [this](const int& column) { - return column == 6; - }; - const auto& isEthernetDstColumn = [this](const int& column) { - return column == 7; - }; - const auto& isIpSrcColumn = [this](const int& column) { - return column == 8; - }; - const auto& isIpDstColumn = [this](const int& column) { - return column == 9; - }; - const auto& isPortSrcColumn = [this](const int& column) { - return column == 10; - }; - const auto& isPortDstColumn = [this](const int& column) { - return column == 11; - }; - tableContextMenu.randomize.setText("Randomize"); tableContextMenu.menu.addAction(&tableContextMenu.randomize); @@ -74,55 +55,31 @@ MainWindow::MainWindow(QWidget *parent) myHexEdit.contextMenu.addAction(&myHexEdit.deleteBytes); myHexEdit.contextMenu.addAction(&myHexEdit.deleteSelection); - connect(&tableContextMenu.randomize, &QAction::triggered, this, [this, isEthernetSrcColumn, isEthernetDstColumn, isIpSrcColumn, isIpDstColumn, isPortSrcColumn, isPortDstColumn](bool checked __attribute__((unused))){ - if (!ppp) - throw std::runtime_error("Can not randomize, no packets available"); + connect(&tableContextMenu.randomize, &QAction::triggered, this, [this](bool checked __attribute__((unused))){ + ui->tableWidget->randomizeLayerItem(ppp); - const auto & y = ui->tableWidget->currentRow(); - const auto & col = ui->tableWidget->currentColumn() + 1; - - if (isEthernetSrcColumn(col) || isEthernetDstColumn(col)) { - ppp->randomizeEth(y, isEthernetSrcColumn(col)); - } else if (isIpSrcColumn(col) || isIpDstColumn(col)) { - ppp->randomizeIp(y, isIpSrcColumn(col)); - } else if (isPortSrcColumn(col) || isPortDstColumn(col)) { - ppp->randomizePort(y, isPortSrcColumn(col)); - } else throw std::runtime_error("BUG: No supported column selected"); - - if (!MainWindow::updateTableRow(y)) - throw std::runtime_error("BUG: Could not update table row"); + const auto &rawPacket = ppp->getRawPacket(ui->tableWidget->currentRow()); + myHexEdit.editor.setData(QByteArray::fromRawData(reinterpret_cast<const char *>(rawPacket.getRawData()), rawPacket.getRawDataLen())); }); - connect(ui->tableWidget, &QTableWidget::itemChanged, this, [this, isEthernetSrcColumn, isEthernetDstColumn, isIpSrcColumn, isIpDstColumn, isPortSrcColumn, isPortDstColumn](QTableWidgetItem *item) { - if (!item || !ppp) - return; + connect(ui->tableWidget, &QTableWidget::itemChanged, this, [this](QTableWidgetItem *item) { + ui->tableWidget->setLayerItem(item, ppp, isProcessing); - const auto & y = ui->tableWidget->currentRow(); - const auto & col = ui->tableWidget->currentColumn() + 1; - const auto & text = item->text().toStdString(); - - if (isEthernetSrcColumn(col) || isEthernetDstColumn(col)) { - ppp->setEth(y, text, isEthernetSrcColumn(col)); - } else if (isIpSrcColumn(col) || isIpDstColumn(col)) { - ppp->setIp(y, text, isIpSrcColumn(col)); - } else if (isPortSrcColumn(col) || isPortDstColumn(col)) { - ppp->setPort(y, text, isPortSrcColumn(col)); + if (!isProcessing) { + const auto &rawPacket = ppp->getRawPacket(item->row()); + myHexEdit.editor.setData(QByteArray::fromRawData(reinterpret_cast<const char *>(rawPacket.getRawData()), rawPacket.getRawDataLen())); } - - if (isProcessing) - return; - if (!MainWindow::updateTableRow(y)) - throw std::runtime_error("BUG: Could not update table row"); }); - connect(ui->tableWidget, &QTableWidget::customContextMenuRequested, this, [this, enableTableButtons, isEthernetSrcColumn, isEthernetDstColumn, isIpSrcColumn, isIpDstColumn, isPortSrcColumn, isPortDstColumn](const QPoint& pos){ + connect(ui->tableWidget, &QTableWidget::customContextMenuRequested, this, [this, enableTableButtons](const QPoint& pos){ const auto & globalPos = ui->tableWidget->viewport()->mapToGlobal(pos); const auto & col = ui->tableWidget->currentColumn() + 1; + const auto & table = ui->tableWidget; if (ppp - && (isEthernetSrcColumn(col) || isEthernetDstColumn(col) - || isIpSrcColumn(col) || isIpDstColumn(col) - || isPortSrcColumn(col) || isPortDstColumn(col))) + && (table->isEthernetSrcColumn(col) || table->isEthernetDstColumn(col) + || table->isIpSrcColumn(col) || table->isIpDstColumn(col) + || table->isPortSrcColumn(col) || table->isPortDstColumn(col))) enableTableButtons(this, true); else enableTableButtons(this, false); @@ -203,7 +160,7 @@ MainWindow::MainWindow(QWidget *parent) if (fileName.length() > 0) { ui->lineEdit->clear(); ui->tableWidget->clearSelection(); - ui->tableWidget->clear(); + ui->tableWidget->clearContents(); ui->tableWidget->setRowCount(0); myHexEdit.editor.data().data_ptr()->clear(); enableTableButtons(this, true); @@ -231,7 +188,7 @@ MainWindow::MainWindow(QWidget *parent) throw std::runtime_error("Reopen PCAP File to apply a BPF failed."); if (!ppp->setFilter(ui->lineEdit->text())) throw std::runtime_error("Could not re-apply a previously set filter."); - ui->tableWidget->clear(); + ui->tableWidget->clearContents(); ui->tableWidget->setRowCount(0); emit processPcap(); } @@ -285,14 +242,12 @@ MainWindow::MainWindow(QWidget *parent) connect(this, &MainWindow::processPcap, this, [&](){ pcpp::Packet packet; if (!ppp) throw std::runtime_error("PcapPlusPlus was not initialized."); - firstPacketTs = 0; isProcessing = true; while (ppp->processPacket(packet)) { - if (!firstPacketTs) - firstPacketTs = packet.getRawPacket()->getPacketTimeStamp().tv_sec; emit onPacketAvailable(); } + ui->tableWidget->clearSelection(); isProcessing = false; pcpp::PcapFileReaderDevice::PcapStats stats; @@ -304,17 +259,14 @@ MainWindow::MainWindow(QWidget *parent) }); connect(this, &MainWindow::onPacketAvailable, this, [&]() { - if (!addTableRow()) - throw std::runtime_error("Could not add row to table for packet"); + emit ui->tableWidget->addRow(ppp); }); - connect(ui->tableWidget, &QTableWidget::cellPressed, this, [&] { - const auto &selected = ui->tableWidget->selectedItems(); - if (selected.empty()) - return; - - const auto &rawPacket = ppp->getRawPacket(selected.last()->row()); - myHexEdit.editor.setData(QByteArray::fromRawData(reinterpret_cast<const char *>(rawPacket.getRawData()), rawPacket.getRawDataLen())); + connect(ui->tableWidget, &QTableWidget::currentCellChanged, this, [&](int currentRow, int currentColumn, int previousRow, int previousColumn) { + if (!isProcessing && currentRow >= 0) { + const auto &rawPacket = ppp->getRawPacket(currentRow); + myHexEdit.editor.setData(QByteArray::fromRawData(reinterpret_cast<const char *>(rawPacket.getRawData()), rawPacket.getRawDataLen())); + } }); connect(ui->tableWidget, &QTableWidget::itemSelectionChanged, this, [this, enableHexEditButtons]() { @@ -363,96 +315,6 @@ pcpp::RawPacket* MainWindow::currentSelectedPacket() return &ppp->getRawPacket(selected.last()->row()); } -bool MainWindow::addTableRow() -{ - QTableWidgetItem* itemRelativeTime = new QTableWidgetItem(); - QTableWidgetItem* itemFrameLength = new QTableWidgetItem(); - QTableWidgetItem* itemFirstLayerProtocol = new QTableWidgetItem(); - QTableWidgetItem* itemSecondLayerProtocol = new QTableWidgetItem(); - QTableWidgetItem* itemThirdLayerProtocol = new QTableWidgetItem(); - QTableWidgetItem* itemSrcMac = new QTableWidgetItem(); - QTableWidgetItem* itemDstMac = new QTableWidgetItem(); - QTableWidgetItem* itemSrcIp = new QTableWidgetItem(); - QTableWidgetItem* itemDstIp = new QTableWidgetItem(); - QTableWidgetItem* itemSrcPort = new QTableWidgetItem(); - QTableWidgetItem* itemDstPort = new QTableWidgetItem(); - QTableWidgetItem* itemDesc = new QTableWidgetItem(); - - if (!itemRelativeTime || !itemFrameLength || !itemFirstLayerProtocol || !itemSecondLayerProtocol || !itemThirdLayerProtocol - || !itemSrcMac || !itemDstMac || !itemSrcIp || !itemDstIp || !itemSrcPort || ! itemDstPort || !itemDesc) - { - delete itemRelativeTime; - delete itemFrameLength; - delete itemFirstLayerProtocol; - delete itemSecondLayerProtocol; - delete itemThirdLayerProtocol; - delete itemSrcMac; - delete itemDstMac; - delete itemSrcIp; - delete itemDstIp; - delete itemSrcPort; - delete itemDstPort; - delete itemDesc; - - return false; - } - - ui->tableWidget->insertRow(ui->tableWidget->rowCount()); - ui->tableWidget->setItem(ui->tableWidget->rowCount() - 1, 0, itemRelativeTime); - ui->tableWidget->setItem(ui->tableWidget->rowCount() - 1, 1, itemFrameLength); - ui->tableWidget->setItem(ui->tableWidget->rowCount() - 1, 2, itemFirstLayerProtocol); - ui->tableWidget->setItem(ui->tableWidget->rowCount() - 1, 3, itemSecondLayerProtocol); - ui->tableWidget->setItem(ui->tableWidget->rowCount() - 1, 4, itemThirdLayerProtocol); - ui->tableWidget->setItem(ui->tableWidget->rowCount() - 1, 5, itemSrcMac); - ui->tableWidget->setItem(ui->tableWidget->rowCount() - 1, 6, itemDstMac); - ui->tableWidget->setItem(ui->tableWidget->rowCount() - 1, 7, itemSrcIp); - ui->tableWidget->setItem(ui->tableWidget->rowCount() - 1, 8, itemDstIp); - ui->tableWidget->setItem(ui->tableWidget->rowCount() - 1, 9, itemSrcPort); - ui->tableWidget->setItem(ui->tableWidget->rowCount() - 1, 10, itemDstPort); - ui->tableWidget->setItem(ui->tableWidget->rowCount() - 1, 11, itemDesc); - - ui->tableWidget->item(ui->tableWidget->rowCount() - 1, 0)->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemNeverHasChildren); - ui->tableWidget->item(ui->tableWidget->rowCount() - 1, 1)->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemNeverHasChildren); - ui->tableWidget->item(ui->tableWidget->rowCount() - 1, 2)->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemNeverHasChildren); - ui->tableWidget->item(ui->tableWidget->rowCount() - 1, 3)->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemNeverHasChildren); - ui->tableWidget->item(ui->tableWidget->rowCount() - 1, 4)->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemNeverHasChildren); - ui->tableWidget->item(ui->tableWidget->rowCount() - 1, 11)->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemNeverHasChildren); - - return updateTableRow(ui->tableWidget->rowCount() - 1); -} - -bool MainWindow::updateTableRow(size_t index) -{ - if (!ppp) - return false; - - auto parsedPacket = pcpp::Packet(&ppp->getRawPacket(index)); - const auto *firstLayer = PcapPlusPlus::getFirstLayer(parsedPacket); - const auto *secondLayer = firstLayer ? firstLayer->getNextLayer() : nullptr; - const auto *thirdLayer = secondLayer ? secondLayer->getNextLayer() : nullptr; - const auto ethTuple = PcapPlusPlus::getEthTuple(parsedPacket); - const auto ipTuple = PcapPlusPlus::getIpTuple(parsedPacket); - const auto l4Tuple = PcapPlusPlus::getLayer4Tuple(parsedPacket); - - if (!firstLayer) - return false; - - ui->tableWidget->item(index, 0)->setText(tr("%1").arg(parsedPacket.getRawPacket()->getPacketTimeStamp().tv_sec - firstPacketTs)); - ui->tableWidget->item(index, 1)->setText(tr("%1").arg(parsedPacket.getRawPacket()->getFrameLength())); - ui->tableWidget->item(index, 2)->setText(tr("%1").arg(firstLayer ? PcapPlusPlus::getProtocolTypeAsString(firstLayer->getProtocol()) : "")); - ui->tableWidget->item(index, 3)->setText(tr("%1").arg(secondLayer ? PcapPlusPlus::getProtocolTypeAsString(secondLayer->getProtocol()) : "")); - ui->tableWidget->item(index, 4)->setText(tr("%1").arg(thirdLayer ? PcapPlusPlus::getProtocolTypeAsString(thirdLayer->getProtocol()) : "")); - ui->tableWidget->item(index, 5)->setText(tr("%1").arg(std::get<0>(ethTuple))); - ui->tableWidget->item(index, 6)->setText(tr("%1").arg(std::get<1>(ethTuple))); - ui->tableWidget->item(index, 7)->setText(tr("%1").arg(std::get<0>(ipTuple))); - ui->tableWidget->item(index, 8)->setText(tr("%1").arg(std::get<1>(ipTuple))); - ui->tableWidget->item(index, 9)->setText(tr("%1").arg(std::get<0>(l4Tuple))); - ui->tableWidget->item(index, 10)->setText(tr("%1").arg(std::get<1>(l4Tuple))); - ui->tableWidget->item(index, 11)->setText(tr("%1").arg(QString::fromStdString(thirdLayer ? thirdLayer->toString() : (secondLayer ? secondLayer->toString() : (firstLayer ? firstLayer->toString() : ""))))); - - return true; -} - bool MainWindow::eventFilter(QObject *obj __attribute__((unused)), QEvent *event) { if (event->type() == QEvent::MouseMove) diff --git a/mainwindow.h b/mainwindow.h index a7d3a37..88b78c9 100644 --- a/mainwindow.h +++ b/mainwindow.h @@ -1,15 +1,15 @@ #ifndef MAINWINDOW_H #define MAINWINDOW_H -#include "bytewindow.h" -#include "pcapplusplus.h" -#include "qhexedit2/src/qhexedit.h" - #include <atomic> #include <optional> #include <QMainWindow> #include <QMenu> +#include "bytewindow.h" +#include "pcapplusplus.h" +#include "qhexedit2/src/qhexedit.h" + QT_BEGIN_NAMESPACE namespace Ui { class MainWindow; } QT_END_NAMESPACE @@ -49,7 +49,6 @@ private: int y; } mouse; - time_t firstPacketTs = 0; Ui::MainWindow *ui = nullptr; QString statusbarMessage; PcapPlusPlus *ppp = nullptr; diff --git a/mainwindow.ui b/mainwindow.ui index fc0c8a6..70451e5 100644 --- a/mainwindow.ui +++ b/mainwindow.ui @@ -42,7 +42,7 @@ <item> <layout class="QGridLayout" name="gridLayout"> <item row="1" column="0"> - <widget class="QTableWidget" name="tableWidget"> + <widget class="PacketsTableWidget" name="tableWidget"> <property name="styleSheet"> <string notr="true">color: black; background-color: white; @@ -68,21 +68,81 @@ border-color: beige;</string> <attribute name="horizontalHeaderCascadingSectionResizes"> <bool>false</bool> </attribute> + <attribute name="horizontalHeaderMinimumSectionSize"> + <number>120</number> + </attribute> + <attribute name="horizontalHeaderDefaultSectionSize"> + <number>120</number> + </attribute> + <attribute name="horizontalHeaderHighlightSections"> + <bool>false</bool> + </attribute> <attribute name="horizontalHeaderStretchLastSection"> <bool>true</bool> </attribute> - <column/> - <column/> - <column/> - <column/> - <column/> - <column/> - <column/> - <column/> - <column/> - <column/> - <column/> - <column/> + <attribute name="verticalHeaderVisible"> + <bool>false</bool> + </attribute> + <column> + <property name="text"> + <string>Timestamp</string> + </property> + </column> + <column> + <property name="text"> + <string>Packet Size</string> + </property> + </column> + <column> + <property name="text"> + <string>Layer 2</string> + </property> + </column> + <column> + <property name="text"> + <string>Layer 3</string> + </property> + </column> + <column> + <property name="text"> + <string>Layer 4</string> + </property> + </column> + <column> + <property name="text"> + <string>Layer 2 Source</string> + </property> + </column> + <column> + <property name="text"> + <string>Layer 2 Destination</string> + </property> + </column> + <column> + <property name="text"> + <string>Layer 3 Source</string> + </property> + </column> + <column> + <property name="text"> + <string>Layer 3 Destination</string> + </property> + </column> + <column> + <property name="text"> + <string>Layer 4 Source</string> + </property> + </column> + <column> + <property name="text"> + <string>Layer 4 Destination</string> + </property> + </column> + <column> + <property name="text"> + <string>Additional Information</string> + </property> + </column> </widget> </item> <item row="0" column="0"> @@ -128,6 +188,13 @@ border-color: beige;</string> </property> </action> </widget> + <customwidgets> + <customwidget> + <class>PacketsTableWidget</class> + <extends>QTableWidget</extends> + <header>packetstablewidget.h</header> + </customwidget> + </customwidgets> <resources/> <connections/> </ui> diff --git a/packetstablewidget.cpp b/packetstablewidget.cpp new file mode 100644 index 0000000..32a4a21 --- /dev/null +++ b/packetstablewidget.cpp @@ -0,0 +1,146 @@ +#include "packetstablewidget.h" + +PacketsTableWidget::PacketsTableWidget(QWidget *parent) : QTableWidget(parent) +{ + connect(this, &PacketsTableWidget::addRow, this, [&](PcapPlusPlus *ppp) { + if (!addTableRow(ppp)) + throw std::runtime_error("Could not add row to table for packet"); + }); + + connect(this, &PacketsTableWidget::updateRow, this, [&](size_t index, PcapPlusPlus *ppp) { + if (!updateTableRow(index, ppp)) + throw std::runtime_error("Could not add row to table for packet"); + }); +} + +void PacketsTableWidget::randomizeLayerItem(PcapPlusPlus *ppp) +{ + if (!ppp) + throw std::runtime_error("Can not randomize, no packets available"); + + const auto & y = currentRow(); + const auto & col = currentColumn() + 1; + + if (isEthernetSrcColumn(col) || isEthernetDstColumn(col)) { + ppp->randomizeEth(y, isEthernetSrcColumn(col)); + } else if (isIpSrcColumn(col) || isIpDstColumn(col)) { + ppp->randomizeIp(y, isIpSrcColumn(col)); + } else if (isPortSrcColumn(col) || isPortDstColumn(col)) { + ppp->randomizePort(y, isPortSrcColumn(col)); + } else throw std::runtime_error("BUG: No supported column selected"); + + emit updateRow(y, ppp); +} + +void PacketsTableWidget::setLayerItem(QTableWidgetItem *item, PcapPlusPlus *ppp, bool isProcessing) +{ + if (!item || !ppp) + return; + + const auto & y = currentRow(); + const auto & col = currentColumn() + 1; + const auto & text = item->text().toStdString(); + + if (isEthernetSrcColumn(col) || isEthernetDstColumn(col)) { + ppp->setEth(y, text, isEthernetSrcColumn(col)); + } else if (isIpSrcColumn(col) || isIpDstColumn(col)) { + ppp->setIp(y, text, isIpSrcColumn(col)); + } else if (isPortSrcColumn(col) || isPortDstColumn(col)) { + ppp->setPort(y, text, isPortSrcColumn(col)); + } + + if (isProcessing) + return; + emit updateRow(y, ppp); +} + +bool PacketsTableWidget::addTableRow(PcapPlusPlus *ppp) +{ + QTableWidgetItem* itemRelativeTime = new QTableWidgetItem(); + QTableWidgetItem* itemFrameLength = new QTableWidgetItem(); + QTableWidgetItem* itemFirstLayerProtocol = new QTableWidgetItem(); + QTableWidgetItem* itemSecondLayerProtocol = new QTableWidgetItem(); + QTableWidgetItem* itemThirdLayerProtocol = new QTableWidgetItem(); + QTableWidgetItem* itemSrcMac = new QTableWidgetItem(); + QTableWidgetItem* itemDstMac = new QTableWidgetItem(); + QTableWidgetItem* itemSrcIp = new QTableWidgetItem(); + QTableWidgetItem* itemDstIp = new QTableWidgetItem(); + QTableWidgetItem* itemSrcPort = new QTableWidgetItem(); + QTableWidgetItem* itemDstPort = new QTableWidgetItem(); + QTableWidgetItem* itemDesc = new QTableWidgetItem(); + + if (!itemRelativeTime || !itemFrameLength || !itemFirstLayerProtocol || !itemSecondLayerProtocol || !itemThirdLayerProtocol + || !itemSrcMac || !itemDstMac || !itemSrcIp || !itemDstIp || !itemSrcPort || ! itemDstPort || !itemDesc) + { + delete itemRelativeTime; + delete itemFrameLength; + delete itemFirstLayerProtocol; + delete itemSecondLayerProtocol; + delete itemThirdLayerProtocol; + delete itemSrcMac; + delete itemDstMac; + delete itemSrcIp; + delete itemDstIp; + delete itemSrcPort; + delete itemDstPort; + delete itemDesc; + + return false; + } + + insertRow(rowCount()); + setItem(rowCount() - 1, 0, itemRelativeTime); + setItem(rowCount() - 1, 1, itemFrameLength); + setItem(rowCount() - 1, 2, itemFirstLayerProtocol); + setItem(rowCount() - 1, 3, itemSecondLayerProtocol); + setItem(rowCount() - 1, 4, itemThirdLayerProtocol); + setItem(rowCount() - 1, 5, itemSrcMac); + setItem(rowCount() - 1, 6, itemDstMac); + setItem(rowCount() - 1, 7, itemSrcIp); + setItem(rowCount() - 1, 8, itemDstIp); + setItem(rowCount() - 1, 9, itemSrcPort); + setItem(rowCount() - 1, 10, itemDstPort); + setItem(rowCount() - 1, 11, itemDesc); + + item(rowCount() - 1, 0)->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemNeverHasChildren); + item(rowCount() - 1, 1)->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemNeverHasChildren); + item(rowCount() - 1, 2)->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemNeverHasChildren); + item(rowCount() - 1, 3)->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemNeverHasChildren); + item(rowCount() - 1, 4)->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemNeverHasChildren); + item(rowCount() - 1, 11)->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemNeverHasChildren); + + emit updateRow(rowCount() - 1, ppp); + return true; +} + +bool PacketsTableWidget::updateTableRow(size_t index, PcapPlusPlus *ppp) +{ + if (!ppp) + return false; + + auto parsedPacket = pcpp::Packet(&ppp->getRawPacket(index)); + const auto *firstLayer = PcapPlusPlus::getFirstLayer(parsedPacket); + const auto *secondLayer = firstLayer ? firstLayer->getNextLayer() : nullptr; + const auto *thirdLayer = secondLayer ? secondLayer->getNextLayer() : nullptr; + const auto ethTuple = PcapPlusPlus::getEthTuple(parsedPacket); + const auto ipTuple = PcapPlusPlus::getIpTuple(parsedPacket); + const auto l4Tuple = PcapPlusPlus::getLayer4Tuple(parsedPacket); + + if (!firstLayer) + return false; + + item(index, 0)->setText(tr("%1").arg(parsedPacket.getRawPacket()->getPacketTimeStamp().tv_sec - static_cast<unsigned long long int>(ppp->getFirstPacketTimestamp()))); + item(index, 1)->setText(tr("%1").arg(parsedPacket.getRawPacket()->getFrameLength())); + item(index, 2)->setText(tr("%1").arg(firstLayer ? PcapPlusPlus::getProtocolTypeAsString(firstLayer->getProtocol()) : "")); + item(index, 3)->setText(tr("%1").arg(secondLayer ? PcapPlusPlus::getProtocolTypeAsString(secondLayer->getProtocol()) : "")); + item(index, 4)->setText(tr("%1").arg(thirdLayer ? PcapPlusPlus::getProtocolTypeAsString(thirdLayer->getProtocol()) : "")); + item(index, 5)->setText(tr("%1").arg(std::get<0>(ethTuple))); + item(index, 6)->setText(tr("%1").arg(std::get<1>(ethTuple))); + item(index, 7)->setText(tr("%1").arg(std::get<0>(ipTuple))); + item(index, 8)->setText(tr("%1").arg(std::get<1>(ipTuple))); + item(index, 9)->setText(tr("%1").arg(std::get<0>(l4Tuple))); + item(index, 10)->setText(tr("%1").arg(std::get<1>(l4Tuple))); + item(index, 11)->setText(tr("%1").arg(QString::fromStdString(thirdLayer ? thirdLayer->toString() : (secondLayer ? secondLayer->toString() : (firstLayer ? firstLayer->toString() : ""))))); + + return true; +} diff --git a/packetstablewidget.h b/packetstablewidget.h new file mode 100644 index 0000000..0de46f9 --- /dev/null +++ b/packetstablewidget.h @@ -0,0 +1,47 @@ +#ifndef PACKETSTABLEWIDGET_H +#define PACKETSTABLEWIDGET_H + +#include <QTableWidget> + +#include "pcapplusplus.h" + +class PacketsTableWidget : public QTableWidget +{ + Q_OBJECT + +public: + PacketsTableWidget(QWidget *parent = nullptr); + + bool isEthernetSrcColumn(const int& column) { + return column == 6; + }; + bool isEthernetDstColumn(const int& column) { + return column == 7; + }; + bool isIpSrcColumn(const int& column) { + return column == 8; + }; + bool isIpDstColumn(const int& column) { + return column == 9; + }; + bool isPortSrcColumn(const int& column) { + return column == 10; + }; + bool isPortDstColumn(const int& column) { + return column == 11; + }; + +private: + bool addTableRow(PcapPlusPlus *ppp); + bool updateTableRow(size_t index, PcapPlusPlus *ppp); + +signals: + bool addRow(PcapPlusPlus *ppp); + bool updateRow(size_t index, PcapPlusPlus *ppp); + +public slots: + void randomizeLayerItem(PcapPlusPlus *ppp); + void setLayerItem(QTableWidgetItem *item, PcapPlusPlus *ppp, bool isProcessing); +}; + +#endif // PACKETSTABLEWIDGET_H diff --git a/pcapplusplus.cpp b/pcapplusplus.cpp index ea0acb7..0848401 100644 --- a/pcapplusplus.cpp +++ b/pcapplusplus.cpp @@ -1,5 +1,3 @@ -#include "pcapplusplus.h" - #include <chrono> #include <EthLayer.h> #include <exception> @@ -12,6 +10,8 @@ #include <tuple> #include <UdpLayer.h> +#include "pcapplusplus.h" + PcapPlusPlus::PcapPlusPlus(std::string fileName) : rawPackets(), parsedPackets() { reader = pcpp::IFileReaderDevice::getReader(fileName); @@ -69,6 +69,11 @@ bool PcapPlusPlus::processPacket(pcpp::Packet & packet) return false; if (reader->getNextPacket(rawPacket)) { + if (rawPackets.size() == 0) { + const auto & pktTs = rawPacket.getPacketTimeStamp(); + firstPacketTs = pktTs.tv_sec; + firstPacketTs += pktTs.tv_nsec / 10e9f; + } rawPackets.emplace_back(std::move(rawPacket)); pcpp::Packet parsedPacket(&rawPackets.back(), false); diff --git a/pcapplusplus.h b/pcapplusplus.h index e2ab070..c0f0eb6 100644 --- a/pcapplusplus.h +++ b/pcapplusplus.h @@ -28,6 +28,7 @@ public: bool setIp(size_t index, const std::string & ip, bool isSourceIp); bool setPort(size_t index, const std::string & port, bool isSourceIp); bool getPcapStatistics(pcpp::IFileDevice::PcapStats & stats); + double getFirstPacketTimestamp() { return firstPacketTs; } static const pcpp::Layer *getFirstLayer(const pcpp::Packet & packet); static QString getProtocolTypeAsString(pcpp::ProtocolType protocolType); @@ -36,7 +37,8 @@ public: static std::tuple<uint16_t, uint16_t> getLayer4Tuple(const pcpp::Packet & packet); private: - pcpp::IFileReaderDevice *reader; + double firstPacketTs = 0; + pcpp::IFileReaderDevice *reader = nullptr; std::vector<pcpp::RawPacket> rawPackets; std::vector<pcpp::Packet> parsedPackets; }; |