From 27c051ac56861154e94e8407a01111d92ab03041 Mon Sep 17 00:00:00 2001
From: hreintke <hreintke@tauri.nl>
Date: Sat, 15 Aug 2020 15:07:09 +0200
Subject: [PATCH 1/4] Netump Initial commit

---
 libraries/Netdump/README.md                   |  52 +++
 .../Netdump/examples/Netdump/Netdump.ino      | 155 +++++++
 libraries/Netdump/keywords.txt                |   1 +
 libraries/Netdump/library.properties          |   9 +
 libraries/Netdump/src/Netdump.cpp             | 220 ++++++++++
 libraries/Netdump/src/Netdump.h               |  87 ++++
 libraries/Netdump/src/NetdumpIP.cpp           | 379 +++++++++++++++++
 libraries/Netdump/src/NetdumpIP.h             | 104 +++++
 libraries/Netdump/src/NetdumpPacket.cpp       | 381 ++++++++++++++++++
 libraries/Netdump/src/NetdumpPacket.h         | 316 +++++++++++++++
 libraries/Netdump/src/PacketType.cpp          |  47 +++
 libraries/Netdump/src/PacketType.h            |  63 +++
 12 files changed, 1814 insertions(+)
 create mode 100644 libraries/Netdump/README.md
 create mode 100644 libraries/Netdump/examples/Netdump/Netdump.ino
 create mode 100644 libraries/Netdump/keywords.txt
 create mode 100644 libraries/Netdump/library.properties
 create mode 100644 libraries/Netdump/src/Netdump.cpp
 create mode 100644 libraries/Netdump/src/Netdump.h
 create mode 100644 libraries/Netdump/src/NetdumpIP.cpp
 create mode 100644 libraries/Netdump/src/NetdumpIP.h
 create mode 100644 libraries/Netdump/src/NetdumpPacket.cpp
 create mode 100644 libraries/Netdump/src/NetdumpPacket.h
 create mode 100644 libraries/Netdump/src/PacketType.cpp
 create mode 100644 libraries/Netdump/src/PacketType.h

diff --git a/libraries/Netdump/README.md b/libraries/Netdump/README.md
new file mode 100644
index 0000000000..7db9c725af
--- /dev/null
+++ b/libraries/Netdump/README.md
@@ -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....
+
diff --git a/libraries/Netdump/examples/Netdump/Netdump.ino b/libraries/Netdump/examples/Netdump/Netdump.ino
new file mode 100644
index 0000000000..385438bf02
--- /dev/null
+++ b/libraries/Netdump/examples/Netdump/Netdump.ino
@@ -0,0 +1,155 @@
+#include "Arduino.h"
+
+#include "Netdump.h"
+#include <ESP8266WiFi.h>
+#include <ESP8266WebServer.h>
+#include <ESP8266mDNS.h>
+#include <FS.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 SerialOption {
+  AllFull,
+  LocalNone,
+  HTTPChar
+};
+
+void startSerial(int option) {
+  switch (option) {
+    case AllFull : //All Packets, show packet summary.
+      nd.printDump(Serial, Packet::PacketDetail::FULL);
+      break;
+
+    case LocalNone : // Only local IP traffic, full details
+      nd.printDump(Serial, Packet::PacketDetail::NONE,
+      [](Packet n) {
+        return (n.hasIP(WiFi.localIP()));
+      }
+                  );
+      break;
+    case 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");
+    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(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();
+}
+
diff --git a/libraries/Netdump/keywords.txt b/libraries/Netdump/keywords.txt
new file mode 100644
index 0000000000..8b13789179
--- /dev/null
+++ b/libraries/Netdump/keywords.txt
@@ -0,0 +1 @@
+
diff --git a/libraries/Netdump/library.properties b/libraries/Netdump/library.properties
new file mode 100644
index 0000000000..2f6ad5e22e
--- /dev/null
+++ b/libraries/Netdump/library.properties
@@ -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
diff --git a/libraries/Netdump/src/Netdump.cpp b/libraries/Netdump/src/Netdump.cpp
new file mode 100644
index 0000000000..3adb32a9d0
--- /dev/null
+++ b/libraries/Netdump/src/Netdump.cpp
@@ -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 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
diff --git a/libraries/Netdump/src/Netdump.h b/libraries/Netdump/src/Netdump.h
new file mode 100644
index 0000000000..bf16e7dd30
--- /dev/null
+++ b/libraries/Netdump/src/Netdump.h
@@ -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 */
diff --git a/libraries/Netdump/src/NetdumpIP.cpp b/libraries/Netdump/src/NetdumpIP.cpp
new file mode 100644
index 0000000000..2a1c9212af
--- /dev/null
+++ b/libraries/Netdump/src/NetdumpIP.cpp
@@ -0,0 +1,379 @@
+/*
+    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()
+{
+}
+
+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
diff --git a/libraries/Netdump/src/NetdumpIP.h b/libraries/Netdump/src/NetdumpIP.h
new file mode 100644
index 0000000000..73b668ac3c
--- /dev/null
+++ b/libraries/Netdump/src/NetdumpIP.h
@@ -0,0 +1,104 @@
+/*
+    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();
+
+    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_ */
diff --git a/libraries/Netdump/src/NetdumpPacket.cpp b/libraries/Netdump/src/NetdumpPacket.cpp
new file mode 100644
index 0000000000..86782dd921
--- /dev/null
+++ b/libraries/Netdump/src/NetdumpPacket.cpp
@@ -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 netdumpDetail, 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 netdumpDetail, 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 netdumpDetail, 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
diff --git a/libraries/Netdump/src/NetdumpPacket.h b/libraries/Netdump/src/NetdumpPacket.h
new file mode 100644
index 0000000000..af0d701619
--- /dev/null
+++ b/libraries/Netdump/src/NetdumpPacket.h
@@ -0,0 +1,316 @@
+/*
+    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();
+    };
+
+    Packet() {};
+
+    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 */
diff --git a/libraries/Netdump/src/PacketType.cpp b/libraries/Netdump/src/PacketType.cpp
new file mode 100644
index 0000000000..1bebea68ec
--- /dev/null
+++ b/libraries/Netdump/src/PacketType.cpp
@@ -0,0 +1,47 @@
+/*
+    PacketType.cpp
+
+    Created on: 19 nov. 2019
+        Author: Herman
+*/
+
+#include <PacketType.h>
+
+namespace NetCapture
+{
+
+PacketType::PacketType()
+{
+}
+
+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 */
diff --git a/libraries/Netdump/src/PacketType.h b/libraries/Netdump/src/PacketType.h
new file mode 100644
index 0000000000..b6fb1db611
--- /dev/null
+++ b/libraries/Netdump/src/PacketType.h
@@ -0,0 +1,63 @@
+/*
+    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) {};
+
+    ~PacketType();
+
+    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_ */

From a53c5c4663d87962a389214c0db5283bacc51a74 Mon Sep 17 00:00:00 2001
From: hreintke <hreintke@tauri.nl>
Date: Sat, 15 Aug 2020 15:29:19 +0200
Subject: [PATCH 2/4] Use LittleFS & unused variable fix

---
 libraries/Netdump/examples/Netdump/Netdump.ino | 7 ++++---
 libraries/Netdump/src/NetdumpPacket.cpp        | 6 +++---
 2 files changed, 7 insertions(+), 6 deletions(-)

diff --git a/libraries/Netdump/examples/Netdump/Netdump.ino b/libraries/Netdump/examples/Netdump/Netdump.ino
index 385438bf02..b8ad4d24ed 100644
--- a/libraries/Netdump/examples/Netdump/Netdump.ino
+++ b/libraries/Netdump/examples/Netdump/Netdump.ino
@@ -4,7 +4,8 @@
 #include <ESP8266WiFi.h>
 #include <ESP8266WebServer.h>
 #include <ESP8266mDNS.h>
-#include <FS.h>
+//#include <FS.h>
+#include <LittleFS.h>
 #include <map>
 
 using namespace NetCapture;
@@ -19,8 +20,8 @@ const char* password = STAPSK;
 
 Netdump nd;
 
-FS* filesystem = &SPIFFS;
-//FS* filesystem = &LittleFS;
+//FS* filesystem = &SPIFFS;
+FS* filesystem = &LittleFS;
 
 ESP8266WebServer webServer(80);    // Used for sending commands
 WiFiServer       tcpServer(8000);  // Used to show netcat option.
diff --git a/libraries/Netdump/src/NetdumpPacket.cpp b/libraries/Netdump/src/NetdumpPacket.cpp
index 86782dd921..2f9da6df93 100644
--- a/libraries/Netdump/src/NetdumpPacket.cpp
+++ b/libraries/Netdump/src/NetdumpPacket.cpp
@@ -230,7 +230,7 @@ void Packet::TCPtoString(PacketDetail netdumpDetail, StreamString& sstr) const
     printDetail(sstr, PSTR("           D "), &data[ETH_HDR_LEN + getIpHdrLen() + getTcpHdrLen()], getTcpLen(), netdumpDetail);
 }
 
-void Packet::ICMPtoString(PacketDetail netdumpDetail, StreamString& sstr) const
+void Packet::ICMPtoString(PacketDetail, StreamString& sstr) const
 {
     sstr.printf_P(PSTR("%s>%s "), sourceIP().toString().c_str(), destIP().toString().c_str());
     if (isIPv4())
@@ -256,7 +256,7 @@ void Packet::ICMPtoString(PacketDetail netdumpDetail, StreamString& sstr) const
     sstr.printf("\r\n");
 }
 
-void Packet::IGMPtoString(PacketDetail netdumpDetail, StreamString& sstr) const
+void Packet::IGMPtoString(PacketDetail, StreamString& sstr) const
 {
     switch (getIgmpType())
     {
@@ -284,7 +284,7 @@ void Packet::IPtoString(PacketDetail netdumpDetail, StreamString& sstr) const
     printDetail(sstr, PSTR("           D "), &data[ETH_HDR_LEN + getIpHdrLen()], getIpTotalLen() - getIpHdrLen(), netdumpDetail);
 }
 
-void Packet::UKNWtoString(PacketDetail netdumpDetail, StreamString& sstr) const
+void Packet::UKNWtoString(PacketDetail, StreamString& sstr) const
 {
     sstr.printf_P(PSTR("Unknown EtherType 0x%04x Src : "), ethType());
     MACtoString(0, sstr);

From 18c8ff66229cc61acfdab477f65410f9a2e1b020 Mon Sep 17 00:00:00 2001
From: hreintke <hreintke@tauri.nl>
Date: Sun, 16 Aug 2020 13:14:44 +0200
Subject: [PATCH 3/4] Update from comments

---
 libraries/Netdump/examples/Netdump/Netdump.ino | 14 +++++++-------
 libraries/Netdump/src/Netdump.cpp              |  4 ++--
 libraries/Netdump/src/Netdump.h                |  2 +-
 libraries/Netdump/src/NetdumpIP.cpp            |  4 ----
 libraries/Netdump/src/NetdumpIP.h              |  1 -
 libraries/Netdump/src/NetdumpPacket.h          |  2 --
 libraries/Netdump/src/PacketType.cpp           |  4 ----
 libraries/Netdump/src/PacketType.h             |  2 --
 8 files changed, 10 insertions(+), 23 deletions(-)

diff --git a/libraries/Netdump/examples/Netdump/Netdump.ino b/libraries/Netdump/examples/Netdump/Netdump.ino
index b8ad4d24ed..dbba63869b 100644
--- a/libraries/Netdump/examples/Netdump/Netdump.ino
+++ b/libraries/Netdump/examples/Netdump/Netdump.ino
@@ -29,26 +29,26 @@ File             tracefile;
 
 std::map<PacketType, int> packetCount;
 
-enum SerialOption {
+enum class SerialOption : uint8_t {
   AllFull,
   LocalNone,
   HTTPChar
 };
 
-void startSerial(int option) {
+void startSerial(SerialOption option) {
   switch (option) {
-    case AllFull : //All Packets, show packet summary.
+    case SerialOption::AllFull : //All Packets, show packet summary.
       nd.printDump(Serial, Packet::PacketDetail::FULL);
       break;
 
-    case LocalNone : // Only local IP traffic, full details
+    case SerialOption::LocalNone : // Only local IP traffic, full details
       nd.printDump(Serial, Packet::PacketDetail::NONE,
       [](Packet n) {
         return (n.hasIP(WiFi.localIP()));
       }
                   );
       break;
-    case HTTPChar : // Only HTTP traffic, show packet content as chars
+    case SerialOption::HTTPChar : // Only HTTP traffic, show packet content as chars
       nd.printDump(Serial, Packet::PacketDetail::CHAR,
       [](Packet n) {
         return (n.isHTTP());
@@ -79,7 +79,7 @@ void setup(void) {
   WiFi.begin(ssid, password);
 
   if (WiFi.waitForConnectResult() != WL_CONNECTED) {
-    Serial.println("WiFi Failed");
+    Serial.println("WiFi Failed, stopping sketch");
     while (1) {
       delay(1000);
     }
@@ -122,7 +122,7 @@ void setup(void) {
   webServer.serveStatic("/", *filesystem, "/");
   webServer.begin();
 
-  startSerial(AllFull); // Serial output examples, use enum SerialOption for selection
+  startSerial(SerialOption::AllFull); // Serial output examples, use enum SerialOption for selection
 
   //  startTcpDump();     // tcpdump option
   //  startTracefile();  // output to SPIFFS or LittleFS
diff --git a/libraries/Netdump/src/Netdump.cpp b/libraries/Netdump/src/Netdump.cpp
index 3adb32a9d0..1adb2b0948 100644
--- a/libraries/Netdump/src/Netdump.cpp
+++ b/libraries/Netdump/src/Netdump.cpp
@@ -89,7 +89,7 @@ void Netdump::tcpDump(WiFiServer &tcpDumpServer, const Filter nf)
 
     if (!packetBuffer)
     {
-        packetBuffer = new char[tcpBuffersize];
+        packetBuffer = new char[tcpBufferSize];
     }
     bufferIndex = 0;
 
@@ -162,7 +162,7 @@ void Netdump::tcpDumpProcess(const Packet& np)
     }
     size_t incl_len = np.getPacketSize() > maxPcapLength ? maxPcapLength : np.getPacketSize();
 
-    if (bufferIndex + 16 + incl_len < tcpBuffersize) // only add if enough space available
+    if (bufferIndex + 16 + incl_len < tcpBufferSize) // only add if enough space available
     {
         struct timeval tv;
         gettimeofday(&tv, nullptr);
diff --git a/libraries/Netdump/src/Netdump.h b/libraries/Netdump/src/Netdump.h
index bf16e7dd30..1011a8e955 100644
--- a/libraries/Netdump/src/Netdump.h
+++ b/libraries/Netdump/src/Netdump.h
@@ -77,7 +77,7 @@ class Netdump
     char* packetBuffer = nullptr;
     size_t bufferIndex = 0;
 
-    static constexpr int tcpBuffersize = 2048;
+    static constexpr int tcpBufferSize = 2048;
     static constexpr int maxPcapLength = 1024;
     static constexpr uint32_t pcapMagic = 0xa1b2c3d4;
 };
diff --git a/libraries/Netdump/src/NetdumpIP.cpp b/libraries/Netdump/src/NetdumpIP.cpp
index 2a1c9212af..d66459d801 100644
--- a/libraries/Netdump/src/NetdumpIP.cpp
+++ b/libraries/Netdump/src/NetdumpIP.cpp
@@ -28,10 +28,6 @@ NetdumpIP::NetdumpIP()
 {
 }
 
-NetdumpIP::~NetdumpIP()
-{
-}
-
 NetdumpIP::NetdumpIP(uint8_t first_octet, uint8_t second_octet, uint8_t third_octet, uint8_t fourth_octet)
 {
     setV4();
diff --git a/libraries/Netdump/src/NetdumpIP.h b/libraries/Netdump/src/NetdumpIP.h
index 73b668ac3c..8a450c374a 100644
--- a/libraries/Netdump/src/NetdumpIP.h
+++ b/libraries/Netdump/src/NetdumpIP.h
@@ -20,7 +20,6 @@ class NetdumpIP
 {
 public:
     NetdumpIP();
-    ~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);
diff --git a/libraries/Netdump/src/NetdumpPacket.h b/libraries/Netdump/src/NetdumpPacket.h
index af0d701619..a9cca76596 100644
--- a/libraries/Netdump/src/NetdumpPacket.h
+++ b/libraries/Netdump/src/NetdumpPacket.h
@@ -43,8 +43,6 @@ class Packet
         setPacketTypes();
     };
 
-    Packet() {};
-
     enum class PacketDetail
     {
         NONE,
diff --git a/libraries/Netdump/src/PacketType.cpp b/libraries/Netdump/src/PacketType.cpp
index 1bebea68ec..565aa55f0a 100644
--- a/libraries/Netdump/src/PacketType.cpp
+++ b/libraries/Netdump/src/PacketType.cpp
@@ -14,10 +14,6 @@ PacketType::PacketType()
 {
 }
 
-PacketType::~PacketType()
-{
-}
-
 String PacketType::toString() const
 {
     switch (ptype)
diff --git a/libraries/Netdump/src/PacketType.h b/libraries/Netdump/src/PacketType.h
index b6fb1db611..8f4aa5ce79 100644
--- a/libraries/Netdump/src/PacketType.h
+++ b/libraries/Netdump/src/PacketType.h
@@ -41,8 +41,6 @@ class PacketType
     PacketType();
     PacketType(PType pt) : ptype(pt) {};
 
-    ~PacketType();
-
     operator PType() const
     {
         return ptype;

From 8024a738a2a80d6f2084e105b51f3efbcdd79c55 Mon Sep 17 00:00:00 2001
From: hreintke <hreintke@tauri.nl>
Date: Fri, 21 Aug 2020 12:54:50 +0200
Subject: [PATCH 4/4] updates due to comments

---
 libraries/Netdump/src/Netdump.cpp       | 2 +-
 libraries/Netdump/src/NetdumpPacket.cpp | 2 +-
 libraries/Netdump/src/NetdumpPacket.h   | 2 +-
 tests/restyle.sh                        | 1 +
 4 files changed, 4 insertions(+), 3 deletions(-)

diff --git a/libraries/Netdump/src/Netdump.cpp b/libraries/Netdump/src/Netdump.cpp
index 1adb2b0948..a608a1c3b2 100644
--- a/libraries/Netdump/src/Netdump.cpp
+++ b/libraries/Netdump/src/Netdump.cpp
@@ -89,7 +89,7 @@ void Netdump::tcpDump(WiFiServer &tcpDumpServer, const Filter nf)
 
     if (!packetBuffer)
     {
-        packetBuffer = new char[tcpBufferSize];
+        packetBuffer = new (std::nothrow) char[tcpBufferSize];
     }
     bufferIndex = 0;
 
diff --git a/libraries/Netdump/src/NetdumpPacket.cpp b/libraries/Netdump/src/NetdumpPacket.cpp
index 2f9da6df93..4e2fcbaf6f 100644
--- a/libraries/Netdump/src/NetdumpPacket.cpp
+++ b/libraries/Netdump/src/NetdumpPacket.cpp
@@ -144,7 +144,7 @@ const PacketType Packet::packetType() const
     return thisPacketType;
 }
 
-const std::vector<PacketType> Packet::allPacketTypes() const
+const std::vector<PacketType>& Packet::allPacketTypes() const
 {
     return thisAllPacketTypes;
 }
diff --git a/libraries/Netdump/src/NetdumpPacket.h b/libraries/Netdump/src/NetdumpPacket.h
index a9cca76596..a898ef230f 100644
--- a/libraries/Netdump/src/NetdumpPacket.h
+++ b/libraries/Netdump/src/NetdumpPacket.h
@@ -280,7 +280,7 @@ class Packet
     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;
+    const std::vector<PacketType>& allPacketTypes() const;
 
 
 private:
diff --git a/tests/restyle.sh b/tests/restyle.sh
index 86c1f337d8..c50c5f6413 100755
--- a/tests/restyle.sh
+++ b/tests/restyle.sh
@@ -14,6 +14,7 @@ all="
 libraries/ESP8266mDNS
 libraries/Wire
 cores/esp8266/core_esp8266_si2c.cpp
+libraries/Netdump
 "
 
 # core