diff --git a/net/openthread-br/Makefile b/net/openthread-br/Makefile index 948668545bc06f..200e1d3ff7d6c9 100644 --- a/net/openthread-br/Makefile +++ b/net/openthread-br/Makefile @@ -4,13 +4,13 @@ include $(TOPDIR)/rules.mk PKG_NAME:=openthread-br -PKG_SOURCE_DATE:=2025-06-12 -PKG_SOURCE_VERSION:=2f3c799c7463c8f674754e65c53f78bc0bbcbd58 +PKG_VERSION:=2026.08.0 +PKG_SOURCE_VERSION:=v$(PKG_VERSION) PKG_RELEASE:=2 PKG_SOURCE_PROTO:=git PKG_SOURCE_URL=https://github.com/openthread/ot-br-posix.git -PKG_MIRROR_HASH:=fae1c7c88102f88bac32f8ee25e044b9a8781eef6b9acef39388e1e11a44a195 +PKG_MIRROR_HASH:=4645fefcf89d0c06de87bbfa9e52e2a522de48fa52146427669323c894405eb9 PKG_MAINTAINER:=Stijn Tintel PKG_LICENSE:=BSD-3-Clause @@ -19,14 +19,6 @@ PKG_LICENSE_FILES:=LICENSE include $(INCLUDE_DIR)/package.mk include $(INCLUDE_DIR)/cmake.mk -define Package/luci-app-openthread - CATEGORY:=LuCI - SECTION:=luci - SUBMENU:=3. Applications - TITLE:=LuCI Support for OpenThread Border Router - DEPENDS:=+luci-base +luci-lua-runtime -endef - define Package/openthread-br CATEGORY:=Network SECTION:=net @@ -41,9 +33,7 @@ define Package/openthread-br +libreadline \ +libstdcpp \ +libubox \ - +libubus \ - +mdnsd \ - +mdnsresponder + +libubus endef define Package/openthread-br/description @@ -63,34 +53,18 @@ CMAKE_OPTIONS += \ -DOT_TARGET_OPENWRT=ON \ -DOTBR_BACKBONE_ROUTER=ON \ -DOTBR_BORDER_ROUTING=ON \ - -DOTBR_DNSSD_DISCOVERY_PROXY=ON \ - -DOTBR_DUA_ROUTING=ON \ - -DOTBR_MDNS=mDNSResponder \ + -DOTBR_MDNS=openthread \ -DOTBR_NAT64=OFF \ -DOTBR_OPENWRT=ON \ + -DOTBR_PRODUCT_NAME=BorderRouter \ -DOTBR_REST=ON \ - -DOTBR_SRP_ADVERTISING_PROXY=ON \ -DOTBR_SRP_SERVER_AUTO_ENABLE=ON \ - -DOTBR_TREL=ON + -DOTBR_TREL=ON \ + -DOTBR_VENDOR_NAME=OpenThread \ + -DOTBR_VERSION=$(PKG_VERSION) TARGET_CFLAGS += -DOPENTHREAD_POSIX_CONFIG_DAEMON_SOCKET_BASENAME=\\\"/var/run/openthread-%s\\\" -define Package/luci-app-openthread/install - $(INSTALL_DIR) \ - $(1)/usr/lib/lua/luci/controller/admin \ - $(1)/usr/lib/lua/luci/view/admin_thread \ - $(1)/www/luci-static/resources - $(INSTALL_DATA) \ - $(PKG_BUILD_DIR)/src/openwrt/controller/thread.lua \ - $(1)/usr/lib/lua/luci/controller/admin - $(INSTALL_DATA) \ - $(PKG_BUILD_DIR)/src/openwrt/view/admin_thread/* \ - $(1)/usr/lib/lua/luci/view/admin_thread - $(INSTALL_DATA) \ - $(PKG_BUILD_DIR)/src/openwrt/handle_error.js \ - $(1)/www/luci-static/resources -endef - define Package/openthread-br/install $(INSTALL_DIR) \ $(1)/etc/init.d \ @@ -101,5 +75,4 @@ define Package/openthread-br/install endef -$(eval $(call BuildPackage,luci-app-openthread)) $(eval $(call BuildPackage,openthread-br)) diff --git a/net/openthread-br/README.md b/net/openthread-br/README.md index e4a26d427ba714..d30f1b194f656e 100644 --- a/net/openthread-br/README.md +++ b/net/openthread-br/README.md @@ -25,6 +25,30 @@ the package will likely result in more bug reports. As the package and its dependencies are unlikely to fit in any router with small flash (16MB or less), I don't see much point in making things configurable for reducing size either. +### Vendor and product name + +`OTBR_VENDOR_NAME` and `OTBR_PRODUCT_NAME` have to be set: this release removed +the built-in defaults, and otbr-agent exits with `Vendor name must be set.` +without them. + +They are deliberately set to the values those defaults had, `OpenThread` and +`BorderRouter`, rather than to something OpenWrt specific. The pair forms the +MeshCoP service instance name as ` `, which is the name shown +when adding the border router in a Thread client and the one already-paired +clients have recorded, so changing it would rename every existing user's border +router on upgrade. + +### Version string + +`OTBR_VERSION` is set to `PKG_VERSION`. Without it the build falls back to the +CMake project version, because the repacked source tree has no git directory +for `git describe` to read, so `otbr-agent --version` and the `Running ...` +line it logs on every start would report `0.3.0` rather than the release the +package was built from. + +The version test in the package CI matches on that string, so dropping this +option would make the package fail it again. + ### Firewall support OpenWrt uses firewall4 with nftables by default, but the OpenThread firewall @@ -35,17 +59,36 @@ Therefore, firewall support is disabled completely. This can be revised once the following feature request is implemented: https://github.com/openthread/ot-br-posix/issues/1675 -### mDNSResponder +### mDNS + +The package uses OpenThread's internal mDNS implementation +(`-DOTBR_MDNS=openthread`), which is upstream's default. This drops the +mDNSResponder dependency entirely: no separate daemon, and no Avahi, whose +libavahi-client requirement would have pulled in D-Bus. + +The internal implementation advertises on a single infrastructure interface, +the one selected by the `backbone_network` option. Anything that needs to be +announced on more than one interface still needs a general-purpose responder. + +It coexists with umdns, which remains the provider for other packages' +services. Both bind the wildcard address on port 5353 with SO_REUSEADDR, which +is what admits the second bind and gets multicast delivered to both, and they +never contend for a name: OpenThread's mDNS names its host after the Thread +extended address, while umdns keeps `.local`. -The package depends on mDNSResponder. The alternative, Avahi, depends on D-Bus, -which is not something I feel comfortable with running on any router. While -there are Avahi packages without D-Bus support, using OpenThread Border Router -with Avahi requires libavahi-client, and this requires Avahi to be built with -D-Bus support. +Only multicast reaches both. A unicast datagram to port 5353 is delivered to +one socket, so a unicast reply meant for one daemon can be received by the +other. umdns does set SO_REUSEPORT, but only on a retry after its own bind +fails, and that does not happen here because SO_REUSEADDR already admits the +bind, so no SO_REUSEPORT group forms in either start order. ### REST Server The REST server is enabled to make this package compatible with Home Assistant. +It listens on 127.0.0.1 by default. `rest_listen_address` and +`rest_listen_port` can move it, but the API is unauthenticated and can read and +replace the Thread dataset — including the network key — so any non-loopback +address must be firewalled to trusted hosts. ### TREL support @@ -88,9 +131,13 @@ config interface 'thread' option verbose '0' ``` -Prefix and verbose are optional. Everything else is required. The protocol -handler will fail if a required setting is missing. If something isn't working, -check ifstatus for the OpenThread interface: +Only backbone_network, device and radio_url are required; the protocol handler +fails the interface if one of them is missing, or if backbone_network names an +interface that has no device. Everything else — dataset, prefix, verbose, +rest_listen_address and rest_listen_port — is optional. See +[REST Server](#rest-server) before moving the REST API off the loopback +default. If something isn't working, check ifstatus for the OpenThread +interface: ``` # ifup thread @@ -125,7 +172,11 @@ ubus call otbr threadstop ### LuCI -Creating a network in LuCI appears to be broken for the moment. +This package no longer ships a LuCI application; the web UI lives in the +`luci-app-openthread` package in the openwrt/luci repository +(https://github.com/openwrt/luci/pull/8871). Install that alongside this package +for a web interface, on a LuCI feed recent enough to carry it — older feeds will +not have the package yet. ### CLI diff --git a/net/openthread-br/files/openthread-proto.sh b/net/openthread-br/files/openthread-proto.sh index 995906c9d39429..fde143c51b5834 100644 --- a/net/openthread-br/files/openthread-proto.sh +++ b/net/openthread-br/files/openthread-proto.sh @@ -21,25 +21,14 @@ proto_openthread_add_prefix() { [ -n "$prefix" ] && $OTCTL prefix add $prefix } -proto_openthread_check_service() { - service="$1" - ret=1 - json_init - json_add_string name "$service" - ubus call service list "$(json_dump)" | jsonfilter -e '@[*].instances[*]["running"]' > /dev/null - ret=$? - json_cleanup - - return "$ret" -} - proto_openthread_init_config() { proto_config_add_array 'prefix:list(string)' proto_config_add_boolean verbose proto_config_add_string backbone_network proto_config_add_string dataset proto_config_add_string radio_url - proto_config_add_string foobar + proto_config_add_string rest_listen_address + proto_config_add_int rest_listen_port available=1 no_device=1 @@ -61,7 +50,7 @@ proto_openthread_setup() { mkdir -p /var/lib/thread - json_get_vars backbone_network dataset device radio_url verbose:0 + json_get_vars backbone_network dataset device radio_url rest_listen_address rest_listen_port verbose:0 [ -n "$backbone_network" ] || proto_openthread_setup_error "$interface" MISSING_BACKBONE_NETWORK proto_add_host_dependency "$interface" "" "$backbone_network" @@ -71,13 +60,17 @@ proto_openthread_setup() { [ -n "$device" ] || proto_openthread_setup_error "$interface" MISSING_DEVICE [ -n "$radio_url" ] || proto_openthread_setup_error "$interface" MISSING_RADIO_URL - # run in subshell to prevent wiping json data needed for prefixes - ( proto_openthread_check_service mdnsd ) || proto_openthread_setup_error "$interface" MISSING_SVC_MDNSD - opts="--auto-attach=0" [ "$verbose" -eq 0 ] || append opts -v append opts "-I$device" append opts "-B$backbone_ifname" + # The REST API listens on 127.0.0.1 by default. Bind it elsewhere (e.g. a + # LAN address) to let remote clients such as Home Assistant reach it; + # leaving it unset keeps the loopback-only default. The REST API is + # unauthenticated and can both read and replace the Thread dataset, so any + # non-loopback address must be firewalled to trusted hosts. + [ -n "$rest_listen_address" ] && append opts "--rest-listen-address=$rest_listen_address" + [ -n "$rest_listen_port" ] && append opts "--rest-listen-port=$rest_listen_port" append opts "$radio_url" append opts "trel://$backbone_ifname" # run in subshell to prevent wiping json data needed for prefixes diff --git a/net/openthread-br/patches/101-rest-Permit-to-externally-provide-cJSON-library.patch b/net/openthread-br/patches/101-rest-Permit-to-externally-provide-cJSON-library.patch deleted file mode 100644 index 812978c3350966..00000000000000 --- a/net/openthread-br/patches/101-rest-Permit-to-externally-provide-cJSON-library.patch +++ /dev/null @@ -1,56 +0,0 @@ -From 59c389a91cfe91eebed9c36887fa2a3eca4cbd6f Mon Sep 17 00:00:00 2001 -From: Christian Marangi -Date: Mon, 24 Nov 2025 18:53:28 +0100 -Subject: [PATCH] [rest] Permit to externally provide cJSON library - -Permit to externally provide cJSON library if found with PKGConfig. - -Signed-off-by: Christian Marangi ---- - src/rest/CMakeLists.txt | 12 +++++++++++- - third_party/CMakeLists.txt | 5 ++++- - 2 files changed, 15 insertions(+), 2 deletions(-) - ---- a/src/rest/CMakeLists.txt -+++ b/src/rest/CMakeLists.txt -@@ -36,11 +36,22 @@ add_library(otbr-rest - response.cpp - ) - -+if (CJSON_FOUND) -+ set(CJSON_LIB_TARGETS ${CJSON_LINK_LIBRARIES}) -+else() -+ set(CJSON_LIB_TARGETS cjson) -+endif() -+ -+target_include_directories(otbr-rest -+ PRIVATE -+ ${CJSON_INCLUDE_DIRS} -+) -+ - target_link_libraries(otbr-rest - PUBLIC - http_parser - PRIVATE -- cjson -+ ${CJSON_LIB_TARGETS} - otbr-config - otbr-utils - openthread-ftd ---- a/third_party/CMakeLists.txt -+++ b/third_party/CMakeLists.txt -@@ -28,6 +28,13 @@ - - add_subdirectory(openthread) - if(OTBR_REST) -- add_subdirectory(cJSON) -+ pkg_check_modules(CJSON libcjson) -+ if (CJSON_FOUND) -+ set(CJSON_FOUND ${CJSON_FOUND} PARENT_SCOPE) -+ set(CJSON_INCLUDE_DIRS ${CJSON_INCLUDE_DIRS} PARENT_SCOPE) -+ set(CJSON_LINK_LIBRARIES ${CJSON_LINK_LIBRARIES} PARENT_SCOPE) -+ else() -+ add_subdirectory(cJSON) -+ endif() - add_subdirectory(http-parser) - endif() diff --git a/net/openthread-br/patches/102-openwrt-fix-LuCI-icons.patch b/net/openthread-br/patches/102-openwrt-fix-LuCI-icons.patch deleted file mode 100644 index 701ae0f201fb4e..00000000000000 --- a/net/openthread-br/patches/102-openwrt-fix-LuCI-icons.patch +++ /dev/null @@ -1,68 +0,0 @@ -From 4b09d856fd3d82bfb6707d889fb40f981945a6a2 Mon Sep 17 00:00:00 2001 -From: Stijn Tintel -Date: Wed, 7 Jan 2026 00:20:04 +0200 -Subject: [PATCH] [openwrt] fix LuCI icons (#3178) - -The PNG icons in LuCI have been replaced with SVG icons. - -Signed-off-by: Stijn Tintel ---- - src/openwrt/view/admin_thread/thread_overview.htm | 10 +++++----- - src/openwrt/view/admin_thread/thread_scan.htm | 12 ++++++------ - 2 files changed, 11 insertions(+), 11 deletions(-) - ---- a/src/openwrt/view/admin_thread/thread_overview.htm -+++ b/src/openwrt/view/admin_thread/thread_overview.htm -@@ -32,7 +32,7 @@ - -
-
-- " id="wpan0" /> <%=threadget("interfacename").InterfaceName%> -+ " id="wpan0" /> <%=threadget("interfacename").InterfaceName%> -
-
- <%:Generic MAC 802.15.4 Thread%>
-@@ -164,13 +164,13 @@ - var scale = percent_thread_signal(info); - - if (scale == 0) -- icon = "<%=resource%>/icons/signal-0.png"; -+ icon = "<%=resource%>/icons/signal-000.svg"; - else if (scale == 30) -- icon = "<%=resource%>/icons/signal-25-50.png"; -+ icon = "<%=resource%>/icons/signal-025-050.svg"; - else if (scale == 50) -- icon = "<%=resource%>/icons/signal-50-75.png"; -+ icon = "<%=resource%>/icons/signal-050-075.svg"; - else -- icon = "<%=resource%>/icons/signal-75-100.png"; -+ icon = "<%=resource%>/icons/signal-075-100.svg"; - - return icon; - } ---- a/src/openwrt/view/admin_thread/thread_scan.htm -+++ b/src/openwrt/view/admin_thread/thread_scan.htm -@@ -17,17 +17,17 @@ - end - - if info.NetworkName == nil then -- icon = resource .. "/icons/signal-none.png" -+ icon = resource .. "/icons/signal-none.svg" - elseif scale < 15 then -- icon = resource .. "/icons/signal-0.png" -+ icon = resource .. "/icons/signal-000.svg" - elseif scale < 35 then -- icon = resource .. "/icons/signal-0-25.png" -+ icon = resource .. "/icons/signal-000-025.svg" - elseif scale < 55 then -- icon = resource .. "/icons/signal-25-50.png" -+ icon = resource .. "/icons/signal-025-050.svg" - elseif scale < 75 then -- icon = resource .. "/icons/signal-50-75.png" -+ icon = resource .. "/icons/signal-050-075.svg" - else -- icon = resource .. "/icons/signal-75-100.png" -+ icon = resource .. "/icons/signal-075-100.svg" - end - - return icon diff --git a/net/openthread-br/test.sh b/net/openthread-br/test.sh new file mode 100644 index 00000000000000..706203cf7e4e76 --- /dev/null +++ b/net/openthread-br/test.sh @@ -0,0 +1,30 @@ +#!/bin/sh +# +# Functional smoke tests for openthread-br. + +set -e + +case "$PKG_NAME" in +openthread-br) + # Exercises otbr-agent's option parser and its full runtime closure. + # --version prints and exits without touching the RCP or the network. + # The Makefile passes OTBR_VERSION=$(PKG_VERSION), so this is also + # the string the generic version check matches. + otbr-agent --version + + # Use -h rather than --version here: ot-ctl has no version option at + # this release (openthread/openthread#13424 adds one, but the openthread + # bundled here predates it), so -h is the option that exits inside the + # parser. The older hazard -- a segfault on any unrecognized long + # option, from a getopt_long() array missing its terminating entry -- + # is fixed in the openthread this release bundles + # (openthread/openthread#13423). + ot-ctl -h >/dev/null + ;; + +*) + echo "test.sh: unknown package '$PKG_NAME' — refusing to silently pass" >&2 + echo "test.sh: update net/openthread-br/test.sh to cover this package" >&2 + exit 1 + ;; +esac