#define LOG_MODULE PacketLogModuleSll2Layer
#include "Sll2Layer.h"
#include "Logger.h"
#include "IPv4Layer.h"
#include "IPv6Layer.h"
#include "PayloadLayer.h"
#include "ArpLayer.h"
#include "VlanLayer.h"
#include "PPPoELayer.h"
#include "MplsLayer.h"
#include <string.h>
#include "EndianPortable.h"
namespace pcpp
{
Sll2Layer::Sll2Layer(uint32_t interfaceIndex, uint16_t ARPHRDType, uint8_t packetType)
{
const size_t headerLen = sizeof(sll2_header);
m_DataLen = headerLen;
m_Data = new uint8_t[headerLen];
memset(m_Data, 0, headerLen);
setPacketType(packetType);
setArphrdType(ARPHRDType);
setInterfaceIndex(interfaceIndex);
m_Protocol = SLL2;
}
bool Sll2Layer::setLinkLayerAddr(const uint8_t* addr, size_t addrLength)
{
if (addr == nullptr || addrLength == 0 || addrLength > 8)
{
PCPP_LOG_ERROR("Address length is out of bounds, it must be between 1 and 8");
return false;
}
getSll2Header()->link_layer_addr_len = addrLength;
memcpy(getSll2Header()->link_layer_addr, addr, addrLength);
return true;
}
MacAddress Sll2Layer::getLinkLayerAsMacAddress() {
const uint8_t* data = getLinkLayerAddr();
uint8_t dataLen = getLinkLayerAddrLen();
if (data == nullptr || dataLen == 0 || dataLen > 8) {
return MacAddress::Zero;
}
return MacAddress(data);
}
bool Sll2Layer::setMacAddressAsLinkLayer(const MacAddress& macAddr)
{
if (!macAddr.isValid())
{
PCPP_LOG_ERROR("MAC address is not valid");
return false;
}
uint8_t macAddrAsArr[6];
macAddr.copyTo(macAddrAsArr);
return setLinkLayerAddr(macAddrAsArr, 6);
}
void Sll2Layer::parseNextLayer()
{
if (m_DataLen <= sizeof(sll2_header))
return;
uint8_t* payload = m_Data + sizeof(sll2_header);
size_t payloadLen = m_DataLen - sizeof(sll2_header);
sll2_header* hdr = getSll2Header();
switch (be16toh(hdr->protocol_type))
{
case PCPP_ETHERTYPE_IP:
m_NextLayer = IPv4Layer::isDataValid(payload, payloadLen)
? static_cast<Layer*>(new IPv4Layer(payload, payloadLen, this, m_Packet))
: static_cast<Layer*>(new PayloadLayer(payload, payloadLen, this, m_Packet));
break;
case PCPP_ETHERTYPE_IPV6:
m_NextLayer = IPv6Layer::isDataValid(payload, payloadLen)
? static_cast<Layer*>(new IPv6Layer(payload, payloadLen, this, m_Packet))
: static_cast<Layer*>(new PayloadLayer(payload, payloadLen, this, m_Packet));
break;
case PCPP_ETHERTYPE_ARP:
m_NextLayer = new ArpLayer(payload, payloadLen, this, m_Packet);
break;
case PCPP_ETHERTYPE_VLAN:
case PCPP_ETHERTYPE_IEEE_802_1AD:
m_NextLayer = new VlanLayer(payload, payloadLen, this, m_Packet);
break;
case PCPP_ETHERTYPE_PPPOES:
m_NextLayer = PPPoESessionLayer::isDataValid(payload, payloadLen)
? static_cast<Layer*>(new PPPoESessionLayer(payload, payloadLen, this, m_Packet))
: static_cast<Layer*>(new PayloadLayer(payload, payloadLen, this, m_Packet));
break;
case PCPP_ETHERTYPE_PPPOED:
m_NextLayer = PPPoEDiscoveryLayer::isDataValid(payload, payloadLen)
? static_cast<Layer*>(new PPPoEDiscoveryLayer(payload, payloadLen, this, m_Packet))
: static_cast<Layer*>(new PayloadLayer(payload, payloadLen, this, m_Packet));
break;
case PCPP_ETHERTYPE_MPLS:
m_NextLayer = new MplsLayer(payload, payloadLen, this, m_Packet);
break;
default:
m_NextLayer = new PayloadLayer(payload, payloadLen, this, m_Packet);
}
}
void Sll2Layer::computeCalculateFields()
{
if (m_NextLayer == nullptr)
return;
sll2_header* hdr = getSll2Header();
switch (m_NextLayer->getProtocol())
{
case IPv4:
hdr->protocol_type = htobe16(PCPP_ETHERTYPE_IP);
break;
case IPv6:
hdr->protocol_type = htobe16(PCPP_ETHERTYPE_IPV6);
break;
case ARP:
hdr->protocol_type = htobe16(PCPP_ETHERTYPE_ARP);
break;
case VLAN:
hdr->protocol_type = htobe16(PCPP_ETHERTYPE_VLAN);
break;
default:
return;
}
}
bool Sll2Layer::isDataValid(const uint8_t* data, size_t dataLen)
{
return data && dataLen >= sizeof(sll2_header);
}
std::string Sll2Layer::toString() const
{
return "Linux cooked header v2";
}
uint16_t Sll2Layer::getProtocolType() const
{
return be16toh(getSll2Header()->protocol_type);
}
void Sll2Layer::setProtocolType(uint16_t protocolType)
{
getSll2Header()->protocol_type = htobe16(protocolType);
}
uint32_t Sll2Layer::getInterfaceIndex() const
{
return be32toh(getSll2Header()->interface_index);
}
void Sll2Layer::setInterfaceIndex(uint32_t interfaceIndex)
{
getSll2Header()->interface_index = htobe32(interfaceIndex);
}
uint16_t Sll2Layer::getArphrdType() const
{
return be16toh(getSll2Header()->ARPHRD_type);
}
void Sll2Layer::setArphrdType(uint16_t arphrdType)
{
getSll2Header()->ARPHRD_type = htobe16(arphrdType);
}
uint8_t Sll2Layer::getPacketType() const
{
return getSll2Header()->packet_type;
}
void Sll2Layer::setPacketType(uint8_t packetType)
{
getSll2Header()->packet_type = packetType;
}
uint8_t Sll2Layer::getLinkLayerAddrLen() const
{
return getSll2Header()->link_layer_addr_len;
}
const uint8_t *Sll2Layer::getLinkLayerAddr() const
{
return getSll2Header()->link_layer_addr;
}
}