diff --git a/agentflow/Makefile b/agentflow/Makefile index f70ec2ad2..826eefe17 100644 --- a/agentflow/Makefile +++ b/agentflow/Makefile @@ -10,12 +10,12 @@ AGENTFLOW_ARCH_x86_64:=amd64 AGENTFLOW_ARCH_aarch64:=arm64 AGENTFLOW_ARCH:=$(AGENTFLOW_ARCH_$(ARCH)) -AGENTFLOW_HASH_x86_64:=478fdb17cfb2b1664e7bc01315186e71f228871c0d20c816d8b3b8fe789bdb4d -AGENTFLOW_HASH_aarch64:=257faeaad2445dd14f87c1e1d9ded869fd301c5df2c2c9af817e70303eab2512 +AGENTFLOW_HASH_x86_64:=9174fec77dc835640f94ea8bef84b580b84f947823f4dd63fc495c4c58a68297 +AGENTFLOW_HASH_aarch64:=256adf7bcb836259dacbf583c52af04f0134587328689a49811c135260fa5aed PKG_NAME:=agentflow PKG_VERSION:=0.3.3 -PKG_RELEASE:=12 +PKG_RELEASE:=13 AGENTFLOW_URL_FILE:=agentflow-linux-$(AGENTFLOW_ARCH) AGENTFLOW_DOWNLOAD:=$(AGENTFLOW_URL_FILE)-$(AGENTFLOW_HASH_$(ARCH)) diff --git a/luci-app-passwall/Makefile b/luci-app-passwall/Makefile index 9ec6fb8cd..5b5a2621a 100644 --- a/luci-app-passwall/Makefile +++ b/luci-app-passwall/Makefile @@ -8,7 +8,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=luci-app-passwall PKG_VERSION:=26.9.16 -PKG_RELEASE:=285 +PKG_RELEASE:=286 PKG_PO_VERSION:=$(PKG_VERSION) PKG_CONFIG_DEPENDS:= \ diff --git a/luci-app-passwall/luasrc/view/passwall/node_config/link_share_man.htm b/luci-app-passwall/luasrc/view/passwall/node_config/link_share_man.htm index b56d08da1..351949e6a 100644 --- a/luci-app-passwall/luasrc/view/passwall/node_config/link_share_man.htm +++ b/luci-app-passwall/luasrc/view/passwall/node_config/link_share_man.htm @@ -1004,6 +1004,7 @@ local current_node = map:get(section) opt.set(dom_prefix + 'method', method || ""); opt.set(dom_prefix + 'ss_method', method || ""); opt.set(dom_prefix + 'tcp_fast_open', queryParam.tfo); + if (plugin && plugin != "none") { plugin = (plugin === "simple-obfs") ? "obfs-local" : plugin; opt.set(dom_prefix + 'plugin_enabled', true); @@ -1026,9 +1027,29 @@ local current_node = map:get(section) opt.set(dom_prefix + 'tls_allowInsecure', true); } } + //部分订阅 ShadowTLS 采用 SIP003 + if (plugin === "shadow-tls") { + pluginOpts = pluginOpts.replace(/(^|;)password=/, '$1passwd='); + pluginOpts = pluginOpts.replace(/(^|;)version=([123])(?=;|$)/, '$1v$2=1'); + if (dom_prefix === "ssrust_") { + opt.set(dom_prefix + 'plugin_opts', pluginOpts || ""); + } else if (dom_prefix === "singbox_") { + const opts = Object.fromEntries(pluginOpts.split(';').map(item => item.split('=', 2))); + const host = opts.host; + const password = opts.passwd; + const versionKey = Object.keys(opts).find(key => /^v[123]$/.test(key)); + const version = versionKey ? versionKey.slice(1) : "1"; + opt.set(dom_prefix + 'shadowtls', true); + opt.set(dom_prefix + 'shadowtls_version', version); + opt.set(dom_prefix + 'shadowtls_password', password || ""); + opt.set(dom_prefix + 'shadowtls_serverName', host || ""); + opt.set(dom_prefix + 'plugin_enabled', false); + } + } } else { opt.set(dom_prefix + 'plugin', "none"); } + if (param !== undefined) { opt.set('remarks', decodeURIComponent(param)); } @@ -1129,7 +1150,7 @@ local current_node = map:get(section) opt.set(dom_prefix + 'finalmask', queryParam.fm || ""); if (queryParam["shadow-tls"]) { - //解析SS Shadow-TLS 插件参数 + //解析SS Shadow-TLS 专用参数 const parseShadowTLSParams = function(base64Str, outObj) { try { let obj = JSON.parse(b64decsafe(base64Str)); diff --git a/luci-app-passwall/root/usr/share/passwall/subscribe.lua b/luci-app-passwall/root/usr/share/passwall/subscribe.lua index dc4688601..73f1c1f53 100755 --- a/luci-app-passwall/root/usr/share/passwall/subscribe.lua +++ b/luci-app-passwall/root/usr/share/passwall/subscribe.lua @@ -749,6 +749,11 @@ local function processData(szType, content, add_mode, group, sub_cfg) if idx_pn then result.plugin = plugin_info:sub(1, idx_pn - 1) result.plugin_opts = plugin_info:sub(idx_pn + 1, #plugin_info) + -- 部分订阅 ShadowTLS 采用 SIP003 + result.plugin_opts = result.plugin_opts:gsub("^password=", "passwd=") + result.plugin_opts = result.plugin_opts:gsub(";password=", ";passwd=") + result.plugin_opts = result.plugin_opts:gsub("^version=([123])", "v%1=1") + result.plugin_opts = result.plugin_opts:gsub(";version=([123])", ";v%1=1") else result.plugin = plugin_info end @@ -855,10 +860,22 @@ local function processData(szType, content, add_mode, group, sub_cfg) result.plugin_opts = nil end elseif result.type == 'sing-box' then - if result.plugin ~= "obfs-local" and result.plugin ~= "v2ray-plugin" then + if result.plugin ~= "obfs-local" and result.plugin ~= "v2ray-plugin" and result.plugin ~= "shadow-tls" then result.error_msg = "Sing-Box 不支持 SS " .. result.plugin .. " 插件。" else result.plugin_enabled = "1" + -- 部分订阅 ShadowTLS 采用 SIP003 + if result.plugin == "shadow-tls" then + for item in result.plugin_opts:gmatch("[^;]+") do + local key, value = item:match("^([^=]+)=(.*)$") + if key == "host" then result.shadowtls_serverName = value end + if key == "passwd" then result.shadowtls_password = value end + if key:match("^v[123]$") then result.shadowtls_version = key:sub(2) end + end + result.shadowtls = "1" + result.plugin_opts = nil + result.plugin_enabled = nil + end end else result.plugin_enabled = "1" @@ -967,7 +984,7 @@ local function processData(szType, content, add_mode, group, sub_cfg) if result.type ~= "sing-box" and result.type ~= "SS-Rust" then result.error_msg = sub_ss_type .. " 不支持 shadow-tls 插件。" else - -- 解析SS Shadow-TLS 插件参数 + -- 解析SS Shadow-TLS 专用参数 local function parseShadowTLSParams(b64str, out) local ok, data = pcall(jsonParse, base64Decode(b64str)) if not ok or type(data) ~= "table" then return "" end diff --git a/luci-app-wizard/htdocs/luci-static/resources/view/wizard/initsetup.js b/luci-app-wizard/htdocs/luci-static/resources/view/wizard/initsetup.js index 4fc6f9b72..40bd1d93e 100644 --- a/luci-app-wizard/htdocs/luci-static/resources/view/wizard/initsetup.js +++ b/luci-app-wizard/htdocs/luci-static/resources/view/wizard/initsetup.js @@ -186,7 +186,7 @@ return view.extend({ { tab: 'netsetup', type: form.Value, id: 'lan_ipaddr', title: _('LAN IPv4 Address'), datatype: 'ip4addr', placeholder: '10.0.0.1' }, { tab: 'netsetup', type: form.DynamicList, id: 'lan_dns', title: _('Custom DNS Server(s)'), datatype: 'ipaddr', placeholder: '223.5.5.5', desc: _('Leave empty for ISP DNS.') }, { tab: 'netsetup', type: form.Value, id: 'lan_gateway', title: _('Gateway Address'), datatype: 'ip4addr', placeholder: '', depends: { wan_proto: 'siderouter' }, desc: _('Primary router IP address used when operating in side-router mode.') }, - { tab: 'netsetup', type: form.Flag, id: 'dhcp', title: _('Enable DHCP Server'), desc: _('Enable or disable LAN DHCP server (usually disabled in side-router mode to avoid IP address conflicts).') }, + { tab: 'netsetup', type: form.Flag, id: 'dhcp', title: _('Enable DHCP Server'), desc: _('If this DHCP is enabled, disable the main router's DHCP. If disabled, manually set client devices' gateway and DNS to this bypass router's IP.') }, { tab: 'netsetup', type: form.Flag, id: 'ipv6', title: _('IPv6 Support'), desc: _('Enable or disable IPv6 router advertisements and DHCPv6.') }, // 固件与系统设置 diff --git a/luci-app-wizard/po/zh_Hans/wizard.po b/luci-app-wizard/po/zh_Hans/wizard.po index ab721260b..27777c35c 100644 --- a/luci-app-wizard/po/zh_Hans/wizard.po +++ b/luci-app-wizard/po/zh_Hans/wizard.po @@ -69,8 +69,8 @@ msgstr "在旁路由模式下工作时填写的上级主路由 IP 地址。" msgid "Enable DHCP Server" msgstr "启用 DHCP 服务器" -msgid "Enable or disable LAN DHCP server (usually disabled in side-router mode to avoid IP address conflicts)." -msgstr "开启或关闭局域网 DHCP 服务(旁路由模式下通常建议关闭,避免局域网 IP 分配冲突)。" +msgid "If this DHCP is enabled, disable the main router's DHCP. If disabled, manually set client devices' gateway and DNS to this bypass router's IP." +msgstr "开启此DHCP则需要关闭主路由DHCP, 关闭此DHCP则需要手动将上网设备的网关和DNS改为此旁路由的IP。" msgid "Leave empty for ISP DNS." msgstr "留空则使用 ISP 运营商DNS" diff --git a/luci-app-wwand/Makefile b/luci-app-wwand/Makefile index 7edd6d387..a05ed965b 100644 --- a/luci-app-wwand/Makefile +++ b/luci-app-wwand/Makefile @@ -17,12 +17,12 @@ include $(TOPDIR)/rules.mk PKG_NAME:=luci-app-wwand -PKG_VERSION:=1.6.7_p13 -PKG_RELEASE:=25 +PKG_VERSION:=1.6.7_p14 +PKG_RELEASE:=26 PKG_SOURCE_PROTO:=git PKG_SOURCE_URL:=https://github.com/ddimension/luci-app-wwand.git -PKG_SOURCE_VERSION:=e97ffb8db7ca59049195d9a37ae86b69c1e1264d +PKG_SOURCE_VERSION:=f46ba800d6f195c5c78a8bf566b4f340b9f1ee25 PKG_MIRROR_HASH:=skip PKG_LICENSE:=GPL-2.0-only diff --git a/my-default-settings/Makefile b/my-default-settings/Makefile index b5e32a3ad..8b0942db5 100644 --- a/my-default-settings/Makefile +++ b/my-default-settings/Makefile @@ -10,7 +10,7 @@ include $(INCLUDE_DIR)/kernel.mk PKG_NAME:=my-default-settings PKG_VERSION:=2 -PKG_RELEASE:=17 +PKG_RELEASE:=18 include $(INCLUDE_DIR)/package.mk diff --git a/my-default-settings/files/sbin/mywifi b/my-default-settings/files/sbin/mywifi index 5d4421b12..3281c8aa4 100644 --- a/my-default-settings/files/sbin/mywifi +++ b/my-default-settings/files/sbin/mywifi @@ -20,8 +20,8 @@ show_help() { -h, --help 查看帮助信息 并发与等待机制: - - 无参调用时:若已有 mywifi 在执行,直接终止退出; - - 带 -f 或传参调用时:若已有 mywifi 在执行,自动排队等待其执行完成后再继续执行。 + - 无参/热插拔调用时:若已有 mywifi 在执行,直接终止退出; + - 带 -f 或用户传参调用时:若已有 mywifi 在执行,自动排队等待其执行完成后再继续执行。 WiFi命名规范: 2.4 GHz -> _2.4G @@ -29,21 +29,27 @@ WiFi命名规范: 6 GHz -> _6G 使用示例: - mywifi # 默认执行(若已配置过或正在执行则自动终止) - mywifi -f # 强制重新按 hostname 恢复默认配置(若有执行中则排队等待) - mywifi "HomeWiFi" "12345678" # 设置指定 WiFi 名及密码(若有执行中则排队等待) + mywifi # 默认执行(使用 hostname,若已配置或正在执行则自动终止) + mywifi -f # 强制重新按 hostname 恢复默认配置 + mywifi "HomeWiFi" "12345678" # 设置指定 WiFi 名及密码 mywifi -f "HomeWiFi" "12345678" # 强制覆盖设置 EOF_HELP } # ------------------------------------------------------------- -# 1. 优先解析命令行参数(判断是否带有 -f 或自定义参数) +# 1. 命令行参数解析(过滤 OpenWrt Hotplug 热插拔系统事件传参) # ------------------------------------------------------------- CUSTOM_SSID="" CUSTOM_PASSWD="" HAS_PASSWD=0 FORCE=0 +# 判断是否是由系统 Hotplug 热插拔机制触发调用 +is_hotplug=0 +if [ -n "$HOTPLUG_TYPE" ] || [ -n "$ACTION" ] || [ -n "$DEVICENAME" ]; then + is_hotplug=1 +fi + while [ $# -gt 0 ]; do case "$1" in -h|--help) @@ -62,27 +68,33 @@ while [ $# -gt 0 ]; do CUSTOM_PASSWD="$1" HAS_PASSWD=1 ;; + ieee80211|net|button|platform|usb|add|remove|bind|unbind) + # 过滤热插拔事件传参,避免将热插拔子系统名称(如 ieee80211)误当作 WiFi SSID + is_hotplug=1 + ;; *) - if [ -z "$CUSTOM_SSID" ]; then - CUSTOM_SSID="$1" - elif [ $HAS_PASSWD -eq 0 ]; then - CUSTOM_PASSWD="$1" - HAS_PASSWD=1 + # 仅在非系统热插拔事件传参时才接收位置参数 + if [ $is_hotplug -eq 0 ]; then + if [ -z "$CUSTOM_SSID" ]; then + CUSTOM_SSID="$1" + elif [ $HAS_PASSWD -eq 0 ]; then + CUSTOM_PASSWD="$1" + HAS_PASSWD=1 + fi fi ;; esac shift done -# 判断是否需要等待正在运行的实例完成 -# 只要指定了 -f 或传入了自定义 SSID / 密码,就启用等待锁机制 +# 判断是否需要等待锁(带 -f 或传了有效自定义参数时排队等待,无参/热插拔直接退出) WAIT_LOCK=0 if [ $FORCE -eq 1 ] || [ -n "$CUSTOM_SSID" ] || [ $HAS_PASSWD -eq 1 ]; then WAIT_LOCK=1 fi # ------------------------------------------------------------- -# 2. 检查 base_config 状态标记(无参且已配置过 wifi=1 时直接退出) +# 2. 检查 base_config 状态标记(无参且已配置过 wifi=1 时,直接终止) # ------------------------------------------------------------- if [ $FORCE -eq 0 ]; then if [ "$(uci -q get base_config.@status[0].wifi 2>/dev/null)" = "1" ]; then @@ -94,7 +106,7 @@ if [ $FORCE -eq 0 ]; then fi # ------------------------------------------------------------- -# 3. 并发锁处理:带参/-f 模式等待完成,无参模式直接终止 +# 3. 防并发检测与等待处理 # ------------------------------------------------------------- LOCK_FILE="/var/run/mywifi.lock" @@ -102,7 +114,7 @@ acquire_lock() { local cur_pid=$$ local cur_ppid=$PPID - # A. 优先采用 flock 文件描述符锁(内核自动回收,安全可靠) + # A. 优先采用 flock 文件描述符锁 if command -v flock >/dev/null 2>&1; then exec 9>"$LOCK_FILE" 2>/dev/null || true if [ $WAIT_LOCK -eq 1 ]; then @@ -277,7 +289,7 @@ if [ -n "$CUSTOM_SSID" ]; then SSID="$CUSTOM_SSID" else SSID="$(uci -q get system.@system[0].hostname 2>/dev/null)" - [ -z "$SSID" ] && [ -r /proc/sys/kernel/hostname ] && SSID="$(cat /proc/sys/kernel/hostname)" + [ -z "$SSID" ] && [ -r /proc/sys/kernel/hostname ] w&& SSID="$(cat /proc/sys/kernel/hostname)" [ -z "$SSID" ] && SSID="$(uci -q get wizard.default.wifi_ssid 2>/dev/null)" [ -z "$SSID" ] && SSID="OpenWrt" fi diff --git a/wwand/Makefile b/wwand/Makefile index 0161e06b8..9999fbcaa 100644 --- a/wwand/Makefile +++ b/wwand/Makefile @@ -11,7 +11,7 @@ # wwand-ncm - NCM/ECM backend (DEPENDS wwand) # wwand-mhi - PCIe/MHI transport + drivers (DEPENDS wwand; add a backend) # wwand-esim - eSIM management (DEPENDS wwand + lpac; no backend) -# wwand-gps - GNSS/NMEA glue for ugps (DEPENDS wwand + ugps; no backend) +# wwand-gps - GNSS/NMEA reader (DEPENDS wwand; no backend) # A typical QMI router installs `wwand-qmi` (which pulls in `wwand`); add # `wwand-mbim` / `wwand-ncm` for those modems, `wwand-mhi` for a PCIe/MHI modem. # The ucode tree ships PRECOMPILED to bytecode (repo-root CMakeLists.txt, @@ -50,12 +50,12 @@ include $(TOPDIR)/rules.mk PKG_NAME:=wwand -PKG_VERSION:=1.6.7_p60 -PKG_RELEASE:=51 +PKG_VERSION:=1.6.7_p63 +PKG_RELEASE:=52 PKG_SOURCE_PROTO:=git PKG_SOURCE_URL:=https://github.com/ddimension/wwand.git -PKG_SOURCE_VERSION:=f5cba40880e0a11c00cf6b9040a6eb74e3d222da +PKG_SOURCE_VERSION:=2c428ced46e584daae9719f722d2ed7c9aa28fff PKG_MIRROR_HASH:=skip PKG_LICENSE:=GPL-2.0-only @@ -439,7 +439,7 @@ define Package/wwand-esim/install endef # --------------------------------------------------------------------------- -# wwand-gps: point ugps at the modem's NMEA port. Backend-neutral — finding the +# wwand-gps: read NMEA off the modem's NMEA port. Backend-neutral — finding the # port and starting the receiver are both in the base package, and neither # depends on the control protocol. # --------------------------------------------------------------------------- @@ -447,34 +447,42 @@ define Package/wwand-gps SECTION:=net CATEGORY:=Network SUBMENU:=WWAN - TITLE:=GNSS/NMEA glue for wwand (ugps) - # ugps is OpenWrt base: it parses NMEA, can set the clock, and publishes a - # `gps` ubus object. It knows nothing about modems, and it reads its tty from - # a STATIC /etc/config/gps — which is exactly the gap this package fills, - # because wwand's NMEA port is discovered and can move between boots or when - # a modem is replaced. - DEPENDS:=+wwand +ugps + TITLE:=GNSS/NMEA reader for wwand + # Reads NMEA off the modem's own port and reports it through wwand's ubus. + # It used to drive ugps (OpenWrt base) instead, and no longer depends on it: + # ugps takes ONE static tty out of /etc/config/gps and publishes ONE `gps` + # object, so a two-modem box could only ever have one position; it exits on + # tty EOF, which on a modem reset means respawning against a device that is + # not back; and it parses neither GSV (satellites in view) nor GSA (fix type, + # PDOP/VDOP) and drops every talker but $GP/$GN. wwand already finds the + # port, starts the receiver and owns the lifecycle, so the reading is the + # small part. Installing ugps alongside is harmless — wwand does not touch + # /etc/config/gps and does not claim the `gps` ubus name. + DEPENDS:=+wwand endef define Package/wwand-gps/description - Joins three pieces that already existed with nothing between them: wwand finds - the modem's NMEA port during enumeration (reported as `gps_port`), `option - gnss` starts the receiver with the vendor AT command — QMI's LOC service is - broken on Quectel and AT is what works, and only wwand has the port — and ugps - reads the NMEA and publishes a position. + wwand finds the modem's NMEA port during enumeration (reported as `gps_port`) + and `option gnss` starts the receiver with the vendor AT command — QMI's LOC + service is broken on Quectel and AT is what works, and only wwand has the + port. This package reads that port: NMEA 0183 framing, checksums, RMC/GGA/GSA/ + GSV/GLL/VTG/ZDA from ANY talker, reported through `modem_gps` as numbers, with + the satellites in view and their SNR, the fix type and the DOP values. - What this adds is the config write that connects them, plus a `modem_gps` ubus - method that answers with both halves at once: the port and receiver state wwand - knows, merged with whatever ugps reports. + ONE READER PER MODEM, so a two-modem router has two positions. `option + gnss_set_time` hands the receiver's clock to wwand's own set_clock, which only + ever steps a clock that is plainly unset and so never fights sysntpd. - Good citizen: it manages exactly one `config gps` section and only one it - created itself (marked `option wwand '1'`). An operator's own section — a hat - GPS on a serial port, a second receiver — is never touched or repointed. + Good citizen: it writes no config at all and does not claim the `gps` ubus + name, so ugps and an operator's own receiver are unaffected by installing it. + One port is only ever read once — a second modem naming a tty that is already + being read is refused rather than given half a stream. endef define Package/wwand-gps/install $(INSTALL_DIR) $(1)$(UCDIR) $(INSTALL_DATA) $(WWAND_UCODE)/gps.uc $(1)$(UCDIR)/ + $(INSTALL_DATA) $(WWAND_UCODE)/nmea.uc $(1)$(UCDIR)/ endef # ---------------------------------------------------------------------------