]> git.ipfire.org Git - thirdparty/openwrt.git/commitdiff
netifd: update to Git HEAD (2026-02-15)
authorFelix Fietkau <nbd@nbd.name>
Sun, 15 Feb 2026 08:27:59 +0000 (08:27 +0000)
committerFelix Fietkau <nbd@nbd.name>
Thu, 19 Feb 2026 12:10:38 +0000 (12:10 +0000)
Adds ucode proto handler support

51fa9ed6d4d6 interface-ip: fix fortify build error
ca33316f8552 proto-ext: extract shared protocol handler code from proto-shell.c
2098f29810e8 proto: add config_load callback to proto_handler
aaf5b194b15d proto-ucode: add ucode protocol handler infrastructure
3fc8b83c8b62 proto-ucode: add ucode proto handler scripts
c6122254eb70 examples: sync wireless scripts with openwrt

Signed-off-by: Felix Fietkau <nbd@nbd.name>
package/network/config/netifd/Makefile
package/network/config/netifd/files/lib/netifd/main.uc
package/network/config/netifd/files/lib/netifd/proto-ucode.uc [new file with mode: 0644]
package/network/config/netifd/files/lib/netifd/proto.uc [new file with mode: 0644]
package/network/config/netifd/files/lib/netifd/utils.uc

index a66f87d38ddf18c0100e3b8f677bc55fe32a2b13..e3a9c145831b7e90f97ab4aa69465370833a33bd 100644 (file)
@@ -1,13 +1,13 @@
 include $(TOPDIR)/rules.mk
 
 PKG_NAME:=netifd
-PKG_RELEASE:=3
+PKG_RELEASE:=1
 
 PKG_SOURCE_PROTO:=git
 PKG_SOURCE_URL=$(PROJECT_GIT)/project/netifd.git
-PKG_SOURCE_DATE:=2025-10-20
-PKG_SOURCE_VERSION:=777f5942fa7d6245f6ad29daa1daecc400344d37
-PKG_MIRROR_HASH:=7fc56f436faa1a5b05a147febed52c6f58c479125a38c9737736b352cd8d4409
+PKG_SOURCE_DATE:=2026-02-15
+PKG_SOURCE_VERSION:=c6122254eb7003377b67a6ad14d284b69725bbee
+PKG_MIRROR_HASH:=feb62dba4dfecba1e3e758e5e4e822e9776b4104ee133dccfc3feb7ae6c5182d
 PKG_MAINTAINER:=Felix Fietkau <nbd@nbd.name>
 
 PKG_LICENSE:=GPL-2.0
index 69677bb159acaae8479e1aac0f19cbf7e472458e..56911347a75d1b85211eecf3cc33d34d93924041 100644 (file)
@@ -1,6 +1,6 @@
 import * as uci from "uci";
 import * as uloop from "uloop";
-import * as ubus from "ubus";
+import * as libubus from "ubus";
 import { access, dirname } from "fs";
 
 function ex_handler(e)
@@ -9,9 +9,11 @@ function ex_handler(e)
 }
 
 uloop.guard(ex_handler);
-ubus.guard(ex_handler);
+libubus.guard(ex_handler);
 
+let ubus = netifd.ubus = libubus.connect();
 let wireless;
+let proto_mod;
 
 function uci_ctx()
 {
@@ -26,8 +28,13 @@ function config_init()
 {
        let ctx = uci_ctx();
 
-       if (wireless)
-               wireless.config_init(ctx);
+       for (let mod in [ wireless, proto_mod ]) {
+               try {
+                       mod?.config_init(ctx);
+               } catch (e) {
+                       netifd.log(netifd.L_WARNING, `${e}\n${e.stacktrace[0].context}`);
+               }
+       }
 }
 
 function config_start()
@@ -77,3 +84,12 @@ if (access(wireless_module, "r")) {
 } else {
        netifd.log(netifd.L_WARNING, `Wireless module not found\n`);
 }
+
+const proto_module = dirname(sourcepath()) + "/proto.uc";
+if (access(proto_module, "r")) {
+       try {
+               proto_mod = loadfile(proto_module)();
+       } catch (e) {
+               netifd.log(netifd.L_WARNING, `Error loading proto module: ${e}\n${e.stacktrace[0].context}\n`);
+       }
+}
diff --git a/package/network/config/netifd/files/lib/netifd/proto-ucode.uc b/package/network/config/netifd/files/lib/netifd/proto-ucode.uc
new file mode 100644 (file)
index 0000000..7db61cd
--- /dev/null
@@ -0,0 +1,112 @@
+#!/usr/bin/env ucode
+
+import * as libubus from "ubus";
+
+let script_path = ARGV[0];
+let proto_name = ARGV[1];
+let action = ARGV[2];
+let iface_name = ARGV[3];
+let config_json = ARGV[4];
+let device = ARGV[5];
+
+let config;
+try {
+       let blob = json(config_json);
+       let inner = blob?._ucode_config;
+       config = inner ? json(inner) : blob;
+} catch (e) {
+       warn(`Failed to parse config JSON: ${e}\n${e.stacktrace[0].context}\n`);
+       exit(1);
+}
+
+let ubus = libubus.connect();
+if (!ubus) {
+       warn(`Failed to connect to ubus\n`);
+       exit(1);
+}
+
+let notify_path = `network.interface.${iface_name}`;
+
+function proto_notify(data)
+{
+       return ubus.call(notify_path, "notify_proto", data);
+}
+
+let proto = {
+       iface: iface_name,
+       proto: proto_name,
+       config,
+       device,
+
+       notify: proto_notify,
+
+       update_link: function(up, data) {
+               let msg = { action: 0, "link-up": up, ...(data ?? {}) };
+               return proto_notify(msg);
+       },
+
+       run_command: function(argv, env) {
+               let msg = { action: 1, command: argv };
+               if (env)
+                       msg.env = env;
+               return proto_notify(msg);
+       },
+
+       kill_command: function(signal) {
+               return proto_notify({ action: 2, signal: signal ?? 15 });
+       },
+
+       error: function(errors) {
+               return proto_notify({ action: 3, error: errors });
+       },
+
+       block_restart: function() {
+               return proto_notify({ action: 4 });
+       },
+
+       set_available: function(available) {
+               return proto_notify({ action: 5, available });
+       },
+
+       add_host_dependency: function(host, ifname) {
+               let msg = { action: 6 };
+               if (host)
+                       msg.host = host;
+               if (ifname)
+                       msg.ifname = ifname;
+               return proto_notify(msg);
+       },
+
+       setup_failed: function() {
+               return proto_notify({ action: 7 });
+       },
+};
+
+let handlers = {};
+
+let netifd_stub = {
+       add_proto: function(handler) {
+               if (handler?.name)
+                       handlers[handler.name] = handler;
+       },
+};
+
+try {
+       include(script_path, { netifd: netifd_stub });
+} catch (e) {
+       warn(`Failed to load proto handler script '${script_path}': ${e}\n${e.stacktrace[0].context}\n`);
+       exit(1);
+}
+
+let handler = handlers[proto_name];
+if (!handler) {
+       warn(`No handler found for protocol '${proto_name}'\n`);
+       exit(1);
+}
+
+if (!handler[action]) {
+       warn(`Handler '${proto_name}' has no '${action}' function\n`);
+       exit(1);
+}
+
+handler[action](proto);
diff --git a/package/network/config/netifd/files/lib/netifd/proto.uc b/package/network/config/netifd/files/lib/netifd/proto.uc
new file mode 100644 (file)
index 0000000..b1a4e2e
--- /dev/null
@@ -0,0 +1,52 @@
+import { sorted_json } from "./utils.uc";
+import { dirname, glob } from "fs";
+
+let ctx;
+
+function proto_config_load(config_fn, section_name)
+{
+       if (!ctx)
+               return null;
+
+       let section_data = ctx.get_all("network", section_name);
+       if (!section_data)
+               return null;
+
+       let config_obj = {
+               iface: section_name,
+               section: section_name,
+               data: section_data,
+               uci: ctx,
+       };
+
+       let result;
+       if (config_fn)
+               result = config_fn(config_obj);
+       else
+               result = section_data;
+
+       return sorted_json(result);
+}
+
+netifd.cb.proto_config_load = proto_config_load;
+
+let base = dirname(sourcepath());
+for (let script in glob(base + "/proto/*.uc")) {
+       try {
+               loadfile(script)();
+       } catch (e) {
+               netifd.log(netifd.L_WARNING,
+                       `Error loading proto handler ${script}: ${e}\n${e.stacktrace[0].context}\n`);
+       }
+}
+
+function config_init(uci)
+{
+       ctx = uci;
+       if (!ctx.load("network"))
+               netifd.log(netifd.L_WARNING, `Failed to load network config\n`);
+}
+
+return {
+       config_init,
+};
index 84db69d2fae2dd1bbf64019315b18a43fe76912e..b038efc5fc7b382ded9ae29b893dc5ab7babdb7c 100644 (file)
@@ -102,6 +102,26 @@ export function parse_attribute_list(data, spec)
        return ret;
 };
 
+export function sorted_json(value) {
+       let t = type(value);
+
+       if (t == "object") {
+               let parts = [];
+               for (let key in sort(keys(value)))
+                       push(parts, sprintf("%J", key) + ":" + sorted_json(value[key]));
+               return "{" + join(",", parts) + "}";
+       }
+
+       if (t == "array") {
+               let parts = [];
+               for (let item in value)
+                       push(parts, sorted_json(item));
+               return "[" + join(",", parts) + "]";
+       }
+
+       return sprintf("%J", value);
+};
+
 export function is_equal(val1, val2) {
        let t1 = type(val1);