Skip to content

Commit a87c74a

Browse files
authored
Extracted MTU check code into its own helper functions. (#1834)
* Extracted MTU check code into its own helper functions. * Fixed inverted if condition. * Replaced call to sendPacket with sendPacketUnchecked. * Apply suggestions from code review Fixed comments * Lint * Renamed checkMtu functions to isPayloadWithinMtu. - Moved checkMtu family of functions to public access. * Deprecated doMtuCheck. * Added guard against negative data length. * Lint * Added comments explaining why unknown length is allowed. * Expanded documentation on the ckeck's return value if the length is unknown. * Improved documentation for value of outPayloadLength on unknown length. * Improved documentation. * Lint * Moved new functions to protected.
1 parent 26b8485 commit a87c74a

File tree

2 files changed

+174
-31
lines changed

2 files changed

+174
-31
lines changed

Pcap++/header/PcapLiveDevice.h

Lines changed: 58 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -672,8 +672,65 @@ namespace pcpp
672672

673673
internal::PcapHandle doOpen(const DeviceConfiguration& config);
674674

675+
/// @brief Checks whether the packetPayloadLength is smaller or equal than the device MTU.
676+
/// @param[in] payloadLength The length of the IP layer of the packet
677+
/// @return True if the payloadLength is less than or equal to the device MTU
678+
bool isPayloadWithinMtu(size_t payloadLength) const;
679+
680+
/// @brief Checks whether the packet's payload length is smaller or equal than the device MTU.
681+
///
682+
/// If the payload length cannot be determined, the function will return the value of allowUnknownLength.
683+
/// In such cases, if outPayloadLength is not nullptr, it will be set to the maximum value of size_t (i.e.,
684+
/// std::numeric_limits<size_t>::max()), indicating that the payload length could not be determined.
685+
///
686+
/// @param[in] packet The packet to check
687+
/// @param[in] allowUnknownLength Controls whether packets with unknown payload length are allowed.
688+
/// @param[out] outPayloadLength If not nullptr, the payload length of the packet will be written to this
689+
/// pointer.
690+
/// @return True if the packet's payload length is less than or equal to the device MTU.
691+
/// If the packet's length cannot be determined, it will return true if allowUnknownLength is true.
692+
bool isPayloadWithinMtu(Packet const& packet, bool allowUnknownLength = false,
693+
size_t* outPayloadLength = nullptr) const;
694+
695+
/// @brief Checks whether the payload length of a RawPacket is smaller or equal than the device MTU.
696+
///
697+
/// If the payload length cannot be determined, the function will return the value of allowUnknownLength.
698+
/// In such cases, if outPayloadLength is not nullptr, it will be set to the maximum value of size_t (i.e.,
699+
/// std::numeric_limits<size_t>::max()), indicating that the payload length could not be determined.
700+
///
701+
/// @param[in] rawPacket The RawPacket to check.
702+
/// @param[in] allowUnknownLength Controls whether packets with unknown payload length are allowed.
703+
/// @param[out] outPayloadLength If not nullptr, the payload length of the packet will be written to this
704+
/// pointer.
705+
/// @return True if the packet's payload length is less than or equal to the device MTU.
706+
/// If the packet's length cannot be determined, it will return true if allowUnknownLength is true.
707+
bool isPayloadWithinMtu(RawPacket const& rawPacket, bool allowUnknownLength = false,
708+
size_t* outPayloadLength = nullptr) const;
709+
710+
/// @brief Checks whether the payload length of a packet's raw data is smaller or equal than the device MTU.
711+
///
712+
/// If the payload length cannot be determined, the function will return the value of allowUnknownLength.
713+
/// In such cases, if outPayloadLength is not nullptr, it will be set to the maximum value of size_t (i.e.,
714+
/// std::numeric_limits<size_t>::max()), indicating that the payload length could not be determined.
715+
///
716+
/// @param[in] packetData A pointer to the raw data of the packet.
717+
/// @param[in] packetLen The length of the raw data in bytes.
718+
/// @param[in] linkType The link layer type of the packet. Default is pcpp::LINKTYPE_ETHERNET.
719+
/// @param[in] allowUnknownLength Controls whether packets with unknown payload length are allowed.
720+
/// @param[out] outPayloadLength If not nullptr, the payload length of the packet will be written to this
721+
/// pointer.
722+
/// @return True if the packet's payload length is less than or equal to the device MTU.
723+
/// If the packet's length cannot be determined, it will return true if allowUnknownLength is true.
724+
bool isPayloadWithinMtu(uint8_t const* packetData, size_t packetLen,
725+
LinkLayerType linkType = pcpp::LINKTYPE_ETHERNET, bool allowUnknownLength = false,
726+
size_t* outPayloadLength = nullptr) const;
727+
675728
// Sends a packet directly to the network.
676-
bool sendPacketDirect(uint8_t const* packetData, int packetDataLength);
729+
bool sendPacketUnchecked(uint8_t const* packetData, int packetDataLength);
730+
bool sendPacketUnchecked(RawPacket const& rawPacket)
731+
{
732+
return sendPacketUnchecked(rawPacket.getRawData(), rawPacket.getRawDataLen());
733+
}
677734

678735
private:
679736
bool isNflogDevice() const;

Pcap++/src/PcapLiveDevice.cpp

Lines changed: 116 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -916,7 +916,13 @@ namespace pcpp
916916

917917
bool PcapLiveDevice::doMtuCheck(int packetPayloadLength) const
918918
{
919-
if (packetPayloadLength > static_cast<int>(m_DeviceMtu))
919+
if (packetPayloadLength < 0)
920+
{
921+
PCPP_LOG_ERROR("Payload length [" << packetPayloadLength << "] is negative");
922+
return false;
923+
}
924+
925+
if (!isPayloadWithinMtu(packetPayloadLength))
920926
{
921927
PCPP_LOG_ERROR("Payload length [" << packetPayloadLength << "] is larger than device MTU [" << m_DeviceMtu
922928
<< "]");
@@ -925,64 +931,144 @@ namespace pcpp
925931
return true;
926932
}
927933

928-
bool PcapLiveDevice::sendPacket(Packet const& packet, bool checkMtu)
934+
bool PcapLiveDevice::isPayloadWithinMtu(size_t packetPayloadLength) const
929935
{
930-
RawPacket const* rawPacket = packet.getRawPacketReadOnly();
931-
932-
if (!checkMtu)
933-
{
934-
return sendPacket(*rawPacket, false);
935-
}
936+
return packetPayloadLength <= static_cast<size_t>(m_DeviceMtu);
937+
}
936938

937-
int packetPayloadLength = 0;
939+
bool PcapLiveDevice::isPayloadWithinMtu(Packet const& packet, bool allowUnknownLength,
940+
size_t* outPayloadLength) const
941+
{
942+
size_t packetPayloadLength = 0;
938943
switch (packet.getFirstLayer()->getOsiModelLayer())
939944
{
940-
case (pcpp::OsiModelDataLinkLayer):
941-
packetPayloadLength = static_cast<int>(packet.getFirstLayer()->getLayerPayloadSize());
945+
case pcpp::OsiModelDataLinkLayer:
946+
packetPayloadLength = packet.getFirstLayer()->getLayerPayloadSize();
942947
break;
943-
case (pcpp::OsiModelNetworkLayer):
944-
packetPayloadLength = static_cast<int>(packet.getFirstLayer()->getDataLen());
948+
case pcpp::OsiModelNetworkLayer:
949+
packetPayloadLength = packet.getFirstLayer()->getDataLen();
945950
break;
946951
default:
947-
// if packet layer is not known, do not perform MTU check.
948-
return sendPacket(*rawPacket, false);
952+
{
953+
// If the packet length is unknown, the MTU check is skipped.
954+
// In such cases the output payload length is set to the maximum size and the return value is the
955+
// allowUnknownLength value.
956+
if (outPayloadLength != nullptr)
957+
{
958+
*outPayloadLength = (std::numeric_limits<size_t>::max)();
959+
}
960+
return allowUnknownLength;
961+
}
962+
}
963+
964+
if (outPayloadLength != nullptr)
965+
{
966+
*outPayloadLength = packetPayloadLength;
967+
}
968+
return isPayloadWithinMtu(packetPayloadLength);
969+
}
970+
971+
bool PcapLiveDevice::isPayloadWithinMtu(RawPacket const& rawPacket, bool allowUnknownLength,
972+
size_t* outPayloadLength) const
973+
{
974+
// Const cast because Packet requires a non-const RawPacket pointer
975+
// and we don't modify the RawPacket in this function.
976+
return isPayloadWithinMtu(Packet(const_cast<RawPacket*>(&rawPacket), OsiModelDataLinkLayer), allowUnknownLength,
977+
outPayloadLength);
978+
}
979+
980+
bool PcapLiveDevice::isPayloadWithinMtu(uint8_t const* packetData, size_t packetLen, LinkLayerType linkType,
981+
bool allowUnknown, size_t* outPayloadLength) const
982+
{
983+
timeval time;
984+
gettimeofday(&time, nullptr);
985+
return isPayloadWithinMtu(RawPacket(packetData, packetLen, time, false, linkType), allowUnknown,
986+
outPayloadLength);
987+
}
988+
989+
bool PcapLiveDevice::sendPacket(Packet const& packet, bool checkMtu)
990+
{
991+
if (checkMtu)
992+
{
993+
size_t packetPayloadLength = 0;
994+
// Unknown length is allowed due to legacy behavior of this function
995+
if (!isPayloadWithinMtu(packet, true, &packetPayloadLength))
996+
{
997+
PCPP_LOG_ERROR("Packet payload length [" << packetPayloadLength << "] is larger than device MTU ["
998+
<< m_DeviceMtu << "]");
999+
return false;
1000+
}
9491001
}
950-
return doMtuCheck(packetPayloadLength) && sendPacket(*rawPacket, false);
1002+
1003+
return sendPacketUnchecked(*packet.getRawPacketReadOnly());
9511004
}
9521005

9531006
bool PcapLiveDevice::sendPacket(RawPacket const& rawPacket, bool checkMtu)
9541007
{
955-
if (!checkMtu)
1008+
if (checkMtu)
9561009
{
957-
return sendPacketDirect(rawPacket.getRawData(), rawPacket.getRawDataLen());
1010+
size_t packetPayloadLength = 0;
1011+
// Unknown length is allowed due to legacy behavior of this function
1012+
if (!isPayloadWithinMtu(rawPacket, true, &packetPayloadLength))
1013+
{
1014+
PCPP_LOG_ERROR("Packet payload length [" << packetPayloadLength << "] is larger than device MTU ["
1015+
<< m_DeviceMtu << "]");
1016+
return false;
1017+
}
9581018
}
9591019

960-
RawPacket* rPacket = const_cast<RawPacket*>(&rawPacket);
961-
Packet parsedPacket = Packet(rPacket, OsiModelDataLinkLayer);
962-
return sendPacket(parsedPacket, true);
1020+
return sendPacketUnchecked(rawPacket);
9631021
}
9641022

9651023
bool PcapLiveDevice::sendPacket(const uint8_t* packetData, int packetDataLength, int packetPayloadLength)
9661024
{
967-
return doMtuCheck(packetPayloadLength) && sendPacketDirect(packetData, packetDataLength);
1025+
if (packetDataLength < 0)
1026+
{
1027+
PCPP_LOG_ERROR("Packet data length is negative: " << packetDataLength);
1028+
return false;
1029+
}
1030+
1031+
if (packetPayloadLength < 0)
1032+
{
1033+
PCPP_LOG_ERROR("Payload length is negative: " << packetPayloadLength);
1034+
return false;
1035+
}
1036+
1037+
if (!isPayloadWithinMtu(packetPayloadLength))
1038+
{
1039+
PCPP_LOG_ERROR("Packet payload length [" << packetPayloadLength << "] is larger than device MTU ["
1040+
<< m_DeviceMtu << "]");
1041+
return false;
1042+
}
1043+
1044+
return sendPacketUnchecked(packetData, packetDataLength);
9681045
}
9691046

9701047
bool PcapLiveDevice::sendPacket(const uint8_t* packetData, int packetDataLength, bool checkMtu,
9711048
pcpp::LinkLayerType linkType)
9721049
{
973-
if (!checkMtu)
1050+
if (packetDataLength < 0)
1051+
{
1052+
PCPP_LOG_ERROR("Packet data length is negative: " << packetDataLength);
1053+
return false;
1054+
}
1055+
1056+
if (checkMtu)
9741057
{
975-
return sendPacketDirect(packetData, packetDataLength);
1058+
size_t packetPayloadLength = 0;
1059+
// Unknown length is allowed due to legacy behavior of this function
1060+
if (!isPayloadWithinMtu(packetData, packetDataLength, linkType, true, &packetPayloadLength))
1061+
{
1062+
PCPP_LOG_ERROR("Packet payload length [" << packetPayloadLength << "] is larger than device MTU ["
1063+
<< m_DeviceMtu << "]");
1064+
return false;
1065+
}
9761066
}
9771067

978-
timeval time;
979-
gettimeofday(&time, nullptr);
980-
pcpp::RawPacket rawPacket(packetData, packetDataLength, time, false, linkType);
981-
Packet parsedPacket = Packet(&rawPacket, pcpp::OsiModelDataLinkLayer);
982-
return sendPacket(parsedPacket, true);
1068+
return sendPacketUnchecked(packetData, packetDataLength);
9831069
}
9841070

985-
bool PcapLiveDevice::sendPacketDirect(uint8_t const* packetData, int packetDataLength)
1071+
bool PcapLiveDevice::sendPacketUnchecked(uint8_t const* packetData, int packetDataLength)
9861072
{
9871073
if (!m_DeviceOpened)
9881074
{

0 commit comments

Comments
 (0)