Created
March 1, 2014 14:42
-
-
Save jplitza/9290756 to your computer and use it in GitHub Desktop.
FFMap backend in NodeJS
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env nodejs | |
var fs = require('fs'); | |
var _ = require('underscore'); | |
var RRD = require('rrd').RRD; | |
var argv = require('optimist') | |
.usage('Usage: $0 -b <batvis file> -a <alias file> <destination dir>') | |
.options('b', {alias: 'batvis', describe: 'File containing output of batadv-vis -f jsondoc', demand: true, string: true}) | |
.options('d', {alias: 'details', describe: 'File containing details sent by the nodes', demand: true, string: true}) | |
.argv; | |
var batvis, details; | |
var inputs = 2; | |
var directory = argv._[0]; | |
var macmap = {}; | |
var nodes = []; | |
if(!directory) { | |
console.error("Missing target directory!"); | |
process.exit(1); | |
} | |
function fuzz_mac_address(addr) { | |
var fuzzes = [ | |
addr, | |
(parseInt(addr.substr(0,2), 16) ^ 2).toString(16) + addr.substr(2), | |
addr.substr(0, 9) + ((parseInt(addr.substr(9, 2), 16) + 1) % 0x100).toString(16) + addr.substr(11), | |
(parseInt(addr.substr(0,2), 16) ^ 2).toString(16) + addr.substr(2, 7) + ((parseInt(addr.substr(9, 2), 16) + 1) % 0x100).toString(16) + addr.substr(11), | |
addr.substr(0, 9) + ((parseInt(addr.substr(9, 2), 16) - 1) % 0x100).toString(16) + addr.substr(11), | |
(parseInt(addr.substr(0,2), 16) ^ 2).toString(16) + addr.substr(2, 7) + ((parseInt(addr.substr(9, 2), 16) - 1) % 0x100).toString(16) + addr.substr(11), | |
]; | |
return fuzzes; | |
} | |
function vpn_neighbors(neighbors) { | |
var counter = 0; | |
for(var i = 0; i < neighbors.length; i++) { | |
if(details[macmap[neighbors[i].neighbor]].vpn) | |
counter++; | |
} | |
return counter; | |
} | |
function create_or_update_rrds(node) { | |
var nodedir = directory + "/" + node.macs[0]; | |
fs.mkdir(nodedir, 0755, function() { | |
for(var rrd_name in rrds) { | |
create_or_update_rrd(rrd_name, node); | |
} | |
}); | |
} | |
function create_or_update_rrd(rrd_name, node) { | |
// XXX: Sanitise filename! | |
var filename = directory + "/" + node.macs[0] + "/" + rrd_name + ".rrd"; | |
var rrd = new RRD(filename); | |
var values = _.map(rrds[rrd_name], function(ds) { | |
try { | |
return eval(ds.attr); | |
} catch(e) { | |
return null; | |
} | |
}); | |
rrd.update(new Date, values, function(err, out) { | |
if(out == null) { | |
console.log_bak = console.log; | |
console.log = function() {}; | |
rrd.create(rras.concat(_.map(rrds[rrd_name], function(ds) { return ds.DS; })), {}, function(err, out) { | |
if(out == null) { | |
console.error("Error creating " + filename); | |
console.error(err) | |
return false; | |
} | |
rrd.update(new Date, values, function(err, out) {}); | |
}); | |
console.log = console.log_bak; | |
} | |
}); | |
} | |
var rras = [ | |
"RRA:AVERAGE:0.5:1:360", // 30 hours of 5 minute samples | |
"RRA:AVERAGE:0.5:12:192", // 8 days of 1 hour samples | |
"RRA:AVERAGE:0.5:36:224", // 4 weeks of 3 hour samples | |
"RRA:AVERAGE:0.5:144:365", // half a year of 12 hour samples | |
] | |
var rrds = { | |
"uptime": [{attr: "node.statistics.uptime", DS: "DS:uptime:GAUGE:600:0:U"}], | |
"loadavg": [{attr: "node.statistics.loadavg", DS: "DS:loadavg:GAUGE:600:0:U"}], | |
"traffic_bytes": [ | |
{attr: "node.statistics.traffic.rx.bytes", DS: "DS:rx:DERIVE:600:0:U"}, | |
{attr: "node.statistics.traffic.tx.bytes", DS: "DS:tx:DERIVE:600:0:U"}, | |
{attr: "node.statistics.traffic.mgmt_rx.bytes", DS: "DS:mgmt_rx:DERIVE:600:0:U"}, | |
{attr: "node.statistics.traffic.mgmt_tx.bytes", DS: "DS:mgmt_tx:DERIVE:600:0:U"}, | |
{attr: "node.statistics.traffic.forward.bytes", DS: "DS:forward:DERIVE:600:0:U"}, | |
], | |
"traffic_packets": [ | |
{attr: "node.statistics.traffic.rx.packets", DS: "DS:rx:DERIVE:600:0:U"}, | |
{attr: "node.statistics.traffic.tx.packets", DS: "DS:tx:DERIVE:600:0:U"}, | |
{attr: "node.statistics.traffic.mgmt_rx.packets", DS: "DS:mgmt_rx:DERIVE:600:0:U"}, | |
{attr: "node.statistics.traffic.mgmt_tx.packets", DS: "DS:mgmt_tx:DERIVE:600:0:U"}, | |
{attr: "node.statistics.traffic.forward.packets", DS: "DS:forward:DERIVE:600:0:U"}, | |
], | |
"clients": [{attr: "node.clients.length-1", DS: "DS:clients:GAUGE:600:0:U"}], | |
"neighbors": [ | |
{attr: "node.neighbors.length", DS: "DS:neighbors:GAUGE:600:0:U"}, | |
{attr: "vpn_neighbors(node.neighbors)", DS: "DS:vpn_neighbors:GAUGE:600:0:U"}, | |
], | |
}; | |
function merge() { | |
var vis = batvis.vis; | |
for(var i = 0; i < vis.length; i++) { | |
var macs = [vis[i].primary]; | |
if(vis[i].secondary) | |
macs = macs.concat(vis[i].secondary); | |
macloop: for(var j = 0; j < macs.length; j++) { | |
var fuzzes = fuzz_mac_address(macs[j]); | |
for(var k = 0; k < fuzzes.length; k++) { | |
if(fuzzes[k] in details) { | |
macs.unshift(fuzzes[k]); | |
break macloop; | |
} | |
} | |
} | |
for(var j = 0; j < macs.length; j++) { | |
macmap[macs[j]] = macs[0]; | |
} | |
if(!details[macs[0]]) | |
details[macs[0]] = {}; | |
for(var property in vis[i]) { | |
details[macs[0]][property] = vis[i][property]; | |
} | |
details[macs[0]].macs = macs; | |
nodes.push(details[macs[0]]); | |
} | |
fs.writeFile(directory + "/nodes.json", JSON.stringify(nodes), {mode: 0644}, function(err) { | |
if(err) throw err; | |
}); | |
for(var i = 0; i < nodes.length; i++) { | |
create_or_update_rrds(nodes[i], nodes); | |
} | |
} | |
fs.readFile(argv.batvis, 'utf-8', function(err, data) { | |
if (err) throw err; | |
batvis = JSON.parse(data); | |
if(--inputs == 0) merge(); | |
}); | |
fs.readFile(argv.details, 'utf-8', function(err, data) { | |
if (err) throw err; | |
details = JSON.parse(data); | |
if(--inputs == 0) merge(); | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment