From 46410952e44f81cea1ffef37947981872ad21957 Mon Sep 17 00:00:00 2001 From: "github-action[bot]" Date: Fri, 10 Jan 2025 19:35:33 +0100 Subject: [PATCH] Update On Fri Jan 10 19:35:33 CET 2025 --- .github/update.log | 1 + .../.github/workflows/deps-build-linux.yaml | 10 +- clash-nyanpasu/backend/Cargo.lock | 251 +++++++----------- clash-nyanpasu/backend/tauri/Cargo.toml | 2 +- .../backend/tauri/src/core/clash/core.rs | 187 +++++-------- .../backend/tauri/src/core/service/control.rs | 15 ++ .../backend/tauri/src/enhance/advice.rs | 52 ++-- clash-nyanpasu/backend/tauri/src/feat.rs | 32 ++- .../backend/tauri/src/utils/dirs.rs | 26 ++ clash-nyanpasu/backend/tauri/tauri.conf.json | 2 +- clash-nyanpasu/frontend/nyanpasu/package.json | 8 +- clash-nyanpasu/manifest/version.json | 6 +- clash-nyanpasu/pnpm-lock.yaml | 78 +++--- clash-nyanpasu/scripts/package.json | 2 +- clash-nyanpasu/scripts/prepare-nightly.ts | 5 + ...rt-for-defining-read-only-partitions.patch | 53 ++++ ...3-03-block-introduce-add_disk_fwnode.patch | 94 +++++++ ...-partitions-fwnode-if-found-in-mmc-c.patch | 104 ++++++++ ...rt-for-partition-table-defined-in-OF.patch | 200 ++++++++++++++ lede/target/linux/generic/config-6.6 | 1 + ...451-block-partitions-populate-fwnode.patch | 4 +- ...-block-add-support-for-notifications.patch | 2 +- ...mmc-block-set-fwnode-of-disk-devices.patch | 32 +-- .../458-mmc-block-set-GENHD_FL_NVMEM.patch | 2 +- .../041-block-fit-partition-parser.patch | 5 +- mieru/pkg/appctl/appctlpb/base.pb.go | 112 ++++++-- mieru/pkg/appctl/appctlpb/servercfg.pb.go | 239 +++++++++++------ mieru/pkg/appctl/proto/base.proto | 8 + mieru/pkg/appctl/proto/servercfg.proto | 9 + mieru/pkg/appctl/server.go | 12 +- .../testdata/server_apply_config_2.json | 3 + mieru/pkg/cli/server.go | 5 +- mieru/pkg/common/ipdualstack.go | 53 ++++ mieru/pkg/common/ipdualstack_test.go | 132 +++++++++ mieru/pkg/socks5/request.go | 11 +- mieru/pkg/socks5/socks5.go | 3 + .../deploy/externalconnect/server_tcp.json | 5 +- .../deploy/externalconnect/server_udp.json | 5 +- .../root/usr/share/passwall/subscribe.lua | 246 +++++++++-------- .../root/usr/share/passwall2/subscribe.lua | 246 +++++++++-------- shadowsocks-rust/Cargo.lock | 16 +- .../root/usr/share/passwall/subscribe.lua | 246 +++++++++-------- v2rayn/v2rayN/ServiceLib/Common/Utils.cs | 2 +- v2rayn/v2rayN/ServiceLib/Enums/ETheme.cs | 13 + .../v2rayN/ServiceLib/Models/ConfigItems.cs | 1 + .../v2rayN/ServiceLib/Resx/ResUI.Designer.cs | 9 + .../v2rayN/ServiceLib/Resx/ResUI.fa-Ir.resx | 5 +- v2rayn/v2rayN/ServiceLib/Resx/ResUI.hu.resx | 3 + v2rayn/v2rayN/ServiceLib/Resx/ResUI.resx | 3 + v2rayn/v2rayN/ServiceLib/Resx/ResUI.ru.resx | 3 + .../v2rayN/ServiceLib/Resx/ResUI.zh-Hans.resx | 3 + .../v2rayN/ServiceLib/Resx/ResUI.zh-Hant.resx | 3 + .../CoreConfig/CoreConfigSingboxService.cs | 3 +- .../ServiceLib/ViewModels/MsgViewModel.cs | 8 +- .../ViewModels/ThemeSettingViewModel.cs | 35 ++- .../Views/BackupAndRestoreView.axaml | 37 ++- .../Views/BackupAndRestoreView.axaml.cs | 7 +- .../Views/CheckUpdateView.axaml | 21 +- .../Views/ClashProxiesView.axaml | 32 +-- .../v2rayN.Desktop/Views/MainWindow.axaml | 65 +---- .../v2rayN/v2rayN.Desktop/Views/MsgView.axaml | 4 +- .../Views/OptionSettingWindow.axaml | 2 +- .../v2rayN.Desktop/Views/ProfilesView.axaml | 2 +- .../Views/ProfilesView.axaml.cs | 7 +- .../v2rayN.Desktop/Views/QrcodeView.axaml | 3 - .../v2rayN.Desktop/Views/QrcodeView.axaml.cs | 5 + .../Views/RoutingRuleDetailsWindow.axaml | 4 +- .../Views/RoutingSettingWindow.axaml | 27 +- .../v2rayN.Desktop/Views/StatusBarView.axaml | 2 +- .../Views/ThemeSettingView.axaml | 33 +-- .../Views/ThemeSettingView.axaml.cs | 8 +- .../v2rayN/v2rayN/Views/CheckUpdateView.xaml | 1 - .../v2rayN/v2rayN/Views/ClashProxiesView.xaml | 12 +- v2rayn/v2rayN/v2rayN/v2rayN.csproj | 2 +- xray-core/go.mod | 8 +- xray-core/go.sum | 16 +- 76 files changed, 1836 insertions(+), 1078 deletions(-) create mode 100644 lede/target/linux/generic/backport-6.6/410-v6.13-01-block-add-support-for-defining-read-only-partitions.patch create mode 100644 lede/target/linux/generic/backport-6.6/410-v6.13-03-block-introduce-add_disk_fwnode.patch create mode 100644 lede/target/linux/generic/backport-6.6/410-v6.13-04-mmc-block-attach-partitions-fwnode-if-found-in-mmc-c.patch create mode 100644 lede/target/linux/generic/backport-6.6/410-v6.13-05-block-add-support-for-partition-table-defined-in-OF.patch create mode 100644 v2rayn/v2rayN/ServiceLib/Enums/ETheme.cs diff --git a/.github/update.log b/.github/update.log index 6783971035..de5fa227f4 100644 --- a/.github/update.log +++ b/.github/update.log @@ -878,3 +878,4 @@ Update On Mon Jan 6 19:35:21 CET 2025 Update On Tue Jan 7 19:34:36 CET 2025 Update On Wed Jan 8 19:36:18 CET 2025 Update On Thu Jan 9 19:34:49 CET 2025 +Update On Fri Jan 10 19:35:24 CET 2025 diff --git a/clash-nyanpasu/.github/workflows/deps-build-linux.yaml b/clash-nyanpasu/.github/workflows/deps-build-linux.yaml index f27003ac8e..52c8dbcfe2 100644 --- a/clash-nyanpasu/.github/workflows/deps-build-linux.yaml +++ b/clash-nyanpasu/.github/workflows/deps-build-linux.yaml @@ -128,7 +128,7 @@ jobs: - name: Nightly Prepare if: ${{ inputs.nightly == true }} run: | - pnpm prepare:nightly + pnpm prepare:nightly ${{ inputs.arch != 'x86_64' && '--disable-updater'}} - name: Build UI run: | pnpm -F ui build @@ -159,16 +159,16 @@ jobs: run: | case "${{ inputs.arch }}" in "i686") - ${{ inputs.nightly == true && 'pnpm build:nightly -r cross --target i686-unknown-linux-gnu -b "rpm,deb" -c ./backend/tauri/tauri.nightly.conf.json' || 'pnpm build -r cross --target i686-unknown-linux-gnu -b "rpm,deb"' }} + ${{ inputs.nightly == true && 'pnpm build:nightly -r cross --target i686-unknown-linux-gnu -b "rpm,deb"' || 'pnpm build -r cross --target i686-unknown-linux-gnu -b "rpm,deb" -c "{ "bundle": { "createUpdaterArtifacts": false } }"' }} ;; "aarch64") - ${{ inputs.nightly == true && 'pnpm build:nightly -r cross --target aarch64-unknown-linux-gnu -b "rpm,deb" -c ./backend/tauri/tauri.nightly.conf.json' || 'pnpm build -r cross --target aarch64-unknown-linux-gnu -b "rpm,deb"' }} + ${{ inputs.nightly == true && 'pnpm build:nightly -r cross --target aarch64-unknown-linux-gnu -b "rpm,deb"' || 'pnpm build -r cross --target aarch64-unknown-linux-gnu -b "rpm,deb" -c "{ "bundle": { "createUpdaterArtifacts": false } }"' }} ;; "armel") - ${{ inputs.nightly == true && 'pnpm build:nightly -r cross --target armv7-unknown-linux-gnueabi -b "rpm,deb" -c ./backend/tauri/tauri.nightly.conf.json' || 'pnpm build -r cross --target armv7-unknown-linux-gnueabi -b "rpm,deb"' }} + ${{ inputs.nightly == true && 'pnpm build:nightly -r cross --target armv7-unknown-linux-gnueabi -b "rpm,deb"' || 'pnpm build -r cross --target armv7-unknown-linux-gnueabi -b "rpm,deb" -c "{ "bundle": { "createUpdaterArtifacts": false } }"' }} ;; "armhf") - ${{ inputs.nightly == true && 'pnpm build:nightly -r cross --target armv7-unknown-linux-gnueabihf -b "rpm,deb" -c ./backend/tauri/tauri.nightly.conf.json' || 'pnpm build -r cross --target armv7-unknown-linux-gnueabihf -b "rpm,deb"' }} + ${{ inputs.nightly == true && 'pnpm build:nightly -r cross --target armv7-unknown-linux-gnueabihf -b "rpm,deb"' || 'pnpm build -r cross --target armv7-unknown-linux-gnueabihf -b "rpm,deb" -c "{ "bundle": { "createUpdaterArtifacts": false } }"' }} ;; esac diff --git a/clash-nyanpasu/backend/Cargo.lock b/clash-nyanpasu/backend/Cargo.lock index 03e3baed65..4233c2cfbb 100644 --- a/clash-nyanpasu/backend/Cargo.lock +++ b/clash-nyanpasu/backend/Cargo.lock @@ -358,7 +358,7 @@ checksum = "0ae92a5119aa49cdbcf6b9f893fe4e1d98b04ccbf82ee0584ad948a44a734dea" dependencies = [ "proc-macro2", "quote", - "syn 2.0.95", + "syn 2.0.96", ] [[package]] @@ -548,7 +548,7 @@ checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11" dependencies = [ "proc-macro2", "quote", - "syn 2.0.95", + "syn 2.0.96", ] [[package]] @@ -583,7 +583,7 @@ checksum = "3f934833b4b7233644e5848f235df3f57ed8c80f1528a26c3dfa13d2147fa056" dependencies = [ "proc-macro2", "quote", - "syn 2.0.95", + "syn 2.0.96", ] [[package]] @@ -623,7 +623,7 @@ checksum = "99e1aca718ea7b89985790c94aad72d77533063fe00bc497bb79a7c2dae6a661" dependencies = [ "proc-macro2", "quote", - "syn 2.0.95", + "syn 2.0.96", ] [[package]] @@ -717,47 +717,13 @@ dependencies = [ "arrayvec 0.7.6", ] -[[package]] -name = "axum" -version = "0.7.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edca88bc138befd0323b20752846e6587272d3b03b0343c8ea28a6f819e6e71f" -dependencies = [ - "async-trait", - "axum-core 0.4.5", - "bytes", - "futures-util", - "http 1.2.0", - "http-body", - "http-body-util", - "hyper", - "hyper-util", - "itoa 1.0.14", - "matchit 0.7.3", - "memchr", - "mime", - "percent-encoding", - "pin-project-lite", - "rustversion", - "serde", - "serde_json", - "serde_path_to_error", - "serde_urlencoded", - "sync_wrapper", - "tokio", - "tower", - "tower-layer", - "tower-service", - "tracing", -] - [[package]] name = "axum" version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6d6fd624c75e18b3b4c6b9caf42b1afe24437daaee904069137d8bab077be8b8" dependencies = [ - "axum-core 0.5.0", + "axum-core", "base64 0.22.1", "bytes", "form_urlencoded", @@ -768,7 +734,7 @@ dependencies = [ "hyper", "hyper-util", "itoa 1.0.14", - "matchit 0.8.4", + "matchit", "memchr", "mime", "percent-encoding", @@ -788,27 +754,6 @@ dependencies = [ "tracing", ] -[[package]] -name = "axum-core" -version = "0.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09f2bd6146b97ae3359fa0cc6d6b376d9539582c7b4220f041a33ec24c226199" -dependencies = [ - "async-trait", - "bytes", - "futures-util", - "http 1.2.0", - "http-body", - "http-body-util", - "mime", - "pin-project-lite", - "rustversion", - "sync_wrapper", - "tower-layer", - "tower-service", - "tracing", -] - [[package]] name = "axum-core" version = "0.5.0" @@ -916,7 +861,7 @@ dependencies = [ "regex", "rustc-hash 1.1.0", "shlex", - "syn 2.0.95", + "syn 2.0.96", "which 4.4.2", ] @@ -1105,7 +1050,7 @@ checksum = "9fd3f870829131332587f607a7ff909f1af5fc523fd1b192db55fbbdf52e8d3c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.95", + "syn 2.0.96", "synstructure", ] @@ -1226,7 +1171,7 @@ checksum = "3fa76293b4f7bb636ab88fd78228235b5248b4d05cc589aed610f954af5d7c7a" dependencies = [ "proc-macro2", "quote", - "syn 2.0.95", + "syn 2.0.96", ] [[package]] @@ -1491,9 +1436,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.24" +version = "4.5.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9560b07a799281c7e0958b9296854d6fafd4c5f31444a7e5bb1ad6dde5ccf1bd" +checksum = "a8eb5e908ef3a6efbe1ed62520fb7287959888c88485abe072543190ecc66783" dependencies = [ "clap_builder", "clap_derive", @@ -1501,9 +1446,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.24" +version = "4.5.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "874e0dd3eb68bf99058751ac9712f622e61e6f393a94f7128fa26e3f02f5c7cd" +checksum = "96b01801b5fc6a0a232407abc821660c9c6d25a1cafc0d4f85f29fb8d9afc121" dependencies = [ "anstream", "anstyle", @@ -1520,7 +1465,7 @@ dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.95", + "syn 2.0.96", ] [[package]] @@ -1540,7 +1485,7 @@ dependencies = [ "async-trait", "atomic_enum", "auto-launch", - "axum 0.7.9", + "axum", "backon", "base64 0.22.1", "bimap", @@ -1722,7 +1667,7 @@ version = "3.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fde0e0ec90c9dfb3b4b1a0891a7dcd0e2bffde2f7efed5fe7c9bb00e5bfb915e" dependencies = [ - "windows-sys 0.59.0", + "windows-sys 0.48.0", ] [[package]] @@ -1787,7 +1732,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f76990911f2267d837d9d0ad060aa63aaad170af40904b29461734c339030d4d" dependencies = [ "quote", - "syn 2.0.95", + "syn 2.0.96", ] [[package]] @@ -2052,7 +1997,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13b588ba4ac1a99f7f2964d24b3d896ddc6bf847ee3855dbd4366f058cfcd331" dependencies = [ "quote", - "syn 2.0.95", + "syn 2.0.96", ] [[package]] @@ -2062,7 +2007,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a2785755761f3ddc1492979ce1e48d2c00d09311c39e4466429188f3dd6501" dependencies = [ "quote", - "syn 2.0.95", + "syn 2.0.96", ] [[package]] @@ -2133,7 +2078,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn 2.0.95", + "syn 2.0.96", ] [[package]] @@ -2144,7 +2089,7 @@ checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" dependencies = [ "darling_core", "quote", - "syn 2.0.95", + "syn 2.0.96", ] [[package]] @@ -2235,7 +2180,7 @@ checksum = "30542c1ad912e0e3d22a1935c290e12e8a29d704a420177a31faad4a601a0800" dependencies = [ "proc-macro2", "quote", - "syn 2.0.95", + "syn 2.0.96", ] [[package]] @@ -2256,7 +2201,7 @@ dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.95", + "syn 2.0.96", ] [[package]] @@ -2266,7 +2211,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ab63b0e2bf4d5928aff72e83a7dace85d7bba5fe12dcc3c5a572d78caffd3f3c" dependencies = [ "derive_builder_core", - "syn 2.0.95", + "syn 2.0.96", ] [[package]] @@ -2279,7 +2224,7 @@ dependencies = [ "proc-macro2", "quote", "rustc_version", - "syn 2.0.95", + "syn 2.0.96", ] [[package]] @@ -2411,7 +2356,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.95", + "syn 2.0.96", ] [[package]] @@ -2443,7 +2388,7 @@ checksum = "f2b99bf03862d7f545ebc28ddd33a665b50865f4dfd84031a393823879bd4c54" dependencies = [ "proc-macro2", "quote", - "syn 2.0.95", + "syn 2.0.96", ] [[package]] @@ -2714,7 +2659,7 @@ checksum = "f282cfdfe92516eb26c2af8589c274c7c17681f5ecc03c18255fe741c6aa64eb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.95", + "syn 2.0.96", ] [[package]] @@ -2735,7 +2680,7 @@ checksum = "de0d48a183585823424a4ce1aa132d174a6a81bd540895822eb4c8373a8e49e8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.95", + "syn 2.0.96", ] [[package]] @@ -2811,7 +2756,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d" dependencies = [ "libc", - "windows-sys 0.59.0", + "windows-sys 0.52.0", ] [[package]] @@ -3030,7 +2975,7 @@ checksum = "1a5c6c585bc94aaf2c7b51dd4c2ba22680844aba4c687be581871a6f518c5742" dependencies = [ "proc-macro2", "quote", - "syn 2.0.95", + "syn 2.0.96", ] [[package]] @@ -3154,7 +3099,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", - "syn 2.0.95", + "syn 2.0.96", ] [[package]] @@ -3442,7 +3387,7 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.95", + "syn 2.0.96", ] [[package]] @@ -3716,7 +3661,7 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.95", + "syn 2.0.96", ] [[package]] @@ -4170,7 +4115,7 @@ checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.95", + "syn 2.0.96", ] [[package]] @@ -4365,7 +4310,7 @@ checksum = "c34819042dc3d3971c46c2190835914dfbe0c3c13f61449b2997f4e9722dfa60" dependencies = [ "proc-macro2", "quote", - "syn 2.0.95", + "syn 2.0.96", ] [[package]] @@ -4767,7 +4712,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc2f4eb4bc735547cfed7c0a4922cbd04a4655978c09b54f1f7b228750664c34" dependencies = [ "cfg-if", - "windows-targets 0.52.6", + "windows-targets 0.48.5", ] [[package]] @@ -4959,12 +4904,6 @@ version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2532096657941c2fea9c289d370a250971c689d4f143798ff67113ec042024a5" -[[package]] -name = "matchit" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e7465ac9959cc2b1404e8e2367b43684a6d13790fe23056cc8c6c5a6b7bcb94" - [[package]] name = "matchit" version = "0.8.4" @@ -5426,7 +5365,7 @@ checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" dependencies = [ "proc-macro2", "quote", - "syn 2.0.95", + "syn 2.0.96", ] [[package]] @@ -5486,7 +5425,7 @@ dependencies = [ "proc-macro-crate 3.2.0", "proc-macro2", "quote", - "syn 2.0.95", + "syn 2.0.96", ] [[package]] @@ -5518,7 +5457,7 @@ version = "1.1.2" source = "git+https://github.com/libnyanpasu/nyanpasu-service.git#08a210684b522d6dbcbf7f11ba5f8528f667b1d2" dependencies = [ "anyhow", - "axum 0.8.1", + "axum", "derive_builder", "futures", "futures-util", @@ -5543,7 +5482,7 @@ version = "0.1.0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.95", + "syn 2.0.96", ] [[package]] @@ -5874,7 +5813,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.95", + "syn 2.0.96", ] [[package]] @@ -6013,7 +5952,7 @@ checksum = "e21f680e8c5f1900297d394627d495351b9e37761f7bbf90116bd5eeb6e80967" dependencies = [ "proc-macro2", "quote", - "syn 2.0.95", + "syn 2.0.96", ] [[package]] @@ -6053,7 +5992,7 @@ checksum = "453922e0b0c402ff4f94d277d9c99c8f60757ed5a84458133758f8142b8707cf" dependencies = [ "proc-macro2", "quote", - "syn 2.0.95", + "syn 2.0.96", ] [[package]] @@ -6289,7 +6228,7 @@ dependencies = [ "pest_meta", "proc-macro2", "quote", - "syn 2.0.95", + "syn 2.0.96", ] [[package]] @@ -6427,7 +6366,7 @@ dependencies = [ "phf_shared 0.11.3", "proc-macro2", "quote", - "syn 2.0.95", + "syn 2.0.96", ] [[package]] @@ -6480,7 +6419,7 @@ checksum = "d56a66c0c55993aa927429d0f8a0abfd74f084e4d9c192cffed01e418d83eefb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.95", + "syn 2.0.96", ] [[package]] @@ -6631,7 +6570,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "483f8c21f64f3ea09fe0f30f5d48c3e8eefe5dac9129f0075f76593b4c1da705" dependencies = [ "proc-macro2", - "syn 2.0.95", + "syn 2.0.96", ] [[package]] @@ -6717,7 +6656,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a65f2e60fbf1063868558d69c6beacf412dc755f9fc020f514b7955fc914fe30" dependencies = [ "quote", - "syn 2.0.95", + "syn 2.0.96", ] [[package]] @@ -6821,7 +6760,7 @@ dependencies = [ "once_cell", "socket2", "tracing", - "windows-sys 0.59.0", + "windows-sys 0.52.0", ] [[package]] @@ -7057,7 +6996,7 @@ checksum = "bcc303e793d3734489387d205e9b186fac9c6cfacedd98cbb2e8a5943595f3e6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.95", + "syn 2.0.96", ] [[package]] @@ -7308,7 +7247,7 @@ dependencies = [ "serde", "serde_json", "serde_yml", - "syn 2.0.95", + "syn 2.0.96", ] [[package]] @@ -7371,7 +7310,7 @@ dependencies = [ "errno", "libc", "linux-raw-sys", - "windows-sys 0.59.0", + "windows-sys 0.52.0", ] [[package]] @@ -7496,7 +7435,7 @@ dependencies = [ "proc-macro2", "quote", "serde_derive_internals", - "syn 2.0.95", + "syn 2.0.96", ] [[package]] @@ -7638,7 +7577,7 @@ checksum = "5a9bf7cf98d04a2b28aead066b7496853d4779c9cc183c440dbac457641e19a0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.95", + "syn 2.0.96", ] [[package]] @@ -7649,7 +7588,7 @@ checksum = "18d26a20a969b9e3fdf2fc2d9f21eda6c40e2de84c9408bb5d3b05d499aae711" dependencies = [ "proc-macro2", "quote", - "syn 2.0.95", + "syn 2.0.96", ] [[package]] @@ -7682,7 +7621,7 @@ checksum = "6c64451ba24fc7a6a2d60fc75dd9c83c90903b19028d4eff35e88fc1e86564e9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.95", + "syn 2.0.96", ] [[package]] @@ -7733,7 +7672,7 @@ dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.95", + "syn 2.0.96", ] [[package]] @@ -8233,7 +8172,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.95", + "syn 2.0.96", ] [[package]] @@ -8286,9 +8225,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.95" +version = "2.0.96" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46f71c0377baf4ef1cc3e3402ded576dccc315800fbc62dfc7fe04b009773b4a" +checksum = "d5d0adab1ae378d7f53bdebc67a39f1f151407ef230f0ce2883572f5d8985c80" dependencies = [ "proc-macro2", "quote", @@ -8312,7 +8251,7 @@ checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" dependencies = [ "proc-macro2", "quote", - "syn 2.0.95", + "syn 2.0.96", ] [[package]] @@ -8432,7 +8371,7 @@ checksum = "f4e16beb8b2ac17db28eab8bca40e62dbfbb34c0fcdc6d9826b11b7b5d047dfd" dependencies = [ "proc-macro2", "quote", - "syn 2.0.95", + "syn 2.0.96", ] [[package]] @@ -8549,7 +8488,7 @@ dependencies = [ "serde", "serde_json", "sha2 0.10.8", - "syn 2.0.95", + "syn 2.0.96", "tauri-utils", "thiserror 2.0.10", "time", @@ -8567,7 +8506,7 @@ dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.95", + "syn 2.0.96", "tauri-codegen", "tauri-utils", ] @@ -8887,7 +8826,7 @@ dependencies = [ "getrandom 0.2.15", "once_cell", "rustix", - "windows-sys 0.59.0", + "windows-sys 0.52.0", ] [[package]] @@ -8983,7 +8922,7 @@ checksum = "5999e24eaa32083191ba4e425deb75cdf25efefabe5aaccb7446dd0d4122a3f5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.95", + "syn 2.0.96", ] [[package]] @@ -9035,7 +8974,7 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.95", + "syn 2.0.96", ] [[package]] @@ -9046,7 +8985,7 @@ checksum = "9e9465d30713b56a37ede7185763c3492a91be2f5fa68d958c44e41ab9248beb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.95", + "syn 2.0.96", ] [[package]] @@ -9202,7 +9141,7 @@ checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.95", + "syn 2.0.96", ] [[package]] @@ -9381,7 +9320,7 @@ checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.95", + "syn 2.0.96", ] [[package]] @@ -10009,7 +9948,7 @@ dependencies = [ "log", "proc-macro2", "quote", - "syn 2.0.95", + "syn 2.0.96", "wasm-bindgen-shared", ] @@ -10044,7 +9983,7 @@ checksum = "30d7a95b763d3c45903ed6c81f156801839e5ee968bb07e534c44df0fcd330c2" dependencies = [ "proc-macro2", "quote", - "syn 2.0.95", + "syn 2.0.96", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -10315,7 +10254,7 @@ checksum = "1d228f15bba3b9d56dde8bddbee66fa24545bd17b48d5128ccf4a8742b18e431" dependencies = [ "proc-macro2", "quote", - "syn 2.0.95", + "syn 2.0.96", ] [[package]] @@ -10517,7 +10456,7 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" dependencies = [ - "windows-sys 0.59.0", + "windows-sys 0.48.0", ] [[package]] @@ -10657,7 +10596,7 @@ checksum = "f6fc35f58ecd95a9b71c4f2329b911016e6bec66b3f2e6a4aad86bd2e99e2f9b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.95", + "syn 2.0.96", ] [[package]] @@ -10668,7 +10607,7 @@ checksum = "9107ddc059d5b6fbfbffdfa7a7fe3e22a226def0b2608f72e9d552763d3e1ad7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.95", + "syn 2.0.96", ] [[package]] @@ -10679,7 +10618,7 @@ checksum = "2bbd5b46c938e506ecbce286b6628a02171d56153ba733b6c741fc627ec9579b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.95", + "syn 2.0.96", ] [[package]] @@ -10690,7 +10629,7 @@ checksum = "83577b051e2f49a058c308f17f273b570a6a758386fc291b5f6a934dd84e48c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.95", + "syn 2.0.96", ] [[package]] @@ -10701,7 +10640,7 @@ checksum = "08990546bf4edef8f431fa6326e032865f27138718c587dc21bc0265bbcb57cc" dependencies = [ "proc-macro2", "quote", - "syn 2.0.95", + "syn 2.0.96", ] [[package]] @@ -10712,7 +10651,7 @@ checksum = "29bee4b38ea3cde66011baa44dba677c432a78593e202392d1e9070cf2a7fca7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.95", + "syn 2.0.96", ] [[package]] @@ -10723,7 +10662,7 @@ checksum = "053c4c462dc91d3b1504c6fe5a726dd15e216ba718e84a0e46a88fbe5ded3515" dependencies = [ "proc-macro2", "quote", - "syn 2.0.95", + "syn 2.0.96", ] [[package]] @@ -10734,7 +10673,7 @@ checksum = "cb26fd936d991781ea39e87c3a27285081e3c0da5ca0fcbc02d368cc6f52ff01" dependencies = [ "proc-macro2", "quote", - "syn 2.0.95", + "syn 2.0.96", ] [[package]] @@ -11406,7 +11345,7 @@ checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154" dependencies = [ "proc-macro2", "quote", - "syn 2.0.95", + "syn 2.0.96", "synstructure", ] @@ -11496,7 +11435,7 @@ checksum = "709ab20fc57cb22af85be7b360239563209258430bccf38d8b979c5a2ae3ecce" dependencies = [ "proc-macro2", "quote", - "syn 2.0.95", + "syn 2.0.96", "zbus-lockstep", "zbus_xml", "zvariant 4.2.0", @@ -11511,7 +11450,7 @@ dependencies = [ "proc-macro-crate 3.2.0", "proc-macro2", "quote", - "syn 2.0.95", + "syn 2.0.96", "zvariant_utils 2.1.0", ] @@ -11524,7 +11463,7 @@ dependencies = [ "proc-macro-crate 3.2.0", "proc-macro2", "quote", - "syn 2.0.95", + "syn 2.0.96", "zbus_names 4.1.0", "zvariant 5.1.0", "zvariant_utils 3.0.2", @@ -11584,7 +11523,7 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.95", + "syn 2.0.96", ] [[package]] @@ -11604,7 +11543,7 @@ checksum = "595eed982f7d355beb85837f651fa22e90b3c044842dc7f2c2842c086f295808" dependencies = [ "proc-macro2", "quote", - "syn 2.0.95", + "syn 2.0.96", "synstructure", ] @@ -11625,7 +11564,7 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.95", + "syn 2.0.96", ] [[package]] @@ -11647,7 +11586,7 @@ checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.95", + "syn 2.0.96", ] [[package]] @@ -11792,7 +11731,7 @@ dependencies = [ "proc-macro-crate 3.2.0", "proc-macro2", "quote", - "syn 2.0.95", + "syn 2.0.96", "zvariant_utils 2.1.0", ] @@ -11805,7 +11744,7 @@ dependencies = [ "proc-macro-crate 3.2.0", "proc-macro2", "quote", - "syn 2.0.95", + "syn 2.0.96", "zvariant_utils 3.0.2", ] @@ -11817,7 +11756,7 @@ checksum = "c51bcff7cc3dbb5055396bcf774748c3dab426b4b8659046963523cee4808340" dependencies = [ "proc-macro2", "quote", - "syn 2.0.95", + "syn 2.0.96", ] [[package]] @@ -11830,6 +11769,6 @@ dependencies = [ "quote", "serde", "static_assertions", - "syn 2.0.95", + "syn 2.0.96", "winnow 0.6.22", ] diff --git a/clash-nyanpasu/backend/tauri/Cargo.toml b/clash-nyanpasu/backend/tauri/Cargo.toml index c99237ff55..3bd9de7e44 100644 --- a/clash-nyanpasu/backend/tauri/Cargo.toml +++ b/clash-nyanpasu/backend/tauri/Cargo.toml @@ -72,7 +72,7 @@ rfd = { version = "0.15", default-features = false, features = [ rust-i18n = "3" # Networking Libraries -axum = "0.7" +axum = "0.8" url = "2" mime = "0.3" reqwest = { version = "0.12", features = ["json", "rustls-tls", "stream"] } diff --git a/clash-nyanpasu/backend/tauri/src/core/clash/core.rs b/clash-nyanpasu/backend/tauri/src/core/clash/core.rs index c2a5426af9..8c9a27799b 100644 --- a/clash-nyanpasu/backend/tauri/src/core/clash/core.rs +++ b/clash-nyanpasu/backend/tauri/src/core/clash/core.rs @@ -469,69 +469,13 @@ impl CoreManager { #[cfg(target_os = "macos")] { - use nyanpasu_utils::network::macos::*; - - let enable_tun = Config::verge().latest().enable_tun_mode; - let enable_tun = enable_tun.unwrap_or(false); - - log::debug!(target: "app", "try to set system dns"); - let default_device = get_default_network_hardware_port() - .inspect_err( - |e| log::error!(target: "app", "failed to get default network device: {:?}", e), - ) - .ok(); - log::debug!(target: "app", "current default network device: {:?}", default_device); - let tun_device_ip = Config::clash() - .clone() - .latest() - .get_tun_device_ip() - .parse::() - .unwrap(); - log::debug!(target: "app", "current tun device ip: {:?}", tun_device_ip); - if let Some(default_device) = default_device { - let current_dns = get_dns(&default_device) - .inspect_err( - |e| log::error!(target: "app", "failed to get current dns: {:?}", e), - ) - .ok() - .flatten(); - log::debug!(target: "app", "current dns: {:?}", current_dns); - let current_dns_contains_tun_device_ip = current_dns - .as_ref() - .is_some_and(|dns| dns.contains(&tun_device_ip)); - let mut previous_dns = self.previous_dns.lock().await; - let previous_dns_clone = previous_dns.clone(); - let new_dns = match enable_tun { - true if !current_dns_contains_tun_device_ip => { - *previous_dns = current_dns; - Some(Some(vec![tun_device_ip])) - } - false if current_dns_contains_tun_device_ip => Some(previous_dns.take()), - _ => None, - }; - if let Some(new_dns) = new_dns { - log::debug!(target: "app", "set new dns: {:?}", new_dns); - let result = match run_type { - RunType::Service => { - nyanpasu_ipc::client::shortcuts::Client::service_default() - .set_dns(&NetworkSetDnsReq { - // FIXME: improve this type notation - dns_servers: new_dns - .as_ref() - .map(|dns| dns.iter().map(Cow::Borrowed).collect()), - }) - .await - .map_err(anyhow::Error::from) - } - _ => set_dns(&default_device, new_dns).map_err(anyhow::Error::from), - }; - if let Err(e) = result { - *previous_dns = previous_dns_clone; - log::error!(target: "app", "failed to set system dns: {:?}", e); - } - } - } + let enable_tun = Config::verge().latest().enable_tun_mode.unwrap_or(false); + let _ = self + .change_default_network_dns(enable_tun) + .await + .inspect_err(|e| log::error!(target: "app", "failed to set system dns: {:?}", e)); } + { let mut this = self.instance.lock(); *this = Some(instance.clone()); @@ -572,63 +516,10 @@ impl CoreManager { /// 停止核心运行 pub async fn stop_core(&self) -> Result<()> { #[cfg(target_os = "macos")] - { - use crate::core::service::ipc::*; - use nyanpasu_utils::network::macos::*; - - let enable_tun = Config::verge().latest().enable_tun_mode; - let enable_tun = enable_tun.unwrap_or(false); - - log::debug!(target: "app", "try to reset system dns"); - let default_device = get_default_network_hardware_port() - .inspect_err( - |e| log::error!(target: "app", "failed to get default network device: {:?}", e), - ) - .ok(); - log::debug!(target: "app", "current default network device: {:?}", default_device); - if let Some(default_device) = default_device { - let current_dns = get_dns(&default_device) - .inspect_err( - |e| log::error!(target: "app", "failed to get current dns: {:?}", e), - ) - .ok() - .flatten(); - log::debug!(target: "app", "current dns: {:?}", current_dns); - let tun_device_ip = Config::clash() - .clone() - .latest() - .get_tun_device_ip() - .parse::() - .unwrap(); - let current_dns_contains_tun_device_ip = current_dns - .as_ref() - .is_some_and(|dns| dns.contains(&tun_device_ip)); - if current_dns_contains_tun_device_ip && !enable_tun { - let mut previous_dns = self.previous_dns.lock().await; - let previous_dns_clone = previous_dns.clone(); - let (_, _, run_type) = self.status().await; - let new_dns = previous_dns.take(); - log::debug!(target: "app", "try to reset dns to: {:?}", new_dns); - let result = match run_type { - RunType::Service if get_ipc_state() == IpcState::Connected => { - nyanpasu_ipc::client::shortcuts::Client::service_default() - .set_dns(&NetworkSetDnsReq { - dns_servers: new_dns - .as_ref() - .map(|dns| dns.iter().map(Cow::Borrowed).collect()), - }) - .await - .map_err(anyhow::Error::from) - } - _ => set_dns(&default_device, new_dns).map_err(anyhow::Error::from), - }; - if let Err(e) = result { - *previous_dns = previous_dns_clone; - log::error!(target: "app", "failed to set system dns: {:?}", e); - } - } - } - } + let _ = self + .change_default_network_dns(false) + .await + .inspect_err(|e| log::error!(target: "app", "failed to set system dns: {:?}", e)); let instance = { let instance = self.instance.lock(); instance.as_ref().cloned() @@ -706,6 +597,64 @@ impl CoreManager { Ok(()) } + + #[cfg(target_os = "macos")] + pub async fn change_default_network_dns(&self, enabled: bool) -> Result<()> { + use anyhow::Context; + use nyanpasu_utils::network::macos::*; + + let run_type = RunType::default(); + + log::debug!(target: "app", "try to set system dns"); + let default_device = + get_default_network_hardware_port().context("failed to get default network device")?; + log::debug!(target: "app", "current default network device: {:?}", default_device); + let tun_device_ip = Config::clash() + .clone() + .latest() + .get_tun_device_ip() + .parse::() + .context("failed to parse tun device ip")?; + log::debug!(target: "app", "current tun device ip: {:?}", tun_device_ip); + + let current_dns = get_dns(&default_device).context("failed to get current dns")?; + log::debug!(target: "app", "current dns: {:?}", current_dns); + let current_dns_contains_tun_device_ip = current_dns + .as_ref() + .is_some_and(|dns| dns.contains(&tun_device_ip)); + let mut previous_dns = self.previous_dns.lock().await; + let previous_dns_clone = previous_dns.clone(); + let new_dns = match enabled { + true if !current_dns_contains_tun_device_ip => { + *previous_dns = current_dns; + Some(Some(vec![tun_device_ip])) + } + false if current_dns_contains_tun_device_ip => Some(previous_dns.take()), + _ => None, + }; + if let Some(new_dns) = new_dns { + log::debug!(target: "app", "set new dns: {:?}", new_dns); + let result = match run_type { + RunType::Service => { + nyanpasu_ipc::client::shortcuts::Client::service_default() + .set_dns(&NetworkSetDnsReq { + // FIXME: improve this type notation + dns_servers: new_dns + .as_ref() + .map(|dns| dns.iter().map(Cow::Borrowed).collect()), + }) + .await + .map_err(anyhow::Error::from) + } + _ => set_dns(&default_device, new_dns).map_err(anyhow::Error::from), + }; + if let Err(e) = result.context("failed to set system dns") { + *previous_dns = previous_dns_clone; + return Err(e); + } + } + Ok(()) + } } // TODO: support system path search via a config or flag diff --git a/clash-nyanpasu/backend/tauri/src/core/service/control.rs b/clash-nyanpasu/backend/tauri/src/core/service/control.rs index 6be84c40aa..841ddecaac 100644 --- a/clash-nyanpasu/backend/tauri/src/core/service/control.rs +++ b/clash-nyanpasu/backend/tauri/src/core/service/control.rs @@ -22,6 +22,7 @@ pub async fn get_service_install_args() -> Result, anyhow::Error> let config_dir = app_config_dir()?; let app_dir = app_install_dir()?; + #[cfg(not(windows))] let args: Vec = vec![ "install".into(), "--user".into(), @@ -33,6 +34,20 @@ pub async fn get_service_install_args() -> Result, anyhow::Error> "--nyanpasu-app-dir".into(), format!("\"{}\"", app_dir.to_string_lossy()).into(), ]; + + #[cfg(windows)] + let args: Vec = vec![ + "install".into(), + "--user".into(), + user.into(), + "--nyanpasu-data-dir".into(), + data_dir.into(), + "--nyanpasu-config-dir".into(), + config_dir.into(), + "--nyanpasu-app-dir".into(), + app_dir.into(), + ]; + Ok(args) } diff --git a/clash-nyanpasu/backend/tauri/src/enhance/advice.rs b/clash-nyanpasu/backend/tauri/src/enhance/advice.rs index a1d5228911..420d665fe5 100644 --- a/clash-nyanpasu/backend/tauri/src/enhance/advice.rs +++ b/clash-nyanpasu/backend/tauri/src/enhance/advice.rs @@ -37,13 +37,6 @@ pub fn chain_advice(config: &Mapping) -> ProcessOutput { // If the core file is not granted the necessary permissions, grant it #[cfg(any(target_os = "macos", target_os = "linux"))] { - #[cfg(target_os = "macos")] - const ROOT_GROUP: &str = "admin"; - #[cfg(target_os = "linux")] - const ROOT_GROUP: &str = "root"; - - use nix::unistd::{Gid, Group as NixGroup, Uid, User}; - use std::os::unix::fs::MetadataExt; if !service_state.is_connected() { let core: nyanpasu_utils::core::CoreType = { crate::config::Config::verge() @@ -53,33 +46,24 @@ pub fn chain_advice(config: &Mapping) -> ProcessOutput { .unwrap_or(&crate::config::nyanpasu::ClashCore::default()) .into() }; - let core_path = crate::core::clash::core::find_binary_path(&core); - if let Ok(core_path) = core_path { - if let Ok(metadata) = std::fs::metadata(&core_path) { - let uid = metadata.uid(); - let gid = metadata.gid(); - let user = User::from_uid(Uid::from_raw(uid)).ok().flatten(); - let group = NixGroup::from_gid(Gid::from_raw(gid)).ok().flatten(); - if let (Some(user), Some(group)) = (user, group) { - if !*crate::consts::IS_APPIMAGE - && (user.name != "root" || group.name != ROOT_GROUP) - { - tracing::warn!("The core file is not granted the necessary permissions, grant it"); - let msg = t!("dialog.info.grant_core_permission"); - if crate::utils::dialog::ask_dialog(msg.as_ref()) { - if let Err(err) = crate::core::manager::grant_permission(&core) - { - tracing::error!( - "Failed to grant permission to the core file: {}", - err - ); - crate::utils::dialog::error_dialog(format!( - "failed to grant core permission:\n{:#?}", - err - )); - } - } - } + if crate::utils::dirs::check_core_permission(&core) + .inspect_err(|v| { + log::error!(target: "app", "clash core is not granted the necessary permissions, grant it: {v:?}"); + }) + .is_ok_and(|v| !v && *crate::consts::IS_APPIMAGE) + { + tracing::warn!("The core file is not granted the necessary permissions, grant it"); + let msg = t!("dialog.info.grant_core_permission"); + if crate::utils::dialog::ask_dialog(msg.as_ref()) { + if let Err(err) = crate::core::manager::grant_permission(&core) { + tracing::error!( + "Failed to grant permission to the core file: {}", + err + ); + crate::utils::dialog::error_dialog(format!( + "failed to grant core permission:\n{:#?}", + err + )); } } } diff --git a/clash-nyanpasu/backend/tauri/src/feat.rs b/clash-nyanpasu/backend/tauri/src/feat.rs index 34b9a0dadb..778e378da4 100644 --- a/clash-nyanpasu/backend/tauri/src/feat.rs +++ b/clash-nyanpasu/backend/tauri/src/feat.rs @@ -297,7 +297,37 @@ pub async fn patch_verge(patch: IVerge) -> Result<()> { } if tun_mode.is_some() { - update_core_config().await?; + log::debug!(target: "app", "toggle tun mode"); + let mut flag = false; + #[cfg(any(target_os = "macos", target_os = "linux"))] + { + use crate::utils::dirs::check_core_permission; + let current_core = Config::verge().data().clash_core.unwrap_or_default(); + let current_core: nyanpasu_utils::core::CoreType = (¤t_core).into(); + let service_state = crate::core::service::ipc::get_ipc_state(); + if !service_state.is_connected() && check_core_permission(¤t_core).inspect_err(|e| { + log::error!(target: "app", "clash core is not granted the necessary permissions, grant it: {e:?}"); + }).is_ok_and(|v| !v) { + log::debug!(target: "app", "grant core permission, and restart core"); + flag = true; + } + } + let (state, _, _) = CoreManager::global().status().await; + if flag || matches!(state.as_ref(), CoreState::Stopped(_)) { + log::debug!(target: "app", "core is stopped, restart core"); + Config::generate().await?; + CoreManager::global().run_core().await?; + } else { + log::debug!(target: "app", "update core config"); + #[cfg(target_os = "macos")] + let _ = CoreManager::global() + .change_default_network_dns(tun_mode.unwrap_or(false)) + .await + .inspect_err( + |e| log::error!(target: "app", "failed to set system dns: {:?}", e), + ); + update_core_config().await?; + } } if auto_launch.is_some() { diff --git a/clash-nyanpasu/backend/tauri/src/utils/dirs.rs b/clash-nyanpasu/backend/tauri/src/utils/dirs.rs index 1df1068c72..fae7dcb8ae 100644 --- a/clash-nyanpasu/backend/tauri/src/utils/dirs.rs +++ b/clash-nyanpasu/backend/tauri/src/utils/dirs.rs @@ -296,6 +296,32 @@ pub fn get_data_or_sidecar_path(binary_name: impl AsRef) -> Result Ok(path) } +#[cfg(any(target_os = "macos", target_os = "linux"))] +pub fn check_core_permission(core: &nyanpasu_utils::core::CoreType) -> anyhow::Result { + #[cfg(target_os = "macos")] + const ROOT_GROUP: &str = "admin"; + #[cfg(target_os = "linux")] + const ROOT_GROUP: &str = "root"; + + use anyhow::Context; + use nix::unistd::{Gid, Group as NixGroup, Uid, User}; + use std::os::unix::fs::MetadataExt; + + let core_path = + crate::core::clash::core::find_binary_path(core).context("clash core not found")?; + let metadata = std::fs::metadata(&core_path).context("failed to get core metadata")?; + let uid = metadata.uid(); + let gid = metadata.gid(); + let user = User::from_uid(Uid::from_raw(uid)).ok().flatten(); + let group = NixGroup::from_gid(Gid::from_raw(gid)).ok().flatten(); + if let (Some(user), Some(group)) = (user, group) { + if user.name == "root" && group.name == ROOT_GROUP { + return Ok(true); + } + } + Ok(false) +} + mod test { #[test] fn test_dir_placeholder() { diff --git a/clash-nyanpasu/backend/tauri/tauri.conf.json b/clash-nyanpasu/backend/tauri/tauri.conf.json index f2d77be922..d05300e49d 100644 --- a/clash-nyanpasu/backend/tauri/tauri.conf.json +++ b/clash-nyanpasu/backend/tauri/tauri.conf.json @@ -57,7 +57,7 @@ } }, "licenseFile": "../../LICENSE", - "createUpdaterArtifacts": false + "createUpdaterArtifacts": "v1Compatible" }, "build": { "beforeBuildCommand": "pnpm run-p web:build generate:git-info && echo $(pwd)", diff --git a/clash-nyanpasu/frontend/nyanpasu/package.json b/clash-nyanpasu/frontend/nyanpasu/package.json index b22e1c75ff..30851ba7c6 100644 --- a/clash-nyanpasu/frontend/nyanpasu/package.json +++ b/clash-nyanpasu/frontend/nyanpasu/package.json @@ -52,9 +52,9 @@ "@csstools/normalize.css": "12.1.1", "@emotion/babel-plugin": "11.13.5", "@emotion/react": "11.14.0", - "@iconify/json": "2.2.293", + "@iconify/json": "2.2.294", "@monaco-editor/react": "4.6.0", - "@tanstack/react-query": "5.62.16", + "@tanstack/react-query": "5.63.0", "@tanstack/react-router": "1.89.2", "@tanstack/router-devtools": "1.89.2", "@tanstack/router-plugin": "1.87.13", @@ -82,8 +82,8 @@ "sass-embedded": "1.83.1", "shiki": "1.26.1", "tailwindcss-textshadow": "2.1.3", - "unplugin-auto-import": "0.19.0", - "unplugin-icons": "0.22.0", + "unplugin-auto-import": "19.0.0", + "unplugin-icons": "22.0.0", "validator": "13.12.0", "vite": "6.0.7", "vite-plugin-html": "3.2.2", diff --git a/clash-nyanpasu/manifest/version.json b/clash-nyanpasu/manifest/version.json index 5af18c9d84..299f13629d 100644 --- a/clash-nyanpasu/manifest/version.json +++ b/clash-nyanpasu/manifest/version.json @@ -3,9 +3,9 @@ "latest": { "mihomo": "v1.19.1", "mihomo_alpha": "alpha-c7661d7", - "clash_rs": "v0.7.3", + "clash_rs": "v0.7.4", "clash_premium": "2023-09-05-gdcc8d87", - "clash_rs_alpha": "0.7.3-alpha+sha.8de5c14" + "clash_rs_alpha": "0.7.4-alpha+sha.306b0f1" }, "arch_template": { "mihomo": { @@ -69,5 +69,5 @@ "linux-armv7hf": "clash-armv7-unknown-linux-gnueabihf" } }, - "updated_at": "2025-01-08T22:20:49.691Z" + "updated_at": "2025-01-09T22:20:42.120Z" } diff --git a/clash-nyanpasu/pnpm-lock.yaml b/clash-nyanpasu/pnpm-lock.yaml index 9b1a8f8f78..e11522c4a5 100644 --- a/clash-nyanpasu/pnpm-lock.yaml +++ b/clash-nyanpasu/pnpm-lock.yaml @@ -315,14 +315,14 @@ importers: specifier: 11.14.0 version: 11.14.0(@types/react@19.0.3)(react@19.0.0) '@iconify/json': - specifier: 2.2.293 - version: 2.2.293 + specifier: 2.2.294 + version: 2.2.294 '@monaco-editor/react': specifier: 4.6.0 version: 4.6.0(monaco-editor@0.52.2)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) '@tanstack/react-query': - specifier: 5.62.16 - version: 5.62.16(react@19.0.0) + specifier: 5.63.0 + version: 5.63.0(react@19.0.0) '@tanstack/react-router': specifier: 1.89.2 version: 1.89.2(@tanstack/router-generator@1.87.7)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) @@ -405,11 +405,11 @@ importers: specifier: 2.1.3 version: 2.1.3 unplugin-auto-import: - specifier: 0.19.0 - version: 0.19.0(rollup@4.27.4) + specifier: 19.0.0 + version: 19.0.0(rollup@4.27.4) unplugin-icons: - specifier: 0.22.0 - version: 0.22.0(@svgr/core@8.1.0(typescript@5.7.2)) + specifier: 22.0.0 + version: 22.0.0(@svgr/core@8.1.0(typescript@5.7.2)) validator: specifier: 13.12.0 version: 13.12.0 @@ -575,8 +575,8 @@ importers: specifier: 2.26.16 version: 2.26.16 undici: - specifier: 7.2.0 - version: 7.2.0 + specifier: 7.2.1 + version: 7.2.1 packages: @@ -1751,8 +1751,8 @@ packages: '@vue/compiler-sfc': optional: true - '@iconify/json@2.2.293': - resolution: {integrity: sha512-eMRJNfQa+MXmE7I9noABNSVPxwsCkgmfgzeh84IKS2Su1cdQhi5FtsZa6YjEXK8y1cpbfv6pYk7KKJ6fV3mvOw==} + '@iconify/json@2.2.294': + resolution: {integrity: sha512-Vopidp3VQtscXYB6qUI8uJf15ihrzaJjwhvLnxHIMB3JYqvCKI1JHI+UMKaWkbOOJDsOg9b0rIXmRovShk8YrQ==} '@iconify/types@2.0.0': resolution: {integrity: sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg==} @@ -2723,8 +2723,8 @@ packages: '@tanstack/query-core@5.62.16': resolution: {integrity: sha512-9Sgft7Qavcd+sN0V25xVyo0nfmcZXBuODy3FVG7BMWTg1HMLm8wwG5tNlLlmSic1u7l1v786oavn+STiFaPH2g==} - '@tanstack/react-query@5.62.16': - resolution: {integrity: sha512-XJIZNj65d2IdvU8VBESmrPakfIm6FSdHDzrS1dPrAwmq3ZX+9riMh/ZfbNQHAWnhrgmq7KoXpgZSRyXnqMYT9A==} + '@tanstack/react-query@5.63.0': + resolution: {integrity: sha512-QWizLzSiog8xqIRYmuJRok9VELlXVBAwtINgVCgW1SNvamQwWDO5R0XFSkjoBEj53x9Of1KAthLRBUC5xmtVLQ==} peerDependencies: react: ^18 || ^19 @@ -5747,9 +5747,6 @@ packages: magic-string@0.30.14: resolution: {integrity: sha512-5c99P1WKTed11ZC0HMJOj6CDIue6F8ySu+bJL+85q1zBEIY8IklrJ1eiKC2NDRh3Ct3FcvmJPyQHb9erXMTJNw==} - magic-string@0.30.15: - resolution: {integrity: sha512-zXeaYRgZ6ldS1RJJUrMrYgNJ4fdwnyI6tVqoiIhyCyv5IVTK9BU8Ic2l253GGETQHxI4HNUwhJ3fjDhKqEoaAw==} - magic-string@0.30.17: resolution: {integrity: sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==} @@ -7742,8 +7739,8 @@ packages: resolution: {integrity: sha512-72RFADWFqKmUb2hmmvNODKL3p9hcB6Gt2DOQMis1SEBaV6a4MH8soBvzg+95CYhCKPFedut2JY9bMfrDl9D23g==} engines: {node: '>=14.0'} - undici@7.2.0: - resolution: {integrity: sha512-klt+0S55GBViA9nsq48/NSCo4YX5mjydjypxD7UmHh/brMu8h/Mhd/F7qAeoH2NOO8SDTk6kjnTFc4WpzmfYpQ==} + undici@7.2.1: + resolution: {integrity: sha512-U2k0XHLJfaciARRxDcqTk2AZQsGXerHzdvfCZcy1hNhSf5KCAF4jIQQxL+apQviOekhRFPqED6Of5/+LcUSLzQ==} engines: {node: '>=20.18.1'} unicode-canonical-property-names-ecmascript@2.0.1: @@ -7811,8 +7808,8 @@ packages: resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==} engines: {node: '>= 10.0.0'} - unplugin-auto-import@0.19.0: - resolution: {integrity: sha512-W97gTDEWu/L1EcKCXY5Ni8bsMW1E9kv12wYQv3mYpd7zcFctXYlLKsqeva6sbCQbzS8t9AG/XdU5/WkEJKPlFw==} + unplugin-auto-import@19.0.0: + resolution: {integrity: sha512-TREXtXqCM6YLy3rE2tjvKZEaCiPlP2e5bmnRKaS8AM2MlNgjV7UP4RPieWIfs4Isv0GoeHmov956PIIvJYdqpQ==} engines: {node: '>=14'} peerDependencies: '@nuxt/kit': ^3.2.2 @@ -7823,8 +7820,8 @@ packages: '@vueuse/core': optional: true - unplugin-icons@0.22.0: - resolution: {integrity: sha512-CP+iZq5U7doOifer5bcM0jQ9t3Is7EGybIYt3myVxceI8Zuk8EZEpe1NPtJvh7iqMs1VdbK0L41t9+um9VuuLw==} + unplugin-icons@22.0.0: + resolution: {integrity: sha512-+1jIt2wynxL+GISehNok8MIb9RaCufIZCHJs0HKbxOljJL9m4NtOhva+dZhNtSKtfQ62Hwd/RRbniSVuuD4Xow==} peerDependencies: '@svgr/core': '>=7.0.0' '@svgx/core': ^1.0.1 @@ -7854,6 +7851,10 @@ packages: resolution: {integrity: sha512-us4j03/499KhbGP8BU7Hrzrgseo+KdfJYWcbcajCOqsAyb8Gk0Yn2kiUIcZISYCb1JFaZfIuG3b42HmguVOKCQ==} engines: {node: '>=18.12.0'} + unplugin@2.1.2: + resolution: {integrity: sha512-Q3LU0e4zxKfRko1wMV2HmP8lB9KWislY7hxXpxd+lGx0PRInE4vhMBVEZwpdVYHvtqzhSrzuIfErsob6bQfCzw==} + engines: {node: '>=18.12.0'} + unzip-response@2.0.1: resolution: {integrity: sha512-N0XH6lqDtFH84JxptQoZYmloF4nzrQqqrAymNj+/gW60AO2AZgOcf4O/nUXJcYfyQkqvMo9lSupBZmmgvuVXlw==} engines: {node: '>=4'} @@ -8983,7 +8984,7 @@ snapshots: '@babel/parser': 7.26.3 '@babel/template': 7.25.9 '@babel/types': 7.26.3 - debug: 4.3.7 + debug: 4.4.0 globals: 11.12.0 transitivePeerDependencies: - supports-color @@ -9515,7 +9516,7 @@ snapshots: transitivePeerDependencies: - supports-color - '@iconify/json@2.2.293': + '@iconify/json@2.2.294': dependencies: '@iconify/types': 2.0.0 pathe: 1.1.2 @@ -10469,7 +10470,7 @@ snapshots: '@tanstack/query-core@5.62.16': {} - '@tanstack/react-query@5.62.16(react@19.0.0)': + '@tanstack/react-query@5.63.0(react@19.0.0)': dependencies: '@tanstack/query-core': 5.62.16 react: 19.0.0 @@ -13930,10 +13931,6 @@ snapshots: dependencies: '@jridgewell/sourcemap-codec': 1.5.0 - magic-string@0.30.15: - dependencies: - '@jridgewell/sourcemap-codec': 1.5.0 - magic-string@0.30.17: dependencies: '@jridgewell/sourcemap-codec': 1.5.0 @@ -16213,7 +16210,7 @@ snapshots: dependencies: '@fastify/busboy': 2.1.1 - undici@7.2.0: {} + undici@7.2.1: {} unicode-canonical-property-names-ecmascript@2.0.1: {} @@ -16240,13 +16237,13 @@ snapshots: unimport@3.14.5(rollup@4.27.4): dependencies: - '@rollup/pluginutils': 5.1.3(rollup@4.27.4) + '@rollup/pluginutils': 5.1.4(rollup@4.27.4) acorn: 8.14.0 escape-string-regexp: 5.0.0 estree-walker: 3.0.3 fast-glob: 3.3.2 local-pkg: 0.5.1 - magic-string: 0.30.15 + magic-string: 0.30.17 mlly: 1.7.3 pathe: 1.1.2 picomatch: 4.0.2 @@ -16299,19 +16296,19 @@ snapshots: universalify@2.0.1: {} - unplugin-auto-import@0.19.0(rollup@4.27.4): + unplugin-auto-import@19.0.0(rollup@4.27.4): dependencies: '@antfu/utils': 0.7.10 - '@rollup/pluginutils': 5.1.3(rollup@4.27.4) + '@rollup/pluginutils': 5.1.4(rollup@4.27.4) local-pkg: 0.5.1 - magic-string: 0.30.15 + magic-string: 0.30.17 picomatch: 4.0.2 unimport: 3.14.5(rollup@4.27.4) - unplugin: 2.1.0 + unplugin: 2.1.2 transitivePeerDependencies: - rollup - unplugin-icons@0.22.0(@svgr/core@8.1.0(typescript@5.7.2)): + unplugin-icons@22.0.0(@svgr/core@8.1.0(typescript@5.7.2)): dependencies: '@antfu/install-pkg': 0.5.0 '@antfu/utils': 0.7.10 @@ -16335,6 +16332,11 @@ snapshots: acorn: 8.14.0 webpack-virtual-modules: 0.6.2 + unplugin@2.1.2: + dependencies: + acorn: 8.14.0 + webpack-virtual-modules: 0.6.2 + unzip-response@2.0.1: {} update-browserslist-db@1.0.15(browserslist@4.23.0): diff --git a/clash-nyanpasu/scripts/package.json b/clash-nyanpasu/scripts/package.json index 96169c94f5..36e7d0c995 100644 --- a/clash-nyanpasu/scripts/package.json +++ b/clash-nyanpasu/scripts/package.json @@ -22,6 +22,6 @@ "picocolors": "1.1.1", "tar": "7.4.3", "telegram": "2.26.16", - "undici": "7.2.0" + "undici": "7.2.1" } } diff --git a/clash-nyanpasu/scripts/prepare-nightly.ts b/clash-nyanpasu/scripts/prepare-nightly.ts index 72ad675c8f..6b631fd209 100644 --- a/clash-nyanpasu/scripts/prepare-nightly.ts +++ b/clash-nyanpasu/scripts/prepare-nightly.ts @@ -29,6 +29,7 @@ const NYANPASU_PACKAGE_JSON_PATH = path.join( const isNSIS = process.argv.includes('--nsis') // only build nsis const isMSI = process.argv.includes('--msi') // only build msi const fixedWebview = process.argv.includes('--fixed-webview') +const disableUpdater = process.argv.includes('--disable-updater') async function main() { consola.debug('Read config...') @@ -61,6 +62,10 @@ async function main() { tauriConf.bundle.targets = ['nsis'] } + if (disableUpdater) { + tauriConf.bundle.createUpdaterArtifacts = false + } + consola.debug('Get current git short hash') const GIT_SHORT_HASH = execSync('git rev-parse --short HEAD') .toString() diff --git a/lede/target/linux/generic/backport-6.6/410-v6.13-01-block-add-support-for-defining-read-only-partitions.patch b/lede/target/linux/generic/backport-6.6/410-v6.13-01-block-add-support-for-defining-read-only-partitions.patch new file mode 100644 index 0000000000..fabf16a2e6 --- /dev/null +++ b/lede/target/linux/generic/backport-6.6/410-v6.13-01-block-add-support-for-defining-read-only-partitions.patch @@ -0,0 +1,53 @@ +From 03cb793b26834ddca170ba87057c8f883772dd45 Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Thu, 3 Oct 2024 00:11:41 +0200 +Subject: [PATCH 1/5] block: add support for defining read-only partitions + +Add support for defining read-only partitions and complete support for +it in the cmdline partition parser as the additional "ro" after a +partition is scanned but never actually applied. + +Signed-off-by: Christian Marangi +Reviewed-by: Christoph Hellwig +Link: https://lore.kernel.org/r/20241002221306.4403-2-ansuelsmth@gmail.com +Signed-off-by: Jens Axboe +--- + block/blk.h | 1 + + block/partitions/cmdline.c | 3 +++ + block/partitions/core.c | 3 +++ + 3 files changed, 7 insertions(+) + +--- a/block/blk.h ++++ b/block/blk.h +@@ -424,6 +424,7 @@ void blk_free_ext_minor(unsigned int min + #define ADDPART_FLAG_NONE 0 + #define ADDPART_FLAG_RAID 1 + #define ADDPART_FLAG_WHOLEDISK 2 ++#define ADDPART_FLAG_READONLY 4 + int bdev_add_partition(struct gendisk *disk, int partno, sector_t start, + sector_t length); + int bdev_del_partition(struct gendisk *disk, int partno); +--- a/block/partitions/cmdline.c ++++ b/block/partitions/cmdline.c +@@ -237,6 +237,9 @@ static int add_part(int slot, struct cmd + put_partition(state, slot, subpart->from >> 9, + subpart->size >> 9); + ++ if (subpart->flags & PF_RDONLY) ++ state->parts[slot].flags |= ADDPART_FLAG_READONLY; ++ + info = &state->parts[slot].info; + + strscpy(info->volname, subpart->name, sizeof(info->volname)); +--- a/block/partitions/core.c ++++ b/block/partitions/core.c +@@ -392,6 +392,9 @@ static struct block_device *add_partitio + goto out_del; + } + ++ if (flags & ADDPART_FLAG_READONLY) ++ bdev->bd_read_only = true; ++ + /* everything is up and running, commence */ + err = xa_insert(&disk->part_tbl, partno, bdev, GFP_KERNEL); + if (err) diff --git a/lede/target/linux/generic/backport-6.6/410-v6.13-03-block-introduce-add_disk_fwnode.patch b/lede/target/linux/generic/backport-6.6/410-v6.13-03-block-introduce-add_disk_fwnode.patch new file mode 100644 index 0000000000..41b51ab215 --- /dev/null +++ b/lede/target/linux/generic/backport-6.6/410-v6.13-03-block-introduce-add_disk_fwnode.patch @@ -0,0 +1,94 @@ +From e5f587242b6072ffab4f4a084a459a59f3035873 Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Thu, 3 Oct 2024 00:11:43 +0200 +Subject: [PATCH 3/5] block: introduce add_disk_fwnode() + +Introduce add_disk_fwnode() as a replacement of device_add_disk() that +permits to pass and attach a fwnode to disk dev. + +This variant can be useful for eMMC that might have the partition table +for the disk defined in DT. A parser can later make use of the attached +fwnode to parse the related table and init the hardcoded partition for +the disk. + +device_add_disk() is converted to a simple wrapper of add_disk_fwnode() +with the fwnode entry set as NULL. + +Signed-off-by: Christian Marangi +Reviewed-by: Christoph Hellwig +Link: https://lore.kernel.org/r/20241002221306.4403-4-ansuelsmth@gmail.com +Signed-off-by: Jens Axboe +--- + block/genhd.c | 28 ++++++++++++++++++++++++---- + include/linux/blkdev.h | 3 +++ + 2 files changed, 27 insertions(+), 4 deletions(-) + +--- a/block/genhd.c ++++ b/block/genhd.c +@@ -383,16 +383,18 @@ int disk_scan_partitions(struct gendisk + } + + /** +- * device_add_disk - add disk information to kernel list ++ * add_disk_fwnode - add disk information to kernel list with fwnode + * @parent: parent device for the disk + * @disk: per-device partitioning information + * @groups: Additional per-device sysfs groups ++ * @fwnode: attached disk fwnode + * + * This function registers the partitioning information in @disk +- * with the kernel. ++ * with the kernel. Also attach a fwnode to the disk device. + */ +-int __must_check device_add_disk(struct device *parent, struct gendisk *disk, +- const struct attribute_group **groups) ++int __must_check add_disk_fwnode(struct device *parent, struct gendisk *disk, ++ const struct attribute_group **groups, ++ struct fwnode_handle *fwnode) + + { + struct device *ddev = disk_to_dev(disk); +@@ -451,6 +453,8 @@ int __must_check device_add_disk(struct + ddev->parent = parent; + ddev->groups = groups; + dev_set_name(ddev, "%s", disk->disk_name); ++ if (fwnode) ++ device_set_node(ddev, fwnode); + if (!(disk->flags & GENHD_FL_HIDDEN)) + ddev->devt = MKDEV(disk->major, disk->first_minor); + ret = device_add(ddev); +@@ -552,6 +556,22 @@ out_exit_elevator: + elevator_exit(disk->queue); + return ret; + } ++EXPORT_SYMBOL_GPL(add_disk_fwnode); ++ ++/** ++ * device_add_disk - add disk information to kernel list ++ * @parent: parent device for the disk ++ * @disk: per-device partitioning information ++ * @groups: Additional per-device sysfs groups ++ * ++ * This function registers the partitioning information in @disk ++ * with the kernel. ++ */ ++int __must_check device_add_disk(struct device *parent, struct gendisk *disk, ++ const struct attribute_group **groups) ++{ ++ return add_disk_fwnode(parent, disk, groups, NULL); ++} + EXPORT_SYMBOL(device_add_disk); + + static void blk_report_disk_dead(struct gendisk *disk, bool surprise) +--- a/include/linux/blkdev.h ++++ b/include/linux/blkdev.h +@@ -741,6 +741,9 @@ static inline unsigned int blk_queue_dep + #define for_each_bio(_bio) \ + for (; _bio; _bio = _bio->bi_next) + ++int __must_check add_disk_fwnode(struct device *parent, struct gendisk *disk, ++ const struct attribute_group **groups, ++ struct fwnode_handle *fwnode); + int __must_check device_add_disk(struct device *parent, struct gendisk *disk, + const struct attribute_group **groups); + static inline int __must_check add_disk(struct gendisk *disk) diff --git a/lede/target/linux/generic/backport-6.6/410-v6.13-04-mmc-block-attach-partitions-fwnode-if-found-in-mmc-c.patch b/lede/target/linux/generic/backport-6.6/410-v6.13-04-mmc-block-attach-partitions-fwnode-if-found-in-mmc-c.patch new file mode 100644 index 0000000000..cf0d18cf06 --- /dev/null +++ b/lede/target/linux/generic/backport-6.6/410-v6.13-04-mmc-block-attach-partitions-fwnode-if-found-in-mmc-c.patch @@ -0,0 +1,104 @@ +From 45ff6c340ddfc2dade74d5b7a8962c778ab7042c Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Thu, 3 Oct 2024 00:11:44 +0200 +Subject: [PATCH 4/5] mmc: block: attach partitions fwnode if found in mmc-card + +Attach partitions fwnode if found in mmc-card and register disk with it. + +This permits block partition to reference the node and register a +partition table defined in DT for the special case for embedded device +that doesn't have a partition table flashed but have an hardcoded +partition table passed from the system. + +JEDEC BOOT partition boot0/boot1 are supported but in DT we refer with +the JEDEC name of boot1 and boot2 to better adhere to documentation. + +Also JEDEC GP partition gp0/1/2/3 are supported but in DT we refer with +the JEDEC name of gp1/2/3/4 to better adhere to documentration. + +Signed-off-by: Christian Marangi +Reviewed-by: Linus Walleij +Link: https://lore.kernel.org/r/20241002221306.4403-5-ansuelsmth@gmail.com +Signed-off-by: Jens Axboe +--- + drivers/mmc/core/block.c | 55 +++++++++++++++++++++++++++++++++++++++- + 1 file changed, 54 insertions(+), 1 deletion(-) + +--- a/drivers/mmc/core/block.c ++++ b/drivers/mmc/core/block.c +@@ -2455,6 +2455,56 @@ static inline int mmc_blk_readonly(struc + !(card->csd.cmdclass & CCC_BLOCK_WRITE); + } + ++/* ++ * Search for a declared partitions node for the disk in mmc-card related node. ++ * ++ * This is to permit support for partition table defined in DT in special case ++ * where a partition table is not written in the disk and is expected to be ++ * passed from the running system. ++ * ++ * For the user disk, "partitions" node is searched. ++ * For the special HW disk, "partitions-" node with the appended name is used ++ * following this conversion table (to adhere to JEDEC naming) ++ * - boot0 -> partitions-boot1 ++ * - boot1 -> partitions-boot2 ++ * - gp0 -> partitions-gp1 ++ * - gp1 -> partitions-gp2 ++ * - gp2 -> partitions-gp3 ++ * - gp3 -> partitions-gp4 ++ */ ++static struct fwnode_handle *mmc_blk_get_partitions_node(struct device *mmc_dev, ++ const char *subname) ++{ ++ const char *node_name = "partitions"; ++ ++ if (subname) { ++ mmc_dev = mmc_dev->parent; ++ ++ /* ++ * Check if we are allocating a BOOT disk boot0/1 disk. ++ * In DT we use the JEDEC naming boot1/2. ++ */ ++ if (!strcmp(subname, "boot0")) ++ node_name = "partitions-boot1"; ++ if (!strcmp(subname, "boot1")) ++ node_name = "partitions-boot2"; ++ /* ++ * Check if we are allocating a GP disk gp0/1/2/3 disk. ++ * In DT we use the JEDEC naming gp1/2/3/4. ++ */ ++ if (!strcmp(subname, "gp0")) ++ node_name = "partitions-gp1"; ++ if (!strcmp(subname, "gp1")) ++ node_name = "partitions-gp2"; ++ if (!strcmp(subname, "gp2")) ++ node_name = "partitions-gp3"; ++ if (!strcmp(subname, "gp3")) ++ node_name = "partitions-gp4"; ++ } ++ ++ return device_get_named_child_node(mmc_dev, node_name); ++} ++ + static struct mmc_blk_data *mmc_blk_alloc_req(struct mmc_card *card, + struct device *parent, + sector_t size, +@@ -2463,6 +2513,7 @@ static struct mmc_blk_data *mmc_blk_allo + int area_type, + unsigned int part_type) + { ++ struct fwnode_handle *disk_fwnode; + struct mmc_blk_data *md; + int devidx, ret; + char cap_str[10]; +@@ -2568,7 +2619,9 @@ static struct mmc_blk_data *mmc_blk_allo + /* used in ->open, must be set before add_disk: */ + if (area_type == MMC_BLK_DATA_AREA_MAIN) + dev_set_drvdata(&card->dev, md); +- ret = device_add_disk(md->parent, md->disk, mmc_disk_attr_groups); ++ disk_fwnode = mmc_blk_get_partitions_node(parent, subname); ++ ret = add_disk_fwnode(md->parent, md->disk, mmc_disk_attr_groups, ++ disk_fwnode); + if (ret) + goto err_put_disk; + return md; diff --git a/lede/target/linux/generic/backport-6.6/410-v6.13-05-block-add-support-for-partition-table-defined-in-OF.patch b/lede/target/linux/generic/backport-6.6/410-v6.13-05-block-add-support-for-partition-table-defined-in-OF.patch new file mode 100644 index 0000000000..d260be168c --- /dev/null +++ b/lede/target/linux/generic/backport-6.6/410-v6.13-05-block-add-support-for-partition-table-defined-in-OF.patch @@ -0,0 +1,200 @@ +From 884555b557e5e6d41c866e2cd8d7b32f50ec974b Mon Sep 17 00:00:00 2001 +From: Christian Marangi +Date: Thu, 3 Oct 2024 00:11:45 +0200 +Subject: [PATCH 5/5] block: add support for partition table defined in OF + +Add support for partition table defined in Device Tree. Similar to how +it's done with MTD, add support for defining a fixed partition table in +device tree. + +A common scenario for this is fixed block (eMMC) embedded devices that +have no MBR or GPT partition table to save storage space. Bootloader +access the block device with absolute address of data. + +This is to complete the functionality with an equivalent implementation +with providing partition table with bootargs, for case where the booargs +can't be modified and tweaking the Device Tree is the only solution to +have an usabe partition table. + +The implementation follow the fixed-partitions parser used on MTD +devices where a "partitions" node is expected to be declared with +"fixed-partitions" compatible in the OF node of the disk device +(mmc-card for eMMC for example) and each child node declare a label +and a reg with offset and size. If label is not declared, the node name +is used as fallback. Eventually is also possible to declare the read-only +property to flag the partition as read-only. + +Signed-off-by: Christian Marangi +Reviewed-by: Christoph Hellwig +Link: https://lore.kernel.org/r/20241002221306.4403-6-ansuelsmth@gmail.com +Signed-off-by: Jens Axboe +--- + block/partitions/Kconfig | 9 ++++ + block/partitions/Makefile | 1 + + block/partitions/check.h | 1 + + block/partitions/core.c | 3 ++ + block/partitions/of.c | 110 ++++++++++++++++++++++++++++++++++++++ + 5 files changed, 124 insertions(+) + create mode 100644 block/partitions/of.c + +--- a/block/partitions/Kconfig ++++ b/block/partitions/Kconfig +@@ -270,4 +270,13 @@ config CMDLINE_PARTITION + Say Y here if you want to read the partition table from bootargs. + The format for the command line is just like mtdparts. + ++config OF_PARTITION ++ bool "Device Tree partition support" if PARTITION_ADVANCED ++ depends on OF ++ help ++ Say Y here if you want to enable support for partition table ++ defined in Device Tree. (mainly for eMMC) ++ The format for the device tree node is just like MTD fixed-partition ++ schema. ++ + endmenu +--- a/block/partitions/Makefile ++++ b/block/partitions/Makefile +@@ -12,6 +12,7 @@ obj-$(CONFIG_CMDLINE_PARTITION) += cmdli + obj-$(CONFIG_MAC_PARTITION) += mac.o + obj-$(CONFIG_LDM_PARTITION) += ldm.o + obj-$(CONFIG_MSDOS_PARTITION) += msdos.o ++obj-$(CONFIG_OF_PARTITION) += of.o + obj-$(CONFIG_OSF_PARTITION) += osf.o + obj-$(CONFIG_SGI_PARTITION) += sgi.o + obj-$(CONFIG_SUN_PARTITION) += sun.o +--- a/block/partitions/check.h ++++ b/block/partitions/check.h +@@ -62,6 +62,7 @@ int karma_partition(struct parsed_partit + int ldm_partition(struct parsed_partitions *state); + int mac_partition(struct parsed_partitions *state); + int msdos_partition(struct parsed_partitions *state); ++int of_partition(struct parsed_partitions *state); + int osf_partition(struct parsed_partitions *state); + int sgi_partition(struct parsed_partitions *state); + int sun_partition(struct parsed_partitions *state); +--- a/block/partitions/core.c ++++ b/block/partitions/core.c +@@ -43,6 +43,9 @@ static int (*const check_part[])(struct + #ifdef CONFIG_CMDLINE_PARTITION + cmdline_partition, + #endif ++#ifdef CONFIG_OF_PARTITION ++ of_partition, /* cmdline have priority to OF */ ++#endif + #ifdef CONFIG_EFI_PARTITION + efi_partition, /* this must come before msdos */ + #endif +--- /dev/null ++++ b/block/partitions/of.c +@@ -0,0 +1,110 @@ ++// SPDX-License-Identifier: GPL-2.0 ++ ++#include ++#include ++#include ++#include ++#include "check.h" ++ ++static int validate_of_partition(struct device_node *np, int slot) ++{ ++ u64 offset, size; ++ int len; ++ ++ const __be32 *reg = of_get_property(np, "reg", &len); ++ int a_cells = of_n_addr_cells(np); ++ int s_cells = of_n_size_cells(np); ++ ++ /* Make sure reg len match the expected addr and size cells */ ++ if (len / sizeof(*reg) != a_cells + s_cells) ++ return -EINVAL; ++ ++ /* Validate offset conversion from bytes to sectors */ ++ offset = of_read_number(reg, a_cells); ++ if (offset % SECTOR_SIZE) ++ return -EINVAL; ++ ++ /* Validate size conversion from bytes to sectors */ ++ size = of_read_number(reg + a_cells, s_cells); ++ if (!size || size % SECTOR_SIZE) ++ return -EINVAL; ++ ++ return 0; ++} ++ ++static void add_of_partition(struct parsed_partitions *state, int slot, ++ struct device_node *np) ++{ ++ struct partition_meta_info *info; ++ char tmp[sizeof(info->volname) + 4]; ++ const char *partname; ++ int len; ++ ++ const __be32 *reg = of_get_property(np, "reg", &len); ++ int a_cells = of_n_addr_cells(np); ++ int s_cells = of_n_size_cells(np); ++ ++ /* Convert bytes to sector size */ ++ u64 offset = of_read_number(reg, a_cells) / SECTOR_SIZE; ++ u64 size = of_read_number(reg + a_cells, s_cells) / SECTOR_SIZE; ++ ++ put_partition(state, slot, offset, size); ++ ++ if (of_property_read_bool(np, "read-only")) ++ state->parts[slot].flags |= ADDPART_FLAG_READONLY; ++ ++ /* ++ * Follow MTD label logic, search for label property, ++ * fallback to node name if not found. ++ */ ++ info = &state->parts[slot].info; ++ partname = of_get_property(np, "label", &len); ++ if (!partname) ++ partname = of_get_property(np, "name", &len); ++ strscpy(info->volname, partname, sizeof(info->volname)); ++ ++ snprintf(tmp, sizeof(tmp), "(%s)", info->volname); ++ strlcat(state->pp_buf, tmp, PAGE_SIZE); ++} ++ ++int of_partition(struct parsed_partitions *state) ++{ ++ struct device *ddev = disk_to_dev(state->disk); ++ struct device_node *np; ++ int slot; ++ ++ struct device_node *partitions_np = of_node_get(ddev->of_node); ++ ++ if (!partitions_np || ++ !of_device_is_compatible(partitions_np, "fixed-partitions")) ++ return 0; ++ ++ slot = 1; ++ /* Validate parition offset and size */ ++ for_each_child_of_node(partitions_np, np) { ++ if (validate_of_partition(np, slot)) { ++ of_node_put(np); ++ of_node_put(partitions_np); ++ ++ return -1; ++ } ++ ++ slot++; ++ } ++ ++ slot = 1; ++ for_each_child_of_node(partitions_np, np) { ++ if (slot >= state->limit) { ++ of_node_put(np); ++ break; ++ } ++ ++ add_of_partition(state, slot, np); ++ ++ slot++; ++ } ++ ++ strlcat(state->pp_buf, "\n", PAGE_SIZE); ++ ++ return 1; ++} diff --git a/lede/target/linux/generic/config-6.6 b/lede/target/linux/generic/config-6.6 index 1da5697ed6..13b0bafe71 100644 --- a/lede/target/linux/generic/config-6.6 +++ b/lede/target/linux/generic/config-6.6 @@ -4364,6 +4364,7 @@ CONFIG_NLS_DEFAULT="iso8859-1" # CONFIG_OCTEONTX2_PF is not set # CONFIG_OCTEON_EP is not set # CONFIG_OF_OVERLAY is not set +CONFIG_OF_PARTITION=y CONFIG_OF_RESERVED_MEM=y # CONFIG_OF_UNITTEST is not set # CONFIG_OID_REGISTRY is not set diff --git a/lede/target/linux/generic/pending-6.6/451-block-partitions-populate-fwnode.patch b/lede/target/linux/generic/pending-6.6/451-block-partitions-populate-fwnode.patch index e279b71173..35b908ca6d 100644 --- a/lede/target/linux/generic/pending-6.6/451-block-partitions-populate-fwnode.patch +++ b/lede/target/linux/generic/pending-6.6/451-block-partitions-populate-fwnode.patch @@ -49,7 +49,7 @@ Signed-off-by: Daniel Golle #include "check.h" static int (*const check_part[])(struct parsed_partitions *) = { -@@ -292,6 +294,74 @@ static ssize_t whole_disk_show(struct de +@@ -295,6 +297,74 @@ static ssize_t whole_disk_show(struct de } static const DEVICE_ATTR(whole_disk, 0444, whole_disk_show, NULL); @@ -124,7 +124,7 @@ Signed-off-by: Daniel Golle /* * Must be called either with open_mutex held, before a disk can be opened or * after all disk users are gone. -@@ -374,6 +444,8 @@ static struct block_device *add_partitio +@@ -377,6 +447,8 @@ static struct block_device *add_partitio goto out_put; } diff --git a/lede/target/linux/generic/pending-6.6/452-block-add-support-for-notifications.patch b/lede/target/linux/generic/pending-6.6/452-block-add-support-for-notifications.patch index cad3fbfa90..667852e387 100644 --- a/lede/target/linux/generic/pending-6.6/452-block-add-support-for-notifications.patch +++ b/lede/target/linux/generic/pending-6.6/452-block-add-support-for-notifications.patch @@ -156,7 +156,7 @@ Signed-off-by: Daniel Golle +device_initcall(blk_notifications_init); --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h -@@ -1564,4 +1564,15 @@ struct io_comp_batch { +@@ -1567,4 +1567,15 @@ struct io_comp_batch { #define DEFINE_IO_COMP_BATCH(name) struct io_comp_batch name = { } diff --git a/lede/target/linux/generic/pending-6.6/457-mmc-block-set-fwnode-of-disk-devices.patch b/lede/target/linux/generic/pending-6.6/457-mmc-block-set-fwnode-of-disk-devices.patch index b45a0ebb1a..66f3515621 100644 --- a/lede/target/linux/generic/pending-6.6/457-mmc-block-set-fwnode-of-disk-devices.patch +++ b/lede/target/linux/generic/pending-6.6/457-mmc-block-set-fwnode-of-disk-devices.patch @@ -14,24 +14,14 @@ Signed-off-by: Daniel Golle --- a/drivers/mmc/core/block.c +++ b/drivers/mmc/core/block.c -@@ -2463,6 +2463,7 @@ static struct mmc_blk_data *mmc_blk_allo - int area_type, - unsigned int part_type) - { -+ struct fwnode_handle *fwnode; - struct mmc_blk_data *md; - int devidx, ret; - char cap_str[10]; -@@ -2559,6 +2560,12 @@ static struct mmc_blk_data *mmc_blk_allo - - blk_queue_write_cache(md->queue.queue, cache_enabled, fua_enabled); - -+ fwnode = device_get_named_child_node(subname ? md->parent->parent : -+ md->parent, -+ subname ? subname : "block"); -+ if (fwnode) -+ device_set_node(disk_to_dev(md->disk), fwnode); -+ - string_get_size((u64)size, 512, STRING_UNITS_2, - cap_str, sizeof(cap_str)); - pr_info("%s: %s %s %s%s\n", +@@ -2620,6 +2620,10 @@ static struct mmc_blk_data *mmc_blk_allo + if (area_type == MMC_BLK_DATA_AREA_MAIN) + dev_set_drvdata(&card->dev, md); + disk_fwnode = mmc_blk_get_partitions_node(parent, subname); ++ if (!disk_fwnode) ++ disk_fwnode = device_get_named_child_node(subname ? md->parent->parent : ++ md->parent, ++ subname ? subname : "block"); + ret = add_disk_fwnode(md->parent, md->disk, mmc_disk_attr_groups, + disk_fwnode); + if (ret) diff --git a/lede/target/linux/generic/pending-6.6/458-mmc-block-set-GENHD_FL_NVMEM.patch b/lede/target/linux/generic/pending-6.6/458-mmc-block-set-GENHD_FL_NVMEM.patch index 713401f104..7f9c512e45 100644 --- a/lede/target/linux/generic/pending-6.6/458-mmc-block-set-GENHD_FL_NVMEM.patch +++ b/lede/target/linux/generic/pending-6.6/458-mmc-block-set-GENHD_FL_NVMEM.patch @@ -12,7 +12,7 @@ Signed-off-by: Daniel Golle --- a/drivers/mmc/core/block.c +++ b/drivers/mmc/core/block.c -@@ -2516,6 +2516,7 @@ static struct mmc_blk_data *mmc_blk_allo +@@ -2566,6 +2566,7 @@ static struct mmc_blk_data *mmc_blk_allo md->disk->major = MMC_BLOCK_MAJOR; md->disk->minors = perdev_minors; md->disk->first_minor = devidx * perdev_minors; diff --git a/lede/target/linux/mediatek/patches-6.6/041-block-fit-partition-parser.patch b/lede/target/linux/mediatek/patches-6.6/041-block-fit-partition-parser.patch index e64f5dc241..12014c17e8 100644 --- a/lede/target/linux/mediatek/patches-6.6/041-block-fit-partition-parser.patch +++ b/lede/target/linux/mediatek/patches-6.6/041-block-fit-partition-parser.patch @@ -19,11 +19,10 @@ Subject: [PATCH] kernel: add block fit partition parser --- a/block/blk.h +++ b/block/blk.h -@@ -424,6 +424,8 @@ void blk_free_ext_minor(unsigned int min - #define ADDPART_FLAG_NONE 0 +@@ -425,6 +425,7 @@ void blk_free_ext_minor(unsigned int min #define ADDPART_FLAG_RAID 1 #define ADDPART_FLAG_WHOLEDISK 2 -+#define ADDPART_FLAG_READONLY 4 + #define ADDPART_FLAG_READONLY 4 +#define ADDPART_FLAG_ROOTDEV 8 int bdev_add_partition(struct gendisk *disk, int partno, sector_t start, sector_t length); diff --git a/mieru/pkg/appctl/appctlpb/base.pb.go b/mieru/pkg/appctl/appctlpb/base.pb.go index 79e939523e..3b0830b1bd 100644 --- a/mieru/pkg/appctl/appctlpb/base.pb.go +++ b/mieru/pkg/appctl/appctlpb/base.pb.go @@ -155,6 +155,61 @@ func (LoggingLevel) EnumDescriptor() ([]byte, []int) { return file_base_proto_rawDescGZIP(), []int{1} } +type DualStack int32 + +const ( + DualStack_ANY_IP_VERSION DualStack = 0 + DualStack_PREFER_IPv4 DualStack = 1 + DualStack_PREFER_IPv6 DualStack = 2 + DualStack_ONLY_IPv4 DualStack = 3 + DualStack_ONLY_IPv6 DualStack = 4 +) + +// Enum value maps for DualStack. +var ( + DualStack_name = map[int32]string{ + 0: "ANY_IP_VERSION", + 1: "PREFER_IPv4", + 2: "PREFER_IPv6", + 3: "ONLY_IPv4", + 4: "ONLY_IPv6", + } + DualStack_value = map[string]int32{ + "ANY_IP_VERSION": 0, + "PREFER_IPv4": 1, + "PREFER_IPv6": 2, + "ONLY_IPv4": 3, + "ONLY_IPv6": 4, + } +) + +func (x DualStack) Enum() *DualStack { + p := new(DualStack) + *p = x + return p +} + +func (x DualStack) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (DualStack) Descriptor() protoreflect.EnumDescriptor { + return file_base_proto_enumTypes[2].Descriptor() +} + +func (DualStack) Type() protoreflect.EnumType { + return &file_base_proto_enumTypes[2] +} + +func (x DualStack) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use DualStack.Descriptor instead. +func (DualStack) EnumDescriptor() ([]byte, []int) { + return file_base_proto_rawDescGZIP(), []int{2} +} + type TransportProtocol int32 const ( @@ -188,11 +243,11 @@ func (x TransportProtocol) String() string { } func (TransportProtocol) Descriptor() protoreflect.EnumDescriptor { - return file_base_proto_enumTypes[2].Descriptor() + return file_base_proto_enumTypes[3].Descriptor() } func (TransportProtocol) Type() protoreflect.EnumType { - return &file_base_proto_enumTypes[2] + return &file_base_proto_enumTypes[3] } func (x TransportProtocol) Number() protoreflect.EnumNumber { @@ -201,7 +256,7 @@ func (x TransportProtocol) Number() protoreflect.EnumNumber { // Deprecated: Use TransportProtocol.Descriptor instead. func (TransportProtocol) EnumDescriptor() ([]byte, []int) { - return file_base_proto_rawDescGZIP(), []int{2} + return file_base_proto_rawDescGZIP(), []int{3} } type Empty struct { @@ -684,15 +739,21 @@ var file_base_proto_rawDesc = []byte{ 0x0a, 0x05, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x02, 0x12, 0x08, 0x0a, 0x04, 0x57, 0x41, 0x52, 0x4e, 0x10, 0x03, 0x12, 0x08, 0x0a, 0x04, 0x49, 0x4e, 0x46, 0x4f, 0x10, 0x04, 0x12, 0x09, 0x0a, 0x05, 0x44, 0x45, 0x42, 0x55, 0x47, 0x10, 0x05, 0x12, 0x09, 0x0a, 0x05, 0x54, 0x52, 0x41, 0x43, - 0x45, 0x10, 0x06, 0x2a, 0x45, 0x0a, 0x11, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, - 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x12, 0x1e, 0x0a, 0x1a, 0x55, 0x4e, 0x4b, 0x4e, - 0x4f, 0x57, 0x4e, 0x5f, 0x54, 0x52, 0x41, 0x4e, 0x53, 0x50, 0x4f, 0x52, 0x54, 0x5f, 0x50, 0x52, - 0x4f, 0x54, 0x4f, 0x43, 0x4f, 0x4c, 0x10, 0x00, 0x12, 0x07, 0x0a, 0x03, 0x55, 0x44, 0x50, 0x10, - 0x01, 0x12, 0x07, 0x0a, 0x03, 0x54, 0x43, 0x50, 0x10, 0x02, 0x42, 0x30, 0x5a, 0x2e, 0x67, 0x69, - 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x65, 0x6e, 0x66, 0x65, 0x69, 0x6e, 0x2f, - 0x6d, 0x69, 0x65, 0x72, 0x75, 0x2f, 0x76, 0x33, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x61, 0x70, 0x70, - 0x63, 0x74, 0x6c, 0x2f, 0x61, 0x70, 0x70, 0x63, 0x74, 0x6c, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x33, + 0x45, 0x10, 0x06, 0x2a, 0x5f, 0x0a, 0x09, 0x44, 0x75, 0x61, 0x6c, 0x53, 0x74, 0x61, 0x63, 0x6b, + 0x12, 0x12, 0x0a, 0x0e, 0x41, 0x4e, 0x59, 0x5f, 0x49, 0x50, 0x5f, 0x56, 0x45, 0x52, 0x53, 0x49, + 0x4f, 0x4e, 0x10, 0x00, 0x12, 0x0f, 0x0a, 0x0b, 0x50, 0x52, 0x45, 0x46, 0x45, 0x52, 0x5f, 0x49, + 0x50, 0x76, 0x34, 0x10, 0x01, 0x12, 0x0f, 0x0a, 0x0b, 0x50, 0x52, 0x45, 0x46, 0x45, 0x52, 0x5f, + 0x49, 0x50, 0x76, 0x36, 0x10, 0x02, 0x12, 0x0d, 0x0a, 0x09, 0x4f, 0x4e, 0x4c, 0x59, 0x5f, 0x49, + 0x50, 0x76, 0x34, 0x10, 0x03, 0x12, 0x0d, 0x0a, 0x09, 0x4f, 0x4e, 0x4c, 0x59, 0x5f, 0x49, 0x50, + 0x76, 0x36, 0x10, 0x04, 0x2a, 0x45, 0x0a, 0x11, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, + 0x74, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x12, 0x1e, 0x0a, 0x1a, 0x55, 0x4e, 0x4b, + 0x4e, 0x4f, 0x57, 0x4e, 0x5f, 0x54, 0x52, 0x41, 0x4e, 0x53, 0x50, 0x4f, 0x52, 0x54, 0x5f, 0x50, + 0x52, 0x4f, 0x54, 0x4f, 0x43, 0x4f, 0x4c, 0x10, 0x00, 0x12, 0x07, 0x0a, 0x03, 0x55, 0x44, 0x50, + 0x10, 0x01, 0x12, 0x07, 0x0a, 0x03, 0x54, 0x43, 0x50, 0x10, 0x02, 0x42, 0x30, 0x5a, 0x2e, 0x67, + 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x65, 0x6e, 0x66, 0x65, 0x69, 0x6e, + 0x2f, 0x6d, 0x69, 0x65, 0x72, 0x75, 0x2f, 0x76, 0x33, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x61, 0x70, + 0x70, 0x63, 0x74, 0x6c, 0x2f, 0x61, 0x70, 0x70, 0x63, 0x74, 0x6c, 0x70, 0x62, 0x62, 0x06, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -707,25 +768,26 @@ func file_base_proto_rawDescGZIP() []byte { return file_base_proto_rawDescData } -var file_base_proto_enumTypes = make([]protoimpl.EnumInfo, 3) +var file_base_proto_enumTypes = make([]protoimpl.EnumInfo, 4) var file_base_proto_msgTypes = make([]protoimpl.MessageInfo, 7) var file_base_proto_goTypes = []interface{}{ (AppStatus)(0), // 0: appctl.AppStatus (LoggingLevel)(0), // 1: appctl.LoggingLevel - (TransportProtocol)(0), // 2: appctl.TransportProtocol - (*Empty)(nil), // 3: appctl.Empty - (*AppStatusMsg)(nil), // 4: appctl.AppStatusMsg - (*ServerEndpoint)(nil), // 5: appctl.ServerEndpoint - (*PortBinding)(nil), // 6: appctl.PortBinding - (*User)(nil), // 7: appctl.User - (*Quota)(nil), // 8: appctl.Quota - (*Auth)(nil), // 9: appctl.Auth + (DualStack)(0), // 2: appctl.DualStack + (TransportProtocol)(0), // 3: appctl.TransportProtocol + (*Empty)(nil), // 4: appctl.Empty + (*AppStatusMsg)(nil), // 5: appctl.AppStatusMsg + (*ServerEndpoint)(nil), // 6: appctl.ServerEndpoint + (*PortBinding)(nil), // 7: appctl.PortBinding + (*User)(nil), // 8: appctl.User + (*Quota)(nil), // 9: appctl.Quota + (*Auth)(nil), // 10: appctl.Auth } var file_base_proto_depIdxs = []int32{ 0, // 0: appctl.AppStatusMsg.status:type_name -> appctl.AppStatus - 6, // 1: appctl.ServerEndpoint.portBindings:type_name -> appctl.PortBinding - 2, // 2: appctl.PortBinding.protocol:type_name -> appctl.TransportProtocol - 8, // 3: appctl.User.quotas:type_name -> appctl.Quota + 7, // 1: appctl.ServerEndpoint.portBindings:type_name -> appctl.PortBinding + 3, // 2: appctl.PortBinding.protocol:type_name -> appctl.TransportProtocol + 9, // 3: appctl.User.quotas:type_name -> appctl.Quota 4, // [4:4] is the sub-list for method output_type 4, // [4:4] is the sub-list for method input_type 4, // [4:4] is the sub-list for extension type_name @@ -835,7 +897,7 @@ func file_base_proto_init() { File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_base_proto_rawDesc, - NumEnums: 3, + NumEnums: 4, NumMessages: 7, NumExtensions: 0, NumServices: 0, diff --git a/mieru/pkg/appctl/appctlpb/servercfg.pb.go b/mieru/pkg/appctl/appctlpb/servercfg.pb.go index da1884f00b..2d442ba57d 100644 --- a/mieru/pkg/appctl/appctlpb/servercfg.pb.go +++ b/mieru/pkg/appctl/appctlpb/servercfg.pb.go @@ -151,6 +151,9 @@ type ServerConfig struct { Mtu *int32 `protobuf:"varint,5,opt,name=mtu,proto3,oneof" json:"mtu,omitempty"` // Egress proxies and rules. Egress *Egress `protobuf:"bytes,6,opt,name=egress,proto3,oneof" json:"egress,omitempty"` + // How to resolve IP address when the client send a request + // with a domain name. + Dns *DNS `protobuf:"bytes,7,opt,name=dns,proto3,oneof" json:"dns,omitempty"` } func (x *ServerConfig) Reset() { @@ -227,6 +230,13 @@ func (x *ServerConfig) GetEgress() *Egress { return nil } +func (x *ServerConfig) GetDns() *DNS { + if x != nil { + return x.Dns + } + return nil +} + type ServerAdvancedSettings struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -495,12 +505,60 @@ func (x *EgressRule) GetProxyName() string { return "" } +type DNS struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Pick up IP address from IP version preference. + DualStack *DualStack `protobuf:"varint,1,opt,name=dualStack,proto3,enum=appctl.DualStack,oneof" json:"dualStack,omitempty"` +} + +func (x *DNS) Reset() { + *x = DNS{} + if protoimpl.UnsafeEnabled { + mi := &file_servercfg_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *DNS) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DNS) ProtoMessage() {} + +func (x *DNS) ProtoReflect() protoreflect.Message { + mi := &file_servercfg_proto_msgTypes[5] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use DNS.ProtoReflect.Descriptor instead. +func (*DNS) Descriptor() ([]byte, []int) { + return file_servercfg_proto_rawDescGZIP(), []int{5} +} + +func (x *DNS) GetDualStack() DualStack { + if x != nil && x.DualStack != nil { + return *x.DualStack + } + return DualStack_ANY_IP_VERSION +} + var File_servercfg_proto protoreflect.FileDescriptor var file_servercfg_proto_rawDesc = []byte{ 0x0a, 0x0f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x63, 0x66, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x06, 0x61, 0x70, 0x70, 0x63, 0x74, 0x6c, 0x1a, 0x0a, 0x62, 0x61, 0x73, 0x65, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xf8, 0x02, 0x0a, 0x0c, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xa4, 0x03, 0x0a, 0x0c, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x37, 0x0a, 0x0c, 0x70, 0x6f, 0x72, 0x74, 0x42, 0x69, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x61, 0x70, 0x70, 0x63, 0x74, 0x6c, 0x2e, 0x50, 0x6f, 0x72, 0x74, 0x42, 0x69, 0x6e, 0x64, 0x69, 0x6e, @@ -520,64 +578,72 @@ var file_servercfg_proto_rawDesc = []byte{ 0x48, 0x02, 0x52, 0x03, 0x6d, 0x74, 0x75, 0x88, 0x01, 0x01, 0x12, 0x2b, 0x0a, 0x06, 0x65, 0x67, 0x72, 0x65, 0x73, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x61, 0x70, 0x70, 0x63, 0x74, 0x6c, 0x2e, 0x45, 0x67, 0x72, 0x65, 0x73, 0x73, 0x48, 0x03, 0x52, 0x06, 0x65, 0x67, - 0x72, 0x65, 0x73, 0x73, 0x88, 0x01, 0x01, 0x42, 0x13, 0x0a, 0x11, 0x5f, 0x61, 0x64, 0x76, 0x61, - 0x6e, 0x63, 0x65, 0x64, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x42, 0x0f, 0x0a, 0x0d, - 0x5f, 0x6c, 0x6f, 0x67, 0x67, 0x69, 0x6e, 0x67, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x42, 0x06, 0x0a, - 0x04, 0x5f, 0x6d, 0x74, 0x75, 0x42, 0x09, 0x0a, 0x07, 0x5f, 0x65, 0x67, 0x72, 0x65, 0x73, 0x73, - 0x22, 0x6d, 0x0a, 0x16, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x41, 0x64, 0x76, 0x61, 0x6e, 0x63, - 0x65, 0x64, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x39, 0x0a, 0x15, 0x61, 0x6c, - 0x6c, 0x6f, 0x77, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x48, 0x00, 0x52, 0x15, 0x61, 0x6c, 0x6c, - 0x6f, 0x77, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x88, 0x01, 0x01, 0x42, 0x18, 0x0a, 0x16, 0x5f, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x4c, - 0x6f, 0x63, 0x61, 0x6c, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, - 0x61, 0x0a, 0x06, 0x45, 0x67, 0x72, 0x65, 0x73, 0x73, 0x12, 0x2d, 0x0a, 0x07, 0x70, 0x72, 0x6f, - 0x78, 0x69, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x61, 0x70, 0x70, - 0x63, 0x74, 0x6c, 0x2e, 0x45, 0x67, 0x72, 0x65, 0x73, 0x73, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x52, - 0x07, 0x70, 0x72, 0x6f, 0x78, 0x69, 0x65, 0x73, 0x12, 0x28, 0x0a, 0x05, 0x72, 0x75, 0x6c, 0x65, - 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x61, 0x70, 0x70, 0x63, 0x74, 0x6c, - 0x2e, 0x45, 0x67, 0x72, 0x65, 0x73, 0x73, 0x52, 0x75, 0x6c, 0x65, 0x52, 0x05, 0x72, 0x75, 0x6c, - 0x65, 0x73, 0x22, 0x98, 0x02, 0x0a, 0x0b, 0x45, 0x67, 0x72, 0x65, 0x73, 0x73, 0x50, 0x72, 0x6f, - 0x78, 0x79, 0x12, 0x17, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x48, 0x00, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x88, 0x01, 0x01, 0x12, 0x36, 0x0a, 0x08, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x15, 0x2e, - 0x61, 0x70, 0x70, 0x63, 0x74, 0x6c, 0x2e, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x50, 0x72, 0x6f, 0x74, - 0x6f, 0x63, 0x6f, 0x6c, 0x48, 0x01, 0x52, 0x08, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, - 0x88, 0x01, 0x01, 0x12, 0x17, 0x0a, 0x04, 0x68, 0x6f, 0x73, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, - 0x09, 0x48, 0x02, 0x52, 0x04, 0x68, 0x6f, 0x73, 0x74, 0x88, 0x01, 0x01, 0x12, 0x17, 0x0a, 0x04, - 0x70, 0x6f, 0x72, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x48, 0x03, 0x52, 0x04, 0x70, 0x6f, - 0x72, 0x74, 0x88, 0x01, 0x01, 0x12, 0x45, 0x0a, 0x14, 0x73, 0x6f, 0x63, 0x6b, 0x73, 0x35, 0x41, - 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x05, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x61, 0x70, 0x70, 0x63, 0x74, 0x6c, 0x2e, 0x41, 0x75, 0x74, - 0x68, 0x48, 0x04, 0x52, 0x14, 0x73, 0x6f, 0x63, 0x6b, 0x73, 0x35, 0x41, 0x75, 0x74, 0x68, 0x65, - 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x88, 0x01, 0x01, 0x42, 0x07, 0x0a, 0x05, - 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x42, 0x0b, 0x0a, 0x09, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, - 0x6f, 0x6c, 0x42, 0x07, 0x0a, 0x05, 0x5f, 0x68, 0x6f, 0x73, 0x74, 0x42, 0x07, 0x0a, 0x05, 0x5f, - 0x70, 0x6f, 0x72, 0x74, 0x42, 0x17, 0x0a, 0x15, 0x5f, 0x73, 0x6f, 0x63, 0x6b, 0x73, 0x35, 0x41, - 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0xb9, 0x01, - 0x0a, 0x0a, 0x45, 0x67, 0x72, 0x65, 0x73, 0x73, 0x52, 0x75, 0x6c, 0x65, 0x12, 0x1a, 0x0a, 0x08, - 0x69, 0x70, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x08, - 0x69, 0x70, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x6f, 0x6d, 0x61, - 0x69, 0x6e, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0b, 0x64, - 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x12, 0x31, 0x0a, 0x06, 0x61, 0x63, - 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x14, 0x2e, 0x61, 0x70, 0x70, - 0x63, 0x74, 0x6c, 0x2e, 0x45, 0x67, 0x72, 0x65, 0x73, 0x73, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, - 0x48, 0x00, 0x52, 0x06, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x88, 0x01, 0x01, 0x12, 0x21, 0x0a, - 0x09, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, - 0x48, 0x01, 0x52, 0x09, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x4e, 0x61, 0x6d, 0x65, 0x88, 0x01, 0x01, - 0x42, 0x09, 0x0a, 0x07, 0x5f, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x0c, 0x0a, 0x0a, 0x5f, - 0x70, 0x72, 0x6f, 0x78, 0x79, 0x4e, 0x61, 0x6d, 0x65, 0x2a, 0x46, 0x0a, 0x0d, 0x50, 0x72, 0x6f, - 0x78, 0x79, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x12, 0x1a, 0x0a, 0x16, 0x55, 0x4e, - 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x5f, 0x50, 0x52, 0x4f, 0x58, 0x59, 0x5f, 0x50, 0x52, 0x4f, 0x54, - 0x4f, 0x43, 0x4f, 0x4c, 0x10, 0x00, 0x12, 0x19, 0x0a, 0x15, 0x53, 0x4f, 0x43, 0x4b, 0x53, 0x35, - 0x5f, 0x50, 0x52, 0x4f, 0x58, 0x59, 0x5f, 0x50, 0x52, 0x4f, 0x54, 0x4f, 0x43, 0x4f, 0x4c, 0x10, - 0x01, 0x2a, 0x31, 0x0a, 0x0c, 0x45, 0x67, 0x72, 0x65, 0x73, 0x73, 0x41, 0x63, 0x74, 0x69, 0x6f, - 0x6e, 0x12, 0x09, 0x0a, 0x05, 0x50, 0x52, 0x4f, 0x58, 0x59, 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, - 0x44, 0x49, 0x52, 0x45, 0x43, 0x54, 0x10, 0x01, 0x12, 0x0a, 0x0a, 0x06, 0x52, 0x45, 0x4a, 0x45, - 0x43, 0x54, 0x10, 0x02, 0x42, 0x30, 0x5a, 0x2e, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, - 0x6f, 0x6d, 0x2f, 0x65, 0x6e, 0x66, 0x65, 0x69, 0x6e, 0x2f, 0x6d, 0x69, 0x65, 0x72, 0x75, 0x2f, - 0x76, 0x33, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x61, 0x70, 0x70, 0x63, 0x74, 0x6c, 0x2f, 0x61, 0x70, - 0x70, 0x63, 0x74, 0x6c, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x72, 0x65, 0x73, 0x73, 0x88, 0x01, 0x01, 0x12, 0x22, 0x0a, 0x03, 0x64, 0x6e, 0x73, 0x18, 0x07, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0b, 0x2e, 0x61, 0x70, 0x70, 0x63, 0x74, 0x6c, 0x2e, 0x44, 0x4e, + 0x53, 0x48, 0x04, 0x52, 0x03, 0x64, 0x6e, 0x73, 0x88, 0x01, 0x01, 0x42, 0x13, 0x0a, 0x11, 0x5f, + 0x61, 0x64, 0x76, 0x61, 0x6e, 0x63, 0x65, 0x64, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, + 0x42, 0x0f, 0x0a, 0x0d, 0x5f, 0x6c, 0x6f, 0x67, 0x67, 0x69, 0x6e, 0x67, 0x4c, 0x65, 0x76, 0x65, + 0x6c, 0x42, 0x06, 0x0a, 0x04, 0x5f, 0x6d, 0x74, 0x75, 0x42, 0x09, 0x0a, 0x07, 0x5f, 0x65, 0x67, + 0x72, 0x65, 0x73, 0x73, 0x42, 0x06, 0x0a, 0x04, 0x5f, 0x64, 0x6e, 0x73, 0x22, 0x6d, 0x0a, 0x16, + 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x41, 0x64, 0x76, 0x61, 0x6e, 0x63, 0x65, 0x64, 0x53, 0x65, + 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x39, 0x0a, 0x15, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x4c, + 0x6f, 0x63, 0x61, 0x6c, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x08, 0x48, 0x00, 0x52, 0x15, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x4c, 0x6f, + 0x63, 0x61, 0x6c, 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x88, 0x01, + 0x01, 0x42, 0x18, 0x0a, 0x16, 0x5f, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x4c, 0x6f, 0x63, 0x61, 0x6c, + 0x44, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x61, 0x0a, 0x06, 0x45, + 0x67, 0x72, 0x65, 0x73, 0x73, 0x12, 0x2d, 0x0a, 0x07, 0x70, 0x72, 0x6f, 0x78, 0x69, 0x65, 0x73, + 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x61, 0x70, 0x70, 0x63, 0x74, 0x6c, 0x2e, + 0x45, 0x67, 0x72, 0x65, 0x73, 0x73, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x52, 0x07, 0x70, 0x72, 0x6f, + 0x78, 0x69, 0x65, 0x73, 0x12, 0x28, 0x0a, 0x05, 0x72, 0x75, 0x6c, 0x65, 0x73, 0x18, 0x02, 0x20, + 0x03, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x61, 0x70, 0x70, 0x63, 0x74, 0x6c, 0x2e, 0x45, 0x67, 0x72, + 0x65, 0x73, 0x73, 0x52, 0x75, 0x6c, 0x65, 0x52, 0x05, 0x72, 0x75, 0x6c, 0x65, 0x73, 0x22, 0x98, + 0x02, 0x0a, 0x0b, 0x45, 0x67, 0x72, 0x65, 0x73, 0x73, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x12, 0x17, + 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x04, + 0x6e, 0x61, 0x6d, 0x65, 0x88, 0x01, 0x01, 0x12, 0x36, 0x0a, 0x08, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x63, 0x6f, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x15, 0x2e, 0x61, 0x70, 0x70, 0x63, + 0x74, 0x6c, 0x2e, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, + 0x48, 0x01, 0x52, 0x08, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x88, 0x01, 0x01, 0x12, + 0x17, 0x0a, 0x04, 0x68, 0x6f, 0x73, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x48, 0x02, 0x52, + 0x04, 0x68, 0x6f, 0x73, 0x74, 0x88, 0x01, 0x01, 0x12, 0x17, 0x0a, 0x04, 0x70, 0x6f, 0x72, 0x74, + 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x48, 0x03, 0x52, 0x04, 0x70, 0x6f, 0x72, 0x74, 0x88, 0x01, + 0x01, 0x12, 0x45, 0x0a, 0x14, 0x73, 0x6f, 0x63, 0x6b, 0x73, 0x35, 0x41, 0x75, 0x74, 0x68, 0x65, + 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x0c, 0x2e, 0x61, 0x70, 0x70, 0x63, 0x74, 0x6c, 0x2e, 0x41, 0x75, 0x74, 0x68, 0x48, 0x04, 0x52, + 0x14, 0x73, 0x6f, 0x63, 0x6b, 0x73, 0x35, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x88, 0x01, 0x01, 0x42, 0x07, 0x0a, 0x05, 0x5f, 0x6e, 0x61, 0x6d, + 0x65, 0x42, 0x0b, 0x0a, 0x09, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x42, 0x07, + 0x0a, 0x05, 0x5f, 0x68, 0x6f, 0x73, 0x74, 0x42, 0x07, 0x0a, 0x05, 0x5f, 0x70, 0x6f, 0x72, 0x74, + 0x42, 0x17, 0x0a, 0x15, 0x5f, 0x73, 0x6f, 0x63, 0x6b, 0x73, 0x35, 0x41, 0x75, 0x74, 0x68, 0x65, + 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0xb9, 0x01, 0x0a, 0x0a, 0x45, 0x67, + 0x72, 0x65, 0x73, 0x73, 0x52, 0x75, 0x6c, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x69, 0x70, 0x52, 0x61, + 0x6e, 0x67, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x08, 0x69, 0x70, 0x52, 0x61, + 0x6e, 0x67, 0x65, 0x73, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x4e, 0x61, + 0x6d, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x6f, 0x6d, 0x61, 0x69, + 0x6e, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x12, 0x31, 0x0a, 0x06, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x14, 0x2e, 0x61, 0x70, 0x70, 0x63, 0x74, 0x6c, 0x2e, + 0x45, 0x67, 0x72, 0x65, 0x73, 0x73, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x00, 0x52, 0x06, + 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x88, 0x01, 0x01, 0x12, 0x21, 0x0a, 0x09, 0x70, 0x72, 0x6f, + 0x78, 0x79, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x48, 0x01, 0x52, 0x09, + 0x70, 0x72, 0x6f, 0x78, 0x79, 0x4e, 0x61, 0x6d, 0x65, 0x88, 0x01, 0x01, 0x42, 0x09, 0x0a, 0x07, + 0x5f, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x0c, 0x0a, 0x0a, 0x5f, 0x70, 0x72, 0x6f, 0x78, + 0x79, 0x4e, 0x61, 0x6d, 0x65, 0x22, 0x49, 0x0a, 0x03, 0x44, 0x4e, 0x53, 0x12, 0x34, 0x0a, 0x09, + 0x64, 0x75, 0x61, 0x6c, 0x53, 0x74, 0x61, 0x63, 0x6b, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, + 0x11, 0x2e, 0x61, 0x70, 0x70, 0x63, 0x74, 0x6c, 0x2e, 0x44, 0x75, 0x61, 0x6c, 0x53, 0x74, 0x61, + 0x63, 0x6b, 0x48, 0x00, 0x52, 0x09, 0x64, 0x75, 0x61, 0x6c, 0x53, 0x74, 0x61, 0x63, 0x6b, 0x88, + 0x01, 0x01, 0x42, 0x0c, 0x0a, 0x0a, 0x5f, 0x64, 0x75, 0x61, 0x6c, 0x53, 0x74, 0x61, 0x63, 0x6b, + 0x2a, 0x46, 0x0a, 0x0d, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, + 0x6c, 0x12, 0x1a, 0x0a, 0x16, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x5f, 0x50, 0x52, 0x4f, + 0x58, 0x59, 0x5f, 0x50, 0x52, 0x4f, 0x54, 0x4f, 0x43, 0x4f, 0x4c, 0x10, 0x00, 0x12, 0x19, 0x0a, + 0x15, 0x53, 0x4f, 0x43, 0x4b, 0x53, 0x35, 0x5f, 0x50, 0x52, 0x4f, 0x58, 0x59, 0x5f, 0x50, 0x52, + 0x4f, 0x54, 0x4f, 0x43, 0x4f, 0x4c, 0x10, 0x01, 0x2a, 0x31, 0x0a, 0x0c, 0x45, 0x67, 0x72, 0x65, + 0x73, 0x73, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x09, 0x0a, 0x05, 0x50, 0x52, 0x4f, 0x58, + 0x59, 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x44, 0x49, 0x52, 0x45, 0x43, 0x54, 0x10, 0x01, 0x12, + 0x0a, 0x0a, 0x06, 0x52, 0x45, 0x4a, 0x45, 0x43, 0x54, 0x10, 0x02, 0x42, 0x30, 0x5a, 0x2e, 0x67, + 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x65, 0x6e, 0x66, 0x65, 0x69, 0x6e, + 0x2f, 0x6d, 0x69, 0x65, 0x72, 0x75, 0x2f, 0x76, 0x33, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x61, 0x70, + 0x70, 0x63, 0x74, 0x6c, 0x2f, 0x61, 0x70, 0x70, 0x63, 0x74, 0x6c, 0x70, 0x62, 0x62, 0x06, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -593,7 +659,7 @@ func file_servercfg_proto_rawDescGZIP() []byte { } var file_servercfg_proto_enumTypes = make([]protoimpl.EnumInfo, 2) -var file_servercfg_proto_msgTypes = make([]protoimpl.MessageInfo, 5) +var file_servercfg_proto_msgTypes = make([]protoimpl.MessageInfo, 6) var file_servercfg_proto_goTypes = []interface{}{ (ProxyProtocol)(0), // 0: appctl.ProxyProtocol (EgressAction)(0), // 1: appctl.EgressAction @@ -602,27 +668,31 @@ var file_servercfg_proto_goTypes = []interface{}{ (*Egress)(nil), // 4: appctl.Egress (*EgressProxy)(nil), // 5: appctl.EgressProxy (*EgressRule)(nil), // 6: appctl.EgressRule - (*PortBinding)(nil), // 7: appctl.PortBinding - (*User)(nil), // 8: appctl.User - (LoggingLevel)(0), // 9: appctl.LoggingLevel - (*Auth)(nil), // 10: appctl.Auth + (*DNS)(nil), // 7: appctl.DNS + (*PortBinding)(nil), // 8: appctl.PortBinding + (*User)(nil), // 9: appctl.User + (LoggingLevel)(0), // 10: appctl.LoggingLevel + (*Auth)(nil), // 11: appctl.Auth + (DualStack)(0), // 12: appctl.DualStack } var file_servercfg_proto_depIdxs = []int32{ - 7, // 0: appctl.ServerConfig.portBindings:type_name -> appctl.PortBinding - 8, // 1: appctl.ServerConfig.users:type_name -> appctl.User + 8, // 0: appctl.ServerConfig.portBindings:type_name -> appctl.PortBinding + 9, // 1: appctl.ServerConfig.users:type_name -> appctl.User 3, // 2: appctl.ServerConfig.advancedSettings:type_name -> appctl.ServerAdvancedSettings - 9, // 3: appctl.ServerConfig.loggingLevel:type_name -> appctl.LoggingLevel + 10, // 3: appctl.ServerConfig.loggingLevel:type_name -> appctl.LoggingLevel 4, // 4: appctl.ServerConfig.egress:type_name -> appctl.Egress - 5, // 5: appctl.Egress.proxies:type_name -> appctl.EgressProxy - 6, // 6: appctl.Egress.rules:type_name -> appctl.EgressRule - 0, // 7: appctl.EgressProxy.protocol:type_name -> appctl.ProxyProtocol - 10, // 8: appctl.EgressProxy.socks5Authentication:type_name -> appctl.Auth - 1, // 9: appctl.EgressRule.action:type_name -> appctl.EgressAction - 10, // [10:10] is the sub-list for method output_type - 10, // [10:10] is the sub-list for method input_type - 10, // [10:10] is the sub-list for extension type_name - 10, // [10:10] is the sub-list for extension extendee - 0, // [0:10] is the sub-list for field type_name + 7, // 5: appctl.ServerConfig.dns:type_name -> appctl.DNS + 5, // 6: appctl.Egress.proxies:type_name -> appctl.EgressProxy + 6, // 7: appctl.Egress.rules:type_name -> appctl.EgressRule + 0, // 8: appctl.EgressProxy.protocol:type_name -> appctl.ProxyProtocol + 11, // 9: appctl.EgressProxy.socks5Authentication:type_name -> appctl.Auth + 1, // 10: appctl.EgressRule.action:type_name -> appctl.EgressAction + 12, // 11: appctl.DNS.dualStack:type_name -> appctl.DualStack + 12, // [12:12] is the sub-list for method output_type + 12, // [12:12] is the sub-list for method input_type + 12, // [12:12] is the sub-list for extension type_name + 12, // [12:12] is the sub-list for extension extendee + 0, // [0:12] is the sub-list for field type_name } func init() { file_servercfg_proto_init() } @@ -692,18 +762,31 @@ func file_servercfg_proto_init() { return nil } } + file_servercfg_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*DNS); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } } file_servercfg_proto_msgTypes[0].OneofWrappers = []interface{}{} file_servercfg_proto_msgTypes[1].OneofWrappers = []interface{}{} file_servercfg_proto_msgTypes[3].OneofWrappers = []interface{}{} file_servercfg_proto_msgTypes[4].OneofWrappers = []interface{}{} + file_servercfg_proto_msgTypes[5].OneofWrappers = []interface{}{} type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_servercfg_proto_rawDesc, NumEnums: 2, - NumMessages: 5, + NumMessages: 6, NumExtensions: 0, NumServices: 0, }, diff --git a/mieru/pkg/appctl/proto/base.proto b/mieru/pkg/appctl/proto/base.proto index ee83df02b1..11564cc7fb 100644 --- a/mieru/pkg/appctl/proto/base.proto +++ b/mieru/pkg/appctl/proto/base.proto @@ -51,6 +51,14 @@ enum LoggingLevel { TRACE = 6; } +enum DualStack { + ANY_IP_VERSION = 0; + PREFER_IPv4 = 1; + PREFER_IPv6 = 2; + ONLY_IPv4 = 3; + ONLY_IPv6 = 4; +} + message ServerEndpoint { // String representation of IP address. // It can be either IPv4 or IPv6. diff --git a/mieru/pkg/appctl/proto/servercfg.proto b/mieru/pkg/appctl/proto/servercfg.proto index c9fe95c022..f3731f135f 100644 --- a/mieru/pkg/appctl/proto/servercfg.proto +++ b/mieru/pkg/appctl/proto/servercfg.proto @@ -40,6 +40,10 @@ message ServerConfig { // Egress proxies and rules. optional Egress egress = 6; + + // How to resolve IP address when the client send a request + // with a domain name. + optional DNS dns = 7; } message ServerAdvancedSettings { @@ -105,3 +109,8 @@ enum EgressAction { // Do not connect to the destination. REJECT = 2; } + +message DNS { + // Pick up IP address from IP version preference. + optional DualStack dualStack = 1; +} diff --git a/mieru/pkg/appctl/server.go b/mieru/pkg/appctl/server.go index 96e3db1377..ca8595039e 100644 --- a/mieru/pkg/appctl/server.go +++ b/mieru/pkg/appctl/server.go @@ -133,8 +133,9 @@ func (s *serverLifecycleService) Start(ctx context.Context, req *pb.Empty) (*pb. AuthOpts: socks5.Auth{ ClientSideAuthentication: true, }, - EgressController: egress.NewSocks5Controller(config.GetEgress()), - HandshakeTimeout: 10 * time.Second, + DualStackPreference: common.DualStackPreference(config.GetDns().GetDualStack()), + EgressController: egress.NewSocks5Controller(config.GetEgress()), + HandshakeTimeout: 10 * time.Second, } socks5Server, err := socks5.New(socks5Config) if err != nil { @@ -759,6 +760,12 @@ func mergeServerConfig(dst, src *pb.ServerConfig) error { } else { egress = dst.GetEgress() } + var dns *pb.DNS + if src.Dns != nil { + dns = src.GetDns() + } else { + dns = dst.GetDns() + } proto.Reset(dst) dst.PortBindings = portBindings @@ -767,6 +774,7 @@ func mergeServerConfig(dst, src *pb.ServerConfig) error { dst.LoggingLevel = &loggingLevel dst.Mtu = proto.Int32(mtu) dst.Egress = egress + dst.Dns = dns return nil } diff --git a/mieru/pkg/appctl/testdata/server_apply_config_2.json b/mieru/pkg/appctl/testdata/server_apply_config_2.json index 076330f32b..b9f34ff351 100644 --- a/mieru/pkg/appctl/testdata/server_apply_config_2.json +++ b/mieru/pkg/appctl/testdata/server_apply_config_2.json @@ -52,5 +52,8 @@ "proxyName": "warp" } ] + }, + "dns": { + "dualStack": "PREFER_IPv4" } } diff --git a/mieru/pkg/cli/server.go b/mieru/pkg/cli/server.go index f466745630..f2d1860473 100644 --- a/mieru/pkg/cli/server.go +++ b/mieru/pkg/cli/server.go @@ -442,8 +442,9 @@ var serverRunFunc = func(s []string) error { AuthOpts: socks5.Auth{ ClientSideAuthentication: true, }, - EgressController: egress.NewSocks5Controller(config.GetEgress()), - HandshakeTimeout: 10 * time.Second, + DualStackPreference: common.DualStackPreference(config.GetDns().GetDualStack()), + EgressController: egress.NewSocks5Controller(config.GetEgress()), + HandshakeTimeout: 10 * time.Second, } socks5Server, err := socks5.New(socks5Config) if err != nil { diff --git a/mieru/pkg/common/ipdualstack.go b/mieru/pkg/common/ipdualstack.go index 39363fab85..e4b507f0a2 100644 --- a/mieru/pkg/common/ipdualstack.go +++ b/mieru/pkg/common/ipdualstack.go @@ -23,6 +23,19 @@ import ( "strings" ) +// DualStackPreference controls the strategy to pick one IP address +// from a list of IPs. +type DualStackPreference int32 + +// The values below must match with file pkg/appctl/proto/base.proto. +const ( + ANY_IP_VERSION DualStackPreference = 0 + PREFER_IPv4 DualStackPreference = 1 + PREFER_IPv6 DualStackPreference = 2 + ONLY_IPv4 DualStackPreference = 3 + ONLY_IPv6 DualStackPreference = 4 +) + // IsIPDualStack returns true if an IPv6 socket is able to send and receive // both IPv4 and IPv6 packets. // @@ -75,6 +88,46 @@ func MaybeDecorateIPv6(addr string) string { return addr } +// SelectIPFromList selects an IP address from a list of IP addresses +// based on the given DualStackPreference. +func SelectIPFromList(ips []net.IP, strategy DualStackPreference) net.IP { + if len(ips) == 0 { + return nil + } + + var ipv4, ipv6 net.IP + for _, ip := range ips { + if ip.To4() != nil { + if ipv4 == nil { + ipv4 = ip + } + } else { + if ipv6 == nil { + ipv6 = ip + } + } + } + + switch strategy { + case PREFER_IPv4: + if ipv4 != nil { + return ipv4 + } + return ipv6 + case PREFER_IPv6: + if ipv6 != nil { + return ipv6 + } + return ipv4 + case ONLY_IPv4: + return ipv4 + case ONLY_IPv6: + return ipv6 + default: + return ips[0] + } +} + // isIPv6 returns true if the given network address is IPv6. func isIPv6(addr string) bool { host, _, err := net.SplitHostPort(addr) diff --git a/mieru/pkg/common/ipdualstack_test.go b/mieru/pkg/common/ipdualstack_test.go index ca29ce4495..5b7f434aec 100644 --- a/mieru/pkg/common/ipdualstack_test.go +++ b/mieru/pkg/common/ipdualstack_test.go @@ -16,6 +16,7 @@ package common import ( + "net" "testing" ) @@ -40,3 +41,134 @@ func TestMaybeDecorateIPv6(t *testing.T) { } } } + +func TestSelectIPFromList(t *testing.T) { + testcases := []struct { + name string + ips []net.IP + strategy DualStackPreference + want net.IP + }{ + { + name: "empty list, prefer ipv4", + ips: []net.IP{}, + strategy: PREFER_IPv4, + want: nil, + }, + { + name: "ipv4 only, prefer ipv4", + ips: []net.IP{net.ParseIP("127.0.0.1")}, + strategy: PREFER_IPv4, + want: net.ParseIP("127.0.0.1"), + }, + { + name: "ipv4 only, prefer ipv6", + ips: []net.IP{net.ParseIP("127.0.0.1")}, + strategy: PREFER_IPv6, + want: net.ParseIP("127.0.0.1"), + }, + { + name: "ipv4 only, only ipv4", + ips: []net.IP{net.ParseIP("127.0.0.1")}, + strategy: ONLY_IPv4, + want: net.ParseIP("127.0.0.1"), + }, + { + name: "ipv4 only, only ipv6", + ips: []net.IP{net.ParseIP("127.0.0.1")}, + strategy: ONLY_IPv6, + want: nil, + }, + { + name: "ipv6 only, prefer ipv4", + ips: []net.IP{net.ParseIP("::1")}, + strategy: PREFER_IPv4, + want: net.ParseIP("::1"), + }, + { + name: "ipv6 only, prefer ipv6", + ips: []net.IP{net.ParseIP("::1")}, + strategy: PREFER_IPv6, + want: net.ParseIP("::1"), + }, + { + name: "ipv6 only, only ipv4", + ips: []net.IP{net.ParseIP("::1")}, + strategy: ONLY_IPv4, + want: nil, + }, + { + name: "ipv6 only, only ipv6", + ips: []net.IP{net.ParseIP("::1")}, + strategy: ONLY_IPv6, + want: net.ParseIP("::1"), + }, + { + name: "ipv4 and ipv6, any IP version", + ips: []net.IP{net.ParseIP("127.0.0.1"), net.ParseIP("127.0.0.2"), net.ParseIP("::1")}, + strategy: ANY_IP_VERSION, + want: net.ParseIP("127.0.0.1"), + }, + { + name: "ipv4 and ipv6, prefer ipv4", + ips: []net.IP{net.ParseIP("127.0.0.1"), net.ParseIP("127.0.0.2"), net.ParseIP("::1")}, + strategy: PREFER_IPv4, + want: net.ParseIP("127.0.0.1"), + }, + { + name: "ipv4 and ipv6, prefer ipv6", + ips: []net.IP{net.ParseIP("127.0.0.1"), net.ParseIP("127.0.0.2"), net.ParseIP("::1")}, + strategy: PREFER_IPv6, + want: net.ParseIP("::1"), + }, + { + name: "ipv4 and ipv6, only ipv4", + ips: []net.IP{net.ParseIP("127.0.0.1"), net.ParseIP("127.0.0.2"), net.ParseIP("::1")}, + strategy: ONLY_IPv4, + want: net.ParseIP("127.0.0.1"), + }, + { + name: "ipv4 and ipv6, only ipv6", + ips: []net.IP{net.ParseIP("127.0.0.1"), net.ParseIP("127.0.0.2"), net.ParseIP("::1")}, + strategy: ONLY_IPv6, + want: net.ParseIP("::1"), + }, + { + name: "ipv6 and ipv4, any IP version", + ips: []net.IP{net.ParseIP("::1"), net.ParseIP("::2"), net.ParseIP("127.0.0.1")}, + strategy: ANY_IP_VERSION, + want: net.ParseIP("::1"), + }, + { + name: "ipv6 and ipv4, prefer ipv4", + ips: []net.IP{net.ParseIP("::1"), net.ParseIP("::2"), net.ParseIP("127.0.0.1")}, + strategy: PREFER_IPv4, + want: net.ParseIP("127.0.0.1"), + }, + { + name: "ipv6 and ipv4, prefer ipv6", + ips: []net.IP{net.ParseIP("::1"), net.ParseIP("::2"), net.ParseIP("127.0.0.1")}, + strategy: PREFER_IPv6, + want: net.ParseIP("::1"), + }, + { + name: "ipv6 and ipv4, only ipv4", + ips: []net.IP{net.ParseIP("::1"), net.ParseIP("::2"), net.ParseIP("127.0.0.1")}, + strategy: ONLY_IPv4, + want: net.ParseIP("127.0.0.1"), + }, + { + name: "ipv6 and ipv4, only ipv6", + ips: []net.IP{net.ParseIP("::1"), net.ParseIP("::2"), net.ParseIP("127.0.0.1")}, + strategy: ONLY_IPv6, + want: net.ParseIP("::1"), + }, + } + + for _, tc := range testcases { + out := SelectIPFromList(tc.ips, tc.strategy) + if !out.Equal(tc.want) { + t.Errorf("%s: SelectIPFromList(%v, %v) = %v, want %v", tc.name, tc.ips, tc.strategy, out, tc.want) + } + } +} diff --git a/mieru/pkg/socks5/request.go b/mieru/pkg/socks5/request.go index da8ed11141..420cd99dad 100644 --- a/mieru/pkg/socks5/request.go +++ b/mieru/pkg/socks5/request.go @@ -96,8 +96,15 @@ func (s *Server) handleRequest(ctx context.Context, req *Request, conn io.ReadWr return fmt.Errorf(stderror.IPAddressNotFound, dst.FQDN) } } else { - log.Debugf("Resolved domain name %s to IP addresses: %v", dst.FQDN, ips) - dst.IP = ips[0] + dst.IP = common.SelectIPFromList(ips, s.config.DualStackPreference) + if dst.IP == nil { + DNSResolveErrors.Add(1) + if err := sendReply(conn, networkUnreachable, nil); err != nil { + return fmt.Errorf("failed to send reply: %w", err) + } + return fmt.Errorf("resolved domain name %s to IP addresses %v, but no IP address satisfy DNS dual stack preference", dst.FQDN, ips) + } + log.Debugf("Resolved domain name %s to IP addresses %v, selected IP address %v", dst.FQDN, ips, dst.IP) } } diff --git a/mieru/pkg/socks5/socks5.go b/mieru/pkg/socks5/socks5.go index 23880b9db3..0cdc4d9044 100644 --- a/mieru/pkg/socks5/socks5.go +++ b/mieru/pkg/socks5/socks5.go @@ -46,6 +46,9 @@ type Config struct { // Resolver can be provided to do custom name resolution. Resolver apicommon.DNSResolver + // Strategy to select IP address from DNS response. + DualStackPreference common.DualStackPreference + // BindIP is used for bind or udp associate BindIP net.IP diff --git a/mieru/test/deploy/externalconnect/server_tcp.json b/mieru/test/deploy/externalconnect/server_tcp.json index b1cf045cab..f6a9c77693 100644 --- a/mieru/test/deploy/externalconnect/server_tcp.json +++ b/mieru/test/deploy/externalconnect/server_tcp.json @@ -26,5 +26,8 @@ "advancedSettings": { "allowLocalDestination": true }, - "loggingLevel": "INFO" + "loggingLevel": "INFO", + "dns": { + "dualStack": "PREFER_IPv4" + } } diff --git a/mieru/test/deploy/externalconnect/server_udp.json b/mieru/test/deploy/externalconnect/server_udp.json index d6d18ceae2..c6eb69b383 100644 --- a/mieru/test/deploy/externalconnect/server_udp.json +++ b/mieru/test/deploy/externalconnect/server_udp.json @@ -27,5 +27,8 @@ "allowLocalDestination": true }, "loggingLevel": "INFO", - "mtu": 1400 + "mtu": 1400, + "dns": { + "dualStack": "PREFER_IPv4" + } } diff --git a/openwrt-passwall/luci-app-passwall/root/usr/share/passwall/subscribe.lua b/openwrt-passwall/luci-app-passwall/root/usr/share/passwall/subscribe.lua index 546a41e868..f8ad658ce3 100755 --- a/openwrt-passwall/luci-app-passwall/root/usr/share/passwall/subscribe.lua +++ b/openwrt-passwall/luci-app-passwall/root/usr/share/passwall/subscribe.lua @@ -96,6 +96,13 @@ local log = function(...) end end +local nodes_table = {} +for k, e in ipairs(api.get_valid_nodes()) do + if e.node_type == "normal" then + nodes_table[#nodes_table + 1] = e + end +end + -- 获取各项动态配置的当前服务器,可以用 get 和 set, get必须要获取到节点表 local CONFIG = {} do @@ -123,20 +130,56 @@ do local option = "node" uci:foreach(appname, "socks", function(t) i = i + 1 + local id = t[".name"] local node_id = t[option] CONFIG[#CONFIG + 1] = { log = true, - id = t[".name"], + id = id, remarks = "Socks节点列表[" .. i .. "]", currentNode = node_id and uci:get_all(appname, node_id) or nil, set = function(o, server) + if not server or server == "" then + if #nodes_table > 0 then + server = nodes_table[1][".name"] + end + end uci:set(appname, t[".name"], option, server) o.newNodeId = server - end, - delete = function(o) - uci:delete(appname, t[".name"]) end } + if t.autoswitch_backup_node and #t.autoswitch_backup_node > 0 then + local flag = "Socks节点列表[" .. i .. "]备用节点的列表" + local currentNodes = {} + local newNodes = {} + for k, node_id in ipairs(t.autoswitch_backup_node) do + if node_id then + local currentNode = uci:get_all(appname, node_id) or nil + if currentNode then + currentNodes[#currentNodes + 1] = { + log = true, + remarks = flag .. "[" .. k .. "]", + currentNode = currentNode, + set = function(o, server) + if server and server ~= "nil" then + table.insert(o.newNodes, server) + end + end + } + end + end + end + CONFIG[#CONFIG + 1] = { + remarks = flag, + currentNodes = currentNodes, + newNodes = newNodes, + set = function(o, newNodes) + if o then + if not newNodes then newNodes = o.newNodes end + uci:set_list(appname, id, "autoswitch_backup_node", newNodes or {}) + end + end + } + end end) end @@ -193,49 +236,6 @@ do end) end - uci:foreach(appname, "socks", function(o) - local id = o[".name"] - local node_table = uci:get(appname, id, "autoswitch_backup_node") - if node_table then - local nodes = {} - local new_nodes = {} - for k,node_id in ipairs(node_table) do - if node_id then - local currentNode = uci:get_all(appname, node_id) or nil - if currentNode then - if currentNode.protocol and (currentNode.protocol == "_balancing" or currentNode.protocol == "_shunt") then - currentNode = nil - end - nodes[#nodes + 1] = { - log = true, - remarks = "Socks[" .. id .. "]备用节点的列表[" .. k .. "]", - currentNode = currentNode, - set = function(o, server) - for kk, vv in pairs(CONFIG) do - if (vv.remarks == id .. "备用节点的列表") then - table.insert(vv.new_nodes, server) - end - end - end - } - end - end - end - CONFIG[#CONFIG + 1] = { - remarks = id .. "备用节点的列表", - nodes = nodes, - new_nodes = new_nodes, - set = function(o) - for kk, vv in pairs(CONFIG) do - if (vv.remarks == id .. "备用节点的列表") then - uci:set_list(appname, id, "autoswitch_backup_node", vv.new_nodes) - end - end - end - } - end - end) - uci:foreach(appname, "nodes", function(node) local node_id = node[".name"] if node.protocol and node.protocol == '_shunt' then @@ -271,39 +271,32 @@ do end end elseif node.protocol and node.protocol == '_balancing' then - local nodes = {} - local new_nodes = {} + local flag = "Xray负载均衡节点[" .. node_id .. "]列表" + local currentNodes = {} + local newNodes = {} if node.balancing_node then for k, node in pairs(node.balancing_node) do - nodes[#nodes + 1] = { + currentNodes[#currentNodes + 1] = { log = false, node = node, currentNode = node and uci:get_all(appname, node) or nil, remarks = node, set = function(o, server) - for kk, vv in pairs(CONFIG) do - if (vv.remarks == "Xray负载均衡节点[" .. node_id .. "]列表") then - table.insert(vv.new_nodes, server) - end + if o and server and server ~= "nil" then + table.insert(o.newNodes, server) end end } end end CONFIG[#CONFIG + 1] = { - remarks = "Xray负载均衡节点[" .. node_id .. "]列表", - nodes = nodes, - new_nodes = new_nodes, - set = function(o) - for kk, vv in pairs(CONFIG) do - if (vv.remarks == "Xray负载均衡节点[" .. node_id .. "]列表") then - uci:foreach(appname, "nodes", function(node2) - if node2[".name"] == node[".name"] then - local section = uci:section(appname, "nodes", node_id) - uci:set_list(appname, section, "balancing_node", vv.new_nodes) - end - end) - end + remarks = flag, + currentNodes = currentNodes, + newNodes = newNodes, + set = function(o, newNodes) + if o then + if not newNodes then newNodes = o.newNodes end + uci:set_list(appname, node_id, "balancing_node", newNodes or {}) end end } @@ -364,10 +357,10 @@ do end) for k, v in pairs(CONFIG) do - if v.nodes and type(v.nodes) == "table" then - for kk, vv in pairs(v.nodes) do + if v.currentNodes and type(v.currentNodes) == "table" then + for kk, vv in pairs(v.currentNodes) do if vv.currentNode == nil then - CONFIG[k].nodes[kk] = nil + CONFIG[k].currentNodes[kk] = nil end end else @@ -1278,44 +1271,54 @@ end local function truncate_nodes(add_from) for _, config in pairs(CONFIG) do - if config.nodes and type(config.nodes) == "table" then - for kk, vv in pairs(config.nodes) do - if vv.currentNode.add_mode == "2" then - else - vv.set(vv, vv.currentNode[".name"]) + if config.currentNodes and #config.currentNodes > 0 then + local newNodes = {} + local removeNodesSet = {} + for k, v in pairs(config.currentNodes) do + if v.currentNode and v.currentNode.add_mode == "2" then + if (not add_from) or (add_from and add_from == v.currentNode.add_from) then + removeNodesSet[v.currentNode[".name"]] = true + end end end - config.set(config) + for _, value in ipairs(config.currentNodes) do + if not removeNodesSet[value.currentNode[".name"]] then + newNodes[#newNodes + 1] = value.currentNode[".name"] + end + end + if config.set then + config.set(config, newNodes) + end else if config.currentNode and config.currentNode.add_mode == "2" then - if add_from then - if config.currentNode.add_from and config.currentNode.add_from == add_from then + if (not add_from) or (add_from and add_from == config.currentNode.add_from) then + if config.delete then + config.delete(config) + elseif config.set then config.set(config, "") end - else - config.set(config, "") - end - if config.id then - uci:delete(appname, config.id) end end end end uci:foreach(appname, "nodes", function(node) if node.add_mode == "2" then - if add_from then - if node.add_from and node.add_from == add_from then - uci:delete(appname, node['.name']) - end - else + if (not add_from) or (add_from and add_from == node.add_from) then uci:delete(appname, node['.name']) end end end) + if add_from then + uci:foreach(appname, "subscribe_list", function(o) + if o.remark == add_from then + uci:delete(appname, o['.name'], "md5") + end + end) + end api.uci_save(uci, appname, true) end -local function select_node(nodes, config) +local function select_node(nodes, config, parentConfig) if config.currentNode then local server -- 特别优先级 cfgid @@ -1408,32 +1411,34 @@ local function select_node(nodes, config) end end end - -- 还不行 随便找一个 - if not server then - local nodes_table = {} - for k, e in ipairs(api.get_valid_nodes()) do - if e.node_type == "normal" then - nodes_table[#nodes_table + 1] = e + if not parentConfig then + -- 还不行 随便找一个 + if not server then + if #nodes_table > 0 then + if config.log == nil or config.log == true then + log('【' .. config.remarks .. '】' .. '无法找到最匹配的节点,当前已更换为:' .. nodes_table[1].remarks) + end + server = nodes_table[1][".name"] end end - if #nodes_table > 0 then - if config.log == nil or config.log == true then - log('【' .. config.remarks .. '】' .. '无法找到最匹配的节点,当前已更换为:' .. nodes_table[1].remarks) - end - server = nodes_table[1][".name"] - end end if server then - config.set(config, server) + if parentConfig then + config.set(parentConfig, server) + else + config.set(config, server) + end end else - config.set(config, "") + if not parentConfig then + config.set(config, "") + end end end local function update_node(manual) if next(nodeResult) == nil then - log("更新失败,没有可用的节点信息") + log("没有可用的节点信息更新。") return end @@ -1473,9 +1478,9 @@ local function update_node(manual) end) for _, config in pairs(CONFIG) do - if config.nodes and type(config.nodes) == "table" then - for kk, vv in pairs(config.nodes) do - select_node(nodes, vv) + if config.currentNodes and #config.currentNodes > 0 then + for kk, vv in pairs(config.currentNodes) do + select_node(nodes, vv, config) end config.set(config) else @@ -1483,22 +1488,6 @@ local function update_node(manual) end end - --[[ - for k, v in pairs(CONFIG) do - if type(v.new_nodes) == "table" and #v.new_nodes > 0 then - local new_node_list = "" - for kk, vv in pairs(v.new_nodes) do - new_node_list = new_node_list .. vv .. " " - end - if new_node_list ~= "" then - print(v.remarks, new_node_list) - end - else - print(v.remarks, v.newNodeId) - end - end - ]]-- - api.uci_save(uci, appname, true) end @@ -1670,8 +1659,15 @@ local execute = function() local stdout = f:read("*all") f:close() raw = trim(stdout) - os.remove("/tmp/" .. cfgid) - parse_link(raw, "2", remark) + local old_md5 = value.md5 or "" + local new_md5 = luci.sys.exec(string.format("echo -n $(echo '%s' | md5sum | awk '{print $1}')", raw)) + if old_md5 == new_md5 then + log('订阅:【' .. remark .. '】没有变化,无需更新。') + else + os.remove("/tmp/" .. cfgid) + parse_link(raw, "2", remark) + uci:set(appname, cfgid, "md5", new_md5) + end else fail_list[#fail_list + 1] = value end diff --git a/openwrt-passwall2/luci-app-passwall2/root/usr/share/passwall2/subscribe.lua b/openwrt-passwall2/luci-app-passwall2/root/usr/share/passwall2/subscribe.lua index 1e93f415b4..10d6ddf11c 100755 --- a/openwrt-passwall2/luci-app-passwall2/root/usr/share/passwall2/subscribe.lua +++ b/openwrt-passwall2/luci-app-passwall2/root/usr/share/passwall2/subscribe.lua @@ -95,6 +95,13 @@ local log = function(...) end end +local nodes_table = {} +for k, e in ipairs(api.get_valid_nodes()) do + if e.node_type == "normal" then + nodes_table[#nodes_table + 1] = e + end +end + -- 获取各项动态配置的当前服务器,可以用 get 和 set, get必须要获取到节点表 local CONFIG = {} do @@ -119,20 +126,56 @@ do local option = "node" uci:foreach(appname, "socks", function(t) i = i + 1 + local id = t[".name"] local node_id = t[option] CONFIG[#CONFIG + 1] = { log = true, - id = t[".name"], + id = id, remarks = "Socks节点列表[" .. i .. "]", currentNode = node_id and uci:get_all(appname, node_id) or nil, set = function(o, server) + if not server or server == "" then + if #nodes_table > 0 then + server = nodes_table[1][".name"] + end + end uci:set(appname, t[".name"], option, server) o.newNodeId = server - end, - delete = function(o) - uci:delete(appname, t[".name"]) end } + if t.autoswitch_backup_node and #t.autoswitch_backup_node > 0 then + local flag = "Socks节点列表[" .. i .. "]备用节点的列表" + local currentNodes = {} + local newNodes = {} + for k, node_id in ipairs(t.autoswitch_backup_node) do + if node_id then + local currentNode = uci:get_all(appname, node_id) or nil + if currentNode then + currentNodes[#currentNodes + 1] = { + log = true, + remarks = flag .. "[" .. k .. "]", + currentNode = currentNode, + set = function(o, server) + if server and server ~= "nil" then + table.insert(o.newNodes, server) + end + end + } + end + end + end + CONFIG[#CONFIG + 1] = { + remarks = flag, + currentNodes = currentNodes, + newNodes = newNodes, + set = function(o, newNodes) + if o then + if not newNodes then newNodes = o.newNodes end + uci:set_list(appname, id, "autoswitch_backup_node", newNodes or {}) + end + end + } + end end) end @@ -177,49 +220,6 @@ do end) end - uci:foreach(appname, "socks", function(o) - local id = o[".name"] - local node_table = uci:get(appname, id, "autoswitch_backup_node") - if node_table then - local nodes = {} - local new_nodes = {} - for k,node_id in ipairs(node_table) do - if node_id then - local currentNode = uci:get_all(appname, node_id) or nil - if currentNode then - if currentNode.protocol and (currentNode.protocol == "_balancing" or currentNode.protocol == "_shunt") then - currentNode = nil - end - nodes[#nodes + 1] = { - log = true, - remarks = "Socks[" .. id .. "]备用节点的列表[" .. k .. "]", - currentNode = currentNode, - set = function(o, server) - for kk, vv in pairs(CONFIG) do - if (vv.remarks == id .. "备用节点的列表") then - table.insert(vv.new_nodes, server) - end - end - end - } - end - end - end - CONFIG[#CONFIG + 1] = { - remarks = id .. "备用节点的列表", - nodes = nodes, - new_nodes = new_nodes, - set = function(o) - for kk, vv in pairs(CONFIG) do - if (vv.remarks == id .. "备用节点的列表") then - uci:set_list(appname, id, "autoswitch_backup_node", vv.new_nodes) - end - end - end - } - end - end) - uci:foreach(appname, "nodes", function(node) local node_id = node[".name"] if node.protocol and node.protocol == '_shunt' then @@ -256,39 +256,32 @@ do end elseif node.protocol and node.protocol == '_balancing' then - local nodes = {} - local new_nodes = {} + local flag = "Xray负载均衡节点[" .. node_id .. "]列表" + local currentNodes = {} + local newNodes = {} if node.balancing_node then for k, node in pairs(node.balancing_node) do - nodes[#nodes + 1] = { + currentNodes[#currentNodes + 1] = { log = false, node = node, currentNode = node and uci:get_all(appname, node) or nil, remarks = node, set = function(o, server) - for kk, vv in pairs(CONFIG) do - if (vv.remarks == "Xray负载均衡节点[" .. node_id .. "]列表") then - table.insert(vv.new_nodes, server) - end + if o and server and server ~= "nil" then + table.insert(o.newNodes, server) end end } end end CONFIG[#CONFIG + 1] = { - remarks = "Xray负载均衡节点[" .. node_id .. "]列表", - nodes = nodes, - new_nodes = new_nodes, - set = function(o) - for kk, vv in pairs(CONFIG) do - if (vv.remarks == "Xray负载均衡节点[" .. node_id .. "]列表") then - uci:foreach(appname, "nodes", function(node2) - if node2[".name"] == node[".name"] then - local section = uci:section(appname, "nodes", node_id) - uci:set_list(appname, section, "balancing_node", vv.new_nodes) - end - end) - end + remarks = flag, + currentNodes = currentNodes, + newNodes = newNodes, + set = function(o, newNodes) + if o then + if not newNodes then newNodes = o.newNodes end + uci:set_list(appname, node_id, "balancing_node", newNodes or {}) end end } @@ -349,10 +342,10 @@ do end) for k, v in pairs(CONFIG) do - if v.nodes and type(v.nodes) == "table" then - for kk, vv in pairs(v.nodes) do + if v.currentNodes and type(v.currentNodes) == "table" then + for kk, vv in pairs(v.currentNodes) do if vv.currentNode == nil then - CONFIG[k].nodes[kk] = nil + CONFIG[k].currentNodes[kk] = nil end end else @@ -1247,44 +1240,54 @@ end local function truncate_nodes(add_from) for _, config in pairs(CONFIG) do - if config.nodes and type(config.nodes) == "table" then - for kk, vv in pairs(config.nodes) do - if vv.currentNode.add_mode == "2" then - else - vv.set(vv, vv.currentNode[".name"]) + if config.currentNodes and #config.currentNodes > 0 then + local newNodes = {} + local removeNodesSet = {} + for k, v in pairs(config.currentNodes) do + if v.currentNode and v.currentNode.add_mode == "2" then + if (not add_from) or (add_from and add_from == v.currentNode.add_from) then + removeNodesSet[v.currentNode[".name"]] = true + end end end - config.set(config) + for _, value in ipairs(config.currentNodes) do + if not removeNodesSet[value.currentNode[".name"]] then + newNodes[#newNodes + 1] = value.currentNode[".name"] + end + end + if config.set then + config.set(config, newNodes) + end else if config.currentNode and config.currentNode.add_mode == "2" then - if add_from then - if config.currentNode.add_from and config.currentNode.add_from == add_from then + if (not add_from) or (add_from and add_from == config.currentNode.add_from) then + if config.delete then + config.delete(config) + elseif config.set then config.set(config, "") end - else - config.set(config, "") - end - if config.id then - uci:delete(appname, config.id) end end end end uci:foreach(appname, "nodes", function(node) if node.add_mode == "2" then - if add_from then - if node.add_from and node.add_from == add_from then - uci:delete(appname, node['.name']) - end - else + if (not add_from) or (add_from and add_from == node.add_from) then uci:delete(appname, node['.name']) end end end) + if add_from then + uci:foreach(appname, "subscribe_list", function(o) + if o.remark == add_from then + uci:delete(appname, o['.name'], "md5") + end + end) + end api.uci_save(uci, appname, true) end -local function select_node(nodes, config) +local function select_node(nodes, config, parentConfig) if config.currentNode then local server -- 特别优先级 cfgid @@ -1377,32 +1380,34 @@ local function select_node(nodes, config) end end end - -- 还不行 随便找一个 - if not server then - local nodes_table = {} - for k, e in ipairs(api.get_valid_nodes()) do - if e.node_type == "normal" then - nodes_table[#nodes_table + 1] = e + if not parentConfig then + -- 还不行 随便找一个 + if not server then + if #nodes_table > 0 then + if config.log == nil or config.log == true then + log('【' .. config.remarks .. '】' .. '无法找到最匹配的节点,当前已更换为:' .. nodes_table[1].remarks) + end + server = nodes_table[1][".name"] end end - if #nodes_table > 0 then - if config.log == nil or config.log == true then - log('【' .. config.remarks .. '】' .. '无法找到最匹配的节点,当前已更换为:' .. nodes_table[1].remarks) - end - server = nodes_table[1][".name"] - end end if server then - config.set(config, server) + if parentConfig then + config.set(parentConfig, server) + else + config.set(config, server) + end end else - config.set(config, "") + if not parentConfig then + config.set(config, "") + end end end local function update_node(manual) if next(nodeResult) == nil then - log("更新失败,没有可用的节点信息") + log("没有可用的节点信息更新。") return end @@ -1442,9 +1447,9 @@ local function update_node(manual) end) for _, config in pairs(CONFIG) do - if config.nodes and type(config.nodes) == "table" then - for kk, vv in pairs(config.nodes) do - select_node(nodes, vv) + if config.currentNodes and #config.currentNodes > 0 then + for kk, vv in pairs(config.currentNodes) do + select_node(nodes, vv, config) end config.set(config) else @@ -1452,22 +1457,6 @@ local function update_node(manual) end end - --[[ - for k, v in pairs(CONFIG) do - if type(v.new_nodes) == "table" and #v.new_nodes > 0 then - local new_node_list = "" - for kk, vv in pairs(v.new_nodes) do - new_node_list = new_node_list .. vv .. " " - end - if new_node_list ~= "" then - print(v.remarks, new_node_list) - end - else - print(v.remarks, v.newNodeId) - end - end - ]]-- - api.uci_save(uci, appname, true) end @@ -1639,8 +1628,15 @@ local execute = function() local stdout = f:read("*all") f:close() raw = trim(stdout) - os.remove("/tmp/" .. cfgid) - parse_link(raw, "2", remark) + local old_md5 = value.md5 or "" + local new_md5 = luci.sys.exec(string.format("echo -n $(echo '%s' | md5sum | awk '{print $1}')", raw)) + if old_md5 == new_md5 then + log('订阅:【' .. remark .. '】没有变化,无需更新。') + else + os.remove("/tmp/" .. cfgid) + parse_link(raw, "2", remark) + uci:set(appname, cfgid, "md5", new_md5) + end else fail_list[#fail_list + 1] = value end diff --git a/shadowsocks-rust/Cargo.lock b/shadowsocks-rust/Cargo.lock index 42eae31278..00b6969607 100644 --- a/shadowsocks-rust/Cargo.lock +++ b/shadowsocks-rust/Cargo.lock @@ -545,18 +545,18 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.25" +version = "4.5.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b95dca1b68188a08ca6af9d96a6576150f598824bdb528c1190460c2940a0b48" +checksum = "a8eb5e908ef3a6efbe1ed62520fb7287959888c88485abe072543190ecc66783" dependencies = [ "clap_builder", ] [[package]] name = "clap_builder" -version = "4.5.25" +version = "4.5.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ab52925392148efd3f7562f2136a81ffb778076bcc85727c6e020d6dd57cf15" +checksum = "96b01801b5fc6a0a232407abc821660c9c6d25a1cafc0d4f85f29fb8d9afc121" dependencies = [ "anstream", "anstyle", @@ -950,7 +950,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d" dependencies = [ "libc", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -2620,7 +2620,7 @@ dependencies = [ "once_cell", "socket2", "tracing", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -2917,7 +2917,7 @@ dependencies = [ "errno", "libc", "linux-raw-sys", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -3607,7 +3607,7 @@ dependencies = [ "fastrand", "once_cell", "rustix", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] diff --git a/small/luci-app-passwall/root/usr/share/passwall/subscribe.lua b/small/luci-app-passwall/root/usr/share/passwall/subscribe.lua index 546a41e868..f8ad658ce3 100755 --- a/small/luci-app-passwall/root/usr/share/passwall/subscribe.lua +++ b/small/luci-app-passwall/root/usr/share/passwall/subscribe.lua @@ -96,6 +96,13 @@ local log = function(...) end end +local nodes_table = {} +for k, e in ipairs(api.get_valid_nodes()) do + if e.node_type == "normal" then + nodes_table[#nodes_table + 1] = e + end +end + -- 获取各项动态配置的当前服务器,可以用 get 和 set, get必须要获取到节点表 local CONFIG = {} do @@ -123,20 +130,56 @@ do local option = "node" uci:foreach(appname, "socks", function(t) i = i + 1 + local id = t[".name"] local node_id = t[option] CONFIG[#CONFIG + 1] = { log = true, - id = t[".name"], + id = id, remarks = "Socks节点列表[" .. i .. "]", currentNode = node_id and uci:get_all(appname, node_id) or nil, set = function(o, server) + if not server or server == "" then + if #nodes_table > 0 then + server = nodes_table[1][".name"] + end + end uci:set(appname, t[".name"], option, server) o.newNodeId = server - end, - delete = function(o) - uci:delete(appname, t[".name"]) end } + if t.autoswitch_backup_node and #t.autoswitch_backup_node > 0 then + local flag = "Socks节点列表[" .. i .. "]备用节点的列表" + local currentNodes = {} + local newNodes = {} + for k, node_id in ipairs(t.autoswitch_backup_node) do + if node_id then + local currentNode = uci:get_all(appname, node_id) or nil + if currentNode then + currentNodes[#currentNodes + 1] = { + log = true, + remarks = flag .. "[" .. k .. "]", + currentNode = currentNode, + set = function(o, server) + if server and server ~= "nil" then + table.insert(o.newNodes, server) + end + end + } + end + end + end + CONFIG[#CONFIG + 1] = { + remarks = flag, + currentNodes = currentNodes, + newNodes = newNodes, + set = function(o, newNodes) + if o then + if not newNodes then newNodes = o.newNodes end + uci:set_list(appname, id, "autoswitch_backup_node", newNodes or {}) + end + end + } + end end) end @@ -193,49 +236,6 @@ do end) end - uci:foreach(appname, "socks", function(o) - local id = o[".name"] - local node_table = uci:get(appname, id, "autoswitch_backup_node") - if node_table then - local nodes = {} - local new_nodes = {} - for k,node_id in ipairs(node_table) do - if node_id then - local currentNode = uci:get_all(appname, node_id) or nil - if currentNode then - if currentNode.protocol and (currentNode.protocol == "_balancing" or currentNode.protocol == "_shunt") then - currentNode = nil - end - nodes[#nodes + 1] = { - log = true, - remarks = "Socks[" .. id .. "]备用节点的列表[" .. k .. "]", - currentNode = currentNode, - set = function(o, server) - for kk, vv in pairs(CONFIG) do - if (vv.remarks == id .. "备用节点的列表") then - table.insert(vv.new_nodes, server) - end - end - end - } - end - end - end - CONFIG[#CONFIG + 1] = { - remarks = id .. "备用节点的列表", - nodes = nodes, - new_nodes = new_nodes, - set = function(o) - for kk, vv in pairs(CONFIG) do - if (vv.remarks == id .. "备用节点的列表") then - uci:set_list(appname, id, "autoswitch_backup_node", vv.new_nodes) - end - end - end - } - end - end) - uci:foreach(appname, "nodes", function(node) local node_id = node[".name"] if node.protocol and node.protocol == '_shunt' then @@ -271,39 +271,32 @@ do end end elseif node.protocol and node.protocol == '_balancing' then - local nodes = {} - local new_nodes = {} + local flag = "Xray负载均衡节点[" .. node_id .. "]列表" + local currentNodes = {} + local newNodes = {} if node.balancing_node then for k, node in pairs(node.balancing_node) do - nodes[#nodes + 1] = { + currentNodes[#currentNodes + 1] = { log = false, node = node, currentNode = node and uci:get_all(appname, node) or nil, remarks = node, set = function(o, server) - for kk, vv in pairs(CONFIG) do - if (vv.remarks == "Xray负载均衡节点[" .. node_id .. "]列表") then - table.insert(vv.new_nodes, server) - end + if o and server and server ~= "nil" then + table.insert(o.newNodes, server) end end } end end CONFIG[#CONFIG + 1] = { - remarks = "Xray负载均衡节点[" .. node_id .. "]列表", - nodes = nodes, - new_nodes = new_nodes, - set = function(o) - for kk, vv in pairs(CONFIG) do - if (vv.remarks == "Xray负载均衡节点[" .. node_id .. "]列表") then - uci:foreach(appname, "nodes", function(node2) - if node2[".name"] == node[".name"] then - local section = uci:section(appname, "nodes", node_id) - uci:set_list(appname, section, "balancing_node", vv.new_nodes) - end - end) - end + remarks = flag, + currentNodes = currentNodes, + newNodes = newNodes, + set = function(o, newNodes) + if o then + if not newNodes then newNodes = o.newNodes end + uci:set_list(appname, node_id, "balancing_node", newNodes or {}) end end } @@ -364,10 +357,10 @@ do end) for k, v in pairs(CONFIG) do - if v.nodes and type(v.nodes) == "table" then - for kk, vv in pairs(v.nodes) do + if v.currentNodes and type(v.currentNodes) == "table" then + for kk, vv in pairs(v.currentNodes) do if vv.currentNode == nil then - CONFIG[k].nodes[kk] = nil + CONFIG[k].currentNodes[kk] = nil end end else @@ -1278,44 +1271,54 @@ end local function truncate_nodes(add_from) for _, config in pairs(CONFIG) do - if config.nodes and type(config.nodes) == "table" then - for kk, vv in pairs(config.nodes) do - if vv.currentNode.add_mode == "2" then - else - vv.set(vv, vv.currentNode[".name"]) + if config.currentNodes and #config.currentNodes > 0 then + local newNodes = {} + local removeNodesSet = {} + for k, v in pairs(config.currentNodes) do + if v.currentNode and v.currentNode.add_mode == "2" then + if (not add_from) or (add_from and add_from == v.currentNode.add_from) then + removeNodesSet[v.currentNode[".name"]] = true + end end end - config.set(config) + for _, value in ipairs(config.currentNodes) do + if not removeNodesSet[value.currentNode[".name"]] then + newNodes[#newNodes + 1] = value.currentNode[".name"] + end + end + if config.set then + config.set(config, newNodes) + end else if config.currentNode and config.currentNode.add_mode == "2" then - if add_from then - if config.currentNode.add_from and config.currentNode.add_from == add_from then + if (not add_from) or (add_from and add_from == config.currentNode.add_from) then + if config.delete then + config.delete(config) + elseif config.set then config.set(config, "") end - else - config.set(config, "") - end - if config.id then - uci:delete(appname, config.id) end end end end uci:foreach(appname, "nodes", function(node) if node.add_mode == "2" then - if add_from then - if node.add_from and node.add_from == add_from then - uci:delete(appname, node['.name']) - end - else + if (not add_from) or (add_from and add_from == node.add_from) then uci:delete(appname, node['.name']) end end end) + if add_from then + uci:foreach(appname, "subscribe_list", function(o) + if o.remark == add_from then + uci:delete(appname, o['.name'], "md5") + end + end) + end api.uci_save(uci, appname, true) end -local function select_node(nodes, config) +local function select_node(nodes, config, parentConfig) if config.currentNode then local server -- 特别优先级 cfgid @@ -1408,32 +1411,34 @@ local function select_node(nodes, config) end end end - -- 还不行 随便找一个 - if not server then - local nodes_table = {} - for k, e in ipairs(api.get_valid_nodes()) do - if e.node_type == "normal" then - nodes_table[#nodes_table + 1] = e + if not parentConfig then + -- 还不行 随便找一个 + if not server then + if #nodes_table > 0 then + if config.log == nil or config.log == true then + log('【' .. config.remarks .. '】' .. '无法找到最匹配的节点,当前已更换为:' .. nodes_table[1].remarks) + end + server = nodes_table[1][".name"] end end - if #nodes_table > 0 then - if config.log == nil or config.log == true then - log('【' .. config.remarks .. '】' .. '无法找到最匹配的节点,当前已更换为:' .. nodes_table[1].remarks) - end - server = nodes_table[1][".name"] - end end if server then - config.set(config, server) + if parentConfig then + config.set(parentConfig, server) + else + config.set(config, server) + end end else - config.set(config, "") + if not parentConfig then + config.set(config, "") + end end end local function update_node(manual) if next(nodeResult) == nil then - log("更新失败,没有可用的节点信息") + log("没有可用的节点信息更新。") return end @@ -1473,9 +1478,9 @@ local function update_node(manual) end) for _, config in pairs(CONFIG) do - if config.nodes and type(config.nodes) == "table" then - for kk, vv in pairs(config.nodes) do - select_node(nodes, vv) + if config.currentNodes and #config.currentNodes > 0 then + for kk, vv in pairs(config.currentNodes) do + select_node(nodes, vv, config) end config.set(config) else @@ -1483,22 +1488,6 @@ local function update_node(manual) end end - --[[ - for k, v in pairs(CONFIG) do - if type(v.new_nodes) == "table" and #v.new_nodes > 0 then - local new_node_list = "" - for kk, vv in pairs(v.new_nodes) do - new_node_list = new_node_list .. vv .. " " - end - if new_node_list ~= "" then - print(v.remarks, new_node_list) - end - else - print(v.remarks, v.newNodeId) - end - end - ]]-- - api.uci_save(uci, appname, true) end @@ -1670,8 +1659,15 @@ local execute = function() local stdout = f:read("*all") f:close() raw = trim(stdout) - os.remove("/tmp/" .. cfgid) - parse_link(raw, "2", remark) + local old_md5 = value.md5 or "" + local new_md5 = luci.sys.exec(string.format("echo -n $(echo '%s' | md5sum | awk '{print $1}')", raw)) + if old_md5 == new_md5 then + log('订阅:【' .. remark .. '】没有变化,无需更新。') + else + os.remove("/tmp/" .. cfgid) + parse_link(raw, "2", remark) + uci:set(appname, cfgid, "md5", new_md5) + end else fail_list[#fail_list + 1] = value end diff --git a/v2rayn/v2rayN/ServiceLib/Common/Utils.cs b/v2rayn/v2rayN/ServiceLib/Common/Utils.cs index 15023f2b04..bae8230d10 100644 --- a/v2rayn/v2rayN/ServiceLib/Common/Utils.cs +++ b/v2rayn/v2rayN/ServiceLib/Common/Utils.cs @@ -558,7 +558,7 @@ namespace ServiceLib.Common public static string GetRuntimeInfo() { - return $"{Utils.GetVersion()} | {Utils.StartupPath()} | {Utils.GetExePath()} | {Environment.OSVersion} | {(Environment.Is64BitOperatingSystem ? 64 : 32)}"; + return $"{Utils.GetVersion()} | {Utils.StartupPath()} | {Utils.GetExePath()} | {Environment.OSVersion}"; } /// diff --git a/v2rayn/v2rayN/ServiceLib/Enums/ETheme.cs b/v2rayn/v2rayN/ServiceLib/Enums/ETheme.cs new file mode 100644 index 0000000000..7701ae8fe7 --- /dev/null +++ b/v2rayn/v2rayN/ServiceLib/Enums/ETheme.cs @@ -0,0 +1,13 @@ +namespace ServiceLib.Enums +{ + public enum ETheme + { + FollowSystem, + Dark, + Light, + Aquatic, + Desert, + Dusk, + NightSky + } +} \ No newline at end of file diff --git a/v2rayn/v2rayN/ServiceLib/Models/ConfigItems.cs b/v2rayn/v2rayN/ServiceLib/Models/ConfigItems.cs index f7642df300..41d34606ec 100644 --- a/v2rayn/v2rayN/ServiceLib/Models/ConfigItems.cs +++ b/v2rayn/v2rayN/ServiceLib/Models/ConfigItems.cs @@ -105,6 +105,7 @@ public bool ColorModeDark { get; set; } public bool FollowSystemTheme { get; set; } public string? ColorPrimaryName { get; set; } + public string? CurrentTheme { get; set; } public string CurrentLanguage { get; set; } public string CurrentFontFamily { get; set; } public int CurrentFontSize { get; set; } diff --git a/v2rayn/v2rayN/ServiceLib/Resx/ResUI.Designer.cs b/v2rayn/v2rayN/ServiceLib/Resx/ResUI.Designer.cs index abe5360356..4cc375a862 100644 --- a/v2rayn/v2rayN/ServiceLib/Resx/ResUI.Designer.cs +++ b/v2rayn/v2rayN/ServiceLib/Resx/ResUI.Designer.cs @@ -3463,6 +3463,15 @@ namespace ServiceLib.Resx { } } + /// + /// 查找类似 Theme 的本地化字符串。 + /// + public static string TbSettingsTheme { + get { + return ResourceManager.GetString("TbSettingsTheme", resourceCulture); + } + } + /// /// 查找类似 Enable Security Protocol TLS v1.3 (subscription/update) 的本地化字符串。 /// diff --git a/v2rayn/v2rayN/ServiceLib/Resx/ResUI.fa-Ir.resx b/v2rayn/v2rayN/ServiceLib/Resx/ResUI.fa-Ir.resx index e9c4a62b4d..20f52b3ecb 100644 --- a/v2rayn/v2rayN/ServiceLib/Resx/ResUI.fa-Ir.resx +++ b/v2rayn/v2rayN/ServiceLib/Resx/ResUI.fa-Ir.resx @@ -1402,4 +1402,7 @@ socks:پورت محلی، socks2: پورت دوم محلی، socks3: پورت LAN - + + Theme + + \ No newline at end of file diff --git a/v2rayn/v2rayN/ServiceLib/Resx/ResUI.hu.resx b/v2rayn/v2rayN/ServiceLib/Resx/ResUI.hu.resx index 053efb6ac4..a66ddedbbb 100644 --- a/v2rayn/v2rayN/ServiceLib/Resx/ResUI.hu.resx +++ b/v2rayn/v2rayN/ServiceLib/Resx/ResUI.hu.resx @@ -1402,4 +1402,7 @@ socks: local port, socks2: second local port, socks3: LAN port + + Theme + \ No newline at end of file diff --git a/v2rayn/v2rayN/ServiceLib/Resx/ResUI.resx b/v2rayn/v2rayN/ServiceLib/Resx/ResUI.resx index 82b271473b..1152a6573c 100644 --- a/v2rayn/v2rayN/ServiceLib/Resx/ResUI.resx +++ b/v2rayn/v2rayN/ServiceLib/Resx/ResUI.resx @@ -1402,4 +1402,7 @@ socks: local port, socks2: second local port, socks3: LAN port + + Theme + \ No newline at end of file diff --git a/v2rayn/v2rayN/ServiceLib/Resx/ResUI.ru.resx b/v2rayn/v2rayN/ServiceLib/Resx/ResUI.ru.resx index 326bf5d3ee..325e431cbc 100644 --- a/v2rayn/v2rayN/ServiceLib/Resx/ResUI.ru.resx +++ b/v2rayn/v2rayN/ServiceLib/Resx/ResUI.ru.resx @@ -1402,4 +1402,7 @@ socks: local port, socks2: second local port, socks3: LAN port + + Theme + \ No newline at end of file diff --git a/v2rayn/v2rayN/ServiceLib/Resx/ResUI.zh-Hans.resx b/v2rayn/v2rayN/ServiceLib/Resx/ResUI.zh-Hans.resx index 6807b6de25..45dfaca1a8 100644 --- a/v2rayn/v2rayN/ServiceLib/Resx/ResUI.zh-Hans.resx +++ b/v2rayn/v2rayN/ServiceLib/Resx/ResUI.zh-Hans.resx @@ -1399,4 +1399,7 @@ socks:本地端口,socks2:第二个本地端口,socks3:局域网端口 + + 主题 + \ No newline at end of file diff --git a/v2rayn/v2rayN/ServiceLib/Resx/ResUI.zh-Hant.resx b/v2rayn/v2rayN/ServiceLib/Resx/ResUI.zh-Hant.resx index 27d7207b7f..ff22b92db1 100644 --- a/v2rayn/v2rayN/ServiceLib/Resx/ResUI.zh-Hant.resx +++ b/v2rayn/v2rayN/ServiceLib/Resx/ResUI.zh-Hant.resx @@ -1400,4 +1400,7 @@ socks:本地端口,socks2:第二個本地端口,socks3:區域網路端口 + + 主題 + \ No newline at end of file diff --git a/v2rayn/v2rayN/ServiceLib/Services/CoreConfig/CoreConfigSingboxService.cs b/v2rayn/v2rayN/ServiceLib/Services/CoreConfig/CoreConfigSingboxService.cs index e426891623..26708d799b 100644 --- a/v2rayn/v2rayN/ServiceLib/Services/CoreConfig/CoreConfigSingboxService.cs +++ b/v2rayn/v2rayN/ServiceLib/Services/CoreConfig/CoreConfigSingboxService.cs @@ -1259,7 +1259,8 @@ namespace ServiceLib.Services.CoreConfig singboxConfig.experimental ??= new Experimental4Sbox(); singboxConfig.experimental.cache_file = new CacheFile4Sbox() { - enabled = true + enabled = true, + path = Utils.GetConfigPath("cache.db") }; } diff --git a/v2rayn/v2rayN/ServiceLib/ViewModels/MsgViewModel.cs b/v2rayn/v2rayN/ServiceLib/ViewModels/MsgViewModel.cs index d5384d4dd8..f2ec4bb848 100644 --- a/v2rayn/v2rayN/ServiceLib/ViewModels/MsgViewModel.cs +++ b/v2rayn/v2rayN/ServiceLib/ViewModels/MsgViewModel.cs @@ -59,14 +59,14 @@ namespace ServiceLib.ViewModels { return; } - - _blLockShow = true; if (!_config.UiItem.ShowInTaskbar) { - await Task.Delay(1000); + return; } - await Task.Delay(100); + _blLockShow = true; + + await Task.Delay(500); var txt = string.Join("", _queueMsg.ToArray()); await _updateView?.Invoke(EViewAction.DispatcherShowMsg, txt); diff --git a/v2rayn/v2rayN/v2rayN.Desktop/ViewModels/ThemeSettingViewModel.cs b/v2rayn/v2rayN/v2rayN.Desktop/ViewModels/ThemeSettingViewModel.cs index d0854a2f6a..afdf78c2c5 100644 --- a/v2rayn/v2rayN/v2rayN.Desktop/ViewModels/ThemeSettingViewModel.cs +++ b/v2rayn/v2rayN/v2rayN.Desktop/ViewModels/ThemeSettingViewModel.cs @@ -6,14 +6,14 @@ using Avalonia.Media; using Avalonia.Styling; using ReactiveUI; using ReactiveUI.Fody.Helpers; +using Semi.Avalonia; using System.Reactive.Linq; namespace v2rayN.Desktop.ViewModels { public class ThemeSettingViewModel : MyReactiveObject { - [Reactive] public bool ColorModeDark { get; set; } - [Reactive] public bool FollowSystemTheme { get; set; } + [Reactive] public string CurrentTheme { get; set; } [Reactive] public int CurrentFontSize { get; set; } @@ -36,28 +36,16 @@ namespace v2rayN.Desktop.ViewModels private void BindingUI() { - ColorModeDark = _config.UiItem.ColorModeDark; - FollowSystemTheme = _config.UiItem.FollowSystemTheme; + CurrentTheme = _config.UiItem.CurrentTheme; CurrentFontSize = _config.UiItem.CurrentFontSize; CurrentLanguage = _config.UiItem.CurrentLanguage; - this.WhenAnyValue(x => x.ColorModeDark) + this.WhenAnyValue(x => x.CurrentTheme) .Subscribe(c => { - if (_config.UiItem.ColorModeDark != ColorModeDark) + if (_config.UiItem.CurrentTheme != CurrentTheme) { - _config.UiItem.ColorModeDark = ColorModeDark; - ModifyTheme(); - ConfigHandler.SaveConfig(_config); - } - }); - this.WhenAnyValue(x => x.FollowSystemTheme, - y => y == true) - .Subscribe(c => - { - if (_config.UiItem.FollowSystemTheme != FollowSystemTheme) - { - _config.UiItem.FollowSystemTheme = FollowSystemTheme; + _config.UiItem.CurrentTheme = CurrentTheme; ModifyTheme(); ConfigHandler.SaveConfig(_config); } @@ -96,7 +84,16 @@ namespace v2rayN.Desktop.ViewModels var app = Application.Current; if (app is not null) { - app.RequestedThemeVariant = FollowSystemTheme ? ThemeVariant.Default : (ColorModeDark ? ThemeVariant.Dark : ThemeVariant.Light); + app.RequestedThemeVariant = CurrentTheme switch + { + nameof(ETheme.Dark) => ThemeVariant.Dark, + nameof(ETheme.Light) => ThemeVariant.Light, + nameof(ETheme.Aquatic) => SemiTheme.Aquatic, + nameof(ETheme.Desert) => SemiTheme.Desert, + nameof(ETheme.Dusk) => SemiTheme.Dusk, + nameof(ETheme.NightSky) => SemiTheme.NightSky, + _ => ThemeVariant.Default, + }; } } diff --git a/v2rayn/v2rayN/v2rayN.Desktop/Views/BackupAndRestoreView.axaml b/v2rayn/v2rayN/v2rayN.Desktop/Views/BackupAndRestoreView.axaml index ecd1227669..badb206119 100644 --- a/v2rayn/v2rayN/v2rayN.Desktop/Views/BackupAndRestoreView.axaml +++ b/v2rayn/v2rayN/v2rayN.Desktop/Views/BackupAndRestoreView.axaml @@ -5,25 +5,28 @@ xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:resx="clr-namespace:ServiceLib.Resx;assembly=ServiceLib" - xmlns:vms="clr-namespace:ServiceLib.ViewModels;assembly=ServiceLib" d:DesignHeight="450" d:DesignWidth="800" - x:DataType="vms:BackupAndRestoreViewModel" mc:Ignorable="d"> + + + - + - + + Theme="{DynamicResource CardBorder}"> - + + Theme="{DynamicResource CardBorder}"> - - + +