move daemon to root folder
authorJohn Crispin <[email protected]>
Mon, 26 May 2025 10:49:53 +0000 (12:49 +0200)
committerJohn Crispin <[email protected]>
Tue, 27 May 2025 11:18:53 +0000 (13:18 +0200)
Signed-off-by: John Crispin <[email protected]>
files/usr/sbin/ufpd [deleted file]
ufpd [new file with mode: 0755]

diff --git a/files/usr/sbin/ufpd b/files/usr/sbin/ufpd
deleted file mode 100755 (executable)
index 11c6284..0000000
+++ /dev/null
@@ -1,434 +0,0 @@
-#!/usr/bin/env ucode
-'use strict';
-import * as uloop from "uloop";
-import * as libubus from "ubus";
-import * as unetmsg from "unetmsg.client";
-import { readfile, glob, basename } from "fs";
-let uht = require("uht");
-push(REQUIRE_SEARCH_PATH, "/usr/share/ufp/*.uc");
-
-uloop.init();
-let ubus = libubus.connect();
-let unet = unetmsg.open(ubus);
-let fingerprints = {};
-let fingerprint_ht = [];
-let devices = {};
-let gc_timer;
-let weight = {
-       "mac-oui": 3.0,
-};
-
-function get_weight(type) {
-       let w = weight[type];
-       if (w)
-               return w;
-       type = split(type, "-");
-       if (length(type) < 2)
-               return null;
-       pop(type);
-       type = join("-", type);
-
-       return weight[type];
-}
-
-function match_fingerprint(key)
-{
-       let fp = [];
-
-       for (let ht in fingerprint_ht) {
-               let cur_fp = ht.get(null, key);
-               if (!cur_fp)
-                       continue;
-               push(fp, ...cur_fp);
-       }
-
-       let user_fp = fingerprints[key];
-       if (user_fp)
-               push(fp, ...user_fp);
-
-       return fp;
-}
-
-unet.publish("ufp", (req) => {
-       let data = req.args;
-       switch (data.type) {
-       case "get_data":
-               let mac = data.macaddr;
-               if (mac)
-                       return { data: devices[mac] };
-               return { data: devices };
-       }
-});
-unet.subscribe("ufp");
-
-function dev_timestamp_cmp(a, b)
-{
-       return a[1].timestamp - b[1].timestamp;
-}
-
-function network_devices() {
-       let device_lists = [
-               devices
-       ];
-
-       unet.request("ufp", "get_data", {}, (msg) => {
-               push(device_lists, msg.data);
-       });
-
-       let cur_devices = [];
-       for (let list in device_lists)
-               for (let mac, dev in list)
-                       push(cur_devices, [ mac, dev ]);
-
-       let ret = {};
-       sort(cur_devices, dev_timestamp_cmp);
-       for (let entry in cur_devices) {
-               let mac = entry[0];
-               let data = entry[1];
-               if (!ret[mac]) {
-                       ret[mac] = data;
-                       continue;
-               }
-
-               let new_data = { ...data };
-               new_data.data = { ...ret[mac].data, ...data.data };
-               new_data.meta = { ...ret[mac].meta, ...data.meta };
-               ret[mac] = new_data;
-       }
-
-       return ret;
-}
-
-let global = {
-       uloop: uloop,
-       ubus: ubus,
-       weight: weight,
-       devices: devices,
-       fingerprints: fingerprints,
-       plugins: [],
-
-       load_fingerprint_json: function(file) {
-               let data = json(readfile(file));
-               fingerprints = data;
-       },
-
-       get_weight: get_weight,
-
-       add_weight: function(data) {
-               for (let entry in data)
-                       weight[entry] = data[entry];
-       },
-
-       device_refresh: function(mac) {
-               mac = lc(mac);
-               let dev = devices[mac];
-               if (!dev)
-                       return;
-
-               dev.timestamp = time();
-       },
-
-       device_add_data: function(mac, line) {
-               mac = lc(mac);
-               let dev = devices[mac];
-               if (!dev) {
-                       dev = devices[mac] = {
-                               data: {},
-                               meta: {},
-                               timestamp: time()
-                       };
-                       let oui = "mac-oui-" + join("", slice(split(mac, ":"), 0, 3));
-                       dev.data[oui] = `${oui}|1`;
-               }
-
-               if (substr(line, 0, 1) == "%") {
-                       line = substr(line, 1);
-                       let meta = split(line, "|", 3);
-                       if (!meta[2])
-                               return;
-
-                       dev.meta[meta[0]] ??= {};
-                       if (!get_weight(meta[1]))
-                               return;
-
-                       dev.meta[meta[0]][meta[1]] = meta[2];
-                       return;
-               }
-
-               let fp = split(line, "|", 2);
-               if (!fp[1])
-                       return;
-
-               dev.data[fp[0]] = line;
-       }
-};
-
-function load_plugins()
-{
-       let plugins = glob("/usr/share/ufp/plugin_*.uc");
-       for (let name in plugins) {
-               name = substr(basename(name), 0, -3);
-               try {
-                       let plugin = require(name);
-                       plugin.init(global);
-                       push(global.plugins, plugin);
-               } catch (e) {
-                       warn(`Failed to load plugin ${name}: ${e}\n${e.stacktrace[0].context}\n`);
-               }
-       }
-}
-
-function refresh_plugins()
-{
-       for (let plugin in global.plugins) {
-               if (!plugin.refresh)
-                       continue;
-
-               try {
-                       plugin.refresh();
-               } catch (e) {
-                       warn(`Failed to refresh plugin: ${e}\n${e.stacktrace[0].context}\n`);
-               }
-       }
-}
-
-function device_gc()
-{
-       gc_timer.set(60 * 60 * 1000);
-       let timeout = time() - 60 * 60 * 24;
-
-       for (let mac in devices) {
-               if (devices[mac].timestamp < timeout)
-                       delete devices[mac];
-       }
-}
-
-// returns: { "<meta>": { "<val>": [ <weight>, [ <fingerprints> ] ] } }
-function __device_match_list(mac, devices)
-{
-       let dev = devices[mac];
-       if (!dev || !length(dev))
-               return null;
-
-       let ret = {};
-       let data = dev.data;
-       let match_devs = [];
-
-       for (let fp in data) {
-               let match = match_fingerprint(data[fp]);
-               for (let match_cur in match)
-                       push(match_devs, [ match_cur, global.get_weight(fp), fp ]);
-       }
-
-       for (let meta in dev.meta) {
-               let meta_cur = dev.meta[meta];
-               for (let type in meta_cur) {
-                       let match = {};
-                       match[meta] = meta_cur[type];
-                       push(match_devs, [ match, global.get_weight(type), type ]);
-               }
-       }
-
-       for (let i = 0; i < length(match_devs); i++) {
-               let match = match_devs[i];
-               let match_data = match[0];
-               let match_weight = match[1];
-               let match_fp = [ match[2] ];
-               let meta_entry = {};
-
-               for (let j = 0; j < length(match_devs); j++) {
-                       if (j == i)
-                               continue;
-
-                       let cur = match_devs[j];
-                       let cur_data = cur[0];
-                       for (let key in cur_data) {
-                               if (lc(match_data[key]) == lc(cur_data[key])) {
-                                       match_weight += cur[1];
-                                       push(match_fp, cur[2]);
-                                       break;
-                               }
-                       }
-               }
-
-               for (let key in match_data) {
-                       let val = match_data[key];
-                       ret[key] ??= {};
-                       let ret_key = ret[key];
-
-                       ret_key[val] ??= [ 0.0, {} ];
-                       let ret_val = ret_key[val];
-
-                       ret_val[0] += match_weight;
-                       for (let fp in match_fp)
-                               ret_val[1][fp]++;
-               }
-       }
-
-       for (let key in ret) {
-               let ret_key = ret[key];
-               for (let val in ret_key) {
-                       let ret_val = ret_key[val];
-                       ret_val[1] = keys(ret_val[1]);
-               }
-       }
-
-       return ret;
-}
-
-function device_match_list(mac, devices)
-{
-       let match = __device_match_list(mac, devices);
-
-       for (let meta in match) {
-               let match_meta = match[meta];
-               let meta_list = keys(match_meta);
-               sort(meta_list, (a, b) => match_meta[b][0] - match_meta[a][0]);
-               match[meta] = map(meta_list, (key) => [ key, match_meta[key][0], match_meta[key][1] ]);
-       }
-
-       return match;
-}
-
-global.ubus_object = {
-       load_fingerprints: {
-               args: {
-                       file: "",
-               },
-               call: function(req) {
-                       let file = req.args.file;
-                       if (!file)
-                               return libubus.STATUS_INVALID_ARGUMENT;
-
-                       try {
-                               global.load_fingerprint_json(file);
-                       } catch (e) {
-                               warn(`Exception in ubus function: ${e}\n${e.stacktrace[0].context}, file=${file}\n`);
-                               return libubus.STATUS_INVALID_ARGUMENT;
-                       }
-
-                       return 0;
-               }
-       },
-
-       get_data: {
-               args: {
-                       macaddr: "",
-               },
-               call: function(req) {
-                       let mac = req.args.macaddr;
-
-                       refresh_plugins();
-
-                       if (!mac)
-                               return devices;
-
-                       let dev = devices[mac];
-                       if (!dev)
-                               return libubus.STATUS_NOT_FOUND;
-
-                       return dev;
-               }
-       },
-
-       add_data: {
-               args: {
-                       macaddr: "",
-                       data: []
-               },
-               call: function(req) {
-                       let mac = req.args.macaddr;
-                       let data = req.args.data;
-                       if (!mac || !data)
-                               return libubus.STATUS_INVALID_ARGUMENT;
-
-                       for (let line in data)
-                               global.device_add_data(mac, line);
-
-                       return 0;
-               }
-       },
-
-       fingerprint: {
-               args: {
-                       macaddr: "",
-                       weight: false
-               },
-               call: function(req) {
-                       refresh_plugins();
-
-                       let cur_devices = network_devices();
-                       let mac_list = req.args.macaddr ? [ req.args.macaddr ] : keys(cur_devices);
-                       let ret = {};
-
-                       for (let mac in mac_list) {
-                               let match_list = device_match_list(mac, cur_devices);
-                               if (!match_list)
-                                       return libubus.STATUS_NOT_FOUND;
-
-                               let cur_ret = { };
-                               if (req.args.weight)
-                                       cur_ret.weight = {};
-                               ret[mac] = cur_ret;
-
-                               for (let meta in match_list) {
-                                       let match_meta = match_list[meta];
-
-                                       if (length(match_meta) < 1)
-                                               continue;
-
-                                       match_meta = match_meta[0];
-
-                                       cur_ret[meta] = match_meta[0];
-                                       if (req.args.weight)
-                                               cur_ret.weight[meta] = match_meta[1];
-                               }
-                       }
-
-                       return req.args.macaddr ? ret[req.args.macaddr] : ret;
-               }
-       },
-
-       list: {
-               args: {
-                       macaddr: ""
-               },
-               call: function(req) {
-                       refresh_plugins();
-
-                       let cur_devices = network_devices();
-                       let mac_list = req.args.macaddr ? [ req.args.macaddr ] : keys(cur_devices);
-                       let ret = {};
-
-                       for (let mac in mac_list) {
-                               let match_list = device_match_list(mac, cur_devices);
-                               if (!match_list)
-                                       return libubus.STATUS_NOT_FOUND;
-
-                               let cur_ret = {};
-                               ret[mac] = cur_ret;
-
-                               for (let meta in match_list)
-                                       cur_ret[meta] = match_list[meta];
-                       }
-
-                       return req.args.macaddr ? ret[req.args.macaddr] : ret;
-               }
-       },
-};
-
-for (let f in [ "/usr/share/ufp/devices.bin", ...glob("/usr/share/ufp/db/*.bin") ]) {
-       let ht;
-       try {
-               ht = uht.open(f);
-       } catch (e) {
-               warn(`Failed to load fingerprints: ${e}\n${e.stacktrace[0].context}\n`);
-       }
-       if (!ht)
-               continue;
-       push(fingerprint_ht, ht);
-}
-load_plugins();
-ubus.publish("fingerprint", global.ubus_object);
-gc_timer = uloop.timer(1000, device_gc);
-uloop.run();
diff --git a/ufpd b/ufpd
new file mode 100755 (executable)
index 0000000..11c6284
--- /dev/null
+++ b/ufpd
@@ -0,0 +1,434 @@
+#!/usr/bin/env ucode
+'use strict';
+import * as uloop from "uloop";
+import * as libubus from "ubus";
+import * as unetmsg from "unetmsg.client";
+import { readfile, glob, basename } from "fs";
+let uht = require("uht");
+push(REQUIRE_SEARCH_PATH, "/usr/share/ufp/*.uc");
+
+uloop.init();
+let ubus = libubus.connect();
+let unet = unetmsg.open(ubus);
+let fingerprints = {};
+let fingerprint_ht = [];
+let devices = {};
+let gc_timer;
+let weight = {
+       "mac-oui": 3.0,
+};
+
+function get_weight(type) {
+       let w = weight[type];
+       if (w)
+               return w;
+       type = split(type, "-");
+       if (length(type) < 2)
+               return null;
+       pop(type);
+       type = join("-", type);
+
+       return weight[type];
+}
+
+function match_fingerprint(key)
+{
+       let fp = [];
+
+       for (let ht in fingerprint_ht) {
+               let cur_fp = ht.get(null, key);
+               if (!cur_fp)
+                       continue;
+               push(fp, ...cur_fp);
+       }
+
+       let user_fp = fingerprints[key];
+       if (user_fp)
+               push(fp, ...user_fp);
+
+       return fp;
+}
+
+unet.publish("ufp", (req) => {
+       let data = req.args;
+       switch (data.type) {
+       case "get_data":
+               let mac = data.macaddr;
+               if (mac)
+                       return { data: devices[mac] };
+               return { data: devices };
+       }
+});
+unet.subscribe("ufp");
+
+function dev_timestamp_cmp(a, b)
+{
+       return a[1].timestamp - b[1].timestamp;
+}
+
+function network_devices() {
+       let device_lists = [
+               devices
+       ];
+
+       unet.request("ufp", "get_data", {}, (msg) => {
+               push(device_lists, msg.data);
+       });
+
+       let cur_devices = [];
+       for (let list in device_lists)
+               for (let mac, dev in list)
+                       push(cur_devices, [ mac, dev ]);
+
+       let ret = {};
+       sort(cur_devices, dev_timestamp_cmp);
+       for (let entry in cur_devices) {
+               let mac = entry[0];
+               let data = entry[1];
+               if (!ret[mac]) {
+                       ret[mac] = data;
+                       continue;
+               }
+
+               let new_data = { ...data };
+               new_data.data = { ...ret[mac].data, ...data.data };
+               new_data.meta = { ...ret[mac].meta, ...data.meta };
+               ret[mac] = new_data;
+       }
+
+       return ret;
+}
+
+let global = {
+       uloop: uloop,
+       ubus: ubus,
+       weight: weight,
+       devices: devices,
+       fingerprints: fingerprints,
+       plugins: [],
+
+       load_fingerprint_json: function(file) {
+               let data = json(readfile(file));
+               fingerprints = data;
+       },
+
+       get_weight: get_weight,
+
+       add_weight: function(data) {
+               for (let entry in data)
+                       weight[entry] = data[entry];
+       },
+
+       device_refresh: function(mac) {
+               mac = lc(mac);
+               let dev = devices[mac];
+               if (!dev)
+                       return;
+
+               dev.timestamp = time();
+       },
+
+       device_add_data: function(mac, line) {
+               mac = lc(mac);
+               let dev = devices[mac];
+               if (!dev) {
+                       dev = devices[mac] = {
+                               data: {},
+                               meta: {},
+                               timestamp: time()
+                       };
+                       let oui = "mac-oui-" + join("", slice(split(mac, ":"), 0, 3));
+                       dev.data[oui] = `${oui}|1`;
+               }
+
+               if (substr(line, 0, 1) == "%") {
+                       line = substr(line, 1);
+                       let meta = split(line, "|", 3);
+                       if (!meta[2])
+                               return;
+
+                       dev.meta[meta[0]] ??= {};
+                       if (!get_weight(meta[1]))
+                               return;
+
+                       dev.meta[meta[0]][meta[1]] = meta[2];
+                       return;
+               }
+
+               let fp = split(line, "|", 2);
+               if (!fp[1])
+                       return;
+
+               dev.data[fp[0]] = line;
+       }
+};
+
+function load_plugins()
+{
+       let plugins = glob("/usr/share/ufp/plugin_*.uc");
+       for (let name in plugins) {
+               name = substr(basename(name), 0, -3);
+               try {
+                       let plugin = require(name);
+                       plugin.init(global);
+                       push(global.plugins, plugin);
+               } catch (e) {
+                       warn(`Failed to load plugin ${name}: ${e}\n${e.stacktrace[0].context}\n`);
+               }
+       }
+}
+
+function refresh_plugins()
+{
+       for (let plugin in global.plugins) {
+               if (!plugin.refresh)
+                       continue;
+
+               try {
+                       plugin.refresh();
+               } catch (e) {
+                       warn(`Failed to refresh plugin: ${e}\n${e.stacktrace[0].context}\n`);
+               }
+       }
+}
+
+function device_gc()
+{
+       gc_timer.set(60 * 60 * 1000);
+       let timeout = time() - 60 * 60 * 24;
+
+       for (let mac in devices) {
+               if (devices[mac].timestamp < timeout)
+                       delete devices[mac];
+       }
+}
+
+// returns: { "<meta>": { "<val>": [ <weight>, [ <fingerprints> ] ] } }
+function __device_match_list(mac, devices)
+{
+       let dev = devices[mac];
+       if (!dev || !length(dev))
+               return null;
+
+       let ret = {};
+       let data = dev.data;
+       let match_devs = [];
+
+       for (let fp in data) {
+               let match = match_fingerprint(data[fp]);
+               for (let match_cur in match)
+                       push(match_devs, [ match_cur, global.get_weight(fp), fp ]);
+       }
+
+       for (let meta in dev.meta) {
+               let meta_cur = dev.meta[meta];
+               for (let type in meta_cur) {
+                       let match = {};
+                       match[meta] = meta_cur[type];
+                       push(match_devs, [ match, global.get_weight(type), type ]);
+               }
+       }
+
+       for (let i = 0; i < length(match_devs); i++) {
+               let match = match_devs[i];
+               let match_data = match[0];
+               let match_weight = match[1];
+               let match_fp = [ match[2] ];
+               let meta_entry = {};
+
+               for (let j = 0; j < length(match_devs); j++) {
+                       if (j == i)
+                               continue;
+
+                       let cur = match_devs[j];
+                       let cur_data = cur[0];
+                       for (let key in cur_data) {
+                               if (lc(match_data[key]) == lc(cur_data[key])) {
+                                       match_weight += cur[1];
+                                       push(match_fp, cur[2]);
+                                       break;
+                               }
+                       }
+               }
+
+               for (let key in match_data) {
+                       let val = match_data[key];
+                       ret[key] ??= {};
+                       let ret_key = ret[key];
+
+                       ret_key[val] ??= [ 0.0, {} ];
+                       let ret_val = ret_key[val];
+
+                       ret_val[0] += match_weight;
+                       for (let fp in match_fp)
+                               ret_val[1][fp]++;
+               }
+       }
+
+       for (let key in ret) {
+               let ret_key = ret[key];
+               for (let val in ret_key) {
+                       let ret_val = ret_key[val];
+                       ret_val[1] = keys(ret_val[1]);
+               }
+       }
+
+       return ret;
+}
+
+function device_match_list(mac, devices)
+{
+       let match = __device_match_list(mac, devices);
+
+       for (let meta in match) {
+               let match_meta = match[meta];
+               let meta_list = keys(match_meta);
+               sort(meta_list, (a, b) => match_meta[b][0] - match_meta[a][0]);
+               match[meta] = map(meta_list, (key) => [ key, match_meta[key][0], match_meta[key][1] ]);
+       }
+
+       return match;
+}
+
+global.ubus_object = {
+       load_fingerprints: {
+               args: {
+                       file: "",
+               },
+               call: function(req) {
+                       let file = req.args.file;
+                       if (!file)
+                               return libubus.STATUS_INVALID_ARGUMENT;
+
+                       try {
+                               global.load_fingerprint_json(file);
+                       } catch (e) {
+                               warn(`Exception in ubus function: ${e}\n${e.stacktrace[0].context}, file=${file}\n`);
+                               return libubus.STATUS_INVALID_ARGUMENT;
+                       }
+
+                       return 0;
+               }
+       },
+
+       get_data: {
+               args: {
+                       macaddr: "",
+               },
+               call: function(req) {
+                       let mac = req.args.macaddr;
+
+                       refresh_plugins();
+
+                       if (!mac)
+                               return devices;
+
+                       let dev = devices[mac];
+                       if (!dev)
+                               return libubus.STATUS_NOT_FOUND;
+
+                       return dev;
+               }
+       },
+
+       add_data: {
+               args: {
+                       macaddr: "",
+                       data: []
+               },
+               call: function(req) {
+                       let mac = req.args.macaddr;
+                       let data = req.args.data;
+                       if (!mac || !data)
+                               return libubus.STATUS_INVALID_ARGUMENT;
+
+                       for (let line in data)
+                               global.device_add_data(mac, line);
+
+                       return 0;
+               }
+       },
+
+       fingerprint: {
+               args: {
+                       macaddr: "",
+                       weight: false
+               },
+               call: function(req) {
+                       refresh_plugins();
+
+                       let cur_devices = network_devices();
+                       let mac_list = req.args.macaddr ? [ req.args.macaddr ] : keys(cur_devices);
+                       let ret = {};
+
+                       for (let mac in mac_list) {
+                               let match_list = device_match_list(mac, cur_devices);
+                               if (!match_list)
+                                       return libubus.STATUS_NOT_FOUND;
+
+                               let cur_ret = { };
+                               if (req.args.weight)
+                                       cur_ret.weight = {};
+                               ret[mac] = cur_ret;
+
+                               for (let meta in match_list) {
+                                       let match_meta = match_list[meta];
+
+                                       if (length(match_meta) < 1)
+                                               continue;
+
+                                       match_meta = match_meta[0];
+
+                                       cur_ret[meta] = match_meta[0];
+                                       if (req.args.weight)
+                                               cur_ret.weight[meta] = match_meta[1];
+                               }
+                       }
+
+                       return req.args.macaddr ? ret[req.args.macaddr] : ret;
+               }
+       },
+
+       list: {
+               args: {
+                       macaddr: ""
+               },
+               call: function(req) {
+                       refresh_plugins();
+
+                       let cur_devices = network_devices();
+                       let mac_list = req.args.macaddr ? [ req.args.macaddr ] : keys(cur_devices);
+                       let ret = {};
+
+                       for (let mac in mac_list) {
+                               let match_list = device_match_list(mac, cur_devices);
+                               if (!match_list)
+                                       return libubus.STATUS_NOT_FOUND;
+
+                               let cur_ret = {};
+                               ret[mac] = cur_ret;
+
+                               for (let meta in match_list)
+                                       cur_ret[meta] = match_list[meta];
+                       }
+
+                       return req.args.macaddr ? ret[req.args.macaddr] : ret;
+               }
+       },
+};
+
+for (let f in [ "/usr/share/ufp/devices.bin", ...glob("/usr/share/ufp/db/*.bin") ]) {
+       let ht;
+       try {
+               ht = uht.open(f);
+       } catch (e) {
+               warn(`Failed to load fingerprints: ${e}\n${e.stacktrace[0].context}\n`);
+       }
+       if (!ht)
+               continue;
+       push(fingerprint_ht, ht);
+}
+load_plugins();
+ubus.publish("fingerprint", global.ubus_object);
+gc_timer = uloop.timer(1000, device_gc);
+uloop.run();