diff --git a/luci-app-homeproxy-pro-pro/Makefile b/luci-app-homeproxy-pro-pro/Makefile index c0a2f4a8c..880c463b1 100644 --- a/luci-app-homeproxy-pro-pro/Makefile +++ b/luci-app-homeproxy-pro-pro/Makefile @@ -23,7 +23,7 @@ LUCI_DEPENDS:= \ PKG_NAME:=luci-app-homeproxy PKG_VERSION:=28.9.1.14 -PKG_RELEASE:=1 +PKG_RELEASE:=2 # Only files the package actually ships belong here. The previous list named # four paths that exist nowhere in the tree - certs/ and ruleset/ are created at diff --git a/luci-app-homeproxy-pro-pro/htdocs/luci-static/resources/homeproxy.js b/luci-app-homeproxy-pro-pro/htdocs/luci-static/resources/homeproxy-pro.js similarity index 100% rename from luci-app-homeproxy-pro-pro/htdocs/luci-static/resources/homeproxy.js rename to luci-app-homeproxy-pro-pro/htdocs/luci-static/resources/homeproxy-pro.js diff --git a/luci-app-homeproxy-pro-pro/htdocs/luci-static/resources/view/homeproxy/client.js b/luci-app-homeproxy-pro-pro/htdocs/luci-static/resources/view/homeproxy-pro/client.js similarity index 100% rename from luci-app-homeproxy-pro-pro/htdocs/luci-static/resources/view/homeproxy/client.js rename to luci-app-homeproxy-pro-pro/htdocs/luci-static/resources/view/homeproxy-pro/client.js diff --git a/luci-app-homeproxy-pro-pro/htdocs/luci-static/resources/view/homeproxy/client/access.js b/luci-app-homeproxy-pro-pro/htdocs/luci-static/resources/view/homeproxy-pro/client/access.js similarity index 100% rename from luci-app-homeproxy-pro-pro/htdocs/luci-static/resources/view/homeproxy/client/access.js rename to luci-app-homeproxy-pro-pro/htdocs/luci-static/resources/view/homeproxy-pro/client/access.js diff --git a/luci-app-homeproxy-pro-pro/htdocs/luci-static/resources/view/homeproxy/client/common.js b/luci-app-homeproxy-pro-pro/htdocs/luci-static/resources/view/homeproxy-pro/client/common.js similarity index 100% rename from luci-app-homeproxy-pro-pro/htdocs/luci-static/resources/view/homeproxy/client/common.js rename to luci-app-homeproxy-pro-pro/htdocs/luci-static/resources/view/homeproxy-pro/client/common.js diff --git a/luci-app-homeproxy-pro-pro/htdocs/luci-static/resources/view/homeproxy/client/dns.js b/luci-app-homeproxy-pro-pro/htdocs/luci-static/resources/view/homeproxy-pro/client/dns.js similarity index 100% rename from luci-app-homeproxy-pro-pro/htdocs/luci-static/resources/view/homeproxy/client/dns.js rename to luci-app-homeproxy-pro-pro/htdocs/luci-static/resources/view/homeproxy-pro/client/dns.js diff --git a/luci-app-homeproxy-pro-pro/htdocs/luci-static/resources/view/homeproxy/client/nodes.js b/luci-app-homeproxy-pro-pro/htdocs/luci-static/resources/view/homeproxy-pro/client/nodes.js similarity index 100% rename from luci-app-homeproxy-pro-pro/htdocs/luci-static/resources/view/homeproxy/client/nodes.js rename to luci-app-homeproxy-pro-pro/htdocs/luci-static/resources/view/homeproxy-pro/client/nodes.js diff --git a/luci-app-homeproxy-pro-pro/htdocs/luci-static/resources/view/homeproxy/client/routing.js b/luci-app-homeproxy-pro-pro/htdocs/luci-static/resources/view/homeproxy-pro/client/routing.js similarity index 100% rename from luci-app-homeproxy-pro-pro/htdocs/luci-static/resources/view/homeproxy/client/routing.js rename to luci-app-homeproxy-pro-pro/htdocs/luci-static/resources/view/homeproxy-pro/client/routing.js diff --git a/luci-app-homeproxy-pro-pro/htdocs/luci-static/resources/view/homeproxy/client/subscription.js b/luci-app-homeproxy-pro-pro/htdocs/luci-static/resources/view/homeproxy-pro/client/subscription.js similarity index 100% rename from luci-app-homeproxy-pro-pro/htdocs/luci-static/resources/view/homeproxy/client/subscription.js rename to luci-app-homeproxy-pro-pro/htdocs/luci-static/resources/view/homeproxy-pro/client/subscription.js diff --git a/luci-app-homeproxy-pro-pro/htdocs/luci-static/resources/view/homeproxy/client/tun_dns.js b/luci-app-homeproxy-pro-pro/htdocs/luci-static/resources/view/homeproxy-pro/client/tun_dns.js similarity index 100% rename from luci-app-homeproxy-pro-pro/htdocs/luci-static/resources/view/homeproxy/client/tun_dns.js rename to luci-app-homeproxy-pro-pro/htdocs/luci-static/resources/view/homeproxy-pro/client/tun_dns.js diff --git a/luci-app-homeproxy-pro-pro/htdocs/luci-static/resources/view/homeproxy/client/udp_nat.js b/luci-app-homeproxy-pro-pro/htdocs/luci-static/resources/view/homeproxy-pro/client/udp_nat.js similarity index 100% rename from luci-app-homeproxy-pro-pro/htdocs/luci-static/resources/view/homeproxy/client/udp_nat.js rename to luci-app-homeproxy-pro-pro/htdocs/luci-static/resources/view/homeproxy-pro/client/udp_nat.js diff --git a/luci-app-homeproxy-pro-pro/htdocs/luci-static/resources/view/homeproxy/node.js b/luci-app-homeproxy-pro-pro/htdocs/luci-static/resources/view/homeproxy-pro/node.js similarity index 100% rename from luci-app-homeproxy-pro-pro/htdocs/luci-static/resources/view/homeproxy/node.js rename to luci-app-homeproxy-pro-pro/htdocs/luci-static/resources/view/homeproxy-pro/node.js diff --git a/luci-app-homeproxy-pro-pro/htdocs/luci-static/resources/view/homeproxy/server.js b/luci-app-homeproxy-pro-pro/htdocs/luci-static/resources/view/homeproxy-pro/server.js similarity index 100% rename from luci-app-homeproxy-pro-pro/htdocs/luci-static/resources/view/homeproxy/server.js rename to luci-app-homeproxy-pro-pro/htdocs/luci-static/resources/view/homeproxy-pro/server.js diff --git a/luci-app-homeproxy-pro-pro/htdocs/luci-static/resources/view/homeproxy/status.js b/luci-app-homeproxy-pro-pro/htdocs/luci-static/resources/view/homeproxy-pro/status.js similarity index 100% rename from luci-app-homeproxy-pro-pro/htdocs/luci-static/resources/view/homeproxy/status.js rename to luci-app-homeproxy-pro-pro/htdocs/luci-static/resources/view/homeproxy-pro/status.js diff --git a/luci-app-homeproxy-pro-pro/po/templates/homeproxy-pro.pot b/luci-app-homeproxy-pro-pro/po/templates/homeproxy-pro-pro.pot similarity index 100% rename from luci-app-homeproxy-pro-pro/po/templates/homeproxy-pro.pot rename to luci-app-homeproxy-pro-pro/po/templates/homeproxy-pro-pro.pot diff --git a/luci-app-homeproxy-pro-pro/po/zh_Hans/homeproxy-pro.po b/luci-app-homeproxy-pro-pro/po/zh_Hans/homeproxy-pro-pro.po similarity index 100% rename from luci-app-homeproxy-pro-pro/po/zh_Hans/homeproxy-pro.po rename to luci-app-homeproxy-pro-pro/po/zh_Hans/homeproxy-pro-pro.po diff --git a/luci-app-homeproxy-pro-pro/root/etc/capabilities/homeproxy.json b/luci-app-homeproxy-pro-pro/root/etc/capabilities/homeproxy-pro.json similarity index 100% rename from luci-app-homeproxy-pro-pro/root/etc/capabilities/homeproxy.json rename to luci-app-homeproxy-pro-pro/root/etc/capabilities/homeproxy-pro.json diff --git a/luci-app-homeproxy-pro-pro/root/etc/config/homeproxy b/luci-app-homeproxy-pro-pro/root/etc/config/homeproxy-pro similarity index 100% rename from luci-app-homeproxy-pro-pro/root/etc/config/homeproxy rename to luci-app-homeproxy-pro-pro/root/etc/config/homeproxy-pro diff --git a/luci-app-homeproxy-pro-pro/root/etc/homeproxy/resources/china_ip4.txt b/luci-app-homeproxy-pro-pro/root/etc/homeproxy-pro/resources/china_ip4.txt similarity index 100% rename from luci-app-homeproxy-pro-pro/root/etc/homeproxy/resources/china_ip4.txt rename to luci-app-homeproxy-pro-pro/root/etc/homeproxy-pro/resources/china_ip4.txt diff --git a/luci-app-homeproxy-pro-pro/root/etc/homeproxy/resources/china_ip4.ver b/luci-app-homeproxy-pro-pro/root/etc/homeproxy-pro/resources/china_ip4.ver similarity index 100% rename from luci-app-homeproxy-pro-pro/root/etc/homeproxy/resources/china_ip4.ver rename to luci-app-homeproxy-pro-pro/root/etc/homeproxy-pro/resources/china_ip4.ver diff --git a/luci-app-homeproxy-pro-pro/root/etc/homeproxy/resources/china_ip6.txt b/luci-app-homeproxy-pro-pro/root/etc/homeproxy-pro/resources/china_ip6.txt similarity index 100% rename from luci-app-homeproxy-pro-pro/root/etc/homeproxy/resources/china_ip6.txt rename to luci-app-homeproxy-pro-pro/root/etc/homeproxy-pro/resources/china_ip6.txt diff --git a/luci-app-homeproxy-pro-pro/root/etc/homeproxy/resources/china_ip6.ver b/luci-app-homeproxy-pro-pro/root/etc/homeproxy-pro/resources/china_ip6.ver similarity index 100% rename from luci-app-homeproxy-pro-pro/root/etc/homeproxy/resources/china_ip6.ver rename to luci-app-homeproxy-pro-pro/root/etc/homeproxy-pro/resources/china_ip6.ver diff --git a/luci-app-homeproxy-pro-pro/root/etc/homeproxy/resources/china_list.txt b/luci-app-homeproxy-pro-pro/root/etc/homeproxy-pro/resources/china_list.txt similarity index 100% rename from luci-app-homeproxy-pro-pro/root/etc/homeproxy/resources/china_list.txt rename to luci-app-homeproxy-pro-pro/root/etc/homeproxy-pro/resources/china_list.txt diff --git a/luci-app-homeproxy-pro-pro/root/etc/homeproxy/resources/china_list.ver b/luci-app-homeproxy-pro-pro/root/etc/homeproxy-pro/resources/china_list.ver similarity index 100% rename from luci-app-homeproxy-pro-pro/root/etc/homeproxy/resources/china_list.ver rename to luci-app-homeproxy-pro-pro/root/etc/homeproxy-pro/resources/china_list.ver diff --git a/luci-app-homeproxy-pro-pro/root/etc/homeproxy/resources/gfw_list.txt b/luci-app-homeproxy-pro-pro/root/etc/homeproxy-pro/resources/gfw_list.txt similarity index 100% rename from luci-app-homeproxy-pro-pro/root/etc/homeproxy/resources/gfw_list.txt rename to luci-app-homeproxy-pro-pro/root/etc/homeproxy-pro/resources/gfw_list.txt diff --git a/luci-app-homeproxy-pro-pro/root/etc/homeproxy/resources/gfw_list.ver b/luci-app-homeproxy-pro-pro/root/etc/homeproxy-pro/resources/gfw_list.ver similarity index 100% rename from luci-app-homeproxy-pro-pro/root/etc/homeproxy/resources/gfw_list.ver rename to luci-app-homeproxy-pro-pro/root/etc/homeproxy-pro/resources/gfw_list.ver diff --git a/luci-app-homeproxy-pro-pro/root/etc/homeproxy/scripts/clean_log.sh b/luci-app-homeproxy-pro-pro/root/etc/homeproxy-pro/scripts/clean_log.sh similarity index 100% rename from luci-app-homeproxy-pro-pro/root/etc/homeproxy/scripts/clean_log.sh rename to luci-app-homeproxy-pro-pro/root/etc/homeproxy-pro/scripts/clean_log.sh diff --git a/luci-app-homeproxy-pro-pro/root/etc/homeproxy/scripts/config/adapter.uc b/luci-app-homeproxy-pro-pro/root/etc/homeproxy-pro/scripts/config/adapter.uc similarity index 100% rename from luci-app-homeproxy-pro-pro/root/etc/homeproxy/scripts/config/adapter.uc rename to luci-app-homeproxy-pro-pro/root/etc/homeproxy-pro/scripts/config/adapter.uc diff --git a/luci-app-homeproxy-pro-pro/root/etc/homeproxy/scripts/config/loader.uc b/luci-app-homeproxy-pro-pro/root/etc/homeproxy-pro/scripts/config/loader.uc similarity index 100% rename from luci-app-homeproxy-pro-pro/root/etc/homeproxy/scripts/config/loader.uc rename to luci-app-homeproxy-pro-pro/root/etc/homeproxy-pro/scripts/config/loader.uc diff --git a/luci-app-homeproxy-pro-pro/root/etc/homeproxy/scripts/config/model.uc b/luci-app-homeproxy-pro-pro/root/etc/homeproxy-pro/scripts/config/model.uc similarity index 100% rename from luci-app-homeproxy-pro-pro/root/etc/homeproxy/scripts/config/model.uc rename to luci-app-homeproxy-pro-pro/root/etc/homeproxy-pro/scripts/config/model.uc diff --git a/luci-app-homeproxy-pro-pro/root/etc/homeproxy/scripts/firewall_post.ut b/luci-app-homeproxy-pro-pro/root/etc/homeproxy-pro/scripts/firewall_post.ut similarity index 100% rename from luci-app-homeproxy-pro-pro/root/etc/homeproxy/scripts/firewall_post.ut rename to luci-app-homeproxy-pro-pro/root/etc/homeproxy-pro/scripts/firewall_post.ut diff --git a/luci-app-homeproxy-pro-pro/root/etc/homeproxy/scripts/firewall_pre.uc b/luci-app-homeproxy-pro-pro/root/etc/homeproxy-pro/scripts/firewall_pre.uc similarity index 100% rename from luci-app-homeproxy-pro-pro/root/etc/homeproxy/scripts/firewall_pre.uc rename to luci-app-homeproxy-pro-pro/root/etc/homeproxy-pro/scripts/firewall_pre.uc diff --git a/luci-app-homeproxy-pro-pro/root/etc/homeproxy/scripts/firewall_utils.uc b/luci-app-homeproxy-pro-pro/root/etc/homeproxy-pro/scripts/firewall_utils.uc similarity index 100% rename from luci-app-homeproxy-pro-pro/root/etc/homeproxy/scripts/firewall_utils.uc rename to luci-app-homeproxy-pro-pro/root/etc/homeproxy-pro/scripts/firewall_utils.uc diff --git a/luci-app-homeproxy-pro-pro/root/etc/homeproxy/scripts/fw4_names.sh b/luci-app-homeproxy-pro-pro/root/etc/homeproxy-pro/scripts/fw4_names.sh similarity index 100% rename from luci-app-homeproxy-pro-pro/root/etc/homeproxy/scripts/fw4_names.sh rename to luci-app-homeproxy-pro-pro/root/etc/homeproxy-pro/scripts/fw4_names.sh diff --git a/luci-app-homeproxy-pro-pro/root/etc/homeproxy/scripts/generate_client.uc b/luci-app-homeproxy-pro-pro/root/etc/homeproxy-pro/scripts/generate_client.uc similarity index 100% rename from luci-app-homeproxy-pro-pro/root/etc/homeproxy/scripts/generate_client.uc rename to luci-app-homeproxy-pro-pro/root/etc/homeproxy-pro/scripts/generate_client.uc diff --git a/luci-app-homeproxy-pro-pro/root/etc/homeproxy/scripts/generate_server.uc b/luci-app-homeproxy-pro-pro/root/etc/homeproxy-pro/scripts/generate_server.uc similarity index 100% rename from luci-app-homeproxy-pro-pro/root/etc/homeproxy/scripts/generate_server.uc rename to luci-app-homeproxy-pro-pro/root/etc/homeproxy-pro/scripts/generate_server.uc diff --git a/luci-app-homeproxy-pro-pro/root/etc/homeproxy/scripts/generator/client.uc b/luci-app-homeproxy-pro-pro/root/etc/homeproxy-pro/scripts/generator/client.uc similarity index 100% rename from luci-app-homeproxy-pro-pro/root/etc/homeproxy/scripts/generator/client.uc rename to luci-app-homeproxy-pro-pro/root/etc/homeproxy-pro/scripts/generator/client.uc diff --git a/luci-app-homeproxy-pro-pro/root/etc/homeproxy/scripts/generator/common.uc b/luci-app-homeproxy-pro-pro/root/etc/homeproxy-pro/scripts/generator/common.uc similarity index 100% rename from luci-app-homeproxy-pro-pro/root/etc/homeproxy/scripts/generator/common.uc rename to luci-app-homeproxy-pro-pro/root/etc/homeproxy-pro/scripts/generator/common.uc diff --git a/luci-app-homeproxy-pro-pro/root/etc/homeproxy/scripts/generator/context.uc b/luci-app-homeproxy-pro-pro/root/etc/homeproxy-pro/scripts/generator/context.uc similarity index 100% rename from luci-app-homeproxy-pro-pro/root/etc/homeproxy/scripts/generator/context.uc rename to luci-app-homeproxy-pro-pro/root/etc/homeproxy-pro/scripts/generator/context.uc diff --git a/luci-app-homeproxy-pro-pro/root/etc/homeproxy/scripts/generator/dns.uc b/luci-app-homeproxy-pro-pro/root/etc/homeproxy-pro/scripts/generator/dns.uc similarity index 100% rename from luci-app-homeproxy-pro-pro/root/etc/homeproxy/scripts/generator/dns.uc rename to luci-app-homeproxy-pro-pro/root/etc/homeproxy-pro/scripts/generator/dns.uc diff --git a/luci-app-homeproxy-pro-pro/root/etc/homeproxy/scripts/generator/inbound.uc b/luci-app-homeproxy-pro-pro/root/etc/homeproxy-pro/scripts/generator/inbound.uc similarity index 100% rename from luci-app-homeproxy-pro-pro/root/etc/homeproxy/scripts/generator/inbound.uc rename to luci-app-homeproxy-pro-pro/root/etc/homeproxy-pro/scripts/generator/inbound.uc diff --git a/luci-app-homeproxy-pro-pro/root/etc/homeproxy/scripts/generator/outbound.uc b/luci-app-homeproxy-pro-pro/root/etc/homeproxy-pro/scripts/generator/outbound.uc similarity index 100% rename from luci-app-homeproxy-pro-pro/root/etc/homeproxy/scripts/generator/outbound.uc rename to luci-app-homeproxy-pro-pro/root/etc/homeproxy-pro/scripts/generator/outbound.uc diff --git a/luci-app-homeproxy-pro-pro/root/etc/homeproxy/scripts/generator/route.uc b/luci-app-homeproxy-pro-pro/root/etc/homeproxy-pro/scripts/generator/route.uc similarity index 100% rename from luci-app-homeproxy-pro-pro/root/etc/homeproxy/scripts/generator/route.uc rename to luci-app-homeproxy-pro-pro/root/etc/homeproxy-pro/scripts/generator/route.uc diff --git a/luci-app-homeproxy-pro-pro/root/etc/homeproxy/scripts/generator/ruleset.uc b/luci-app-homeproxy-pro-pro/root/etc/homeproxy-pro/scripts/generator/ruleset.uc similarity index 100% rename from luci-app-homeproxy-pro-pro/root/etc/homeproxy/scripts/generator/ruleset.uc rename to luci-app-homeproxy-pro-pro/root/etc/homeproxy-pro/scripts/generator/ruleset.uc diff --git a/luci-app-homeproxy-pro-pro/root/etc/homeproxy/scripts/generator/server.uc b/luci-app-homeproxy-pro-pro/root/etc/homeproxy-pro/scripts/generator/server.uc similarity index 100% rename from luci-app-homeproxy-pro-pro/root/etc/homeproxy/scripts/generator/server.uc rename to luci-app-homeproxy-pro-pro/root/etc/homeproxy-pro/scripts/generator/server.uc diff --git a/luci-app-homeproxy-pro-pro/root/etc/homeproxy/scripts/homeproxy.uc b/luci-app-homeproxy-pro-pro/root/etc/homeproxy-pro/scripts/homeproxy-pro.uc similarity index 100% rename from luci-app-homeproxy-pro-pro/root/etc/homeproxy/scripts/homeproxy.uc rename to luci-app-homeproxy-pro-pro/root/etc/homeproxy-pro/scripts/homeproxy-pro.uc diff --git a/luci-app-homeproxy-pro-pro/root/etc/homeproxy/scripts/migrate_config.uc b/luci-app-homeproxy-pro-pro/root/etc/homeproxy-pro/scripts/migrate_config.uc similarity index 100% rename from luci-app-homeproxy-pro-pro/root/etc/homeproxy/scripts/migrate_config.uc rename to luci-app-homeproxy-pro-pro/root/etc/homeproxy-pro/scripts/migrate_config.uc diff --git a/luci-app-homeproxy-pro-pro/root/etc/homeproxy/scripts/parser/flatten.uc b/luci-app-homeproxy-pro-pro/root/etc/homeproxy-pro/scripts/parser/flatten.uc similarity index 100% rename from luci-app-homeproxy-pro-pro/root/etc/homeproxy/scripts/parser/flatten.uc rename to luci-app-homeproxy-pro-pro/root/etc/homeproxy-pro/scripts/parser/flatten.uc diff --git a/luci-app-homeproxy-pro-pro/root/etc/homeproxy/scripts/parser/mapping.uc b/luci-app-homeproxy-pro-pro/root/etc/homeproxy-pro/scripts/parser/mapping.uc similarity index 100% rename from luci-app-homeproxy-pro-pro/root/etc/homeproxy/scripts/parser/mapping.uc rename to luci-app-homeproxy-pro-pro/root/etc/homeproxy-pro/scripts/parser/mapping.uc diff --git a/luci-app-homeproxy-pro-pro/root/etc/homeproxy/scripts/parser/normalize.uc b/luci-app-homeproxy-pro-pro/root/etc/homeproxy-pro/scripts/parser/normalize.uc similarity index 100% rename from luci-app-homeproxy-pro-pro/root/etc/homeproxy/scripts/parser/normalize.uc rename to luci-app-homeproxy-pro-pro/root/etc/homeproxy-pro/scripts/parser/normalize.uc diff --git a/luci-app-homeproxy-pro-pro/root/etc/homeproxy/scripts/parser/protocols.uc b/luci-app-homeproxy-pro-pro/root/etc/homeproxy-pro/scripts/parser/protocols.uc similarity index 100% rename from luci-app-homeproxy-pro-pro/root/etc/homeproxy/scripts/parser/protocols.uc rename to luci-app-homeproxy-pro-pro/root/etc/homeproxy-pro/scripts/parser/protocols.uc diff --git a/luci-app-homeproxy-pro-pro/root/etc/homeproxy/scripts/parser/uri.uc b/luci-app-homeproxy-pro-pro/root/etc/homeproxy-pro/scripts/parser/uri.uc similarity index 100% rename from luci-app-homeproxy-pro-pro/root/etc/homeproxy/scripts/parser/uri.uc rename to luci-app-homeproxy-pro-pro/root/etc/homeproxy-pro/scripts/parser/uri.uc diff --git a/luci-app-homeproxy-pro-pro/root/etc/homeproxy/scripts/parser/validator.uc b/luci-app-homeproxy-pro-pro/root/etc/homeproxy-pro/scripts/parser/validator.uc similarity index 100% rename from luci-app-homeproxy-pro-pro/root/etc/homeproxy/scripts/parser/validator.uc rename to luci-app-homeproxy-pro-pro/root/etc/homeproxy-pro/scripts/parser/validator.uc diff --git a/luci-app-homeproxy-pro-pro/root/etc/homeproxy/scripts/resource_blob_sha.uc b/luci-app-homeproxy-pro-pro/root/etc/homeproxy-pro/scripts/resource_blob_sha.uc similarity index 100% rename from luci-app-homeproxy-pro-pro/root/etc/homeproxy/scripts/resource_blob_sha.uc rename to luci-app-homeproxy-pro-pro/root/etc/homeproxy-pro/scripts/resource_blob_sha.uc diff --git a/luci-app-homeproxy-pro-pro/root/etc/homeproxy/scripts/runtime/config.sh b/luci-app-homeproxy-pro-pro/root/etc/homeproxy-pro/scripts/runtime/config.sh similarity index 100% rename from luci-app-homeproxy-pro-pro/root/etc/homeproxy/scripts/runtime/config.sh rename to luci-app-homeproxy-pro-pro/root/etc/homeproxy-pro/scripts/runtime/config.sh diff --git a/luci-app-homeproxy-pro-pro/root/etc/homeproxy/scripts/runtime/dns.sh b/luci-app-homeproxy-pro-pro/root/etc/homeproxy-pro/scripts/runtime/dns.sh similarity index 100% rename from luci-app-homeproxy-pro-pro/root/etc/homeproxy/scripts/runtime/dns.sh rename to luci-app-homeproxy-pro-pro/root/etc/homeproxy-pro/scripts/runtime/dns.sh diff --git a/luci-app-homeproxy-pro-pro/root/etc/homeproxy/scripts/runtime/firewall.sh b/luci-app-homeproxy-pro-pro/root/etc/homeproxy-pro/scripts/runtime/firewall.sh similarity index 100% rename from luci-app-homeproxy-pro-pro/root/etc/homeproxy/scripts/runtime/firewall.sh rename to luci-app-homeproxy-pro-pro/root/etc/homeproxy-pro/scripts/runtime/firewall.sh diff --git a/luci-app-homeproxy-pro-pro/root/etc/homeproxy/scripts/runtime/health.sh b/luci-app-homeproxy-pro-pro/root/etc/homeproxy-pro/scripts/runtime/health.sh similarity index 100% rename from luci-app-homeproxy-pro-pro/root/etc/homeproxy/scripts/runtime/health.sh rename to luci-app-homeproxy-pro-pro/root/etc/homeproxy-pro/scripts/runtime/health.sh diff --git a/luci-app-homeproxy-pro-pro/root/etc/homeproxy/scripts/runtime/net.sh b/luci-app-homeproxy-pro-pro/root/etc/homeproxy-pro/scripts/runtime/net.sh similarity index 100% rename from luci-app-homeproxy-pro-pro/root/etc/homeproxy/scripts/runtime/net.sh rename to luci-app-homeproxy-pro-pro/root/etc/homeproxy-pro/scripts/runtime/net.sh diff --git a/luci-app-homeproxy-pro-pro/root/etc/homeproxy/scripts/runtime/service.sh b/luci-app-homeproxy-pro-pro/root/etc/homeproxy-pro/scripts/runtime/service.sh similarity index 100% rename from luci-app-homeproxy-pro-pro/root/etc/homeproxy/scripts/runtime/service.sh rename to luci-app-homeproxy-pro-pro/root/etc/homeproxy-pro/scripts/runtime/service.sh diff --git a/luci-app-homeproxy-pro-pro/root/etc/homeproxy/scripts/subscription/decoder.uc b/luci-app-homeproxy-pro-pro/root/etc/homeproxy-pro/scripts/subscription/decoder.uc similarity index 100% rename from luci-app-homeproxy-pro-pro/root/etc/homeproxy/scripts/subscription/decoder.uc rename to luci-app-homeproxy-pro-pro/root/etc/homeproxy-pro/scripts/subscription/decoder.uc diff --git a/luci-app-homeproxy-pro-pro/root/etc/homeproxy/scripts/subscription/fetcher.uc b/luci-app-homeproxy-pro-pro/root/etc/homeproxy-pro/scripts/subscription/fetcher.uc similarity index 100% rename from luci-app-homeproxy-pro-pro/root/etc/homeproxy/scripts/subscription/fetcher.uc rename to luci-app-homeproxy-pro-pro/root/etc/homeproxy-pro/scripts/subscription/fetcher.uc diff --git a/luci-app-homeproxy-pro-pro/root/etc/homeproxy/scripts/subscription/filter.uc b/luci-app-homeproxy-pro-pro/root/etc/homeproxy-pro/scripts/subscription/filter.uc similarity index 100% rename from luci-app-homeproxy-pro-pro/root/etc/homeproxy/scripts/subscription/filter.uc rename to luci-app-homeproxy-pro-pro/root/etc/homeproxy-pro/scripts/subscription/filter.uc diff --git a/luci-app-homeproxy-pro-pro/root/etc/homeproxy/scripts/subscription/repository.uc b/luci-app-homeproxy-pro-pro/root/etc/homeproxy-pro/scripts/subscription/repository.uc similarity index 100% rename from luci-app-homeproxy-pro-pro/root/etc/homeproxy/scripts/subscription/repository.uc rename to luci-app-homeproxy-pro-pro/root/etc/homeproxy-pro/scripts/subscription/repository.uc diff --git a/luci-app-homeproxy-pro-pro/root/etc/homeproxy/scripts/update_crond.sh b/luci-app-homeproxy-pro-pro/root/etc/homeproxy-pro/scripts/update_crond.sh similarity index 100% rename from luci-app-homeproxy-pro-pro/root/etc/homeproxy/scripts/update_crond.sh rename to luci-app-homeproxy-pro-pro/root/etc/homeproxy-pro/scripts/update_crond.sh diff --git a/luci-app-homeproxy-pro-pro/root/etc/homeproxy/scripts/update_resources.sh b/luci-app-homeproxy-pro-pro/root/etc/homeproxy-pro/scripts/update_resources.sh similarity index 100% rename from luci-app-homeproxy-pro-pro/root/etc/homeproxy/scripts/update_resources.sh rename to luci-app-homeproxy-pro-pro/root/etc/homeproxy-pro/scripts/update_resources.sh diff --git a/luci-app-homeproxy-pro-pro/root/etc/homeproxy/scripts/update_subscriptions.uc b/luci-app-homeproxy-pro-pro/root/etc/homeproxy-pro/scripts/update_subscriptions.uc similarity index 100% rename from luci-app-homeproxy-pro-pro/root/etc/homeproxy/scripts/update_subscriptions.uc rename to luci-app-homeproxy-pro-pro/root/etc/homeproxy-pro/scripts/update_subscriptions.uc diff --git a/luci-app-homeproxy-pro-pro/root/etc/init.d/homeproxy b/luci-app-homeproxy-pro-pro/root/etc/init.d/homeproxy-pro similarity index 100% rename from luci-app-homeproxy-pro-pro/root/etc/init.d/homeproxy rename to luci-app-homeproxy-pro-pro/root/etc/init.d/homeproxy-pro diff --git a/luci-app-homeproxy-pro-pro/root/etc/uci-defaults/luci-homeproxy b/luci-app-homeproxy-pro-pro/root/etc/uci-defaults/luci-homeproxy-pro similarity index 100% rename from luci-app-homeproxy-pro-pro/root/etc/uci-defaults/luci-homeproxy rename to luci-app-homeproxy-pro-pro/root/etc/uci-defaults/luci-homeproxy-pro diff --git a/luci-app-homeproxy-pro-pro/root/etc/uci-defaults/luci-homeproxy-migration b/luci-app-homeproxy-pro-pro/root/etc/uci-defaults/luci-homeproxy-pro-migration similarity index 100% rename from luci-app-homeproxy-pro-pro/root/etc/uci-defaults/luci-homeproxy-migration rename to luci-app-homeproxy-pro-pro/root/etc/uci-defaults/luci-homeproxy-pro-migration diff --git a/luci-app-homeproxy-pro-pro/root/usr/share/rpcd/ucode/luci.homeproxy b/luci-app-homeproxy-pro-pro/root/usr/share/rpcd/ucode/luci.homeproxy-pro similarity index 100% rename from luci-app-homeproxy-pro-pro/root/usr/share/rpcd/ucode/luci.homeproxy rename to luci-app-homeproxy-pro-pro/root/usr/share/rpcd/ucode/luci.homeproxy-pro diff --git a/luci-app-homeproxy-pro-pro/tests/ucode/mocks/homeproxy.uc b/luci-app-homeproxy-pro-pro/tests/ucode/mocks/homeproxy-pro.uc similarity index 100% rename from luci-app-homeproxy-pro-pro/tests/ucode/mocks/homeproxy.uc rename to luci-app-homeproxy-pro-pro/tests/ucode/mocks/homeproxy-pro.uc diff --git a/luci-app-homeproxy-pro-pro/tests/ucode/mocks/homeproxy_fetcher.uc b/luci-app-homeproxy-pro-pro/tests/ucode/mocks/homeproxy-pro_fetcher.uc similarity index 100% rename from luci-app-homeproxy-pro-pro/tests/ucode/mocks/homeproxy_fetcher.uc rename to luci-app-homeproxy-pro-pro/tests/ucode/mocks/homeproxy-pro_fetcher.uc diff --git a/luci-app-homeproxy-pro-pro/tests/ucode/mocks/homeproxy_firewall.uc b/luci-app-homeproxy-pro-pro/tests/ucode/mocks/homeproxy-pro_firewall.uc similarity index 100% rename from luci-app-homeproxy-pro-pro/tests/ucode/mocks/homeproxy_firewall.uc rename to luci-app-homeproxy-pro-pro/tests/ucode/mocks/homeproxy-pro_firewall.uc diff --git a/luci-app-homeproxy-pro-pro/tests/ucode/test_homeproxy_utils.uc b/luci-app-homeproxy-pro-pro/tests/ucode/test_homeproxy-pro_utils.uc similarity index 100% rename from luci-app-homeproxy-pro-pro/tests/ucode/test_homeproxy_utils.uc rename to luci-app-homeproxy-pro-pro/tests/ucode/test_homeproxy-pro_utils.uc diff --git a/luci-app-homeproxy-pro-pro/tests/ucode/test_homeproxy_utils_inject.uc b/luci-app-homeproxy-pro-pro/tests/ucode/test_homeproxy-pro_utils_inject.uc similarity index 100% rename from luci-app-homeproxy-pro-pro/tests/ucode/test_homeproxy_utils_inject.uc rename to luci-app-homeproxy-pro-pro/tests/ucode/test_homeproxy-pro_utils_inject.uc diff --git a/luci-app-trafficctl/Makefile b/luci-app-trafficctl/Makefile index 708a02b37..37fed11eb 100644 --- a/luci-app-trafficctl/Makefile +++ b/luci-app-trafficctl/Makefile @@ -2,7 +2,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=luci-app-trafficctl PKG_VERSION:=1.18.0 -PKG_RELEASE:=2 +PKG_RELEASE:=3 PKG_LICENSE:=Apache-2.0 PKG_MAINTAINER:=Denis Iusupov diff --git a/luci-app-trafficctl/htdocs/luci-static/resources/view/trafficctl/status.js b/luci-app-trafficctl/htdocs/luci-static/resources/view/trafficctl/status.js index ee466a6e0..c3c29b9d2 100644 --- a/luci-app-trafficctl/htdocs/luci-static/resources/view/trafficctl/status.js +++ b/luci-app-trafficctl/htdocs/luci-static/resources/view/trafficctl/status.js @@ -431,6 +431,21 @@ function mkEthIcon(size) { return svg; } +// Marks a device that the WiFi MAC filter lists as blocked. `pending` is the +// backend's wifi_block_pending: the device is on the deny list AND associated +// on a radio right now, which is proof the running hostapd ACL never got the +// block. Saying "blocked" there is the lie this whole change exists to remove, +// so that case gets its own wording and colour. +function mkWifiBlockBadge(pending) { + return E('span', { + 'class': pending ? 'tc-c-err tc-fw-bold' : 'tc-c-warn tc-fw-bold', + 'style': 'margin-left:4px;cursor:help;white-space:nowrap', + 'title': pending + ? _('On the WiFi deny list but still connected — the block is NOT in effect on the running radio. Install hostapd-utils so blocks apply immediately, or restart WiFi (disconnects every client).') + : _('Blocked from WiFi (MAC deny list)') + }, pending ? '📵⚠' : '📵'); +} + function renderSparkline(history, globalMax, width, height, limitKbit) { if (!history || history.length < 2) return null; var maxVal = globalMax || 1; @@ -1322,6 +1337,15 @@ function buildSummaryTable(rows, sortCol, sortDir, onSort, onSelect, speedMap, d linkBadge = E('span', { 'class': 'tc-c-muted' }, [mkEthIcon(14), document.createTextNode(ethLabel)]); } cellMap.conn_type = E('div', { 'class': 'td tc-center' }, linkBadge); + // A WiFi block used to show in the row only as the line-through above, + // which lives inside the isWifi branch — so it disappeared from the row + // in the two cases that matter most: a block that WORKED (the device + // stops associating, the cell falls through to "?" or eth) and a device + // blocked while sitting on cable. Mark it in every branch, with a label + // and a tooltip rather than a text decoration nobody reads as "blocked". + if (r.wifi_blocked) { + cellMap.conn_type.appendChild(mkWifiBlockBadge(r.wifi_block_pending)); + } var appBadge; if (r.app) { @@ -2791,9 +2815,18 @@ return view.extend({ parts.push(_('Dropped') + ': 🚫 '+(Number(dm.packets) || 0)+' pkts / '+fmtBytes(dm.bytes||0)+''); } } - var wifiPart = data.wifi_blocked - ? '  |  📵 ' + _('WiFi blocked') + ' ('+escHtml(data.mac||'') + ')' - : (data.mac ? '  |  MAC: '+escHtml(data.mac)+'' : ''); + // Listed but still associated is not a block, so it must not + // read as one — that claim is the whole bug. + var wifiPart; + if (data.wifi_blocked && data.wifi_block_pending) { + wifiPart = '  |  📵⚠ ' + _('WiFi block NOT in effect') + ' — ' + + _('on the deny list but still connected; install hostapd-utils or restart WiFi') + + ' ('+escHtml(data.mac||'') + ')'; + } else if (data.wifi_blocked) { + wifiPart = '  |  📵 ' + _('WiFi blocked') + ' ('+escHtml(data.mac||'') + ')'; + } else { + wifiPart = data.mac ? '  |  MAC: '+escHtml(data.mac)+'' : ''; + } statsDiv.className = 'alert-message ' + (data.blocked ? 'error' : 'info'); statsDiv.innerHTML = (data.blocked ? '⛔ ' + _('BLOCKED') + ' — '+(Number(data.block_packets) || 0)+' pkts, '+fmtBytes(Number(data.block_bytes) || 0)+' ' + _('dropped') + '  |  ' @@ -2969,6 +3002,7 @@ return view.extend({ var shaped = rows.filter(function(r){return (r.shape_kbit||0) > 0;}).length; var blocked = rows.filter(function(r){return r.blocked;}).length; var wifiBlk = rows.filter(function(r){return r.wifi_blocked;}).length; + var wifiPending = rows.filter(function(r){return r.wifi_block_pending;}).length; var totalDropPkts = Object.keys(self._dropMap).reduce(function(s, ip) { return s + (self._dropMap[ip].packets||0); }, 0); var lnk = 'cursor:pointer;text-decoration:underline;text-decoration-style:dashed'; @@ -2987,6 +3021,15 @@ return view.extend({ parts.push(E('span', {}, [document.createTextNode(_('Active') + ': '), E('b', {}, String(rows.length))])); parts.push(E('span', {}, [document.createTextNode(_('Blocked') + ': '), mkFilterVal('blocked', 'var(--tc-err)', String(blocked))])); parts.push(E('span', {}, [document.createTextNode(_('WiFi') + ': '), mkFilterVal('wifi_blocked', 'var(--tc-warn)', String(wifiBlk))])); + // Without this the header counts a device as blocked on the strength of + // the uci maclist alone — which is how a router can report "WiFi: 2" + // while both of those devices are browsing. + if (wifiPending > 0) { + parts.push(E('span', { + 'style': 'color:var(--tc-err);font-weight:700;cursor:help', + 'title': _('Devices on the WiFi deny list that are still connected — those blocks are not in effect on the running radio.') + }, '⚠ ' + wifiPending + ' ' + _('not applied'))); + } if (limited > 0) parts.push(E('span', {}, [document.createTextNode(_('Limited') + ': '), mkFilterVal('limited', 'var(--tc-warn)', '⚡' + limited)])); if (shaped > 0) parts.push(E('span', {}, [document.createTextNode(_('Shaped') + ': '), mkFilterVal('shaped', 'var(--tc-speed)', '🌊' + shaped)])); if (totalDropPkts > 0) { @@ -3130,7 +3173,19 @@ return view.extend({ setStatus(statusDiv, 'loading', (action==='block' ? _('Adding to') : _('Removing from')) + ' ' + _('WiFi deny list') + ': ' + name + '…'); var fn = action === 'block' ? callMacfilterAdd : callMacfilterRemove; fn(ip).then(function(res) { - setStatus(statusDiv, (res && res.ok) ? (action==='block'?'action':'ok') : 'error', (res && res.msg) || '?'); + // res.ok is now true only when the RUNNING radio was verified to + // carry the change, so a config-only write must not paint green. + // "ban" is the partial middle state (temporary hostapd ban, no + // ACL) and gets the attention colour rather than a hard error. + var state; + if (res && res.ok) { + state = (action === 'block') ? 'action' : 'ok'; + } else if (res && res.enforcement === 'ban') { + state = 'action'; + } else { + state = 'error'; + } + setStatus(statusDiv, state, (res && res.msg) || '?'); runQuery(); }).catch(function(e) { setStatus(statusDiv, 'error', '✗ '+e.message); diff --git a/luci-app-trafficctl/root/usr/local/bin/trafficctl-device.sh b/luci-app-trafficctl/root/usr/local/bin/trafficctl-device.sh index 975193395..c0efde9f4 100755 --- a/luci-app-trafficctl/root/usr/local/bin/trafficctl-device.sh +++ b/luci-app-trafficctl/root/usr/local/bin/trafficctl-device.sh @@ -374,8 +374,13 @@ if [ "$DO_RDNS" = "1" ]; then fi fi +# Listed as blocked yet associated right now = the radio never got the block. +WIFI_PENDING=false +tctl_wifi_block_pending "$([ "$WIFI_BLOCKED" = "true" ] && echo 1 || echo 0)" "$CONN_TYPE" \ + && WIFI_PENDING=true + # Output final JSON -printf '{"ip":"%s","name":"%s","mac":"%s","conn_type":"%s","conn_last":"%s","timestamp":%d,"blocked":%s,"block_packets":%d,"block_bytes":%.0f,"wifi_blocked":%s,"total":%.0f,"protocols":{"tcp":%d,"udp":%d,"other":%d},"tcp_states":{"established":%d,"time_wait":%d,"syn_sent":%d,"close_wait":%d},"connections":[%s],"rate_limit_kbit":%d,"shape_kbit":%d}\n' \ +printf '{"ip":"%s","name":"%s","mac":"%s","conn_type":"%s","conn_last":"%s","timestamp":%d,"blocked":%s,"block_packets":%d,"block_bytes":%.0f,"wifi_blocked":%s,"wifi_block_pending":%s,"total":%.0f,"protocols":{"tcp":%d,"udp":%d,"other":%d},"tcp_states":{"established":%d,"time_wait":%d,"syn_sent":%d,"close_wait":%d},"connections":[%s],"rate_limit_kbit":%d,"shape_kbit":%d}\n' \ "$IP" "$NAME" "$MAC" "$CONN_TYPE" "$CONN_LAST" "$TIMESTAMP" "$BLOCKED" "$BLOCK_PACKETS" "$BLOCK_BYTES" \ - "$WIFI_BLOCKED" "$TOTAL" "$N_TCP" "$N_UDP" "$N_OTHER" \ + "$WIFI_BLOCKED" "$WIFI_PENDING" "$TOTAL" "$N_TCP" "$N_UDP" "$N_OTHER" \ "$EST" "$TW" "$SS" "$CW" "$CONNS_OUT" "$RATE_LIM" "$SHAPE_KBIT" diff --git a/luci-app-trafficctl/root/usr/local/bin/trafficctl-fw.sh b/luci-app-trafficctl/root/usr/local/bin/trafficctl-fw.sh index f6b84f9f7..599525044 100755 --- a/luci-app-trafficctl/root/usr/local/bin/trafficctl-fw.sh +++ b/luci-app-trafficctl/root/usr/local/bin/trafficctl-fw.sh @@ -418,12 +418,24 @@ tctl_get_wifi_interfaces() { uci show wireless 2>/dev/null | grep '=wifi-iface' | cut -d. -f2 | cut -d= -f1 } -# Get running WiFi interface names (e.g. wlan0, wlan1) +# Running AP interface names, one per line (e.g. phy0-ap0), taken from the +# hostapd ubus objects. +# +# Returns non-zero when ubus itself could not be consulted. That is NOT the +# same as "no AP is running", and callers must not read an empty list as +# "nothing to enforce" unless the query actually succeeded — doing so would +# turn a broken router into a silent "blocked". tctl_get_hostapd_ifaces() { - ubus list 2>/dev/null | grep '^hostapd\.' | cut -d. -f2 + local out + command -v ubus >/dev/null 2>&1 || return 1 + out=$(ubus list 2>/dev/null) || return 1 + # An empty result is a valid answer -- "no AP is running" -- so the grep + # matching nothing must not be reported as a failed query. Only ubus itself + # failing, above, is that. + printf '%s\n' "$out" | grep '^hostapd\.' | cut -d. -f2- + return 0 } -# Add MAC to hostapd deny ACL at runtime + deauth the client (no wifi reload) # Which ACL policy a wifi-iface uses: "allow" (whitelist — only listed MACs may # associate) or "deny" (blacklist — listed MACs are rejected). Anything else, # including unset, means no filtering is configured yet, reported as "deny" @@ -434,51 +446,187 @@ tctl_get_wifi_filter_mode() { [ "$mode" = "allow" ] && echo "allow" || echo "deny" } -# Block a MAC at runtime. In deny mode that means adding it to the deny ACL; in -# allow (whitelist) mode it means dropping it from the accept ACL. Either way -# the client is deauthenticated so the change takes effect immediately. +# ── Runtime WiFi enforcement ────────────────────────────────────────────── +# +# The uci maclist is the durable half of a WiFi block; hostapd's running ACL is +# the half that decides whether the device is on the air *now*. The two drift +# apart whenever the runtime call cannot be made, and for a long time that +# drift was invisible: the calls below were fire-and-forget, their exit status +# discarded, so a router without hostapd-utils reported every block as done +# while the device kept browsing. +# +# So every entry point here reports how far enforcement actually got, as one +# of these words, and proves it by reading the state back rather than trusting +# a return code: +# +# acl - the running ACL was changed and the change was read back +# ban - no usable hostapd_cli; hostapd's ubus deauthed and banned the +# client, which expires on its own (see TCTL_WIFI_BAN_MS) +# none - nothing could be applied or verified on the running radio +# no-radio - ubus answered and no AP is running, so there is nothing to +# enforce; the uci maclist applies when wifi next starts +# +# Only "acl" and "no-radio" mean the operator's intent is in force, and the +# functions return 0 for exactly those two. + +# How long a ubus ban lasts, in milliseconds. Used only where hostapd_cli is +# unavailable: hostapd's ubus object has no ACL method (del_client, list_bans, +# get_clients, reload), so a timed ban is the strongest immediate measure it +# can offer. One hour is long enough to be worth doing and short enough that +# callers must keep calling it temporary rather than done. +TCTL_WIFI_BAN_MS=3600000 + +# hostapd_cli exists AND this AP's control socket answers. Both halves matter: +# the package can be absent (the router this bug was found on), or present +# while hostapd is not listening, and only a PONG shows the ACL commands will +# reach anything. +tctl_hostapd_cli_alive() { + command -v hostapd_cli >/dev/null 2>&1 || return 1 + hostapd_cli -i "$1" ping 2>/dev/null | grep -q PONG +} + +# Does the running ACL currently keep this MAC off the air? Read back from +# hostapd instead of inferred from our own call: hostapd_cli exits 0 for +# "command delivered", and an ACL that stays empty afterwards is exactly the +# failure being guarded against. hostapd also reloads its maclist file at times +# of its own choosing, so the entry present may not be the one we added — which +# is fine, and another reason to ask rather than assume. +tctl_hostapd_acl_blocks() { + local iface="$1" mac="$2" mode="$3" acl + if [ "$mode" = "allow" ]; then + acl=$(hostapd_cli -i "$iface" accept_acl SHOW 2>/dev/null) + ! printf '%s\n' "$acl" | grep -qi "$mac" + else + acl=$(hostapd_cli -i "$iface" deny_acl SHOW 2>/dev/null) + printf '%s\n' "$acl" | grep -qi "$mac" + fi +} + +tctl_hostapd_ubus_banned() { + local iface="$1" mac="$2" + command -v ubus >/dev/null 2>&1 || return 1 + ubus call "hostapd.$iface" list_bans 2>/dev/null | grep -qi "$mac" +} + +# Fallback when hostapd_cli is unusable. del_client deauthenticates and refuses +# the client for ban_time, which is not an ACL entry — the durable half stays +# the uci maclist. The call's own exit status is deliberately ignored: it can +# fail for a client that is not currently associated while the ban still lands, +# and list_bans is the only answer worth having. +tctl_hostapd_ubus_ban() { + local iface="$1" mac="$2" + command -v ubus >/dev/null 2>&1 || return 1 + ubus call "hostapd.$iface" del_client \ + "{\"addr\":\"$mac\",\"reason\":1,\"deauth\":true,\"ban_time\":$TCTL_WIFI_BAN_MS}" \ + >/dev/null 2>&1 + tctl_hostapd_ubus_banned "$iface" "$mac" +} + +# acl > ban > none, so a loop over several APs can keep the worst result. +tctl_enforce_rank() { + case "$1" in + acl) echo 3 ;; + ban) echo 2 ;; + *) echo 1 ;; + esac +} + +tctl_hostapd_block_iface() { + local iface="$1" mac="$2" mode="$3" + if tctl_hostapd_cli_alive "$iface"; then + if [ "$mode" = "allow" ]; then + hostapd_cli -i "$iface" accept_acl DEL_MAC "$mac" >/dev/null 2>&1 + else + hostapd_cli -i "$iface" deny_acl ADD_MAC "$mac" >/dev/null 2>&1 + fi + hostapd_cli -i "$iface" deauthenticate "$mac" >/dev/null 2>&1 + if tctl_hostapd_acl_blocks "$iface" "$mac" "$mode"; then + echo acl + return + fi + fi + if tctl_hostapd_ubus_ban "$iface" "$mac"; then + echo ban + return + fi + echo none +} + +tctl_hostapd_unblock_iface() { + local iface="$1" mac="$2" mode="$3" + if tctl_hostapd_cli_alive "$iface"; then + if [ "$mode" = "allow" ]; then + hostapd_cli -i "$iface" accept_acl ADD_MAC "$mac" >/dev/null 2>&1 + else + hostapd_cli -i "$iface" deny_acl DEL_MAC "$mac" >/dev/null 2>&1 + fi + if ! tctl_hostapd_acl_blocks "$iface" "$mac" "$mode"; then + # The ACL permits the MAC again, but a ban left over from an + # earlier hostapd_cli-less block would still keep it off the air, + # and there is no ubus method to lift one. + if tctl_hostapd_ubus_banned "$iface" "$mac"; then + echo ban + else + echo acl + fi + return + fi + fi + if tctl_hostapd_ubus_banned "$iface" "$mac"; then + echo ban + return + fi + echo none +} + +# Applies $2 ("allow"/"deny" ACL policy) to every running AP and echoes the +# worst per-AP outcome. Always safe to re-run: it enforces from the runtime +# state, so calling it on a MAC that uci already lists is how a block that was +# only ever written to config gets applied for real. +tctl_hostapd_apply_mac() { + local op="$1" mac="$2" mode="$3" + local ifaces iface state rank worst=3 + ifaces=$(tctl_get_hostapd_ifaces) || { echo none; return 1; } + if [ -z "$ifaces" ]; then + echo no-radio + return 0 + fi + for iface in $ifaces; do + case "$op" in + block) state=$(tctl_hostapd_block_iface "$iface" "$mac" "$mode") ;; + *) state=$(tctl_hostapd_unblock_iface "$iface" "$mac" "$mode") ;; + esac + rank=$(tctl_enforce_rank "$state") + [ "$rank" -lt "$worst" ] && worst="$rank" + done + case "$worst" in + 3) echo acl; return 0 ;; + 2) echo ban ;; + *) echo none ;; + esac + return 1 +} + tctl_hostapd_block_mac() { - local mac="$1" mode="$2" - local iface - for iface in $(tctl_get_hostapd_ifaces); do - if [ "$mode" = "allow" ]; then - hostapd_cli -i "$iface" accept_acl DEL_MAC "$mac" 2>/dev/null - else - hostapd_cli -i "$iface" deny_acl ADD_MAC "$mac" 2>/dev/null - fi - hostapd_cli -i "$iface" deauthenticate "$mac" 2>/dev/null - done + tctl_hostapd_apply_mac block "$1" "$2" } -# Unblock a MAC at runtime — the inverse of tctl_hostapd_block_mac. tctl_hostapd_unblock_mac() { - local mac="$1" mode="$2" - local iface - for iface in $(tctl_get_hostapd_ifaces); do - if [ "$mode" = "allow" ]; then - hostapd_cli -i "$iface" accept_acl ADD_MAC "$mac" 2>/dev/null - else - hostapd_cli -i "$iface" deny_acl DEL_MAC "$mac" 2>/dev/null - fi - done + tctl_hostapd_apply_mac unblock "$1" "$2" } -tctl_hostapd_deny_mac() { - local mac="$1" - local iface - for iface in $(tctl_get_hostapd_ifaces); do - hostapd_cli -i "$iface" deny_acl ADD_MAC "$mac" 2>/dev/null - hostapd_cli -i "$iface" deauthenticate "$mac" 2>/dev/null - done -} - -# Remove MAC from hostapd deny ACL at runtime (client can reassociate immediately) -tctl_hostapd_allow_mac() { - local mac="$1" - local iface - for iface in $(tctl_get_hostapd_ifaces); do - hostapd_cli -i "$iface" deny_acl DEL_MAC "$mac" 2>/dev/null - done +# A device listed as WiFi-blocked while it is associated on a radio right now +# is proof the running ACL does not carry the block — the state a silent +# enforcement failure leaves a router in. Keyed off conn_type rather than the +# station dump so it still holds where iw is missing and the connection type +# came from the bridge port instead. +tctl_wifi_block_pending() { + local blocked="$1" conn_type="$2" + [ "$blocked" = "1" ] || return 1 + case "$conn_type" in + wifi|2.4G|5G|6G) return 0 ;; + esac + return 1 } # ── Persistence ─────────────────────────────────────────────────────────── diff --git a/luci-app-trafficctl/root/usr/local/bin/trafficctl-macfilter-add.sh b/luci-app-trafficctl/root/usr/local/bin/trafficctl-macfilter-add.sh index a8fda1fd3..d62ae04cd 100755 --- a/luci-app-trafficctl/root/usr/local/bin/trafficctl-macfilter-add.sh +++ b/luci-app-trafficctl/root/usr/local/bin/trafficctl-macfilter-add.sh @@ -1,7 +1,9 @@ #!/bin/sh # shellcheck shell=dash # Block device WiFi access by adding its MAC to deny maclist on all interfaces. -# Uses hostapd to deauth only the target client — no wifi reload needed. +# The uci maclist is the durable half; hostapd is then programmed at runtime so +# only the target client is kicked, with no wifi reload. Reports how far that +# runtime half actually got — see the enforcement words in trafficctl-fw.sh. # Usage: trafficctl-macfilter-add.sh . /usr/local/bin/trafficctl-fw.sh @@ -76,11 +78,41 @@ for iface in $IFACES; do fi done -if [ "$CHANGED" = "1" ]; then - uci commit wireless - # Apply at runtime and deauth just this client — no wifi reload. - tctl_hostapd_block_mac "$MAC" "$MODE" -fi +[ "$CHANGED" = "1" ] && uci commit wireless -tctl_log "wifi_block" "$IP" "MAC=$MAC" "${TCTL_VIA:-cli}" "${TCTL_SRC:-local}" -echo "{\"ok\":true,\"msg\":\"MAC $MAC blocked on wifi for $IP\"}" +# Applied unconditionally, not just when uci needed editing. Config and runtime +# are two pieces of state: a router whose maclist already names the MAC but +# whose radio never got the ACL entry used to make this a no-op that still +# reported success, so pressing Block again — the obvious reaction to "it did +# not work" — could never recover it. +ENFORCE=$(tctl_hostapd_block_mac "$MAC" "$MODE") +BAN_MIN=$(( TCTL_WIFI_BAN_MS / 60000 )) + +# The uci entry is kept even when the radio could not be programmed. It is the +# only durable record of the operator's intent and it does take effect at the +# next wifi restart, so discarding it would throw away the half that worked and +# leave the device unblocked forever. What made keeping it dangerous was the +# claim of success, not the entry — so the claim is what goes. A wifi reload +# would apply it now, but it disconnects every client on the radio, which is +# not something a per-device click should do behind the operator's back. +case "$ENFORCE" in + acl) + OK=true + MSG="MAC $MAC blocked on wifi for $IP" + ;; + no-radio) + OK=true + MSG="MAC $MAC added to the wifi deny list for $IP; no radio is running, it applies when wifi starts" + ;; + ban) + OK=false + MSG="MAC $MAC is NOT permanently blocked: hostapd_cli is missing, so the block is temporary ($BAN_MIN min). Install hostapd-utils, or restart wifi (drops all clients)" + ;; + *) + OK=false + MSG="MAC $MAC saved to the wifi deny list but NOT applied to the radio, so the device stays online. Install hostapd-utils, or restart wifi (drops all clients)" + ;; +esac + +tctl_log "wifi_block" "$IP" "MAC=$MAC enforce=$ENFORCE" "${TCTL_VIA:-cli}" "${TCTL_SRC:-local}" +printf '{"ok":%s,"enforcement":"%s","msg":"%s"}\n' "$OK" "$ENFORCE" "$MSG" diff --git a/luci-app-trafficctl/root/usr/local/bin/trafficctl-macfilter-remove.sh b/luci-app-trafficctl/root/usr/local/bin/trafficctl-macfilter-remove.sh index e472d415b..819f9a4c6 100755 --- a/luci-app-trafficctl/root/usr/local/bin/trafficctl-macfilter-remove.sh +++ b/luci-app-trafficctl/root/usr/local/bin/trafficctl-macfilter-remove.sh @@ -1,7 +1,9 @@ #!/bin/sh # shellcheck shell=dash # Remove device WiFi MAC filter (unblock from wifi deny list). -# Uses hostapd beacon update — no wifi reload, other clients stay connected. +# Updates the uci maclist and the running hostapd ACL, so the client can +# reassociate without a wifi reload and other clients stay connected. Reports +# how far the runtime half got — see the enforcement words in trafficctl-fw.sh. # Usage: trafficctl-macfilter-remove.sh . /usr/local/bin/trafficctl-fw.sh @@ -68,11 +70,32 @@ for iface in $IFACES; do fi done -if [ "$CHANGED" = "1" ]; then - uci commit wireless - # Update the runtime ACL — the client can reassociate immediately. - tctl_hostapd_unblock_mac "$MAC" "$MODE" -fi +[ "$CHANGED" = "1" ] && uci commit wireless -tctl_log "wifi_unblock" "$IP" "MAC=$MAC" "${TCTL_VIA:-cli}" "${TCTL_SRC:-local}" -echo "{\"ok\":true,\"msg\":\"MAC $MAC removed from wifi filter for $IP\"}" +# Unconditional for the same reason as the add path, and the stakes are higher +# here: a MAC that uci no longer lists but the radio still denies leaves a real +# person off the network while the UI says they are not blocked. +ENFORCE=$(tctl_hostapd_unblock_mac "$MAC" "$MODE") +BAN_MIN=$(( TCTL_WIFI_BAN_MS / 60000 )) + +case "$ENFORCE" in + acl) + OK=true + MSG="MAC $MAC removed from wifi filter for $IP" + ;; + no-radio) + OK=true + MSG="MAC $MAC removed from the wifi filter for $IP; no radio is running" + ;; + ban) + OK=false + MSG="MAC $MAC removed from the wifi filter, but hostapd still bans it for up to $BAN_MIN min. Restart wifi (drops all clients) to clear it now" + ;; + *) + OK=false + MSG="MAC $MAC removed from the wifi filter, but the radio ACL could not be read back: it may still be blocked. Install hostapd-utils, or restart wifi" + ;; +esac + +tctl_log "wifi_unblock" "$IP" "MAC=$MAC enforce=$ENFORCE" "${TCTL_VIA:-cli}" "${TCTL_SRC:-local}" +printf '{"ok":%s,"enforcement":"%s","msg":"%s"}\n' "$OK" "$ENFORCE" "$MSG" diff --git a/luci-app-trafficctl/root/usr/local/bin/trafficctl-summary.sh b/luci-app-trafficctl/root/usr/local/bin/trafficctl-summary.sh index 95403ccfd..2d26e2d06 100755 --- a/luci-app-trafficctl/root/usr/local/bin/trafficctl-summary.sh +++ b/luci-app-trafficctl/root/usr/local/bin/trafficctl-summary.sh @@ -436,16 +436,21 @@ for ip in $ACTIVE_IPS; do fi fi + # Needs CONN_TYPE, so it is decided here rather than next to WIFI_BLK. + WIFI_PENDING=0 + tctl_wifi_block_pending "$WIFI_BLK" "$CONN_TYPE" && WIFI_PENDING=1 + if [ "$FIRST" = "1" ]; then FIRST=0 else printf "," fi - printf '{"ip":"%s","name":"%s","mac":"%s","conn_type":"%s","conn_last":"%s","app":"%s","conns":%d,"total":%.0f,"tcp":%.0f,"udp":%.0f,"blocked":%s,"block_bytes":%.0f,"wifi_blocked":%s,"rate_limit_kbit":%.0f,"shape_kbit":%.0f}' \ + printf '{"ip":"%s","name":"%s","mac":"%s","conn_type":"%s","conn_last":"%s","app":"%s","conns":%d,"total":%.0f,"tcp":%.0f,"udp":%.0f,"blocked":%s,"block_bytes":%.0f,"wifi_blocked":%s,"wifi_block_pending":%s,"rate_limit_kbit":%.0f,"shape_kbit":%.0f}' \ "$ip" "$NAME" "$MAC" "$CONN_TYPE" "$CONN_LAST" "$APP" "$CONNS" "$TOTAL" "$TCP" "$UDP" \ "$([ "$BLOCKED" = "1" ] && echo true || echo false)" \ "$BLOCK_BYTES" \ "$([ "$WIFI_BLK" = "1" ] && echo true || echo false)" \ + "$([ "$WIFI_PENDING" = "1" ] && echo true || echo false)" \ "$RATE_LIM" "$SHAPE" done printf "]\n" diff --git a/luci-app-trafficctl/root/usr/local/bin/trafficctl-telegram.sh b/luci-app-trafficctl/root/usr/local/bin/trafficctl-telegram.sh index 883ec837a..34589c5c3 100755 --- a/luci-app-trafficctl/root/usr/local/bin/trafficctl-telegram.sh +++ b/luci-app-trafficctl/root/usr/local/bin/trafficctl-telegram.sh @@ -97,6 +97,14 @@ tg_send() { tg_answer_cb() { local cb_id="$1" text="$2" + # The Bot API caps a callback toast at 200 characters and rejects the whole + # call when it is longer — so an over-long message does not get trimmed, it + # vanishes. Backend results carrying remediation advice can reach that + # length, and a silently missing answer is exactly the failure mode this + # plugin is being fixed for. + if [ "${#text}" -gt 200 ]; then + text="$(printf '%.196s' "$text")..." + fi text=$(tg_json_escape "$text") tg_api "answerCallbackQuery" \ "$(printf '{"callback_query_id":"%s","text":"%s"}' "$cb_id" "$text")" >/dev/null diff --git a/luci-app-wwand/Makefile b/luci-app-wwand/Makefile index c4a38302c..d0223a3e8 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.8_p14 -PKG_RELEASE:=33 +PKG_VERSION:=1.6.8_p17 +PKG_RELEASE:=34 PKG_SOURCE_PROTO:=git PKG_SOURCE_URL:=https://github.com/ddimension/luci-app-wwand.git -PKG_SOURCE_VERSION:=5064320d9e69c3289febbc5552a4d96947d97046 +PKG_SOURCE_VERSION:=376f2dc5c658f06f88cb3b917e65e9e7d58a6e85 PKG_MIRROR_HASH:=skip PKG_LICENSE:=GPL-2.0-only diff --git a/wwand-ipa/Makefile b/wwand-ipa/Makefile index 79e3de7ab..a6aa1f048 100644 --- a/wwand-ipa/Makefile +++ b/wwand-ipa/Makefile @@ -13,8 +13,8 @@ include $(TOPDIR)/rules.mk PKG_NAME:=wwand-ipa -PKG_VERSION:=0.1.0_p6 -PKG_RELEASE:=7 +PKG_VERSION:=0.1.0_p7 +PKG_RELEASE:=8 PKG_SOURCE_PROTO:=git PKG_SOURCE_URL:=https://github.com/ddimension/wwand-ipa.git diff --git a/wwand/Makefile b/wwand/Makefile index 5da763dfc..c45c82f51 100644 --- a/wwand/Makefile +++ b/wwand/Makefile @@ -50,12 +50,12 @@ include $(TOPDIR)/rules.mk PKG_NAME:=wwand -PKG_VERSION:=1.6.8_p70 -PKG_RELEASE:=62 +PKG_VERSION:=1.6.8_p74 +PKG_RELEASE:=63 PKG_SOURCE_PROTO:=git PKG_SOURCE_URL:=https://github.com/ddimension/wwand.git -PKG_SOURCE_VERSION:=99125f0c4c8162cce254a5ac56e9f4a1160bcf34 +PKG_SOURCE_VERSION:=d146e6b2a30cbbb2737aa4bfb0403322623a81ad PKG_MIRROR_HASH:=skip PKG_LICENSE:=GPL-2.0-only