mirror of
https://github.com/esp8266/Arduino.git
synced 2025-04-21 10:26:06 +03:00
314 lines
8.1 KiB
C++
314 lines
8.1 KiB
C++
/*
|
|
NetDump library - tcpdump-like packet logger facility
|
|
|
|
Copyright (c) 2019 Herman Reintke. All rights reserved.
|
|
This file is part of the esp8266 core for Arduino environment.
|
|
|
|
This library is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU Lesser General Public
|
|
License as published by the Free Software Foundation; either
|
|
version 2.1 of the License, or (at your option) any later version.
|
|
|
|
This library is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Lesser General Public License for more details.
|
|
|
|
You should have received a copy of the GNU Lesser General Public
|
|
License along with this library; if not, write to the Free Software
|
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
*/
|
|
|
|
#ifndef __NETDUMP_PACKET_H
|
|
#define __NETDUMP_PACKET_H
|
|
|
|
#include <lwipopts.h>
|
|
#include <IPAddress.h>
|
|
#include <StreamString.h>
|
|
#include "NetdumpIP.h"
|
|
#include "PacketType.h"
|
|
#include <vector>
|
|
|
|
namespace NetCapture
|
|
{
|
|
|
|
int constexpr ETH_HDR_LEN = 14;
|
|
|
|
class Packet
|
|
{
|
|
public:
|
|
Packet(unsigned long msec, int n, const char* d, size_t l, int o, int s) :
|
|
packetTime(msec), netif_idx(n), data(d), packetLength(l), out(o), success(s)
|
|
{
|
|
setPacketTypes();
|
|
};
|
|
|
|
enum class PacketDetail
|
|
{
|
|
NONE,
|
|
FULL,
|
|
CHAR,
|
|
RAW
|
|
};
|
|
|
|
const char* rawData() const
|
|
{
|
|
return data;
|
|
}
|
|
int getInOut() const
|
|
{
|
|
return out;
|
|
}
|
|
time_t getTime() const
|
|
{
|
|
return packetTime;
|
|
}
|
|
uint32_t getPacketSize() const
|
|
{
|
|
return packetLength;
|
|
}
|
|
uint16_t ntoh16(uint16_t idx) const
|
|
{
|
|
return data[idx + 1] | (((uint16_t)data[idx]) << 8);
|
|
};
|
|
uint32_t ntoh32(uint16_t idx) const
|
|
{
|
|
return ntoh16(idx + 2) | (((uint32_t)ntoh16(idx)) << 16);
|
|
};
|
|
uint8_t byteData(uint16_t idx) const
|
|
{
|
|
return data[idx];
|
|
}
|
|
const char* byteIdx(uint16_t idx) const
|
|
{
|
|
return &data[idx];
|
|
};
|
|
uint16_t ethType() const
|
|
{
|
|
return ntoh16(12);
|
|
};
|
|
uint8_t ipType() const
|
|
{
|
|
return isIP() ? isIPv4() ? data[ETH_HDR_LEN + 9] : data[ETH_HDR_LEN + 6] : 0;
|
|
};
|
|
uint16_t getIpHdrLen() const
|
|
{
|
|
return isIPv4() ? (((unsigned char)data[ETH_HDR_LEN]) & 0x0f) << 2
|
|
: 40; // IPv6 is fixed length
|
|
}
|
|
uint16_t getIpTotalLen() const
|
|
{
|
|
return isIP() ? isIPv4() ? ntoh16(ETH_HDR_LEN + 2) : (packetLength - ETH_HDR_LEN) : 0;
|
|
}
|
|
uint32_t getTcpSeq() const
|
|
{
|
|
return isTCP() ? ntoh32(ETH_HDR_LEN + getIpHdrLen() + 4) : 0;
|
|
}
|
|
uint32_t getTcpAck() const
|
|
{
|
|
return isTCP() ? ntoh32(ETH_HDR_LEN + getIpHdrLen() + 8) : 0;
|
|
}
|
|
uint16_t getTcpFlags() const
|
|
{
|
|
return isTCP() ? ntoh16(ETH_HDR_LEN + getIpHdrLen() + 12) : 0;
|
|
}
|
|
uint16_t getTcpWindow() const
|
|
{
|
|
return isTCP() ? ntoh16(ETH_HDR_LEN + getIpHdrLen() + 14) : 0;
|
|
}
|
|
uint8_t getTcpHdrLen() const
|
|
{
|
|
return isTCP() ? (data[ETH_HDR_LEN + getIpHdrLen() + 12] >> 4) * 4 : 0;
|
|
}; // Header len is in multiple of 4 bytes
|
|
uint16_t getTcpLen() const
|
|
{
|
|
return isTCP() ? getIpTotalLen() - getIpHdrLen() - getTcpHdrLen() : 0;
|
|
};
|
|
|
|
uint8_t getIcmpType() const
|
|
{
|
|
return isICMP() ? data[ETH_HDR_LEN + getIpHdrLen() + 0] : 0;
|
|
}
|
|
uint8_t getIgmpType() const
|
|
{
|
|
return isIGMP() ? data[ETH_HDR_LEN + getIpHdrLen() + 0] : 0;
|
|
}
|
|
uint8_t getARPType() const
|
|
{
|
|
return isARP() ? data[ETH_HDR_LEN + 7] : 0;
|
|
}
|
|
bool is_ARP_who() const
|
|
{
|
|
return (getARPType() == 1);
|
|
}
|
|
bool is_ARP_is() const
|
|
{
|
|
return (getARPType() == 2);
|
|
}
|
|
|
|
uint8_t getUdpHdrLen() const
|
|
{
|
|
return isUDP() ? 8 : 0;
|
|
};
|
|
uint16_t getUdpLen() const
|
|
{
|
|
return isUDP() ? ntoh16(ETH_HDR_LEN + getIpHdrLen() + 4) : 0;
|
|
};
|
|
bool isARP() const
|
|
{
|
|
return (ethType() == 0x0806);
|
|
};
|
|
bool isIPv4() const
|
|
{
|
|
return (ethType() == 0x0800);
|
|
};
|
|
bool isIPv6() const
|
|
{
|
|
return (ethType() == 0x86dd);
|
|
};
|
|
bool isIP() const
|
|
{
|
|
return (isIPv4() || isIPv6());
|
|
};
|
|
bool isICMP() const
|
|
{
|
|
return (isIP() && ((ipType() == 1) || (ipType() == 58)));
|
|
};
|
|
bool isIGMP() const
|
|
{
|
|
return (isIP() && (ipType() == 2));
|
|
};
|
|
bool isTCP() const
|
|
{
|
|
return (isIP() && (ipType() == 6));
|
|
};
|
|
bool isUDP() const
|
|
{
|
|
return (isIP() && ipType() == 17);
|
|
};
|
|
bool isMDNS() const
|
|
{
|
|
return (isUDP() && hasPort(5353));
|
|
};
|
|
bool isDNS() const
|
|
{
|
|
return (isUDP() && hasPort(53));
|
|
};
|
|
bool isSSDP() const
|
|
{
|
|
return (isUDP() && hasPort(1900));
|
|
};
|
|
bool isDHCP() const
|
|
{
|
|
return (isUDP() && ((hasPort(546) || hasPort(547) || hasPort(67) || hasPort(68))));
|
|
};
|
|
bool isWSDD() const
|
|
{
|
|
return (isUDP() && hasPort(3702));
|
|
};
|
|
bool isHTTP() const
|
|
{
|
|
return (isTCP() && hasPort(80));
|
|
};
|
|
bool isOTA() const
|
|
{
|
|
return (isUDP() && hasPort(8266));
|
|
}
|
|
bool isNETBIOS() const
|
|
{
|
|
return (isUDP() && (hasPort(137) || hasPort(138) || hasPort(139)));
|
|
}
|
|
bool isSMB() const
|
|
{
|
|
return (isUDP() && hasPort(445));
|
|
}
|
|
NetdumpIP getIP(uint16_t idx) const
|
|
{
|
|
return NetdumpIP(data[idx], data[idx + 1], data[idx + 2], data[idx + 3]);
|
|
};
|
|
|
|
NetdumpIP getIP6(uint16_t idx) const
|
|
{
|
|
return NetdumpIP((const uint8_t*)&data[idx], false);
|
|
};
|
|
NetdumpIP sourceIP() const
|
|
{
|
|
NetdumpIP ip;
|
|
if (isIPv4())
|
|
{
|
|
ip = getIP(ETH_HDR_LEN + 12);
|
|
}
|
|
else if (isIPv6())
|
|
{
|
|
ip = getIP6(ETH_HDR_LEN + 8);
|
|
}
|
|
return ip;
|
|
};
|
|
|
|
bool hasIP(NetdumpIP ip) const
|
|
{
|
|
return (isIP() && ((ip == sourceIP()) || (ip == destIP())));
|
|
}
|
|
|
|
NetdumpIP destIP() const
|
|
{
|
|
NetdumpIP ip;
|
|
if (isIPv4())
|
|
{
|
|
ip = getIP(ETH_HDR_LEN + 16);
|
|
}
|
|
else if (isIPv6())
|
|
{
|
|
ip = getIP6(ETH_HDR_LEN + 24);
|
|
}
|
|
return ip;
|
|
};
|
|
uint16_t getSrcPort() const
|
|
{
|
|
return isIP() ? ntoh16(ETH_HDR_LEN + getIpHdrLen() + 0) : 0;
|
|
}
|
|
uint16_t getDstPort() const
|
|
{
|
|
return isIP() ? ntoh16(ETH_HDR_LEN + getIpHdrLen() + 2) : 0;
|
|
}
|
|
bool hasPort(uint16_t p) const
|
|
{
|
|
return (isIP() && ((getSrcPort() == p) || (getDstPort() == p)));
|
|
}
|
|
|
|
const String toString() const;
|
|
const String toString(PacketDetail netdumpDetail) const;
|
|
void printDetail(Print& out, const String& indent, const char* data, size_t size,
|
|
PacketDetail pd) const;
|
|
|
|
const PacketType packetType() const;
|
|
const std::vector<PacketType>& allPacketTypes() const;
|
|
|
|
private:
|
|
void setPacketType(PacketType);
|
|
void setPacketTypes();
|
|
|
|
void MACtoString(int dataIdx, StreamString& sstr) const;
|
|
void ARPtoString(PacketDetail netdumpDetail, StreamString& sstr) const;
|
|
void DNStoString(PacketDetail netdumpDetail, StreamString& sstr) const;
|
|
void UDPtoString(PacketDetail netdumpDetail, StreamString& sstr) const;
|
|
void TCPtoString(PacketDetail netdumpDetail, StreamString& sstr) const;
|
|
void ICMPtoString(PacketDetail netdumpDetail, StreamString& sstr) const;
|
|
void IGMPtoString(PacketDetail netdumpDetail, StreamString& sstr) const;
|
|
void IPtoString(PacketDetail netdumpDetail, StreamString& sstr) const;
|
|
void UKNWtoString(PacketDetail netdumpDetail, StreamString& sstr) const;
|
|
|
|
time_t packetTime;
|
|
int netif_idx;
|
|
const char* data;
|
|
size_t packetLength;
|
|
int out;
|
|
int success;
|
|
PacketType thisPacketType;
|
|
std::vector<PacketType> thisAllPacketTypes;
|
|
};
|
|
|
|
} // namespace NetCapture
|
|
|
|
#endif /* __NETDUMP_PACKET_H */
|