Skip to content
32 changes: 32 additions & 0 deletions astyle_goodies.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# Code formatting rules for Arduino examples, taken from:
#
# https://github.com/arduino/Arduino/blob/master/build/shared/examples_formatter.conf
#

mode=c
lineend=linux
style=allman

# 4 spaces indentation
indent=spaces=4

# also indent macros
#indent-preprocessor

# indent classes, switches (and cases), comments starting at column 1
indent-col1-comments

# put a space around operators
pad-oper

# put a space after if/for/while
pad-header

# if you like one-liners, keep them
keep-one-line-statements

attach-closing-while
unpad-paren
pad-oper
remove-comment-prefix
add-braces
75 changes: 75 additions & 0 deletions examples/NetDumpTest.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
// Do not remove the include below
#include "NetDumpTest.h"
#include <ESP8266WiFi.h>
#include "LocalDefines.h"
#include <ESP8266WebServer.h>
#include <Netdump/Netdump.h>
#include <FS.h>

/*
dump network packets on serial console
released to the public domain
*/


Netdump nd;
ESP8266WebServer server(80);
WiFiServer ws(8000);


void handleRoot() {
static int rq = 0;
String a = "<h1>You are connected, rq = "+String(rq++)+"</h1>";
server.send(200, "text/html", a);
}


File outfile = SPIFFS.open("test", "w");

void setup(void) {
Serial.begin(115200);

WiFi.mode(WIFI_STA);
WiFi.begin(ssid,password);
SPIFFS.begin();

server.on("/", handleRoot);
server.begin();

/*
// To serial, include hex print only localIP traffic
nd.printDump(Serial, true,
[](NetdumpPacket n)
{
return ((n.ethType() != 0x8912) &&
((n.sourceIP()==WiFi.localIP()) || n.destIP()==WiFi.localIP()) );
});
*/

/*
// To serial, include hex print only localIP traffic
nd.printDump(Serial, false); // To serial all traffic, no hex dump
*/

/*
nd.printDump(outfile, false); // To file all traffic, no hex dump, format ascii
*/

/*
nd.fileDump(outfile, false); // To file all traffic, no hex dump, format pcap file
*/

/*
// To telnet, all traffic, use `n 10.0.0.212 8000 | tcpdump -r -`
ws.begin();
nd.tcpDump(ws);

*/


}

void loop(void) {
server.handleClient();

}
File renamed without changes.
198 changes: 198 additions & 0 deletions src/Netdump/NetDump.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,198 @@
/*
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>

Netdump* Netdump::self;

void Netdump::setCallback(NetdumpCallback nc)
{
netDumpCallback = nc;
}
void Netdump::setCallback(NetdumpCallback nc, NetdumpFilter nf)
{
netDumpFilter = nf;
netDumpCallback = nc;
}
void Netdump::setFilter(NetdumpFilter nf)
{
netDumpFilter = nf;
}
void Netdump::reset()
{
setCallback(nullptr, nullptr);
}
void Netdump::printDump(Print& out, NetdumpPacket::PacketDetail ndd, NetdumpFilter nf)
{
out.printf("netDump starting\r\n");
setCallback(std::bind(&Netdump::printDumpProcess, this, std::ref(out), ndd, std::placeholders::_1), nf);
// setCallback([out,ndd](NetdumpPacket& ndp){printDumpProcess(out,ndd,ndp);});
setCallback([&out, ndd, this](NetdumpPacket & ndp)
{
printDumpProcess(out, ndd, ndp);
}, nf);


}
void Netdump::fileDump(File outfile, NetdumpFilter nf)
{

char buf[24];

*(uint32_t*)&buf[0] = 0xa1b2c3d4;
*(uint32_t*)&buf[4] = 0x00040002;
*(uint32_t*)&buf[8] = 0;
*(uint32_t*)&buf[12] = 0;
*(uint32_t*)&buf[16] = 1024;
*(uint32_t*)&buf[20] = 1;

outfile.write(buf, 24);
// setCallback( std::bind(&Netdump::fileDumpProcess, this, outfile, std::placeholders::_1));
setCallback([outfile, this](NetdumpPacket & ndp)
{
fileDumpProcess(outfile, ndp);
}, nf);
}
void Netdump::tcpDump(WiFiServer &tcpDumpServer, NetdumpFilter nf)
{
// Get initialize code from netdumpout.cpp
if (packetBuffer)
{
delete packetBuffer;
}
packetBuffer = new char[2048];
bufferIndex = 0;

// schedule_function(std::bind(&Netdump::tcpDumpLoop,this,std::ref(tcpDumpServer)));
schedule_function([&tcpDumpServer, this]()
{
tcpDumpLoop(tcpDumpServer);
});
Serial.printf("scheduled\r\n");
}

void Netdump::capture(int netif_idx, const char* data, size_t len, int out, int success)
{
NetdumpPacket np(netif_idx, data, len, out, success);
if (self->netDumpCallback)
{
if (self->netDumpFilter && !self->netDumpFilter(np))
{
return;
}
self->netDumpCallback(np);
}
}

void Netdump::printDumpProcess(Print& out, NetdumpPacket::PacketDetail ndd, NetdumpPacket np)
{
out.printf("%8d %s", millis(), np.toString(ndd).c_str());
}
void Netdump::fileDumpProcess(File outfile, NetdumpPacket np)
{
size_t incl_len = np.len > 1024 ? 1024 : np.len;
char buf[16];

struct timeval tv;
gettimeofday(&tv, nullptr);
*(uint32_t*)&buf[0] = tv.tv_sec;
*(uint32_t*)&buf[4] = tv.tv_usec;
*(uint32_t*)&buf[8] = incl_len;
*(uint32_t*)&buf[12] = np.len;
outfile.write(buf, 16);

outfile.write(np.data, incl_len);
}
void Netdump::tcpDumpProcess(NetdumpPacket np)
{
// Get capture code from netdumpout.cpp
if (np.isIPv4() && np.isTCP()
&& ((np.out && np.getSrcPort() == tcpDumpClient.localPort())
|| (!np.out && np.getDstPort() == tcpDumpClient.localPort())
)
)
{
// skip myself
return;
}
size_t incl_len = np.len > 1024 ? 1024 : np.len;

struct timeval tv;
gettimeofday(&tv, nullptr);
*(uint32_t*)&packetBuffer[bufferIndex] = tv.tv_sec;
*(uint32_t*)&packetBuffer[bufferIndex + 4] = tv.tv_usec;
*(uint32_t*)&packetBuffer[bufferIndex + 8] = incl_len;
*(uint32_t*)&packetBuffer[bufferIndex + 12] = np.len;
bufferIndex += 16;
memcpy(&packetBuffer[bufferIndex], np.data, incl_len);
bufferIndex += incl_len;
if (bufferIndex && tcpDumpClient && tcpDumpClient.availableForWrite() >= bufferIndex)
{
tcpDumpClient.write(packetBuffer, bufferIndex);
bufferIndex = 0;
}


}
void Netdump::tcpDumpLoop(WiFiServer &tcpDumpServer)
{

if (tcpDumpServer.hasClient())
{
tcpDumpClient = tcpDumpServer.available();
//if (fastsend)
tcpDumpClient.setNoDelay(true);


// pcap-savefile(5) capture preamble
*(uint32_t*)&packetBuffer[0] = 0xa1b2c3d4;
*(uint32_t*)&packetBuffer[4] = 0x00040002;
*(uint32_t*)&packetBuffer[8] = 0;
*(uint32_t*)&packetBuffer[12] = 0;
*(uint32_t*)&packetBuffer[16] = 1024;
*(uint32_t*)&packetBuffer[20] = 1;
tcpDumpClient.write(packetBuffer, 24);
bufferIndex = 0;
// setCallback(std::bind(&Netdump::tcpDumpProcess,this,std::placeholders::_1));
setCallback([this](NetdumpPacket & ndp)
{
tcpDumpProcess(ndp);
});

Serial.printf("client started\r\n");
}
if (!tcpDumpClient || !tcpDumpClient.connected())
{
setCallback(nullptr);
}
if (bufferIndex && tcpDumpClient && tcpDumpClient.availableForWrite() >= bufferIndex)
{
Serial.printf("tcp write %d\r\n", bufferIndex);
tcpDumpClient.write(packetBuffer, bufferIndex);
bufferIndex = 0;
}
// schedule_function(std::bind(&Netdump::tcpDumpLoop,this,std::ref(tcpDumpServer)));
schedule_function([&tcpDumpServer, this]()
{
tcpDumpLoop(tcpDumpServer);
});
}
Loading