luci-mod-status: resolve service names for ports
authorKonstantin Glukhov <redacted>
Thu, 22 Jan 2026 02:13:35 +0000 (11:13 +0900)
committerPaul Donald <redacted>
Fri, 23 Jan 2026 02:52:28 +0000 (03:52 +0100)
- Parse and map ports to corresponding service names.
- Display service names when DNS lookups are enabled.

Rationale:

Enhance endpoint readability by showing service names where available,
improving clarity of source/destination information.

Signed-off-by: Konstantin Glukhov <redacted>
modules/luci-mod-status/htdocs/luci-static/resources/view/status/connections.js
modules/luci-mod-status/root/usr/share/rpcd/acl.d/luci-mod-status.json

index b7cd7c875f612829daed93f3108916e022bfe3f5..d2580fe43b6ad75d43b257ae1260fd07038d4b43 100644 (file)
@@ -3,6 +3,7 @@
 'require poll';
 'require request';
 'require rpc';
+'require fs';
 
 var callLuciRealtimeStats = rpc.declare({
        object: 'luci',
@@ -31,10 +32,11 @@ var callLuciRpcGetHostHints = rpc.declare({
 });
 
 var graphPolls = [],
-    pollInterval = 3,
-    dns_cache = {},
-    enableLookups = false,
-    filterText = '';
+       pollInterval = 3,
+       dns_cache = {},
+       service_cache = {},
+       enableLookups = false,
+       filterText = '';
 
 var recheck_lookup_queue = {};
 
@@ -113,6 +115,40 @@ return view.extend({
        },
 
        updateConntrack: function(conn) {
+               function fetchServices() {
+                       if (Object.keys(service_cache).length > 0) return;
+
+                       fs.read('/etc/services')
+                               .then((rawData) => {
+                                       const lines = rawData.split('\n');  // Split data into lines
+                                       // Parse each line to extract port and service info
+                                       lines.forEach(line => {
+                                               const match = line.match(/^([\w-]+)\s+(\d+)\/(\w+)/);  // Regex to match service definition
+                                               if (match) {
+                                                       const [, service, port, protocol] = match;
+                                                       // Cache the service info by port and protocol
+                                                       if (!service_cache[port]) service_cache[port] = {};
+                                                       service_cache[port][protocol] = service;
+                                               }
+                                       });
+                               })
+                               .catch((error) => {
+                                       console.error('Error fetching services:', error);
+                               });
+               }
+
+               function joinAddressWithPortOrServiceName(address, port, protocol) {
+                       if (!port) return address;
+
+                       if (enableLookups) {
+                               fetchServices();
+                               const service = service_cache[Number(port)]?.[protocol];
+                               if (service)
+                                       return `${address}:${service}`;
+                       }
+                       return `${address}:${port}`;
+               }
+
                var lookup_queue = [ ];
                var rows = [];
 
@@ -139,8 +175,8 @@ return view.extend({
 
                        const network = c.layer3.toUpperCase();
                        const protocol = c.layer4.toUpperCase();
-                       const source ='%h'.format(c.hasOwnProperty('sport') ? (src + ':' + c.sport) : src);
-                       const destination = '%h'.format(c.hasOwnProperty('dport') ? (dst + ':' + c.dport) : dst);
+                       const source ='%h'.format(joinAddressWithPortOrServiceName(src, c.sport, protocol));
+                       const destination = '%h'.format(joinAddressWithPortOrServiceName(dst, c.dport, protocol));
                        const transfer = [ c.bytes, '%1024.2mB (%d %s)'.format(c.bytes, c.packets, _('Pkts.')) ];
 
                        if (filterText) {
index 037efb34370695b097a9337e59fdf6cd40f10a76..d9f93ab8db62c934a58b4b8ea92e37e5204e58fd 100644 (file)
@@ -2,6 +2,9 @@
        "luci-mod-status-realtime": {
                "description": "Grant access to realtime statistics",
                "read": {
+                       "file": {
+                               "/etc/services": [ "read" ]
+                       },
                        "ubus": {
                                "luci": [ "getConntrackList", "getRealtimeStats" ],
                                "network.rrdns": [ "lookup" ]
git clone https://git.99rst.org/PROJECT