From c7397db0cc8f0d8c69f09bdb85a6676401306a29 Mon Sep 17 00:00:00 2001 From: Christian Korber Date: Wed, 22 Apr 2026 12:37:30 +0200 Subject: [PATCH] luci-mod-network: fill ieee-oui.txt from ufp-neigh With ufp-neigh it is possible to get the vendor of a MAC address. Because arp-scan allows us to specify a txt file for lookup, it is suitable to use ufp-neigh to create a txt file on the spot and populate it with vendors of connected devices. This is only used if ufp is running as service. Signed-off-by: Christian Korber --- .../resources/view/network/diagnostics.js | 35 +++++++++++++++++-- .../share/rpcd/acl.d/luci-mod-network.json | 4 ++- 2 files changed, 36 insertions(+), 3 deletions(-) diff --git a/modules/luci-mod-network/htdocs/luci-static/resources/view/network/diagnostics.js b/modules/luci-mod-network/htdocs/luci-static/resources/view/network/diagnostics.js index 9cabfc73187f..02afa40bac54 100644 --- a/modules/luci-mod-network/htdocs/luci-static/resources/view/network/diagnostics.js +++ b/modules/luci-mod-network/htdocs/luci-static/resources/view/network/diagnostics.js @@ -4,8 +4,25 @@ 'require fs'; 'require ui'; 'require uci'; +'require rpc'; 'require network'; +const callFingerprint = rpc.declare({ + object: 'fingerprint', + method: 'fingerprint', + params: [ 'export' ], + expect: { '': {} } +}); + +const callServiceList = rpc.declare({ + object: 'service', + method: 'list', + params: [ 'name' ], + expect: { ufp: {} } +}); + +let has_ufp; + return view.extend({ handleCommand(exec, args) { const buttons = document.querySelectorAll('.diag-action > .cbi-button'); @@ -50,8 +67,11 @@ return view.extend({ handleArpScan(ev, cmd) { const addr = ev.currentTarget.parentNode.previousSibling.value; + const ieee_file = '/tmp/arp-scan/ieee-oui.txt'; - return this.handleCommand('arp-scan', [ '-l', '-I', addr ]); + if (!has_ufp) + return this.handleCommand('arp-scan', [ '-l', '-I', addr ]); + return this.handleCommand('arp-scan', [ '-l', '-I', addr, '-O', ieee_file ]); }, load() { @@ -60,14 +80,25 @@ return view.extend({ L.resolveDefault(fs.stat('/bin/traceroute6') || fs.stat('/usr/bin/traceroute6'), false), L.resolveDefault(fs.stat('/usr/bin/arp-scan'), false), network.getDevices(), + callServiceList('ufp').then((res) => { + let instances = res.instances; + + for (let i in instances) { + if (instances[i].running) + return callFingerprint(true); + } + + return null; + }), uci.load('luci') ]); }, - render([has_ping6, has_traceroute6, has_arpscan, devices]) { + render([has_ping6, has_traceroute6, has_arpscan, devices, ufp]) { const dns_host = uci.get('luci', 'diag', 'dns') || 'openwrt.org'; const ping_host = uci.get('luci', 'diag', 'ping') || 'openwrt.org'; const route_host = uci.get('luci', 'diag', 'route') || 'openwrt.org'; + has_ufp = ufp != null ? true : false; const table = E('table', { 'class': 'table' }, [ E('tr', { 'class': 'tr' }, [ diff --git a/modules/luci-mod-network/root/usr/share/rpcd/acl.d/luci-mod-network.json b/modules/luci-mod-network/root/usr/share/rpcd/acl.d/luci-mod-network.json index 954b76c5578d..de4706dbd1ea 100644 --- a/modules/luci-mod-network/root/usr/share/rpcd/acl.d/luci-mod-network.json +++ b/modules/luci-mod-network/root/usr/share/rpcd/acl.d/luci-mod-network.json @@ -78,7 +78,9 @@ "/usr/bin/arp-scan": [ "exec", "list" ] }, "ubus": { - "file": [ "exec", "stat" ] + "file": [ "exec", "stat" ], + "fingerprint": [ "fingerprint" ], + "service": [ "list" ] }, "uci": [ "luci" ] }