Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TCP reassembly - support closing connection with FIN + RST on one side #1496

Merged
merged 12 commits into from
Sep 25, 2024
5 changes: 5 additions & 0 deletions Packet++/src/TcpReassembly.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,11 @@ TcpReassembly::ReassemblyStatus TcpReassembly::reassemblePacket(Packet& tcpData)
if (tcpReassemblyData->twoSides[sideIndex].gotFinOrRst)
{
PCPP_LOG_DEBUG("Got a packet after FIN or RST were already seen on this side (" << static_cast<int>(sideIndex) << "). Ignoring this packet");
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's move this debug log to after the if condition?

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in this commit a1f3495

if (!tcpReassemblyData->twoSides[1 - sideIndex].gotFinOrRst && isRst)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not very familiar with this piece of code, could you explain why it's 1 - sideIndex here?

Copy link
Contributor Author

@prudens prudens Jul 13, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1-sideIndex is mean other side tcp stream,the sideIndex's value maybe 0 or 1.

{
handleFinOrRst(tcpReassemblyData, 1 - sideIndex, flowKey, isRst);
return FIN_RSTWithNoData;
}
return Ignore_PacketOfClosedFlow;
}

Expand Down
Binary file not shown.
1 change: 1 addition & 0 deletions Tests/Pcap++Test/TestDefinition.h
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ PTF_TEST_CASE(TestTcpReassemblyMaxOOOFrags);
PTF_TEST_CASE(TestTcpReassemblyMaxSeq);
PTF_TEST_CASE(TestTcpReassemblyDisableOOOCleanup);
PTF_TEST_CASE(TestTcpReassemblyTimeStamps);
PTF_TEST_CASE(TestTcpReassemblyFinishReset);

// Implemented in IPFragmentationTests.cpp
PTF_TEST_CASE(TestIPFragmentationSanity);
Expand Down
33 changes: 33 additions & 0 deletions Tests/Pcap++Test/Tests/TcpReassemblyTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1264,3 +1264,36 @@ PTF_TEST_CASE(TestTcpReassemblyTimeStamps)
packetStream.clear();
tcpReassemblyResults.clear();
} // TestTcpReassemblyTimeStamps

PTF_TEST_CASE(TestTcpReassemblyFinishReset)
{
TcpReassemblyMultipleConnStats results;
std::string errMsg;

pcpp::TcpReassemblyConfiguration config(true, 2, 1);
pcpp::TcpReassembly tcpReassembly(tcpReassemblyMsgReadyCallback, &results, tcpReassemblyConnectionStartCallback,
tcpReassemblyConnectionEndCallback, config);
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think a better approach would be to call tcpReassemblyTest(packetStream, tcpReassemblyResults, true, false) and check the results:

  • Verify there is only 1 connection
  • Verify that connectionsStarted == true, connectionsEnded == false, connectionsEndedManually == false
  • Verify that the number of packets from each side is what we expect


std::vector<pcpp::RawPacket> packetStream;
PTF_ASSERT_TRUE(
readPcapIntoPacketVec("PcapExamples/one_tcp_stream_fin_rst_close_packet.pcap", packetStream, errMsg));

pcpp::RawPacket lastPacket = packetStream.back();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

unused?


packetStream.pop_back();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why do you pop the last packet?


for (auto iter : packetStream)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let's declare tcpReassembly before this line.

{
pcpp::Packet packet(&iter);
tcpReassembly.reassemblePacket(packet);
}

pcpp::TcpReassembly::ConnectionInfoList managedConnections =
seladb marked this conversation as resolved.
Show resolved Hide resolved
tcpReassembly.getConnectionInformation(); // make a copy of list
PTF_ASSERT_EQUAL(managedConnections.size(), 1);
bool isOpen = tcpReassembly.isConnectionOpen(managedConnections.begin()->second);
PTF_ASSERT_FALSE(isOpen);

packetStream.clear();

} // TestTcpReassemblyFinishReset
1 change: 1 addition & 0 deletions Tests/Pcap++Test/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,7 @@ int main(int argc, char* argv[])
PTF_RUN_TEST(TestTcpReassemblyMaxSeq, "no_network;tcp_reassembly");
PTF_RUN_TEST(TestTcpReassemblyDisableOOOCleanup, "no_network;tcp_reassembly");
PTF_RUN_TEST(TestTcpReassemblyTimeStamps, "no_network;tcp_reassembly");
PTF_RUN_TEST(TestTcpReassemblyFinishReset, "no_network;tcp_reassembly");

PTF_RUN_TEST(TestIPFragmentationSanity, "no_network;ip_frag");
PTF_RUN_TEST(TestIPFragOutOfOrder, "no_network;ip_frag");
Expand Down
Loading