mirror of
https://github.com/esp8266/Arduino.git
synced 2025-04-22 21:23:07 +03:00
Netump Initial commit (#7527)
This commit is contained in:
parent
b9db9440fe
commit
be812d2a8d
52
libraries/Netdump/README.md
Normal file
52
libraries/Netdump/README.md
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
|
||||||
|
esp8266/Arduino goodies
|
||||||
|
-----------------------
|
||||||
|
|
||||||
|
* NetDump (lwip2)
|
||||||
|
Packet sniffer library to help study network issues, check example-sketches
|
||||||
|
Log examples on serial console:
|
||||||
|
```
|
||||||
|
14:07:01.854 -> in 0 ARP who has 10.43.1.117 tell 10.43.1.254
|
||||||
|
14:07:01.854 -> out 0 ARP 10.43.1.117 is at 5c:cf:7f:c3:ad:51
|
||||||
|
|
||||||
|
[...] hello-world, dumped in packets:
|
||||||
|
14:07:46.227 -> in 0 IPv4 10.43.1.254>10.43.1.117 TCP 54546>2[P.] seq:1945448681..1945448699 ack:6618 win:29200 len=18
|
||||||
|
14:07:46.260 -> 5c cf 7f c3 ad 51 74 da 38 3a 1f 61 08 00 45 10 \..Qt.8:.a..E.
|
||||||
|
14:07:46.260 -> 00 3a b2 bc 40 00 40 06 70 29 0a 2b 01 fe 0a 2b .:..@.@.p).+...+
|
||||||
|
14:07:46.260 -> 01 75 d5 12 00 02 73 f5 30 e9 00 00 19 da 50 18 .u....s.0.....P.
|
||||||
|
14:07:46.260 -> 72 10 f8 da 00 00 70 6c 20 68 65 6c 6c 6f 2d 77 r.....pl hello-w
|
||||||
|
14:07:46.260 -> 6f 72 6c 64 20 31 0d 0a orld 1..
|
||||||
|
14:07:46.294 -> out 0 IPv4 10.43.1.117>10.43.1.254 TCP 2>54546[P.] seq:6618..6619 ack:1945448699 win:2126 len=1
|
||||||
|
14:07:46.326 -> 00 20 00 00 00 00 aa aa 03 00 00 00 08 00 45 00 . ............E.
|
||||||
|
14:07:46.326 -> 00 29 00 0d 00 00 ff 06 a3 f9 0a 2b 01 75 0a 2b .).........+.u.+
|
||||||
|
14:07:46.327 -> 01 fe 00 02 d5 12 00 00 19 da 73 f5 30 fb 50 18 ..........s.0.P.
|
||||||
|
14:07:46.327 -> 08 4e 93 d5 00 00 68 .N....h
|
||||||
|
14:07:46.327 -> in 0 IPv4 10.43.1.254>10.43.1.117 TCP 54546>2[.] seq:1945448699 ack:6619 win:29200
|
||||||
|
14:07:46.327 -> 5c cf 7f c3 ad 51 74 da 38 3a 1f 61 08 00 45 10 \..Qt.8:.a..E.
|
||||||
|
14:07:46.360 -> 00 28 b2 bd 40 00 40 06 70 3a 0a 2b 01 fe 0a 2b .(..@.@.p:.+...+
|
||||||
|
14:07:46.360 -> 01 75 d5 12 00 02 73 f5 30 fb 00 00 19 db 50 10 .u....s.0.....P.
|
||||||
|
14:07:46.360 -> 72 10 92 1b 00 00 r.....
|
||||||
|
14:07:46.360 -> out 0 IPv4 10.43.1.117>10.43.1.254 TCP 2>54546[P.] seq:6619..6630 ack:1945448699 win:2126 len=11
|
||||||
|
14:07:46.360 -> 00 20 00 00 00 00 aa aa 03 00 00 00 08 00 45 00 . ............E.
|
||||||
|
14:07:46.360 -> 00 33 00 0e 00 00 ff 06 a3 ee 0a 2b 01 75 0a 2b .3.........+.u.+
|
||||||
|
14:07:46.393 -> 01 fe 00 02 d5 12 00 00 19 db 73 f5 30 fb 50 18 ..........s.0.P.
|
||||||
|
14:07:46.393 -> 08 4e 16 a1 00 00 65 6c 6c 6f 2d 77 6f 72 6c 64 .N....ello-world
|
||||||
|
14:07:46.393 -> 0a .
|
||||||
|
|
||||||
|
[...] help protocol decoding from inside the esp
|
||||||
|
14:08:11.715 -> in 0 IPv4 10.43.1.254>239.255.255.250 UDP 50315>1900 len=172
|
||||||
|
14:08:11.716 -> 01 00 5e 7f ff fa 74 da 38 3a 1f 61 08 00 45 00 ....t.8:.a..E.
|
||||||
|
14:08:11.716 -> 00 c8 9b 40 40 00 01 11 e1 c1 0a 2b 01 fe ef ff ...@@......+....
|
||||||
|
14:08:11.749 -> ff fa c4 8b 07 6c 00 b4 9c 28 4d 2d 53 45 41 52 .....l...(M-SEAR
|
||||||
|
14:08:11.749 -> 43 48 20 2a 20 48 54 54 50 2f 31 2e 31 0d 0a 48 CH * HTTP/1.1..H
|
||||||
|
14:08:11.749 -> 4f 53 54 3a 20 32 33 39 2e 32 35 35 2e 32 35 35 OST: 239.255.255
|
||||||
|
14:08:11.749 -> 2e 32 35 30 3a 31 39 30 30 0d 0a 4d 41 4e 3a 20 .250:1900..MAN:
|
||||||
|
14:08:11.749 -> 22 73 73 64 70 3a 64 69 73 63 6f 76 65 72 22 0d "ssdp:discover".
|
||||||
|
14:08:11.749 -> 0a 4d 58 3a 20 31 0d 0a 53 54 3a 20 75 72 6e 3a .MX: 1..ST: urn:
|
||||||
|
14:08:11.782 -> 64 69 61 6c 2d 6d 75 6c 74 69 73 63 72 65 65 6e dial-multiscreen
|
||||||
|
14:08:11.782 -> 2d 6f 72 67 3a 73 65 72 76 69 63 65 3a 64 69 61 -org:service:dia
|
||||||
|
14:08:11.782 -> 6c 3a 31 0d 0a 55 53 45 52 2d 41 47 45 4e 54 3a l:1..USER-AGENT:
|
||||||
|
14:08:11.782 -> 20 47 6f 6f 67 6c 65 20 43 68 72 6f 6d 65 2f 36 Google Chrome/6
|
||||||
|
14:08:11.782 -> 36 2e 30 2e 33 33 35 39 2e 31 31 37 20 4c 69 6e 6.0.3359.117 Lin
|
||||||
|
14:08:11.782 -> 75 78 0d 0a 0d 0a ux....
|
||||||
|
|
156
libraries/Netdump/examples/Netdump/Netdump.ino
Normal file
156
libraries/Netdump/examples/Netdump/Netdump.ino
Normal file
@ -0,0 +1,156 @@
|
|||||||
|
#include "Arduino.h"
|
||||||
|
|
||||||
|
#include "Netdump.h"
|
||||||
|
#include <ESP8266WiFi.h>
|
||||||
|
#include <ESP8266WebServer.h>
|
||||||
|
#include <ESP8266mDNS.h>
|
||||||
|
//#include <FS.h>
|
||||||
|
#include <LittleFS.h>
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
using namespace NetCapture;
|
||||||
|
|
||||||
|
#ifndef STASSID
|
||||||
|
#define STASSID "your-ssid"
|
||||||
|
#define STAPSK "your-password"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
const char* ssid = STASSID;
|
||||||
|
const char* password = STAPSK;
|
||||||
|
|
||||||
|
Netdump nd;
|
||||||
|
|
||||||
|
//FS* filesystem = &SPIFFS;
|
||||||
|
FS* filesystem = &LittleFS;
|
||||||
|
|
||||||
|
ESP8266WebServer webServer(80); // Used for sending commands
|
||||||
|
WiFiServer tcpServer(8000); // Used to show netcat option.
|
||||||
|
File tracefile;
|
||||||
|
|
||||||
|
std::map<PacketType, int> packetCount;
|
||||||
|
|
||||||
|
enum class SerialOption : uint8_t {
|
||||||
|
AllFull,
|
||||||
|
LocalNone,
|
||||||
|
HTTPChar
|
||||||
|
};
|
||||||
|
|
||||||
|
void startSerial(SerialOption option) {
|
||||||
|
switch (option) {
|
||||||
|
case SerialOption::AllFull : //All Packets, show packet summary.
|
||||||
|
nd.printDump(Serial, Packet::PacketDetail::FULL);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SerialOption::LocalNone : // Only local IP traffic, full details
|
||||||
|
nd.printDump(Serial, Packet::PacketDetail::NONE,
|
||||||
|
[](Packet n) {
|
||||||
|
return (n.hasIP(WiFi.localIP()));
|
||||||
|
}
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
case SerialOption::HTTPChar : // Only HTTP traffic, show packet content as chars
|
||||||
|
nd.printDump(Serial, Packet::PacketDetail::CHAR,
|
||||||
|
[](Packet n) {
|
||||||
|
return (n.isHTTP());
|
||||||
|
}
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
default :
|
||||||
|
Serial.printf("No valid SerialOption provided\r\n");
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
void startTracefile() {
|
||||||
|
// To file all traffic, format pcap file
|
||||||
|
tracefile = filesystem->open("/tr.pcap", "w");
|
||||||
|
nd.fileDump(tracefile);
|
||||||
|
}
|
||||||
|
|
||||||
|
void startTcpDump() {
|
||||||
|
// To tcpserver, all traffic.
|
||||||
|
tcpServer.begin();
|
||||||
|
nd.tcpDump(tcpServer);
|
||||||
|
}
|
||||||
|
|
||||||
|
void setup(void) {
|
||||||
|
Serial.begin(115200);
|
||||||
|
|
||||||
|
WiFi.mode(WIFI_STA);
|
||||||
|
WiFi.begin(ssid, password);
|
||||||
|
|
||||||
|
if (WiFi.waitForConnectResult() != WL_CONNECTED) {
|
||||||
|
Serial.println("WiFi Failed, stopping sketch");
|
||||||
|
while (1) {
|
||||||
|
delay(1000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!MDNS.begin("netdumphost")) {
|
||||||
|
Serial.println("Error setting up MDNS responder!");
|
||||||
|
}
|
||||||
|
|
||||||
|
filesystem->begin();
|
||||||
|
|
||||||
|
webServer.on("/list",
|
||||||
|
[]() {
|
||||||
|
Dir dir = filesystem->openDir("/");
|
||||||
|
String d = "<h1>File list</h1>";
|
||||||
|
while (dir.next()) {
|
||||||
|
d.concat("<li>" + dir.fileName() + "</li>");
|
||||||
|
}
|
||||||
|
webServer.send(200, "text.html", d);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
webServer.on("/req",
|
||||||
|
[]() {
|
||||||
|
static int rq = 0;
|
||||||
|
String a = "<h1>You are connected, Number of requests = " + String(rq++) + "</h1>";
|
||||||
|
webServer.send(200, "text/html", a);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
webServer.on("/reset",
|
||||||
|
[]() {
|
||||||
|
nd.reset();
|
||||||
|
tracefile.close();
|
||||||
|
tcpServer.close();
|
||||||
|
webServer.send(200, "text.html", "<h1>Netdump session reset</h1>");
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
webServer.serveStatic("/", *filesystem, "/");
|
||||||
|
webServer.begin();
|
||||||
|
|
||||||
|
startSerial(SerialOption::AllFull); // Serial output examples, use enum SerialOption for selection
|
||||||
|
|
||||||
|
// startTcpDump(); // tcpdump option
|
||||||
|
// startTracefile(); // output to SPIFFS or LittleFS
|
||||||
|
|
||||||
|
// use a self provide callback, this count network packets
|
||||||
|
/*
|
||||||
|
nd.setCallback(
|
||||||
|
[](Packet p)
|
||||||
|
{
|
||||||
|
Serial.printf("PKT : %s : ",p.sourceIP().toString().c_str());
|
||||||
|
for ( auto pp : p.allPacketTypes())
|
||||||
|
{
|
||||||
|
Serial.printf("%s ",pp.toString().c_str());
|
||||||
|
packetCount[pp]++;
|
||||||
|
}
|
||||||
|
Serial.printf("\r\n CNT ");
|
||||||
|
for (auto pc : packetCount)
|
||||||
|
{
|
||||||
|
Serial.printf("%s %d ", pc.first.toString().c_str(),pc.second);
|
||||||
|
}
|
||||||
|
Serial.printf("\r\n");
|
||||||
|
}
|
||||||
|
);
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop(void) {
|
||||||
|
webServer.handleClient();
|
||||||
|
MDNS.update();
|
||||||
|
}
|
||||||
|
|
1
libraries/Netdump/keywords.txt
Normal file
1
libraries/Netdump/keywords.txt
Normal file
@ -0,0 +1 @@
|
|||||||
|
|
9
libraries/Netdump/library.properties
Normal file
9
libraries/Netdump/library.properties
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
name=NetDump
|
||||||
|
version=2
|
||||||
|
author=Herman Reintke
|
||||||
|
maintainer=Herman Reintke
|
||||||
|
sentence=tcpdump-like logger for esp8266/Arduino
|
||||||
|
paragraph=Dumps input / output packets on "Print"able type, or provide a TCP server for the real tcpdump. Check examples. Some other unrelated and independant tools are included.
|
||||||
|
category=Communication
|
||||||
|
url=https://
|
||||||
|
architectures=esp8266 lwip
|
220
libraries/Netdump/src/Netdump.cpp
Normal file
220
libraries/Netdump/src/Netdump.cpp
Normal file
@ -0,0 +1,220 @@
|
|||||||
|
/*
|
||||||
|
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
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "Netdump.h"
|
||||||
|
#include <lwip/init.h>
|
||||||
|
#include "Schedule.h"
|
||||||
|
|
||||||
|
|
||||||
|
namespace NetCapture
|
||||||
|
{
|
||||||
|
|
||||||
|
CallBackList<Netdump::LwipCallback> Netdump::lwipCallback;
|
||||||
|
|
||||||
|
Netdump::Netdump()
|
||||||
|
{
|
||||||
|
using namespace std::placeholders;
|
||||||
|
phy_capture = capture;
|
||||||
|
lwipHandler = lwipCallback.add(std::bind(&Netdump::netdumpCapture, this, _1, _2, _3, _4, _5));
|
||||||
|
};
|
||||||
|
|
||||||
|
Netdump::~Netdump()
|
||||||
|
{
|
||||||
|
reset();
|
||||||
|
if (packetBuffer)
|
||||||
|
{
|
||||||
|
delete[] packetBuffer;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
void Netdump::setCallback(const Callback nc)
|
||||||
|
{
|
||||||
|
netDumpCallback = nc;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Netdump::setCallback(const Callback nc, const Filter nf)
|
||||||
|
{
|
||||||
|
netDumpFilter = nf;
|
||||||
|
netDumpCallback = nc;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Netdump::setFilter(const Filter nf)
|
||||||
|
{
|
||||||
|
netDumpFilter = nf;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Netdump::reset()
|
||||||
|
{
|
||||||
|
setCallback(nullptr, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Netdump::printDump(Print& out, Packet::PacketDetail ndd, const Filter nf)
|
||||||
|
{
|
||||||
|
out.printf("netDump starting\r\n");
|
||||||
|
setCallback([&out, ndd, this](const Packet & ndp)
|
||||||
|
{
|
||||||
|
printDumpProcess(out, ndd, ndp);
|
||||||
|
}, nf);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Netdump::fileDump(File& outfile, const Filter nf)
|
||||||
|
{
|
||||||
|
|
||||||
|
writePcapHeader(outfile);
|
||||||
|
setCallback([&outfile, this](const Packet & ndp)
|
||||||
|
{
|
||||||
|
fileDumpProcess(outfile, ndp);
|
||||||
|
}, nf);
|
||||||
|
}
|
||||||
|
void Netdump::tcpDump(WiFiServer &tcpDumpServer, const Filter nf)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (!packetBuffer)
|
||||||
|
{
|
||||||
|
packetBuffer = new (std::nothrow) char[tcpBufferSize];
|
||||||
|
}
|
||||||
|
bufferIndex = 0;
|
||||||
|
|
||||||
|
schedule_function([&tcpDumpServer, this, nf]()
|
||||||
|
{
|
||||||
|
tcpDumpLoop(tcpDumpServer, nf);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void Netdump::capture(int netif_idx, const char* data, size_t len, int out, int success)
|
||||||
|
{
|
||||||
|
if (lwipCallback.execute(netif_idx, data, len, out, success) == 0)
|
||||||
|
{
|
||||||
|
phy_capture = nullptr; // No active callback/netdump instances, will be set again by new object.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Netdump::netdumpCapture(int netif_idx, const char* data, size_t len, int out, int success)
|
||||||
|
{
|
||||||
|
if (netDumpCallback)
|
||||||
|
{
|
||||||
|
Packet np(millis(), netif_idx, data, len, out, success);
|
||||||
|
if (netDumpFilter && !netDumpFilter(np))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
netDumpCallback(np);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Netdump::writePcapHeader(Stream& s) const
|
||||||
|
{
|
||||||
|
uint32_t pcapHeader[6];
|
||||||
|
pcapHeader[0] = 0xa1b2c3d4; // pcap magic number
|
||||||
|
pcapHeader[1] = 0x00040002; // pcap major/minor version
|
||||||
|
pcapHeader[2] = 0; // pcap UTC correction in seconds
|
||||||
|
pcapHeader[3] = 0; // pcap time stamp accuracy
|
||||||
|
pcapHeader[4] = maxPcapLength; // pcap max packet length per record
|
||||||
|
pcapHeader[5] = 1; // pacp data linkt type = ethernet
|
||||||
|
s.write(reinterpret_cast<char*>(pcapHeader), 24);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Netdump::printDumpProcess(Print& out, Packet::PacketDetail ndd, const Packet& np) const
|
||||||
|
{
|
||||||
|
out.printf_P(PSTR("%8d %s"), np.getTime(), np.toString(ndd).c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
void Netdump::fileDumpProcess(File& outfile, const Packet& np) const
|
||||||
|
{
|
||||||
|
size_t incl_len = np.getPacketSize() > maxPcapLength ? maxPcapLength : np.getPacketSize();
|
||||||
|
uint32_t pcapHeader[4];
|
||||||
|
|
||||||
|
struct timeval tv;
|
||||||
|
gettimeofday(&tv, nullptr);
|
||||||
|
pcapHeader[0] = tv.tv_sec;
|
||||||
|
pcapHeader[1] = tv.tv_usec;
|
||||||
|
pcapHeader[2] = incl_len;
|
||||||
|
pcapHeader[3] = np.getPacketSize();
|
||||||
|
outfile.write(reinterpret_cast<char*>(pcapHeader), 16); // pcap record header
|
||||||
|
|
||||||
|
outfile.write(np.rawData(), incl_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Netdump::tcpDumpProcess(const Packet& np)
|
||||||
|
{
|
||||||
|
if (np.isTCP() && np.hasPort(tcpDumpClient.localPort()))
|
||||||
|
{
|
||||||
|
// skip myself
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
size_t incl_len = np.getPacketSize() > maxPcapLength ? maxPcapLength : np.getPacketSize();
|
||||||
|
|
||||||
|
if (bufferIndex + 16 + incl_len < tcpBufferSize) // only add if enough space available
|
||||||
|
{
|
||||||
|
struct timeval tv;
|
||||||
|
gettimeofday(&tv, nullptr);
|
||||||
|
uint32_t* pcapHeader = reinterpret_cast<uint32_t*>(&packetBuffer[bufferIndex]);
|
||||||
|
pcapHeader[0] = tv.tv_sec; // add pcap record header
|
||||||
|
pcapHeader[1] = tv.tv_usec;
|
||||||
|
pcapHeader[2] = incl_len;
|
||||||
|
pcapHeader[3] = np.getPacketSize();
|
||||||
|
bufferIndex += 16; // pcap header size
|
||||||
|
memcpy(&packetBuffer[bufferIndex], np.rawData(), incl_len);
|
||||||
|
bufferIndex += incl_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bufferIndex && tcpDumpClient && tcpDumpClient.availableForWrite() >= bufferIndex)
|
||||||
|
{
|
||||||
|
tcpDumpClient.write(packetBuffer, bufferIndex);
|
||||||
|
bufferIndex = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Netdump::tcpDumpLoop(WiFiServer &tcpDumpServer, const Filter nf)
|
||||||
|
{
|
||||||
|
if (tcpDumpServer.hasClient())
|
||||||
|
{
|
||||||
|
tcpDumpClient = tcpDumpServer.available();
|
||||||
|
tcpDumpClient.setNoDelay(true);
|
||||||
|
|
||||||
|
bufferIndex = 0;
|
||||||
|
writePcapHeader(tcpDumpClient);
|
||||||
|
|
||||||
|
setCallback([this](const Packet & ndp)
|
||||||
|
{
|
||||||
|
tcpDumpProcess(ndp);
|
||||||
|
}, nf);
|
||||||
|
}
|
||||||
|
if (!tcpDumpClient || !tcpDumpClient.connected())
|
||||||
|
{
|
||||||
|
setCallback(nullptr);
|
||||||
|
}
|
||||||
|
if (bufferIndex && tcpDumpClient && tcpDumpClient.availableForWrite() >= bufferIndex)
|
||||||
|
{
|
||||||
|
tcpDumpClient.write(packetBuffer, bufferIndex);
|
||||||
|
bufferIndex = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tcpDumpServer.status() != CLOSED)
|
||||||
|
{
|
||||||
|
schedule_function([&tcpDumpServer, this, nf]()
|
||||||
|
{
|
||||||
|
tcpDumpLoop(tcpDumpServer, nf);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace NetCapture
|
87
libraries/Netdump/src/Netdump.h
Normal file
87
libraries/Netdump/src/Netdump.h
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
/*
|
||||||
|
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_H
|
||||||
|
#define __NETDUMP_H
|
||||||
|
|
||||||
|
#include <Print.h>
|
||||||
|
#include <functional>
|
||||||
|
#include <lwipopts.h>
|
||||||
|
#include <FS.h>
|
||||||
|
#include "NetdumpPacket.h"
|
||||||
|
#include <ESP8266WiFi.h>
|
||||||
|
#include "CallBackList.h"
|
||||||
|
|
||||||
|
namespace NetCapture
|
||||||
|
{
|
||||||
|
|
||||||
|
using namespace experimental::CBListImplentation;
|
||||||
|
|
||||||
|
class Netdump
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
using Filter = std::function<bool(const Packet&)>;
|
||||||
|
using Callback = std::function<void(const Packet&)>;
|
||||||
|
using LwipCallback = std::function<void(int, const char*, int, int, int)>;
|
||||||
|
|
||||||
|
Netdump();
|
||||||
|
~Netdump();
|
||||||
|
|
||||||
|
void setCallback(const Callback nc);
|
||||||
|
void setCallback(const Callback nc, const Filter nf);
|
||||||
|
void setFilter(const Filter nf);
|
||||||
|
void reset();
|
||||||
|
|
||||||
|
void printDump(Print& out, Packet::PacketDetail ndd, const Filter nf = nullptr);
|
||||||
|
void fileDump(File& outfile, const Filter nf = nullptr);
|
||||||
|
void tcpDump(WiFiServer &tcpDumpServer, const Filter nf = nullptr);
|
||||||
|
|
||||||
|
|
||||||
|
private:
|
||||||
|
Callback netDumpCallback = nullptr;
|
||||||
|
Filter netDumpFilter = nullptr;
|
||||||
|
|
||||||
|
static void capture(int netif_idx, const char* data, size_t len, int out, int success);
|
||||||
|
static CallBackList<LwipCallback> lwipCallback;
|
||||||
|
CallBackList<LwipCallback>::CallBackHandler lwipHandler;
|
||||||
|
|
||||||
|
void netdumpCapture(int netif_idx, const char* data, size_t len, int out, int success);
|
||||||
|
|
||||||
|
void printDumpProcess(Print& out, Packet::PacketDetail ndd, const Packet& np) const;
|
||||||
|
void fileDumpProcess(File& outfile, const Packet& np) const;
|
||||||
|
void tcpDumpProcess(const Packet& np);
|
||||||
|
void tcpDumpLoop(WiFiServer &tcpDumpServer, const Filter nf);
|
||||||
|
|
||||||
|
void writePcapHeader(Stream& s) const;
|
||||||
|
|
||||||
|
WiFiClient tcpDumpClient;
|
||||||
|
char* packetBuffer = nullptr;
|
||||||
|
size_t bufferIndex = 0;
|
||||||
|
|
||||||
|
static constexpr int tcpBufferSize = 2048;
|
||||||
|
static constexpr int maxPcapLength = 1024;
|
||||||
|
static constexpr uint32_t pcapMagic = 0xa1b2c3d4;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace NetCapture
|
||||||
|
|
||||||
|
#endif /* __NETDUMP_H */
|
375
libraries/Netdump/src/NetdumpIP.cpp
Normal file
375
libraries/Netdump/src/NetdumpIP.cpp
Normal file
@ -0,0 +1,375 @@
|
|||||||
|
/*
|
||||||
|
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
|
||||||
|
|
||||||
|
*/
|
||||||
|
#include <Arduino.h>
|
||||||
|
#include <NetdumpIP.h>
|
||||||
|
|
||||||
|
namespace NetCapture
|
||||||
|
{
|
||||||
|
|
||||||
|
NetdumpIP::NetdumpIP()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
NetdumpIP::NetdumpIP(uint8_t first_octet, uint8_t second_octet, uint8_t third_octet, uint8_t fourth_octet)
|
||||||
|
{
|
||||||
|
setV4();
|
||||||
|
(*this)[0] = first_octet;
|
||||||
|
(*this)[1] = second_octet;
|
||||||
|
(*this)[2] = third_octet;
|
||||||
|
(*this)[3] = fourth_octet;
|
||||||
|
}
|
||||||
|
|
||||||
|
NetdumpIP::NetdumpIP(const uint8_t *address, bool v4)
|
||||||
|
{
|
||||||
|
uint8_t cnt;
|
||||||
|
if (v4)
|
||||||
|
{
|
||||||
|
cnt = 4;
|
||||||
|
setV4();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cnt = 16;
|
||||||
|
setV6();
|
||||||
|
}
|
||||||
|
for (int i = 0; i < cnt; i++)
|
||||||
|
{
|
||||||
|
(*this)[i] = address[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
NetdumpIP::NetdumpIP(const IPAddress& ip)
|
||||||
|
{
|
||||||
|
if (!ip.isSet())
|
||||||
|
{
|
||||||
|
setUnset();
|
||||||
|
}
|
||||||
|
else if (ip.isV4())
|
||||||
|
{
|
||||||
|
setV4();
|
||||||
|
for (int i = 0; i < 4; i++)
|
||||||
|
{
|
||||||
|
rawip[i] = ip[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
setV6();
|
||||||
|
for (int i = 0; i < 16; i++)
|
||||||
|
{
|
||||||
|
rawip[i] = ip[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
NetdumpIP::NetdumpIP(const String& ip)
|
||||||
|
{
|
||||||
|
if (!fromString(ip.c_str()))
|
||||||
|
{
|
||||||
|
setUnset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool NetdumpIP::fromString(const char *address)
|
||||||
|
{
|
||||||
|
if (!fromString4(address))
|
||||||
|
{
|
||||||
|
return fromString6(address);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool NetdumpIP::fromString4(const char *address)
|
||||||
|
{
|
||||||
|
// TODO: (IPv4) add support for "a", "a.b", "a.b.c" formats
|
||||||
|
|
||||||
|
uint16_t acc = 0; // Accumulator
|
||||||
|
uint8_t dots = 0;
|
||||||
|
|
||||||
|
while (*address)
|
||||||
|
{
|
||||||
|
char c = *address++;
|
||||||
|
if (c >= '0' && c <= '9')
|
||||||
|
{
|
||||||
|
acc = acc * 10 + (c - '0');
|
||||||
|
if (acc > 255)
|
||||||
|
{
|
||||||
|
// Value out of [0..255] range
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (c == '.')
|
||||||
|
{
|
||||||
|
if (dots == 3)
|
||||||
|
{
|
||||||
|
// Too much dots (there must be 3 dots)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
(*this)[dots++] = acc;
|
||||||
|
acc = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Invalid char
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dots != 3)
|
||||||
|
{
|
||||||
|
// Too few dots (there must be 3 dots)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
(*this)[3] = acc;
|
||||||
|
|
||||||
|
setV4();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool NetdumpIP::fromString6(const char *address)
|
||||||
|
{
|
||||||
|
// TODO: test test test
|
||||||
|
|
||||||
|
uint32_t acc = 0; // Accumulator
|
||||||
|
int dots = 0, doubledots = -1;
|
||||||
|
|
||||||
|
while (*address)
|
||||||
|
{
|
||||||
|
char c = tolower(*address++);
|
||||||
|
if (isalnum(c))
|
||||||
|
{
|
||||||
|
if (c >= 'a')
|
||||||
|
{
|
||||||
|
c -= 'a' - '0' - 10;
|
||||||
|
}
|
||||||
|
acc = acc * 16 + (c - '0');
|
||||||
|
if (acc > 0xffff)
|
||||||
|
// Value out of range
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (c == ':')
|
||||||
|
{
|
||||||
|
if (*address == ':')
|
||||||
|
{
|
||||||
|
if (doubledots >= 0)
|
||||||
|
// :: allowed once
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// remember location
|
||||||
|
doubledots = dots + !!acc;
|
||||||
|
address++;
|
||||||
|
}
|
||||||
|
if (dots == 7)
|
||||||
|
// too many separators
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
reinterpret_cast<uint16_t*>(rawip)[dots++] = PP_HTONS(acc);
|
||||||
|
acc = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
// Invalid char
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (doubledots == -1 && dots != 7)
|
||||||
|
// Too few separators
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
reinterpret_cast<uint16_t*>(rawip)[dots++] = PP_HTONS(acc);
|
||||||
|
|
||||||
|
if (doubledots != -1)
|
||||||
|
{
|
||||||
|
for (int i = dots - doubledots - 1; i >= 0; i--)
|
||||||
|
{
|
||||||
|
reinterpret_cast<uint16_t*>(rawip)[8 - dots + doubledots + i] = reinterpret_cast<uint16_t*>(rawip)[doubledots + i];
|
||||||
|
}
|
||||||
|
for (int i = doubledots; i < 8 - dots + doubledots; i++)
|
||||||
|
{
|
||||||
|
reinterpret_cast<uint16_t*>(rawip)[i] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
setV6();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
String NetdumpIP::toString()
|
||||||
|
{
|
||||||
|
StreamString sstr;
|
||||||
|
if (isV6())
|
||||||
|
{
|
||||||
|
sstr.reserve(40); // 8 shorts x 4 chars each + 7 colons + nullterm
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sstr.reserve(16); // 4 bytes with 3 chars max + 3 dots + nullterm, or '(IP unset)'
|
||||||
|
}
|
||||||
|
printTo(sstr);
|
||||||
|
return sstr;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t NetdumpIP::printTo(Print& p)
|
||||||
|
{
|
||||||
|
size_t n = 0;
|
||||||
|
|
||||||
|
if (!isSet())
|
||||||
|
{
|
||||||
|
return p.print(F("(IP unset)"));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isV6())
|
||||||
|
{
|
||||||
|
int count0 = 0;
|
||||||
|
for (int i = 0; i < 8; i++)
|
||||||
|
{
|
||||||
|
uint16_t bit = PP_NTOHS(reinterpret_cast<const uint16_t*>(rawip)[i]);
|
||||||
|
if (bit || count0 < 0)
|
||||||
|
{
|
||||||
|
n += p.printf("%x", bit);
|
||||||
|
if (count0 > 0)
|
||||||
|
// no more hiding 0
|
||||||
|
{
|
||||||
|
count0 = -8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
count0++;
|
||||||
|
}
|
||||||
|
if ((i != 7 && count0 < 2) || count0 == 7)
|
||||||
|
{
|
||||||
|
n += p.print(':');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
for (int i = 0; i < 4; i++)
|
||||||
|
{
|
||||||
|
n += p.print((*this)[i], DEC);
|
||||||
|
if (i != 3)
|
||||||
|
{
|
||||||
|
n += p.print('.');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool NetdumpIP::compareRaw(IPversion v, const uint8_t* a, const uint8_t* b) const
|
||||||
|
{
|
||||||
|
for (int i = 0; i < (v == IPversion::IPV4 ? 4 : 16); i++)
|
||||||
|
{
|
||||||
|
if (a[i] != b[i])
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool NetdumpIP::compareIP(const IPAddress& ip) const
|
||||||
|
{
|
||||||
|
switch (ipv)
|
||||||
|
{
|
||||||
|
case IPversion::UNSET :
|
||||||
|
if (ip.isSet())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case IPversion::IPV4 :
|
||||||
|
if (ip.isV6() || !ip.isSet())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return compareRaw(IPversion::IPV4, rawip, reinterpret_cast<const uint8_t*>(&ip.v4()));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case IPversion::IPV6 :
|
||||||
|
if (ip.isV4() || !ip.isSet())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return compareRaw(IPversion::IPV6, rawip, reinterpret_cast<const uint8_t*>(ip.raw6()));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default :
|
||||||
|
return false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool NetdumpIP::compareIP(const NetdumpIP& nip) const
|
||||||
|
{
|
||||||
|
switch (ipv)
|
||||||
|
{
|
||||||
|
case IPversion::UNSET :
|
||||||
|
if (nip.isSet())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case IPversion::IPV4 :
|
||||||
|
if (nip.isV6() || !nip.isSet())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return compareRaw(IPversion::IPV4, rawip, nip.rawip);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case IPversion::IPV6 :
|
||||||
|
if (nip.isV4() || !nip.isSet())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return compareRaw(IPversion::IPV6, rawip, nip.rawip);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default :
|
||||||
|
return false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace NetCapture
|
103
libraries/Netdump/src/NetdumpIP.h
Normal file
103
libraries/Netdump/src/NetdumpIP.h
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
/*
|
||||||
|
NetdumpIP.h
|
||||||
|
|
||||||
|
Created on: 18 mei 2019
|
||||||
|
Author: Herman
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef LIBRARIES_ESPGOODIES_HR_SRC_NETDUMP_NETDUMPIP_H_
|
||||||
|
#define LIBRARIES_ESPGOODIES_HR_SRC_NETDUMP_NETDUMPIP_H_
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <lwip/init.h>
|
||||||
|
#include <StreamString.h>
|
||||||
|
#include <IPAddress.h>
|
||||||
|
|
||||||
|
namespace NetCapture
|
||||||
|
{
|
||||||
|
|
||||||
|
class NetdumpIP
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
NetdumpIP();
|
||||||
|
|
||||||
|
NetdumpIP(uint8_t first_octet, uint8_t second_octet, uint8_t third_octet, uint8_t fourth_octet);
|
||||||
|
NetdumpIP(const uint8_t *address, bool V4 = true);
|
||||||
|
NetdumpIP(const IPAddress& ip);
|
||||||
|
NetdumpIP(const String& ip);
|
||||||
|
|
||||||
|
uint8_t& operator[](int index)
|
||||||
|
{
|
||||||
|
return rawip[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
bool fromString(const char *address);
|
||||||
|
|
||||||
|
String toString();
|
||||||
|
|
||||||
|
private:
|
||||||
|
enum class IPversion {UNSET, IPV4, IPV6};
|
||||||
|
IPversion ipv = IPversion::UNSET;
|
||||||
|
|
||||||
|
uint8_t rawip[16] = {0};
|
||||||
|
|
||||||
|
void setV4()
|
||||||
|
{
|
||||||
|
ipv = IPversion::IPV4;
|
||||||
|
};
|
||||||
|
void setV6()
|
||||||
|
{
|
||||||
|
ipv = IPversion::IPV6;
|
||||||
|
};
|
||||||
|
void setUnset()
|
||||||
|
{
|
||||||
|
ipv = IPversion::UNSET;
|
||||||
|
};
|
||||||
|
bool isV4() const
|
||||||
|
{
|
||||||
|
return (ipv == IPversion::IPV4);
|
||||||
|
};
|
||||||
|
bool isV6() const
|
||||||
|
{
|
||||||
|
return (ipv == IPversion::IPV6);
|
||||||
|
};
|
||||||
|
bool isUnset() const
|
||||||
|
{
|
||||||
|
return (ipv == IPversion::UNSET);
|
||||||
|
};
|
||||||
|
bool isSet() const
|
||||||
|
{
|
||||||
|
return (ipv != IPversion::UNSET);
|
||||||
|
};
|
||||||
|
|
||||||
|
bool compareRaw(IPversion v, const uint8_t* a, const uint8_t* b) const;
|
||||||
|
bool compareIP(const IPAddress& ip) const;
|
||||||
|
bool compareIP(const NetdumpIP& nip) const;
|
||||||
|
|
||||||
|
bool fromString4(const char *address);
|
||||||
|
bool fromString6(const char *address);
|
||||||
|
|
||||||
|
size_t printTo(Print& p);
|
||||||
|
public:
|
||||||
|
bool operator==(const IPAddress& addr) const
|
||||||
|
{
|
||||||
|
return compareIP(addr);
|
||||||
|
};
|
||||||
|
bool operator!=(const IPAddress& addr)
|
||||||
|
{
|
||||||
|
return compareIP(addr);
|
||||||
|
};
|
||||||
|
bool operator==(const NetdumpIP& addr)
|
||||||
|
{
|
||||||
|
return compareIP(addr);
|
||||||
|
};
|
||||||
|
bool operator!=(const NetdumpIP& addr)
|
||||||
|
{
|
||||||
|
return !compareIP(addr);
|
||||||
|
};
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace NetCapture
|
||||||
|
|
||||||
|
#endif /* LIBRARIES_ESPGOODIES_HR_SRC_NETDUMP_NETDUMPIP_H_ */
|
381
libraries/Netdump/src/NetdumpPacket.cpp
Normal file
381
libraries/Netdump/src/NetdumpPacket.cpp
Normal file
@ -0,0 +1,381 @@
|
|||||||
|
/*
|
||||||
|
NetDump library - tcpdump-like packet logger facility
|
||||||
|
|
||||||
|
Copyright (c) 2018 David Gauchard. 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
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "Netdump.h"
|
||||||
|
#include <lwip/init.h>
|
||||||
|
|
||||||
|
namespace NetCapture
|
||||||
|
{
|
||||||
|
|
||||||
|
void Packet::printDetail(Print& out, const String& indent, const char* data, size_t size, PacketDetail pd) const
|
||||||
|
{
|
||||||
|
if (pd == PacketDetail::NONE)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t charCount = (pd == PacketDetail::CHAR) ? 80 : 24;
|
||||||
|
|
||||||
|
size_t start = 0;
|
||||||
|
while (start < size)
|
||||||
|
{
|
||||||
|
size_t end = start + charCount;
|
||||||
|
if (end > size)
|
||||||
|
{
|
||||||
|
end = size;
|
||||||
|
}
|
||||||
|
out.printf("%s", indent.c_str());
|
||||||
|
if (pd != PacketDetail::CHAR)
|
||||||
|
{
|
||||||
|
for (size_t i = start; i < end; i++)
|
||||||
|
{
|
||||||
|
out.printf("%02x ", (unsigned char)data[i]);
|
||||||
|
}
|
||||||
|
for (size_t i = end; i < start + charCount; i++)
|
||||||
|
{
|
||||||
|
out.print(" ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (size_t i = start; i < end; i++)
|
||||||
|
{
|
||||||
|
out.printf("%c", data[i] >= 32 && data[i] < 128 ? data[i] : '.');
|
||||||
|
}
|
||||||
|
out.println();
|
||||||
|
|
||||||
|
start += charCount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Packet::setPacketType(PacketType pt)
|
||||||
|
{
|
||||||
|
thisPacketType = pt;
|
||||||
|
thisAllPacketTypes.emplace_back(pt);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Packet::setPacketTypes()
|
||||||
|
{
|
||||||
|
if (isARP())
|
||||||
|
{
|
||||||
|
setPacketType(PacketType::ARP);
|
||||||
|
}
|
||||||
|
else if (isIP())
|
||||||
|
{
|
||||||
|
setPacketType(PacketType::IP);
|
||||||
|
setPacketType(isIPv4() ? PacketType::IPv4 : PacketType::IPv6);
|
||||||
|
if (isUDP())
|
||||||
|
{
|
||||||
|
setPacketType(PacketType::UDP);
|
||||||
|
if (isMDNS())
|
||||||
|
{
|
||||||
|
setPacketType(PacketType::MDNS);
|
||||||
|
}
|
||||||
|
if (isDNS())
|
||||||
|
{
|
||||||
|
setPacketType(PacketType::DNS);
|
||||||
|
}
|
||||||
|
if (isSSDP())
|
||||||
|
{
|
||||||
|
setPacketType(PacketType::SSDP);
|
||||||
|
}
|
||||||
|
if (isDHCP())
|
||||||
|
{
|
||||||
|
setPacketType(PacketType::DHCP);
|
||||||
|
}
|
||||||
|
if (isWSDD())
|
||||||
|
{
|
||||||
|
setPacketType(PacketType::WSDD);
|
||||||
|
}
|
||||||
|
if (isNETBIOS())
|
||||||
|
{
|
||||||
|
setPacketType(PacketType::NETBIOS);
|
||||||
|
}
|
||||||
|
if (isSMB())
|
||||||
|
{
|
||||||
|
setPacketType(PacketType::SMB);
|
||||||
|
}
|
||||||
|
if (isOTA())
|
||||||
|
{
|
||||||
|
setPacketType(PacketType::OTA);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (isTCP())
|
||||||
|
{
|
||||||
|
setPacketType(PacketType::TCP);
|
||||||
|
if (isHTTP())
|
||||||
|
{
|
||||||
|
setPacketType(PacketType::HTTP);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (isICMP())
|
||||||
|
{
|
||||||
|
setPacketType(PacketType::ICMP);
|
||||||
|
}
|
||||||
|
if (isIGMP())
|
||||||
|
{
|
||||||
|
setPacketType(PacketType::IGMP);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
setPacketType(PacketType::UKNW);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const PacketType Packet::packetType() const
|
||||||
|
{
|
||||||
|
return thisPacketType;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::vector<PacketType>& Packet::allPacketTypes() const
|
||||||
|
{
|
||||||
|
return thisAllPacketTypes;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Packet::MACtoString(int dataIdx, StreamString& sstr) const
|
||||||
|
{
|
||||||
|
for (int i = 0; i < 6; i++)
|
||||||
|
{
|
||||||
|
sstr.printf_P(PSTR("%02x"), (unsigned char)data[dataIdx + i]);
|
||||||
|
if (i < 5)
|
||||||
|
{
|
||||||
|
sstr.print(':');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void Packet::ARPtoString(PacketDetail netdumpDetail, StreamString& sstr) const
|
||||||
|
{
|
||||||
|
switch (getARPType())
|
||||||
|
{
|
||||||
|
case 1 : sstr.printf_P(PSTR("who has %s tell %s"), getIP(ETH_HDR_LEN + 24).toString().c_str(), getIP(ETH_HDR_LEN + 14).toString().c_str());
|
||||||
|
break;
|
||||||
|
case 2 : sstr.printf_P(PSTR("%s is at "), getIP(ETH_HDR_LEN + 14).toString().c_str());
|
||||||
|
MACtoString(ETH_HDR_LEN + 8, sstr);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
sstr.printf("\r\n");
|
||||||
|
printDetail(sstr, PSTR(" D "), &data[ETH_HDR_LEN], packetLength - ETH_HDR_LEN, netdumpDetail);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Packet::DNStoString(PacketDetail netdumpDetail, StreamString& sstr) const
|
||||||
|
{
|
||||||
|
sstr.printf_P(PSTR("%s>%s "), sourceIP().toString().c_str(), destIP().toString().c_str());
|
||||||
|
sstr.printf_P(PSTR("ID=0x%04x "), ntoh16(ETH_HDR_LEN + getIpHdrLen() + 8));
|
||||||
|
sstr.printf_P(PSTR("F=0x%04x "), ntoh16(ETH_HDR_LEN + getIpHdrLen() + 8 + 2));
|
||||||
|
if (uint16_t t = ntoh16(ETH_HDR_LEN + getIpHdrLen() + 8 + 4))
|
||||||
|
{
|
||||||
|
sstr.printf_P(PSTR("Q=%d "), t);
|
||||||
|
}
|
||||||
|
if (uint16_t t = ntoh16(ETH_HDR_LEN + getIpHdrLen() + 8 + 6))
|
||||||
|
{
|
||||||
|
sstr.printf_P(PSTR("R=%d "), t);
|
||||||
|
}
|
||||||
|
if (uint16_t t = ntoh16(ETH_HDR_LEN + getIpHdrLen() + 8 + 8))
|
||||||
|
{
|
||||||
|
sstr.printf_P(PSTR("TR=%d "), t);
|
||||||
|
}
|
||||||
|
if (uint16_t t = ntoh16(ETH_HDR_LEN + getIpHdrLen() + 8 + 10))
|
||||||
|
{
|
||||||
|
sstr.printf_P(PSTR("DR=%d "), t);
|
||||||
|
}
|
||||||
|
sstr.printf_P(PSTR("\r\n"));
|
||||||
|
printDetail(sstr, PSTR(" H "), &data[ETH_HDR_LEN + getIpHdrLen()], getUdpHdrLen(), netdumpDetail);
|
||||||
|
printDetail(sstr, PSTR(" D "), &data[ETH_HDR_LEN + getIpHdrLen() + getUdpHdrLen()], getUdpLen(), netdumpDetail);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Packet::UDPtoString(PacketDetail netdumpDetail, StreamString& sstr) const
|
||||||
|
{
|
||||||
|
sstr.printf_P(PSTR("%s>%s "), sourceIP().toString().c_str(), destIP().toString().c_str());
|
||||||
|
sstr.printf_P(PSTR("%d:%d"), getSrcPort(), getDstPort());
|
||||||
|
sstr.printf_P(PSTR("\r\n"));
|
||||||
|
printDetail(sstr, PSTR(" H "), &data[ETH_HDR_LEN + getIpHdrLen()], getUdpHdrLen(), netdumpDetail);
|
||||||
|
printDetail(sstr, PSTR(" D "), &data[ETH_HDR_LEN + getIpHdrLen() + getUdpHdrLen()], getUdpLen(), netdumpDetail);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Packet::TCPtoString(PacketDetail netdumpDetail, StreamString& sstr) const
|
||||||
|
{
|
||||||
|
sstr.printf_P(PSTR("%s>%s "), sourceIP().toString().c_str(), destIP().toString().c_str());
|
||||||
|
sstr.printf_P(PSTR("%d:%d "), getSrcPort(), getDstPort());
|
||||||
|
uint16_t flags = getTcpFlags();
|
||||||
|
sstr.print('[');
|
||||||
|
const char chars [] = "FSRPAUECN";
|
||||||
|
for (uint8_t i = 0; i < sizeof chars; i++)
|
||||||
|
if (flags & (1 << i))
|
||||||
|
{
|
||||||
|
sstr.print(chars[i]);
|
||||||
|
}
|
||||||
|
sstr.print(']');
|
||||||
|
sstr.printf_P(PSTR(" len: %u seq: %u, ack: %u, wnd: %u "), getTcpLen(), getTcpSeq(), getTcpAck(), getTcpWindow());
|
||||||
|
sstr.printf_P(PSTR("\r\n"));
|
||||||
|
printDetail(sstr, PSTR(" H "), &data[ETH_HDR_LEN + getIpHdrLen()], getTcpHdrLen(), netdumpDetail);
|
||||||
|
printDetail(sstr, PSTR(" D "), &data[ETH_HDR_LEN + getIpHdrLen() + getTcpHdrLen()], getTcpLen(), netdumpDetail);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Packet::ICMPtoString(PacketDetail, StreamString& sstr) const
|
||||||
|
{
|
||||||
|
sstr.printf_P(PSTR("%s>%s "), sourceIP().toString().c_str(), destIP().toString().c_str());
|
||||||
|
if (isIPv4())
|
||||||
|
{
|
||||||
|
switch (getIcmpType())
|
||||||
|
{
|
||||||
|
case 0 : sstr.printf_P(PSTR("ping reply")); break;
|
||||||
|
case 8 : sstr.printf_P(PSTR("ping request")); break;
|
||||||
|
default: sstr.printf_P(PSTR("type(0x%02x)"), getIcmpType()); break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (isIPv6())
|
||||||
|
{
|
||||||
|
switch (getIcmpType())
|
||||||
|
{
|
||||||
|
case 129 : sstr.printf_P(PSTR("ping reply")); break;
|
||||||
|
case 128 : sstr.printf_P(PSTR("ping request")); break;
|
||||||
|
case 135 : sstr.printf_P(PSTR("Neighbour solicitation")); break;
|
||||||
|
case 136 : sstr.printf_P(PSTR("Neighbour advertisement")); break;
|
||||||
|
default: sstr.printf_P(PSTR("type(0x%02x)"), getIcmpType()); break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sstr.printf("\r\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void Packet::IGMPtoString(PacketDetail, StreamString& sstr) const
|
||||||
|
{
|
||||||
|
switch (getIgmpType())
|
||||||
|
{
|
||||||
|
case 1 : sstr.printf_P(PSTR("Create Group Request")); break;
|
||||||
|
case 2 : sstr.printf_P(PSTR("Create Group Reply")); break;
|
||||||
|
case 3 : sstr.printf_P(PSTR("Join Group Request")); break;
|
||||||
|
case 4 : sstr.printf_P(PSTR("Join Group Reply")); break;
|
||||||
|
case 5 : sstr.printf_P(PSTR("Leave Group Request")); break;
|
||||||
|
case 6 : sstr.printf_P(PSTR("Leave Group Reply")); break;
|
||||||
|
case 7 : sstr.printf_P(PSTR("Confirm Group Request")); break;
|
||||||
|
case 8 : sstr.printf_P(PSTR("Confirm Group Reply")); break;
|
||||||
|
case 0x11 : sstr.printf_P(PSTR("Group Membership Query")); break;
|
||||||
|
case 0x12 : sstr.printf_P(PSTR("IGMPv1 Membership Report")); break;
|
||||||
|
case 0x22 : sstr.printf_P(PSTR("IGMPv3 Membership Report")); break;
|
||||||
|
default: sstr.printf_P(PSTR("type(0x%02x)"), getIgmpType()); break;
|
||||||
|
}
|
||||||
|
sstr.printf_P(PSTR("\r\n"));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Packet::IPtoString(PacketDetail netdumpDetail, StreamString& sstr) const
|
||||||
|
{
|
||||||
|
sstr.printf_P(PSTR("%s>%s "), sourceIP().toString().c_str(), destIP().toString().c_str());
|
||||||
|
sstr.printf_P(PSTR("Unknown IP type : %d\r\n"), ipType());
|
||||||
|
printDetail(sstr, PSTR(" H "), &data[ETH_HDR_LEN], getIpHdrLen(), netdumpDetail);
|
||||||
|
printDetail(sstr, PSTR(" D "), &data[ETH_HDR_LEN + getIpHdrLen()], getIpTotalLen() - getIpHdrLen(), netdumpDetail);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Packet::UKNWtoString(PacketDetail, StreamString& sstr) const
|
||||||
|
{
|
||||||
|
sstr.printf_P(PSTR("Unknown EtherType 0x%04x Src : "), ethType());
|
||||||
|
MACtoString(0, sstr);
|
||||||
|
sstr.printf_P(PSTR(" Dst : "));
|
||||||
|
MACtoString(6, sstr);
|
||||||
|
sstr.printf_P(PSTR("\r\n"));
|
||||||
|
}
|
||||||
|
|
||||||
|
const String Packet::toString() const
|
||||||
|
{
|
||||||
|
return toString(PacketDetail::NONE);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const String Packet::toString(PacketDetail netdumpDetail) const
|
||||||
|
{
|
||||||
|
StreamString sstr;
|
||||||
|
sstr.reserve(128);
|
||||||
|
|
||||||
|
sstr.printf_P(PSTR("%d %3s %-4s "), netif_idx, out ? "out" : "in ", packetType().toString().c_str());
|
||||||
|
|
||||||
|
if (netdumpDetail == PacketDetail::RAW)
|
||||||
|
{
|
||||||
|
sstr.printf_P(PSTR(" : "));
|
||||||
|
for (auto at : thisAllPacketTypes)
|
||||||
|
{
|
||||||
|
sstr.printf_P(PSTR("%s "), at.toString().c_str());
|
||||||
|
}
|
||||||
|
sstr.printf_P(PSTR("\r\n"));
|
||||||
|
printDetail(sstr, PSTR(" D "), data, packetLength, netdumpDetail);
|
||||||
|
return sstr;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (thisPacketType)
|
||||||
|
{
|
||||||
|
case PacketType::ARP :
|
||||||
|
{
|
||||||
|
ARPtoString(netdumpDetail, sstr);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case PacketType::MDNS :
|
||||||
|
case PacketType::DNS :
|
||||||
|
{
|
||||||
|
DNStoString(netdumpDetail, sstr);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case PacketType::SSDP :
|
||||||
|
case PacketType::DHCP :
|
||||||
|
case PacketType::WSDD :
|
||||||
|
case PacketType::NETBIOS :
|
||||||
|
case PacketType::SMB :
|
||||||
|
case PacketType::OTA :
|
||||||
|
case PacketType::UDP :
|
||||||
|
{
|
||||||
|
UDPtoString(netdumpDetail, sstr);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case PacketType::TCP :
|
||||||
|
case PacketType::HTTP :
|
||||||
|
{
|
||||||
|
TCPtoString(netdumpDetail, sstr);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case PacketType::ICMP :
|
||||||
|
{
|
||||||
|
ICMPtoString(netdumpDetail, sstr);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case PacketType::IGMP :
|
||||||
|
{
|
||||||
|
IGMPtoString(netdumpDetail, sstr);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case PacketType::IPv4 :
|
||||||
|
case PacketType::IPv6 :
|
||||||
|
{
|
||||||
|
IPtoString(netdumpDetail, sstr);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case PacketType::UKNW :
|
||||||
|
{
|
||||||
|
UKNWtoString(netdumpDetail, sstr);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default :
|
||||||
|
{
|
||||||
|
sstr.printf_P(PSTR("Non identified packet\r\n"));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return sstr;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace NetCapture
|
314
libraries/Netdump/src/NetdumpPacket.h
Normal file
314
libraries/Netdump/src/NetdumpPacket.h
Normal file
@ -0,0 +1,314 @@
|
|||||||
|
/*
|
||||||
|
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 */
|
43
libraries/Netdump/src/PacketType.cpp
Normal file
43
libraries/Netdump/src/PacketType.cpp
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
/*
|
||||||
|
PacketType.cpp
|
||||||
|
|
||||||
|
Created on: 19 nov. 2019
|
||||||
|
Author: Herman
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <PacketType.h>
|
||||||
|
|
||||||
|
namespace NetCapture
|
||||||
|
{
|
||||||
|
|
||||||
|
PacketType::PacketType()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
String PacketType::toString() const
|
||||||
|
{
|
||||||
|
switch (ptype)
|
||||||
|
{
|
||||||
|
case PType::ARP : return PSTR("ARP");
|
||||||
|
case PType::IP : return PSTR("IP");
|
||||||
|
case PType::UDP : return PSTR("UDP");
|
||||||
|
case PType::MDNS : return PSTR("MDNS");
|
||||||
|
case PType::DNS : return PSTR("DNS");
|
||||||
|
case PType::SSDP : return PSTR("SSDP");
|
||||||
|
case PType::DHCP : return PSTR("DHCP");
|
||||||
|
case PType::WSDD : return PSTR("WSDD");
|
||||||
|
case PType::NETBIOS: return PSTR("NBIO");
|
||||||
|
case PType::SMB : return PSTR("SMB");
|
||||||
|
case PType::OTA : return PSTR("OTA");
|
||||||
|
case PType::TCP : return PSTR("TCP");
|
||||||
|
case PType::HTTP : return PSTR("HTTP");
|
||||||
|
case PType::ICMP : return PSTR("ICMP");
|
||||||
|
case PType::IGMP : return PSTR("IGMP");
|
||||||
|
case PType::IPv4: return PSTR("IPv4");
|
||||||
|
case PType::IPv6: return PSTR("IPv6");
|
||||||
|
case PType::UKNW : return PSTR("UKNW");
|
||||||
|
default : return PSTR("ERR");
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
} /* namespace NetCapture */
|
61
libraries/Netdump/src/PacketType.h
Normal file
61
libraries/Netdump/src/PacketType.h
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
/*
|
||||||
|
PacketType.h
|
||||||
|
|
||||||
|
Created on: 19 nov. 2019
|
||||||
|
Author: Herman
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef LIBRARIES_NETDUMP_SRC_PACKETTYPE_H_
|
||||||
|
#define LIBRARIES_NETDUMP_SRC_PACKETTYPE_H_
|
||||||
|
#include "Arduino.h"
|
||||||
|
|
||||||
|
namespace NetCapture
|
||||||
|
{
|
||||||
|
|
||||||
|
class PacketType
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
enum PType : int
|
||||||
|
{
|
||||||
|
ARP,
|
||||||
|
IP,
|
||||||
|
UDP,
|
||||||
|
MDNS,
|
||||||
|
DNS,
|
||||||
|
SSDP,
|
||||||
|
DHCP,
|
||||||
|
WSDD,
|
||||||
|
NETBIOS,
|
||||||
|
SMB,
|
||||||
|
OTA,
|
||||||
|
TCP,
|
||||||
|
HTTP,
|
||||||
|
ICMP,
|
||||||
|
IGMP,
|
||||||
|
IPv4,
|
||||||
|
IPv6,
|
||||||
|
UKNW,
|
||||||
|
};
|
||||||
|
|
||||||
|
PacketType();
|
||||||
|
PacketType(PType pt) : ptype(pt) {};
|
||||||
|
|
||||||
|
operator PType() const
|
||||||
|
{
|
||||||
|
return ptype;
|
||||||
|
};
|
||||||
|
bool operator==(const PacketType& p)
|
||||||
|
{
|
||||||
|
return ptype == p.ptype;
|
||||||
|
};
|
||||||
|
|
||||||
|
String toString() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
PType ptype;
|
||||||
|
};
|
||||||
|
|
||||||
|
} /* namespace NetCapture */
|
||||||
|
|
||||||
|
#endif /* LIBRARIES_NETDUMP_SRC_PACKETTYPE_H_ */
|
@ -14,6 +14,7 @@ all="
|
|||||||
libraries/ESP8266mDNS
|
libraries/ESP8266mDNS
|
||||||
libraries/Wire
|
libraries/Wire
|
||||||
cores/esp8266/core_esp8266_si2c.cpp
|
cores/esp8266/core_esp8266_si2c.cpp
|
||||||
|
libraries/Netdump
|
||||||
"
|
"
|
||||||
|
|
||||||
# core
|
# core
|
||||||
|
Loading…
x
Reference in New Issue
Block a user