internet: (fixes #1109) Add support for multiple hardware types in ArpHeader

This commit is contained in:
AlessioBugetti
2024-08-14 17:32:32 +02:00
committed by Eduardo Almeida
parent fd93b6ff7d
commit e08ae6eaa9
2 changed files with 118 additions and 29 deletions

View File

@@ -27,6 +27,7 @@ ArpHeader::SetRequest(Address sourceHardwareAddress,
{
NS_LOG_FUNCTION(this << sourceHardwareAddress << sourceProtocolAddress
<< destinationHardwareAddress << destinationProtocolAddress);
m_hardwareType = DetermineHardwareType(sourceHardwareAddress);
m_type = ARP_TYPE_REQUEST;
m_macSource = sourceHardwareAddress;
m_macDest = destinationHardwareAddress;
@@ -42,6 +43,7 @@ ArpHeader::SetReply(Address sourceHardwareAddress,
{
NS_LOG_FUNCTION(this << sourceHardwareAddress << sourceProtocolAddress
<< destinationHardwareAddress << destinationProtocolAddress);
m_hardwareType = DetermineHardwareType(sourceHardwareAddress);
m_type = ARP_TYPE_REPLY;
m_macSource = sourceHardwareAddress;
m_macDest = destinationHardwareAddress;
@@ -49,6 +51,22 @@ ArpHeader::SetReply(Address sourceHardwareAddress,
m_ipv4Dest = destinationProtocolAddress;
}
ArpHeader::HardwareType
ArpHeader::DetermineHardwareType(const Address& address) const
{
NS_LOG_FUNCTION(this << address);
uint8_t addressLength = address.GetLength();
switch (addressLength)
{
case 6:
return HardwareType::ETHERNET;
case 8:
return HardwareType::EUI_64;
default:
return HardwareType::UNKNOWN;
}
}
bool
ArpHeader::IsRequest() const
{
@@ -63,6 +81,13 @@ ArpHeader::IsReply() const
return m_type == ARP_TYPE_REPLY;
}
ArpHeader::HardwareType
ArpHeader::GetHardwareType() const
{
NS_LOG_FUNCTION(this);
return m_hardwareType;
}
Address
ArpHeader::GetSourceHardwareAddress() const
{
@@ -114,7 +139,8 @@ ArpHeader::Print(std::ostream& os) const
NS_LOG_FUNCTION(this << &os);
if (IsRequest())
{
os << "request "
os << "hardware type: " << GetHardwareType() << " "
<< "request "
<< "source mac: " << m_macSource << " "
<< "source ipv4: " << m_ipv4Source << " "
<< "dest ipv4: " << m_ipv4Dest;
@@ -122,7 +148,8 @@ ArpHeader::Print(std::ostream& os) const
else
{
NS_ASSERT(IsReply());
os << "reply "
os << "hardware type: " << GetHardwareType() << " "
<< "reply "
<< "source mac: " << m_macSource << " "
<< "source ipv4: " << m_ipv4Source << " "
<< "dest mac: " << m_macDest << " "
@@ -151,8 +178,7 @@ ArpHeader::Serialize(Buffer::Iterator start) const
Buffer::Iterator i = start;
NS_ASSERT(m_macSource.GetLength() == m_macDest.GetLength());
/* ethernet */
i.WriteHtonU16(0x0001);
i.WriteHtonU16(static_cast<uint16_t>(m_hardwareType));
/* ipv4 */
i.WriteHtonU16(0x0800);
i.WriteU8(m_macSource.GetLength());
@@ -169,10 +195,10 @@ ArpHeader::Deserialize(Buffer::Iterator start)
{
NS_LOG_FUNCTION(this << &start);
Buffer::Iterator i = start;
i.Next(2); // Skip HRD
uint32_t protocolType = i.ReadNtohU16(); // Read PRO
uint32_t hardwareAddressLen = i.ReadU8(); // Read HLN
uint32_t protocolAddressLen = i.ReadU8(); // Read PLN
m_hardwareType = static_cast<HardwareType>(i.ReadNtohU16()); // Read HTYPE
uint32_t protocolType = i.ReadNtohU16(); // Read PRO
uint32_t hardwareAddressLen = i.ReadU8(); // Read HLN
uint32_t protocolAddressLen = i.ReadU8(); // Read PLN
//
// It is implicit here that we have a protocol type of 0x800 (IP).
@@ -185,12 +211,27 @@ ArpHeader::Deserialize(Buffer::Iterator start)
return 0;
}
m_type = i.ReadNtohU16(); // Read OP
ReadFrom(i, m_macSource, hardwareAddressLen); // Read SHA (size HLN)
ReadFrom(i, m_ipv4Source); // Read SPA (size PLN == 4)
ReadFrom(i, m_macDest, hardwareAddressLen); // Read THA (size HLN)
ReadFrom(i, m_ipv4Dest); // Read TPA (size PLN == 4)
m_type = static_cast<ArpType_e>(i.ReadNtohU16()); // Read OP
ReadFrom(i, m_macSource, hardwareAddressLen); // Read SHA (size HLN)
ReadFrom(i, m_ipv4Source); // Read SPA (size PLN == 4)
ReadFrom(i, m_macDest, hardwareAddressLen); // Read THA (size HLN)
ReadFrom(i, m_ipv4Dest); // Read TPA (size PLN == 4)
return GetSerializedSize();
}
std::ostream&
operator<<(std::ostream& os, ArpHeader::HardwareType hardwareType)
{
switch (hardwareType)
{
case ArpHeader::HardwareType::ETHERNET:
return (os << "Ethernet");
case ArpHeader::HardwareType::EUI_64:
return (os << "EUI-64");
case ArpHeader::HardwareType::UNKNOWN:
return (os << "Unknown Hardware Type");
}
return os << "Unrecognized Hardware Type(" << static_cast<uint16_t>(hardwareType) << ")";
}
} // namespace ns3

View File

@@ -13,8 +13,6 @@
#include "ns3/header.h"
#include "ns3/ipv4-address.h"
#include <string>
namespace ns3
{
/**
@@ -24,6 +22,33 @@ namespace ns3
class ArpHeader : public Header
{
public:
/**
* \brief Enumeration listing the possible ARP types
*
* These ARP types are part of the standard ARP packet format as defined in Section
* "Definitions" of \RFC{826}.
*/
enum ArpType_e : uint16_t
{
ARP_TYPE_REQUEST = 1,
ARP_TYPE_REPLY = 2
};
/**
* \brief Enumeration listing the supported hardware types
*
* \RFC{826} specifies that the Hardware Type field in the ARP packet indicates the type
of hardware used.
* For the full list of Hardware Types, refer to:
* https://www.iana.org/assignments/arp-parameters/arp-parameters.xhtml
*/
enum class HardwareType : uint16_t
{
UNKNOWN = 0,
ETHERNET = 1,
EUI_64 = 27,
};
/**
* \brief Set the ARP request parameters
* \param sourceHardwareAddress the source hardware address
@@ -49,6 +74,22 @@ class ArpHeader : public Header
Address destinationHardwareAddress,
Ipv4Address destinationProtocolAddress);
/**
* @brief Determines the hardware type based on the length of the address.
*
* This method determines the hardware type based on the length of the address.
* It supports two common hardware address lengths:
* - 6 bytes: Assumed to be Ethernet.
* - 8 bytes: Assumed to be EUI-64.
*
* If the length of the address does not match these common lengths, the method defaults
* to Unknown hardware type.
*
* @param address The address whose length is used to determine the hardware type.
* @return The corresponding hardware type.
*/
HardwareType DetermineHardwareType(const Address& address) const;
/**
* \brief Check if the ARP is a request
* \returns true if it is a request
@@ -61,6 +102,12 @@ class ArpHeader : public Header
*/
bool IsReply() const;
/**
* \brief Get the hardware type
* \return the hardware type
*/
HardwareType GetHardwareType() const;
/**
* \brief Returns the source hardware address
* \returns the source hardware address
@@ -96,22 +143,23 @@ class ArpHeader : public Header
void Serialize(Buffer::Iterator start) const override;
uint32_t Deserialize(Buffer::Iterator start) override;
/**
* \brief Enumeration listing the possible ARP types
*/
enum ArpType_e
{
ARP_TYPE_REQUEST = 1,
ARP_TYPE_REPLY = 2
};
uint16_t m_type; //!< type of the ICMP (ARP_TYPE_REQUEST)
Address m_macSource; //!< hardware source address
Address m_macDest; //!< hardware destination address
Ipv4Address m_ipv4Source; //!< IP source address
Ipv4Address m_ipv4Dest; //!< IP destination address
HardwareType m_hardwareType; //!< hardware type
ArpType_e m_type; //!< type of the ICMP packet
Address m_macSource; //!< hardware source address
Address m_macDest; //!< hardware destination address
Ipv4Address m_ipv4Source; //!< IP source address
Ipv4Address m_ipv4Dest; //!< IP destination address
};
/**
* \brief Stream insertion operator.
*
* \param os The reference to the output stream
* \param hardwareType the hardware type
* \return The reference to the output stream.
*/
std::ostream& operator<<(std::ostream& os, ArpHeader::HardwareType hardwareType);
} // namespace ns3
#endif /* ARP_HEADER_H */