1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152
|
/*
SPDX-FileCopyrightText: 2019 Arjen Hiemstra <ahiemstra@heimr.nl>
SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
*/
#include "Packet.h"
#include <arpa/inet.h>
#include <net/ethernet.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/ip6.h>
#include <netinet/tcp.h>
#include <netinet/udp.h>
#include <sys/types.h>
#include <pcap/pcap.h>
#include <pcap/sll.h>
uint32_t u8Tou32(uint8_t first, uint8_t second, uint8_t third, uint8_t fourth)
{
return uint32_t(first) << 24 | uint32_t(second) << 16 | uint32_t(third) << 8 | uint32_t(fourth);
}
Packet::Packet()
{
}
Packet::Packet(const TimeStamp::MicroSeconds &timeStamp, const uint8_t *data, uint32_t dataLength, uint32_t packetSize)
: m_timeStamp(timeStamp)
{
m_size = packetSize;
const sll_header *header = reinterpret_cast<const sll_header *>(data);
switch (ntohs(header->sll_protocol)) {
case ETHERTYPE_IP:
m_networkProtocol = NetworkProtocolType::IPv4;
if (sizeof(sll_header) <= dataLength) {
parseIPv4(data + sizeof(sll_header), dataLength - sizeof(sll_header));
}
break;
case ETHERTYPE_IPV6:
m_networkProtocol = NetworkProtocolType::IPv6;
if (sizeof(sll_header) <= dataLength) {
parseIPv6(data + sizeof(sll_header), dataLength - sizeof(sll_header));
}
break;
default:
m_networkProtocol = NetworkProtocolType::Unknown;
break;
}
}
Packet::~Packet()
{
}
unsigned int Packet::size() const
{
return m_size;
}
TimeStamp::MicroSeconds Packet::timeStamp() const
{
return m_timeStamp;
}
Packet::NetworkProtocolType Packet::networkProtocol() const
{
return m_networkProtocol;
}
Packet::TransportProtocolType Packet::transportProtocol() const
{
return m_transportProtocol;
}
Packet::Address Packet::sourceAddress() const
{
return m_sourceAddress;
}
Packet::Address Packet::destinationAddress() const
{
return m_destinationAddress;
}
void Packet::parseIPv4(const uint8_t *data, int32_t dataLength)
{
if (dataLength < int32_t(sizeof(ip))) {
return;
}
const ip *header = reinterpret_cast<const ip *>(data);
m_sourceAddress.address[3] = ntohl(header->ip_src.s_addr);
m_destinationAddress.address[3] = ntohl(header->ip_dst.s_addr);
parseTransport(header->ip_p, data + sizeof(ip), dataLength - sizeof(ip));
}
void Packet::parseIPv6(const uint8_t *data, int32_t dataLength)
{
if (dataLength < int32_t(sizeof(ip6_hdr))) {
return;
}
const ip6_hdr *header = reinterpret_cast<const ip6_hdr *>(data);
m_sourceAddress.address = {
u8Tou32(header->ip6_src.s6_addr[0], header->ip6_src.s6_addr[1], header->ip6_src.s6_addr[2], header->ip6_src.s6_addr[3]),
u8Tou32(header->ip6_src.s6_addr[4], header->ip6_src.s6_addr[5], header->ip6_src.s6_addr[6], header->ip6_src.s6_addr[7]),
u8Tou32(header->ip6_src.s6_addr[8], header->ip6_src.s6_addr[9], header->ip6_src.s6_addr[10], header->ip6_src.s6_addr[11]),
u8Tou32(header->ip6_src.s6_addr[12], header->ip6_src.s6_addr[13], header->ip6_src.s6_addr[14], header->ip6_src.s6_addr[15]),
};
m_destinationAddress.address = {
u8Tou32(header->ip6_dst.s6_addr[0], header->ip6_dst.s6_addr[1], header->ip6_dst.s6_addr[2], header->ip6_dst.s6_addr[3]),
u8Tou32(header->ip6_dst.s6_addr[4], header->ip6_dst.s6_addr[5], header->ip6_dst.s6_addr[6], header->ip6_dst.s6_addr[7]),
u8Tou32(header->ip6_dst.s6_addr[8], header->ip6_dst.s6_addr[9], header->ip6_dst.s6_addr[10], header->ip6_dst.s6_addr[11]),
u8Tou32(header->ip6_dst.s6_addr[12], header->ip6_dst.s6_addr[13], header->ip6_dst.s6_addr[14], header->ip6_dst.s6_addr[15]),
};
parseTransport(header->ip6_nxt, data + sizeof(ip6_hdr), dataLength - sizeof(ip6_hdr));
}
void Packet::parseTransport(uint8_t type, const uint8_t *data, int32_t dataLength)
{
switch (type) {
case IPPROTO_TCP: {
m_transportProtocol = TransportProtocolType::Tcp;
if (dataLength >= int32_t(sizeof(tcphdr))) {
const tcphdr *tcpHeader = reinterpret_cast<const tcphdr *>(data);
m_sourceAddress.port = ntohs(tcpHeader->th_sport);
m_destinationAddress.port = ntohs(tcpHeader->th_dport);
}
break;
}
case IPPROTO_UDP: {
m_transportProtocol = TransportProtocolType::Udp;
if (dataLength >= int32_t(sizeof(udphdr))) {
const udphdr *udpHeader = reinterpret_cast<const udphdr *>(data);
m_sourceAddress.port = ntohs(udpHeader->uh_sport);
m_destinationAddress.port = ntohs(udpHeader->uh_dport);
}
break;
}
default:
m_transportProtocol = TransportProtocolType::Unknown;
break;
}
}
|