22 Commits

Author SHA1 Message Date
6e05a0b45c Merge branch 'release-1.0' 2021-11-29 15:55:27 +01:00
d14e469ef4 Removed error-logging from RegexBlockStream FIXME 2021-11-29 15:35:53 +01:00
99a3e13d77 Added further exception to error-event from tcpdump 2021-11-29 15:35:36 +01:00
b5c895674e Merge branch 'f_gracefulShutdown' into dev 2021-11-29 15:34:56 +01:00
86d2b8c1cf Added event for SIGTERM and SIGINT 2021-11-29 15:34:19 +01:00
7ff6556d51 Merge branch 'f_userHelper' into dev 2021-11-29 15:12:39 +01:00
16388c73e5 Added additional check for packetStream 2021-11-29 15:11:14 +01:00
8211f55b89 Added check for tcpdump-process stdout 2021-11-29 15:10:42 +01:00
c28bbaaada Moved Stream-creations outside 2021-11-29 15:09:59 +01:00
4ddbe3f06f Implemented userHelper methods to detect if streams have data before timeout 2021-11-29 15:09:21 +01:00
0d84079ce1 Added packetType to tag-fields 2021-11-29 14:20:29 +01:00
1bf761970f Added error-handling for regexBlockStream 2021-11-29 13:45:36 +01:00
5a0118aedd Added error-handling for process 2021-11-29 13:45:15 +01:00
0709db0ddf Changed exit-log to debug 2021-11-29 13:44:37 +01:00
c27761322c Catch start-error from tcpdump
tcpdump writes to stderr at the beginning
2021-11-29 13:18:29 +01:00
45a11753de Add own logger for tcpdump 2021-11-29 13:16:23 +01:00
d482001cdc Merge branch 'f_docker' into dev 2021-11-29 13:12:00 +01:00
a681bbd2d2 Removed sudo as container runs as root anyways 2021-11-29 13:11:11 +01:00
d9ee804c3b Removed src-references as hats the workdir 2021-11-29 13:10:44 +01:00
e320d8670b Add installation of package tcpdump 2021-11-29 13:10:05 +01:00
2d824543d1 fixed cmd 2021-11-29 13:09:49 +01:00
6e080907d1 Merge branch 'code-smell_handling' into dev 2021-11-29 09:58:04 +01:00
5 changed files with 108 additions and 13 deletions

View File

@@ -7,7 +7,11 @@ WORKDIR /usr/src/app
COPY package*.json ./ COPY package*.json ./
RUN npm install RUN npm install
RUN apt-get update
RUN apt-get -y install \
tcpdump
# Bundle app source # Bundle app source
COPY ./src/ . COPY ./src/ .
CMD ["npm", "run"] CMD ["npm", "run", "start"]

View File

@@ -2,10 +2,10 @@
"name": "rfmon-to-influx", "name": "rfmon-to-influx",
"version": "1.0.0", "version": "1.0.0",
"description": "Writing (mostly meta-) data received in Wireless-Monitor-Mode into an InfluxDB", "description": "Writing (mostly meta-) data received in Wireless-Monitor-Mode into an InfluxDB",
"main": "src/main.js", "main": "main.js",
"scripts": { "scripts": {
"test": "echo \"Error: no test specified\" && exit 1", "test": "echo \"Error: no test specified\" && exit 1",
"start": "node src/main.js" "start": "node main.js"
}, },
"repository": { "repository": {
"type": "git", "type": "git",

46
src/helper/userHelper.js Normal file
View File

@@ -0,0 +1,46 @@
// This file specifies functions to help a user with e.g. configuration-errors
function detectStreamData(stream, timeout = 5000){
return new Promise((resolve, reject) => {
let timeoutHandler;
if(timeout){
timeoutHandler = setTimeout(() => {
reject('timeout');
remListeners();
},
timeout);
}
function remListeners(){
stream.removeListener('error', errorHandler);
stream.removeListener('data', dataHandler);
if(timeoutHandler) clearTimeout(timeoutHandler);
}
function errorHandler(err) {
remListeners();
}
function dataHandler(data) {
resolve(data);
remListeners();
}
stream.on('error', errorHandler);
stream.on('data', dataHandler);
});
}
function detectStreamsData(streams, timeout = 5000){
let promises = [];
streams.forEach((stream) => {
promises.push(detectStreamData(stream, timeout));
})
return promises;
}
// Specify exports
module.exports = {
detectStreamData,
detectStreamsData,
};

View File

@@ -1,5 +1,6 @@
"use strict"; "use strict";
const logger = require("./helper/logger.js")("main"); const logFactory = require("./helper/logger.js");
const logger = logFactory("main");
const { requireEnvVars } = require("./helper/env.js"); const { requireEnvVars } = require("./helper/env.js");
const { exit } = require("process"); const { exit } = require("process");
@@ -13,6 +14,9 @@ const { PacketStreamFactory } = require("./streamHandler/PacketStreamFactory.js"
const { PacketInfluxPointFactory } = require("./streamHandler/PacketInfluxPointFactory.js"); const { PacketInfluxPointFactory } = require("./streamHandler/PacketInfluxPointFactory.js");
const { InfluxPointWriter } = require("./streamHandler/InfluxPointWriter.js"); const { InfluxPointWriter } = require("./streamHandler/InfluxPointWriter.js");
const userHelper = require("./helper/userHelper.js");
/// Setup ENVs /// Setup ENVs
const env = process.env; const env = process.env;
// Defaults // Defaults
@@ -56,32 +60,72 @@ if(errorMsg){
logger.info("Starting tcpdump.."); logger.info("Starting tcpdump..");
const TCPDUMP_BASECMD = "tcpdump -vvv -e -n -X -s0 -i" const TCPDUMP_BASECMD = "tcpdump -vvv -e -n -X -s0 -i"
let cmd = `sudo ${TCPDUMP_BASECMD} ${env.WIFI_INTERFACE}`; let cmd = `${TCPDUMP_BASECMD} ${env.WIFI_INTERFACE}`;
let proc = exec(cmd); let proc = exec(cmd);
logger.debug("Creating & Attaching streams.."); logger.debug("Creating & Attaching streams..");
let regexBlockStream = new RegexBlockStream(/^\d{2}:\d{2}:\d{2}.\d{6}.*(\n( {4,8}|\t\t?).*)+\n/gm);
let packetStreamFactory = new PacketStreamFactory();
let packetInfluxPointFactory = new PacketInfluxPointFactory();
let influxPointWriter = new InfluxPointWriter(influxDb, env.INFLUX_ORG, env.INFLUX_BUCKET);
proc.stdout proc.stdout
.setEncoding("utf8") .setEncoding("utf8")
.pipe(new RegexBlockStream(/^\d{2}:\d{2}:\d{2}.\d{6}.*(\n( {4,8}|\t\t?).*)+\n/gm)) .pipe(regexBlockStream)
.pipe(new PacketStreamFactory()) .pipe(packetStreamFactory)
.pipe(new PacketInfluxPointFactory()) .pipe(packetInfluxPointFactory)
.pipe(new InfluxPointWriter(influxDb, env.INFLUX_ORG, env.INFLUX_BUCKET)); .pipe(influxPointWriter);
logger.debug("Attaching error-logger.."); logger.debug("Attaching error-logger..");
const loggerTcpdump = logFactory("tcpdump");
proc.stderr.setEncoding("utf8").on("data", (data) => { proc.stderr.setEncoding("utf8").on("data", (data) => {
logger.error(data); if(!data.match(/^(tcpdump: )?listening on /i) || !data.match(/^\d+ packets captured/i)) { // Catch start-error
loggerTcpdump.debug(data);
}
else loggerTcpdump.error(data);
}); });
// FIXME: This is a hacky workaround to not let errors from subprocess bubble up and terminate our process
regexBlockStream.on('error', (err) => {});
proc.on("error", (err) => {
loggerTcpdump.error(err);
});
const loggerPacketStream = logFactory("PacketStreamFactory");
userHelper.detectStreamData(proc.stdout, 10000) // Expect tcpdump-logs to have data after max. 10s
.then(() => {
loggerTcpdump.debug("Got first data");
userHelper.detectStreamData(packetStreamFactory, 10000) // Expect then to have packets after further 10s
.then(() => {
loggerPacketStream.debug("Got first packet");
})
.catch((err) => {
if(err == 'timeout') loggerPacketStream.warn("No packets");
});
})
.catch((err) => {
if(err == 'timeout') loggerTcpdump.warn("No data after 10s! Wrong configuration?");
});
logger.debug("Attaching exit-handler.."); logger.debug("Attaching exit-handler..");
proc.on("exit", (code) => { proc.on("exit", (code) => {
logger.info(`tcpdump exited code: ${code}`); loggerTcpdump.debug(`tcpdump exited code: ${code}`);
if (code) { if (code) {
logger.fatal(`tcpdump exited with non-zero code: ${code}`); loggerTcpdump.fatal(`tcpdump exited with non-zero code: ${code}`);
exit(1); exit(1);
} }
logger.info("Shutdown"); logger.info("Shutdown");
exit(0); exit(0);
}); });
// Handle stop-signals for graceful shutdown
function shutdownReq() {
logger.info("Shutdown request received..");
logger.debug("Stopping subprocess tcpdump, then exiting myself..");
proc.kill(); // Kill process (send SIGTERM), then upper event-handler will stop self
}
process.on('SIGTERM', shutdownReq);
process.on('SIGINT', shutdownReq);
logger.info("Startup complete"); logger.info("Startup complete");
})(); })();

View File

@@ -9,6 +9,7 @@ const TAG_LIST = [
"bssid", "bssid",
"frequency", "frequency",
"flags", "flags",
"packetType",
]; ];
/** Measurement-name and corresponding field-key */ /** Measurement-name and corresponding field-key */