mirror of
https://github.com/Ysurac/openmptcprouter-feeds.git
synced 2025-03-09 15:40:03 +00:00
Add luci-app-packet-capture
This commit is contained in:
parent
19dde3a38a
commit
93694b5983
9 changed files with 489 additions and 2 deletions
|
@ -0,0 +1,287 @@
|
|||
'use strict';
|
||||
'require rpc';
|
||||
'require uci';
|
||||
'require ui';
|
||||
'require fs';
|
||||
'require form';
|
||||
'require network';
|
||||
'require tools.widgets as widgets';
|
||||
|
||||
var eventSource,
|
||||
captureFilePoll,
|
||||
hostName;
|
||||
|
||||
function stopTcpdump() {
|
||||
fs.exec("/usr/libexec/packet_capture_stop").then(function(replay) {
|
||||
if (eventSource)
|
||||
eventSource.close();
|
||||
}.bind(this)).catch(function(error) {
|
||||
console.log(error);
|
||||
});
|
||||
}
|
||||
|
||||
window.addEventListener('beforeunload', stopTcpdump);
|
||||
|
||||
var callLuciProcessList = rpc.declare({
|
||||
object: 'luci',
|
||||
method: 'getProcessList',
|
||||
expect: { result: [] }
|
||||
});
|
||||
|
||||
var callInitAction = rpc.declare({
|
||||
object: 'luci',
|
||||
method: 'setInitAction',
|
||||
params: [ 'name', 'action' ],
|
||||
expect: { result: false }
|
||||
});
|
||||
|
||||
function addOutput() {
|
||||
var tcpdumpOut = document.querySelectorAll('[id$="tcpdump_out"]')[0];
|
||||
if (tcpdumpOut)
|
||||
return;
|
||||
|
||||
var frameEl = E('div', {'class': 'cbi-value'});
|
||||
|
||||
frameEl.appendChild(E('textarea', {
|
||||
'id': 'tcpdump_out',
|
||||
'class': 'cbi-input-textarea',
|
||||
'readonly': '',
|
||||
'style': 'width:100%',
|
||||
'rows': 30,
|
||||
}));
|
||||
|
||||
frameEl.firstElementChild.style.fontFamily = 'monospace';
|
||||
|
||||
var downloadBtn = document.querySelectorAll('[id$="download_file"]')[0];
|
||||
if (downloadBtn)
|
||||
downloadBtn.parentNode.insertBefore(frameEl, downloadBtn.nextSibling);
|
||||
}
|
||||
|
||||
var downloadCaptureFile = function(ev) {
|
||||
var form = E('form', {
|
||||
method: 'post',
|
||||
action: '/cgi-bin/cgi-download',
|
||||
enctype: 'application/x-www-form-urlencoded'
|
||||
}, E('input', { type: 'hidden', name: 'sessionid', value: rpc.getSessionID()},
|
||||
E('input', { type: 'hidden', name: 'path', value: "/tmp/capture.pcap"},
|
||||
E('input', { type: 'hidden', name: 'filename', value: hostName + "-" + Date.now() + ".pcap"},
|
||||
E('input', { type: 'hidden', name: 'mimetype', value: 'application/vnd.tcpdump.pcap'}
|
||||
)))));
|
||||
|
||||
ev.currentTarget.parentNode.appendChild(form);
|
||||
form.submit();
|
||||
form.parentNode.removeChild(form);
|
||||
}
|
||||
|
||||
function subscribeTcpdump() {
|
||||
if (eventSource)
|
||||
eventSource.close();
|
||||
|
||||
eventSource = new EventSource('/ubus/subscribe/tcpdump' + '?' + rpc.getSessionID());
|
||||
eventSource.onerror = function(event) {
|
||||
eventSource.close();
|
||||
console.log(event);
|
||||
};
|
||||
|
||||
addOutput();
|
||||
var textOut = document.querySelectorAll('[id$="tcpdump_out"]')[0];
|
||||
textOut.value = "";
|
||||
eventSource.addEventListener("tcpdump.data", function(event) {
|
||||
textOut.value = textOut.value + "\n" + JSON.parse(event.data).data;
|
||||
});
|
||||
}
|
||||
|
||||
function updateButtons() {
|
||||
var tasks = [];
|
||||
tasks.push(fs.stat("/var/run/packet_capture.pid").then(L.bind(function(res) {
|
||||
var downloadBtn = document.querySelectorAll('[id$="download_file"]')[0];
|
||||
if (!downloadBtn)
|
||||
return;
|
||||
if (!eventSource || eventSource.readyState == 2)
|
||||
subscribeTcpdump();
|
||||
var textOut = document.querySelectorAll('[id$="tcpdump_out"]')[0];
|
||||
if (textOut)
|
||||
textOut.style.borderColor = "green";
|
||||
var startBtn = document.querySelectorAll('[id$="start_tcpdump"]')[0];
|
||||
if (startBtn)
|
||||
startBtn.hidden = true;
|
||||
var stopBtn = document.querySelectorAll('[id$="stop_tcpdump"]')[0];
|
||||
if (stopBtn)
|
||||
stopBtn.hidden = false;
|
||||
return;
|
||||
})).catch(function(error) {
|
||||
var textOut = document.querySelectorAll('[id$="tcpdump_out"]')[0];
|
||||
if (textOut)
|
||||
textOut.style.borderColor = "red";
|
||||
var startBtn = document.querySelectorAll('[id$="start_tcpdump"]')[0];
|
||||
if (startBtn)
|
||||
startBtn.hidden = false;
|
||||
var stopBtn = document.querySelectorAll('[id$="stop_tcpdump"]')[0];
|
||||
if (stopBtn)
|
||||
stopBtn.hidden = true;
|
||||
if (eventSource)
|
||||
eventSource.close();
|
||||
}));
|
||||
|
||||
return Promise.all(tasks);
|
||||
}
|
||||
|
||||
function updatePollCheckCaptureFileExists() {
|
||||
checkCaptureFileExists();
|
||||
L.Poll.remove(captureFilePoll);
|
||||
L.Poll.add(L.bind(checkCaptureFileExists, m),5);
|
||||
}
|
||||
|
||||
function checkCaptureFileExists() {
|
||||
var tasks = [];
|
||||
tasks.push(fs.stat("/tmp/capture.pcap").then(L.bind(function(res) {
|
||||
var downloadBtn = document.querySelector('[data-action="download"]');
|
||||
if (!downloadBtn)
|
||||
return;
|
||||
var downloadCheckBox = document.querySelectorAll('[data-widget-id$="file"]')[0].checked;
|
||||
if (!downloadCheckBox) {
|
||||
fs.remove("/tmp/capture.pcap").then(function(replay) {
|
||||
downloadBtn.disabled = true;;
|
||||
}.bind(this)).catch(function(error) {
|
||||
console.log(error);
|
||||
});
|
||||
} else {
|
||||
downloadBtn.disabled = false;
|
||||
}
|
||||
})).catch(function(error) {
|
||||
var downloadBtn = document.querySelector('[data-action="download"]');
|
||||
if (downloadBtn)
|
||||
downloadBtn.disabled = true;
|
||||
}));
|
||||
|
||||
return Promise.all(tasks);
|
||||
}
|
||||
|
||||
return L.view.extend({
|
||||
|
||||
load: function() {
|
||||
return Promise.all([
|
||||
uci.load('system')
|
||||
]);
|
||||
},
|
||||
|
||||
handleDownload: function(ev) {
|
||||
downloadCaptureFile(ev);
|
||||
},
|
||||
|
||||
render: function(processes) {
|
||||
var m, s, o;
|
||||
|
||||
hostName = uci.get('system', '@system[0]', 'hostname');
|
||||
|
||||
m = new form.Map('packet_capture', _('Packet Capture - Tcpdump'), _('Capture packets with tcpdump.'));
|
||||
s = m.section(form.TypedSection, 'tcpdump');
|
||||
s.anonymous = 1;
|
||||
|
||||
o = s.option(widgets.DeviceSelect, 'interface', _('Interface'), _(''));
|
||||
o.noaliases = true;
|
||||
o.modalonly = true;
|
||||
o.rmempty = false;
|
||||
o.filter = function(section_id, value) {
|
||||
return true;
|
||||
}
|
||||
|
||||
o = s.option(form.Value, 'filter', _('Filter'), _('Tcpdump filter like protocol, port etc.'));
|
||||
o.modalonly = false;
|
||||
o.datatype = 'and(minlength(1),maxlength(1024))';
|
||||
|
||||
o = s.option(form.Value, 'duration', _('Duration'), _('Duration of packet capturing in seconds.'));
|
||||
o.modalonly = false;
|
||||
o.datatype = 'range(1,4294967296)';
|
||||
|
||||
o = s.option(form.Value, 'packets', _('Packets'), _('Number of packets to be captured.'));
|
||||
o.modalonly = false;
|
||||
o.datatype = 'range(1,4294967296)';
|
||||
|
||||
o = s.option(form.Flag, 'domains', _('Resolve domains'), _("Convert host addresses to names."));
|
||||
|
||||
o = s.option(form.Flag, 'verbose', _('Verbose output'), _("Print the link-level header on each dump line."));
|
||||
|
||||
o = s.option(form.Flag, 'file', _('Save to file'), _("Save capture to pcap file."));
|
||||
|
||||
o = s.option(form.Button, 'start_tcpdump', _('Start tcpdump'), _(''));
|
||||
o.inputstyle = 'apply';
|
||||
o.onclick = ui.createHandlerFn(this, function(section_id, ev) {
|
||||
var downloadBtn = document.querySelector('[data-action="download"]');
|
||||
if (!downloadBtn)
|
||||
return;
|
||||
fs.remove("/tmp/capture.pcap").then(function(replay) {
|
||||
downloadBtn.disabled = true;;
|
||||
}.bind(this)).catch(function(error) {
|
||||
console.log(error);
|
||||
});
|
||||
|
||||
var iface = document.querySelectorAll('[id$="interface"]')[1].value,
|
||||
filter = document.querySelectorAll('[id$="filter"]')[2].value,
|
||||
packets = document.querySelectorAll('[id$="packets"]')[2].value,
|
||||
duration = document.querySelectorAll('[id$="duration"]')[2].value,
|
||||
verbose = document.querySelectorAll('[data-widget-id$="verbose"]')[0].checked,
|
||||
domains = document.querySelectorAll('[data-widget-id$="domains"]')[0].checked,
|
||||
file = document.querySelectorAll('[data-widget-id$="file"]')[0].checked
|
||||
|
||||
var args = {
|
||||
"interface": iface,
|
||||
"filter": filter,
|
||||
"packets": packets,
|
||||
"duration": duration,
|
||||
"verbose": verbose,
|
||||
"domains": domains,
|
||||
"file": file
|
||||
}
|
||||
|
||||
return fs.exec_direct('/usr/libexec/packet_capture_start', [JSON.stringify(args)]).then(function(replay) {
|
||||
var error_position = replay.search("error:");
|
||||
if (error_position != -1){
|
||||
ui.showModal(_(replay.substring(error_position + 6, replay.length)), [
|
||||
E('div', { 'class': 'right' }, [
|
||||
E('button', {
|
||||
'class': 'cbi-button cbi-button-negative important',
|
||||
'click': function(ev) {
|
||||
ui.hideModal();
|
||||
}
|
||||
}, _('Close')),
|
||||
])
|
||||
]);
|
||||
return;
|
||||
}
|
||||
rpc.list.apply(rpc).then(function(res) {
|
||||
for (var k in res) {
|
||||
if (res[k] == "tcpdump" )
|
||||
subscribeTcpdump()
|
||||
}
|
||||
}.bind(this));
|
||||
}.bind(this)).catch(function(error) {
|
||||
console.log(error);
|
||||
});
|
||||
});
|
||||
|
||||
o = s.option(form.Button, 'stop_tcpdump', _('Stop tcpdump'), _(''));
|
||||
o.inputstyle = 'apply';
|
||||
o.onclick = ui.createHandlerFn(this, function(section_id, ev) {
|
||||
if (!eventSource)
|
||||
return;
|
||||
return fs.exec("/usr/libexec/packet_capture_stop").then(function(replay) {
|
||||
eventSource.close();
|
||||
}.bind(this)).catch(function(error) {
|
||||
console.log(error);
|
||||
});
|
||||
});
|
||||
|
||||
o = s.option(form.Button, 'download_file', _('Download capture file'));
|
||||
o.inputstyle = 'action important';
|
||||
o.inputtitle = _('Download');
|
||||
o.data_action = 'download'
|
||||
o.onclick = this.handleDownload;
|
||||
|
||||
L.Poll.add(L.bind(updateButtons, m),1);
|
||||
captureFilePoll = L.bind(updatePollCheckCaptureFileExists, m);
|
||||
L.Poll.add(captureFilePoll,1);
|
||||
|
||||
return m.render();
|
||||
},
|
||||
});
|
Loading…
Add table
Add a link
Reference in a new issue