File indexing completed on 2024-06-23 05:27:54

0001 /*
0002     SPDX-FileCopyrightText: 2019 Arjen Hiemstra <ahiemstra@heimr.nl>
0003 
0004     SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
0005 */
0006 
0007 #include "Packet.h"
0008 
0009 #include <arpa/inet.h>
0010 #include <net/ethernet.h>
0011 #include <netinet/in.h>
0012 #include <netinet/ip.h>
0013 #include <netinet/ip6.h>
0014 #include <netinet/tcp.h>
0015 #include <netinet/udp.h>
0016 #include <sys/types.h>
0017 
0018 #include <pcap/pcap.h>
0019 #include <pcap/sll.h>
0020 
0021 uint32_t u8Tou32(uint8_t first, uint8_t second, uint8_t third, uint8_t fourth)
0022 {
0023     return uint32_t(first) << 24 | uint32_t(second) << 16 | uint32_t(third) << 8 | uint32_t(fourth);
0024 }
0025 
0026 Packet::Packet()
0027 {
0028 }
0029 
0030 Packet::Packet(const TimeStamp::MicroSeconds &timeStamp, const uint8_t *data, uint32_t dataLength, uint32_t packetSize)
0031     : m_timeStamp(timeStamp)
0032 {
0033     m_size = packetSize;
0034 
0035     const sll_header *header = reinterpret_cast<const sll_header *>(data);
0036     switch (ntohs(header->sll_protocol)) {
0037     case ETHERTYPE_IP:
0038         m_networkProtocol = NetworkProtocolType::IPv4;
0039         if (sizeof(sll_header) <= dataLength) {
0040             parseIPv4(data + sizeof(sll_header), dataLength - sizeof(sll_header));
0041         }
0042         break;
0043     case ETHERTYPE_IPV6:
0044         m_networkProtocol = NetworkProtocolType::IPv6;
0045         if (sizeof(sll_header) <= dataLength) {
0046             parseIPv6(data + sizeof(sll_header), dataLength - sizeof(sll_header));
0047         }
0048         break;
0049     default:
0050         m_networkProtocol = NetworkProtocolType::Unknown;
0051         break;
0052     }
0053 }
0054 
0055 Packet::~Packet()
0056 {
0057 }
0058 
0059 unsigned int Packet::size() const
0060 {
0061     return m_size;
0062 }
0063 
0064 TimeStamp::MicroSeconds Packet::timeStamp() const
0065 {
0066     return m_timeStamp;
0067 }
0068 
0069 Packet::NetworkProtocolType Packet::networkProtocol() const
0070 {
0071     return m_networkProtocol;
0072 }
0073 
0074 Packet::TransportProtocolType Packet::transportProtocol() const
0075 {
0076     return m_transportProtocol;
0077 }
0078 
0079 Packet::Address Packet::sourceAddress() const
0080 {
0081     return m_sourceAddress;
0082 }
0083 
0084 Packet::Address Packet::destinationAddress() const
0085 {
0086     return m_destinationAddress;
0087 }
0088 
0089 void Packet::parseIPv4(const uint8_t *data, int32_t dataLength)
0090 {
0091     if (dataLength < int32_t(sizeof(ip))) {
0092         return;
0093     }
0094 
0095     const ip *header = reinterpret_cast<const ip *>(data);
0096 
0097     m_sourceAddress.address[3] = header->ip_src.s_addr;
0098     m_destinationAddress.address[3] = header->ip_dst.s_addr;
0099 
0100     parseTransport(header->ip_p, data + sizeof(ip), dataLength - sizeof(ip));
0101 }
0102 
0103 void Packet::parseIPv6(const uint8_t *data, int32_t dataLength)
0104 {
0105     if (dataLength < int32_t(sizeof(ip6_hdr))) {
0106         return;
0107     }
0108 
0109     const ip6_hdr *header = reinterpret_cast<const ip6_hdr *>(data);
0110 
0111     m_sourceAddress.address = {
0112         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]),
0113         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]),
0114         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]),
0115         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]),
0116     };
0117     m_destinationAddress.address = {
0118         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]),
0119         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]),
0120         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]),
0121         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]),
0122     };
0123 
0124     parseTransport(header->ip6_nxt, data + sizeof(ip6_hdr), dataLength - sizeof(ip6_hdr));
0125 }
0126 
0127 void Packet::parseTransport(uint8_t type, const uint8_t *data, int32_t dataLength)
0128 {
0129     switch (type) {
0130     case IPPROTO_TCP: {
0131         m_transportProtocol = TransportProtocolType::Tcp;
0132         if (dataLength >= int32_t(sizeof(tcphdr))) {
0133             const tcphdr *tcpHeader = reinterpret_cast<const tcphdr *>(data);
0134             m_sourceAddress.port = ntohs(tcpHeader->th_sport);
0135             m_destinationAddress.port = ntohs(tcpHeader->th_dport);
0136         }
0137         break;
0138     }
0139     case IPPROTO_UDP: {
0140         m_transportProtocol = TransportProtocolType::Udp;
0141         if (dataLength >= int32_t(sizeof(udphdr))) {
0142             const udphdr *udpHeader = reinterpret_cast<const udphdr *>(data);
0143             m_sourceAddress.port = ntohs(udpHeader->uh_sport);
0144             m_destinationAddress.port = ntohs(udpHeader->uh_dport);
0145         }
0146         break;
0147     }
0148     default:
0149         m_transportProtocol = TransportProtocolType::Unknown;
0150         break;
0151     }
0152 }