summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mainwindow.cpp240
-rw-r--r--mainwindow.h10
-rw-r--r--mainwindow.ui6
-rw-r--r--pcapplusplus.cpp44
-rw-r--r--pcapplusplus.h1
5 files changed, 236 insertions, 65 deletions
diff --git a/mainwindow.cpp b/mainwindow.cpp
index 69e46bd..d4aeac2 100644
--- a/mainwindow.cpp
+++ b/mainwindow.cpp
@@ -8,15 +8,21 @@
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
+ , tableContextMenu()
, myHexEdit()
, ui(new Ui::MainWindow)
, ppp(nullptr)
{
ui->setupUi(this);
ui->gridLayout->addWidget(&myHexEdit.editor);
+ ui->tableWidget->setContextMenuPolicy(Qt::CustomContextMenu);
+ const auto& enableTableButtons = [](MainWindow *mainwindow, bool enable) {
+ mainwindow->tableContextMenu.randomize.setEnabled(enable);
+ };
const auto& enableMenuButtons = [](MainWindow *mainwindow, bool enable) {
mainwindow->ui->actionSave->setEnabled(enable);
+ mainwindow->ui->actionSave_Selection->setEnabled(enable);
};
const auto& enableHexEditButtons = [](MainWindow *mainwindow, bool enable) {
mainwindow->myHexEdit.prependBytes.setEnabled(enable);
@@ -24,9 +30,24 @@ MainWindow::MainWindow(QWidget *parent)
mainwindow->myHexEdit.deleteBytes.setEnabled(enable);
mainwindow->myHexEdit.deleteSelection.setEnabled(enable);
};
+ enableTableButtons(this, false);
enableMenuButtons(this, false);
enableHexEditButtons(this, false);
+ const auto& isIpColumn = [this](const int& column) {
+ switch (column) {
+ case 8:
+ return std::make_tuple(true, false);
+ case 9:
+ return std::make_tuple(false, true);
+ default:
+ return std::make_tuple(false, false);
+ }
+ };
+
+ tableContextMenu.randomize.setText("Randomize");
+ tableContextMenu.menu.addAction(&tableContextMenu.randomize);
+
myHexEdit.editor.setContextMenuPolicy(Qt::CustomContextMenu);
myHexEdit.prependBytes.setText("Prepend byte(s)..");
myHexEdit.appendBytes.setText("Append byte(s)..");
@@ -37,6 +58,32 @@ MainWindow::MainWindow(QWidget *parent)
myHexEdit.contextMenu.addAction(&myHexEdit.deleteBytes);
myHexEdit.contextMenu.addAction(&myHexEdit.deleteSelection);
+ connect(&tableContextMenu.randomize, &QAction::triggered, this, [this, isIpColumn](bool checked __attribute__((unused))){
+ if (!ppp)
+ throw std::runtime_error("Can not randomize, no packets available");
+
+ const auto & row = ui->tableWidget->currentRow();
+ const auto & ipColumn = isIpColumn(ui->tableWidget->currentColumn() + 1);
+
+ if (std::get<0>(ipColumn) || std::get<1>(ipColumn)) {
+ ppp->randomizeIp(row, std::get<0>(ipColumn));
+ if (!MainWindow::setTableRow(row, ppp->getParsedPacket(row)))
+ throw std::runtime_error("BUG: Could not change table row");
+ } else throw std::runtime_error("BUG: No IP column selected");
+ });
+
+ connect(ui->tableWidget, &QTableWidget::customContextMenuRequested, this, [this, enableTableButtons, isIpColumn](const QPoint& pos){
+ const auto & globalPos = ui->tableWidget->viewport()->mapToGlobal(pos);
+ const auto & ipColumn = isIpColumn(ui->tableWidget->columnAt(pos.x()) + 1);
+
+ if ((std::get<0>(ipColumn) || std::get<1>(ipColumn)) && ppp)
+ enableTableButtons(this, true);
+ else
+ enableTableButtons(this, false);
+
+ tableContextMenu.menu.popup(globalPos);
+ });
+
connect(&myHexEdit.bytewindow, &QDialog::finished, this, [&](int result) {
if (result == 0)
return;
@@ -105,8 +152,8 @@ MainWindow::MainWindow(QWidget *parent)
}
});
- connect(ui->actionOpen, &QAction::triggered, this, [this, enableMenuButtons, enableHexEditButtons](bool){
- QString fileName = QFileDialog::getOpenFileName(this, tr("Open PCAP File"), "", tr("PCAP Files (*.pcap)"));
+ connect(ui->actionOpen, &QAction::triggered, this, [this, enableTableButtons, enableMenuButtons, enableHexEditButtons](bool){
+ QString fileName = QFileDialog::getOpenFileName(this, tr("Open PCAP File"), "", tr("PCAP Files (*.pcap);;All Files (*.*)"));
if (fileName.length() > 0) {
if (ppp) {
delete ppp;
@@ -116,8 +163,10 @@ MainWindow::MainWindow(QWidget *parent)
ui->tableWidget->clear();
ui->tableWidget->setRowCount(0);
myHexEdit.editor.data().data_ptr()->clear();
+ enableTableButtons(this, true);
enableMenuButtons(this, true);
enableHexEditButtons(this, false);
+ ui->actionSave_Selection->setEnabled(false);
ppp = new PcapPlusPlus(fileName.toStdString());
if (ppp) emit processPcap();
}
@@ -142,19 +191,39 @@ MainWindow::MainWindow(QWidget *parent)
});
connect(ui->actionSave, &QAction::triggered, this, [&](bool){
- if (ppp) {
- QString selectedFilter;
- QString fileName = QFileDialog::getSaveFileName(this, tr("Save PCAP File"), "", tr("PCAP Files (*.pcap)"), &selectedFilter);
- if (fileName.length() > 0) {
- pcpp::PcapFileWriterDevice pcapWriter(fileName.toStdString(), ppp->getLinkLayer());
- if (!pcapWriter.open())
- throw std::runtime_error("Could not open file " + fileName.toStdString() + " for writing.");
- {
- for (auto rawPacket = ppp->rawPacketsBegin(); rawPacket < ppp->rawPacketsEnd(); rawPacket++) {
- pcapWriter.writePacket(*rawPacket);
- }
- pcapWriter.flush();
+ if (!ppp)
+ return;
+
+ QString selectedFilter;
+ QString fileName = QFileDialog::getSaveFileName(this, tr("Save PCAP File"), "", tr("PCAP Files (*.pcap);;All Files (*.*)"), &selectedFilter);
+ if (fileName.length() > 0) {
+ pcpp::PcapFileWriterDevice pcapWriter(fileName.toStdString(), ppp->getLinkLayer());
+ if (!pcapWriter.open())
+ throw std::runtime_error("Could not open file " + fileName.toStdString() + " for writing.");
+ {
+ for (auto rawPacket = ppp->rawPacketsBegin(); rawPacket < ppp->rawPacketsEnd(); rawPacket++) {
+ pcapWriter.writePacket(*rawPacket);
+ }
+ pcapWriter.flush();
+ }
+ }
+ });
+
+ connect(ui->actionSave_Selection, &QAction::triggered, this, [&](bool){
+ if (!ppp)
+ return;
+
+ QString selectedFilter;
+ QString fileName = QFileDialog::getSaveFileName(this, tr("Save PCAP File"), "", tr("PCAP Files (*.pcap);;All Files (*.*)"), &selectedFilter);
+ if (fileName.length() > 0) {
+ pcpp::PcapFileWriterDevice pcapWriter(fileName.toStdString(), ppp->getLinkLayer());
+ if (!pcapWriter.open())
+ throw std::runtime_error("Could not open file " + fileName.toStdString() + " for writing.");
+ {
+ for (const auto & selected : ui->tableWidget->selectedRanges()) {
+ pcapWriter.writePacket(ppp->getRawPacket(selected.topRow()));
}
+ pcapWriter.flush();
}
}
});
@@ -177,55 +246,8 @@ MainWindow::MainWindow(QWidget *parent)
});
connect(this, &MainWindow::onPacketAvailable, this, [&](const pcpp::Packet& packet) {
- ui->tableWidget->insertRow(ui->tableWidget->rowCount());
-
- QTableWidgetItem* itemRelativeTime =new QTableWidgetItem(tr("%1").arg(packet.getRawPacket()->getPacketTimeStamp().tv_sec - firstPacketTs));
- ui->tableWidget->setItem(ui->tableWidget->rowCount() - 1, 0, itemRelativeTime);
-
- QTableWidgetItem* itemFrameLength = new QTableWidgetItem(tr("%1").arg(packet.getRawPacket()->getFrameLength()));
- ui->tableWidget->setItem(ui->tableWidget->rowCount() - 1, 1, itemFrameLength);
-
- const auto *firstLayer = PcapPlusPlus::getFirstLayer(packet);
-
- QTableWidgetItem* itemFirstLayerProtocol = new QTableWidgetItem(tr("%1").arg(firstLayer ? PcapPlusPlus::getProtocolTypeAsString(firstLayer->getProtocol()) : ""));
- ui->tableWidget->setItem(ui->tableWidget->rowCount() - 1, 2, itemFirstLayerProtocol);
-
- const auto *secondLayer = firstLayer ? firstLayer->getNextLayer() : nullptr;
-
- QTableWidgetItem* itemSecondLayerProtocol = new QTableWidgetItem(tr("%1").arg(secondLayer ? PcapPlusPlus::getProtocolTypeAsString(secondLayer->getProtocol()) : ""));
- ui->tableWidget->setItem(ui->tableWidget->rowCount() - 1, 3, itemSecondLayerProtocol);
-
- const auto *thirdLayer = secondLayer ? secondLayer->getNextLayer() : nullptr;
-
- QTableWidgetItem* itemThirdLayerProtocol = new QTableWidgetItem(tr("%1").arg(thirdLayer ? PcapPlusPlus::getProtocolTypeAsString(thirdLayer->getProtocol()) : ""));
- ui->tableWidget->setItem(ui->tableWidget->rowCount() - 1, 4, itemThirdLayerProtocol);
-
- const auto ethTuple = PcapPlusPlus::getEthTuple(packet);
-
- QTableWidgetItem* itemSrcMac = new QTableWidgetItem(tr("%1").arg(std::get<0>(ethTuple)));
- ui->tableWidget->setItem(ui->tableWidget->rowCount() - 1, 5, itemSrcMac);
-
- QTableWidgetItem* itemDstMac = new QTableWidgetItem(tr("%1").arg(std::get<1>(ethTuple)));
- ui->tableWidget->setItem(ui->tableWidget->rowCount() - 1, 6, itemDstMac);
-
- const auto ipTuple = PcapPlusPlus::getIpTuple(packet);
-
- QTableWidgetItem* itemSrcIp = new QTableWidgetItem(tr("%1").arg(std::get<0>(ipTuple)));
- ui->tableWidget->setItem(ui->tableWidget->rowCount() - 1, 7, itemSrcIp);
-
- QTableWidgetItem* itemDstIp = new QTableWidgetItem(tr("%1").arg(std::get<1>(ipTuple)));
- ui->tableWidget->setItem(ui->tableWidget->rowCount() - 1, 8, itemDstIp);
-
- const auto l4Tuple = PcapPlusPlus::getLayer4Tuple(packet);
-
- QTableWidgetItem* itemSrcPort = new QTableWidgetItem(tr("%1").arg(std::get<0>(l4Tuple)));
- ui->tableWidget->setItem(ui->tableWidget->rowCount() - 1, 9, itemSrcPort);
-
- QTableWidgetItem* itemDstPort = new QTableWidgetItem(tr("%1").arg(std::get<1>(l4Tuple)));
- ui->tableWidget->setItem(ui->tableWidget->rowCount() - 1, 10, itemDstPort);
-
- QTableWidgetItem* itemDesc = new QTableWidgetItem(tr("%1").arg(QString::fromStdString(thirdLayer ? thirdLayer->toString() : (secondLayer ? secondLayer->toString() : (firstLayer ? firstLayer->toString() : "")))));
- ui->tableWidget->setItem(ui->tableWidget->rowCount() - 1, 11, itemDesc);
+ if (!addTableRow(packet))
+ throw std::runtime_error("Could not add row to table for packet: " + packet.toString());
});
connect(ui->tableWidget, &QTableWidget::cellPressed, this, [&] {
@@ -237,8 +259,9 @@ MainWindow::MainWindow(QWidget *parent)
myHexEdit.editor.setData(QByteArray::fromRawData(reinterpret_cast<const char *>(rawPacket.getRawData()), rawPacket.getRawDataLen()));
});
- connect(ui->tableWidget, &QTableWidget::itemSelectionChanged, this, [&]() {
+ connect(ui->tableWidget, &QTableWidget::itemSelectionChanged, this, [this, enableHexEditButtons]() {
enableHexEditButtons(this, ui->tableWidget->selectedItems().size() > 0);
+ ui->actionSave_Selection->setEnabled(ui->tableWidget->selectedItems().size() > 0);
if (ui->tableWidget->selectedItems().size() == 0 && myHexEdit.editor.data().size() > 0)
myHexEdit.editor.setData(QByteArray());
});
@@ -275,3 +298,92 @@ pcpp::RawPacket* MainWindow::currentSelectedPacket()
return &ppp->getRawPacket(selected.last()->row());
}
+
+bool MainWindow::addTableRow(const pcpp::Packet& packet)
+{
+ const auto *firstLayer = PcapPlusPlus::getFirstLayer(packet);
+ const auto *secondLayer = firstLayer ? firstLayer->getNextLayer() : nullptr;
+ const auto *thirdLayer = secondLayer ? secondLayer->getNextLayer() : nullptr;
+ const auto ethTuple = PcapPlusPlus::getEthTuple(packet);
+ const auto ipTuple = PcapPlusPlus::getIpTuple(packet);
+ const auto l4Tuple = PcapPlusPlus::getLayer4Tuple(packet);
+
+ if (!firstLayer)
+ return false;
+
+ QTableWidgetItem* itemRelativeTime = new QTableWidgetItem(tr("%1").arg(packet.getRawPacket()->getPacketTimeStamp().tv_sec - firstPacketTs));
+ QTableWidgetItem* itemFrameLength = new QTableWidgetItem(tr("%1").arg(packet.getRawPacket()->getFrameLength()));
+ QTableWidgetItem* itemFirstLayerProtocol = new QTableWidgetItem(tr("%1").arg(firstLayer ? PcapPlusPlus::getProtocolTypeAsString(firstLayer->getProtocol()) : ""));
+ QTableWidgetItem* itemSecondLayerProtocol = new QTableWidgetItem(tr("%1").arg(secondLayer ? PcapPlusPlus::getProtocolTypeAsString(secondLayer->getProtocol()) : ""));
+ QTableWidgetItem* itemThirdLayerProtocol = new QTableWidgetItem(tr("%1").arg(thirdLayer ? PcapPlusPlus::getProtocolTypeAsString(thirdLayer->getProtocol()) : ""));
+ QTableWidgetItem* itemSrcMac = new QTableWidgetItem(tr("%1").arg(std::get<0>(ethTuple)));
+ QTableWidgetItem* itemDstMac = new QTableWidgetItem(tr("%1").arg(std::get<1>(ethTuple)));
+ QTableWidgetItem* itemSrcIp = new QTableWidgetItem(tr("%1").arg(std::get<0>(ipTuple)));
+ QTableWidgetItem* itemDstIp = new QTableWidgetItem(tr("%1").arg(std::get<1>(ipTuple)));
+ QTableWidgetItem* itemSrcPort = new QTableWidgetItem(tr("%1").arg(std::get<0>(l4Tuple)));
+ QTableWidgetItem* itemDstPort = new QTableWidgetItem(tr("%1").arg(std::get<1>(l4Tuple)));
+ QTableWidgetItem* itemDesc = new QTableWidgetItem(tr("%1").arg(QString::fromStdString(thirdLayer ? thirdLayer->toString() : (secondLayer ? secondLayer->toString() : (firstLayer ? firstLayer->toString() : "")))));
+
+ 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);
+
+ return true;
+}
+
+bool MainWindow::setTableRow(size_t index, const pcpp::Packet& packet)
+{
+ const auto *firstLayer = PcapPlusPlus::getFirstLayer(packet);
+ const auto *secondLayer = firstLayer ? firstLayer->getNextLayer() : nullptr;
+ const auto *thirdLayer = secondLayer ? secondLayer->getNextLayer() : nullptr;
+ const auto ethTuple = PcapPlusPlus::getEthTuple(packet);
+ const auto ipTuple = PcapPlusPlus::getIpTuple(packet);
+ const auto l4Tuple = PcapPlusPlus::getLayer4Tuple(packet);
+
+ if (!firstLayer)
+ return false;
+
+ ui->tableWidget->item(index, 0)->setText(tr("%1").arg(packet.getRawPacket()->getPacketTimeStamp().tv_sec - firstPacketTs));
+ ui->tableWidget->item(index, 1)->setText(tr("%1").arg(packet.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;
+}
diff --git a/mainwindow.h b/mainwindow.h
index f5e1c39..5670898 100644
--- a/mainwindow.h
+++ b/mainwindow.h
@@ -21,8 +21,16 @@ public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
pcpp::RawPacket* currentSelectedPacket();
+ bool addTableRow(const pcpp::Packet& packet);
+ bool setTableRow(size_t index, const pcpp::Packet& packet);
+
private:
struct {
+ QMenu menu;
+ QAction randomize;
+ } tableContextMenu;
+
+ struct {
QMenu contextMenu;
QAction prependBytes;
QAction appendBytes;
@@ -33,8 +41,8 @@ private:
} myHexEdit;
time_t firstPacketTs;
- PcapPlusPlus *ppp;
Ui::MainWindow *ui;
+ PcapPlusPlus *ppp;
signals:
void processPcap();
diff --git a/mainwindow.ui b/mainwindow.ui
index 340b454..fc0c8a6 100644
--- a/mainwindow.ui
+++ b/mainwindow.ui
@@ -107,6 +107,7 @@ border-color: beige;</string>
</property>
<addaction name="actionOpen"/>
<addaction name="actionSave"/>
+ <addaction name="actionSave_Selection"/>
</widget>
<addaction name="menuFile"/>
</widget>
@@ -121,6 +122,11 @@ border-color: beige;</string>
<string>Save</string>
</property>
</action>
+ <action name="actionSave_Selection">
+ <property name="text">
+ <string>Save Selection</string>
+ </property>
+ </action>
</widget>
<resources/>
<connections/>
diff --git a/pcapplusplus.cpp b/pcapplusplus.cpp
index 743e845..004db71 100644
--- a/pcapplusplus.cpp
+++ b/pcapplusplus.cpp
@@ -1,9 +1,13 @@
#include "pcapplusplus.h"
+#include <chrono>
#include <EthLayer.h>
#include <exception>
#include <IPLayer.h>
+#include <IPv4Layer.h>
+#include <IPv6Layer.h>
#include <TcpLayer.h>
+#include <random>
#include <tuple>
#include <UdpLayer.h>
@@ -117,6 +121,46 @@ std::vector<pcpp::Packet>::iterator PcapPlusPlus::parsedPacketsEnd()
return parsedPackets.end();
}
+bool PcapPlusPlus::randomizeIp(size_t index, bool isSourceIp)
+{
+ std::default_random_engine generator(std::chrono::system_clock::now().time_since_epoch().count());
+ auto retval = false;
+ pcpp::RawPacket rawPacket(getRawPacket(index));
+ pcpp::Packet parsedPacket(&rawPacket);
+ auto * ip4Layer = parsedPacket.getLayerOfType<pcpp::IPv4Layer>();
+ auto * ip6Layer = parsedPacket.getLayerOfType<pcpp::IPv6Layer>();
+
+ if (ip4Layer) {
+ std::uniform_int_distribution<unsigned int> ip4Distribution(0, 0xFFFFFFFF);
+
+ if (isSourceIp)
+ ip4Layer->setSrcIPv4Address(pcpp::IPv4Address(ip4Distribution(generator)));
+ else
+ ip4Layer->setDstIPv4Address(pcpp::IPv4Address(ip4Distribution(generator)));
+
+ retval = true;
+ }
+
+ if (ip6Layer) {
+ std::uniform_int_distribution<unsigned long long int> ip6Distribution(0, 0xFFFFFFFFFFFFFFFF);
+ unsigned long long int newIp6Addr[2] { ip6Distribution(generator), ip6Distribution(generator) };
+
+ if (isSourceIp)
+ ip6Layer->setSrcIPv6Address(reinterpret_cast<uint8_t *>(newIp6Addr));
+ else
+ ip6Layer->setDstIPv6Address(reinterpret_cast<uint8_t *>(newIp6Addr));
+
+ retval = true;
+ }
+
+ rawPackets.erase(rawPackets.cbegin() + index);
+ rawPackets.insert(rawPackets.cbegin() + index, rawPacket);
+ parsedPackets.erase(parsedPackets.cbegin() + index);
+ parsedPackets.insert(parsedPackets.cbegin() + index, parsedPacket);
+
+ return retval;
+}
+
bool PcapPlusPlus::getPcapStatistics(pcpp::IFileDevice::PcapStats & stats)
{
if (reader) {
diff --git a/pcapplusplus.h b/pcapplusplus.h
index 81d1b9d..04756e6 100644
--- a/pcapplusplus.h
+++ b/pcapplusplus.h
@@ -21,6 +21,7 @@ public:
std::vector<pcpp::RawPacket>::iterator rawPacketsEnd();
std::vector<pcpp::Packet>::iterator parsedPacketsBegin();
std::vector<pcpp::Packet>::iterator parsedPacketsEnd();
+ bool randomizeIp(size_t index, bool isSourceIp);
bool getPcapStatistics(pcpp::IFileDevice::PcapStats & stats);
static const pcpp::Layer *getFirstLayer(const pcpp::Packet & packet);