aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--COPYING2
-rw-r--r--Makefile38
-rw-r--r--README.md4
-rw-r--r--build.bat20
-rw-r--r--conf/admin_windows.go2
-rw-r--r--conf/config.go76
-rw-r--r--conf/dnsresolver_windows.go63
-rw-r--r--conf/dpapi/dpapi_windows.go28
-rw-r--r--conf/dpapi/dpapi_windows_test.go8
-rwxr-xr-xconf/dpapi/test.exebin3622400 -> 0 bytes
-rw-r--r--conf/filewriter_windows.go5
-rw-r--r--conf/migration_windows.go29
-rw-r--r--conf/mksyscall.go8
-rw-r--r--conf/name.go33
-rw-r--r--conf/parser.go266
-rw-r--r--conf/parser_test.go17
-rw-r--r--conf/path_windows.go18
-rw-r--r--conf/store.go18
-rw-r--r--conf/store_test.go10
-rw-r--r--conf/storewatcher.go2
-rw-r--r--conf/storewatcher_windows.go2
-rw-r--r--conf/writer.go82
-rw-r--r--conf/zsyscall_windows.go50
-rw-r--r--docs/adminregistry.md18
-rw-r--r--docs/attacksurface.md15
-rw-r--r--docs/buildrun.md6
-rw-r--r--docs/enterprise.md45
-rw-r--r--docs/netquirk.md4
-rw-r--r--driver/configuration_windows.go183
-rw-r--r--driver/dll_fromfile_windows.go56
-rw-r--r--driver/dll_fromrsrc_windows.go62
-rw-r--r--driver/dll_windows.go91
-rw-r--r--driver/driver_windows.go170
-rw-r--r--driver/memmod/memmod_windows.go698
-rw-r--r--driver/memmod/memmod_windows_32.go16
-rw-r--r--driver/memmod/memmod_windows_386.go8
-rw-r--r--driver/memmod/memmod_windows_64.go36
-rw-r--r--driver/memmod/memmod_windows_amd64.go8
-rw-r--r--driver/memmod/memmod_windows_arm.go8
-rw-r--r--driver/memmod/memmod_windows_arm64.go8
-rw-r--r--driver/memmod/syscall_windows.go392
-rw-r--r--driver/memmod/syscall_windows_32.go96
-rw-r--r--driver/memmod/syscall_windows_64.go95
-rw-r--r--driver/wintunremoval_windows.go50
-rw-r--r--elevate/doas.go8
-rw-r--r--elevate/loader.go2
-rw-r--r--elevate/membership.go2
-rw-r--r--elevate/privileges.go4
-rw-r--r--elevate/shellexecute.go10
-rw-r--r--embeddable-dll-service/.gitignore4
-rw-r--r--embeddable-dll-service/README.md15
-rw-r--r--embeddable-dll-service/build.bat13
-rw-r--r--embeddable-dll-service/csharp/.gitignore3
-rw-r--r--embeddable-dll-service/csharp/DemoUI/MainWindow.Designer.cs2
-rw-r--r--embeddable-dll-service/csharp/DemoUI/MainWindow.cs60
-rw-r--r--embeddable-dll-service/csharp/DemoUI/Program.cs2
-rw-r--r--embeddable-dll-service/csharp/README.md10
-rw-r--r--embeddable-dll-service/csharp/TunnelDll/Driver.cs234
-rw-r--r--embeddable-dll-service/csharp/TunnelDll/Keypair.cs2
-rw-r--r--embeddable-dll-service/csharp/TunnelDll/Ringlogger.cs2
-rw-r--r--embeddable-dll-service/csharp/TunnelDll/Service.cs12
-rw-r--r--embeddable-dll-service/csharp/TunnelDll/Win32.cs54
-rw-r--r--embeddable-dll-service/main.go13
-rw-r--r--go.mod17
-rw-r--r--go.mod.master3
-rw-r--r--go.sum41
-rw-r--r--gotext.go5
-rw-r--r--installer/build.bat10
-rw-r--r--installer/customactions.c94
-rw-r--r--installer/fetcher/Makefile2
-rw-r--r--installer/fetcher/constants.h2
-rw-r--r--installer/fetcher/crypto.c6
-rw-r--r--installer/fetcher/crypto.h4
-rw-r--r--installer/fetcher/fetcher.c33
-rw-r--r--installer/fetcher/filelist.c2
-rw-r--r--installer/fetcher/filelist.h2
-rw-r--r--installer/fetcher/resources.rc4
-rw-r--r--installer/fetcher/systeminfo.c11
-rw-r--r--installer/fetcher/systeminfo.h3
-rw-r--r--installer/fetcher/version.h2
-rw-r--r--installer/wireguard.wxs10
-rw-r--r--l18n/l18n.go10
-rw-r--r--locales/ca/messages.gotext.json751
-rw-r--r--locales/cs/messages.gotext.json1907
-rw-r--r--locales/de/messages.gotext.json30
-rw-r--r--locales/es-ES/messages.gotext.json1036
-rw-r--r--locales/fi/messages.gotext.json142
-rw-r--r--locales/it/messages.gotext.json142
-rw-r--r--locales/ja/messages.gotext.json132
-rw-r--r--locales/ko/messages.gotext.json11
-rw-r--r--locales/pa-IN/messages.gotext.json244
-rw-r--r--locales/pl/messages.gotext.json8
-rw-r--r--locales/si-LK/messages.gotext.json715
-rw-r--r--locales/sk/messages.gotext.json874
-rw-r--r--locales/tr/messages.gotext.json1847
-rw-r--r--locales/uk/messages.gotext.json560
-rw-r--r--locales/zh-CN/messages.gotext.json6
-rw-r--r--locales/zh-TW/messages.gotext.json120
-rw-r--r--main.go104
-rw-r--r--manager/install.go51
-rw-r--r--manager/interfacecleanup.go56
-rw-r--r--manager/ipc_client.go17
-rw-r--r--manager/ipc_driver.go61
-rw-r--r--manager/ipc_server.go128
-rw-r--r--manager/ipc_uapi.go71
-rw-r--r--manager/legacystore.go129
-rw-r--r--manager/service.go65
-rw-r--r--manager/tunneltracker.go130
-rw-r--r--manager/uiprocess.go103
-rw-r--r--manager/updatestate.go34
-rw-r--r--quickinstall.bat2
-rw-r--r--resources.rc6
-rw-r--r--ringlogger/cli_test.go2
-rw-r--r--ringlogger/dump.go40
-rw-r--r--ringlogger/global.go20
-rw-r--r--ringlogger/ringlogger.go24
-rw-r--r--services/boot.go47
-rw-r--r--services/errors.go25
-rw-r--r--services/names.go26
-rw-r--r--tunnel/addressconfig.go187
-rw-r--r--tunnel/deterministicguid.go16
-rw-r--r--tunnel/firewall/blocker.go6
-rw-r--r--tunnel/firewall/helpers.go2
-rw-r--r--tunnel/firewall/mksyscall.go2
-rw-r--r--tunnel/firewall/rules.go17
-rw-r--r--tunnel/firewall/syscall_windows.go2
-rw-r--r--tunnel/firewall/types_windows.go8
-rw-r--r--tunnel/firewall/types_windows_32.go4
-rw-r--r--tunnel/firewall/types_windows_64.go4
-rw-r--r--tunnel/firewall/types_windows_test.go29
-rw-r--r--tunnel/interfacewatcher.go116
-rw-r--r--tunnel/ipcpermissions.go63
-rw-r--r--tunnel/mtumonitor.go (renamed from tunnel/defaultroutemonitor.go)59
-rw-r--r--tunnel/pitfalls.go177
-rw-r--r--tunnel/scriptrunner.go2
-rw-r--r--tunnel/service.go149
-rw-r--r--tunnel/winipcfg/interface_change_handler.go2
-rw-r--r--tunnel/winipcfg/luid.go93
-rw-r--r--tunnel/winipcfg/mksyscall.go2
-rw-r--r--tunnel/winipcfg/netsh.go14
-rw-r--r--tunnel/winipcfg/route_change_handler.go2
-rw-r--r--tunnel/winipcfg/types.go186
-rw-r--r--tunnel/winipcfg/types_32.go4
-rw-r--r--tunnel/winipcfg/types_64.go4
-rw-r--r--tunnel/winipcfg/types_test.go3
-rw-r--r--tunnel/winipcfg/types_test_32.go4
-rw-r--r--tunnel/winipcfg/types_test_64.go4
-rw-r--r--tunnel/winipcfg/unicast_address_change_handler.go2
-rw-r--r--tunnel/winipcfg/winipcfg.go12
-rw-r--r--tunnel/winipcfg/winipcfg_test.go90
-rw-r--r--tunnel/winipcfg/zwinipcfg_windows.go10
-rw-r--r--tunnel/wintun_test.go202
-rw-r--r--ui/aboutdialog.go13
-rw-r--r--ui/confview.go14
-rw-r--r--ui/editdialog.go61
-rw-r--r--ui/filesave.go4
-rw-r--r--ui/iconprovider.go10
-rw-r--r--ui/listview.go6
-rw-r--r--ui/logpage.go4
-rw-r--r--ui/managewindow.go8
-rw-r--r--ui/raise.go4
-rw-r--r--ui/syntax/highlighter.go22
-rw-r--r--ui/syntax/syntaxedit.go50
-rw-r--r--ui/tray.go8
-rw-r--r--ui/tunnelspage.go11
-rw-r--r--ui/ui.go14
-rw-r--r--ui/updatepage.go10
-rw-r--r--updater/authenticode.go7
-rw-r--r--updater/constants.go2
-rw-r--r--updater/downloader.go2
-rw-r--r--updater/msirunner.go4
-rw-r--r--updater/signify.go10
-rw-r--r--updater/updater_test.go2
-rw-r--r--updater/versions.go2
-rw-r--r--updater/winhttp/mksyscall.go2
-rw-r--r--updater/winhttp/syscall_windows.go12
-rw-r--r--updater/winhttp/winhttp.go19
-rw-r--r--updater/winhttp/winhttp_test.go2
-rw-r--r--version/certificate_test.go2
-rw-r--r--version/official.go11
-rw-r--r--version/os.go2
-rw-r--r--version/protocol.go28
-rw-r--r--version/useragent.go2
-rw-r--r--version/version.go4
-rw-r--r--zgotext.go5405
185 files changed, 16179 insertions, 4280 deletions
diff --git a/COPYING b/COPYING
index eaf986ca..916eef78 100644
--- a/COPYING
+++ b/COPYING
@@ -1,4 +1,4 @@
-Copyright (C) 2018-2021 WireGuard LLC. All Rights Reserved.
+Copyright (C) 2018-2022 WireGuard LLC. All Rights Reserved.
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
diff --git a/Makefile b/Makefile
index a947d313..02127e1f 100644
--- a/Makefile
+++ b/Makefile
@@ -1,4 +1,4 @@
-GOFLAGS := -tags load_wintun_from_rsrc -ldflags="-H windowsgui -s -w" -v -trimpath
+GOFLAGS := -tags load_wgnt_from_rsrc -ldflags="-H windowsgui -s -w" -trimpath -buildvcs=false -v
export GOOS := windows
export PATH := $(CURDIR)/.deps/go/bin:$(PATH)
@@ -10,12 +10,12 @@ RCFLAGS := -DWIREGUARD_VERSION_ARRAY=$(subst $(space),$(comma),$(wordlist 1,4,$(
rwildcard=$(foreach d,$(filter-out .deps,$(wildcard $1*)),$(call rwildcard,$d/,$2) $(filter $(subst *,%,$2),$d))
SOURCE_FILES := $(call rwildcard,,*.go) .deps/go/prepared go.mod go.sum
-RESOURCE_FILES := resources.rc version/version.go manifest.xml $(patsubst %.svg,%.ico,$(wildcard ui/icon/*.svg)) .deps/wintun/prepared
+RESOURCE_FILES := resources.rc version/version.go manifest.xml $(patsubst %.svg,%.ico,$(wildcard ui/icon/*.svg)) .deps/wireguard-nt/prepared
DEPLOYMENT_HOST ?= winvm
DEPLOYMENT_PATH ?= Desktop
-all: amd64/wireguard.exe x86/wireguard.exe arm64/wireguard.exe arm/wireguard.exe
+all: amd64/wireguard.exe x86/wireguard.exe arm64/wireguard.exe
define download =
.distfiles/$(1):
@@ -25,35 +25,33 @@ define download =
if ! mv $$@.unverified $$@; then rm -f $$@.unverified; exit 1; fi
endef
-$(eval $(call download,go.tar.zst,https://download.wireguard.com/windows-toolchain/distfiles/go1.16.2-linux_amd64_2021-03-22.tar.zst,a12882673a0e29842a3ba5bfefd1a41dcb4fd0889e1957c98e33b9a3872190a9))
-$(eval $(call download,wintun.zip,https://www.wintun.net/builds/wintun-0.10.2.zip,fcd9f62f1bd5a550fcb9c21fbb5d6a556214753ccbbd1a3ebad4d318ec9dcbef))
+$(eval $(call download,go.tar.gz,https://go.dev/dl/go1.18.linux-amd64.tar.gz,e85278e98f57cdb150fe8409e6e5df5343ecb13cebf03a5d5ff12bd55a80264f))
+$(eval $(call download,wireguard-nt.zip,https://download.wireguard.com/wireguard-nt/wireguard-nt-0.10.1.zip,772c0b1463d8d2212716f43f06f4594d880dea4f735165bd68e388fc41b81605))
-.deps/go/prepared: .distfiles/go.tar.zst
+.deps/go/prepared: .distfiles/go.tar.gz
mkdir -p .deps
rm -rf .deps/go
- bsdtar -C .deps -xf .distfiles/go.tar.zst
+ bsdtar -C .deps -xf .distfiles/go.tar.gz
+ chmod -R +w .deps/go
touch $@
-.deps/wintun/prepared: .distfiles/wintun.zip
+.deps/wireguard-nt/prepared: .distfiles/wireguard-nt.zip
mkdir -p .deps
- rm -rf .deps/wintun
- bsdtar -C .deps -xf .distfiles/wintun.zip
+ rm -rf .deps/wireguard-nt
+ bsdtar -C .deps -xf .distfiles/wireguard-nt.zip
touch $@
%.ico: %.svg
convert -background none $< -define icon:auto-resize="256,192,128,96,64,48,40,32,24,20,16" -compress zip $@
resources_amd64.syso: $(RESOURCE_FILES)
- x86_64-w64-mingw32-windres $(RCFLAGS) -I .deps/wintun/bin/amd64 -i $< -o $@
+ x86_64-w64-mingw32-windres $(RCFLAGS) -I .deps/wireguard-nt/bin/amd64 -i $< -o $@
resources_386.syso: $(RESOURCE_FILES)
- i686-w64-mingw32-windres $(RCFLAGS) -I .deps/wintun/bin/x86 -i $< -o $@
-
-resources_arm.syso: $(RESOURCE_FILES)
- armv7-w64-mingw32-windres $(RCFLAGS) -I .deps/wintun/bin/arm -i $< -o $@
+ i686-w64-mingw32-windres $(RCFLAGS) -I .deps/wireguard-nt/bin/x86 -i $< -o $@
resources_arm64.syso: $(RESOURCE_FILES)
- aarch64-w64-mingw32-windres $(RCFLAGS) -I .deps/wintun/bin/arm64 -i $< -o $@
+ aarch64-w64-mingw32-windres $(RCFLAGS) -I .deps/wireguard-nt/bin/arm64 -i $< -o $@
amd64/wireguard.exe: export GOARCH := amd64
amd64/wireguard.exe: resources_amd64.syso $(SOURCE_FILES)
@@ -63,11 +61,6 @@ x86/wireguard.exe: export GOARCH := 386
x86/wireguard.exe: resources_386.syso $(SOURCE_FILES)
go build $(GOFLAGS) -o $@
-arm/wireguard.exe: export GOARCH := arm
-arm/wireguard.exe: export GOARM := 7
-arm/wireguard.exe: resources_arm.syso $(SOURCE_FILES)
- go build $(GOFLAGS) -o $@
-
arm64/wireguard.exe: export GOARCH := arm64
arm64/wireguard.exe: resources_arm64.syso $(SOURCE_FILES)
go build $(GOFLAGS) -o $@
@@ -78,6 +71,7 @@ remaster: .deps/go/prepared
rm -f go.sum go.mod
cp go.mod.master go.mod
go get -d
+ sed -i $(shell curl -L 'https://go.dev/dl/?mode=json&include=all' | jq -r '(".windows-amd64.zip",".linux-amd64.tar.gz") as $$suffix | .[0].files[] | select(.filename|endswith($$suffix)) | ("-e", "s/go[0-9][^ ]*\\\($$suffix)\\([ ,]\\)[a-f0-9]\\+/\(.filename)\\1\(.sha256)/") | @sh') Makefile build.bat
fmt: export GOARCH := amd64
fmt: .deps/go/prepared
@@ -98,7 +92,7 @@ deploy: amd64/wireguard.exe
scp $< $(DEPLOYMENT_HOST):$(DEPLOYMENT_PATH)
clean:
- rm -rf *.syso ui/icon/*.ico x86/ amd64/ arm/ arm64/ .deps
+ rm -rf *.syso ui/icon/*.ico x86/ amd64/ arm64/ .deps
distclean: clean
rm -rf .distfiles
diff --git a/README.md b/README.md
index 76abf9dd..4ae2f267 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,6 @@
# [WireGuard](https://www.wireguard.com/) for Windows
-This is a fully-featured WireGuard client for Windows that uses [Wintun](https://www.wintun.net/). It is the only official and recommended way of using WireGuard on Windows.
+This is a fully-featured WireGuard client for Windows that uses [WireGuardNT](https://git.zx2c4.com/wireguard-nt/about/). It is the only official and recommended way of using WireGuard on Windows.
## Download &amp; Install
@@ -24,7 +24,7 @@ In addition to this [`README.md`](README.md), the following documents are also a
This repository is MIT-licensed.
```text
-Copyright (C) 2018-2021 WireGuard LLC. All Rights Reserved.
+Copyright (C) 2018-2022 WireGuard LLC. All Rights Reserved.
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
diff --git a/build.bat b/build.bat
index aa810019..afb171ef 100644
--- a/build.bat
+++ b/build.bat
@@ -1,6 +1,6 @@
@echo off
rem SPDX-License-Identifier: MIT
-rem Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+rem Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
setlocal enabledelayedexpansion
set BUILDDIR=%~dp0
@@ -13,15 +13,15 @@ if exist .deps\prepared goto :render
rmdir /s /q .deps 2> NUL
mkdir .deps || goto :error
cd .deps || goto :error
- call :download go.zip https://download.wireguard.com/windows-toolchain/distfiles/go1.16.2-windows_amd64_2021-03-22.zip 4f31feaf91be300e3b75be78e6ebf0b99facbdacb6c1367c8c156617b8be0d35 || goto :error
+ call :download go.zip https://go.dev/dl/go1.18.windows-amd64.zip 65c5c0c709a7ca1b357091b10b795b439d8b50e579d3893edab4c7e9b384f435 || goto :error
rem Mirror of https://github.com/mstorsjo/llvm-mingw/releases/download/20201020/llvm-mingw-20201020-msvcrt-x86_64.zip
call :download llvm-mingw-msvcrt.zip https://download.wireguard.com/windows-toolchain/distfiles/llvm-mingw-20201020-msvcrt-x86_64.zip 2e46593245090df96d15e360e092f0b62b97e93866e0162dca7f93b16722b844 || goto :error
rem Mirror of https://imagemagick.org/download/binaries/ImageMagick-7.0.8-42-portable-Q16-x64.zip
call :download imagemagick.zip https://download.wireguard.com/windows-toolchain/distfiles/ImageMagick-7.0.8-42-portable-Q16-x64.zip 584e069f56456ce7dde40220948ff9568ac810688c892c5dfb7f6db902aa05aa "convert.exe colors.xml delegates.xml" || goto :error
rem Mirror of https://sourceforge.net/projects/ezwinports/files/make-4.2.1-without-guile-w32-bin.zip
call :download make.zip https://download.wireguard.com/windows-toolchain/distfiles/make-4.2.1-without-guile-w32-bin.zip 30641be9602712be76212b99df7209f4f8f518ba764cf564262bc9d6e4047cc7 "--strip-components 1 bin" || goto :error
- call :download wireguard-tools.zip https://git.zx2c4.com/wireguard-tools/snapshot/wireguard-tools-1.0.20210223.zip c0cee24d469ecd3f0420dd2cc9747faa67f257a39c17063c10cff99ba62a6fa6 "--exclude wg-quick --strip-components 1" || goto :error
- call :download wintun.zip https://www.wintun.net/builds/wintun-0.10.2.zip fcd9f62f1bd5a550fcb9c21fbb5d6a556214753ccbbd1a3ebad4d318ec9dcbef || goto :error
+ call :download wireguard-tools.zip https://git.zx2c4.com/wireguard-tools/snapshot/wireguard-tools-1ee37b8e4833a25efe6f1fc0d5bdcb476148f4ba.zip ed0739bc3e5a7021a59d4cc4fc63e5fb60a0cb8628d30515a747bfbdcf1fdb0a "--exclude wg-quick --strip-components 1" || goto :error
+ call :download wireguard-nt.zip https://download.wireguard.com/wireguard-nt/wireguard-nt-0.10.1.zip 772c0b1463d8d2212716f43f06f4594d880dea4f735165bd68e388fc41b81605 || goto :error
copy /y NUL prepared > NUL || goto :error
cd .. || goto :error
@@ -43,7 +43,6 @@ if exist .deps\prepared goto :render
)
call :build_plat x86 i686 386 || goto :error
call :build_plat amd64 x86_64 amd64 || goto :error
- call :build_plat arm armv7 arm || goto :error
call :build_plat arm64 aarch64 arm64 || goto :error
:sign
@@ -51,7 +50,7 @@ if exist .deps\prepared goto :render
if "%SigningCertificate%"=="" goto :success
if "%TimestampServer%"=="" goto :success
echo [+] Signing
- signtool sign /sha1 "%SigningCertificate%" /fd sha256 /tr "%TimestampServer%" /td sha256 /d WireGuard x86\wireguard.exe x86\wg.exe amd64\wireguard.exe amd64\wg.exe arm\wireguard.exe arm\wg.exe arm64\wireguard.exe arm64\wg.exe || goto :error
+ signtool sign /sha1 "%SigningCertificate%" /fd sha256 /tr "%TimestampServer%" /td sha256 /d WireGuard x86\wireguard.exe x86\wg.exe amd64\wireguard.exe amd64\wg.exe arm64\wireguard.exe arm64\wg.exe || goto :error
:success
echo [+] Success. Launch wireguard.exe.
@@ -72,13 +71,14 @@ if exist .deps\prepared goto :render
set GOARCH=%~3
mkdir %1 >NUL 2>&1
echo [+] Assembling resources %1
- %~2-w64-mingw32-windres -I ".deps\wintun\bin\%~1" -DWIREGUARD_VERSION_ARRAY=%WIREGUARD_VERSION_ARRAY% -DWIREGUARD_VERSION_STR=%WIREGUARD_VERSION% -i resources.rc -o "resources_%~3.syso" -O coff -c 65001 || exit /b %errorlevel%
+ %~2-w64-mingw32-windres -I ".deps\wireguard-nt\bin\%~1" -DWIREGUARD_VERSION_ARRAY=%WIREGUARD_VERSION_ARRAY% -DWIREGUARD_VERSION_STR=%WIREGUARD_VERSION% -i resources.rc -o "resources_%~3.syso" -O coff -c 65001 || exit /b %errorlevel%
echo [+] Building program %1
- go build -tags load_wintun_from_rsrc -ldflags="-H windowsgui -s -w" -trimpath -v -o "%~1\wireguard.exe" || exit /b 1
+ go build -tags load_wgnt_from_rsrc -ldflags="-H windowsgui -s -w" -trimpath -buildvcs=false -v -o "%~1\wireguard.exe" || exit /b 1
if not exist "%~1\wg.exe" (
echo [+] Building command line tools %1
- del .deps\src\*.exe .deps\src\*.o .deps\src\wincompat\*.o 2> NUL
- make --no-print-directory -C .deps\src PLATFORM=windows CC=%~2-w64-mingw32-gcc WINDRES=%~2-w64-mingw32-windres V=1 LDFLAGS=-s RUNSTATEDIR= SYSTEMDUNITDIR= -j%NUMBER_OF_PROCESSORS% || exit /b 1
+ del .deps\src\*.exe .deps\src\*.o .deps\src\wincompat\*.o .deps\src\wincompat\*.lib 2> NUL
+ set LDFLAGS=-s
+ make --no-print-directory -C .deps\src PLATFORM=windows CC=%~2-w64-mingw32-gcc WINDRES=%~2-w64-mingw32-windres V=1 RUNSTATEDIR= SYSTEMDUNITDIR= -j%NUMBER_OF_PROCESSORS% || exit /b 1
move /Y .deps\src\wg.exe "%~1\wg.exe" > NUL || exit /b 1
)
goto :eof
diff --git a/conf/admin_windows.go b/conf/admin_windows.go
index a135aa6d..91d4bdc9 100644
--- a/conf/admin_windows.go
+++ b/conf/admin_windows.go
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package conf
diff --git a/conf/config.go b/conf/config.go
index 0a6c6abf..74ffacf6 100644
--- a/conf/config.go
+++ b/conf/config.go
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package conf
@@ -9,9 +9,8 @@ import (
"crypto/rand"
"crypto/subtle"
"encoding/base64"
- "encoding/hex"
"fmt"
- "net"
+ "net/netip"
"strings"
"time"
@@ -22,19 +21,16 @@ import (
const KeyLength = 32
-type IPCidr struct {
- IP net.IP
- Cidr uint8
-}
-
type Endpoint struct {
Host string
Port uint16
}
-type Key [KeyLength]byte
-type HandshakeTime time.Duration
-type Bytes uint64
+type (
+ Key [KeyLength]byte
+ HandshakeTime time.Duration
+ Bytes uint64
+)
type Config struct {
Name string
@@ -44,21 +40,22 @@ type Config struct {
type Interface struct {
PrivateKey Key
- Addresses []IPCidr
+ Addresses []netip.Prefix
ListenPort uint16
MTU uint16
- DNS []net.IP
+ DNS []netip.Addr
DNSSearch []string
PreUp string
PostUp string
PreDown string
PostDown string
+ TableOff bool
}
type Peer struct {
PublicKey Key
PresharedKey Key
- AllowedIPs []IPCidr
+ AllowedIPs []netip.Prefix
Endpoint Endpoint
PersistentKeepalive uint16
@@ -67,34 +64,37 @@ type Peer struct {
LastHandshakeTime HandshakeTime
}
-func (r *IPCidr) String() string {
- return fmt.Sprintf("%s/%d", r.IP.String(), r.Cidr)
-}
-
-func (r *IPCidr) Bits() uint8 {
- if r.IP.To4() != nil {
- return 32
+func (conf *Config) IntersectsWith(other *Config) bool {
+ allRoutes := make(map[netip.Prefix]bool, len(conf.Interface.Addresses)*2+len(conf.Peers)*3)
+ for _, a := range conf.Interface.Addresses {
+ allRoutes[netip.PrefixFrom(a.Addr(), a.Addr().BitLen())] = true
+ allRoutes[a.Masked()] = true
}
- return 128
-}
-
-func (r *IPCidr) IPNet() net.IPNet {
- return net.IPNet{
- IP: r.IP,
- Mask: net.CIDRMask(int(r.Cidr), int(r.Bits())),
+ for i := range conf.Peers {
+ for _, a := range conf.Peers[i].AllowedIPs {
+ allRoutes[a.Masked()] = true
+ }
}
-}
-
-func (r *IPCidr) MaskSelf() {
- bits := int(r.Bits())
- mask := net.CIDRMask(int(r.Cidr), bits)
- for i := 0; i < bits/8; i++ {
- r.IP[i] &= mask[i]
+ for _, a := range other.Interface.Addresses {
+ if allRoutes[netip.PrefixFrom(a.Addr(), a.Addr().BitLen())] {
+ return true
+ }
+ if allRoutes[a.Masked()] {
+ return true
+ }
}
+ for i := range other.Peers {
+ for _, a := range other.Peers[i].AllowedIPs {
+ if allRoutes[a.Masked()] {
+ return true
+ }
+ }
+ }
+ return false
}
func (e *Endpoint) String() string {
- if strings.IndexByte(e.Host, ':') > 0 {
+ if strings.IndexByte(e.Host, ':') != -1 {
return fmt.Sprintf("[%s]:%d", e.Host, e.Port)
}
return fmt.Sprintf("%s:%d", e.Host, e.Port)
@@ -108,10 +108,6 @@ func (k *Key) String() string {
return base64.StdEncoding.EncodeToString(k[:])
}
-func (k *Key) HexString() string {
- return hex.EncodeToString(k[:])
-}
-
func (k *Key) IsZero() bool {
var zeros Key
return subtle.ConstantTimeCompare(zeros[:], k[:]) == 1
diff --git a/conf/dnsresolver_windows.go b/conf/dnsresolver_windows.go
index b17be849..a299c475 100644
--- a/conf/dnsresolver_windows.go
+++ b/conf/dnsresolver_windows.go
@@ -1,28 +1,26 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package conf
import (
- "fmt"
"log"
- "net"
- "syscall"
+ "net/netip"
"time"
"unsafe"
+ "golang.zx2c4.com/wireguard/windows/tunnel/winipcfg"
+
"golang.org/x/sys/windows"
+ "golang.zx2c4.com/wireguard/windows/services"
)
-//sys internetGetConnectedState(flags *uint32, reserved uint32) (connected bool) = wininet.InternetGetConnectedState
-
func resolveHostname(name string) (resolvedIPString string, err error) {
maxTries := 10
- systemJustBooted := windows.DurationSinceBoot() <= time.Minute*4
- if systemJustBooted {
- maxTries *= 4
+ if services.StartedAtBoot() {
+ maxTries *= 3
}
for i := 0; i < maxTries; i++ {
if i > 0 {
@@ -33,12 +31,11 @@ func resolveHostname(name string) (resolvedIPString string, err error) {
return
}
if err == windows.WSATRY_AGAIN {
- log.Printf("Temporary DNS error when resolving %s, sleeping for 4 seconds", name)
+ log.Printf("Temporary DNS error when resolving %s, so sleeping for 4 seconds", name)
continue
}
- var state uint32
- if err == windows.WSAHOST_NOT_FOUND && systemJustBooted && !internetGetConnectedState(&state, 0) {
- log.Printf("Host not found when resolving %s, but no Internet connection available, sleeping for 4 seconds", name)
+ if err == windows.WSAHOST_NOT_FOUND && services.StartedAtBoot() {
+ log.Printf("Host not found when resolving %s at boot time, so sleeping for 4 seconds", name)
continue
}
return
@@ -66,25 +63,35 @@ func resolveHostnameOnce(name string) (resolvedIPString string, err error) {
return
}
defer windows.FreeAddrInfoW(result)
- ipv6 := ""
+ var v6 netip.Addr
for ; result != nil; result = result.Next {
- switch result.Family {
- case windows.AF_INET:
- return (net.IP)((*syscall.RawSockaddrInet4)(unsafe.Pointer(result.Addr)).Addr[:]).String(), nil
- case windows.AF_INET6:
- if len(ipv6) != 0 {
- continue
- }
- a := (*syscall.RawSockaddrInet6)(unsafe.Pointer(result.Addr))
- ipv6 = (net.IP)(a.Addr[:]).String()
- if a.Scope_id != 0 {
- ipv6 += fmt.Sprintf("%%%d", a.Scope_id)
- }
+ if result.Family != windows.AF_INET && result.Family != windows.AF_INET6 {
+ continue
+ }
+ addr := (*winipcfg.RawSockaddrInet)(unsafe.Pointer(result.Addr)).Addr()
+ if addr.Is4() {
+ return addr.String(), nil
+ } else if !v6.IsValid() && addr.Is6() {
+ v6 = addr
}
}
- if len(ipv6) != 0 {
- return ipv6, nil
+ if v6.IsValid() {
+ return v6.String(), nil
}
err = windows.WSAHOST_NOT_FOUND
return
}
+
+func (config *Config) ResolveEndpoints() error {
+ for i := range config.Peers {
+ if config.Peers[i].Endpoint.IsEmpty() {
+ continue
+ }
+ var err error
+ config.Peers[i].Endpoint.Host, err = resolveHostname(config.Peers[i].Endpoint.Host)
+ if err != nil {
+ return err
+ }
+ }
+ return nil
+}
diff --git a/conf/dpapi/dpapi_windows.go b/conf/dpapi/dpapi_windows.go
index b3f28a93..49a32915 100644
--- a/conf/dpapi/dpapi_windows.go
+++ b/conf/dpapi/dpapi_windows.go
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package dpapi
@@ -28,16 +28,9 @@ func Encrypt(data []byte, name string) ([]byte, error) {
if err != nil {
return nil, fmt.Errorf("unable to encrypt DPAPI protected data: %w", err)
}
-
- outSlice := *(*[]byte)(unsafe.Pointer(&(struct {
- addr *byte
- len int
- cap int
- }{out.Data, int(out.Size), int(out.Size)})))
- ret := make([]byte, len(outSlice))
- copy(ret, outSlice)
+ ret := make([]byte, out.Size)
+ copy(ret, unsafe.Slice(out.Data, out.Size))
windows.LocalFree(windows.Handle(unsafe.Pointer(out.Data)))
-
return ret, nil
}
@@ -48,19 +41,12 @@ func Decrypt(data []byte, name string) ([]byte, error) {
if err != nil {
return nil, err
}
-
err = windows.CryptUnprotectData(bytesToBlob(data), &outName, nil, 0, nil, windows.CRYPTPROTECT_UI_FORBIDDEN, &out)
if err != nil {
return nil, fmt.Errorf("unable to decrypt DPAPI protected data: %w", err)
}
-
- outSlice := *(*[]byte)(unsafe.Pointer(&(struct {
- addr *byte
- len int
- cap int
- }{out.Data, int(out.Size), int(out.Size)})))
- ret := make([]byte, len(outSlice))
- copy(ret, outSlice)
+ ret := make([]byte, out.Size)
+ copy(ret, unsafe.Slice(out.Data, out.Size))
windows.LocalFree(windows.Handle(unsafe.Pointer(out.Data)))
// Note: this ridiculous open-coded strcmp is not constant time.
@@ -75,8 +61,8 @@ func Decrypt(data []byte, name string) ([]byte, error) {
if *a == 0 || *b == 0 {
break
}
- a = (*uint16)(unsafe.Pointer(uintptr(unsafe.Pointer(a)) + 2))
- b = (*uint16)(unsafe.Pointer(uintptr(unsafe.Pointer(b)) + 2))
+ a = (*uint16)(unsafe.Add(unsafe.Pointer(a), 2))
+ b = (*uint16)(unsafe.Add(unsafe.Pointer(b), 2))
}
runtime.KeepAlive(utf16Name)
windows.LocalFree(windows.Handle(unsafe.Pointer(outName)))
diff --git a/conf/dpapi/dpapi_windows_test.go b/conf/dpapi/dpapi_windows_test.go
index 2e12e273..fd7307e6 100644
--- a/conf/dpapi/dpapi_windows_test.go
+++ b/conf/dpapi/dpapi_windows_test.go
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package dpapi
@@ -53,11 +53,7 @@ func TestRoundTrip(t *testing.T) {
if err != nil {
t.Errorf("Unable to get utf16 chars for name: %s", err)
}
- nameUtf16Bytes := *(*[]byte)(unsafe.Pointer(&struct {
- addr *byte
- len int
- cap int
- }{(*byte)(unsafe.Pointer(&nameUtf16[0])), len(nameUtf16) * 2, cap(nameUtf16) * 2}))
+ nameUtf16Bytes := unsafe.Slice((*byte)(unsafe.Pointer(&nameUtf16[0])), len(nameUtf16)*2)
i := bytes.Index(eCorrupt, nameUtf16Bytes)
if i == -1 {
t.Error("Unable to find ad in blob")
diff --git a/conf/dpapi/test.exe b/conf/dpapi/test.exe
deleted file mode 100755
index 9e5f23a7..00000000
--- a/conf/dpapi/test.exe
+++ /dev/null
Binary files differ
diff --git a/conf/filewriter_windows.go b/conf/filewriter_windows.go
index b0fca73e..c6bb2b45 100644
--- a/conf/filewriter_windows.go
+++ b/conf/filewriter_windows.go
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package conf
@@ -8,6 +8,7 @@ package conf
import (
"crypto/rand"
"encoding/hex"
+ "path/filepath"
"sync/atomic"
"unsafe"
@@ -40,7 +41,7 @@ func writeLockedDownFile(destination string, overwrite bool, contents []byte) er
if err != nil {
return err
}
- tmpDestination := randomFileName()
+ tmpDestination := filepath.Join(filepath.Dir(destination), randomFileName())
tmpDestination16, err := windows.UTF16PtrFromString(tmpDestination)
if err != nil {
return err
diff --git a/conf/migration_windows.go b/conf/migration_windows.go
index 091efa32..ed288f3c 100644
--- a/conf/migration_windows.go
+++ b/conf/migration_windows.go
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package conf
@@ -18,12 +18,19 @@ import (
"golang.org/x/sys/windows"
)
-var migrating sync.Mutex
-var lastMigrationTimer *time.Timer
+var (
+ migrating sync.Mutex
+ lastMigrationTimer *time.Timer
+)
+
+type MigrationCallback func(name, oldPath, newPath string)
-func MigrateUnencryptedConfigs() { migrateUnencryptedConfigs(3) }
+func MigrateUnencryptedConfigs(migrated MigrationCallback) { migrateUnencryptedConfigs(3, migrated) }
-func migrateUnencryptedConfigs(sharingBase int) {
+func migrateUnencryptedConfigs(sharingBase int, migrated MigrationCallback) {
+ if migrated == nil {
+ migrated = func(_, _, _ string) {}
+ }
migrating.Lock()
defer migrating.Unlock()
configFileDir, err := tunnelConfigurationsDirectory()
@@ -48,12 +55,13 @@ func migrateUnencryptedConfigs(sharingBase int) {
if err != nil {
continue
}
- if info.Mode().Perm()&0444 == 0 {
+ if info.Mode().Perm()&0o444 == 0 {
continue
}
var bytes []byte
var config *Config
+ var newPath string
// We don't use os.ReadFile, because we actually want RDWR, so that we can take advantage
// of Windows file locking for ensuring the file is finished being written.
f, err := os.OpenFile(path, os.O_RDWR, 0)
@@ -65,7 +73,7 @@ func migrateUnencryptedConfigs(sharingBase int) {
if lastMigrationTimer != nil {
lastMigrationTimer.Stop()
}
- lastMigrationTimer = time.AfterFunc(time.Second/time.Duration(sharingBase*sharingBase), func() { migrateUnencryptedConfigs(sharingBase - 1) })
+ lastMigrationTimer = time.AfterFunc(time.Second/time.Duration(sharingBase*sharingBase), func() { migrateUnencryptedConfigs(sharingBase-1, migrated) })
ignoreSharingViolations = true
continue
}
@@ -87,8 +95,13 @@ func migrateUnencryptedConfigs(sharingBase int) {
}
err = os.Remove(path)
if err != nil {
- log.Printf("Unable to remove old path %#q: %v", path, err)
+ goto error
+ }
+ newPath, err = config.Path()
+ if err != nil {
+ goto error
}
+ migrated(config.Name, path, newPath)
continue
error:
log.Printf("Unable to ingest and encrypt %#q: %v", path, err)
diff --git a/conf/mksyscall.go b/conf/mksyscall.go
deleted file mode 100644
index c7ed0e4f..00000000
--- a/conf/mksyscall.go
+++ /dev/null
@@ -1,8 +0,0 @@
-/* SPDX-License-Identifier: MIT
- *
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
- */
-
-package conf
-
-//go:generate go run golang.org/x/sys/windows/mkwinsyscall -output zsyscall_windows.go dnsresolver_windows.go migration_windows.go storewatcher_windows.go
diff --git a/conf/name.go b/conf/name.go
index a4affb48..0d084070 100644
--- a/conf/name.go
+++ b/conf/name.go
@@ -1,11 +1,12 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package conf
import (
+ "errors"
"regexp"
"strconv"
"strings"
@@ -17,15 +18,13 @@ var reservedNames = []string{
"LPT1", "LPT2", "LPT3", "LPT4", "LPT5", "LPT6", "LPT7", "LPT8", "LPT9",
}
-const serviceNameForbidden = "$"
-const netshellDllForbidden = "\\/:*?\"<>|\t"
-const specialChars = "/\\<>:\"|?*\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x00"
-
-var allowedNameFormat *regexp.Regexp
+const (
+ serviceNameForbidden = "$"
+ netshellDllForbidden = "\\/:*?\"<>|\t"
+ specialChars = "/\\<>:\"|?*\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x00"
+)
-func init() {
- allowedNameFormat = regexp.MustCompile("^[a-zA-Z0-9_=+.-]{1,32}$")
-}
+var allowedNameFormat = regexp.MustCompile("^[a-zA-Z0-9_=+.-]{1,32}$")
func isReserved(name string) bool {
if len(name) == 0 {
@@ -35,6 +34,14 @@ func isReserved(name string) bool {
if strings.EqualFold(name, reserved) {
return true
}
+ for i := len(name) - 1; i >= 0; i-- {
+ if name[i] == '.' {
+ if strings.EqualFold(name[:i], reserved) {
+ return true
+ }
+ break
+ }
+ }
}
return false
}
@@ -55,6 +62,7 @@ type naturalSortToken struct {
maybeString string
maybeNumber int
}
+
type naturalSortString struct {
originalString string
tokens []naturalSortToken
@@ -110,3 +118,10 @@ func TunnelNameIsLess(a, b string) bool {
}
return false
}
+
+func ServiceNameOfTunnel(tunnelName string) (string, error) {
+ if !TunnelNameIsValid(tunnelName) {
+ return "", errors.New("Tunnel name is not valid")
+ }
+ return "WireGuardTunnel$" + tunnelName, nil
+}
diff --git a/conf/parser.go b/conf/parser.go
index bd08ee6c..b1da9816 100644
--- a/conf/parser.go
+++ b/conf/parser.go
@@ -1,22 +1,20 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package conf
import (
- "bufio"
"encoding/base64"
- "encoding/hex"
- "io"
- "net"
+ "net/netip"
"strconv"
"strings"
- "time"
+ "golang.org/x/sys/windows"
"golang.org/x/text/encoding/unicode"
+ "golang.zx2c4.com/wireguard/windows/driver"
"golang.zx2c4.com/wireguard/windows/l18n"
)
@@ -29,43 +27,16 @@ func (e *ParseError) Error() string {
return l18n.Sprintf("%s: %q", e.why, e.offender)
}
-func parseIPCidr(s string) (ipcidr *IPCidr, err error) {
- var addrStr, cidrStr string
- var cidr int
-
- i := strings.IndexByte(s, '/')
- if i < 0 {
- addrStr = s
- } else {
- addrStr, cidrStr = s[:i], s[i+1:]
- }
-
- err = &ParseError{l18n.Sprintf("Invalid IP address"), s}
- addr := net.ParseIP(addrStr)
- if addr == nil {
- return
+func parseIPCidr(s string) (netip.Prefix, error) {
+ ipcidr, err := netip.ParsePrefix(s)
+ if err == nil {
+ return ipcidr, nil
}
- maybeV4 := addr.To4()
- if maybeV4 != nil {
- addr = maybeV4
- }
- if len(cidrStr) > 0 {
- err = &ParseError{l18n.Sprintf("Invalid network prefix length"), s}
- cidr, err = strconv.Atoi(cidrStr)
- if err != nil || cidr < 0 || cidr > 128 {
- return
- }
- if cidr > 32 && maybeV4 != nil {
- return
- }
- } else {
- if maybeV4 != nil {
- cidr = 32
- } else {
- cidr = 128
- }
+ addr, err := netip.ParseAddr(s)
+ if err != nil {
+ return netip.Prefix{}, &ParseError{l18n.Sprintf("Invalid IP address: "), s}
}
- return &IPCidr{addr, uint8(cidr)}, nil
+ return netip.PrefixFrom(addr, addr.BitLen()), nil
}
func parseEndpoint(s string) (*Endpoint, error) {
@@ -89,8 +60,8 @@ func parseEndpoint(s string) (*Endpoint, error) {
if i := strings.LastIndexByte(host, '%'); i > 1 {
end = i
}
- maybeV6 := net.ParseIP(host[1:end])
- if maybeV6 == nil || len(maybeV6) != net.IPv6len {
+ maybeV6, err2 := netip.ParseAddr(host[1:end])
+ if err2 != nil || !maybeV6.Is6() {
return nil, err
}
} else {
@@ -98,7 +69,7 @@ func parseEndpoint(s string) (*Endpoint, error) {
}
host = host[1 : len(host)-1]
}
- return &Endpoint{host, uint16(port)}, nil
+ return &Endpoint{host, port}, nil
}
func parseMTU(s string) (uint16, error) {
@@ -137,21 +108,18 @@ func parsePersistentKeepalive(s string) (uint16, error) {
return uint16(m), nil
}
-func parseKeyBase64(s string) (*Key, error) {
- k, err := base64.StdEncoding.DecodeString(s)
- if err != nil {
- return nil, &ParseError{l18n.Sprintf("Invalid key: %v", err), s}
- }
- if len(k) != KeyLength {
- return nil, &ParseError{l18n.Sprintf("Keys must decode to exactly 32 bytes"), s}
+func parseTableOff(s string) (bool, error) {
+ if s == "off" {
+ return true, nil
+ } else if s == "auto" || s == "main" {
+ return false, nil
}
- var key Key
- copy(key[:], k)
- return &key, nil
+ _, err := strconv.ParseUint(s, 10, 32)
+ return false, err
}
-func parseKeyHex(s string) (*Key, error) {
- k, err := hex.DecodeString(s)
+func parseKeyBase64(s string) (*Key, error) {
+ k, err := base64.StdEncoding.DecodeString(s)
if err != nil {
return nil, &ParseError{l18n.Sprintf("Invalid key: %v", err), s}
}
@@ -163,14 +131,6 @@ func parseKeyHex(s string) (*Key, error) {
return &key, nil
}
-func parseBytesOrStamp(s string) (uint64, error) {
- b, err := strconv.ParseUint(s, 10, 64)
- if err != nil {
- return 0, &ParseError{l18n.Sprintf("Number must be a number between 0 and 2^64-1: %v", err), s}
- }
- return b, nil
-}
-
func splitList(s string) ([]string, error) {
var out []string
for _, split := range strings.Split(s, ",") {
@@ -197,7 +157,7 @@ func (c *Config) maybeAddPeer(p *Peer) {
}
}
-func FromWgQuick(s string, name string) (*Config, error) {
+func FromWgQuick(s, name string) (*Config, error) {
if !TunnelNameIsValid(name) {
return nil, &ParseError{l18n.Sprintf("Tunnel name is not valid"), name}
}
@@ -207,10 +167,7 @@ func FromWgQuick(s string, name string) (*Config, error) {
sawPrivateKey := false
var peer *Peer
for _, line := range lines {
- pound := strings.IndexByte(line, '#')
- if pound >= 0 {
- line = line[:pound]
- }
+ line, _, _ = strings.Cut(line, "#")
line = strings.TrimSpace(line)
lineLower := strings.ToLower(line)
if len(line) == 0 {
@@ -269,7 +226,7 @@ func FromWgQuick(s string, name string) (*Config, error) {
if err != nil {
return nil, err
}
- conf.Interface.Addresses = append(conf.Interface.Addresses, *a)
+ conf.Interface.Addresses = append(conf.Interface.Addresses, a)
}
case "dns":
addresses, err := splitList(val)
@@ -277,8 +234,8 @@ func FromWgQuick(s string, name string) (*Config, error) {
return nil, err
}
for _, address := range addresses {
- a := net.ParseIP(address)
- if a == nil {
+ a, err := netip.ParseAddr(address)
+ if err != nil {
conf.Interface.DNSSearch = append(conf.Interface.DNSSearch, address)
} else {
conf.Interface.DNS = append(conf.Interface.DNS, a)
@@ -292,6 +249,12 @@ func FromWgQuick(s string, name string) (*Config, error) {
conf.Interface.PreDown = val
case "postdown":
conf.Interface.PostDown = val
+ case "table":
+ tableOff, err := parseTableOff(val)
+ if err != nil {
+ return nil, err
+ }
+ conf.Interface.TableOff = tableOff
default:
return nil, &ParseError{l18n.Sprintf("Invalid key for [Interface] section"), key}
}
@@ -319,7 +282,7 @@ func FromWgQuick(s string, name string) (*Config, error) {
if err != nil {
return nil, err
}
- peer.AllowedIPs = append(peer.AllowedIPs, *a)
+ peer.AllowedIPs = append(peer.AllowedIPs, a)
}
case "persistentkeepalive":
p, err := parsePersistentKeepalive(val)
@@ -352,7 +315,7 @@ func FromWgQuick(s string, name string) (*Config, error) {
return &conf, nil
}
-func FromWgQuickWithUnknownEncoding(s string, name string) (*Config, error) {
+func FromWgQuickWithUnknownEncoding(s, name string) (*Config, error) {
c, firstErr := FromWgQuick(s, name)
if firstErr == nil {
return c, nil
@@ -369,8 +332,7 @@ func FromWgQuickWithUnknownEncoding(s string, name string) (*Config, error) {
return nil, firstErr
}
-func FromUAPI(reader io.Reader, existingConfig *Config) (*Config, error) {
- parserState := inInterfaceSection
+func FromDriverConfiguration(interfaze *driver.Interface, existingConfig *Config) *Config {
conf := Config{
Name: existingConfig.Name,
Interface: Interface{
@@ -382,125 +344,57 @@ func FromUAPI(reader io.Reader, existingConfig *Config) (*Config, error) {
PostUp: existingConfig.Interface.PostUp,
PreDown: existingConfig.Interface.PreDown,
PostDown: existingConfig.Interface.PostDown,
+ TableOff: existingConfig.Interface.TableOff,
},
}
- var peer *Peer
- lineReader := bufio.NewReader(reader)
- for {
- line, err := lineReader.ReadString('\n')
- if err != nil {
- return nil, err
+ if interfaze.Flags&driver.InterfaceHasPrivateKey != 0 {
+ conf.Interface.PrivateKey = interfaze.PrivateKey
+ }
+ if interfaze.Flags&driver.InterfaceHasListenPort != 0 {
+ conf.Interface.ListenPort = interfaze.ListenPort
+ }
+ var p *driver.Peer
+ for i := uint32(0); i < interfaze.PeerCount; i++ {
+ if p == nil {
+ p = interfaze.FirstPeer()
+ } else {
+ p = p.NextPeer()
}
- line = line[:len(line)-1]
- if len(line) == 0 {
- break
+ peer := Peer{}
+ if p.Flags&driver.PeerHasPublicKey != 0 {
+ peer.PublicKey = p.PublicKey
}
- equals := strings.IndexByte(line, '=')
- if equals < 0 {
- return nil, &ParseError{l18n.Sprintf("Config key is missing an equals separator"), line}
+ if p.Flags&driver.PeerHasPresharedKey != 0 {
+ peer.PresharedKey = p.PresharedKey
}
- key, val := line[:equals], line[equals+1:]
- if len(val) == 0 {
- return nil, &ParseError{l18n.Sprintf("Key must have a value"), line}
+ if p.Flags&driver.PeerHasEndpoint != 0 {
+ peer.Endpoint.Port = p.Endpoint.Port()
+ peer.Endpoint.Host = p.Endpoint.Addr().String()
}
- switch key {
- case "public_key":
- conf.maybeAddPeer(peer)
- peer = &Peer{}
- parserState = inPeerSection
- case "errno":
- if val == "0" {
- continue
- } else {
- return nil, &ParseError{l18n.Sprintf("Error in getting configuration"), val}
- }
+ if p.Flags&driver.PeerHasPersistentKeepalive != 0 {
+ peer.PersistentKeepalive = p.PersistentKeepalive
}
- if parserState == inInterfaceSection {
- switch key {
- case "private_key":
- k, err := parseKeyHex(val)
- if err != nil {
- return nil, err
- }
- conf.Interface.PrivateKey = *k
- case "listen_port":
- p, err := parsePort(val)
- if err != nil {
- return nil, err
- }
- conf.Interface.ListenPort = p
- case "fwmark":
- // Ignored for now.
-
- default:
- return nil, &ParseError{l18n.Sprintf("Invalid key for interface section"), key}
+ peer.TxBytes = Bytes(p.TxBytes)
+ peer.RxBytes = Bytes(p.RxBytes)
+ if p.LastHandshake != 0 {
+ peer.LastHandshakeTime = HandshakeTime((p.LastHandshake - 116444736000000000) * 100)
+ }
+ var a *driver.AllowedIP
+ for j := uint32(0); j < p.AllowedIPsCount; j++ {
+ if a == nil {
+ a = p.FirstAllowedIP()
+ } else {
+ a = a.NextAllowedIP()
}
- } else if parserState == inPeerSection {
- switch key {
- case "public_key":
- k, err := parseKeyHex(val)
- if err != nil {
- return nil, err
- }
- peer.PublicKey = *k
- case "preshared_key":
- k, err := parseKeyHex(val)
- if err != nil {
- return nil, err
- }
- peer.PresharedKey = *k
- case "protocol_version":
- if val != "1" {
- return nil, &ParseError{l18n.Sprintf("Protocol version must be 1"), val}
- }
- case "allowed_ip":
- a, err := parseIPCidr(val)
- if err != nil {
- return nil, err
- }
- peer.AllowedIPs = append(peer.AllowedIPs, *a)
- case "persistent_keepalive_interval":
- p, err := parsePersistentKeepalive(val)
- if err != nil {
- return nil, err
- }
- peer.PersistentKeepalive = p
- case "endpoint":
- e, err := parseEndpoint(val)
- if err != nil {
- return nil, err
- }
- peer.Endpoint = *e
- case "tx_bytes":
- b, err := parseBytesOrStamp(val)
- if err != nil {
- return nil, err
- }
- peer.TxBytes = Bytes(b)
- case "rx_bytes":
- b, err := parseBytesOrStamp(val)
- if err != nil {
- return nil, err
- }
- peer.RxBytes = Bytes(b)
- case "last_handshake_time_sec":
- t, err := parseBytesOrStamp(val)
- if err != nil {
- return nil, err
- }
- peer.LastHandshakeTime += HandshakeTime(time.Duration(t) * time.Second)
- case "last_handshake_time_nsec":
- t, err := parseBytesOrStamp(val)
- if err != nil {
- return nil, err
- }
- peer.LastHandshakeTime += HandshakeTime(time.Duration(t) * time.Nanosecond)
- default:
- return nil, &ParseError{l18n.Sprintf("Invalid key for peer section"), key}
+ var ip netip.Addr
+ if a.AddressFamily == windows.AF_INET {
+ ip = netip.AddrFrom4(*(*[4]byte)(a.Address[:4]))
+ } else if a.AddressFamily == windows.AF_INET6 {
+ ip = netip.AddrFrom16(*(*[16]byte)(a.Address[:16]))
}
+ peer.AllowedIPs = append(peer.AllowedIPs, netip.PrefixFrom(ip, int(a.Cidr)))
}
+ conf.Peers = append(conf.Peers, peer)
}
- conf.maybeAddPeer(peer)
-
- return &conf, nil
+ return &conf
}
diff --git a/conf/parser_test.go b/conf/parser_test.go
index f80d6d18..25d906fd 100644
--- a/conf/parser_test.go
+++ b/conf/parser_test.go
@@ -1,12 +1,12 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package conf
import (
- "net"
+ "net/netip"
"reflect"
"runtime"
"testing"
@@ -45,7 +45,7 @@ func noError(t *testing.T, err error) bool {
return false
}
-func equal(t *testing.T, expected, actual interface{}) bool {
+func equal(t *testing.T, expected, actual any) bool {
if reflect.DeepEqual(expected, actual) {
return true
}
@@ -53,7 +53,8 @@ func equal(t *testing.T, expected, actual interface{}) bool {
t.Errorf("Failed equals at %s:%d\nactual %#v\nexpected %#v", fn, line, actual, expected)
return false
}
-func lenTest(t *testing.T, actualO interface{}, expected int) bool {
+
+func lenTest(t *testing.T, actualO any, expected int) bool {
actual := reflect.ValueOf(actualO).Len()
if reflect.DeepEqual(expected, actual) {
return true
@@ -62,7 +63,8 @@ func lenTest(t *testing.T, actualO interface{}, expected int) bool {
t.Errorf("Wrong length at %s:%d\nactual %#v\nexpected %#v", fn, line, actual, expected)
return false
}
-func contains(t *testing.T, list, element interface{}) bool {
+
+func contains(t *testing.T, list, element any) bool {
listValue := reflect.ValueOf(list)
for i := 0; i < listValue.Len(); i++ {
if reflect.DeepEqual(listValue.Index(i).Interface(), element) {
@@ -77,10 +79,9 @@ func contains(t *testing.T, list, element interface{}) bool {
func TestFromWgQuick(t *testing.T) {
conf, err := FromWgQuick(testInput, "test")
if noError(t, err) {
-
lenTest(t, conf.Interface.Addresses, 2)
- contains(t, conf.Interface.Addresses, IPCidr{net.IPv4(10, 10, 0, 1), uint8(16)})
- contains(t, conf.Interface.Addresses, IPCidr{net.IPv4(10, 192, 122, 1), uint8(24)})
+ contains(t, conf.Interface.Addresses, netip.PrefixFrom(netip.AddrFrom4([4]byte{0, 10, 0, 1}), 16))
+ contains(t, conf.Interface.Addresses, netip.PrefixFrom(netip.AddrFrom4([4]byte{10, 192, 122, 1}), 24))
equal(t, "yAnz5TF+lXXJte14tji3zlMNq+hd2rYUIgJBgB3fBmk=", conf.Interface.PrivateKey.String())
equal(t, uint16(51820), conf.Interface.ListenPort)
diff --git a/conf/path_windows.go b/conf/path_windows.go
index e9ff783a..0ff0a057 100644
--- a/conf/path_windows.go
+++ b/conf/path_windows.go
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package conf
@@ -15,8 +15,10 @@ import (
"golang.org/x/sys/windows"
)
-var cachedConfigFileDir string
-var cachedRootDir string
+var (
+ cachedConfigFileDir string
+ cachedRootDir string
+)
func tunnelConfigurationsDirectory() (string, error) {
if cachedConfigFileDir != "" {
@@ -27,7 +29,7 @@ func tunnelConfigurationsDirectory() (string, error) {
return "", err
}
c := filepath.Join(root, "Configurations")
- err = os.Mkdir(c, os.ModeDir|0700)
+ err = os.Mkdir(c, os.ModeDir|0o700)
if err != nil && !os.IsExist(err) {
return "", err
}
@@ -126,3 +128,11 @@ func RootDirectory(create bool) (string, error) {
cachedRootDir = data
return cachedRootDir, nil
}
+
+func LogFile(createRoot bool) (string, error) {
+ root, err := RootDirectory(createRoot)
+ if err != nil {
+ return "", err
+ }
+ return filepath.Join(root, "log.bin"), nil
+}
diff --git a/conf/store.go b/conf/store.go
index f6f450c6..02807b77 100644
--- a/conf/store.go
+++ b/conf/store.go
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package conf
@@ -14,8 +14,10 @@ import (
"golang.zx2c4.com/wireguard/windows/conf/dpapi"
)
-const configFileSuffix = ".conf.dpapi"
-const configFileUnencryptedSuffix = ".conf"
+const (
+ configFileSuffix = ".conf.dpapi"
+ configFileUnencryptedSuffix = ".conf"
+)
func ListConfigNames() ([]string, error) {
configFileDir, err := tunnelConfigurationsDirectory()
@@ -29,8 +31,8 @@ func ListConfigNames() ([]string, error) {
configs := make([]string, len(files))
i := 0
for _, file := range files {
- name := filepath.Base(file.Name())
- if len(name) <= len(configFileSuffix) || !strings.HasSuffix(name, configFileSuffix) {
+ name, err := NameFromPath(file.Name())
+ if err != nil {
continue
}
if !file.Type().IsRegular() {
@@ -40,11 +42,7 @@ func ListConfigNames() ([]string, error) {
if err != nil {
continue
}
- if info.Mode().Perm()&0444 == 0 {
- continue
- }
- name = strings.TrimSuffix(name, configFileSuffix)
- if !TunnelNameIsValid(name) {
+ if info.Mode().Perm()&0o444 == 0 {
continue
}
configs[i] = name
diff --git a/conf/store_test.go b/conf/store_test.go
index 3cec0035..3427a2b1 100644
--- a/conf/store_test.go
+++ b/conf/store_test.go
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package conf
@@ -17,7 +17,7 @@ func TestStorage(t *testing.T) {
return
}
- err = c.Save()
+ err = c.Save(true)
if err != nil {
t.Errorf("Unable to save config: %s", err.Error())
}
@@ -54,7 +54,11 @@ func TestStorage(t *testing.T) {
}
c.Interface.PrivateKey = *k
- err = c.Save()
+ err = c.Save(false)
+ if err == nil {
+ t.Error("Config disappeared or was unexpectedly overwritten")
+ }
+ err = c.Save(true)
if err != nil {
t.Errorf("Unable to save config a second time: %s", err.Error())
}
diff --git a/conf/storewatcher.go b/conf/storewatcher.go
index 94586c38..70a44add 100644
--- a/conf/storewatcher.go
+++ b/conf/storewatcher.go
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package conf
diff --git a/conf/storewatcher_windows.go b/conf/storewatcher_windows.go
index a12fb59b..0c4b74e7 100644
--- a/conf/storewatcher_windows.go
+++ b/conf/storewatcher_windows.go
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package conf
diff --git a/conf/writer.go b/conf/writer.go
index c786ec10..162962b5 100644
--- a/conf/writer.go
+++ b/conf/writer.go
@@ -1,13 +1,19 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package conf
import (
"fmt"
+ "net/netip"
"strings"
+ "unsafe"
+
+ "golang.org/x/sys/windows"
+ "golang.zx2c4.com/wireguard/windows/driver"
+ "golang.zx2c4.com/wireguard/windows/tunnel/winipcfg"
)
func (conf *Config) ToWgQuick() string {
@@ -53,6 +59,9 @@ func (conf *Config) ToWgQuick() string {
if len(conf.Interface.PostDown) > 0 {
output.WriteString(fmt.Sprintf("PostDown = %s\n", conf.Interface.PostDown))
}
+ if conf.Interface.TableOff {
+ output.WriteString("Table = off\n")
+ }
for _, peer := range conf.Peers {
output.WriteString("\n[Peer]\n")
@@ -82,43 +91,50 @@ func (conf *Config) ToWgQuick() string {
return output.String()
}
-func (conf *Config) ToUAPI() (uapi string, dnsErr error) {
- var output strings.Builder
- output.WriteString(fmt.Sprintf("private_key=%s\n", conf.Interface.PrivateKey.HexString()))
-
- if conf.Interface.ListenPort > 0 {
- output.WriteString(fmt.Sprintf("listen_port=%d\n", conf.Interface.ListenPort))
- }
-
- if len(conf.Peers) > 0 {
- output.WriteString("replace_peers=true\n")
+func (config *Config) ToDriverConfiguration() (*driver.Interface, uint32) {
+ preallocation := unsafe.Sizeof(driver.Interface{}) + uintptr(len(config.Peers))*unsafe.Sizeof(driver.Peer{})
+ for i := range config.Peers {
+ preallocation += uintptr(len(config.Peers[i].AllowedIPs)) * unsafe.Sizeof(driver.AllowedIP{})
}
-
- for _, peer := range conf.Peers {
- output.WriteString(fmt.Sprintf("public_key=%s\n", peer.PublicKey.HexString()))
-
- if !peer.PresharedKey.IsZero() {
- output.WriteString(fmt.Sprintf("preshared_key=%s\n", peer.PresharedKey.HexString()))
+ var c driver.ConfigBuilder
+ c.Preallocate(uint32(preallocation))
+ c.AppendInterface(&driver.Interface{
+ Flags: driver.InterfaceHasPrivateKey | driver.InterfaceHasListenPort,
+ ListenPort: config.Interface.ListenPort,
+ PrivateKey: config.Interface.PrivateKey,
+ PeerCount: uint32(len(config.Peers)),
+ })
+ for i := range config.Peers {
+ flags := driver.PeerHasPublicKey | driver.PeerHasPersistentKeepalive
+ if !config.Peers[i].PresharedKey.IsZero() {
+ flags |= driver.PeerHasPresharedKey
}
-
- if !peer.Endpoint.IsEmpty() {
- var resolvedIP string
- resolvedIP, dnsErr = resolveHostname(peer.Endpoint.Host)
- if dnsErr != nil {
- return
+ var endpoint winipcfg.RawSockaddrInet
+ if !config.Peers[i].Endpoint.IsEmpty() {
+ addr, err := netip.ParseAddr(config.Peers[i].Endpoint.Host)
+ if err == nil {
+ flags |= driver.PeerHasEndpoint
+ endpoint.SetAddrPort(netip.AddrPortFrom(addr, config.Peers[i].Endpoint.Port))
}
- resolvedEndpoint := Endpoint{resolvedIP, peer.Endpoint.Port}
- output.WriteString(fmt.Sprintf("endpoint=%s\n", resolvedEndpoint.String()))
}
-
- output.WriteString(fmt.Sprintf("persistent_keepalive_interval=%d\n", peer.PersistentKeepalive))
-
- if len(peer.AllowedIPs) > 0 {
- output.WriteString("replace_allowed_ips=true\n")
- for _, address := range peer.AllowedIPs {
- output.WriteString(fmt.Sprintf("allowed_ip=%s\n", address.String()))
+ c.AppendPeer(&driver.Peer{
+ Flags: flags,
+ PublicKey: config.Peers[i].PublicKey,
+ PresharedKey: config.Peers[i].PresharedKey,
+ PersistentKeepalive: config.Peers[i].PersistentKeepalive,
+ Endpoint: endpoint,
+ AllowedIPsCount: uint32(len(config.Peers[i].AllowedIPs)),
+ })
+ for j := range config.Peers[i].AllowedIPs {
+ a := &driver.AllowedIP{Cidr: uint8(config.Peers[i].AllowedIPs[j].Bits())}
+ copy(a.Address[:], config.Peers[i].AllowedIPs[j].Addr().AsSlice())
+ if config.Peers[i].AllowedIPs[j].Addr().Is4() {
+ a.AddressFamily = windows.AF_INET
+ } else if config.Peers[i].AllowedIPs[j].Addr().Is6() {
+ a.AddressFamily = windows.AF_INET6
}
+ c.AppendAllowedIP(a)
}
}
- return output.String(), nil
+ return c.Interface()
}
diff --git a/conf/zsyscall_windows.go b/conf/zsyscall_windows.go
deleted file mode 100644
index 783411f6..00000000
--- a/conf/zsyscall_windows.go
+++ /dev/null
@@ -1,50 +0,0 @@
-// Code generated by 'go generate'; DO NOT EDIT.
-
-package conf
-
-import (
- "syscall"
- "unsafe"
-
- "golang.org/x/sys/windows"
-)
-
-var _ unsafe.Pointer
-
-// Do the interface allocations only once for common
-// Errno values.
-const (
- errnoERROR_IO_PENDING = 997
-)
-
-var (
- errERROR_IO_PENDING error = syscall.Errno(errnoERROR_IO_PENDING)
- errERROR_EINVAL error = syscall.EINVAL
-)
-
-// errnoErr returns common boxed Errno values, to prevent
-// allocations at runtime.
-func errnoErr(e syscall.Errno) error {
- switch e {
- case 0:
- return errERROR_EINVAL
- case errnoERROR_IO_PENDING:
- return errERROR_IO_PENDING
- }
- // TODO: add more here, after collecting data on the common
- // error values see on Windows. (perhaps when running
- // all.bat?)
- return e
-}
-
-var (
- modwininet = windows.NewLazySystemDLL("wininet.dll")
-
- procInternetGetConnectedState = modwininet.NewProc("InternetGetConnectedState")
-)
-
-func internetGetConnectedState(flags *uint32, reserved uint32) (connected bool) {
- r0, _, _ := syscall.Syscall(procInternetGetConnectedState.Addr(), 2, uintptr(unsafe.Pointer(flags)), uintptr(reserved), 0)
- connected = r0 != 0
- return
-}
diff --git a/docs/adminregistry.md b/docs/adminregistry.md
index f7d04409..4289fb38 100644
--- a/docs/adminregistry.md
+++ b/docs/adminregistry.md
@@ -13,12 +13,16 @@ users belonging to the Network Configuration Operators builtin group
(S-1-5-32-556), with the following limitations for members of that group:
- Configurations are stripped of all public, private, and pre-shared keys;
- - No version update notifications are delivered;
+ - No version update popup notifications are shown, and updates are not permitted, though a tab still indicates the availability;
- Adding, removing, editing, importing, or exporting configurations is forbidden; and
- Quitting the manager is forbidden.
However, basic functionality such as starting and stopping tunnels remains intact.
+```
+> reg add HKLM\Software\WireGuard /v LimitedOperatorUI /t REG_DWORD /d 1 /f
+```
+
#### `HKLM\Software\WireGuard\DangerousScriptExecution`
When this key is set to `DWORD(1)`, the tunnel service will execute the commands
@@ -30,12 +34,6 @@ utmost trepidation. Rather than use `%i`, WireGuard for Windows instead sets the
environment variable `WIREGUARD_TUNNEL_NAME` to the name of the tunnel when
executing these scripts.
-#### `HKLM\Software\WireGuard\MultipleSimultaneousTunnels`
-
-When this key is set to `DWORD(1)`, the UI may start multiple tunnels at the
-same time; otherwise, an existing tunnel is stopped when a new one is started.
-Note that it is always possible, regardless of this key, to start multiple
-tunnels using `wireguard /installtunnelservice`; this controls only the semantics
-of tunnel start requests coming from the UI. If all goes well, this key will be
-removed and the logic of whether to stop existing tunnels will be based on
-overlapping routes, but for now, this key provides a manual override.
+```
+> reg add HKLM\Software\WireGuard /v DangerousScriptExecution /t REG_DWORD /d 1 /f
+```
diff --git a/docs/attacksurface.md b/docs/attacksurface.md
index 6dca229f..a495ba41 100644
--- a/docs/attacksurface.md
+++ b/docs/attacksurface.md
@@ -4,22 +4,21 @@ _This is an evolving document, describing currently known attack surface, a few
WireGuard for Windows consists of four components: a kernel driver, and three separate interacting userspace parts.
-### Wintun
+### WireGuardNT
-Wintun is a kernel driver. It exposes:
+WireGuardNT is a kernel driver. It exposes:
- A miniport driver to the ndis stack, meaning any process on the system that can access the network stack in a reasonable way can send and receive packets, hitting those related ndis handlers.
+ - A UDP port parsing WireGuard packets.
- There are also various ndis OID calls, accessible to certain users, which hit further code.
- - IOCTLs are added to the NDIS device file, and those IOCTLs are restricted to `SDDL_DEVOBJ_SYS_ALL`. The IOCTL allows userspace to register a pair of rings and event objects, which Wintun then locks the pages of with a double mapping and takes a reference to the event object. It parses the contents of the ring to send and receive layer 3 packets, each of which it minimally parses to determine IP family.
+ - A PNP and Close notifier added to the NDIS device file.
+ - IOCTLs are added to the NDIS device file, and those IOCTLs are restricted to `O:SYD:P(A;;FA;;;SY)(A;;FA;;;BA)S:(ML;;NWNRNX;;;HI)`. The IOCTL allows userspace to get and set configuration, adapter state, and read log messages from a ring buffer.
### Tunnel Service
-The tunnel service is a userspace service running as Local System, responsible for creating UDP sockets, creating Wintun adapters, and speaking the WireGuard protocol between the two. It exposes:
+The tunnel service is a userspace service running as Local System, responsible for creating WireGuardNT adapters and configuring them. It exposes:
- - A listening pipe in `\\.\pipe\ProtectedPrefix\Administrators\WireGuard\%s`, where `%s` is some basename of an already valid filename. Its DACL is set to `O:SYD:(A;;GA;;;SY)`. If the config file used by the tunnel service is not DPAPI-encrypted and it is owned by a SID other than "Local System" then an additional ACE is added giving that file owner SID access to the named pipe. This pipe gives access to private keys and allows for reconfiguration of the interface, as well as rebinding to different ports (below 1024, even). Clients who connect to the pipe run `GetSecurityInfo` to verify that it is owned by "Local System".
- - A global mutex is used for Wintun interface creation, with the same DACL as the pipe, but first CreatePrivateNamespace is called with a "Local System" SID.
- - It handles data from its two UDP sockets, accessible to the public Internet.
- - It handles data from Wintun, accessible to all users who can do anything with the network stack.
+ - A global mutex is used for WireGuardNT interface creation, with the same DACL as the pipe, but first CreatePrivateNamespace is called with a "Local System" SID.
- After some initial setup, it uses `AdjustTokenPrivileges` to remove all privileges, except for `SeLoadDriverPrivilege`, so that it can remove the interface when shutting down. This latter point is rather unfortunate, as `SeLoadDriverPrivilege` can be used for all sorts of interesting escalation. Future work includes forking an additional process or the like so that we can drop this from the main tunnel process.
### Manager Service
diff --git a/docs/buildrun.md b/docs/buildrun.md
index 265c4d68..3d356f2a 100644
--- a/docs/buildrun.md
+++ b/docs/buildrun.md
@@ -18,7 +18,7 @@ After you've built the application, run `amd64\wireguard.exe` or `x86\wireguard.
C:\Projects\wireguard-windows> amd64\wireguard.exe
```
-Since WireGuard requires the Wintun driver to be installed, and this generally requires a valid Microsoft signature, you may benefit from first installing a release of WireGuard for Windows from the official [wireguard.com](https://www.wireguard.com/install/) builds, which bundles a Microsoft-signed Wintun, and then subsequently run your own wireguard.exe. Alternatively, you can craft your own installer using the `quickinstall.bat` script.
+Since WireGuard requires a driver to be installed, and this generally requires a valid Microsoft signature, you may benefit from first installing a release of WireGuard for Windows from the official [wireguard.com](https://www.wireguard.com/install/) builds, which bundles a Microsoft-signed driver, and then subsequently run your own wireguard.exe. Alternatively, you can craft your own installer using the `quickinstall.bat` script.
### Optional: Localizing
@@ -60,8 +60,8 @@ C:\Projects\wireguard-windows\installer> build
Add a file called `sign.bat` in the root of this repository with these contents, or similar:
```text
-set SigningCertificate=DF98E075A012ED8C86FBCF14854B8F9555CB3D45
-set TimestampServer=http://timestamp.digicert.com
+set SigningCertificate=8BC932FDFF15B892E8364C49B383210810E4709D
+set TimestampServer=http://timestamp.entrust.net/rfc3161ts2
```
After, run the above `build` commands as usual, from a shell that has [`signtool.exe`](https://docs.microsoft.com/en-us/windows/desktop/SecCrypto/signtool) in its `PATH`, such as the Visual Studio 2017 command prompt.
diff --git a/docs/enterprise.md b/docs/enterprise.md
index 3f75ad14..8430cc99 100644
--- a/docs/enterprise.md
+++ b/docs/enterprise.md
@@ -8,7 +8,7 @@ While consumer users are generally directed toward [wireguard-installer.exe](htt
### Tunnel Service versus Manager Service and UI
-The "manager service" is responsible for displaying a UI on select users' desktops (in the system tray), and responding to requests from the UI to do things like add, remove, start, or stop tunnels. The "tunnel service" is a separate Windows service for each tunnel. These two services may be used together, or separately, as described below.
+The "manager service" is responsible for displaying a UI on select users' desktops (in the system tray), and responding to requests from the UI to do things like add, remove, start, or stop tunnels. The "tunnel service" is a separate Windows service for each tunnel. These two services may be used together, or separately, as described below. The various commands below will log errors and status to standard error, or, if standard error does not exist, to standard output.
### Tunnel Service
@@ -58,15 +58,24 @@ The manager service monitors `%ProgramFiles%\WireGuard\Data\Configurations\` for
The UI is started in the system tray of all builtin Administrators when the manager service is running. A limited UI may also be started in the system tray of all builtin Network Configuration Operators, if the correct registry key is set. [See `adminregistry.md` for information.](adminregistry.md)
-By default, the manager stops existing tunnels when starting new tunnels, so that only one tunnel service is running at a time. This behavior may be disabled if the correct registry key is set. [See `adminregistry.md` for information.](adminregistry.md)
+### Diagnostic Logs
+The manager and all tunnel services produce diagnostic logs in a shared ringbuffer-based log. This is shown in the UI, and also can be dumped to standard out using the command:
-### Diagnostic Logs
+```text
+> wireguard /dumplog > C:\path\to\diagnostic\log.txt
+```
+
+Alternatively, the log can be tailed continuously, for passing it to logging services:
-The manager and all tunnel services produce diagnostic logs in a shared ringbuffer-based log. This is shown in the UI, and also can be dumped to a file using the command:
+```text
+> wireguard /dumplog /tail | log-ingest
+```
+
+Or it can be monitored in PowerShell by piping to `select`:
```text
-> wireguard /dumplog C:\path\to\diagnostic\log.txt
+PS> wireguard /dumplog /tail | select
```
### Updates
@@ -74,13 +83,31 @@ The manager and all tunnel services produce diagnostic logs in a shared ringbuff
Administrators are notified of updates within the UI and can update from within the UI, but updates can also be invoked at the command line using the command:
```text
-> wireguard /update C:\path\to\update\log.txt
+> wireguard /update
+```
+
+Or, to log the status of that command:
+
+```text
+> wireguard /update 2> C:\path\to\update\log.txt
+```
+
+One could have Task Scheduler run it daily at 3am:
+
+```text
+> schtasks /create /f /ru SYSTEM /sc daily /tn "WireGuard Update" /tr "%PROGRAMFILES%\WireGuard\wireguard.exe /update" /st 03:00
```
-### Wintun Adapters
+### Driver Removal
+
+The tunnel service creates a network adapter at startup and destroys it at shutdown. If there are no more network adapters, the driver may be removed with:
+
+```text
+> wireguard /removedriver
+```
-The tunnel service creates a Wintun adapter at startup and destroys it at shutdown. It may be desirable, however, to remove all Wintun adapters created in WireGuard's pool and uninstall the driver if no other applications are using Wintun. This can be accomplished using the command:
+Or, to log the status of that command:
```text
-> wireguard /removealladapters C:\path\to\removal\log.txt
+> wireguard /removedriver 2> C:\path\to\removal\log.txt
```
diff --git a/docs/netquirk.md b/docs/netquirk.md
index 1fe2ad72..d53c8cdb 100644
--- a/docs/netquirk.md
+++ b/docs/netquirk.md
@@ -4,7 +4,7 @@ As part of setting up a WireGuard tunnel, the tunnel service also sets up variou
### Routing
-The tunnel service takes all the allowed IPs from each peer, deduplicates them, and adds them to the routes for the WireGuard interface. The service then monitors which interface on the system has a default route (a route with a `/0` CIDR) that is not the WireGuard interface itself, and it uses the [`IP_UNICAST_IF` socket option](https://docs.microsoft.com/en-us/windows/win32/winsock/ipproto-ip-socket-options) to bind WireGuard's UDP packets to that default route interface. If no MTU has been specified in the configuration, it also sets the MTU of the WireGuard interface to be 80 less than the MTU of that default route interface. If no default route interface can be found, then those outgoing packets are blackholed. If WireGuard packets would ordinarily be routed over a non-default route interface, the use of `IP_UNICAST_IF` forces the packets to, in fact, go over the default route interface. This is problematic, but at this moment, Microsoft has not provided a viable workaround. If any allowed IPs are a `/0`, then the interface is given a `0` metric and Windows' [automatic metric logic](https://docs.microsoft.com/en-us/troubleshoot/windows-server/networking/automatic-metric-for-ipv4-routes) is disabled.
+The tunnel service takes all the allowed IPs from each peer, deduplicates them, and adds them to the routes for the WireGuard interface. The service then monitors which interface on the system has a default route (a route with a `/0` CIDR) that is not the WireGuard interface itself, and, if no MTU has been specified in the configuration, it sets the MTU of the WireGuard interface to be 80 less than the MTU of that default route interface. WireGuardNT also monitors the routing table and determines the outgoing route that does not loopback to itself, and then sends each packet using `IP_PKTINFO`/`IPV6_PKTINFO`. It keeps track of the incoming interface and source address for received packets, and always replies to the sender in that way.
### Firewall Considerations for `/0` Allowed IPs
@@ -30,4 +30,4 @@ Windows assigns a unique GUID to each new WireGuard adapter. The application tak
### Adapter Lifetime
-WireGuard's Wintun adapter is created dynamically when a tunnel is started and destroyed when a tunnel is stopped. This means that additional filters, address families, or protocols should be bound to the adapter programmatically, possibly through use of dangerous script execution in thet configuration file or by way of automatic NDIS layer binding.
+WireGuard's network adapter is created dynamically when a tunnel is started and destroyed when a tunnel is stopped. This means that additional filters, address families, or protocols should be bound to the adapter programmatically, possibly through use of dangerous script execution in the configuration file or by way of automatic NDIS layer binding.
diff --git a/driver/configuration_windows.go b/driver/configuration_windows.go
new file mode 100644
index 00000000..d838dcf2
--- /dev/null
+++ b/driver/configuration_windows.go
@@ -0,0 +1,183 @@
+/* SPDX-License-Identifier: MIT
+ *
+ * Copyright (C) 2017-2022 WireGuard LLC. All Rights Reserved.
+ */
+
+package driver
+
+import (
+ "syscall"
+ "unsafe"
+
+ "golang.org/x/sys/windows"
+ "golang.zx2c4.com/wireguard/windows/tunnel/winipcfg"
+)
+
+type AdapterState uint32
+
+const (
+ AdapterStateDown AdapterState = 0
+ AdapterStateUp AdapterState = 1
+)
+
+type AllowedIP struct {
+ Address [16]byte
+ AddressFamily winipcfg.AddressFamily
+ Cidr uint8
+ _ [4]byte
+}
+
+type PeerFlag uint32
+
+const (
+ PeerHasPublicKey PeerFlag = 1 << 0
+ PeerHasPresharedKey PeerFlag = 1 << 1
+ PeerHasPersistentKeepalive PeerFlag = 1 << 2
+ PeerHasEndpoint PeerFlag = 1 << 3
+ PeerReplaceAllowedIPs PeerFlag = 1 << 5
+ PeerRemove PeerFlag = 1 << 6
+ PeerUpdateOnly PeerFlag = 1 << 7
+)
+
+type Peer struct {
+ Flags PeerFlag
+ _ uint32
+ PublicKey [32]byte
+ PresharedKey [32]byte
+ PersistentKeepalive uint16
+ _ uint16
+ Endpoint winipcfg.RawSockaddrInet
+ TxBytes uint64
+ RxBytes uint64
+ LastHandshake uint64
+ AllowedIPsCount uint32
+ _ [4]byte
+}
+
+type InterfaceFlag uint32
+
+const (
+ InterfaceHasPublicKey InterfaceFlag = 1 << 0
+ InterfaceHasPrivateKey InterfaceFlag = 1 << 1
+ InterfaceHasListenPort InterfaceFlag = 1 << 2
+ InterfaceReplacePeers InterfaceFlag = 1 << 3
+)
+
+type Interface struct {
+ Flags InterfaceFlag
+ ListenPort uint16
+ PrivateKey [32]byte
+ PublicKey [32]byte
+ PeerCount uint32
+ _ [4]byte
+}
+
+var (
+ procWireGuardSetAdapterState = modwireguard.NewProc("WireGuardSetAdapterState")
+ procWireGuardGetAdapterState = modwireguard.NewProc("WireGuardGetAdapterState")
+ procWireGuardSetConfiguration = modwireguard.NewProc("WireGuardSetConfiguration")
+ procWireGuardGetConfiguration = modwireguard.NewProc("WireGuardGetConfiguration")
+)
+
+// SetAdapterState sets the adapter either Up or Down.
+func (wireguard *Adapter) SetAdapterState(adapterState AdapterState) (err error) {
+ r0, _, e1 := syscall.SyscallN(procWireGuardSetAdapterState.Addr(), wireguard.handle, uintptr(adapterState))
+ if r0 == 0 {
+ err = e1
+ }
+ return
+}
+
+// AdapterState returns the current state of the adapter.
+func (wireguard *Adapter) AdapterState() (adapterState AdapterState, err error) {
+ r0, _, e1 := syscall.SyscallN(procWireGuardGetAdapterState.Addr(), wireguard.handle, uintptr(unsafe.Pointer(&adapterState)))
+ if r0 == 0 {
+ err = e1
+ }
+ return
+}
+
+// SetConfiguration sets the adapter configuration.
+func (wireguard *Adapter) SetConfiguration(interfaze *Interface, size uint32) (err error) {
+ r0, _, e1 := syscall.SyscallN(procWireGuardSetConfiguration.Addr(), wireguard.handle, uintptr(unsafe.Pointer(interfaze)), uintptr(size))
+ if r0 == 0 {
+ err = e1
+ }
+ return
+}
+
+// Configuration gets the adapter configuration.
+func (wireguard *Adapter) Configuration() (interfaze *Interface, err error) {
+ size := wireguard.lastGetGuessSize
+ if size == 0 {
+ size = 512
+ }
+ for {
+ buf := make([]byte, size)
+ r0, _, e1 := syscall.SyscallN(procWireGuardGetConfiguration.Addr(), wireguard.handle, uintptr(unsafe.Pointer(&buf[0])), uintptr(unsafe.Pointer(&size)))
+ if r0 != 0 {
+ wireguard.lastGetGuessSize = size
+ return (*Interface)(unsafe.Pointer(&buf[0])), nil
+ }
+ if e1 != windows.ERROR_MORE_DATA {
+ return nil, e1
+ }
+ }
+}
+
+// FirstPeer returns the first peer attached to the interface.
+func (interfaze *Interface) FirstPeer() *Peer {
+ return (*Peer)(unsafe.Add(unsafe.Pointer(interfaze), unsafe.Sizeof(*interfaze)))
+}
+
+// NextPeer returns the subsequent peer of the current one.
+func (peer *Peer) NextPeer() *Peer {
+ return (*Peer)(unsafe.Pointer(uintptr(unsafe.Pointer(peer)) + unsafe.Sizeof(*peer) + uintptr(peer.AllowedIPsCount)*unsafe.Sizeof(AllowedIP{})))
+}
+
+// FirstAllowedIP returns the first allowed IP attached to the peer.
+func (peer *Peer) FirstAllowedIP() *AllowedIP {
+ return (*AllowedIP)(unsafe.Add(unsafe.Pointer(peer), unsafe.Sizeof(*peer)))
+}
+
+// NextAllowedIP returns the subsequent allowed IP of the current one.
+func (allowedIP *AllowedIP) NextAllowedIP() *AllowedIP {
+ return (*AllowedIP)(unsafe.Add(unsafe.Pointer(allowedIP), unsafe.Sizeof(*allowedIP)))
+}
+
+type ConfigBuilder struct {
+ buffer []byte
+}
+
+// Preallocate reserves memory in the config builder to reduce allocations of append operations.
+func (builder *ConfigBuilder) Preallocate(size uint32) {
+ if builder.buffer == nil {
+ builder.buffer = make([]byte, 0, size)
+ }
+}
+
+// AppendInterface appends an interface to the building configuration. This should be called first.
+func (builder *ConfigBuilder) AppendInterface(interfaze *Interface) {
+ newBytes := unsafe.Slice((*byte)(unsafe.Pointer(interfaze)), unsafe.Sizeof(*interfaze))
+ builder.buffer = append(builder.buffer, newBytes...)
+}
+
+// AppendPeer appends a peer to the building configuration. This should be called after an interface has been added.
+func (builder *ConfigBuilder) AppendPeer(peer *Peer) {
+ newBytes := unsafe.Slice((*byte)(unsafe.Pointer(peer)), unsafe.Sizeof(*peer))
+ builder.buffer = append(builder.buffer, newBytes...)
+}
+
+// AppendAllowedIP appends an allowed IP to the building configuration. This should be called after a peer has been added.
+func (builder *ConfigBuilder) AppendAllowedIP(allowedIP *AllowedIP) {
+ newBytes := unsafe.Slice((*byte)(unsafe.Pointer(allowedIP)), unsafe.Sizeof(*allowedIP))
+ builder.buffer = append(builder.buffer, newBytes...)
+}
+
+// Interface assembles the configuration and returns the interface and length to be passed to SetConfiguration.
+func (builder *ConfigBuilder) Interface() (*Interface, uint32) {
+ if builder.buffer == nil {
+ return nil, 0
+ }
+ return (*Interface)(unsafe.Pointer(&builder.buffer[0])), uint32(len(builder.buffer))
+}
diff --git a/driver/dll_fromfile_windows.go b/driver/dll_fromfile_windows.go
new file mode 100644
index 00000000..b815b4c0
--- /dev/null
+++ b/driver/dll_fromfile_windows.go
@@ -0,0 +1,56 @@
+//go:build !load_wgnt_from_rsrc
+
+/* SPDX-License-Identifier: MIT
+ *
+ * Copyright (C) 2019 WireGuard LLC. All Rights Reserved.
+ */
+
+package driver
+
+import (
+ "fmt"
+ "sync"
+ "sync/atomic"
+ "unsafe"
+
+ "golang.org/x/sys/windows"
+)
+
+type lazyDLL struct {
+ Name string
+ Base windows.Handle
+ mu sync.Mutex
+ module windows.Handle
+ onLoad func(d *lazyDLL)
+}
+
+func (d *lazyDLL) Load() error {
+ if atomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer(&d.module))) != nil {
+ return nil
+ }
+ d.mu.Lock()
+ defer d.mu.Unlock()
+ if d.module != 0 {
+ return nil
+ }
+
+ const (
+ LOAD_LIBRARY_SEARCH_APPLICATION_DIR = 0x00000200
+ LOAD_LIBRARY_SEARCH_SYSTEM32 = 0x00000800
+ )
+ module, err := windows.LoadLibraryEx(d.Name, 0, LOAD_LIBRARY_SEARCH_APPLICATION_DIR|LOAD_LIBRARY_SEARCH_SYSTEM32)
+ if err != nil {
+ return fmt.Errorf("Unable to load library: %w", err)
+ }
+ d.Base = module
+
+ atomic.StorePointer((*unsafe.Pointer)(unsafe.Pointer(&d.module)), unsafe.Pointer(module))
+ if d.onLoad != nil {
+ d.onLoad(d)
+ }
+ return nil
+}
+
+func (p *lazyProc) nameToAddr() (uintptr, error) {
+ return windows.GetProcAddress(p.dll.module, p.Name)
+}
diff --git a/driver/dll_fromrsrc_windows.go b/driver/dll_fromrsrc_windows.go
new file mode 100644
index 00000000..65b1cfce
--- /dev/null
+++ b/driver/dll_fromrsrc_windows.go
@@ -0,0 +1,62 @@
+//go:build load_wgnt_from_rsrc
+
+/* SPDX-License-Identifier: MIT
+ *
+ * Copyright (C) 2019 WireGuard LLC. All Rights Reserved.
+ */
+
+package driver
+
+import (
+ "fmt"
+ "sync"
+ "sync/atomic"
+ "unsafe"
+
+ "golang.org/x/sys/windows"
+ "golang.zx2c4.com/wireguard/windows/driver/memmod"
+)
+
+type lazyDLL struct {
+ Name string
+ Base windows.Handle
+ mu sync.Mutex
+ module *memmod.Module
+ onLoad func(d *lazyDLL)
+}
+
+func (d *lazyDLL) Load() error {
+ if atomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer(&d.module))) != nil {
+ return nil
+ }
+ d.mu.Lock()
+ defer d.mu.Unlock()
+ if d.module != nil {
+ return nil
+ }
+
+ const ourModule windows.Handle = 0
+ resInfo, err := windows.FindResource(ourModule, d.Name, windows.RT_RCDATA)
+ if err != nil {
+ return fmt.Errorf("Unable to find \"%v\" RCDATA resource: %w", d.Name, err)
+ }
+ data, err := windows.LoadResourceData(ourModule, resInfo)
+ if err != nil {
+ return fmt.Errorf("Unable to load resource: %w", err)
+ }
+ module, err := memmod.LoadLibrary(data)
+ if err != nil {
+ return fmt.Errorf("Unable to load library: %w", err)
+ }
+ d.Base = windows.Handle(module.BaseAddr())
+
+ atomic.StorePointer((*unsafe.Pointer)(unsafe.Pointer(&d.module)), unsafe.Pointer(module))
+ if d.onLoad != nil {
+ d.onLoad(d)
+ }
+ return nil
+}
+
+func (p *lazyProc) nameToAddr() (uintptr, error) {
+ return p.dll.module.ProcAddressByName(p.Name)
+}
diff --git a/driver/dll_windows.go b/driver/dll_windows.go
new file mode 100644
index 00000000..5dcb849e
--- /dev/null
+++ b/driver/dll_windows.go
@@ -0,0 +1,91 @@
+/* SPDX-License-Identifier: MIT
+ *
+ * Copyright (C) 2017-2022 WireGuard LLC. All Rights Reserved.
+ */
+
+package driver
+
+import (
+ "fmt"
+ "sync"
+ "sync/atomic"
+ "unsafe"
+
+ "golang.org/x/sys/windows"
+)
+
+func newLazyDLL(name string, onLoad func(d *lazyDLL)) *lazyDLL {
+ return &lazyDLL{Name: name, onLoad: onLoad}
+}
+
+func (d *lazyDLL) NewProc(name string) *lazyProc {
+ return &lazyProc{dll: d, Name: name}
+}
+
+type lazyProc struct {
+ Name string
+ mu sync.Mutex
+ dll *lazyDLL
+ addr uintptr
+}
+
+func (p *lazyProc) Find() error {
+ if atomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer(&p.addr))) != nil {
+ return nil
+ }
+ p.mu.Lock()
+ defer p.mu.Unlock()
+ if p.addr != 0 {
+ return nil
+ }
+
+ err := p.dll.Load()
+ if err != nil {
+ return fmt.Errorf("Error loading %v DLL: %w", p.dll.Name, err)
+ }
+ addr, err := p.nameToAddr()
+ if err != nil {
+ return fmt.Errorf("Error getting %v address: %w", p.Name, err)
+ }
+
+ atomic.StorePointer((*unsafe.Pointer)(unsafe.Pointer(&p.addr)), unsafe.Pointer(addr))
+ return nil
+}
+
+func (p *lazyProc) Addr() uintptr {
+ err := p.Find()
+ if err != nil {
+ panic(err)
+ }
+ return p.addr
+}
+
+// Version returns the version of the driver DLL.
+func Version() string {
+ if modwireguard.Load() != nil {
+ return "unknown"
+ }
+ resInfo, err := windows.FindResource(modwireguard.Base, windows.ResourceID(1), windows.RT_VERSION)
+ if err != nil {
+ return "unknown"
+ }
+ data, err := windows.LoadResourceData(modwireguard.Base, resInfo)
+ if err != nil {
+ return "unknown"
+ }
+
+ var fixedInfo *windows.VS_FIXEDFILEINFO
+ fixedInfoLen := uint32(unsafe.Sizeof(*fixedInfo))
+ err = windows.VerQueryValue(unsafe.Pointer(&data[0]), `\`, unsafe.Pointer(&fixedInfo), &fixedInfoLen)
+ if err != nil {
+ return "unknown"
+ }
+ version := fmt.Sprintf("%d.%d", (fixedInfo.FileVersionMS>>16)&0xff, (fixedInfo.FileVersionMS>>0)&0xff)
+ if nextNibble := (fixedInfo.FileVersionLS >> 16) & 0xff; nextNibble != 0 {
+ version += fmt.Sprintf(".%d", nextNibble)
+ }
+ if nextNibble := (fixedInfo.FileVersionLS >> 0) & 0xff; nextNibble != 0 {
+ version += fmt.Sprintf(".%d", nextNibble)
+ }
+ return version
+}
diff --git a/driver/driver_windows.go b/driver/driver_windows.go
new file mode 100644
index 00000000..462c3a30
--- /dev/null
+++ b/driver/driver_windows.go
@@ -0,0 +1,170 @@
+/* SPDX-License-Identifier: MIT
+ *
+ * Copyright (C) 2017-2022 WireGuard LLC. All Rights Reserved.
+ */
+
+package driver
+
+import (
+ "log"
+ "runtime"
+ "syscall"
+ "unsafe"
+
+ "golang.org/x/sys/windows"
+ "golang.zx2c4.com/wireguard/windows/tunnel/winipcfg"
+)
+
+type loggerLevel int
+
+const (
+ logInfo loggerLevel = iota
+ logWarn
+ logErr
+)
+
+const AdapterNameMax = 128
+
+type Adapter struct {
+ handle uintptr
+ lastGetGuessSize uint32
+}
+
+var (
+ modwireguard = newLazyDLL("wireguard.dll", setupLogger)
+ procWireGuardCreateAdapter = modwireguard.NewProc("WireGuardCreateAdapter")
+ procWireGuardOpenAdapter = modwireguard.NewProc("WireGuardOpenAdapter")
+ procWireGuardCloseAdapter = modwireguard.NewProc("WireGuardCloseAdapter")
+ procWireGuardDeleteDriver = modwireguard.NewProc("WireGuardDeleteDriver")
+ procWireGuardGetAdapterLUID = modwireguard.NewProc("WireGuardGetAdapterLUID")
+ procWireGuardGetRunningDriverVersion = modwireguard.NewProc("WireGuardGetRunningDriverVersion")
+ procWireGuardSetAdapterLogging = modwireguard.NewProc("WireGuardSetAdapterLogging")
+)
+
+type TimestampedWriter interface {
+ WriteWithTimestamp(p []byte, ts int64) (n int, err error)
+}
+
+func logMessage(level loggerLevel, timestamp uint64, msg *uint16) int {
+ if tw, ok := log.Default().Writer().(TimestampedWriter); ok {
+ tw.WriteWithTimestamp([]byte(log.Default().Prefix()+windows.UTF16PtrToString(msg)), (int64(timestamp)-116444736000000000)*100)
+ } else {
+ log.Println(windows.UTF16PtrToString(msg))
+ }
+ return 0
+}
+
+func setupLogger(dll *lazyDLL) {
+ var callback uintptr
+ if runtime.GOARCH == "386" {
+ callback = windows.NewCallback(func(level loggerLevel, timestampLow, timestampHigh uint32, msg *uint16) int {
+ return logMessage(level, uint64(timestampHigh)<<32|uint64(timestampLow), msg)
+ })
+ } else if runtime.GOARCH == "arm" {
+ callback = windows.NewCallback(func(level loggerLevel, _, timestampLow, timestampHigh uint32, msg *uint16) int {
+ return logMessage(level, uint64(timestampHigh)<<32|uint64(timestampLow), msg)
+ })
+ } else if runtime.GOARCH == "amd64" || runtime.GOARCH == "arm64" {
+ callback = windows.NewCallback(logMessage)
+ }
+ syscall.SyscallN(dll.NewProc("WireGuardSetLogger").Addr(), callback)
+}
+
+func closeAdapter(wireguard *Adapter) {
+ syscall.SyscallN(procWireGuardCloseAdapter.Addr(), wireguard.handle)
+}
+
+// CreateAdapter creates a WireGuard adapter. name is the cosmetic name of the adapter.
+// tunnelType represents the type of adapter and should be "WireGuard". requestedGUID is
+// the GUID of the created network adapter, which then influences NLA generation
+// deterministically. If it is set to nil, the GUID is chosen by the system at random,
+// and hence a new NLA entry is created for each new adapter.
+func CreateAdapter(name, tunnelType string, requestedGUID *windows.GUID) (wireguard *Adapter, err error) {
+ var name16 *uint16
+ name16, err = windows.UTF16PtrFromString(name)
+ if err != nil {
+ return
+ }
+ var tunnelType16 *uint16
+ tunnelType16, err = windows.UTF16PtrFromString(tunnelType)
+ if err != nil {
+ return
+ }
+ r0, _, e1 := syscall.SyscallN(procWireGuardCreateAdapter.Addr(), uintptr(unsafe.Pointer(name16)), uintptr(unsafe.Pointer(tunnelType16)), uintptr(unsafe.Pointer(requestedGUID)))
+ if r0 == 0 {
+ err = e1
+ return
+ }
+ wireguard = &Adapter{handle: r0}
+ runtime.SetFinalizer(wireguard, closeAdapter)
+ return
+}
+
+// OpenAdapter opens an existing WireGuard adapter by name.
+func OpenAdapter(name string) (wireguard *Adapter, err error) {
+ var name16 *uint16
+ name16, err = windows.UTF16PtrFromString(name)
+ if err != nil {
+ return
+ }
+ r0, _, e1 := syscall.SyscallN(procWireGuardOpenAdapter.Addr(), uintptr(unsafe.Pointer(name16)))
+ if r0 == 0 {
+ err = e1
+ return
+ }
+ wireguard = &Adapter{handle: r0}
+ runtime.SetFinalizer(wireguard, closeAdapter)
+ return
+}
+
+// Close closes a WireGuard adapter.
+func (wireguard *Adapter) Close() (err error) {
+ runtime.SetFinalizer(wireguard, nil)
+ r1, _, e1 := syscall.SyscallN(procWireGuardCloseAdapter.Addr(), wireguard.handle)
+ if r1 == 0 {
+ err = e1
+ }
+ return
+}
+
+// Uninstall removes the driver from the system if no drivers are currently in use.
+func Uninstall() (err error) {
+ r1, _, e1 := syscall.SyscallN(procWireGuardDeleteDriver.Addr())
+ if r1 == 0 {
+ err = e1
+ }
+ return
+}
+
+type AdapterLogState uint32
+
+const (
+ AdapterLogOff AdapterLogState = 0
+ AdapterLogOn AdapterLogState = 1
+ AdapterLogOnWithPrefix AdapterLogState = 2
+)
+
+// SetLogging enables or disables logging on the WireGuard adapter.
+func (wireguard *Adapter) SetLogging(logState AdapterLogState) (err error) {
+ r1, _, e1 := syscall.SyscallN(procWireGuardSetAdapterLogging.Addr(), wireguard.handle, uintptr(logState))
+ if r1 == 0 {
+ err = e1
+ }
+ return
+}
+
+// RunningVersion returns the version of the loaded driver.
+func RunningVersion() (version uint32, err error) {
+ r0, _, e1 := syscall.SyscallN(procWireGuardGetRunningDriverVersion.Addr())
+ version = uint32(r0)
+ if version == 0 {
+ err = e1
+ }
+ return
+}
+
+// LUID returns the LUID of the adapter.
+func (wireguard *Adapter) LUID() (luid winipcfg.LUID) {
+ syscall.SyscallN(procWireGuardGetAdapterLUID.Addr(), wireguard.handle, uintptr(unsafe.Pointer(&luid)))
+ return
+}
diff --git a/driver/memmod/memmod_windows.go b/driver/memmod/memmod_windows.go
new file mode 100644
index 00000000..7b54282a
--- /dev/null
+++ b/driver/memmod/memmod_windows.go
@@ -0,0 +1,698 @@
+/* SPDX-License-Identifier: MIT
+ *
+ * Copyright (C) 2017-2022 WireGuard LLC. All Rights Reserved.
+ */
+
+package memmod
+
+import (
+ "errors"
+ "fmt"
+ "strings"
+ "sync"
+ "syscall"
+ "unsafe"
+
+ "golang.org/x/sys/windows"
+)
+
+type addressList struct {
+ next *addressList
+ address uintptr
+}
+
+func (head *addressList) free() {
+ for node := head; node != nil; node = node.next {
+ windows.VirtualFree(node.address, 0, windows.MEM_RELEASE)
+ }
+}
+
+type Module struct {
+ headers *IMAGE_NT_HEADERS
+ codeBase uintptr
+ modules []windows.Handle
+ initialized bool
+ isDLL bool
+ isRelocated bool
+ nameExports map[string]uint16
+ entry uintptr
+ blockedMemory *addressList
+}
+
+func (module *Module) BaseAddr() uintptr {
+ return module.codeBase
+}
+
+func (module *Module) headerDirectory(idx int) *IMAGE_DATA_DIRECTORY {
+ return &module.headers.OptionalHeader.DataDirectory[idx]
+}
+
+func (module *Module) copySections(address, size uintptr, oldHeaders *IMAGE_NT_HEADERS) error {
+ sections := module.headers.Sections()
+ for i := range sections {
+ if sections[i].SizeOfRawData == 0 {
+ // Section doesn't contain data in the dll itself, but may define uninitialized data.
+ sectionSize := oldHeaders.OptionalHeader.SectionAlignment
+ if sectionSize == 0 {
+ continue
+ }
+ dest, err := windows.VirtualAlloc(module.codeBase+uintptr(sections[i].VirtualAddress),
+ uintptr(sectionSize),
+ windows.MEM_COMMIT,
+ windows.PAGE_READWRITE)
+ if err != nil {
+ return fmt.Errorf("Error allocating section: %w", err)
+ }
+
+ // Always use position from file to support alignments smaller than page size (allocation above will align to page size).
+ dest = module.codeBase + uintptr(sections[i].VirtualAddress)
+ // NOTE: On 64bit systems we truncate to 32bit here but expand again later when "PhysicalAddress" is used.
+ sections[i].SetPhysicalAddress((uint32)(dest & 0xffffffff))
+ dst := unsafe.Slice((*byte)(a2p(dest)), sectionSize)
+ for j := range dst {
+ dst[j] = 0
+ }
+ continue
+ }
+
+ if size < uintptr(sections[i].PointerToRawData+sections[i].SizeOfRawData) {
+ return errors.New("Incomplete section")
+ }
+
+ // Commit memory block and copy data from dll.
+ dest, err := windows.VirtualAlloc(module.codeBase+uintptr(sections[i].VirtualAddress),
+ uintptr(sections[i].SizeOfRawData),
+ windows.MEM_COMMIT,
+ windows.PAGE_READWRITE)
+ if err != nil {
+ return fmt.Errorf("Error allocating memory block: %w", err)
+ }
+
+ // Always use position from file to support alignments smaller than page size (allocation above will align to page size).
+ memcpy(
+ module.codeBase+uintptr(sections[i].VirtualAddress),
+ address+uintptr(sections[i].PointerToRawData),
+ uintptr(sections[i].SizeOfRawData))
+ // NOTE: On 64bit systems we truncate to 32bit here but expand again later when "PhysicalAddress" is used.
+ sections[i].SetPhysicalAddress((uint32)(dest & 0xffffffff))
+ }
+
+ return nil
+}
+
+func (module *Module) realSectionSize(section *IMAGE_SECTION_HEADER) uintptr {
+ size := section.SizeOfRawData
+ if size != 0 {
+ return uintptr(size)
+ }
+ if (section.Characteristics & IMAGE_SCN_CNT_INITIALIZED_DATA) != 0 {
+ return uintptr(module.headers.OptionalHeader.SizeOfInitializedData)
+ }
+ if (section.Characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA) != 0 {
+ return uintptr(module.headers.OptionalHeader.SizeOfUninitializedData)
+ }
+ return 0
+}
+
+type sectionFinalizeData struct {
+ address uintptr
+ alignedAddress uintptr
+ size uintptr
+ characteristics uint32
+ last bool
+}
+
+func (module *Module) finalizeSection(sectionData *sectionFinalizeData) error {
+ if sectionData.size == 0 {
+ return nil
+ }
+
+ if (sectionData.characteristics & IMAGE_SCN_MEM_DISCARDABLE) != 0 {
+ // Section is not needed any more and can safely be freed.
+ if sectionData.address == sectionData.alignedAddress &&
+ (sectionData.last ||
+ (sectionData.size%uintptr(module.headers.OptionalHeader.SectionAlignment)) == 0) {
+ // Only allowed to decommit whole pages.
+ windows.VirtualFree(sectionData.address, sectionData.size, windows.MEM_DECOMMIT)
+ }
+ return nil
+ }
+
+ // determine protection flags based on characteristics
+ ProtectionFlags := [8]uint32{
+ windows.PAGE_NOACCESS, // not writeable, not readable, not executable
+ windows.PAGE_EXECUTE, // not writeable, not readable, executable
+ windows.PAGE_READONLY, // not writeable, readable, not executable
+ windows.PAGE_EXECUTE_READ, // not writeable, readable, executable
+ windows.PAGE_WRITECOPY, // writeable, not readable, not executable
+ windows.PAGE_EXECUTE_WRITECOPY, // writeable, not readable, executable
+ windows.PAGE_READWRITE, // writeable, readable, not executable
+ windows.PAGE_EXECUTE_READWRITE, // writeable, readable, executable
+ }
+ protect := ProtectionFlags[sectionData.characteristics>>29]
+ if (sectionData.characteristics & IMAGE_SCN_MEM_NOT_CACHED) != 0 {
+ protect |= windows.PAGE_NOCACHE
+ }
+
+ // Change memory access flags.
+ var oldProtect uint32
+ err := windows.VirtualProtect(sectionData.address, sectionData.size, protect, &oldProtect)
+ if err != nil {
+ return fmt.Errorf("Error protecting memory page: %w", err)
+ }
+
+ return nil
+}
+
+func (module *Module) registerExceptionHandlers() {
+ directory := module.headerDirectory(IMAGE_DIRECTORY_ENTRY_EXCEPTION)
+ if directory.Size == 0 || directory.VirtualAddress == 0 {
+ return
+ }
+ runtimeFuncs := (*windows.RUNTIME_FUNCTION)(unsafe.Pointer(module.codeBase + uintptr(directory.VirtualAddress)))
+ windows.RtlAddFunctionTable(runtimeFuncs, uint32(uintptr(directory.Size)/unsafe.Sizeof(*runtimeFuncs)), module.codeBase)
+}
+
+func (module *Module) finalizeSections() error {
+ sections := module.headers.Sections()
+ imageOffset := module.headers.OptionalHeader.imageOffset()
+ sectionData := sectionFinalizeData{}
+ sectionData.address = uintptr(sections[0].PhysicalAddress()) | imageOffset
+ sectionData.alignedAddress = alignDown(sectionData.address, uintptr(module.headers.OptionalHeader.SectionAlignment))
+ sectionData.size = module.realSectionSize(&sections[0])
+ sections[0].SetVirtualSize(uint32(sectionData.size))
+ sectionData.characteristics = sections[0].Characteristics
+
+ // Loop through all sections and change access flags.
+ for i := uint16(1); i < module.headers.FileHeader.NumberOfSections; i++ {
+ sectionAddress := uintptr(sections[i].PhysicalAddress()) | imageOffset
+ alignedAddress := alignDown(sectionAddress, uintptr(module.headers.OptionalHeader.SectionAlignment))
+ sectionSize := module.realSectionSize(&sections[i])
+ sections[i].SetVirtualSize(uint32(sectionSize))
+ // Combine access flags of all sections that share a page.
+ // TODO: We currently share flags of a trailing large section with the page of a first small section. This should be optimized.
+ if sectionData.alignedAddress == alignedAddress || sectionData.address+sectionData.size > alignedAddress {
+ // Section shares page with previous.
+ if (sections[i].Characteristics&IMAGE_SCN_MEM_DISCARDABLE) == 0 || (sectionData.characteristics&IMAGE_SCN_MEM_DISCARDABLE) == 0 {
+ sectionData.characteristics = (sectionData.characteristics | sections[i].Characteristics) &^ IMAGE_SCN_MEM_DISCARDABLE
+ } else {
+ sectionData.characteristics |= sections[i].Characteristics
+ }
+ sectionData.size = sectionAddress + sectionSize - sectionData.address
+ continue
+ }
+
+ err := module.finalizeSection(&sectionData)
+ if err != nil {
+ return fmt.Errorf("Error finalizing section: %w", err)
+ }
+ sectionData.address = sectionAddress
+ sectionData.alignedAddress = alignedAddress
+ sectionData.size = sectionSize
+ sectionData.characteristics = sections[i].Characteristics
+ }
+ sectionData.last = true
+ err := module.finalizeSection(&sectionData)
+ if err != nil {
+ return fmt.Errorf("Error finalizing section: %w", err)
+ }
+ return nil
+}
+
+func (module *Module) executeTLS() {
+ directory := module.headerDirectory(IMAGE_DIRECTORY_ENTRY_TLS)
+ if directory.VirtualAddress == 0 {
+ return
+ }
+
+ tls := (*IMAGE_TLS_DIRECTORY)(a2p(module.codeBase + uintptr(directory.VirtualAddress)))
+ callback := tls.AddressOfCallbacks
+ if callback != 0 {
+ for {
+ f := *(*uintptr)(a2p(callback))
+ if f == 0 {
+ break
+ }
+ syscall.SyscallN(f, module.codeBase, DLL_PROCESS_ATTACH, 0)
+ callback += unsafe.Sizeof(f)
+ }
+ }
+}
+
+func (module *Module) performBaseRelocation(delta uintptr) (relocated bool, err error) {
+ directory := module.headerDirectory(IMAGE_DIRECTORY_ENTRY_BASERELOC)
+ if directory.Size == 0 {
+ return delta == 0, nil
+ }
+
+ relocationHdr := (*IMAGE_BASE_RELOCATION)(a2p(module.codeBase + uintptr(directory.VirtualAddress)))
+ for relocationHdr.VirtualAddress > 0 {
+ dest := module.codeBase + uintptr(relocationHdr.VirtualAddress)
+
+ relInfos := unsafe.Slice(
+ (*uint16)(a2p(uintptr(unsafe.Pointer(relocationHdr))+unsafe.Sizeof(*relocationHdr))),
+ (uintptr(relocationHdr.SizeOfBlock)-unsafe.Sizeof(*relocationHdr))/unsafe.Sizeof(uint16(0)))
+ for _, relInfo := range relInfos {
+ // The upper 4 bits define the type of relocation.
+ relType := relInfo >> 12
+ // The lower 12 bits define the offset.
+ relOffset := uintptr(relInfo & 0xfff)
+
+ switch relType {
+ case IMAGE_REL_BASED_ABSOLUTE:
+ // Skip relocation.
+
+ case IMAGE_REL_BASED_LOW:
+ *(*uint16)(a2p(dest + relOffset)) += uint16(delta & 0xffff)
+ break
+
+ case IMAGE_REL_BASED_HIGH:
+ *(*uint16)(a2p(dest + relOffset)) += uint16(uint32(delta) >> 16)
+ break
+
+ case IMAGE_REL_BASED_HIGHLOW:
+ *(*uint32)(a2p(dest + relOffset)) += uint32(delta)
+
+ case IMAGE_REL_BASED_DIR64:
+ *(*uint64)(a2p(dest + relOffset)) += uint64(delta)
+
+ case IMAGE_REL_BASED_THUMB_MOV32:
+ inst := *(*uint32)(a2p(dest + relOffset))
+ imm16 := ((inst << 1) & 0x0800) + ((inst << 12) & 0xf000) +
+ ((inst >> 20) & 0x0700) + ((inst >> 16) & 0x00ff)
+ if (inst & 0x8000fbf0) != 0x0000f240 {
+ return false, fmt.Errorf("Wrong Thumb2 instruction %08x, expected MOVW", inst)
+ }
+ imm16 += uint32(delta) & 0xffff
+ hiDelta := (uint32(delta&0xffff0000) >> 16) + ((imm16 & 0xffff0000) >> 16)
+ *(*uint32)(a2p(dest + relOffset)) = (inst & 0x8f00fbf0) + ((imm16 >> 1) & 0x0400) +
+ ((imm16 >> 12) & 0x000f) +
+ ((imm16 << 20) & 0x70000000) +
+ ((imm16 << 16) & 0xff0000)
+ if hiDelta != 0 {
+ inst = *(*uint32)(a2p(dest + relOffset + 4))
+ imm16 = ((inst << 1) & 0x0800) + ((inst << 12) & 0xf000) +
+ ((inst >> 20) & 0x0700) + ((inst >> 16) & 0x00ff)
+ if (inst & 0x8000fbf0) != 0x0000f2c0 {
+ return false, fmt.Errorf("Wrong Thumb2 instruction %08x, expected MOVT", inst)
+ }
+ imm16 += hiDelta
+ if imm16 > 0xffff {
+ return false, fmt.Errorf("Resulting immediate value won't fit: %08x", imm16)
+ }
+ *(*uint32)(a2p(dest + relOffset + 4)) = (inst & 0x8f00fbf0) +
+ ((imm16 >> 1) & 0x0400) +
+ ((imm16 >> 12) & 0x000f) +
+ ((imm16 << 20) & 0x70000000) +
+ ((imm16 << 16) & 0xff0000)
+ }
+
+ default:
+ return false, fmt.Errorf("Unsupported relocation: %v", relType)
+ }
+ }
+
+ // Advance to next relocation block.
+ relocationHdr = (*IMAGE_BASE_RELOCATION)(a2p(uintptr(unsafe.Pointer(relocationHdr)) + uintptr(relocationHdr.SizeOfBlock)))
+ }
+ return true, nil
+}
+
+func (module *Module) buildImportTable() error {
+ directory := module.headerDirectory(IMAGE_DIRECTORY_ENTRY_IMPORT)
+ if directory.Size == 0 {
+ return nil
+ }
+
+ module.modules = make([]windows.Handle, 0, 16)
+ importDesc := (*IMAGE_IMPORT_DESCRIPTOR)(a2p(module.codeBase + uintptr(directory.VirtualAddress)))
+ for importDesc.Name != 0 {
+ handle, err := windows.LoadLibraryEx(windows.BytePtrToString((*byte)(a2p(module.codeBase+uintptr(importDesc.Name)))), 0, windows.LOAD_LIBRARY_SEARCH_SYSTEM32)
+ if err != nil {
+ return fmt.Errorf("Error loading module: %w", err)
+ }
+ var thunkRef, funcRef *uintptr
+ if importDesc.OriginalFirstThunk() != 0 {
+ thunkRef = (*uintptr)(a2p(module.codeBase + uintptr(importDesc.OriginalFirstThunk())))
+ funcRef = (*uintptr)(a2p(module.codeBase + uintptr(importDesc.FirstThunk)))
+ } else {
+ // No hint table.
+ thunkRef = (*uintptr)(a2p(module.codeBase + uintptr(importDesc.FirstThunk)))
+ funcRef = (*uintptr)(a2p(module.codeBase + uintptr(importDesc.FirstThunk)))
+ }
+ for *thunkRef != 0 {
+ if IMAGE_SNAP_BY_ORDINAL(*thunkRef) {
+ *funcRef, err = windows.GetProcAddressByOrdinal(handle, IMAGE_ORDINAL(*thunkRef))
+ } else {
+ thunkData := (*IMAGE_IMPORT_BY_NAME)(a2p(module.codeBase + *thunkRef))
+ *funcRef, err = windows.GetProcAddress(handle, windows.BytePtrToString(&thunkData.Name[0]))
+ }
+ if err != nil {
+ windows.FreeLibrary(handle)
+ return fmt.Errorf("Error getting function address: %w", err)
+ }
+ thunkRef = (*uintptr)(a2p(uintptr(unsafe.Pointer(thunkRef)) + unsafe.Sizeof(*thunkRef)))
+ funcRef = (*uintptr)(a2p(uintptr(unsafe.Pointer(funcRef)) + unsafe.Sizeof(*funcRef)))
+ }
+ module.modules = append(module.modules, handle)
+ importDesc = (*IMAGE_IMPORT_DESCRIPTOR)(a2p(uintptr(unsafe.Pointer(importDesc)) + unsafe.Sizeof(*importDesc)))
+ }
+ return nil
+}
+
+func (module *Module) buildNameExports() error {
+ directory := module.headerDirectory(IMAGE_DIRECTORY_ENTRY_EXPORT)
+ if directory.Size == 0 {
+ return errors.New("No export table found")
+ }
+ exports := (*IMAGE_EXPORT_DIRECTORY)(a2p(module.codeBase + uintptr(directory.VirtualAddress)))
+ if exports.NumberOfNames == 0 || exports.NumberOfFunctions == 0 {
+ return errors.New("No functions exported")
+ }
+ if exports.NumberOfNames == 0 {
+ return errors.New("No functions exported by name")
+ }
+ nameRefs := unsafe.Slice((*uint32)(a2p(module.codeBase+uintptr(exports.AddressOfNames))), exports.NumberOfNames)
+ ordinals := unsafe.Slice((*uint16)(a2p(module.codeBase+uintptr(exports.AddressOfNameOrdinals))), exports.NumberOfNames)
+ module.nameExports = make(map[string]uint16)
+ for i := range nameRefs {
+ nameArray := windows.BytePtrToString((*byte)(a2p(module.codeBase + uintptr(nameRefs[i]))))
+ module.nameExports[nameArray] = ordinals[i]
+ }
+ return nil
+}
+
+type addressRange struct {
+ start uintptr
+ end uintptr
+}
+
+var (
+ loadedAddressRanges []addressRange
+ loadedAddressRangesMu sync.RWMutex
+ haveHookedRtlPcToFileHeader sync.Once
+ hookRtlPcToFileHeaderResult error
+)
+
+func hookRtlPcToFileHeader() error {
+ var kernelBase windows.Handle
+ err := windows.GetModuleHandleEx(windows.GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, windows.StringToUTF16Ptr("kernelbase.dll"), &kernelBase)
+ if err != nil {
+ return err
+ }
+ imageBase := unsafe.Pointer(kernelBase)
+ dosHeader := (*IMAGE_DOS_HEADER)(imageBase)
+ ntHeaders := (*IMAGE_NT_HEADERS)(unsafe.Add(imageBase, dosHeader.E_lfanew))
+ importsDirectory := ntHeaders.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT]
+ importDescriptor := (*IMAGE_IMPORT_DESCRIPTOR)(unsafe.Add(imageBase, importsDirectory.VirtualAddress))
+ for ; importDescriptor.Name != 0; importDescriptor = (*IMAGE_IMPORT_DESCRIPTOR)(unsafe.Add(unsafe.Pointer(importDescriptor), unsafe.Sizeof(*importDescriptor))) {
+ libraryName := windows.BytePtrToString((*byte)(unsafe.Add(imageBase, importDescriptor.Name)))
+ if strings.EqualFold(libraryName, "ntdll.dll") {
+ break
+ }
+ }
+ if importDescriptor.Name == 0 {
+ return errors.New("ntdll.dll not found")
+ }
+ originalThunk := (*uintptr)(unsafe.Add(imageBase, importDescriptor.OriginalFirstThunk()))
+ thunk := (*uintptr)(unsafe.Add(imageBase, importDescriptor.FirstThunk))
+ for ; *originalThunk != 0; originalThunk = (*uintptr)(unsafe.Add(unsafe.Pointer(originalThunk), unsafe.Sizeof(*originalThunk))) {
+ if *originalThunk&IMAGE_ORDINAL_FLAG == 0 {
+ function := (*IMAGE_IMPORT_BY_NAME)(unsafe.Add(imageBase, *originalThunk))
+ name := windows.BytePtrToString(&function.Name[0])
+ if name == "RtlPcToFileHeader" {
+ break
+ }
+ }
+ thunk = (*uintptr)(unsafe.Add(unsafe.Pointer(thunk), unsafe.Sizeof(*thunk)))
+ }
+ if *originalThunk == 0 {
+ return errors.New("RtlPcToFileHeader not found")
+ }
+ var oldProtect uint32
+ err = windows.VirtualProtect(uintptr(unsafe.Pointer(thunk)), unsafe.Sizeof(*thunk), windows.PAGE_READWRITE, &oldProtect)
+ if err != nil {
+ return err
+ }
+ originalRtlPcToFileHeader := *thunk
+ *thunk = windows.NewCallback(func(pcValue uintptr, baseOfImage *uintptr) uintptr {
+ loadedAddressRangesMu.RLock()
+ for i := range loadedAddressRanges {
+ if pcValue >= loadedAddressRanges[i].start && pcValue < loadedAddressRanges[i].end {
+ pcValue = *thunk
+ break
+ }
+ }
+ loadedAddressRangesMu.RUnlock()
+ ret, _, _ := syscall.SyscallN(originalRtlPcToFileHeader, pcValue, uintptr(unsafe.Pointer(baseOfImage)))
+ return ret
+ })
+ err = windows.VirtualProtect(uintptr(unsafe.Pointer(thunk)), unsafe.Sizeof(*thunk), oldProtect, &oldProtect)
+ if err != nil {
+ return err
+ }
+ return nil
+}
+
+// LoadLibrary loads module image to memory.
+func LoadLibrary(data []byte) (module *Module, err error) {
+ addr := uintptr(unsafe.Pointer(&data[0]))
+ size := uintptr(len(data))
+ if size < unsafe.Sizeof(IMAGE_DOS_HEADER{}) {
+ return nil, errors.New("Incomplete IMAGE_DOS_HEADER")
+ }
+ dosHeader := (*IMAGE_DOS_HEADER)(a2p(addr))
+ if dosHeader.E_magic != IMAGE_DOS_SIGNATURE {
+ return nil, fmt.Errorf("Not an MS-DOS binary (provided: %x, expected: %x)", dosHeader.E_magic, IMAGE_DOS_SIGNATURE)
+ }
+ if (size < uintptr(dosHeader.E_lfanew)+unsafe.Sizeof(IMAGE_NT_HEADERS{})) {
+ return nil, errors.New("Incomplete IMAGE_NT_HEADERS")
+ }
+ oldHeader := (*IMAGE_NT_HEADERS)(a2p(addr + uintptr(dosHeader.E_lfanew)))
+ if oldHeader.Signature != IMAGE_NT_SIGNATURE {
+ return nil, fmt.Errorf("Not an NT binary (provided: %x, expected: %x)", oldHeader.Signature, IMAGE_NT_SIGNATURE)
+ }
+ if oldHeader.FileHeader.Machine != imageFileProcess {
+ return nil, fmt.Errorf("Foreign platform (provided: %x, expected: %x)", oldHeader.FileHeader.Machine, imageFileProcess)
+ }
+ if (oldHeader.OptionalHeader.SectionAlignment & 1) != 0 {
+ return nil, errors.New("Unaligned section")
+ }
+ lastSectionEnd := uintptr(0)
+ sections := oldHeader.Sections()
+ optionalSectionSize := oldHeader.OptionalHeader.SectionAlignment
+ for i := range sections {
+ var endOfSection uintptr
+ if sections[i].SizeOfRawData == 0 {
+ // Section without data in the DLL
+ endOfSection = uintptr(sections[i].VirtualAddress) + uintptr(optionalSectionSize)
+ } else {
+ endOfSection = uintptr(sections[i].VirtualAddress) + uintptr(sections[i].SizeOfRawData)
+ }
+ if endOfSection > lastSectionEnd {
+ lastSectionEnd = endOfSection
+ }
+ }
+ alignedImageSize := alignUp(uintptr(oldHeader.OptionalHeader.SizeOfImage), uintptr(oldHeader.OptionalHeader.SectionAlignment))
+ if alignedImageSize != alignUp(lastSectionEnd, uintptr(oldHeader.OptionalHeader.SectionAlignment)) {
+ return nil, errors.New("Section is not page-aligned")
+ }
+
+ module = &Module{isDLL: (oldHeader.FileHeader.Characteristics & IMAGE_FILE_DLL) != 0}
+ defer func() {
+ if err != nil {
+ module.Free()
+ module = nil
+ }
+ }()
+
+ // Reserve memory for image of library.
+ // TODO: Is it correct to commit the complete memory region at once? Calling DllEntry raises an exception if we don't.
+ module.codeBase, err = windows.VirtualAlloc(oldHeader.OptionalHeader.ImageBase,
+ alignedImageSize,
+ windows.MEM_RESERVE|windows.MEM_COMMIT,
+ windows.PAGE_READWRITE)
+ if err != nil {
+ // Try to allocate memory at arbitrary position.
+ module.codeBase, err = windows.VirtualAlloc(0,
+ alignedImageSize,
+ windows.MEM_RESERVE|windows.MEM_COMMIT,
+ windows.PAGE_READWRITE)
+ if err != nil {
+ err = fmt.Errorf("Error allocating code: %w", err)
+ return
+ }
+ }
+ err = module.check4GBBoundaries(alignedImageSize)
+ if err != nil {
+ err = fmt.Errorf("Error reallocating code: %w", err)
+ return
+ }
+
+ if size < uintptr(oldHeader.OptionalHeader.SizeOfHeaders) {
+ err = errors.New("Incomplete headers")
+ return
+ }
+ // Commit memory for headers.
+ headers, err := windows.VirtualAlloc(module.codeBase,
+ uintptr(oldHeader.OptionalHeader.SizeOfHeaders),
+ windows.MEM_COMMIT,
+ windows.PAGE_READWRITE)
+ if err != nil {
+ err = fmt.Errorf("Error allocating headers: %w", err)
+ return
+ }
+ // Copy PE header to code.
+ memcpy(headers, addr, uintptr(oldHeader.OptionalHeader.SizeOfHeaders))
+ module.headers = (*IMAGE_NT_HEADERS)(a2p(headers + uintptr(dosHeader.E_lfanew)))
+
+ // Update position.
+ module.headers.OptionalHeader.ImageBase = module.codeBase
+
+ // Copy sections from DLL file block to new memory location.
+ err = module.copySections(addr, size, oldHeader)
+ if err != nil {
+ err = fmt.Errorf("Error copying sections: %w", err)
+ return
+ }
+
+ // Adjust base address of imported data.
+ locationDelta := module.headers.OptionalHeader.ImageBase - oldHeader.OptionalHeader.ImageBase
+ if locationDelta != 0 {
+ module.isRelocated, err = module.performBaseRelocation(locationDelta)
+ if err != nil {
+ err = fmt.Errorf("Error relocating module: %w", err)
+ return
+ }
+ } else {
+ module.isRelocated = true
+ }
+
+ // Load required dlls and adjust function table of imports.
+ err = module.buildImportTable()
+ if err != nil {
+ err = fmt.Errorf("Error building import table: %w", err)
+ return
+ }
+
+ // Mark memory pages depending on section headers and release sections that are marked as "discardable".
+ err = module.finalizeSections()
+ if err != nil {
+ err = fmt.Errorf("Error finalizing sections: %w", err)
+ return
+ }
+
+ // Register exception tables, if they exist.
+ module.registerExceptionHandlers()
+
+ // Register function PCs.
+ loadedAddressRangesMu.Lock()
+ loadedAddressRanges = append(loadedAddressRanges, addressRange{module.codeBase, module.codeBase + alignedImageSize})
+ loadedAddressRangesMu.Unlock()
+ haveHookedRtlPcToFileHeader.Do(func() {
+ hookRtlPcToFileHeaderResult = hookRtlPcToFileHeader()
+ })
+ err = hookRtlPcToFileHeaderResult
+ if err != nil {
+ return
+ }
+
+ // TLS callbacks are executed BEFORE the main loading.
+ module.executeTLS()
+
+ // Get entry point of loaded module.
+ if module.headers.OptionalHeader.AddressOfEntryPoint != 0 {
+ module.entry = module.codeBase + uintptr(module.headers.OptionalHeader.AddressOfEntryPoint)
+ if module.isDLL {
+ // Notify library about attaching to process.
+ r0, _, _ := syscall.SyscallN(module.entry, module.codeBase, DLL_PROCESS_ATTACH, 0)
+ successful := r0 != 0
+ if !successful {
+ err = windows.ERROR_DLL_INIT_FAILED
+ return
+ }
+ module.initialized = true
+ }
+ }
+
+ module.buildNameExports()
+ return
+}
+
+// Free releases module resources and unloads it.
+func (module *Module) Free() {
+ if module.initialized {
+ // Notify library about detaching from process.
+ syscall.SyscallN(module.entry, module.codeBase, DLL_PROCESS_DETACH, 0)
+ module.initialized = false
+ }
+ if module.modules != nil {
+ // Free previously opened libraries.
+ for _, handle := range module.modules {
+ windows.FreeLibrary(handle)
+ }
+ module.modules = nil
+ }
+ if module.codeBase != 0 {
+ windows.VirtualFree(module.codeBase, 0, windows.MEM_RELEASE)
+ module.codeBase = 0
+ }
+ if module.blockedMemory != nil {
+ module.blockedMemory.free()
+ module.blockedMemory = nil
+ }
+}
+
+// ProcAddressByName returns function address by exported name.
+func (module *Module) ProcAddressByName(name string) (uintptr, error) {
+ directory := module.headerDirectory(IMAGE_DIRECTORY_ENTRY_EXPORT)
+ if directory.Size == 0 {
+ return 0, errors.New("No export table found")
+ }
+ exports := (*IMAGE_EXPORT_DIRECTORY)(a2p(module.codeBase + uintptr(directory.VirtualAddress)))
+ if module.nameExports == nil {
+ return 0, errors.New("No functions exported by name")
+ }
+ if idx, ok := module.nameExports[name]; ok {
+ if uint32(idx) > exports.NumberOfFunctions {
+ return 0, errors.New("Ordinal number too high")
+ }
+ // AddressOfFunctions contains the RVAs to the "real" functions.
+ return module.codeBase + uintptr(*(*uint32)(a2p(module.codeBase + uintptr(exports.AddressOfFunctions) + uintptr(idx)*4))), nil
+ }
+ return 0, errors.New("Function not found by name")
+}
+
+// ProcAddressByOrdinal returns function address by exported ordinal.
+func (module *Module) ProcAddressByOrdinal(ordinal uint16) (uintptr, error) {
+ directory := module.headerDirectory(IMAGE_DIRECTORY_ENTRY_EXPORT)
+ if directory.Size == 0 {
+ return 0, errors.New("No export table found")
+ }
+ exports := (*IMAGE_EXPORT_DIRECTORY)(a2p(module.codeBase + uintptr(directory.VirtualAddress)))
+ if uint32(ordinal) < exports.Base {
+ return 0, errors.New("Ordinal number too low")
+ }
+ idx := ordinal - uint16(exports.Base)
+ if uint32(idx) > exports.NumberOfFunctions {
+ return 0, errors.New("Ordinal number too high")
+ }
+ // AddressOfFunctions contains the RVAs to the "real" functions.
+ return module.codeBase + uintptr(*(*uint32)(a2p(module.codeBase + uintptr(exports.AddressOfFunctions) + uintptr(idx)*4))), nil
+}
+
+func alignDown(value, alignment uintptr) uintptr {
+ return value & ^(alignment - 1)
+}
+
+func alignUp(value, alignment uintptr) uintptr {
+ return (value + alignment - 1) & ^(alignment - 1)
+}
+
+func a2p(addr uintptr) unsafe.Pointer {
+ return unsafe.Pointer(addr)
+}
+
+func memcpy(dst, src, size uintptr) {
+ copy(unsafe.Slice((*byte)(a2p(dst)), size), unsafe.Slice((*byte)(a2p(src)), size))
+}
diff --git a/driver/memmod/memmod_windows_32.go b/driver/memmod/memmod_windows_32.go
new file mode 100644
index 00000000..611fbe53
--- /dev/null
+++ b/driver/memmod/memmod_windows_32.go
@@ -0,0 +1,16 @@
+//go:build (windows && 386) || (windows && arm)
+
+/* SPDX-License-Identifier: MIT
+ *
+ * Copyright (C) 2017-2022 WireGuard LLC. All Rights Reserved.
+ */
+
+package memmod
+
+func (opthdr *IMAGE_OPTIONAL_HEADER) imageOffset() uintptr {
+ return 0
+}
+
+func (module *Module) check4GBBoundaries(alignedImageSize uintptr) (err error) {
+ return
+}
diff --git a/driver/memmod/memmod_windows_386.go b/driver/memmod/memmod_windows_386.go
new file mode 100644
index 00000000..71d6c93e
--- /dev/null
+++ b/driver/memmod/memmod_windows_386.go
@@ -0,0 +1,8 @@
+/* SPDX-License-Identifier: MIT
+ *
+ * Copyright (C) 2017-2022 WireGuard LLC. All Rights Reserved.
+ */
+
+package memmod
+
+const imageFileProcess = IMAGE_FILE_MACHINE_I386
diff --git a/driver/memmod/memmod_windows_64.go b/driver/memmod/memmod_windows_64.go
new file mode 100644
index 00000000..28ada96e
--- /dev/null
+++ b/driver/memmod/memmod_windows_64.go
@@ -0,0 +1,36 @@
+//go:build (windows && amd64) || (windows && arm64)
+
+/* SPDX-License-Identifier: MIT
+ *
+ * Copyright (C) 2017-2022 WireGuard LLC. All Rights Reserved.
+ */
+
+package memmod
+
+import (
+ "fmt"
+
+ "golang.org/x/sys/windows"
+)
+
+func (opthdr *IMAGE_OPTIONAL_HEADER) imageOffset() uintptr {
+ return uintptr(opthdr.ImageBase & 0xffffffff00000000)
+}
+
+func (module *Module) check4GBBoundaries(alignedImageSize uintptr) (err error) {
+ for (module.codeBase >> 32) < ((module.codeBase + alignedImageSize) >> 32) {
+ node := &addressList{
+ next: module.blockedMemory,
+ address: module.codeBase,
+ }
+ module.blockedMemory = node
+ module.codeBase, err = windows.VirtualAlloc(0,
+ alignedImageSize,
+ windows.MEM_RESERVE|windows.MEM_COMMIT,
+ windows.PAGE_READWRITE)
+ if err != nil {
+ return fmt.Errorf("Error allocating memory block: %w", err)
+ }
+ }
+ return
+}
diff --git a/driver/memmod/memmod_windows_amd64.go b/driver/memmod/memmod_windows_amd64.go
new file mode 100644
index 00000000..2459b2d2
--- /dev/null
+++ b/driver/memmod/memmod_windows_amd64.go
@@ -0,0 +1,8 @@
+/* SPDX-License-Identifier: MIT
+ *
+ * Copyright (C) 2017-2022 WireGuard LLC. All Rights Reserved.
+ */
+
+package memmod
+
+const imageFileProcess = IMAGE_FILE_MACHINE_AMD64
diff --git a/driver/memmod/memmod_windows_arm.go b/driver/memmod/memmod_windows_arm.go
new file mode 100644
index 00000000..a644cee6
--- /dev/null
+++ b/driver/memmod/memmod_windows_arm.go
@@ -0,0 +1,8 @@
+/* SPDX-License-Identifier: MIT
+ *
+ * Copyright (C) 2017-2022 WireGuard LLC. All Rights Reserved.
+ */
+
+package memmod
+
+const imageFileProcess = IMAGE_FILE_MACHINE_ARMNT
diff --git a/driver/memmod/memmod_windows_arm64.go b/driver/memmod/memmod_windows_arm64.go
new file mode 100644
index 00000000..09e24639
--- /dev/null
+++ b/driver/memmod/memmod_windows_arm64.go
@@ -0,0 +1,8 @@
+/* SPDX-License-Identifier: MIT
+ *
+ * Copyright (C) 2017-2022 WireGuard LLC. All Rights Reserved.
+ */
+
+package memmod
+
+const imageFileProcess = IMAGE_FILE_MACHINE_ARM64
diff --git a/driver/memmod/syscall_windows.go b/driver/memmod/syscall_windows.go
new file mode 100644
index 00000000..cdc6ef67
--- /dev/null
+++ b/driver/memmod/syscall_windows.go
@@ -0,0 +1,392 @@
+/* SPDX-License-Identifier: MIT
+ *
+ * Copyright (C) 2017-2022 WireGuard LLC. All Rights Reserved.
+ */
+
+package memmod
+
+import "unsafe"
+
+const (
+ IMAGE_DOS_SIGNATURE = 0x5A4D // MZ
+ IMAGE_OS2_SIGNATURE = 0x454E // NE
+ IMAGE_OS2_SIGNATURE_LE = 0x454C // LE
+ IMAGE_VXD_SIGNATURE = 0x454C // LE
+ IMAGE_NT_SIGNATURE = 0x00004550 // PE00
+)
+
+// DOS .EXE header
+type IMAGE_DOS_HEADER struct {
+ E_magic uint16 // Magic number
+ E_cblp uint16 // Bytes on last page of file
+ E_cp uint16 // Pages in file
+ E_crlc uint16 // Relocations
+ E_cparhdr uint16 // Size of header in paragraphs
+ E_minalloc uint16 // Minimum extra paragraphs needed
+ E_maxalloc uint16 // Maximum extra paragraphs needed
+ E_ss uint16 // Initial (relative) SS value
+ E_sp uint16 // Initial SP value
+ E_csum uint16 // Checksum
+ E_ip uint16 // Initial IP value
+ E_cs uint16 // Initial (relative) CS value
+ E_lfarlc uint16 // File address of relocation table
+ E_ovno uint16 // Overlay number
+ E_res [4]uint16 // Reserved words
+ E_oemid uint16 // OEM identifier (for e_oeminfo)
+ E_oeminfo uint16 // OEM information; e_oemid specific
+ E_res2 [10]uint16 // Reserved words
+ E_lfanew int32 // File address of new exe header
+}
+
+// File header format
+type IMAGE_FILE_HEADER struct {
+ Machine uint16
+ NumberOfSections uint16
+ TimeDateStamp uint32
+ PointerToSymbolTable uint32
+ NumberOfSymbols uint32
+ SizeOfOptionalHeader uint16
+ Characteristics uint16
+}
+
+const (
+ IMAGE_SIZEOF_FILE_HEADER = 20
+
+ IMAGE_FILE_RELOCS_STRIPPED = 0x0001 // Relocation info stripped from file.
+ IMAGE_FILE_EXECUTABLE_IMAGE = 0x0002 // File is executable (i.e. no unresolved external references).
+ IMAGE_FILE_LINE_NUMS_STRIPPED = 0x0004 // Line nunbers stripped from file.
+ IMAGE_FILE_LOCAL_SYMS_STRIPPED = 0x0008 // Local symbols stripped from file.
+ IMAGE_FILE_AGGRESIVE_WS_TRIM = 0x0010 // Aggressively trim working set
+ IMAGE_FILE_LARGE_ADDRESS_AWARE = 0x0020 // App can handle >2gb addresses
+ IMAGE_FILE_BYTES_REVERSED_LO = 0x0080 // Bytes of machine word are reversed.
+ IMAGE_FILE_32BIT_MACHINE = 0x0100 // 32 bit word machine.
+ IMAGE_FILE_DEBUG_STRIPPED = 0x0200 // Debugging info stripped from file in .DBG file
+ IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP = 0x0400 // If Image is on removable media, copy and run from the swap file.
+ IMAGE_FILE_NET_RUN_FROM_SWAP = 0x0800 // If Image is on Net, copy and run from the swap file.
+ IMAGE_FILE_SYSTEM = 0x1000 // System File.
+ IMAGE_FILE_DLL = 0x2000 // File is a DLL.
+ IMAGE_FILE_UP_SYSTEM_ONLY = 0x4000 // File should only be run on a UP machine
+ IMAGE_FILE_BYTES_REVERSED_HI = 0x8000 // Bytes of machine word are reversed.
+
+ IMAGE_FILE_MACHINE_UNKNOWN = 0
+ IMAGE_FILE_MACHINE_TARGET_HOST = 0x0001 // Useful for indicating we want to interact with the host and not a WoW guest.
+ IMAGE_FILE_MACHINE_I386 = 0x014c // Intel 386.
+ IMAGE_FILE_MACHINE_R3000 = 0x0162 // MIPS little-endian, 0x160 big-endian
+ IMAGE_FILE_MACHINE_R4000 = 0x0166 // MIPS little-endian
+ IMAGE_FILE_MACHINE_R10000 = 0x0168 // MIPS little-endian
+ IMAGE_FILE_MACHINE_WCEMIPSV2 = 0x0169 // MIPS little-endian WCE v2
+ IMAGE_FILE_MACHINE_ALPHA = 0x0184 // Alpha_AXP
+ IMAGE_FILE_MACHINE_SH3 = 0x01a2 // SH3 little-endian
+ IMAGE_FILE_MACHINE_SH3DSP = 0x01a3
+ IMAGE_FILE_MACHINE_SH3E = 0x01a4 // SH3E little-endian
+ IMAGE_FILE_MACHINE_SH4 = 0x01a6 // SH4 little-endian
+ IMAGE_FILE_MACHINE_SH5 = 0x01a8 // SH5
+ IMAGE_FILE_MACHINE_ARM = 0x01c0 // ARM Little-Endian
+ IMAGE_FILE_MACHINE_THUMB = 0x01c2 // ARM Thumb/Thumb-2 Little-Endian
+ IMAGE_FILE_MACHINE_ARMNT = 0x01c4 // ARM Thumb-2 Little-Endian
+ IMAGE_FILE_MACHINE_AM33 = 0x01d3
+ IMAGE_FILE_MACHINE_POWERPC = 0x01F0 // IBM PowerPC Little-Endian
+ IMAGE_FILE_MACHINE_POWERPCFP = 0x01f1
+ IMAGE_FILE_MACHINE_IA64 = 0x0200 // Intel 64
+ IMAGE_FILE_MACHINE_MIPS16 = 0x0266 // MIPS
+ IMAGE_FILE_MACHINE_ALPHA64 = 0x0284 // ALPHA64
+ IMAGE_FILE_MACHINE_MIPSFPU = 0x0366 // MIPS
+ IMAGE_FILE_MACHINE_MIPSFPU16 = 0x0466 // MIPS
+ IMAGE_FILE_MACHINE_AXP64 = IMAGE_FILE_MACHINE_ALPHA64
+ IMAGE_FILE_MACHINE_TRICORE = 0x0520 // Infineon
+ IMAGE_FILE_MACHINE_CEF = 0x0CEF
+ IMAGE_FILE_MACHINE_EBC = 0x0EBC // EFI Byte Code
+ IMAGE_FILE_MACHINE_AMD64 = 0x8664 // AMD64 (K8)
+ IMAGE_FILE_MACHINE_M32R = 0x9041 // M32R little-endian
+ IMAGE_FILE_MACHINE_ARM64 = 0xAA64 // ARM64 Little-Endian
+ IMAGE_FILE_MACHINE_CEE = 0xC0EE
+)
+
+// Directory format
+type IMAGE_DATA_DIRECTORY struct {
+ VirtualAddress uint32
+ Size uint32
+}
+
+const IMAGE_NUMBEROF_DIRECTORY_ENTRIES = 16
+
+type IMAGE_NT_HEADERS struct {
+ Signature uint32
+ FileHeader IMAGE_FILE_HEADER
+ OptionalHeader IMAGE_OPTIONAL_HEADER
+}
+
+func (ntheader *IMAGE_NT_HEADERS) Sections() []IMAGE_SECTION_HEADER {
+ return (*[0xffff]IMAGE_SECTION_HEADER)(unsafe.Pointer(
+ (uintptr)(unsafe.Pointer(ntheader)) +
+ unsafe.Offsetof(ntheader.OptionalHeader) +
+ uintptr(ntheader.FileHeader.SizeOfOptionalHeader)))[:ntheader.FileHeader.NumberOfSections]
+}
+
+const (
+ IMAGE_DIRECTORY_ENTRY_EXPORT = 0 // Export Directory
+ IMAGE_DIRECTORY_ENTRY_IMPORT = 1 // Import Directory
+ IMAGE_DIRECTORY_ENTRY_RESOURCE = 2 // Resource Directory
+ IMAGE_DIRECTORY_ENTRY_EXCEPTION = 3 // Exception Directory
+ IMAGE_DIRECTORY_ENTRY_SECURITY = 4 // Security Directory
+ IMAGE_DIRECTORY_ENTRY_BASERELOC = 5 // Base Relocation Table
+ IMAGE_DIRECTORY_ENTRY_DEBUG = 6 // Debug Directory
+ IMAGE_DIRECTORY_ENTRY_COPYRIGHT = 7 // (X86 usage)
+ IMAGE_DIRECTORY_ENTRY_ARCHITECTURE = 7 // Architecture Specific Data
+ IMAGE_DIRECTORY_ENTRY_GLOBALPTR = 8 // RVA of GP
+ IMAGE_DIRECTORY_ENTRY_TLS = 9 // TLS Directory
+ IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG = 10 // Load Configuration Directory
+ IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT = 11 // Bound Import Directory in headers
+ IMAGE_DIRECTORY_ENTRY_IAT = 12 // Import Address Table
+ IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT = 13 // Delay Load Import Descriptors
+ IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR = 14 // COM Runtime descriptor
+)
+
+const IMAGE_SIZEOF_SHORT_NAME = 8
+
+// Section header format
+type IMAGE_SECTION_HEADER struct {
+ Name [IMAGE_SIZEOF_SHORT_NAME]byte
+ physicalAddressOrVirtualSize uint32
+ VirtualAddress uint32
+ SizeOfRawData uint32
+ PointerToRawData uint32
+ PointerToRelocations uint32
+ PointerToLinenumbers uint32
+ NumberOfRelocations uint16
+ NumberOfLinenumbers uint16
+ Characteristics uint32
+}
+
+func (ishdr *IMAGE_SECTION_HEADER) PhysicalAddress() uint32 {
+ return ishdr.physicalAddressOrVirtualSize
+}
+
+func (ishdr *IMAGE_SECTION_HEADER) SetPhysicalAddress(addr uint32) {
+ ishdr.physicalAddressOrVirtualSize = addr
+}
+
+func (ishdr *IMAGE_SECTION_HEADER) VirtualSize() uint32 {
+ return ishdr.physicalAddressOrVirtualSize
+}
+
+func (ishdr *IMAGE_SECTION_HEADER) SetVirtualSize(addr uint32) {
+ ishdr.physicalAddressOrVirtualSize = addr
+}
+
+const (
+ // Dll characteristics.
+ IMAGE_DLL_CHARACTERISTICS_HIGH_ENTROPY_VA = 0x0020
+ IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE = 0x0040
+ IMAGE_DLL_CHARACTERISTICS_FORCE_INTEGRITY = 0x0080
+ IMAGE_DLL_CHARACTERISTICS_NX_COMPAT = 0x0100
+ IMAGE_DLL_CHARACTERISTICS_NO_ISOLATION = 0x0200
+ IMAGE_DLL_CHARACTERISTICS_NO_SEH = 0x0400
+ IMAGE_DLL_CHARACTERISTICS_NO_BIND = 0x0800
+ IMAGE_DLL_CHARACTERISTICS_APPCONTAINER = 0x1000
+ IMAGE_DLL_CHARACTERISTICS_WDM_DRIVER = 0x2000
+ IMAGE_DLL_CHARACTERISTICS_GUARD_CF = 0x4000
+ IMAGE_DLL_CHARACTERISTICS_TERMINAL_SERVER_AWARE = 0x8000
+)
+
+const (
+ // Section characteristics.
+ IMAGE_SCN_TYPE_REG = 0x00000000 // Reserved.
+ IMAGE_SCN_TYPE_DSECT = 0x00000001 // Reserved.
+ IMAGE_SCN_TYPE_NOLOAD = 0x00000002 // Reserved.
+ IMAGE_SCN_TYPE_GROUP = 0x00000004 // Reserved.
+ IMAGE_SCN_TYPE_NO_PAD = 0x00000008 // Reserved.
+ IMAGE_SCN_TYPE_COPY = 0x00000010 // Reserved.
+
+ IMAGE_SCN_CNT_CODE = 0x00000020 // Section contains code.
+ IMAGE_SCN_CNT_INITIALIZED_DATA = 0x00000040 // Section contains initialized data.
+ IMAGE_SCN_CNT_UNINITIALIZED_DATA = 0x00000080 // Section contains uninitialized data.
+
+ IMAGE_SCN_LNK_OTHER = 0x00000100 // Reserved.
+ IMAGE_SCN_LNK_INFO = 0x00000200 // Section contains comments or some other type of information.
+ IMAGE_SCN_TYPE_OVER = 0x00000400 // Reserved.
+ IMAGE_SCN_LNK_REMOVE = 0x00000800 // Section contents will not become part of image.
+ IMAGE_SCN_LNK_COMDAT = 0x00001000 // Section contents comdat.
+ IMAGE_SCN_MEM_PROTECTED = 0x00004000 // Obsolete.
+ IMAGE_SCN_NO_DEFER_SPEC_EXC = 0x00004000 // Reset speculative exceptions handling bits in the TLB entries for this section.
+ IMAGE_SCN_GPREL = 0x00008000 // Section content can be accessed relative to GP
+ IMAGE_SCN_MEM_FARDATA = 0x00008000
+ IMAGE_SCN_MEM_SYSHEAP = 0x00010000 // Obsolete.
+ IMAGE_SCN_MEM_PURGEABLE = 0x00020000
+ IMAGE_SCN_MEM_16BIT = 0x00020000
+ IMAGE_SCN_MEM_LOCKED = 0x00040000
+ IMAGE_SCN_MEM_PRELOAD = 0x00080000
+
+ IMAGE_SCN_ALIGN_1BYTES = 0x00100000 //
+ IMAGE_SCN_ALIGN_2BYTES = 0x00200000 //
+ IMAGE_SCN_ALIGN_4BYTES = 0x00300000 //
+ IMAGE_SCN_ALIGN_8BYTES = 0x00400000 //
+ IMAGE_SCN_ALIGN_16BYTES = 0x00500000 // Default alignment if no others are specified.
+ IMAGE_SCN_ALIGN_32BYTES = 0x00600000 //
+ IMAGE_SCN_ALIGN_64BYTES = 0x00700000 //
+ IMAGE_SCN_ALIGN_128BYTES = 0x00800000 //
+ IMAGE_SCN_ALIGN_256BYTES = 0x00900000 //
+ IMAGE_SCN_ALIGN_512BYTES = 0x00A00000 //
+ IMAGE_SCN_ALIGN_1024BYTES = 0x00B00000 //
+ IMAGE_SCN_ALIGN_2048BYTES = 0x00C00000 //
+ IMAGE_SCN_ALIGN_4096BYTES = 0x00D00000 //
+ IMAGE_SCN_ALIGN_8192BYTES = 0x00E00000 //
+ IMAGE_SCN_ALIGN_MASK = 0x00F00000
+
+ IMAGE_SCN_LNK_NRELOC_OVFL = 0x01000000 // Section contains extended relocations.
+ IMAGE_SCN_MEM_DISCARDABLE = 0x02000000 // Section can be discarded.
+ IMAGE_SCN_MEM_NOT_CACHED = 0x04000000 // Section is not cachable.
+ IMAGE_SCN_MEM_NOT_PAGED = 0x08000000 // Section is not pageable.
+ IMAGE_SCN_MEM_SHARED = 0x10000000 // Section is shareable.
+ IMAGE_SCN_MEM_EXECUTE = 0x20000000 // Section is executable.
+ IMAGE_SCN_MEM_READ = 0x40000000 // Section is readable.
+ IMAGE_SCN_MEM_WRITE = 0x80000000 // Section is writeable.
+
+ // TLS Characteristic Flags
+ IMAGE_SCN_SCALE_INDEX = 0x00000001 // Tls index is scaled.
+)
+
+// Based relocation format
+type IMAGE_BASE_RELOCATION struct {
+ VirtualAddress uint32
+ SizeOfBlock uint32
+}
+
+const (
+ IMAGE_REL_BASED_ABSOLUTE = 0
+ IMAGE_REL_BASED_HIGH = 1
+ IMAGE_REL_BASED_LOW = 2
+ IMAGE_REL_BASED_HIGHLOW = 3
+ IMAGE_REL_BASED_HIGHADJ = 4
+ IMAGE_REL_BASED_MACHINE_SPECIFIC_5 = 5
+ IMAGE_REL_BASED_RESERVED = 6
+ IMAGE_REL_BASED_MACHINE_SPECIFIC_7 = 7
+ IMAGE_REL_BASED_MACHINE_SPECIFIC_8 = 8
+ IMAGE_REL_BASED_MACHINE_SPECIFIC_9 = 9
+ IMAGE_REL_BASED_DIR64 = 10
+
+ IMAGE_REL_BASED_IA64_IMM64 = 9
+
+ IMAGE_REL_BASED_MIPS_JMPADDR = 5
+ IMAGE_REL_BASED_MIPS_JMPADDR16 = 9
+
+ IMAGE_REL_BASED_ARM_MOV32 = 5
+ IMAGE_REL_BASED_THUMB_MOV32 = 7
+)
+
+// Export Format
+type IMAGE_EXPORT_DIRECTORY struct {
+ Characteristics uint32
+ TimeDateStamp uint32
+ MajorVersion uint16
+ MinorVersion uint16
+ Name uint32
+ Base uint32
+ NumberOfFunctions uint32
+ NumberOfNames uint32
+ AddressOfFunctions uint32 // RVA from base of image
+ AddressOfNames uint32 // RVA from base of image
+ AddressOfNameOrdinals uint32 // RVA from base of image
+}
+
+type IMAGE_IMPORT_BY_NAME struct {
+ Hint uint16
+ Name [1]byte
+}
+
+func IMAGE_ORDINAL(ordinal uintptr) uintptr {
+ return ordinal & 0xffff
+}
+
+func IMAGE_SNAP_BY_ORDINAL(ordinal uintptr) bool {
+ return (ordinal & IMAGE_ORDINAL_FLAG) != 0
+}
+
+// Thread Local Storage
+type IMAGE_TLS_DIRECTORY struct {
+ StartAddressOfRawData uintptr
+ EndAddressOfRawData uintptr
+ AddressOfIndex uintptr // PDWORD
+ AddressOfCallbacks uintptr // PIMAGE_TLS_CALLBACK *;
+ SizeOfZeroFill uint32
+ Characteristics uint32
+}
+
+type IMAGE_IMPORT_DESCRIPTOR struct {
+ characteristicsOrOriginalFirstThunk uint32 // 0 for terminating null import descriptor
+ // RVA to original unbound IAT (PIMAGE_THUNK_DATA)
+ TimeDateStamp uint32 // 0 if not bound,
+ // -1 if bound, and real date\time stamp
+ // in IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT (new BIND)
+ // O.W. date/time stamp of DLL bound to (Old BIND)
+ ForwarderChain uint32 // -1 if no forwarders
+ Name uint32
+ FirstThunk uint32 // RVA to IAT (if bound this IAT has actual addresses)
+}
+
+func (imgimpdesc *IMAGE_IMPORT_DESCRIPTOR) Characteristics() uint32 {
+ return imgimpdesc.characteristicsOrOriginalFirstThunk
+}
+
+func (imgimpdesc *IMAGE_IMPORT_DESCRIPTOR) OriginalFirstThunk() uint32 {
+ return imgimpdesc.characteristicsOrOriginalFirstThunk
+}
+
+type IMAGE_DELAYLOAD_DESCRIPTOR struct {
+ Attributes uint32
+ DllNameRVA uint32
+ ModuleHandleRVA uint32
+ ImportAddressTableRVA uint32
+ ImportNameTableRVA uint32
+ BoundImportAddressTableRVA uint32
+ UnloadInformationTableRVA uint32
+ TimeDateStamp uint32
+}
+
+type IMAGE_LOAD_CONFIG_CODE_INTEGRITY struct {
+ Flags uint16
+ Catalog uint16
+ CatalogOffset uint32
+ Reserved uint32
+}
+
+const (
+ IMAGE_GUARD_CF_INSTRUMENTED = 0x00000100
+ IMAGE_GUARD_CFW_INSTRUMENTED = 0x00000200
+ IMAGE_GUARD_CF_FUNCTION_TABLE_PRESENT = 0x00000400
+ IMAGE_GUARD_SECURITY_COOKIE_UNUSED = 0x00000800
+ IMAGE_GUARD_PROTECT_DELAYLOAD_IAT = 0x00001000
+ IMAGE_GUARD_DELAYLOAD_IAT_IN_ITS_OWN_SECTION = 0x00002000
+ IMAGE_GUARD_CF_EXPORT_SUPPRESSION_INFO_PRESENT = 0x00004000
+ IMAGE_GUARD_CF_ENABLE_EXPORT_SUPPRESSION = 0x00008000
+ IMAGE_GUARD_CF_LONGJUMP_TABLE_PRESENT = 0x00010000
+ IMAGE_GUARD_RF_INSTRUMENTED = 0x00020000
+ IMAGE_GUARD_RF_ENABLE = 0x00040000
+ IMAGE_GUARD_RF_STRICT = 0x00080000
+ IMAGE_GUARD_RETPOLINE_PRESENT = 0x00100000
+ IMAGE_GUARD_EH_CONTINUATION_TABLE_PRESENT = 0x00400000
+ IMAGE_GUARD_XFG_ENABLED = 0x00800000
+ IMAGE_GUARD_CF_FUNCTION_TABLE_SIZE_MASK = 0xF0000000
+ IMAGE_GUARD_CF_FUNCTION_TABLE_SIZE_SHIFT = 28
+)
+
+const (
+ DLL_PROCESS_ATTACH = 1
+ DLL_THREAD_ATTACH = 2
+ DLL_THREAD_DETACH = 3
+ DLL_PROCESS_DETACH = 0
+)
+
+type SYSTEM_INFO struct {
+ ProcessorArchitecture uint16
+ Reserved uint16
+ PageSize uint32
+ MinimumApplicationAddress uintptr
+ MaximumApplicationAddress uintptr
+ ActiveProcessorMask uintptr
+ NumberOfProcessors uint32
+ ProcessorType uint32
+ AllocationGranularity uint32
+ ProcessorLevel uint16
+ ProcessorRevision uint16
+}
diff --git a/driver/memmod/syscall_windows_32.go b/driver/memmod/syscall_windows_32.go
new file mode 100644
index 00000000..dde8b360
--- /dev/null
+++ b/driver/memmod/syscall_windows_32.go
@@ -0,0 +1,96 @@
+//go:build (windows && 386) || (windows && arm)
+
+/* SPDX-License-Identifier: MIT
+ *
+ * Copyright (C) 2017-2022 WireGuard LLC. All Rights Reserved.
+ */
+
+package memmod
+
+// Optional header format
+type IMAGE_OPTIONAL_HEADER struct {
+ Magic uint16
+ MajorLinkerVersion uint8
+ MinorLinkerVersion uint8
+ SizeOfCode uint32
+ SizeOfInitializedData uint32
+ SizeOfUninitializedData uint32
+ AddressOfEntryPoint uint32
+ BaseOfCode uint32
+ BaseOfData uint32
+ ImageBase uintptr
+ SectionAlignment uint32
+ FileAlignment uint32
+ MajorOperatingSystemVersion uint16
+ MinorOperatingSystemVersion uint16
+ MajorImageVersion uint16
+ MinorImageVersion uint16
+ MajorSubsystemVersion uint16
+ MinorSubsystemVersion uint16
+ Win32VersionValue uint32
+ SizeOfImage uint32
+ SizeOfHeaders uint32
+ CheckSum uint32
+ Subsystem uint16
+ DllCharacteristics uint16
+ SizeOfStackReserve uintptr
+ SizeOfStackCommit uintptr
+ SizeOfHeapReserve uintptr
+ SizeOfHeapCommit uintptr
+ LoaderFlags uint32
+ NumberOfRvaAndSizes uint32
+ DataDirectory [IMAGE_NUMBEROF_DIRECTORY_ENTRIES]IMAGE_DATA_DIRECTORY
+}
+
+const IMAGE_ORDINAL_FLAG uintptr = 0x80000000
+
+type IMAGE_LOAD_CONFIG_DIRECTORY struct {
+ Size uint32
+ TimeDateStamp uint32
+ MajorVersion uint16
+ MinorVersion uint16
+ GlobalFlagsClear uint32
+ GlobalFlagsSet uint32
+ CriticalSectionDefaultTimeout uint32
+ DeCommitFreeBlockThreshold uint32
+ DeCommitTotalFreeThreshold uint32
+ LockPrefixTable uint32
+ MaximumAllocationSize uint32
+ VirtualMemoryThreshold uint32
+ ProcessHeapFlags uint32
+ ProcessAffinityMask uint32
+ CSDVersion uint16
+ DependentLoadFlags uint16
+ EditList uint32
+ SecurityCookie uint32
+ SEHandlerTable uint32
+ SEHandlerCount uint32
+ GuardCFCheckFunctionPointer uint32
+ GuardCFDispatchFunctionPointer uint32
+ GuardCFFunctionTable uint32
+ GuardCFFunctionCount uint32
+ GuardFlags uint32
+ CodeIntegrity IMAGE_LOAD_CONFIG_CODE_INTEGRITY
+ GuardAddressTakenIatEntryTable uint32
+ GuardAddressTakenIatEntryCount uint32
+ GuardLongJumpTargetTable uint32
+ GuardLongJumpTargetCount uint32
+ DynamicValueRelocTable uint32
+ CHPEMetadataPointer uint32
+ GuardRFFailureRoutine uint32
+ GuardRFFailureRoutineFunctionPointer uint32
+ DynamicValueRelocTableOffset uint32
+ DynamicValueRelocTableSection uint16
+ Reserved2 uint16
+ GuardRFVerifyStackPointerFunctionPointer uint32
+ HotPatchTableOffset uint32
+ Reserved3 uint32
+ EnclaveConfigurationPointer uint32
+ VolatileMetadataPointer uint32
+ GuardEHContinuationTable uint32
+ GuardEHContinuationCount uint32
+ GuardXFGCheckFunctionPointer uint32
+ GuardXFGDispatchFunctionPointer uint32
+ GuardXFGTableDispatchFunctionPointer uint32
+ CastGuardOsDeterminedFailureMode uint32
+}
diff --git a/driver/memmod/syscall_windows_64.go b/driver/memmod/syscall_windows_64.go
new file mode 100644
index 00000000..f23524fb
--- /dev/null
+++ b/driver/memmod/syscall_windows_64.go
@@ -0,0 +1,95 @@
+//go:build (windows && amd64) || (windows && arm64)
+
+/* SPDX-License-Identifier: MIT
+ *
+ * Copyright (C) 2017-2022 WireGuard LLC. All Rights Reserved.
+ */
+
+package memmod
+
+// Optional header format
+type IMAGE_OPTIONAL_HEADER struct {
+ Magic uint16
+ MajorLinkerVersion uint8
+ MinorLinkerVersion uint8
+ SizeOfCode uint32
+ SizeOfInitializedData uint32
+ SizeOfUninitializedData uint32
+ AddressOfEntryPoint uint32
+ BaseOfCode uint32
+ ImageBase uintptr
+ SectionAlignment uint32
+ FileAlignment uint32
+ MajorOperatingSystemVersion uint16
+ MinorOperatingSystemVersion uint16
+ MajorImageVersion uint16
+ MinorImageVersion uint16
+ MajorSubsystemVersion uint16
+ MinorSubsystemVersion uint16
+ Win32VersionValue uint32
+ SizeOfImage uint32
+ SizeOfHeaders uint32
+ CheckSum uint32
+ Subsystem uint16
+ DllCharacteristics uint16
+ SizeOfStackReserve uintptr
+ SizeOfStackCommit uintptr
+ SizeOfHeapReserve uintptr
+ SizeOfHeapCommit uintptr
+ LoaderFlags uint32
+ NumberOfRvaAndSizes uint32
+ DataDirectory [IMAGE_NUMBEROF_DIRECTORY_ENTRIES]IMAGE_DATA_DIRECTORY
+}
+
+const IMAGE_ORDINAL_FLAG uintptr = 0x8000000000000000
+
+type IMAGE_LOAD_CONFIG_DIRECTORY struct {
+ Size uint32
+ TimeDateStamp uint32
+ MajorVersion uint16
+ MinorVersion uint16
+ GlobalFlagsClear uint32
+ GlobalFlagsSet uint32
+ CriticalSectionDefaultTimeout uint32
+ DeCommitFreeBlockThreshold uint64
+ DeCommitTotalFreeThreshold uint64
+ LockPrefixTable uint64
+ MaximumAllocationSize uint64
+ VirtualMemoryThreshold uint64
+ ProcessAffinityMask uint64
+ ProcessHeapFlags uint32
+ CSDVersion uint16
+ DependentLoadFlags uint16
+ EditList uint64
+ SecurityCookie uint64
+ SEHandlerTable uint64
+ SEHandlerCount uint64
+ GuardCFCheckFunctionPointer uint64
+ GuardCFDispatchFunctionPointer uint64
+ GuardCFFunctionTable uint64
+ GuardCFFunctionCount uint64
+ GuardFlags uint32
+ CodeIntegrity IMAGE_LOAD_CONFIG_CODE_INTEGRITY
+ GuardAddressTakenIatEntryTable uint64
+ GuardAddressTakenIatEntryCount uint64
+ GuardLongJumpTargetTable uint64
+ GuardLongJumpTargetCount uint64
+ DynamicValueRelocTable uint64
+ CHPEMetadataPointer uint64
+ GuardRFFailureRoutine uint64
+ GuardRFFailureRoutineFunctionPointer uint64
+ DynamicValueRelocTableOffset uint32
+ DynamicValueRelocTableSection uint16
+ Reserved2 uint16
+ GuardRFVerifyStackPointerFunctionPointer uint64
+ HotPatchTableOffset uint32
+ Reserved3 uint32
+ EnclaveConfigurationPointer uint64
+ VolatileMetadataPointer uint64
+ GuardEHContinuationTable uint64
+ GuardEHContinuationCount uint64
+ GuardXFGCheckFunctionPointer uint64
+ GuardXFGDispatchFunctionPointer uint64
+ GuardXFGTableDispatchFunctionPointer uint64
+ CastGuardOsDeterminedFailureMode uint64
+}
diff --git a/driver/wintunremoval_windows.go b/driver/wintunremoval_windows.go
new file mode 100644
index 00000000..ab51d989
--- /dev/null
+++ b/driver/wintunremoval_windows.go
@@ -0,0 +1,50 @@
+/* SPDX-License-Identifier: MIT
+ *
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
+ */
+
+package driver
+
+import (
+ "path/filepath"
+
+ "golang.org/x/sys/windows"
+)
+
+func UninstallLegacyWintun() error {
+ deviceClassNetGUID := &windows.GUID{0x4d36e972, 0xe325, 0x11ce, [8]byte{0xbf, 0xc1, 0x08, 0x00, 0x2b, 0xe1, 0x03, 0x18}}
+ devInfo, err := windows.SetupDiCreateDeviceInfoListEx(deviceClassNetGUID, 0, "")
+ if err != nil {
+ return err
+ }
+ defer devInfo.Close()
+ devInfoData, err := devInfo.CreateDeviceInfo("Wintun", deviceClassNetGUID, "", 0, windows.DICD_GENERATE_ID)
+ if err != nil {
+ return err
+ }
+ err = devInfo.SetDeviceRegistryProperty(devInfoData, windows.SPDRP_HARDWAREID, []byte("W\x00i\x00n\x00t\x00u\x00n\x00\x00\x00\x00\x00"))
+ if err != nil {
+ return err
+ }
+ err = devInfo.BuildDriverInfoList(devInfoData, windows.SPDIT_COMPATDRIVER)
+ if err != nil {
+ return err
+ }
+ defer devInfo.DestroyDriverInfoList(devInfoData, windows.SPDIT_COMPATDRIVER)
+ var lastError error
+ for i := 0; ; i++ {
+ drvInfoData, err := devInfo.EnumDriverInfo(devInfoData, windows.SPDIT_COMPATDRIVER, i)
+ if err != nil {
+ if err == windows.ERROR_NO_MORE_ITEMS {
+ break
+ }
+ continue
+ }
+ drvInfoDetailData, err := devInfo.DriverInfoDetail(devInfoData, drvInfoData)
+ if err != nil {
+ continue
+ }
+ lastError = windows.SetupUninstallOEMInf(filepath.Base(drvInfoDetailData.InfFileName()), 0)
+ }
+ return lastError
+}
diff --git a/elevate/doas.go b/elevate/doas.go
index da692b20..b67ee88c 100644
--- a/elevate/doas.go
+++ b/elevate/doas.go
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package elevate
@@ -19,11 +19,11 @@ import (
func setAllEnv(env []string) {
windows.Clearenv()
for _, e := range env {
- kv := strings.SplitN(e, "=", 2)
- if len(kv) != 2 {
+ k, v, ok := strings.Cut(e, "=")
+ if !ok {
continue
}
- windows.Setenv(kv[0], kv[1])
+ windows.Setenv(k, v)
}
}
diff --git a/elevate/loader.go b/elevate/loader.go
index d474a007..7d15f8a4 100644
--- a/elevate/loader.go
+++ b/elevate/loader.go
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package elevate
diff --git a/elevate/membership.go b/elevate/membership.go
index e73b2f9d..383a10ba 100644
--- a/elevate/membership.go
+++ b/elevate/membership.go
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package elevate
diff --git a/elevate/privileges.go b/elevate/privileges.go
index 5c4cd69f..3d51640f 100644
--- a/elevate/privileges.go
+++ b/elevate/privileges.go
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package elevate
@@ -44,7 +44,7 @@ func DropAllPrivileges(retainDriverLoading bool) error {
}
tokenPrivileges := (*windows.Tokenprivileges)(unsafe.Pointer(&buffer[0]))
for i := uint32(0); i < tokenPrivileges.PrivilegeCount; i++ {
- item := (*windows.LUIDAndAttributes)(unsafe.Pointer(uintptr(unsafe.Pointer(&tokenPrivileges.Privileges[0])) + unsafe.Sizeof(tokenPrivileges.Privileges[0])*uintptr(i)))
+ item := (*windows.LUIDAndAttributes)(unsafe.Add(unsafe.Pointer(&tokenPrivileges.Privileges[0]), unsafe.Sizeof(tokenPrivileges.Privileges[0])*uintptr(i)))
if retainDriverLoading && item.Luid == luid {
continue
}
diff --git a/elevate/shellexecute.go b/elevate/shellexecute.go
index 2ac5581c..e0be9d98 100644
--- a/elevate/shellexecute.go
+++ b/elevate/shellexecute.go
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package elevate
@@ -24,7 +24,7 @@ const (
cSEE_MASK_DEFAULT = 0
)
-func ShellExecute(program string, arguments string, directory string, show int32) (err error) {
+func ShellExecute(program, arguments, directory string, show int32) (err error) {
var (
program16 *uint16
arguments16 *uint16
@@ -121,7 +121,7 @@ func ShellExecute(program string, arguments string, directory string, show int32
if err = windows.CoGetObject(
windows.StringToUTF16Ptr("Elevation:Administrator!new:{3E5FC7F9-9A51-4367-9063-A120244FBEC7}"),
&windows.BIND_OPTS3{
- CbStruct: uint32(unsafe.Sizeof(windows.BIND_OPTS3{})),
+ CbStruct: uint32(unsafe.Sizeof(windows.BIND_OPTS3{})),
ClassContext: windows.CLSCTX_LOCAL_SERVER,
},
&windows.GUID{0x6EDD6D74, 0xC007, 0x4E75, [8]byte{0xB7, 0x6A, 0xE5, 0x74, 0x09, 0x95, 0xE2, 0x4C}},
@@ -130,13 +130,13 @@ func ShellExecute(program string, arguments string, directory string, show int32
return
}
- defer syscall.Syscall((*interfacePointer)[releaseOffset], 1, uintptr(unsafe.Pointer(interfacePointer)), 0, 0)
+ defer syscall.SyscallN((*interfacePointer)[releaseOffset], uintptr(unsafe.Pointer(interfacePointer)))
if program16 == nil {
return
}
- if ret, _, _ := syscall.Syscall6((*interfacePointer)[shellExecuteOffset], 6,
+ if ret, _, _ := syscall.SyscallN((*interfacePointer)[shellExecuteOffset],
uintptr(unsafe.Pointer(interfacePointer)),
uintptr(unsafe.Pointer(program16)),
uintptr(unsafe.Pointer(arguments16)),
diff --git a/embeddable-dll-service/.gitignore b/embeddable-dll-service/.gitignore
new file mode 100644
index 00000000..9e3c52ab
--- /dev/null
+++ b/embeddable-dll-service/.gitignore
@@ -0,0 +1,4 @@
+# Build Output
+/x86
+/amd64
+/arm64
diff --git a/embeddable-dll-service/README.md b/embeddable-dll-service/README.md
index c93b4345..a326dc70 100644
--- a/embeddable-dll-service/README.md
+++ b/embeddable-dll-service/README.md
@@ -1,6 +1,6 @@
## Embeddable WireGuard Tunnel Library
-This allows embedding WireGuard as a service inside of another application. Build `tunnel.dll` by running `./build.bat` in this folder. The first time you run it, it will invoke `..\build.bat` simply for downloading dependencies. After, you should have `amd64/tunnel.dll` and `x86/tunnel.dll`.
+This allows embedding WireGuard as a service inside of another application. Build `tunnel.dll` by running `./build.bat` in this folder. The first time you run it, it will invoke `..\build.bat` simply for downloading dependencies. After, you should have `amd64/tunnel.dll`, `x86/tunnel.dll`, and `arm64/tunnel.dll`. In addition, `tunnel.dll` requires `wireguard.dll`, which can be downloaded from [the wireguard-nt download server](https://download.wireguard.com/wireguard-nt/).
The basic setup to use `tunnel.dll` is:
@@ -24,23 +24,18 @@ is absolutely essential; do not forget it.
##### 2. Have your program's main function handle the `/service` switch:
```c
-if (!strcmp(argv[1], "/service") && argc == 3) {
+if (wargc == 3 && !wcscmp(wargv[1], L"/service")) {
HMODULE tunnel_lib = LoadLibrary("tunnel.dll");
if (!tunnel_lib)
abort();
- tunnel_proc_t tunnel_proc = (tunnel_proc_t)GetProcAddress(tunnel_lib, "WireGuardTunnelService");
+ BOOL (_cdecl *tunnel_proc)(_In_ LPCWSTR conf_file);
+ *(FARPROC*)&tunnel_proc = GetProcAddress(tunnel_lib, "WireGuardTunnelService");
if (!tunnel_proc)
abort();
- struct go_string conf_file = {
- .str = argv[2],
- .n = strlen(argv[2])
- };
- return tunnel_proc(conf_file);
+ return tunnel_proc(wargv[2]);
}
```
##### 3. Scoop up logs by implementing a ringlogger format reader.
-##### 4. Talk to the service over its named pipe.
-
There is a sample implementation of bits and pieces of this inside of the `csharp\` directory.
diff --git a/embeddable-dll-service/build.bat b/embeddable-dll-service/build.bat
index 0d2cbdbb..b4c29000 100644
--- a/embeddable-dll-service/build.bat
+++ b/embeddable-dll-service/build.bat
@@ -1,6 +1,6 @@
@echo off
rem SPDX-License-Identifier: MIT
-rem Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+rem Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
setlocal
set BUILDDIR=%~dp0
@@ -21,9 +21,14 @@ if exist ..\.deps\prepared goto :build
set CGO_CFLAGS=-O3 -Wall -Wno-unused-function -Wno-switch -std=gnu11 -DWINVER=0x0601
call :build_plat x86 i686 386 || goto :error
call :build_plat amd64 x86_64 amd64 || goto :error
- rem Uncomment when cgo is implemented:
- rem call :build_plat arm armv7 arm || goto :error
- rem call :build_plat arm64 aarch64 arm64 || goto :error
+ call :build_plat arm64 aarch64 arm64 || goto :error
+
+:sign
+ if exist ..\sign.bat call ..\sign.bat
+ if "%SigningCertificate%"=="" goto :success
+ if "%TimestampServer%"=="" goto :success
+ echo [+] Signing
+ signtool sign /sha1 "%SigningCertificate%" /fd sha256 /tr "%TimestampServer%" /td sha256 /d "WireGuard Tunnel" x86\tunnel.dll amd64\tunnel.dll arm64\tunnel.dll || goto :error
:success
echo [+] Success
diff --git a/embeddable-dll-service/csharp/.gitignore b/embeddable-dll-service/csharp/.gitignore
new file mode 100644
index 00000000..28bcb4ab
--- /dev/null
+++ b/embeddable-dll-service/csharp/.gitignore
@@ -0,0 +1,3 @@
+/.vs
+/bin
+/obj
diff --git a/embeddable-dll-service/csharp/DemoUI/MainWindow.Designer.cs b/embeddable-dll-service/csharp/DemoUI/MainWindow.Designer.cs
index 5fae35d3..5aad1b97 100644
--- a/embeddable-dll-service/csharp/DemoUI/MainWindow.Designer.cs
+++ b/embeddable-dll-service/csharp/DemoUI/MainWindow.Designer.cs
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
namespace DemoUI
diff --git a/embeddable-dll-service/csharp/DemoUI/MainWindow.cs b/embeddable-dll-service/csharp/DemoUI/MainWindow.cs
index 7d1e3f6f..1df17181 100644
--- a/embeddable-dll-service/csharp/DemoUI/MainWindow.cs
+++ b/embeddable-dll-service/csharp/DemoUI/MainWindow.cs
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
using System;
@@ -66,49 +66,43 @@ namespace DemoUI
private void tailTransfer()
{
- StreamReader reader = null;
- NamedPipeClientStream stream = null;
+ Tunnel.Driver.Adapter adapter = null;
while (threadsRunning)
{
- try
+ if (adapter == null)
{
- stream = Tunnel.Service.GetPipe(configFile);
- stream.Connect();
- reader = new StreamReader(stream);
- break;
+ while (threadsRunning)
+ {
+ try
+ {
+ adapter = Tunnel.Service.GetAdapter(configFile);
+ break;
+ }
+ catch
+ {
+ try
+ {
+ Thread.Sleep(1000);
+ }
+ catch { }
+ }
+ }
}
- catch { }
- Thread.Sleep(1000);
- }
-
- try
- {
- while (threadsRunning)
+ if (adapter == null)
+ continue;
+ try
{
- stream.Write(Encoding.UTF8.GetBytes("get=1\n\n"));
ulong rx = 0, tx = 0;
- while (threadsRunning)
+ var config = adapter.GetConfiguration();
+ foreach (var peer in config.Peers)
{
- var line = reader.ReadLine();
- if (line == null)
- break;
- line = line.Trim();
- if (line.Length == 0)
- break;
- if (line.StartsWith("rx_bytes="))
- rx += ulong.Parse(line.Substring(9));
- else if (line.StartsWith("tx_bytes="))
- tx += ulong.Parse(line.Substring(9));
+ rx += peer.RxBytes;
+ tx += peer.TxBytes;
}
Invoke(new Action<ulong, ulong>(updateTransferTitle), new object[] { rx, tx });
Thread.Sleep(1000);
}
- }
- catch { }
- finally
- {
- if (stream.IsConnected)
- stream.Close();
+ catch { adapter = null; }
}
}
diff --git a/embeddable-dll-service/csharp/DemoUI/Program.cs b/embeddable-dll-service/csharp/DemoUI/Program.cs
index 8c420973..3649ab93 100644
--- a/embeddable-dll-service/csharp/DemoUI/Program.cs
+++ b/embeddable-dll-service/csharp/DemoUI/Program.cs
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
using System;
diff --git a/embeddable-dll-service/csharp/README.md b/embeddable-dll-service/csharp/README.md
index 071d15f6..24b36563 100644
--- a/embeddable-dll-service/csharp/README.md
+++ b/embeddable-dll-service/csharp/README.md
@@ -4,12 +4,4 @@ This is a simple client for demo.wireguard.com, which brings up WireGuard tunnel
## Building
-The code in this repository can be built in Visual Studio 2019 by opening the .sln and pressing build. However, it requires `tunnel.dll` to be present in the run directory. That can be built by:
-
-```batch
-> git clone https://git.zx2c4.com/wireguard-windows
-> cd wireguard-windows\embeddable-dll-service
-> .\build.bat
-```
-
-In addition, `tunnel.dll` requires `wintun.dll`, which can be downloaded from [wintun.net](https://www.wintun.net).
+The code in this repository can be built in Visual Studio 2019 by opening the .sln and pressing build. However, it requires [`tunnel.dll` and `wireguard.dll`](../README.md).
diff --git a/embeddable-dll-service/csharp/TunnelDll/Driver.cs b/embeddable-dll-service/csharp/TunnelDll/Driver.cs
new file mode 100644
index 00000000..69911ec8
--- /dev/null
+++ b/embeddable-dll-service/csharp/TunnelDll/Driver.cs
@@ -0,0 +1,234 @@
+/* SPDX-License-Identifier: MIT
+ *
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
+ */
+
+using System;
+using System.ComponentModel;
+using System.Net;
+using System.Runtime.InteropServices;
+
+namespace Tunnel
+{
+ public class Driver
+ {
+ [DllImport("wireguard.dll", EntryPoint = "WireGuardOpenAdapter", CallingConvention = CallingConvention.StdCall, SetLastError = true)]
+ private static extern IntPtr openAdapter([MarshalAs(UnmanagedType.LPWStr)] string name);
+ [DllImport("wireguard.dll", EntryPoint = "WireGuardCloseAdapter", CallingConvention = CallingConvention.StdCall)]
+ private static extern void freeAdapter(IntPtr adapter);
+ [DllImport("wireguard.dll", EntryPoint = "WireGuardGetConfiguration", CallingConvention = CallingConvention.StdCall, SetLastError = true)]
+ private static extern bool getConfiguration(IntPtr adapter, byte[] iface, ref UInt32 bytes);
+
+ public class Adapter
+ {
+ private IntPtr _handle;
+ private UInt32 _lastGetGuess;
+ public Adapter(string name)
+ {
+ _lastGetGuess = 1024;
+ _handle = openAdapter(name);
+ if (_handle == IntPtr.Zero)
+ throw new Win32Exception();
+ }
+ ~Adapter()
+ {
+ freeAdapter(_handle);
+ }
+ public unsafe Interface GetConfiguration()
+ {
+ var iface = new Interface();
+ byte[] bytes;
+ for (; ; )
+ {
+ bytes = new byte[_lastGetGuess];
+ if (getConfiguration(_handle, bytes, ref _lastGetGuess))
+ break;
+ if (Marshal.GetLastWin32Error() != 234 /* ERROR_MORE_DATA */)
+ throw new Win32Exception();
+ }
+ fixed (void* start = bytes)
+ {
+ var ioctlIface = (IoctlInterface*)start;
+ if ((ioctlIface->Flags & IoctlInterfaceFlags.HasPublicKey) != 0)
+ iface.PublicKey = new Key(ioctlIface->PublicKey);
+ if ((ioctlIface->Flags & IoctlInterfaceFlags.HasPrivateKey) != 0)
+ iface.PrivateKey = new Key(ioctlIface->PrivateKey);
+ if ((ioctlIface->Flags & IoctlInterfaceFlags.HasListenPort) != 0)
+ iface.ListenPort = ioctlIface->ListenPort;
+ var peers = new Peer[ioctlIface->PeersCount];
+ var ioctlPeer = (IoctlPeer*)((byte*)ioctlIface + sizeof(IoctlInterface));
+ for (UInt32 i = 0; i < peers.Length; ++i)
+ {
+ var peer = new Peer();
+ if ((ioctlPeer->Flags & IoctlPeerFlags.HasPublicKey) != 0)
+ peer.PublicKey = new Key(ioctlPeer->PublicKey);
+ if ((ioctlPeer->Flags & IoctlPeerFlags.HasPresharedKey) != 0)
+ peer.PresharedKey = new Key(ioctlPeer->PresharedKey);
+ if ((ioctlPeer->Flags & IoctlPeerFlags.HasPersistentKeepalive) != 0)
+ peer.PersistentKeepalive = ioctlPeer->PersistentKeepalive;
+ if ((ioctlPeer->Flags & IoctlPeerFlags.HasEndpoint) != 0)
+ {
+ if (ioctlPeer->Endpoint.si_family == Win32.ADDRESS_FAMILY.AF_INET)
+ {
+ var ip = new byte[4];
+ Marshal.Copy((IntPtr)ioctlPeer->Endpoint.Ipv4.sin_addr.bytes, ip, 0, 4);
+ peer.Endpoint = new IPEndPoint(new IPAddress(ip), (ushort)IPAddress.NetworkToHostOrder((short)ioctlPeer->Endpoint.Ipv4.sin_port));
+ }
+ else if (ioctlPeer->Endpoint.si_family == Win32.ADDRESS_FAMILY.AF_INET6)
+ {
+ var ip = new byte[16];
+ Marshal.Copy((IntPtr)ioctlPeer->Endpoint.Ipv6.sin6_addr.bytes, ip, 0, 16);
+ peer.Endpoint = new IPEndPoint(new IPAddress(ip), (ushort)IPAddress.NetworkToHostOrder((short)ioctlPeer->Endpoint.Ipv6.sin6_port));
+ }
+ }
+ peer.TxBytes = ioctlPeer->TxBytes;
+ peer.RxBytes = ioctlPeer->RxBytes;
+ if (ioctlPeer->LastHandshake != 0)
+ peer.LastHandshake = DateTime.FromFileTimeUtc((long)ioctlPeer->LastHandshake);
+ var allowedIPs = new AllowedIP[ioctlPeer->AllowedIPsCount];
+ var ioctlAllowedIP = (IoctlAllowedIP*)((byte*)ioctlPeer + sizeof(IoctlPeer));
+ for (UInt32 j = 0; j < allowedIPs.Length; ++j)
+ {
+ var allowedIP = new AllowedIP();
+ if (ioctlAllowedIP->AddressFamily == Win32.ADDRESS_FAMILY.AF_INET)
+ {
+ var ip = new byte[4];
+ Marshal.Copy((IntPtr)ioctlAllowedIP->V4.bytes, ip, 0, 4);
+ allowedIP.Address = new IPAddress(ip);
+ }
+ else if (ioctlAllowedIP->AddressFamily == Win32.ADDRESS_FAMILY.AF_INET6)
+ {
+ var ip = new byte[16];
+ Marshal.Copy((IntPtr)ioctlAllowedIP->V6.bytes, ip, 0, 16);
+ allowedIP.Address = new IPAddress(ip);
+ }
+ allowedIP.Cidr = ioctlAllowedIP->Cidr;
+ allowedIPs[j] = allowedIP;
+ ioctlAllowedIP = (IoctlAllowedIP*)((byte*)ioctlAllowedIP + sizeof(IoctlAllowedIP));
+ }
+ peer.AllowedIPs = allowedIPs;
+ peers[i] = peer;
+ ioctlPeer = (IoctlPeer*)ioctlAllowedIP;
+ }
+ iface.Peers = peers;
+ }
+ return iface;
+ }
+
+ public class Key
+ {
+ private byte[] _bytes;
+ public byte[] Bytes
+ {
+ get
+ {
+ return _bytes;
+ }
+ set
+ {
+ if (value == null || value.Length != 32)
+ throw new ArgumentException("Keys must be 32 bytes");
+ _bytes = value;
+ }
+ }
+ public Key(byte[] bytes)
+ {
+ Bytes = bytes;
+ }
+ public unsafe Key(byte* bytes)
+ {
+ _bytes = new byte[32];
+ Marshal.Copy((IntPtr)bytes, _bytes, 0, 32);
+ }
+ public override String ToString()
+ {
+ return Convert.ToBase64String(_bytes);
+ }
+ }
+
+ public class Interface
+ {
+ public UInt16 ListenPort { get; set; }
+ public Key PrivateKey { get; set; }
+ public Key PublicKey { get; set; }
+ public Peer[] Peers { get; set; }
+ }
+
+ public class Peer
+ {
+ public Key PublicKey { get; set; }
+ public Key PresharedKey { get; set; }
+ public UInt16 PersistentKeepalive { get; set; }
+ public IPEndPoint Endpoint { get; set; }
+ public UInt64 TxBytes { get; set; }
+ public UInt64 RxBytes { get; set; }
+ public DateTime LastHandshake { get; set; }
+ public AllowedIP[] AllowedIPs { get; set; }
+ }
+
+ public class AllowedIP
+ {
+ public IPAddress Address { get; set; }
+ public byte Cidr { get; set; }
+ }
+
+ private enum IoctlInterfaceFlags : UInt32
+ {
+ HasPublicKey = 1 << 0,
+ HasPrivateKey = 1 << 1,
+ HasListenPort = 1 << 2,
+ ReplacePeers = 1 << 3
+ };
+
+ [StructLayout(LayoutKind.Sequential, Pack = 8, Size = 80)]
+ private unsafe struct IoctlInterface
+ {
+ public IoctlInterfaceFlags Flags;
+ public UInt16 ListenPort;
+ public fixed byte PrivateKey[32];
+ public fixed byte PublicKey[32];
+ public UInt32 PeersCount;
+ };
+
+ private enum IoctlPeerFlags : UInt32
+ {
+ HasPublicKey = 1 << 0,
+ HasPresharedKey = 1 << 1,
+ HasPersistentKeepalive = 1 << 2,
+ HasEndpoint = 1 << 3,
+ ReplaceAllowedIPs = 1 << 5,
+ Remove = 1 << 6,
+ UpdateOnly = 1 << 7
+ };
+
+ [StructLayout(LayoutKind.Sequential, Pack = 8, Size = 136)]
+ private unsafe struct IoctlPeer
+ {
+ public IoctlPeerFlags Flags;
+ public UInt32 Reserved;
+ public fixed byte PublicKey[32];
+ public fixed byte PresharedKey[32];
+ public UInt16 PersistentKeepalive;
+ public Win32.SOCKADDR_INET Endpoint;
+ public UInt64 TxBytes, RxBytes;
+ public UInt64 LastHandshake;
+ public UInt32 AllowedIPsCount;
+ };
+
+ [StructLayout(LayoutKind.Explicit, Pack = 8, Size = 24)]
+ private unsafe struct IoctlAllowedIP
+ {
+ [FieldOffset(0)]
+ [MarshalAs(UnmanagedType.Struct)]
+ public Win32.IN_ADDR V4;
+ [FieldOffset(0)]
+ [MarshalAs(UnmanagedType.Struct)]
+ public Win32.IN6_ADDR V6;
+ [FieldOffset(16)]
+ public Win32.ADDRESS_FAMILY AddressFamily;
+ [FieldOffset(20)]
+ public byte Cidr;
+ }
+ }
+ }
+}
diff --git a/embeddable-dll-service/csharp/TunnelDll/Keypair.cs b/embeddable-dll-service/csharp/TunnelDll/Keypair.cs
index 146d56e0..59847b98 100644
--- a/embeddable-dll-service/csharp/TunnelDll/Keypair.cs
+++ b/embeddable-dll-service/csharp/TunnelDll/Keypair.cs
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
using System;
diff --git a/embeddable-dll-service/csharp/TunnelDll/Ringlogger.cs b/embeddable-dll-service/csharp/TunnelDll/Ringlogger.cs
index 469927c1..9db01fc8 100644
--- a/embeddable-dll-service/csharp/TunnelDll/Ringlogger.cs
+++ b/embeddable-dll-service/csharp/TunnelDll/Ringlogger.cs
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
using System;
diff --git a/embeddable-dll-service/csharp/TunnelDll/Service.cs b/embeddable-dll-service/csharp/TunnelDll/Service.cs
index 7f2c622e..74e1a888 100644
--- a/embeddable-dll-service/csharp/TunnelDll/Service.cs
+++ b/embeddable-dll-service/csharp/TunnelDll/Service.cs
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
using System;
@@ -21,10 +21,9 @@ namespace Tunnel
[DllImport("tunnel.dll", EntryPoint = "WireGuardTunnelService", CallingConvention = CallingConvention.Cdecl)]
public static extern bool Run([MarshalAs(UnmanagedType.LPWStr)] string configFile);
- public static NamedPipeClientStream GetPipe(string configFile)
+ public static Driver.Adapter GetAdapter(string configFile)
{
- var pipepath = "ProtectedPrefix\\Administrators\\WireGuard\\" + Path.GetFileNameWithoutExtension(configFile);
- return new NamedPipeClientStream(pipepath);
+ return new Driver.Adapter(Path.GetFileNameWithoutExtension(configFile));
}
public static void Add(string configFile, bool ephemeral)
@@ -46,7 +45,7 @@ namespace Tunnel
Win32.CloseServiceHandle(service);
Remove(configFile, true);
}
- service = Win32.CreateService(scm, shortName, longName, Win32.ServiceAccessRights.AllAccess, Win32.ServiceType.Win32OwnProcess, Win32.ServiceStartType.Demand, Win32.ServiceError.Normal, pathAndArgs, null, IntPtr.Zero, "Nsi\0TcpIp", null, null);
+ service = Win32.CreateService(scm, shortName, longName, Win32.ServiceAccessRights.AllAccess, Win32.ServiceType.Win32OwnProcess, Win32.ServiceStartType.Demand, Win32.ServiceError.Normal, pathAndArgs, null, IntPtr.Zero, "Nsi\0TcpIp\0", null, null);
if (service == IntPtr.Zero)
throw new Win32Exception(Marshal.GetLastWin32Error());
try
@@ -88,10 +87,7 @@ namespace Tunnel
{
var service = Win32.OpenService(scm, shortName, Win32.ServiceAccessRights.AllAccess);
if (service == IntPtr.Zero)
- {
- Win32.CloseServiceHandle(service);
return;
- }
try
{
var serviceStatus = new Win32.ServiceStatus();
diff --git a/embeddable-dll-service/csharp/TunnelDll/Win32.cs b/embeddable-dll-service/csharp/TunnelDll/Win32.cs
index d8447f7f..8e7f986d 100644
--- a/embeddable-dll-service/csharp/TunnelDll/Win32.cs
+++ b/embeddable-dll-service/csharp/TunnelDll/Win32.cs
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
using System;
@@ -135,6 +135,58 @@ namespace Tunnel
SidInfo = 5
}
+ [StructLayout(LayoutKind.Sequential)]
+ public unsafe struct IN_ADDR
+ {
+ public fixed byte bytes[4];
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ public unsafe struct IN6_ADDR
+ {
+ public fixed byte bytes[16];
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ public struct SOCKADDR_IN
+ {
+ public ushort sin_family;
+ public ushort sin_port;
+ public IN_ADDR sin_addr;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ public struct SOCKADDR_IN6
+ {
+ public ushort sin6_family;
+ public ushort sin6_port;
+ public uint sin6_flowinfo;
+ public IN6_ADDR sin6_addr;
+ public uint sin6_scope_id;
+ }
+
+ [StructLayout(LayoutKind.Explicit)]
+ public struct SOCKADDR_INET
+ {
+ [FieldOffset(0)]
+ [MarshalAs(UnmanagedType.Struct)]
+ public SOCKADDR_IN Ipv4;
+
+ [FieldOffset(0)]
+ [MarshalAs(UnmanagedType.Struct)]
+ public SOCKADDR_IN6 Ipv6;
+
+ [FieldOffset(0)]
+ public ADDRESS_FAMILY si_family;
+ }
+
+ public enum ADDRESS_FAMILY : UInt16
+ {
+ AF_UNSPEC = 0,
+ AF_INET = 2,
+ AF_INET6 = 23
+ }
+
[DllImport("advapi32.dll", EntryPoint = "OpenSCManagerW", ExactSpelling = true, CharSet = CharSet.Unicode, SetLastError = true)]
public static extern IntPtr OpenSCManager(string machineName, string databaseName, ScmAccessRights dwDesiredAccess);
diff --git a/embeddable-dll-service/main.go b/embeddable-dll-service/main.go
index df63034e..f313ae7f 100644
--- a/embeddable-dll-service/main.go
+++ b/embeddable-dll-service/main.go
@@ -1,23 +1,22 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package main
import (
"C"
+ "crypto/rand"
+ "log"
+ "path/filepath"
+ "unsafe"
"golang.org/x/crypto/curve25519"
"golang.org/x/sys/windows"
"golang.zx2c4.com/wireguard/windows/conf"
"golang.zx2c4.com/wireguard/windows/tunnel"
-
- "crypto/rand"
- "log"
- "path/filepath"
- "unsafe"
)
//export WireGuardTunnelService
@@ -33,7 +32,7 @@ func WireGuardTunnelService(confFile16 *uint16) bool {
}
//export WireGuardGenerateKeypair
-func WireGuardGenerateKeypair(publicKey *byte, privateKey *byte) {
+func WireGuardGenerateKeypair(publicKey, privateKey *byte) {
publicKeyArray := (*[32]byte)(unsafe.Pointer(publicKey))
privateKeyArray := (*[32]byte)(unsafe.Pointer(privateKey))
n, err := rand.Read(privateKeyArray[:])
diff --git a/go.mod b/go.mod
index 8c85ec21..84a49f75 100644
--- a/go.mod
+++ b/go.mod
@@ -1,15 +1,20 @@
module golang.zx2c4.com/wireguard/windows
-go 1.16
+go 1.18
require (
github.com/lxn/walk v0.0.0-20210112085537-c389da54e794
github.com/lxn/win v0.0.0-20210218163916-a377121e959e
- golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2
- golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4
- golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57
- golang.org/x/text v0.3.6
- golang.zx2c4.com/wireguard v0.0.0-20210409202608-75526d60714c
+ golang.org/x/crypto v0.0.0-20220315160706-3147a52a75dd
+ golang.org/x/net v0.0.0-20220225172249-27dd8689420f
+ golang.org/x/sys v0.0.0-20220315194320-039c03cc5b86
+ golang.org/x/text v0.3.8-0.20220124021120-d1c84af989ab
+)
+
+require (
+ golang.org/x/mod v0.4.2 // indirect
+ golang.org/x/tools v0.1.7 // indirect
+ golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
)
replace (
diff --git a/go.mod.master b/go.mod.master
index a61c1ed9..ca40b2f0 100644
--- a/go.mod.master
+++ b/go.mod.master
@@ -1,6 +1,6 @@
module golang.zx2c4.com/wireguard/windows
-go 1.16
+go 1.18
require (
github.com/lxn/walk latest
@@ -9,7 +9,6 @@ require (
golang.org/x/net latest
golang.org/x/sys latest
golang.org/x/text master
- golang.zx2c4.com/wireguard master
)
replace (
diff --git a/go.sum b/go.sum
index 2ae11467..c402ce70 100644
--- a/go.sum
+++ b/go.sum
@@ -1,29 +1,28 @@
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
-golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
-golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2 h1:It14KIkyBFYkHkwZ7k45minvA9aorojkyjGk9KJ5B/w=
-golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
+golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
+golang.org/x/crypto v0.0.0-20220315160706-3147a52a75dd h1:XcWmESyNjXJMLahc3mqVQJcgSTDxFxhETVlfk9uGc38=
+golang.org/x/crypto v0.0.0-20220315160706-3147a52a75dd/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
+golang.org/x/mod v0.4.2 h1:Gz96sIWK3OalVv/I/qNygP42zyoKp3xptRVCWRFEBvo=
+golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
-golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
-golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4 h1:4nGaVu0QrbjT/AK2PRLuQfQuh6DJve+pELhqTdAj3x0=
-golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
+golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
+golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
-golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201018230417-eeed37f84f13/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210309040221-94ec62e08169/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57 h1:F5Gozwx4I1xtr/sr/8CFbb57iKi3297KFs0QDbGN60A=
-golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
-golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
+golang.org/x/sys v0.0.0-20220315194320-039c03cc5b86 h1:A9i04dxx7Cribqbs8jf3FQLogkL/CV2YN7hj9KWJCkc=
+golang.org/x/sys v0.0.0-20220315194320-039c03cc5b86/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
-golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
-golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M=
-golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
-golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e h1:FDhOuMEY4JVRztM/gsbk+IKUQ8kj74bxZrgw87eMMVc=
-golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
-golang.zx2c4.com/wireguard v0.0.0-20210409202608-75526d60714c h1:XRNeg3YTKFRna0lwwswhrxNM5nyeS6WIUcmB+NkPB5c=
-golang.zx2c4.com/wireguard v0.0.0-20210409202608-75526d60714c/go.mod h1:a057zjmoc00UN7gVkaJt2sXVK523kMJcogDTEvPIasg=
+golang.org/x/text v0.3.8-0.20220124021120-d1c84af989ab h1:eHo2TTVBaAPw9lDGK2Gb9GyPMXT6g7O63W6sx3ylbzU=
+golang.org/x/text v0.3.8-0.20220124021120-d1c84af989ab/go.mod h1:EFNZuWvGYxIRUEX+K8UmCFwYmZjqcrnq15ZuVldZkZ0=
+golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.1.7 h1:6j8CgantCy3yc8JGBqkDLMKWqZ0RDU2g1HVgacojGWQ=
+golang.org/x/tools v0.1.7/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo=
+golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
+golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.zx2c4.com/wireguard/windows v0.0.0-20210121140954-e7fc19d483bd h1:kAUzMAITME2MCtrXBaUa9P4tndiXGWO674k9gn6ZR28=
golang.zx2c4.com/wireguard/windows v0.0.0-20210121140954-e7fc19d483bd/go.mod h1:Y+FYqVFaQO6a+1uigm0N0GiuaZrLEaBxEiJ8tfH9sMQ=
golang.zx2c4.com/wireguard/windows v0.0.0-20210224134948-620c54ef6199 h1:ogXKLng/Myrt2odYTkleySGzQj/GWg9GV1AQ8P9NnU4=
diff --git a/gotext.go b/gotext.go
index 0ed7401c..db39bdd3 100644
--- a/gotext.go
+++ b/gotext.go
@@ -1,9 +1,10 @@
-// +build generate
+//go:build generate
+
//go:generate go run gotext.go
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package main
diff --git a/installer/build.bat b/installer/build.bat
index c9da9c91..60d2558c 100644
--- a/installer/build.bat
+++ b/installer/build.bat
@@ -1,6 +1,6 @@
@echo off
rem SPDX-License-Identifier: MIT
-rem Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+rem Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
setlocal
set PATHEXT=.exe
@@ -31,6 +31,7 @@ if exist .deps\prepared goto :build
cd .. || goto :error
:build
+ if exist ..\sign.bat call ..\sign.bat
set PATH=%BUILDDIR%..\.deps\llvm-mingw\bin;%PATH%
set WIX=%BUILDDIR%.deps\wix\
set CFLAGS=-O3 -Wall -std=gnu11 -DWINVER=0x0601 -D_WIN32_WINNT=0x0601 -municode -DUNICODE -D_UNICODE -DNDEBUG
@@ -38,9 +39,7 @@ if exist .deps\prepared goto :build
set LDLIBS=-lmsi -lole32 -lshlwapi -lshell32 -luuid -lntdll
call :msi x86 i686 x86 || goto :error
call :msi amd64 x86_64 x64 || goto :error
- call :msi arm armv7 arm || goto :error
call :msi arm64 aarch64 arm64 || goto :error
- if exist ..\sign.bat call ..\sign.bat
if "%SigningCertificate%"=="" goto :success
if "%TimestampServer%"=="" goto :success
echo [+] Signing
@@ -62,6 +61,11 @@ if exist .deps\prepared goto :build
if not exist "%~1" mkdir "%~1"
echo [+] Compiling %1
%CC% %CFLAGS% %LDFLAGS% -o "%~1\customactions.dll" customactions.c %LDLIBS% || exit /b 1
+ if "%SigningCertificate%"=="" goto :skipsign
+ if "%TimestampServer%"=="" goto :skipsign
+ echo [+] Signing %1
+ signtool sign /sha1 "%SigningCertificate%" /fd sha256 /tr "%TimestampServer%" /td sha256 /d "WireGuard Setup Custom Actions" "%~1\customactions.dll" || exit /b 1
+:skipsign
"%WIX%bin\candle" %WIX_CANDLE_FLAGS% -dWIREGUARD_PLATFORM="%~1" -out "%~1\wireguard.wixobj" -arch %3 wireguard.wxs || exit /b %errorlevel%
echo [+] Linking %1
"%WIX%bin\light" %WIX_LIGHT_FLAGS% -out "dist\wireguard-%~1-%WIREGUARD_VERSION%.msi" "%~1\wireguard.wixobj" || exit /b %errorlevel%
diff --git a/installer/customactions.c b/installer/customactions.c
index 981415e1..d3078a31 100644
--- a/installer/customactions.c
+++ b/installer/customactions.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: MIT
/*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
#include <windows.h>
@@ -96,7 +96,7 @@ __declspec(dllexport) UINT __stdcall CheckWow64(MSIHANDLE installer)
log_errorf(installer, LOG_LEVEL_ERR, ret, TEXT("Failed to get kernel32.dll handle"));
goto out;
}
- IsWow64Process2 = (void *)GetProcAddress(kernel32, "IsWow64Process2");
+ *(FARPROC *)&IsWow64Process2 = GetProcAddress(kernel32, "IsWow64Process2");
if (IsWow64Process2) {
if (!IsWow64Process2(GetCurrentProcess(), &process_machine, &native_machine)) {
ret = GetLastError();
@@ -122,94 +122,6 @@ out:
return ret;
}
-extern NTAPI __declspec(dllimport) void RtlGetNtVersionNumbers(DWORD *MajorVersion, DWORD *MinorVersion, DWORD *BuildNumber);
-
-static int message_box(MSIHANDLE installer, TCHAR *text, UINT type)
-{
- TCHAR progressOnly[2];
- DWORD len;
- MSIHANDLE record;
- int ret;
-
- len = _countof(progressOnly);
- if (MsiGetProperty(installer, TEXT("MsiUIProgressOnly"), progressOnly, &len) == ERROR_SUCCESS && _tcstoul(progressOnly, NULL, 10) == 1)
- return MessageBox(GetForegroundWindow(), text, TEXT("WireGuard"), type);
- record = MsiCreateRecord(2);
- MsiRecordSetString(record, 0, TEXT("[1]"));
- MsiRecordSetString(record, 1, text);
- ret = MsiProcessMessage(installer, INSTALLMESSAGE_USER | type, record);
- MsiCloseHandle(record);
- return ret;
-}
-
-__declspec(dllexport) UINT __stdcall CheckKB2921916(MSIHANDLE installer)
-{
- bool is_com_initialized = SUCCEEDED(CoInitialize(NULL));
- UINT ret = ERROR_SUCCESS;
- DWORD maj, min, build, len;
- TCHAR uiLevel[10];
- TCHAR setupapi_path[MAX_PATH];
- HANDLE setupapi_handle = INVALID_HANDLE_VALUE;
- HANDLE setupapi_filemapping = NULL;
- const char *setupapi_bytes = NULL;
- MEMORY_BASIC_INFORMATION setupapi_meminfo;
- static const char setupapi_marker[] = "Signature Hash";
-
- RtlGetNtVersionNumbers(&maj, &min, &build);
- if (maj != 6 || min != 1)
- goto out;
-
- ret = ERROR_INSTALL_FAILURE;
- if (!GetSystemDirectory(setupapi_path, _countof(setupapi_path)))
- goto out;
- if (!PathAppend(setupapi_path, TEXT("setupapi.dll")))
- goto out;
- setupapi_handle = CreateFile(setupapi_path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
- if (setupapi_handle == INVALID_HANDLE_VALUE)
- goto out;
- setupapi_filemapping = CreateFileMapping(setupapi_handle, NULL, PAGE_READONLY, 0, 0, NULL);
- if (!setupapi_filemapping)
- goto out;
- setupapi_bytes = MapViewOfFile(setupapi_filemapping, FILE_MAP_READ, 0, 0, 0);
- if (!setupapi_bytes)
- goto out;
- if (VirtualQuery(setupapi_bytes, &setupapi_meminfo, sizeof(setupapi_meminfo)) != sizeof(setupapi_meminfo))
- goto out;
- if (setupapi_meminfo.RegionSize > strlen(setupapi_marker)) {
- for (const char *p = setupapi_bytes + strlen(setupapi_marker) - 1; (p = memchr(p, 'h', setupapi_meminfo.RegionSize - (p - setupapi_bytes))); ++p) {
- if (!memcmp(p - strlen(setupapi_marker) + 1, setupapi_marker, strlen(setupapi_marker))) {
- ret = ERROR_SUCCESS;
- goto out;
- }
- }
- }
-
- len = _countof(uiLevel);
- if (MsiGetProperty(installer, TEXT("UILevel"), uiLevel, &len) != ERROR_SUCCESS || _tcstoul(uiLevel, NULL, 10) < INSTALLUILEVEL_BASIC) {
- log_messagef(installer, LOG_LEVEL_MSIERR, TEXT("Use of WireGuard on Windows 7 requires KB2921916."));
- goto out;
- }
-#ifdef _WIN64
- static const TCHAR url[] = TEXT("https://download.wireguard.com/windows-toolchain/distfiles/Windows6.1-KB2921916-x64.msu");
-#else
- static const TCHAR url[] = TEXT("https://download.wireguard.com/windows-toolchain/distfiles/Windows6.1-KB2921916-x86.msu");
-#endif
- if (message_box(installer, TEXT("Missing Windows Hotfix\n\nUse of WireGuard on Windows 7 requires KB2921916. Would you like to download the hotfix in your web browser?"), MB_ICONWARNING | MB_YESNO) == IDYES)
- ShellExecute(GetForegroundWindow(), NULL, url, NULL, NULL, SW_SHOWNORMAL);
- ret = ERROR_INSTALL_USEREXIT;
-
-out:
- if (setupapi_bytes)
- UnmapViewOfFile(setupapi_bytes);
- if (setupapi_filemapping)
- CloseHandle(setupapi_filemapping);
- if (setupapi_handle != INVALID_HANDLE_VALUE)
- CloseHandle(setupapi_handle);
- if (is_com_initialized)
- CoUninitialize();
- return ret;
-}
-
static UINT insert_service_control(MSIHANDLE installer, MSIHANDLE view, const TCHAR *service_name, bool start)
{
static unsigned int index = 0;
@@ -607,7 +519,7 @@ __declspec(dllexport) UINT __stdcall RemoveAdapters(MSIHANDLE installer)
log_errorf(installer, LOG_LEVEL_WARN, GetLastError(), TEXT("SetHandleInformation failed"));
goto cleanup_pipe_w;
}
- if (!CreateProcess(path, TEXT("wireguard /removealladapters"), NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi)) {
+ if (!CreateProcess(path, TEXT("wireguard /removedriver"), NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi)) {
log_errorf(installer, LOG_LEVEL_WARN, GetLastError(), TEXT("Failed to create \"%1\" process"), path);
goto cleanup_pipe_w;
}
diff --git a/installer/fetcher/Makefile b/installer/fetcher/Makefile
index 8bc06ff1..a247adfe 100644
--- a/installer/fetcher/Makefile
+++ b/installer/fetcher/Makefile
@@ -1,6 +1,6 @@
# SPDX-License-Identifier: GPL-2.0
#
-# Copyright (C) 2015-2021 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
+# Copyright (C) 2015-2022 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
CFLAGS ?= -Os
DEPLOYMENT_HOST ?= winvm
diff --git a/installer/fetcher/constants.h b/installer/fetcher/constants.h
index 8f2f3403..96d88d0e 100644
--- a/installer/fetcher/constants.h
+++ b/installer/fetcher/constants.h
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0
*
- * Copyright (C) 2020-2021 Jason A. Donenfeld. All Rights Reserved.
+ * Copyright (C) 2020-2022 Jason A. Donenfeld. All Rights Reserved.
*/
#ifndef _CONSTANTS_H
diff --git a/installer/fetcher/crypto.c b/installer/fetcher/crypto.c
index 880cff30..33154efb 100644
--- a/installer/fetcher/crypto.c
+++ b/installer/fetcher/crypto.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0
/*
- * Copyright (C) 2020-2021 Jason A. Donenfeld. All Rights Reserved.
+ * Copyright (C) 2020-2022 Jason A. Donenfeld. All Rights Reserved.
* Copyright (c) 2020, Google Inc.
*/
@@ -2239,7 +2239,7 @@ void blake2b256_update(struct blake2b256_state *state, const uint8_t *in,
state->buflen += inlen;
}
-void blake2b256_final(struct blake2b256_state *state, uint8_t *out)
+void blake2b256_final(struct blake2b256_state *state, uint8_t out[32])
{
state->t[0] += state->buflen;
state->t[1] += (state->t[0] < state->buflen);
@@ -2247,6 +2247,6 @@ void blake2b256_final(struct blake2b256_state *state, uint8_t *out)
memset(state->buf + state->buflen, 0, 128 - state->buflen);
blake2b256_compress(state, state->buf);
- for (int i = 0; i < 8; ++i)
+ for (int i = 0; i < 4; ++i)
store_le64(out + i * sizeof(state->h[i]), state->h[i]);
}
diff --git a/installer/fetcher/crypto.h b/installer/fetcher/crypto.h
index 51691a46..dc234ec7 100644
--- a/installer/fetcher/crypto.h
+++ b/installer/fetcher/crypto.h
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0
*
- * Copyright (C) 2020-2021 Jason A. Donenfeld. All Rights Reserved.
+ * Copyright (C) 2020-2022 Jason A. Donenfeld. All Rights Reserved.
*/
#ifndef _CRYPTO_H
@@ -21,7 +21,7 @@ struct blake2b256_state {
void blake2b256_init(struct blake2b256_state *state);
void blake2b256_update(struct blake2b256_state *state, const uint8_t *in,
unsigned int inlen);
-void blake2b256_final(struct blake2b256_state *state, uint8_t *out);
+void blake2b256_final(struct blake2b256_state *state, uint8_t out[32]);
bool ed25519_verify(const uint8_t signature[64], const uint8_t public_key[32],
const void *message, size_t message_size);
diff --git a/installer/fetcher/fetcher.c b/installer/fetcher/fetcher.c
index e9d23567..5c688997 100644
--- a/installer/fetcher/fetcher.c
+++ b/installer/fetcher/fetcher.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0
/*
- * Copyright (C) 2020-2021 Jason A. Donenfeld. All Rights Reserved.
+ * Copyright (C) 2020-2022 Jason A. Donenfeld. All Rights Reserved.
*/
#include <windows.h>
@@ -23,7 +23,7 @@
#include "constants.h"
static char msi_filename[MAX_PATH];
-static volatile bool msi_filename_is_set;
+static volatile bool msi_filename_is_set, prompts = true;
static volatile size_t g_current, g_total;
static HWND progress;
static HANDLE filehandle = INVALID_HANDLE_VALUE;
@@ -114,6 +114,12 @@ static DWORD __stdcall download_thread(void *param)
if (!session)
goto out;
WinHttpSetOption(session, WINHTTP_OPTION_ENABLE_HTTP_PROTOCOL, &enable_http2, sizeof(enable_http2)); // Don't check return value, in case of old Windows
+ if (is_win8dotzero_or_below()) {
+ DWORD enable_tls12 = WINHTTP_FLAG_SECURE_PROTOCOL_TLS1_2;
+ if (!WinHttpSetOption(session, WINHTTP_OPTION_SECURE_PROTOCOLS, &enable_tls12, sizeof(enable_tls12)))
+ goto out;
+ }
+
connection = WinHttpConnect(session, L(server), port, 0);
if (!connection)
goto out;
@@ -181,7 +187,10 @@ static DWORD __stdcall download_thread(void *param)
CloseHandle(filehandle); //TODO: I wish this wasn't required.
filehandle = INVALID_HANDLE_VALUE;
wintrust_fileinfo.pcwszFilePath = L(msi_filename);
- if (WinVerifyTrust(INVALID_HANDLE_VALUE, &(GUID)WINTRUST_ACTION_GENERIC_VERIFY_V2, &wintrust_data))
+ ret = WinVerifyTrustEx(INVALID_HANDLE_VALUE, &(GUID)WINTRUST_ACTION_GENERIC_VERIFY_V2, &wintrust_data);
+ wintrust_data.dwStateAction = WTD_STATEACTION_CLOSE;
+ WinVerifyTrustEx(INVALID_HANDLE_VALUE, &(GUID)WINTRUST_ACTION_GENERIC_VERIFY_V2, &wintrust_data);
+ if (ret)
goto out;
set_status(progress, "launching installer");
@@ -199,7 +208,7 @@ out:
if (security_attributes.lpSecurityDescriptor)
LocalFree(security_attributes.lpSecurityDescriptor);
- if (ret) {
+ if (ret && prompts) {
ShowWindow(progress, SW_SHOWDEFAULT);
if (MessageBoxA(progress, "Something went wrong when downloading the WireGuard installer. Would you like to open your web browser to the MSI download page?", "Download Error", MB_YESNO | MB_ICONWARNING) == IDYES)
ShellExecuteA(progress, NULL, "https://" server msi_path, NULL, NULL, SW_SHOWNORMAL);
@@ -276,6 +285,20 @@ static LRESULT CALLBACK wndproc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lPar
return DefSubclassProc(hWnd, uMsg, wParam, lParam);
}
+static void parse_command_line(void)
+{
+ LPWSTR *argv;
+ int argc;
+ argv = CommandLineToArgvW(GetCommandLineW(), &argc);
+ if (!argv)
+ return;
+ for (int i = 1; i < argc; ++i) {
+ if (wcsicmp(argv[i], L"/noprompt") == 0)
+ prompts = false;
+ }
+ LocalFree(argv);
+}
+
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR pCmdLine, int nCmdShow)
{
MSG msg;
@@ -288,6 +311,8 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR pCmdLine,
if (!SetDllDirectoryA("") || !SetDefaultDllDirectories(LOAD_LIBRARY_SEARCH_SYSTEM32))
return 1;
+ parse_command_line();
+
InitCommonControlsEx(&(INITCOMMONCONTROLSEX){ .dwSize = sizeof(INITCOMMONCONTROLSEX), .dwICC = ICC_PROGRESS_CLASS });
progress = CreateWindowExA(0, PROGRESS_CLASS, "WireGuard Installer",
diff --git a/installer/fetcher/filelist.c b/installer/fetcher/filelist.c
index a65c397d..f938e324 100644
--- a/installer/fetcher/filelist.c
+++ b/installer/fetcher/filelist.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0
/*
- * Copyright (C) 2020-2021 Jason A. Donenfeld. All Rights Reserved.
+ * Copyright (C) 2020-2022 Jason A. Donenfeld. All Rights Reserved.
*/
#include "constants.h"
diff --git a/installer/fetcher/filelist.h b/installer/fetcher/filelist.h
index 7b3b7263..7da57470 100644
--- a/installer/fetcher/filelist.h
+++ b/installer/fetcher/filelist.h
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0
*
- * Copyright (C) 2020-2021 Jason A. Donenfeld. All Rights Reserved.
+ * Copyright (C) 2020-2022 Jason A. Donenfeld. All Rights Reserved.
*/
#ifndef _FILELIST_H
diff --git a/installer/fetcher/resources.rc b/installer/fetcher/resources.rc
index 771c6d46..f2bedb66 100644
--- a/installer/fetcher/resources.rc
+++ b/installer/fetcher/resources.rc
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0
*
- * Copyright (C) 2020-2021 Jason A. Donenfeld. All Rights Reserved.
+ * Copyright (C) 2020-2022 Jason A. Donenfeld. All Rights Reserved.
*/
#include <windows.h>
@@ -27,7 +27,7 @@ BEGIN
VALUE "FileDescription", "WireGuard Installer: Fast, Modern, Secure VPN Tunnel"
VALUE "FileVersion", VERSION_STR
VALUE "InternalName", "wireguard-installer"
- VALUE "LegalCopyright", "Copyright © 2015-2021 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved."
+ VALUE "LegalCopyright", "Copyright © 2015-2022 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved."
VALUE "OriginalFilename", "wireguard-installer.exe"
VALUE "ProductName", "WireGuard"
VALUE "ProductVersion", VERSION_STR
diff --git a/installer/fetcher/systeminfo.c b/installer/fetcher/systeminfo.c
index 2281226b..f1f80e7f 100644
--- a/installer/fetcher/systeminfo.c
+++ b/installer/fetcher/systeminfo.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0
/*
- * Copyright (C) 2020-2021 Jason A. Donenfeld. All Rights Reserved.
+ * Copyright (C) 2020-2022 Jason A. Donenfeld. All Rights Reserved.
*/
#include "systeminfo.h"
@@ -25,7 +25,7 @@ const char *architecture(void)
kernel32 = GetModuleHandleA("kernel32.dll");
if (!kernel32)
return NULL;
- IsWow64Process2 = (void *)GetProcAddress(kernel32, "IsWow64Process2");
+ *(FARPROC *)&IsWow64Process2 = GetProcAddress(kernel32, "IsWow64Process2");
if (IsWow64Process2) {
if (!IsWow64Process2(GetCurrentProcess(), &process_machine, &native_machine))
return NULL;
@@ -65,3 +65,10 @@ bool is_win7(void)
RtlGetNtVersionNumbers(&maj, &min, &build);
return maj == 6 && min == 1;
}
+
+bool is_win8dotzero_or_below(void)
+{
+ DWORD maj, min, build;
+ RtlGetNtVersionNumbers(&maj, &min, &build);
+ return maj == 6 && min <= 2;
+}
diff --git a/installer/fetcher/systeminfo.h b/installer/fetcher/systeminfo.h
index 12c3444a..2c06a166 100644
--- a/installer/fetcher/systeminfo.h
+++ b/installer/fetcher/systeminfo.h
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0
*
- * Copyright (C) 2020-2021 Jason A. Donenfeld. All Rights Reserved.
+ * Copyright (C) 2020-2022 Jason A. Donenfeld. All Rights Reserved.
*/
#ifndef _SYSTEMINFO_H
@@ -11,5 +11,6 @@
const char *architecture(void);
const char *useragent(void);
bool is_win7(void);
+bool is_win8dotzero_or_below(void);
#endif
diff --git a/installer/fetcher/version.h b/installer/fetcher/version.h
index 794a9926..dd6f54d1 100644
--- a/installer/fetcher/version.h
+++ b/installer/fetcher/version.h
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0
*
- * Copyright (C) 2020-2021 Jason A. Donenfeld. All Rights Reserved.
+ * Copyright (C) 2020-2022 Jason A. Donenfeld. All Rights Reserved.
*/
#ifndef _VERSION_H
diff --git a/installer/wireguard.wxs b/installer/wireguard.wxs
index a0fc1396..ab90d3cd 100644
--- a/installer/wireguard.wxs
+++ b/installer/wireguard.wxs
@@ -2,7 +2,7 @@
<!--
SPDX-License-Identifier: GPL-2.0
- Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
-->
<?if $(var.WIREGUARD_PLATFORM) = "amd64" Or $(var.WIREGUARD_PLATFORM) = "arm64"?>
@@ -102,14 +102,6 @@
</InstallExecuteSequence>
<!--
- Abort early if running without KB2921916 on Windows 7
- -->
- <CustomAction Id="CheckKB2921916" BinaryKey="customactions.dll" DllEntry="CheckKB2921916" />
- <InstallExecuteSequence>
- <Custom Action="CheckKB2921916" After="CheckWow64">NOT REMOVE</Custom>
- </InstallExecuteSequence>
-
- <!--
Evaluate WireGuard services and populate ServiceControl table
-->
<CustomAction Id="EvaluateWireGuardServices" BinaryKey="customactions.dll" DllEntry="EvaluateWireGuardServices" />
diff --git a/l18n/l18n.go b/l18n/l18n.go
index 0eb72714..512fe2a2 100644
--- a/l18n/l18n.go
+++ b/l18n/l18n.go
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package l18n
@@ -13,8 +13,10 @@ import (
"golang.org/x/text/message"
)
-var printer *message.Printer
-var printerLock sync.Mutex
+var (
+ printer *message.Printer
+ printerLock sync.Mutex
+)
// prn returns the printer for user preferred UI language.
func prn() *message.Printer {
@@ -50,7 +52,7 @@ func lang() (tag language.Tag) {
}
// Sprintf is like fmt.Sprintf, but using language-specific formatting.
-func Sprintf(key message.Reference, a ...interface{}) string {
+func Sprintf(key message.Reference, a ...any) string {
return prn().Sprintf(key, a...)
}
diff --git a/locales/ca/messages.gotext.json b/locales/ca/messages.gotext.json
new file mode 100644
index 00000000..fbc227b1
--- /dev/null
+++ b/locales/ca/messages.gotext.json
@@ -0,0 +1,751 @@
+{
+ "language": "ca",
+ "messages": [
+ {
+ "id": "Error",
+ "message": "Error",
+ "translation": "Error",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "(no argument): elevate and install manager service",
+ "message": "(no argument): elevate and install manager service",
+ "translation": "(sense argument): eleva i instala el servei d'administrador",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Usage: {Args0} [\n{String}]",
+ "message": "Usage: {Args0} [\n{String}]",
+ "translation": "Ús: {Args0} [\n{String}]",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Args0",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "os.Args[0]"
+ },
+ {
+ "id": "String",
+ "string": "%[2]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 2,
+ "expr": "builder.String()"
+ }
+ ]
+ },
+ {
+ "id": "Command Line Options",
+ "message": "Command Line Options",
+ "translation": "Opcions de línia d'ordres",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Unable to determine whether the process is running under WOW64: {Err}",
+ "message": "Unable to determine whether the process is running under WOW64: {Err}",
+ "translation": "No s'ha pogut determinar si el procés corre sota WOW64: {Err}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Err",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "err"
+ }
+ ]
+ },
+ {
+ "id": "You must use the native version of WireGuard on this computer.",
+ "message": "You must use the native version of WireGuard on this computer.",
+ "translation": "Heu de fer servir la versio nativa de WireGuard en aquest ordinador.",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Unable to open current process token: {Err}",
+ "message": "Unable to open current process token: {Err}",
+ "translation": "No s'ha pogut obrir el token del procés actual: {Err}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Err",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "err"
+ }
+ ]
+ },
+ {
+ "id": "WireGuard may only be used by users who are a member of the Builtin {AdminGroupName} group.",
+ "message": "WireGuard may only be used by users who are a member of the Builtin {AdminGroupName} group.",
+ "translation": "WireGuard només es pot fer servir per els usuaris que són membres del grup del sistema {AdminGroupName}.",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "AdminGroupName",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "elevate.AdminGroupName()"
+ }
+ ]
+ },
+ {
+ "id": "WireGuard is running, but the UI is only accessible from desktops of the Builtin {AdminGroupName} group.",
+ "message": "WireGuard is running, but the UI is only accessible from desktops of the Builtin {AdminGroupName} group.",
+ "translation": "WireGuard s'està executsnt, pero la interfície gràfica només és accessible als usuaris que són membres del grup del sistema {AdminGroupName}.",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "AdminGroupName",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "elevate.AdminGroupName()"
+ }
+ ]
+ },
+ {
+ "id": "Now",
+ "message": "Now",
+ "translation": "Ara",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "System clock wound backward!",
+ "message": "System clock wound backward!",
+ "translation": "El rellotge del sistema s'ha atraçat!",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "{Years} year(s)",
+ "message": "{Years} year(s)",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "Years",
+ "cases": {
+ "one": {
+ "msg": "{Years} any"
+ },
+ "other": {
+ "msg": "{Years} anys"
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "Years",
+ "string": "%[1]d",
+ "type": "int64",
+ "underlyingType": "int64",
+ "argNum": 1,
+ "expr": "years"
+ }
+ ]
+ },
+ {
+ "id": "{Days} day(s)",
+ "message": "{Days} day(s)",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "Days",
+ "cases": {
+ "one": {
+ "msg": "{Days} dia"
+ },
+ "other": {
+ "msg": "{Days} dies"
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "Days",
+ "string": "%[1]d",
+ "type": "int64",
+ "underlyingType": "int64",
+ "argNum": 1,
+ "expr": "days"
+ }
+ ]
+ },
+ {
+ "id": "{Hours} hour(s)",
+ "message": "{Hours} hour(s)",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "Hours",
+ "cases": {
+ "one": {
+ "msg": "{Hours} hora"
+ },
+ "other": {
+ "msg": "{Hours} hores"
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "Hours",
+ "string": "%[1]d",
+ "type": "int64",
+ "underlyingType": "int64",
+ "argNum": 1,
+ "expr": "hours"
+ }
+ ]
+ },
+ {
+ "id": "{Minutes} minute(s)",
+ "message": "{Minutes} minute(s)",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "Minutes",
+ "cases": {
+ "one": {
+ "msg": "{Minutes} minut"
+ },
+ "other": {
+ "msg": "{Minutes} minuts"
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "Minutes",
+ "string": "%[1]d",
+ "type": "int64",
+ "underlyingType": "int64",
+ "argNum": 1,
+ "expr": "minutes"
+ }
+ ]
+ },
+ {
+ "id": "{Seconds} second(s)",
+ "message": "{Seconds} second(s)",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "Seconds",
+ "cases": {
+ "one": {
+ "msg": "{Seconds} segon"
+ },
+ "other": {
+ "msg": "{Seconds} segons"
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "Seconds",
+ "string": "%[1]d",
+ "type": "int64",
+ "underlyingType": "int64",
+ "argNum": 1,
+ "expr": "seconds"
+ }
+ ]
+ },
+ {
+ "id": "{Timestamp} ago",
+ "message": "{Timestamp} ago",
+ "translation": "Fa {Timestamp}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Timestamp",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "timestamp"
+ }
+ ]
+ },
+ {
+ "id": "{Bytes} B",
+ "message": "{Bytes} B",
+ "translation": "{Bytes} B",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Bytes",
+ "string": "%[1]d",
+ "type": "golang.zx2c4.com/wireguard/windows/conf.Bytes",
+ "underlyingType": "uint64",
+ "argNum": 1,
+ "expr": "b"
+ }
+ ]
+ },
+ {
+ "id": "{Float64b__1024} KiB",
+ "message": "{Float64b__1024} KiB",
+ "translation": "{Float64b__1024} KiB",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Float64b__1024",
+ "string": "%.2[1]f",
+ "type": "float64",
+ "underlyingType": "float64",
+ "argNum": 1,
+ "expr": "float64(b) / 1024"
+ }
+ ]
+ },
+ {
+ "id": "{Float64b__1024__1024} MiB",
+ "message": "{Float64b__1024__1024} MiB",
+ "translation": "{Float64b__1024__1024} MiB",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Float64b__1024__1024",
+ "string": "%.2[1]f",
+ "type": "float64",
+ "underlyingType": "float64",
+ "argNum": 1,
+ "expr": "float64(b) / (1024 * 1024)"
+ }
+ ]
+ },
+ {
+ "id": "{Float64b__1024__1024__1024} GiB",
+ "message": "{Float64b__1024__1024__1024} GiB",
+ "translation": "{Float64b__1024__1024__1024} GiB",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Float64b__1024__1024__1024",
+ "string": "%.2[1]f",
+ "type": "float64",
+ "underlyingType": "float64",
+ "argNum": 1,
+ "expr": "float64(b) / (1024 * 1024 * 1024)"
+ }
+ ]
+ },
+ {
+ "id": "{Float64b__1024__1024__1024__1024} TiB",
+ "message": "{Float64b__1024__1024__1024__1024} TiB",
+ "translation": "{Float64b__1024__1024__1024__1024} TiB",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Float64b__1024__1024__1024__1024",
+ "string": "%.2[1]f",
+ "type": "float64",
+ "underlyingType": "float64",
+ "argNum": 1,
+ "expr": "float64(b) / (1024 * 1024 * 1024) / 1024"
+ }
+ ]
+ },
+ {
+ "id": "{Why}: {Offender}",
+ "message": "{Why}: {Offender}",
+ "translation": "{Why}: {Offender}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Why",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "e.why"
+ },
+ {
+ "id": "Offender",
+ "string": "%[2]q",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 2,
+ "expr": "e.offender"
+ }
+ ]
+ },
+ {
+ "id": "Invalid IP address",
+ "message": "Invalid IP address",
+ "translation": "Adreça IP invàlida",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Invalid network prefix length",
+ "message": "Invalid network prefix length",
+ "translation": "Tamany del prefix de xarxa invàlid",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Missing port from endpoint",
+ "message": "Missing port from endpoint",
+ "translation": "Falta el port de l'extrem",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Invalid endpoint host",
+ "message": "Invalid endpoint host",
+ "translation": "El format de l'extrem no és valid",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Invalid MTU",
+ "message": "Invalid MTU",
+ "translation": "MTU invàlida",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Invalid port",
+ "message": "Invalid port",
+ "translation": "Port invàlid",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Invalid persistent keepalive",
+ "message": "Invalid persistent keepalive",
+ "translation": "Temps de missatge de persistència invàlid",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Invalid key: {Err}",
+ "message": "Invalid key: {Err}",
+ "translation": "Clau invàlida: {Err}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Err",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "err"
+ }
+ ]
+ },
+ {
+ "id": "Number must be a number between 0 and 2^64-1: {Err}",
+ "message": "Number must be a number between 0 and 2^64-1: {Err}",
+ "translation": "El nombre ha de estar entre 0 i 2^64-1: {Err}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Err",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "err"
+ }
+ ]
+ },
+ {
+ "id": "Two commas in a row",
+ "message": "Two commas in a row",
+ "translation": "Dos comes seguides",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Tunnel name is not valid",
+ "message": "Tunnel name is not valid",
+ "translation": "El nom del túnel no és vàlid",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "[none specified]",
+ "message": "[none specified]",
+ "translation": "[no especificat]",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "All peers must have public keys",
+ "message": "All peers must have public keys",
+ "translation": "Tots els parells han de tenir claus públiques",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Error in getting configuration",
+ "message": "Error in getting configuration",
+ "translation": "Error obtenint configuració",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "[EnumerationSeparator]",
+ "message": "[EnumerationSeparator]",
+ "translation": ", ",
+ "comment": "Text to insert between items when listing - most western languages will translate ‘[EnumerationSeparator]’ into ‘, ’ to produce lists like ‘apple, orange, strawberry’. Eastern languages might translate into ‘、’ to produce lists like ‘リンゴ、オレンジ、イチゴ’."
+ },
+ {
+ "id": "[UnitSeparator]",
+ "message": "[UnitSeparator]",
+ "translation": ", ",
+ "comment": "Text to insert when combining units of a measure - most languages will translate ‘[UnitSeparator]’ into ‘ ’ (space) to produce lists like ‘2 minuti 30 sekund’, or empty string ‘’ to produce ‘2分30秒’."
+ },
+ {
+ "id": "About WireGuard",
+ "message": "About WireGuard",
+ "translation": "Sobre WireGuard",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "WireGuard logo image",
+ "message": "WireGuard logo image",
+ "translation": "Logo de WireGuard",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Close",
+ "message": "Close",
+ "translation": "Tanca",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "♥ &Donate!",
+ "message": "♥ &Donate!",
+ "translation": "♥ & Dona!",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Status:",
+ "message": "Status:",
+ "translation": "Estat:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Deactivate",
+ "message": "&Deactivate",
+ "translation": "&Desactiva",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Activate",
+ "message": "&Activate",
+ "translation": "&Activa",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Public key:",
+ "message": "Public key:",
+ "translation": "Clau pública:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Listen port:",
+ "message": "Listen port:",
+ "translation": "Port d'escolta:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "MTU:",
+ "message": "MTU:",
+ "translation": "MTU:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Addresses:",
+ "message": "Addresses:",
+ "translation": "Adreces:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "DNS servers:",
+ "message": "DNS servers:",
+ "translation": "Servidors DNS:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Preshared key:",
+ "message": "Preshared key:",
+ "translation": "Clau precompartida:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Allowed IPs:",
+ "message": "Allowed IPs:",
+ "translation": "IPs permeses:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Endpoint:",
+ "message": "Endpoint:",
+ "translation": "Extrem:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Persistent keepalive:",
+ "message": "Persistent keepalive:",
+ "translation": "Missatge de persistència:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Latest handshake:",
+ "message": "Latest handshake:",
+ "translation": "Últim handshake:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Inactive",
+ "message": "Inactive",
+ "translation": "Inactiu",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Deactivating",
+ "message": "Deactivating",
+ "translation": "Desactivant",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Unknown state",
+ "message": "Unknown state",
+ "translation": "Estat desconegut",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Log",
+ "message": "Log",
+ "translation": "Registre",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Copy",
+ "message": "&Copy",
+ "translation": "&Copia",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Select &all",
+ "message": "Select &all",
+ "translation": "Selecciona-ho tot",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Save to file…",
+ "message": "&Save to file…",
+ "translation": "Desa en un arxiu…",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Time",
+ "message": "Time",
+ "translation": "Temps",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Log message",
+ "message": "Log message",
+ "translation": "Missatge de registre",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Export log to file",
+ "message": "Export log to file",
+ "translation": "Exporta registre a fitxer",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&About WireGuard…",
+ "message": "&About WireGuard…",
+ "translation": "&Sobre WireGuard…",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Tunnel Error",
+ "message": "Tunnel Error",
+ "translation": "Error de túnel",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "{ErrMsg}\n\nPlease consult the log for more information.",
+ "message": "{ErrMsg}\n\nPlease consult the log for more information.",
+ "translation": "{ErrMsg}\n\nSi us plau, consulteu el registre per més informació.",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "ErrMsg",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "errMsg"
+ }
+ ]
+ },
+ {
+ "id": "{Title} (out of date)",
+ "message": "{Title} (out of date)",
+ "translation": "{Title} (desactualitzat)",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Title",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "mtw.Title()"
+ }
+ ]
+ },
+ {
+ "id": "Error Exiting WireGuard",
+ "message": "Error Exiting WireGuard",
+ "translation": "Error al sortir de WireGuard",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "An update to WireGuard is available. It is highly advisable to update without delay.",
+ "message": "An update to WireGuard is available. It is highly advisable to update without delay.",
+ "translation": "Una actualització per WireGuard està disponible. Es recomana actualitzar immediatament.",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Update Now",
+ "message": "Update Now",
+ "translation": "Actualitza ara",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Error: {Err}. Please try again.",
+ "message": "Error: {Err}. Please try again.",
+ "translation": "Error: {Err}. Si us plau, torneu-ho a provar.",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Err",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "err"
+ }
+ ]
+ },
+ {
+ "id": "Status: Complete!",
+ "message": "Status: Complete!",
+ "translation": "Estat: Completat!",
+ "translatorComment": "Copied from source."
+ }
+ ]
+} \ No newline at end of file
diff --git a/locales/cs/messages.gotext.json b/locales/cs/messages.gotext.json
new file mode 100644
index 00000000..a28d47b9
--- /dev/null
+++ b/locales/cs/messages.gotext.json
@@ -0,0 +1,1907 @@
+{
+ "language": "cs",
+ "messages": [
+ {
+ "id": "Error",
+ "message": "Error",
+ "translation": "Chyba",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "(no argument): elevate and install manager service",
+ "message": "(no argument): elevate and install manager service",
+ "translation": "(žádný argument): Zvýšit oprávnění a instalovat službu správce",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Usage: {Args0} [\n{String}]",
+ "message": "Usage: {Args0} [\n{String}]",
+ "translation": "Použití: {Args0} [\n{String}]",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Args0",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "os.Args[0]"
+ },
+ {
+ "id": "String",
+ "string": "%[2]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 2,
+ "expr": "builder.String()"
+ }
+ ]
+ },
+ {
+ "id": "Command Line Options",
+ "message": "Command Line Options",
+ "translation": "Možnosti příkazového řádku",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Unable to determine whether the process is running under WOW64: {Err}",
+ "message": "Unable to determine whether the process is running under WOW64: {Err}",
+ "translation": "Nelze zjistit, zda proces běží pod WOW64: {Err}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Err",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "err"
+ }
+ ]
+ },
+ {
+ "id": "You must use the native version of WireGuard on this computer.",
+ "message": "You must use the native version of WireGuard on this computer.",
+ "translation": "Musíte použít nativní verzi aplikace WireGuard na tomto počítači.",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Unable to open current process token: {Err}",
+ "message": "Unable to open current process token: {Err}",
+ "translation": "Nelze otevřít token aktuálního procesu: {Err}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Err",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "err"
+ }
+ ]
+ },
+ {
+ "id": "WireGuard may only be used by users who are a member of the Builtin {AdminGroupName} group.",
+ "message": "WireGuard may only be used by users who are a member of the Builtin {AdminGroupName} group.",
+ "translation": "WireGuard můžou používat pouze uživatelé, kteří jsou členy Builtin skupiny {AdminGroupName}.",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "AdminGroupName",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "elevate.AdminGroupName()"
+ }
+ ]
+ },
+ {
+ "id": "WireGuard is running, but the UI is only accessible from desktops of the Builtin {AdminGroupName} group.",
+ "message": "WireGuard is running, but the UI is only accessible from desktops of the Builtin {AdminGroupName} group.",
+ "translation": "WireGuard je spuštěn, ale uživatelské rozhraní je přístupné pouze uživatelům Builtin skupiny {AdminGroupName}.",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "AdminGroupName",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "elevate.AdminGroupName()"
+ }
+ ]
+ },
+ {
+ "id": "WireGuard system tray icon did not appear after 30 seconds.",
+ "message": "WireGuard system tray icon did not appear after 30 seconds.",
+ "translation": "Ikona WireGuard se ani po 30 sekundách nezobrazila na systémové liště.",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Now",
+ "message": "Now",
+ "translation": "Teď",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "System clock wound backward!",
+ "message": "System clock wound backward!",
+ "translation": "Systémové hodiny byly posunuty dozadu!",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "{Years} year(s)",
+ "message": "{Years} year(s)",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "Years",
+ "cases": {
+ "one": {
+ "msg": "{Years} rok"
+ },
+ "few": {
+ "msg": "{Years} roky"
+ },
+ "many": {
+ "msg": "{Years} let"
+ },
+ "other": {
+ "msg": "{Years} let"
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "Years",
+ "string": "%[1]d",
+ "type": "int64",
+ "underlyingType": "int64",
+ "argNum": 1,
+ "expr": "years"
+ }
+ ]
+ },
+ {
+ "id": "{Days} day(s)",
+ "message": "{Days} day(s)",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "Days",
+ "cases": {
+ "one": {
+ "msg": "{Days} den"
+ },
+ "few": {
+ "msg": "{Days} dny"
+ },
+ "many": {
+ "msg": "{Days} dnů"
+ },
+ "other": {
+ "msg": "{Days} dny"
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "Days",
+ "string": "%[1]d",
+ "type": "int64",
+ "underlyingType": "int64",
+ "argNum": 1,
+ "expr": "days"
+ }
+ ]
+ },
+ {
+ "id": "{Hours} hour(s)",
+ "message": "{Hours} hour(s)",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "Hours",
+ "cases": {
+ "one": {
+ "msg": "{Hours} hodina"
+ },
+ "few": {
+ "msg": "{Hours} hodiny"
+ },
+ "many": {
+ "msg": "{Hours} hodin"
+ },
+ "other": {
+ "msg": "{Hours} hodin"
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "Hours",
+ "string": "%[1]d",
+ "type": "int64",
+ "underlyingType": "int64",
+ "argNum": 1,
+ "expr": "hours"
+ }
+ ]
+ },
+ {
+ "id": "{Minutes} minute(s)",
+ "message": "{Minutes} minute(s)",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "Minutes",
+ "cases": {
+ "one": {
+ "msg": "{Minutes} minuta"
+ },
+ "few": {
+ "msg": "{Minutes} minuty"
+ },
+ "many": {
+ "msg": "{Minutes} minut"
+ },
+ "other": {
+ "msg": "{Minutes} minut"
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "Minutes",
+ "string": "%[1]d",
+ "type": "int64",
+ "underlyingType": "int64",
+ "argNum": 1,
+ "expr": "minutes"
+ }
+ ]
+ },
+ {
+ "id": "{Seconds} second(s)",
+ "message": "{Seconds} second(s)",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "Seconds",
+ "cases": {
+ "one": {
+ "msg": "{Seconds} sekunda"
+ },
+ "few": {
+ "msg": "{Seconds} sekundy"
+ },
+ "many": {
+ "msg": "{Seconds} sekund"
+ },
+ "other": {
+ "msg": "{Seconds} sekund"
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "Seconds",
+ "string": "%[1]d",
+ "type": "int64",
+ "underlyingType": "int64",
+ "argNum": 1,
+ "expr": "seconds"
+ }
+ ]
+ },
+ {
+ "id": "{Timestamp} ago",
+ "message": "{Timestamp} ago",
+ "translation": "před {Timestamp}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Timestamp",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "timestamp"
+ }
+ ]
+ },
+ {
+ "id": "{Bytes} B",
+ "message": "{Bytes} B",
+ "translation": "{Bytes} B",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Bytes",
+ "string": "%[1]d",
+ "type": "golang.zx2c4.com/wireguard/windows/conf.Bytes",
+ "underlyingType": "uint64",
+ "argNum": 1,
+ "expr": "b"
+ }
+ ]
+ },
+ {
+ "id": "{Float64b__1024} KiB",
+ "message": "{Float64b__1024} KiB",
+ "translation": "{Float64b__1024} KiB",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Float64b__1024",
+ "string": "%.2[1]f",
+ "type": "float64",
+ "underlyingType": "float64",
+ "argNum": 1,
+ "expr": "float64(b) / 1024"
+ }
+ ]
+ },
+ {
+ "id": "{Float64b__1024__1024} MiB",
+ "message": "{Float64b__1024__1024} MiB",
+ "translation": "{Float64b__1024__1024} MiB",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Float64b__1024__1024",
+ "string": "%.2[1]f",
+ "type": "float64",
+ "underlyingType": "float64",
+ "argNum": 1,
+ "expr": "float64(b) / (1024 * 1024)"
+ }
+ ]
+ },
+ {
+ "id": "{Float64b__1024__1024__1024} GiB",
+ "message": "{Float64b__1024__1024__1024} GiB",
+ "translation": "{Float64b__1024__1024__1024} GiB",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Float64b__1024__1024__1024",
+ "string": "%.2[1]f",
+ "type": "float64",
+ "underlyingType": "float64",
+ "argNum": 1,
+ "expr": "float64(b) / (1024 * 1024 * 1024)"
+ }
+ ]
+ },
+ {
+ "id": "{Float64b__1024__1024__1024__1024} TiB",
+ "message": "{Float64b__1024__1024__1024__1024} TiB",
+ "translation": "{Float64b__1024__1024__1024__1024} TiB",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Float64b__1024__1024__1024__1024",
+ "string": "%.2[1]f",
+ "type": "float64",
+ "underlyingType": "float64",
+ "argNum": 1,
+ "expr": "float64(b) / (1024 * 1024 * 1024) / 1024"
+ }
+ ]
+ },
+ {
+ "id": "{Why}: {Offender}",
+ "message": "{Why}: {Offender}",
+ "translation": "{Why}: {Offender}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Why",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "e.why"
+ },
+ {
+ "id": "Offender",
+ "string": "%[2]q",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 2,
+ "expr": "e.offender"
+ }
+ ]
+ },
+ {
+ "id": "Invalid IP address",
+ "message": "Invalid IP address",
+ "translation": "Neplatná IP adresa",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Invalid network prefix length",
+ "message": "Invalid network prefix length",
+ "translation": "Neplatná délka síťového prefixu",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Missing port from endpoint",
+ "message": "Missing port from endpoint",
+ "translation": "Endpointu chybí port",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Invalid endpoint host",
+ "message": "Invalid endpoint host",
+ "translation": "Neplatný endpoint",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Brackets must contain an IPv6 address",
+ "message": "Brackets must contain an IPv6 address",
+ "translation": "Závorky musí obsahovat IPv6 adresu",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Invalid MTU",
+ "message": "Invalid MTU",
+ "translation": "Neplatné MTU",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Invalid port",
+ "message": "Invalid port",
+ "translation": "Neplatný port",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Invalid persistent keepalive",
+ "message": "Invalid persistent keepalive",
+ "translation": "Neplatný persistentní keepalive",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Invalid key: {Err}",
+ "message": "Invalid key: {Err}",
+ "translation": "Neplatný klíč: {Err}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Err",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "err"
+ }
+ ]
+ },
+ {
+ "id": "Keys must decode to exactly 32 bytes",
+ "message": "Keys must decode to exactly 32 bytes",
+ "translation": "Klíče musí být dekódovány přesně na 32 bajtů",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Number must be a number between 0 and 2^64-1: {Err}",
+ "message": "Number must be a number between 0 and 2^64-1: {Err}",
+ "translation": "Číslo musí mít hodnotu mezi 0 a 2^64-1: {Err}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Err",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "err"
+ }
+ ]
+ },
+ {
+ "id": "Two commas in a row",
+ "message": "Two commas in a row",
+ "translation": "Dvě čárky za sebou",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Tunnel name is not valid",
+ "message": "Tunnel name is not valid",
+ "translation": "Název tunelu je neplatný",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Line must occur in a section",
+ "message": "Line must occur in a section",
+ "translation": "Řádek musí být v některé sekci",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Config key is missing an equals separator",
+ "message": "Config key is missing an equals separator",
+ "translation": "Konfigurační klíč neobsahuje oddělovač (znak 'rovná se')",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Key must have a value",
+ "message": "Key must have a value",
+ "translation": "Klíč musí mít hodnotu",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Invalid key for [Interface] section",
+ "message": "Invalid key for [Interface] section",
+ "translation": "Neplatný klíč pro sekci [Interface]",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Invalid key for [Peer] section",
+ "message": "Invalid key for [Peer] section",
+ "translation": "Neplatný klíč pro sekci [Peer]",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "An interface must have a private key",
+ "message": "An interface must have a private key",
+ "translation": "Rozhraní musí obsahovat soukromý klíč",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "[none specified]",
+ "message": "[none specified]",
+ "translation": "[není specifikováno]",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "All peers must have public keys",
+ "message": "All peers must have public keys",
+ "translation": "Všichni peeři musí mít veřejné klíče",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Error in getting configuration",
+ "message": "Error in getting configuration",
+ "translation": "Chyba při načítání konfigurace",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Invalid key for interface section",
+ "message": "Invalid key for interface section",
+ "translation": "Neplatný klíč pro sekci rozhraní",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Protocol version must be 1",
+ "message": "Protocol version must be 1",
+ "translation": "Verze protokolu musí být 1",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Invalid key for peer section",
+ "message": "Invalid key for peer section",
+ "translation": "Neplatný klíč v sekci peer",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "[EnumerationSeparator]",
+ "message": "[EnumerationSeparator]",
+ "translation": ", ",
+ "comment": "Text to insert between items when listing - most western languages will translate ‘[EnumerationSeparator]’ into ‘, ’ to produce lists like ‘apple, orange, strawberry’. Eastern languages might translate into ‘、’ to produce lists like ‘リンゴ、オレンジ、イチゴ’."
+ },
+ {
+ "id": "[UnitSeparator]",
+ "message": "[UnitSeparator]",
+ "translation": ", ",
+ "comment": "Text to insert when combining units of a measure - most languages will translate ‘[UnitSeparator]’ into ‘ ’ (space) to produce lists like ‘2 minuti 30 sekund’, or empty string ‘’ to produce ‘2分30秒’."
+ },
+ {
+ "id": "About WireGuard",
+ "message": "About WireGuard",
+ "translation": "O aplikaci WireGuard",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "WireGuard logo image",
+ "message": "WireGuard logo image",
+ "translation": "Obrázek loga WireGuard",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "App version: {Number}\nGo backend version: {WireGuardGoVersion}\nGo version: {Version_go}-{GOARCH}\nOperating system: {OsName}\nArchitecture: {NativeArch}",
+ "message": "App version: {Number}\nGo backend version: {WireGuardGoVersion}\nGo version: {Version_go}-{GOARCH}\nOperating system: {OsName}\nArchitecture: {NativeArch}",
+ "translation": "Verze aplikace: {Number}\nVerze Go backendu: {WireGuardGoVersion}\nVerze Go: {Version_go}-{GOARCH}\nOperační systém: {OsName}\nArchitektura: {NativeArch}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Number",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "version.Number"
+ },
+ {
+ "id": "WireGuardGoVersion",
+ "string": "%[2]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 2,
+ "expr": "device.WireGuardGoVersion"
+ },
+ {
+ "id": "Version_go",
+ "string": "%[3]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 3,
+ "expr": "strings.TrimPrefix(runtime.Version(), \"go\")"
+ },
+ {
+ "id": "GOARCH",
+ "string": "%[4]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 4,
+ "expr": "runtime.GOARCH"
+ },
+ {
+ "id": "OsName",
+ "string": "%[5]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 5,
+ "expr": "version.OsName()"
+ },
+ {
+ "id": "NativeArch",
+ "string": "%[6]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 6,
+ "expr": "version.NativeArch()"
+ }
+ ]
+ },
+ {
+ "id": "Close",
+ "message": "Close",
+ "translation": "Zavřít",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "♥ &Donate!",
+ "message": "♥ &Donate!",
+ "translation": "♥ &Darovat!",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Status:",
+ "message": "Status:",
+ "translation": "Stav:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Deactivate",
+ "message": "&Deactivate",
+ "translation": "&Deaktivovat",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Activate",
+ "message": "&Activate",
+ "translation": "&Aktivovat",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Public key:",
+ "message": "Public key:",
+ "translation": "Veřejný klíč:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Listen port:",
+ "message": "Listen port:",
+ "translation": "Port pro naslouchání:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "MTU:",
+ "message": "MTU:",
+ "translation": "MTU:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Addresses:",
+ "message": "Addresses:",
+ "translation": "Adresy:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "DNS servers:",
+ "message": "DNS servers:",
+ "translation": "DNS servery:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Scripts:",
+ "message": "Scripts:",
+ "translation": "Skripty:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Preshared key:",
+ "message": "Preshared key:",
+ "translation": "Předsdílený klíč:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Allowed IPs:",
+ "message": "Allowed IPs:",
+ "translation": "Povolené IP:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Endpoint:",
+ "message": "Endpoint:",
+ "translation": "Endpoint:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Persistent keepalive:",
+ "message": "Persistent keepalive:",
+ "translation": "Persistent keepalive:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Latest handshake:",
+ "message": "Latest handshake:",
+ "translation": "Poslední handshake:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Transfer:",
+ "message": "Transfer:",
+ "translation": "Přenos:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "pre-up",
+ "message": "pre-up",
+ "translation": "před-zapnutím",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "post-up",
+ "message": "post-up",
+ "translation": "po-zapnutí",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "pre-down",
+ "message": "pre-down",
+ "translation": "před-vypnutím",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "post-down",
+ "message": "post-down",
+ "translation": "po-vypnutí",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "disabled, per policy",
+ "message": "disabled, per policy",
+ "translation": "vypnuto, podle zásad",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "enabled",
+ "message": "enabled",
+ "translation": "zapnuto",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "{String} received, {String_1} sent",
+ "message": "{String} received, {String_1} sent",
+ "translation": "{String} přijato, {String_1} odesláno",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "String",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "c.RxBytes.String()"
+ },
+ {
+ "id": "String_1",
+ "string": "%[2]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 2,
+ "expr": "c.TxBytes.String()"
+ }
+ ]
+ },
+ {
+ "id": "Failed to determine tunnel state",
+ "message": "Failed to determine tunnel state",
+ "translation": "Nepodařilo se zjistit stav tunelu",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Failed to activate tunnel",
+ "message": "Failed to activate tunnel",
+ "translation": "Nepodařilo se aktivovat tunel",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Failed to deactivate tunnel",
+ "message": "Failed to deactivate tunnel",
+ "translation": "Nepodařilo se deaktivovat tunel",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Interface: {Name}",
+ "message": "Interface: {Name}",
+ "translation": "Rozhraní: {Name}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Name",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "config.Name"
+ }
+ ]
+ },
+ {
+ "id": "Peer",
+ "message": "Peer",
+ "translation": "Peer",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Create new tunnel",
+ "message": "Create new tunnel",
+ "translation": "Vytvořit nový tunel",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Edit tunnel",
+ "message": "Edit tunnel",
+ "translation": "Upravit tunel",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Name:",
+ "message": "&Name:",
+ "translation": "&Název:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Public key:",
+ "message": "&Public key:",
+ "translation": "&Veřejný klíč:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "(unknown)",
+ "message": "(unknown)",
+ "translation": "(neznámý)",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Block untunneled traffic (kill-switch)",
+ "message": "&Block untunneled traffic (kill-switch)",
+ "translation": "&Blokovat netunelovaný provoz (kill-switch)",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "When a configuration has exactly one peer, and that peer has an allowed IPs containing at least one of 0.0.0.0/0 or ::/0, then the tunnel service engages a firewall ruleset to block all traffic that is neither to nor from the tunnel interface or is to the wrong DNS server, with special exceptions for DHCP and NDP.",
+ "message": "When a configuration has exactly one peer, and that peer has an allowed IPs containing at least one of 0.0.0.0/0 or ::/0, then the tunnel service engages a firewall ruleset to block all traffic that is neither to nor from the tunnel interface or is to the wrong DNS server, with special exceptions for DHCP and NDP.",
+ "translation": "Pokud má konfigurace přesně jednoho peera a tento peer má povolené IP adresy obsahující alespoň jednu z 0.0.0.0/0 nebo ::/0, pak služba tunelu použije sadu pravidel firewallu k blokování veškerého provozu, který nesměřuje z/do rozhraní tunelu nebo na nesprávný server DNS, se zvláštními výjimkami pro DHCP a NDP.",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Save",
+ "message": "&Save",
+ "translation": "&Uložit",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Cancel",
+ "message": "Cancel",
+ "translation": "Zrušit",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Configuration:",
+ "message": "&Configuration:",
+ "translation": "&Nastavení:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Invalid name",
+ "message": "Invalid name",
+ "translation": "Neplatný název",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "A name is required.",
+ "message": "A name is required.",
+ "translation": "Název je povinný.",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Tunnel name ‘{NewName}’ is invalid.",
+ "message": "Tunnel name ‘{NewName}’ is invalid.",
+ "translation": "Název tunelu '{NewName}' je neplatný.",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "NewName",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "newName"
+ }
+ ]
+ },
+ {
+ "id": "Unable to list existing tunnels",
+ "message": "Unable to list existing tunnels",
+ "translation": "Nepodařilo se zobrazit existující tunely",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Tunnel already exists",
+ "message": "Tunnel already exists",
+ "translation": "Tunel již existuje",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Another tunnel already exists with the name ‘{NewName}’.",
+ "message": "Another tunnel already exists with the name ‘{NewName}’.",
+ "translation": "Tunel s názvem '{NewName}' již existuje.",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "NewName",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "newName"
+ }
+ ]
+ },
+ {
+ "id": "Unable to create new configuration",
+ "message": "Unable to create new configuration",
+ "translation": "Nepodařilo se vytvořit novou konfiguraci",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Writing file failed",
+ "message": "Writing file failed",
+ "translation": "Zápis souboru se nezdařil",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "File ‘{FilePath}’ already exists.\n\nDo you want to overwrite it?",
+ "message": "File ‘{FilePath}’ already exists.\n\nDo you want to overwrite it?",
+ "translation": "Soubor \"{FilePath}\" již existuje.\n\nChcete jej přepsat?",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "FilePath",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "filePath"
+ }
+ ]
+ },
+ {
+ "id": "Active",
+ "message": "Active",
+ "translation": "Aktivní",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Activating",
+ "message": "Activating",
+ "translation": "Aktivuji",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Inactive",
+ "message": "Inactive",
+ "translation": "Neaktivní",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Deactivating",
+ "message": "Deactivating",
+ "translation": "Deaktivuji",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Unknown state",
+ "message": "Unknown state",
+ "translation": "Neznámý stav",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Log",
+ "message": "Log",
+ "translation": "Záznamy",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Copy",
+ "message": "&Copy",
+ "translation": "&Kopírovat",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Select &all",
+ "message": "Select &all",
+ "translation": "Vybr&at vše",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Save to file…",
+ "message": "&Save to file…",
+ "translation": "&Uložit do souboru…",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Time",
+ "message": "Time",
+ "translation": "Čas",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Log message",
+ "message": "Log message",
+ "translation": "Zpráva logu",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Text Files (*.txt)|*.txt|All Files (*.*)|*.*",
+ "message": "Text Files (*.txt)|*.txt|All Files (*.*)|*.*",
+ "translation": "Textové soubory (*.txt)|*.txt|Všechny soubory (*.*)|*.*",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Export log to file",
+ "message": "Export log to file",
+ "translation": "Exportovat záznam do souboru",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&About WireGuard…",
+ "message": "&About WireGuard…",
+ "translation": "&O aplikaci WireGuard…",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Tunnel Error",
+ "message": "Tunnel Error",
+ "translation": "Chyba tunelu",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "{ErrMsg}\n\nPlease consult the log for more information.",
+ "message": "{ErrMsg}\n\nPlease consult the log for more information.",
+ "translation": "{ErrMsg}\n\nPro více informací se prosím podívejte do logu.",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "ErrMsg",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "errMsg"
+ }
+ ]
+ },
+ {
+ "id": "{Title} (out of date)",
+ "message": "{Title} (out of date)",
+ "translation": "{Title} (neaktuální)",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Title",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "mtw.Title()"
+ }
+ ]
+ },
+ {
+ "id": "WireGuard Detection Error",
+ "message": "WireGuard Detection Error",
+ "translation": "Chyba při detekci WireGuard",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Unable to wait for WireGuard window to appear: {Err}",
+ "message": "Unable to wait for WireGuard window to appear: {Err}",
+ "translation": "Nelze čekat na zobrazení okna WireGuard: {Err}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Err",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "err"
+ }
+ ]
+ },
+ {
+ "id": "WireGuard: Deactivated",
+ "message": "WireGuard: Deactivated",
+ "translation": "WireGuard: Deaktivován",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Status: Unknown",
+ "message": "Status: Unknown",
+ "translation": "Stav: Neznámý",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Addresses: None",
+ "message": "Addresses: None",
+ "translation": "Adresy: žádné",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Manage tunnels…",
+ "message": "&Manage tunnels…",
+ "translation": "Spravovat tunely…",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Import tunnel(s) from file…",
+ "message": "&Import tunnel(s) from file…",
+ "translation": "&Importovat tunel(y) ze souboru…",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "E&xit",
+ "message": "E&xit",
+ "translation": "U&končit",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Tunnels",
+ "message": "&Tunnels",
+ "translation": "&Tunely",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "WireGuard Activated",
+ "message": "WireGuard Activated",
+ "translation": "WireGuard aktivován",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "The {Name} tunnel has been activated.",
+ "message": "The {Name} tunnel has been activated.",
+ "translation": "Tunel {Name} byl aktivován.",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Name",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "tunnel.Name"
+ }
+ ]
+ },
+ {
+ "id": "WireGuard Deactivated",
+ "message": "WireGuard Deactivated",
+ "translation": "WireGuard deaktivován",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "The {Name} tunnel has been deactivated.",
+ "message": "The {Name} tunnel has been deactivated.",
+ "translation": "Tunel {Name} byl deaktivován.",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Name",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "tunnel.Name"
+ }
+ ]
+ },
+ {
+ "id": "WireGuard Tunnel Error",
+ "message": "WireGuard Tunnel Error",
+ "translation": "WireGuard Chyba Tunelu",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "WireGuard: {TextForStateglobalState_true}",
+ "message": "WireGuard: {TextForStateglobalState_true}",
+ "translation": "WireGuard: {TextForStateglobalState_true}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "TextForStateglobalState_true",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "textForState(globalState, true)"
+ }
+ ]
+ },
+ {
+ "id": "Status: {StateText}",
+ "message": "Status: {StateText}",
+ "translation": "Stav: {StateText}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "StateText",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "stateText"
+ }
+ ]
+ },
+ {
+ "id": "Addresses: {EnumerationSeparator}",
+ "message": "Addresses: {EnumerationSeparator}",
+ "translation": "Adresy: {EnumerationSeparator}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "EnumerationSeparator",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "strings.Join(addrs, l18n.EnumerationSeparator())"
+ }
+ ]
+ },
+ {
+ "id": "An Update is Available!",
+ "message": "An Update is Available!",
+ "translation": "Aktualizace je k dispozici!",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "WireGuard Update Available",
+ "message": "WireGuard Update Available",
+ "translation": "Aktualizace WireGuard je k dispozici",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "An update to WireGuard is now available. You are advised to update as soon as possible.",
+ "message": "An update to WireGuard is now available. You are advised to update as soon as possible.",
+ "translation": "Aktualizace aplikace WireGuard je nyní k dispozici. Doporučujeme ji aktualizovat co nejdříve.",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Tunnels",
+ "message": "Tunnels",
+ "translation": "Tunely",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Edit",
+ "message": "&Edit",
+ "translation": "&Upravit",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Add &empty tunnel…",
+ "message": "Add &empty tunnel…",
+ "translation": "Přidat &prázdný tunel…",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Add Tunnel",
+ "message": "Add Tunnel",
+ "translation": "Přidat tunel",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Remove selected tunnel(s)",
+ "message": "Remove selected tunnel(s)",
+ "translation": "Odstranit vybrané tunely",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Export all tunnels to zip",
+ "message": "Export all tunnels to zip",
+ "translation": "Exportovat všechny tunely do zip",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Toggle",
+ "message": "&Toggle",
+ "translation": "&Přepnout",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Export all tunnels to &zip…",
+ "message": "Export all tunnels to &zip…",
+ "translation": "Exportovat všechny tunely do &zip…",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Edit &selected tunnel…",
+ "message": "Edit &selected tunnel…",
+ "translation": "Upravit &vybraný tunel…",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Remove selected tunnel(s)",
+ "message": "&Remove selected tunnel(s)",
+ "translation": "&Odstranit vybrané tunely",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "no configuration files were found",
+ "message": "no configuration files were found",
+ "translation": "nebyly nalezeny žádné konfigurační soubory",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Could not import selected configuration: {LastErr}",
+ "message": "Could not import selected configuration: {LastErr}",
+ "translation": "Nelze importovat vybranou konfiguraci: {LastErr}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "LastErr",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "lastErr"
+ }
+ ]
+ },
+ {
+ "id": "Could not enumerate existing tunnels: {LastErr}",
+ "message": "Could not enumerate existing tunnels: {LastErr}",
+ "translation": "Nepodařilo se vyjmenovat existující tunely: {LastErr}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "LastErr",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "lastErr"
+ }
+ ]
+ },
+ {
+ "id": "Another tunnel already exists with the name ‘{Name}’",
+ "message": "Another tunnel already exists with the name ‘{Name}’",
+ "translation": "Tunel s názvem '{Name}' již existuje",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Name",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "unparsedConfig.Name"
+ }
+ ]
+ },
+ {
+ "id": "Unable to import configuration: {LastErr}",
+ "message": "Unable to import configuration: {LastErr}",
+ "translation": "Nelze importovat konfiguraci: {LastErr}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "LastErr",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "lastErr"
+ }
+ ]
+ },
+ {
+ "id": "Imported tunnels",
+ "message": "Imported tunnels",
+ "translation": "Importované tunely",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Imported {M} tunnels",
+ "message": "Imported {M} tunnels",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "M",
+ "cases": {
+ "one": {
+ "msg": "Importován {M} tunel"
+ },
+ "few": {
+ "msg": "Importovány {M} tunely"
+ },
+ "many": {
+ "msg": "Importováno {M} tunelů"
+ },
+ "other": {
+ "msg": "Importováno {M} tunelů"
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "M",
+ "string": "%[1]d",
+ "type": "int",
+ "underlyingType": "int",
+ "argNum": 1,
+ "expr": "m"
+ }
+ ]
+ },
+ {
+ "id": "Imported {M} of {N} tunnels",
+ "message": "Imported {M} of {N} tunnels",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "N",
+ "cases": {
+ "one": {
+ "msg": "Importován {M} z {N} tunel"
+ },
+ "few": {
+ "msg": "Importováno {M} z {N} tunelů"
+ },
+ "many": {
+ "msg": "Importováno {M} z {N} tunelů"
+ },
+ "other": {
+ "msg": "Importováno {M} z {N} tunelů"
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "M",
+ "string": "%[1]d",
+ "type": "int",
+ "underlyingType": "int",
+ "argNum": 1,
+ "expr": "m"
+ },
+ {
+ "id": "N",
+ "string": "%[2]d",
+ "type": "int",
+ "underlyingType": "int",
+ "argNum": 2,
+ "expr": "n"
+ }
+ ]
+ },
+ {
+ "id": "Unable to create tunnel",
+ "message": "Unable to create tunnel",
+ "translation": "Nelze vytvořit tunel",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Delete {TunnelCount} tunnels",
+ "message": "Delete {TunnelCount} tunnels",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "TunnelCount",
+ "cases": {
+ "one": {
+ "msg": "Odstranit {TunnelCount} tunel"
+ },
+ "few": {
+ "msg": "Odstranit {TunnelCount} tunely"
+ },
+ "many": {
+ "msg": "Odstranit {TunnelCount} tunelů"
+ },
+ "other": {
+ "msg": "Odstranit {TunnelCount} tunelů"
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "TunnelCount",
+ "string": "%[1]d",
+ "type": "int",
+ "underlyingType": "int",
+ "argNum": 1,
+ "expr": "tunnelCount"
+ }
+ ]
+ },
+ {
+ "id": "Are you sure you would like to delete {TunnelCount} tunnels?",
+ "message": "Are you sure you would like to delete {TunnelCount} tunnels?",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "TunnelCount",
+ "cases": {
+ "one": {
+ "msg": "Opravdu chcete odstranit {TunnelCount} tunel?"
+ },
+ "few": {
+ "msg": "Opravdu chcete odstranit {TunnelCount} tunely?"
+ },
+ "many": {
+ "msg": "Opravdu chcete odstranit {TunnelCount} tunelů?"
+ },
+ "other": {
+ "msg": "Opravdu chcete odstranit {TunnelCount} tunelů?"
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "TunnelCount",
+ "string": "%[1]d",
+ "type": "int",
+ "underlyingType": "int",
+ "argNum": 1,
+ "expr": "tunnelCount"
+ }
+ ]
+ },
+ {
+ "id": "Delete tunnel ‘{TunnelName}’",
+ "message": "Delete tunnel ‘{TunnelName}’",
+ "translation": "Odstranit tunel \"{TunnelName}\"",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "TunnelName",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "tunnelName"
+ }
+ ]
+ },
+ {
+ "id": "Are you sure you would like to delete tunnel ‘{TunnelName}’?",
+ "message": "Are you sure you would like to delete tunnel ‘{TunnelName}’?",
+ "translation": "Opravdu chcete odstranit tunel \"{TunnelName}\"?",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "TunnelName",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "tunnelName"
+ }
+ ]
+ },
+ {
+ "id": "{Question} You cannot undo this action.",
+ "message": "{Question} You cannot undo this action.",
+ "translation": "{Question} Tuto akci nelze vrátit zpět.",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Question",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "question"
+ }
+ ]
+ },
+ {
+ "id": "Unable to delete tunnel",
+ "message": "Unable to delete tunnel",
+ "translation": "Nelze odstranit tunel",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "A tunnel was unable to be removed: {Error}",
+ "message": "A tunnel was unable to be removed: {Error}",
+ "translation": "Tunel nebylo možné odstranit: {Error}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Error",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "errors[0].Error()"
+ }
+ ]
+ },
+ {
+ "id": "Unable to delete tunnels",
+ "message": "Unable to delete tunnels",
+ "translation": "Nelze odstranit tunely",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "{Lenerrors} tunnels were unable to be removed.",
+ "message": "{Lenerrors} tunnels were unable to be removed.",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "Lenerrors",
+ "cases": {
+ "one": {
+ "msg": "{Lenerrors} tunel nebylo možné odstranit."
+ },
+ "few": {
+ "msg": "{Lenerrors} tunely nebylo možné odstranit."
+ },
+ "many": {
+ "msg": "{Lenerrors} tunelů nebylo možné odstranit."
+ },
+ "other": {
+ "msg": "{Lenerrors} tunelů nebylo možné odstranit."
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "Lenerrors",
+ "string": "%[1]d",
+ "type": "int",
+ "underlyingType": "int",
+ "argNum": 1,
+ "expr": "len(errors)"
+ }
+ ]
+ },
+ {
+ "id": "Configuration Files (*.zip, *.conf)|*.zip;*.conf|All Files (*.*)|*.*",
+ "message": "Configuration Files (*.zip, *.conf)|*.zip;*.conf|All Files (*.*)|*.*",
+ "translation": "Konfigurace souborů (*.zip, *.conf)|*.zip; *.conf|Všechny soubory (*.*)|*.*",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Import tunnel(s) from file",
+ "message": "Import tunnel(s) from file",
+ "translation": "Importovat tunel(y) ze souboru",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Configuration ZIP Files (*.zip)|*.zip",
+ "message": "Configuration ZIP Files (*.zip)|*.zip",
+ "translation": "Konfigurace souborů ZIP (*.zip)|*.zip",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Export tunnels to zip",
+ "message": "Export tunnels to zip",
+ "translation": "Exportovat tunely do zip",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "{Title} (unsigned build, no updates)",
+ "message": "{Title} (unsigned build, no updates)",
+ "translation": "{Title} (nepodepsaná verze, žádné aktualizace)",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Title",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "mtw.Title()"
+ }
+ ]
+ },
+ {
+ "id": "Error Exiting WireGuard",
+ "message": "Error Exiting WireGuard",
+ "translation": "Chyba při ukončování aplikace WireGuard",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Unable to exit service due to: {Err}. You may want to stop WireGuard from the service manager.",
+ "message": "Unable to exit service due to: {Err}. You may want to stop WireGuard from the service manager.",
+ "translation": "Nelze ukončit službu z důvodu: {Err}. WireGuard můžete zastavit ve správci služeb.",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Err",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "err"
+ }
+ ]
+ },
+ {
+ "id": "An update to WireGuard is available. It is highly advisable to update without delay.",
+ "message": "An update to WireGuard is available. It is highly advisable to update without delay.",
+ "translation": "Aktualizace aplikace WireGuard je nyní k dispozici. Silně doporučujeme ji aktualizovat co nejdříve.",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Status: Waiting for user",
+ "message": "Status: Waiting for user",
+ "translation": "Stav: Čekání na uživatele",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Update Now",
+ "message": "Update Now",
+ "translation": "Aktualizovat nyní",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Status: Waiting for updater service",
+ "message": "Status: Waiting for updater service",
+ "translation": "Stav: Čeká se na službu aktualizací",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Error: {Err}. Please try again.",
+ "message": "Error: {Err}. Please try again.",
+ "translation": "Chyba: {Err}. Zkuste to znovu.",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Err",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "err"
+ }
+ ]
+ },
+ {
+ "id": "Status: Complete!",
+ "message": "Status: Complete!",
+ "translation": "Stav: Dokončeno!",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "http2: Framer {F}: failed to decode just-written frame",
+ "message": "http2: Framer {F}: failed to decode just-written frame",
+ "translation": "http2: Framer {F}: failed to decode just-written frame",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "F",
+ "string": "%[1]p",
+ "type": "*net/http.http2Framer",
+ "underlyingType": "*net/http.http2Framer",
+ "argNum": 1,
+ "expr": "f"
+ }
+ ]
+ },
+ {
+ "id": "http2: Framer {F}: wrote {Http2summarizeFramefr}",
+ "message": "http2: Framer {F}: wrote {Http2summarizeFramefr}",
+ "translation": "http2: Framer {F}: wrote {Http2summarizeFramefr}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "F",
+ "string": "%[1]p",
+ "type": "*net/http.http2Framer",
+ "underlyingType": "*net/http.http2Framer",
+ "argNum": 1,
+ "expr": "f"
+ },
+ {
+ "id": "Http2summarizeFramefr",
+ "string": "%[2]v",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 2,
+ "expr": "http2summarizeFrame(fr)"
+ }
+ ]
+ },
+ {
+ "id": "http2: Framer {Fr}: read {Http2summarizeFramef}",
+ "message": "http2: Framer {Fr}: read {Http2summarizeFramef}",
+ "translation": "http2: Framer {Fr}: read {Http2summarizeFramef}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Fr",
+ "string": "%[1]p",
+ "type": "*net/http.http2Framer",
+ "underlyingType": "*net/http.http2Framer",
+ "argNum": 1,
+ "expr": "fr"
+ },
+ {
+ "id": "Http2summarizeFramef",
+ "string": "%[2]v",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 2,
+ "expr": "http2summarizeFrame(f)"
+ }
+ ]
+ },
+ {
+ "id": "http2: decoded hpack field {HeaderField}",
+ "message": "http2: decoded hpack field {HeaderField}",
+ "translation": "http2: decoded hpack field {HeaderField}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "HeaderField",
+ "string": "%+[1]v",
+ "type": "vendor/golang.org/x/net/http2/hpack.HeaderField",
+ "underlyingType": "struct{Name string; Value string; Sensitive bool}",
+ "argNum": 1,
+ "expr": "hf"
+ }
+ ]
+ }
+ ]
+} \ No newline at end of file
diff --git a/locales/de/messages.gotext.json b/locales/de/messages.gotext.json
index cae1860e..5d26c8ab 100644
--- a/locales/de/messages.gotext.json
+++ b/locales/de/messages.gotext.json
@@ -744,6 +744,30 @@
"translatorComment": "Copied from source."
},
{
+ "id": "pre-up",
+ "message": "pre-up",
+ "translation": "vor Verbindsaufbau",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "post-up",
+ "message": "post-up",
+ "translation": "nach Verbindungsaufbau",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "pre-down",
+ "message": "pre-down",
+ "translation": "vor Verbindungsabbau",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "post-down",
+ "message": "post-down",
+ "translation": "nach Verbindungsabbau",
+ "translatorComment": "Copied from source."
+ },
+ {
"id": "disabled, per policy",
"message": "disabled, per policy",
"translation": "deaktiviert, per Richtlinie",
@@ -1144,6 +1168,12 @@
"translatorComment": "Copied from source."
},
{
+ "id": "&Tunnels",
+ "message": "&Tunnels",
+ "translation": "&Tunnel",
+ "translatorComment": "Copied from source."
+ },
+ {
"id": "WireGuard Activated",
"message": "WireGuard Activated",
"translation": "WireGuard aktiviert",
diff --git a/locales/es-ES/messages.gotext.json b/locales/es-ES/messages.gotext.json
index 273022d4..a4cff055 100644
--- a/locales/es-ES/messages.gotext.json
+++ b/locales/es-ES/messages.gotext.json
@@ -36,6 +36,1042 @@
"expr": "builder.String()"
}
]
+ },
+ {
+ "id": "Command Line Options",
+ "message": "Command Line Options",
+ "translation": "Opciones de línea de comandos",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Now",
+ "message": "Now",
+ "translation": "Ahora",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "{Years} year(s)",
+ "message": "{Years} year(s)",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "Years",
+ "cases": {
+ "one": {
+ "msg": "{Years} año"
+ },
+ "other": {
+ "msg": "{Years} años"
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "Years",
+ "string": "%[1]d",
+ "type": "int64",
+ "underlyingType": "int64",
+ "argNum": 1,
+ "expr": "years"
+ }
+ ]
+ },
+ {
+ "id": "{Days} day(s)",
+ "message": "{Days} day(s)",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "Days",
+ "cases": {
+ "one": {
+ "msg": "{Days} día"
+ },
+ "other": {
+ "msg": "{Days} dias"
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "Days",
+ "string": "%[1]d",
+ "type": "int64",
+ "underlyingType": "int64",
+ "argNum": 1,
+ "expr": "days"
+ }
+ ]
+ },
+ {
+ "id": "{Hours} hour(s)",
+ "message": "{Hours} hour(s)",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "Hours",
+ "cases": {
+ "one": {
+ "msg": "{Hours} hora"
+ },
+ "other": {
+ "msg": "{Hours} horas"
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "Hours",
+ "string": "%[1]d",
+ "type": "int64",
+ "underlyingType": "int64",
+ "argNum": 1,
+ "expr": "hours"
+ }
+ ]
+ },
+ {
+ "id": "{Minutes} minute(s)",
+ "message": "{Minutes} minute(s)",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "Minutes",
+ "cases": {
+ "one": {
+ "msg": "{Minutes} minuto"
+ },
+ "other": {
+ "msg": "{Minutes} minutos"
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "Minutes",
+ "string": "%[1]d",
+ "type": "int64",
+ "underlyingType": "int64",
+ "argNum": 1,
+ "expr": "minutes"
+ }
+ ]
+ },
+ {
+ "id": "{Seconds} second(s)",
+ "message": "{Seconds} second(s)",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "Seconds",
+ "cases": {
+ "one": {
+ "msg": "{Seconds} segundo"
+ },
+ "other": {
+ "msg": "{Seconds} segundos"
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "Seconds",
+ "string": "%[1]d",
+ "type": "int64",
+ "underlyingType": "int64",
+ "argNum": 1,
+ "expr": "seconds"
+ }
+ ]
+ },
+ {
+ "id": "{Timestamp} ago",
+ "message": "{Timestamp} ago",
+ "translation": "hace {Timestamp}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Timestamp",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "timestamp"
+ }
+ ]
+ },
+ {
+ "id": "{Bytes} B",
+ "message": "{Bytes} B",
+ "translation": "{Bytes} B",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Bytes",
+ "string": "%[1]d",
+ "type": "golang.zx2c4.com/wireguard/windows/conf.Bytes",
+ "underlyingType": "uint64",
+ "argNum": 1,
+ "expr": "b"
+ }
+ ]
+ },
+ {
+ "id": "{Float64b__1024} KiB",
+ "message": "{Float64b__1024} KiB",
+ "translation": "{Float64b__1024} KiB",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Float64b__1024",
+ "string": "%.2[1]f",
+ "type": "float64",
+ "underlyingType": "float64",
+ "argNum": 1,
+ "expr": "float64(b) / 1024"
+ }
+ ]
+ },
+ {
+ "id": "{Float64b__1024__1024} MiB",
+ "message": "{Float64b__1024__1024} MiB",
+ "translation": "{Float64b__1024__1024} MiB",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Float64b__1024__1024",
+ "string": "%.2[1]f",
+ "type": "float64",
+ "underlyingType": "float64",
+ "argNum": 1,
+ "expr": "float64(b) / (1024 * 1024)"
+ }
+ ]
+ },
+ {
+ "id": "{Float64b__1024__1024__1024} GiB",
+ "message": "{Float64b__1024__1024__1024} GiB",
+ "translation": "{Float64b__1024__1024__1024} GiB",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Float64b__1024__1024__1024",
+ "string": "%.2[1]f",
+ "type": "float64",
+ "underlyingType": "float64",
+ "argNum": 1,
+ "expr": "float64(b) / (1024 * 1024 * 1024)"
+ }
+ ]
+ },
+ {
+ "id": "{Float64b__1024__1024__1024__1024} TiB",
+ "message": "{Float64b__1024__1024__1024__1024} TiB",
+ "translation": "{Float64b__1024__1024__1024__1024} TiB",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Float64b__1024__1024__1024__1024",
+ "string": "%.2[1]f",
+ "type": "float64",
+ "underlyingType": "float64",
+ "argNum": 1,
+ "expr": "float64(b) / (1024 * 1024 * 1024) / 1024"
+ }
+ ]
+ },
+ {
+ "id": "Invalid IP address",
+ "message": "Invalid IP address",
+ "translation": "Dirección IP inválida",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Invalid network prefix length",
+ "message": "Invalid network prefix length",
+ "translation": "Longitud de prefijo de red no válida",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Missing port from endpoint",
+ "message": "Missing port from endpoint",
+ "translation": "Falta el puerto del extremo",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Invalid endpoint host",
+ "message": "Invalid endpoint host",
+ "translation": "Host de endpoint no válido",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Invalid MTU",
+ "message": "Invalid MTU",
+ "translation": "MTU no valido",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Invalid port",
+ "message": "Invalid port",
+ "translation": "Puerto no válido",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Invalid key: {Err}",
+ "message": "Invalid key: {Err}",
+ "translation": "Clave no válida: {Err}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Err",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "err"
+ }
+ ]
+ },
+ {
+ "id": "About WireGuard",
+ "message": "About WireGuard",
+ "translation": "Acerca de WireGuard",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "WireGuard logo image",
+ "message": "WireGuard logo image",
+ "translation": "Imagen del logo de WireGuard",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Close",
+ "message": "Close",
+ "translation": "Cerrar",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "♥ &Donate!",
+ "message": "♥ &Donate!",
+ "translation": "♥ &Donar!",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Status:",
+ "message": "Status:",
+ "translation": "Estado:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Deactivate",
+ "message": "&Deactivate",
+ "translation": "&Desactivar",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Activate",
+ "message": "&Activate",
+ "translation": "&Activar",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Public key:",
+ "message": "Public key:",
+ "translation": "Clave pública:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Listen port:",
+ "message": "Listen port:",
+ "translation": "Puerto de escucha:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "MTU:",
+ "message": "MTU:",
+ "translation": "MTU:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Addresses:",
+ "message": "Addresses:",
+ "translation": "Direcciones:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "DNS servers:",
+ "message": "DNS servers:",
+ "translation": "Servidores DNS:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Preshared key:",
+ "message": "Preshared key:",
+ "translation": "Clave compartida:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Allowed IPs:",
+ "message": "Allowed IPs:",
+ "translation": "IPs permitidas:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Latest handshake:",
+ "message": "Latest handshake:",
+ "translation": "Último saludo:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Transfer:",
+ "message": "Transfer:",
+ "translation": "Transferir:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "enabled",
+ "message": "enabled",
+ "translation": "activado",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Failed to activate tunnel",
+ "message": "Failed to activate tunnel",
+ "translation": "Error al activar el túnel",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Failed to deactivate tunnel",
+ "message": "Failed to deactivate tunnel",
+ "translation": "Error al desactivar el túnel",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Interface: {Name}",
+ "message": "Interface: {Name}",
+ "translation": "Interfaz: {Name}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Name",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "config.Name"
+ }
+ ]
+ },
+ {
+ "id": "Peer",
+ "message": "Peer",
+ "translation": "Pares",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Create new tunnel",
+ "message": "Create new tunnel",
+ "translation": "Crear un túnel nuevo",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Edit tunnel",
+ "message": "Edit tunnel",
+ "translation": "Editar túnel",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Name:",
+ "message": "&Name:",
+ "translation": "&Nombre:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Public key:",
+ "message": "&Public key:",
+ "translation": "Clave pública:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "(unknown)",
+ "message": "(unknown)",
+ "translation": "(desconocido)",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Save",
+ "message": "&Save",
+ "translation": "&Guardar",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Cancel",
+ "message": "Cancel",
+ "translation": "Cancelar",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Configuration:",
+ "message": "&Configuration:",
+ "translation": "&Configuración:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Invalid name",
+ "message": "Invalid name",
+ "translation": "Nombre no válido",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "A name is required.",
+ "message": "A name is required.",
+ "translation": "Se requiere un nombre.",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Tunnel name ‘{NewName}’ is invalid.",
+ "message": "Tunnel name ‘{NewName}’ is invalid.",
+ "translation": "El nombre del túnel ‘{NewName}’ no es válido.",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "NewName",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "newName"
+ }
+ ]
+ },
+ {
+ "id": "Active",
+ "message": "Active",
+ "translation": "Activo",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Activating",
+ "message": "Activating",
+ "translation": "Activando",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Inactive",
+ "message": "Inactive",
+ "translation": "Inactivo",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Deactivating",
+ "message": "Deactivating",
+ "translation": "Desactivando",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Unknown state",
+ "message": "Unknown state",
+ "translation": "Estado desconocido",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Log",
+ "message": "Log",
+ "translation": "Registro",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Copy",
+ "message": "&Copy",
+ "translation": "&Copiar",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Select &all",
+ "message": "Select &all",
+ "translation": "Seleccionar &todo",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Save to file…",
+ "message": "&Save to file…",
+ "translation": "&Guardar en archivo…",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Time",
+ "message": "Time",
+ "translation": "Tiempo",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Log message",
+ "message": "Log message",
+ "translation": "Registro de mensajes",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Text Files (*.txt)|*.txt|All Files (*.*)|*.*",
+ "message": "Text Files (*.txt)|*.txt|All Files (*.*)|*.*",
+ "translation": "Archivos de texto (*.txt)|*.txt|Todos los archivos (*.*)|*.*",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Export log to file",
+ "message": "Export log to file",
+ "translation": "Exportar archivo de registro",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&About WireGuard…",
+ "message": "&About WireGuard…",
+ "translation": "&Acerca de WireGuard…",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Tunnel Error",
+ "message": "Tunnel Error",
+ "translation": "Error en el túnel",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "{ErrMsg}\n\nPlease consult the log for more information.",
+ "message": "{ErrMsg}\n\nPlease consult the log for more information.",
+ "translation": "{ErrMsg}\n\nPor favor, consulte el registro para más información.",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "ErrMsg",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "errMsg"
+ }
+ ]
+ },
+ {
+ "id": "WireGuard: Deactivated",
+ "message": "WireGuard: Deactivated",
+ "translation": "WireGuard: Desactivado",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Status: Unknown",
+ "message": "Status: Unknown",
+ "translation": "Estado: Desconocido",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Addresses: None",
+ "message": "Addresses: None",
+ "translation": "Direcciones: Ninguna",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "E&xit",
+ "message": "E&xit",
+ "translation": "&Salir",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Tunnels",
+ "message": "&Tunnels",
+ "translation": "&Túneles",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "WireGuard Activated",
+ "message": "WireGuard Activated",
+ "translation": "WireGuard Activado",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "WireGuard Deactivated",
+ "message": "WireGuard Deactivated",
+ "translation": "WireGuard: Desactivado",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "WireGuard Tunnel Error",
+ "message": "WireGuard Tunnel Error",
+ "translation": "Error en el túnel de WireGuard",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "WireGuard: {TextForStateglobalState_true}",
+ "message": "WireGuard: {TextForStateglobalState_true}",
+ "translation": "WireGuard: {TextForStateglobalState_true}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "TextForStateglobalState_true",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "textForState(globalState, true)"
+ }
+ ]
+ },
+ {
+ "id": "Status: {StateText}",
+ "message": "Status: {StateText}",
+ "translation": "Estado: {StateText}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "StateText",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "stateText"
+ }
+ ]
+ },
+ {
+ "id": "Addresses: {EnumerationSeparator}",
+ "message": "Addresses: {EnumerationSeparator}",
+ "translation": "Direcciones: {EnumerationSeparator}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "EnumerationSeparator",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "strings.Join(addrs, l18n.EnumerationSeparator())"
+ }
+ ]
+ },
+ {
+ "id": "An Update is Available!",
+ "message": "An Update is Available!",
+ "translation": "Hay una actualización disponible!",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "WireGuard Update Available",
+ "message": "WireGuard Update Available",
+ "translation": "Actualización de WireGuard disponible",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "An update to WireGuard is now available. You are advised to update as soon as possible.",
+ "message": "An update to WireGuard is now available. You are advised to update as soon as possible.",
+ "translation": "Ya está disponible una actualización de WireGuard. Se recomienda actualizar lo antes posible.",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Tunnels",
+ "message": "Tunnels",
+ "translation": "Túneles",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Edit",
+ "message": "&Edit",
+ "translation": "&Editar",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Add &empty tunnel…",
+ "message": "Add &empty tunnel…",
+ "translation": "Añadir &túnel vacío…",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Add Tunnel",
+ "message": "Add Tunnel",
+ "translation": "Añadir túnel",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Remove selected tunnel(s)",
+ "message": "Remove selected tunnel(s)",
+ "translation": "Eliminar túneles seleccionados",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Export all tunnels to zip",
+ "message": "Export all tunnels to zip",
+ "translation": "Exportar todos los túneles a zip",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Toggle",
+ "message": "&Toggle",
+ "translation": "&Alternar",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Could not enumerate existing tunnels: {LastErr}",
+ "message": "Could not enumerate existing tunnels: {LastErr}",
+ "translation": "No se pueden enumerar los túneles existentes: {LastErr}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "LastErr",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "lastErr"
+ }
+ ]
+ },
+ {
+ "id": "Another tunnel already exists with the name ‘{Name}’",
+ "message": "Another tunnel already exists with the name ‘{Name}’",
+ "translation": "Ya existe otro túnel con el nombre '{Name}'",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Name",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "unparsedConfig.Name"
+ }
+ ]
+ },
+ {
+ "id": "Unable to import configuration: {LastErr}",
+ "message": "Unable to import configuration: {LastErr}",
+ "translation": "Imposible importar la configuración: {LastErr}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "LastErr",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "lastErr"
+ }
+ ]
+ },
+ {
+ "id": "Imported tunnels",
+ "message": "Imported tunnels",
+ "translation": "Túneles importados",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Imported {M} tunnels",
+ "message": "Imported {M} tunnels",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "M",
+ "cases": {
+ "one": {
+ "msg": "{M} túnel importado"
+ },
+ "other": {
+ "msg": "{M} túneles importados"
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "M",
+ "string": "%[1]d",
+ "type": "int",
+ "underlyingType": "int",
+ "argNum": 1,
+ "expr": "m"
+ }
+ ]
+ },
+ {
+ "id": "Imported {M} of {N} tunnels",
+ "message": "Imported {M} of {N} tunnels",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "N",
+ "cases": {
+ "one": {
+ "msg": "Importado {M} de {N} túnel"
+ },
+ "other": {
+ "msg": "Importados {M} de {N} túneles"
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "M",
+ "string": "%[1]d",
+ "type": "int",
+ "underlyingType": "int",
+ "argNum": 1,
+ "expr": "m"
+ },
+ {
+ "id": "N",
+ "string": "%[2]d",
+ "type": "int",
+ "underlyingType": "int",
+ "argNum": 2,
+ "expr": "n"
+ }
+ ]
+ },
+ {
+ "id": "Unable to create tunnel",
+ "message": "Unable to create tunnel",
+ "translation": "No se pudo crear el túnel",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Delete {TunnelCount} tunnels",
+ "message": "Delete {TunnelCount} tunnels",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "TunnelCount",
+ "cases": {
+ "one": {
+ "msg": "Eliminar {TunnelCount} túnel"
+ },
+ "other": {
+ "msg": "Eliminar {TunnelCount} túneles"
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "TunnelCount",
+ "string": "%[1]d",
+ "type": "int",
+ "underlyingType": "int",
+ "argNum": 1,
+ "expr": "tunnelCount"
+ }
+ ]
+ },
+ {
+ "id": "Delete tunnel ‘{TunnelName}’",
+ "message": "Delete tunnel ‘{TunnelName}’",
+ "translation": "Eliminar túnel ‘{TunnelName}’",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "TunnelName",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "tunnelName"
+ }
+ ]
+ },
+ {
+ "id": "Are you sure you would like to delete tunnel ‘{TunnelName}’?",
+ "message": "Are you sure you would like to delete tunnel ‘{TunnelName}’?",
+ "translation": "¿Está seguro de que desea eliminar el túnel ‘{TunnelName}’?",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "TunnelName",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "tunnelName"
+ }
+ ]
+ },
+ {
+ "id": "{Question} You cannot undo this action.",
+ "message": "{Question} You cannot undo this action.",
+ "translation": "{Question} No puedes deshacer esta acción.",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Question",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "question"
+ }
+ ]
+ },
+ {
+ "id": "Unable to delete tunnel",
+ "message": "Unable to delete tunnel",
+ "translation": "No se pudo eliminar el tunel",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "A tunnel was unable to be removed: {Error}",
+ "message": "A tunnel was unable to be removed: {Error}",
+ "translation": "No se ha podido eliminar un túnel: {Error}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Error",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "errors[0].Error()"
+ }
+ ]
+ },
+ {
+ "id": "Unable to delete tunnels",
+ "message": "Unable to delete tunnels",
+ "translation": "Imposible eliminar túneles",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Status: Waiting for user",
+ "message": "Status: Waiting for user",
+ "translation": "Estado: Esperando al usuario",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Update Now",
+ "message": "Update Now",
+ "translation": "Actualizar",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Error: {Err}. Please try again.",
+ "message": "Error: {Err}. Please try again.",
+ "translation": "Error: {Err}. Inténtalo de nuevo.",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Err",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "err"
+ }
+ ]
+ },
+ {
+ "id": "Status: Complete!",
+ "message": "Status: Complete!",
+ "translation": "Estado: Completo!",
+ "translatorComment": "Copied from source."
}
]
} \ No newline at end of file
diff --git a/locales/fi/messages.gotext.json b/locales/fi/messages.gotext.json
index cca09e32..59521b02 100644
--- a/locales/fi/messages.gotext.json
+++ b/locales/fi/messages.gotext.json
@@ -20,18 +20,84 @@
"translatorComment": "Copied from source."
},
{
+ "id": "{Timestamp} ago",
+ "message": "{Timestamp} ago",
+ "translation": "{Timestamp} sitten",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Timestamp",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "timestamp"
+ }
+ ]
+ },
+ {
+ "id": "{Bytes} B",
+ "message": "{Bytes} B",
+ "translation": "{Bytes} B",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Bytes",
+ "string": "%[1]d",
+ "type": "golang.zx2c4.com/wireguard/windows/conf.Bytes",
+ "underlyingType": "uint64",
+ "argNum": 1,
+ "expr": "b"
+ }
+ ]
+ },
+ {
+ "id": "Invalid MTU",
+ "message": "Invalid MTU",
+ "translation": "Virheellinen MTU",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Invalid port",
+ "message": "Invalid port",
+ "translation": "Virheellinen portti",
+ "translatorComment": "Copied from source."
+ },
+ {
"id": "Invalid persistent keepalive",
"message": "Invalid persistent keepalive",
"translation": "Virheellinen jatkuva keepalive",
"translatorComment": "Copied from source."
},
{
+ "id": "Invalid key: {Err}",
+ "message": "Invalid key: {Err}",
+ "translation": "Virheellinen avain: {Err}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Err",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "err"
+ }
+ ]
+ },
+ {
"id": "[EnumerationSeparator]",
"message": "[EnumerationSeparator]",
"translation": ", ",
"comment": "Text to insert between items when listing - most western languages will translate ‘[EnumerationSeparator]’ into ‘, ’ to produce lists like ‘apple, orange, strawberry’. Eastern languages might translate into ‘、’ to produce lists like ‘リンゴ、オレンジ、イチゴ’."
},
{
+ "id": "[UnitSeparator]",
+ "message": "[UnitSeparator]",
+ "translation": ", ",
+ "comment": "Text to insert when combining units of a measure - most languages will translate ‘[UnitSeparator]’ into ‘ ’ (space) to produce lists like ‘2 minuti 30 sekund’, or empty string ‘’ to produce ‘2分30秒’."
+ },
+ {
"id": "About WireGuard",
"message": "About WireGuard",
"translation": "Tietoa WireGuardista",
@@ -62,6 +128,18 @@
"translatorComment": "Copied from source."
},
{
+ "id": "Public key:",
+ "message": "Public key:",
+ "translation": "Julkinen avain:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Listen port:",
+ "message": "Listen port:",
+ "translation": "Kuuntele porttia:",
+ "translatorComment": "Copied from source."
+ },
+ {
"id": "MTU:",
"message": "MTU:",
"translation": "MTU:",
@@ -122,6 +200,52 @@
"translatorComment": "Copied from source."
},
{
+ "id": "enabled",
+ "message": "enabled",
+ "translation": "käytössä",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "{String} received, {String_1} sent",
+ "message": "{String} received, {String_1} sent",
+ "translation": "{String} vastaanotettu, {String_1} lähetetty",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "String",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "c.RxBytes.String()"
+ },
+ {
+ "id": "String_1",
+ "string": "%[2]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 2,
+ "expr": "c.TxBytes.String()"
+ }
+ ]
+ },
+ {
+ "id": "Interface: {Name}",
+ "message": "Interface: {Name}",
+ "translation": "Verkkoyhteys: {Name}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Name",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "config.Name"
+ }
+ ]
+ },
+ {
"id": "Peer",
"message": "Peer",
"translation": "Osapuoli",
@@ -206,6 +330,12 @@
"translatorComment": "Copied from source."
},
{
+ "id": "&Import tunnel(s) from file…",
+ "message": "&Import tunnel(s) from file…",
+ "translation": "Tuo tunnele&ita tiedostosta…",
+ "translatorComment": "Copied from source."
+ },
+ {
"id": "An Update is Available!",
"message": "An Update is Available!",
"translation": "Päivitys on saatavilla!",
@@ -236,6 +366,18 @@
"translatorComment": "Copied from source."
},
{
+ "id": "Add &empty tunnel…",
+ "message": "Add &empty tunnel…",
+ "translation": "Lisää tyhjä tunn&eli…",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Add Tunnel",
+ "message": "Add Tunnel",
+ "translation": "Lisää tunneli",
+ "translatorComment": "Copied from source."
+ },
+ {
"id": "Imported tunnels",
"message": "Imported tunnels",
"translation": "Tuodut tunnelit",
diff --git a/locales/it/messages.gotext.json b/locales/it/messages.gotext.json
index f1626e8b..5bea90c2 100644
--- a/locales/it/messages.gotext.json
+++ b/locales/it/messages.gotext.json
@@ -60,6 +60,12 @@
]
},
{
+ "id": "You must use the native version of WireGuard on this computer.",
+ "message": "You must use the native version of WireGuard on this computer.",
+ "translation": "Devi utilizzare la versione nativa di WireGuard su questo computer.",
+ "translatorComment": "Copied from source."
+ },
+ {
"id": "Unable to open current process token: {Err}",
"message": "Unable to open current process token: {Err}",
"translation": "Impossibile aprire il token del processo corrente: {Err}",
@@ -490,6 +496,12 @@
"translatorComment": "Copied from source."
},
{
+ "id": "Config key is missing an equals separator",
+ "message": "Config key is missing an equals separator",
+ "translation": "Manca un separatore di uguaglianza per la chiave di configurazione",
+ "translatorComment": "Copied from source."
+ },
+ {
"id": "Key must have a value",
"message": "Key must have a value",
"translation": "La chiave deve avere un valore",
@@ -574,6 +586,62 @@
"translatorComment": "Copied from source."
},
{
+ "id": "App version: {Number}\nGo backend version: {WireGuardGoVersion}\nGo version: {Version_go}-{GOARCH}\nOperating system: {OsName}\nArchitecture: {NativeArch}",
+ "message": "App version: {Number}\nGo backend version: {WireGuardGoVersion}\nGo version: {Version_go}-{GOARCH}\nOperating system: {OsName}\nArchitecture: {NativeArch}",
+ "translation": "Versione applicazione: {Number}\nVersione backend Go: {WireGuardGoVersion}\nVersione Go: {Version_go}-{GOARCH}\nSistema operativo: {OsName}\nArchitettura: {NativeArch}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Number",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "version.Number"
+ },
+ {
+ "id": "WireGuardGoVersion",
+ "string": "%[2]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 2,
+ "expr": "device.WireGuardGoVersion"
+ },
+ {
+ "id": "Version_go",
+ "string": "%[3]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 3,
+ "expr": "strings.TrimPrefix(runtime.Version(), \"go\")"
+ },
+ {
+ "id": "GOARCH",
+ "string": "%[4]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 4,
+ "expr": "runtime.GOARCH"
+ },
+ {
+ "id": "OsName",
+ "string": "%[5]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 5,
+ "expr": "version.OsName()"
+ },
+ {
+ "id": "NativeArch",
+ "string": "%[6]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 6,
+ "expr": "version.NativeArch()"
+ }
+ ]
+ },
+ {
"id": "Close",
"message": "Close",
"translation": "Chiudi",
@@ -634,6 +702,12 @@
"translatorComment": "Copied from source."
},
{
+ "id": "Scripts:",
+ "message": "Scripts:",
+ "translation": "Script:",
+ "translatorComment": "Copied from source."
+ },
+ {
"id": "Preshared key:",
"message": "Preshared key:",
"translation": "Chiave pre-condivisa:",
@@ -670,6 +744,36 @@
"translatorComment": "Copied from source."
},
{
+ "id": "pre-up",
+ "message": "pre-up",
+ "translation": "pre-up",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "post-up",
+ "message": "post-up",
+ "translation": "post-up",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "pre-down",
+ "message": "pre-down",
+ "translation": "pre-down",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "post-down",
+ "message": "post-down",
+ "translation": "post-down",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "disabled, per policy",
+ "message": "disabled, per policy",
+ "translation": "disattivato, per criterio",
+ "translatorComment": "Copied from source."
+ },
+ {
"id": "enabled",
"message": "enabled",
"translation": "abilitato",
@@ -776,6 +880,12 @@
"translatorComment": "Copied from source."
},
{
+ "id": "When a configuration has exactly one peer, and that peer has an allowed IPs containing at least one of 0.0.0.0/0 or ::/0, then the tunnel service engages a firewall ruleset to block all traffic that is neither to nor from the tunnel interface or is to the wrong DNS server, with special exceptions for DHCP and NDP.",
+ "message": "When a configuration has exactly one peer, and that peer has an allowed IPs containing at least one of 0.0.0.0/0 or ::/0, then the tunnel service engages a firewall ruleset to block all traffic that is neither to nor from the tunnel interface or is to the wrong DNS server, with special exceptions for DHCP and NDP.",
+ "translation": "Quando una configurazione ha esattamente un peer e quel peer ha un IP consentito contenente almeno uno tra 0.0.0.0/0 o ::/0, il servizio tunnel impiega un insieme di regole del firewall per bloccare tutto il traffico nè diretto nè proveniente dall'interfaccia tunnel o verso un server DNS sbagliato, con speciali eccezioni per DHCP e NDP.",
+ "translatorComment": "Copied from source."
+ },
+ {
"id": "&Save",
"message": "&Save",
"translation": "&Salva",
@@ -1058,6 +1168,12 @@
"translatorComment": "Copied from source."
},
{
+ "id": "&Tunnels",
+ "message": "&Tunnels",
+ "translation": "&Tunnel",
+ "translatorComment": "Copied from source."
+ },
+ {
"id": "WireGuard Activated",
"message": "WireGuard Activated",
"translation": "WireGuard attivato",
@@ -1140,6 +1256,22 @@
]
},
{
+ "id": "Addresses: {EnumerationSeparator}",
+ "message": "Addresses: {EnumerationSeparator}",
+ "translation": "Indirizzi: {EnumerationSeparator}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "EnumerationSeparator",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "strings.Join(addrs, l18n.EnumerationSeparator())"
+ }
+ ]
+ },
+ {
"id": "An Update is Available!",
"message": "An Update is Available!",
"translation": "Un aggiornamento è disponibile!",
@@ -1172,7 +1304,7 @@
{
"id": "Add &empty tunnel…",
"message": "Add &empty tunnel…",
- "translation": "Aggiungi tunn&el vuoto",
+ "translation": "Aggiungi tunn&el vuoto...",
"translatorComment": "Copied from source."
},
{
@@ -1202,7 +1334,7 @@
{
"id": "Export all tunnels to &zip…",
"message": "Export all tunnels to &zip…",
- "translation": "Esporta tutti i tunnel in &zip",
+ "translation": "Esporta tutti i tunnel in &zip...",
"translatorComment": "Copied from source."
},
{
@@ -1218,6 +1350,12 @@
"translatorComment": "Copied from source."
},
{
+ "id": "no configuration files were found",
+ "message": "no configuration files were found",
+ "translation": "nessun file di configurazione trovato",
+ "translatorComment": "Copied from source."
+ },
+ {
"id": "Could not import selected configuration: {LastErr}",
"message": "Could not import selected configuration: {LastErr}",
"translation": "Impossibile importare la configurazione selezionata: {LastErr}",
diff --git a/locales/ja/messages.gotext.json b/locales/ja/messages.gotext.json
index 61751200..77234a68 100644
--- a/locales/ja/messages.gotext.json
+++ b/locales/ja/messages.gotext.json
@@ -60,6 +60,12 @@
]
},
{
+ "id": "You must use the native version of WireGuard on this computer.",
+ "message": "You must use the native version of WireGuard on this computer.",
+ "translation": "このコンピュータではネイティブ版の WireGuard を使ってください。",
+ "translatorComment": "Copied from source."
+ },
+ {
"id": "Unable to open current process token: {Err}",
"message": "Unable to open current process token: {Err}",
"translation": "現在のプロセスのトークンを開けません: {Err}",
@@ -565,6 +571,62 @@
"translatorComment": "Copied from source."
},
{
+ "id": "App version: {Number}\nGo backend version: {WireGuardGoVersion}\nGo version: {Version_go}-{GOARCH}\nOperating system: {OsName}\nArchitecture: {NativeArch}",
+ "message": "App version: {Number}\nGo backend version: {WireGuardGoVersion}\nGo version: {Version_go}-{GOARCH}\nOperating system: {OsName}\nArchitecture: {NativeArch}",
+ "translation": "アプリ バージョン: {Number}\nGo バックエンド バージョン: {WireGuardGoVersion}\nGo バージョン: {Version_go}-{GOARCH}\nOS: {OsName}\nアーキテクチャ: {NativeArch}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Number",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "version.Number"
+ },
+ {
+ "id": "WireGuardGoVersion",
+ "string": "%[2]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 2,
+ "expr": "device.WireGuardGoVersion"
+ },
+ {
+ "id": "Version_go",
+ "string": "%[3]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 3,
+ "expr": "strings.TrimPrefix(runtime.Version(), \"go\")"
+ },
+ {
+ "id": "GOARCH",
+ "string": "%[4]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 4,
+ "expr": "runtime.GOARCH"
+ },
+ {
+ "id": "OsName",
+ "string": "%[5]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 5,
+ "expr": "version.OsName()"
+ },
+ {
+ "id": "NativeArch",
+ "string": "%[6]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 6,
+ "expr": "version.NativeArch()"
+ }
+ ]
+ },
+ {
"id": "Close",
"message": "Close",
"translation": "閉じる",
@@ -625,6 +687,12 @@
"translatorComment": "Copied from source."
},
{
+ "id": "Scripts:",
+ "message": "Scripts:",
+ "translation": "スクリプト:",
+ "translatorComment": "Copied from source."
+ },
+ {
"id": "Preshared key:",
"message": "Preshared key:",
"translation": "事前共有鍵:",
@@ -661,6 +729,36 @@
"translatorComment": "Copied from source."
},
{
+ "id": "pre-up",
+ "message": "pre-up",
+ "translation": "pre-up",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "post-up",
+ "message": "post-up",
+ "translation": "post-up",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "pre-down",
+ "message": "pre-down",
+ "translation": "pre-down",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "post-down",
+ "message": "post-down",
+ "translation": "post-down",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "disabled, per policy",
+ "message": "disabled, per policy",
+ "translation": "ポリシーにより無効です",
+ "translatorComment": "Copied from source."
+ },
+ {
"id": "enabled",
"message": "enabled",
"translation": "有効",
@@ -767,6 +865,12 @@
"translatorComment": "Copied from source."
},
{
+ "id": "When a configuration has exactly one peer, and that peer has an allowed IPs containing at least one of 0.0.0.0/0 or ::/0, then the tunnel service engages a firewall ruleset to block all traffic that is neither to nor from the tunnel interface or is to the wrong DNS server, with special exceptions for DHCP and NDP.",
+ "message": "When a configuration has exactly one peer, and that peer has an allowed IPs containing at least one of 0.0.0.0/0 or ::/0, then the tunnel service engages a firewall ruleset to block all traffic that is neither to nor from the tunnel interface or is to the wrong DNS server, with special exceptions for DHCP and NDP.",
+ "translation": "ピアが1つだけ設定されていて、Allowed IPs に 0.0.0.0/0 または :: / 0 が含まれている場合、トンネルサービスはトンネルインターフェイスを通らないトラフィックや間違った DNS サーバーに向かう通信をブロックするファイアウォールルールを追加します。\nDHCP と NDP には特別な例外があります。",
+ "translatorComment": "Copied from source."
+ },
+ {
"id": "&Save",
"message": "&Save",
"translation": "保存(&S)",
@@ -1049,6 +1153,12 @@
"translatorComment": "Copied from source."
},
{
+ "id": "&Tunnels",
+ "message": "&Tunnels",
+ "translation": "& トンネル",
+ "translatorComment": "Copied from source."
+ },
+ {
"id": "WireGuard Activated",
"message": "WireGuard Activated",
"translation": "WireGuard 有効化済み",
@@ -1131,6 +1241,22 @@
]
},
{
+ "id": "Addresses: {EnumerationSeparator}",
+ "message": "Addresses: {EnumerationSeparator}",
+ "translation": "アドレス: {EnumerationSeparator}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "EnumerationSeparator",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "strings.Join(addrs, l18n.EnumerationSeparator())"
+ }
+ ]
+ },
+ {
"id": "An Update is Available!",
"message": "An Update is Available!",
"translation": "更新が利用できます!",
@@ -1209,6 +1335,12 @@
"translatorComment": "Copied from source."
},
{
+ "id": "no configuration files were found",
+ "message": "no configuration files were found",
+ "translation": "設定ファイルが見つかりません",
+ "translatorComment": "Copied from source."
+ },
+ {
"id": "Could not import selected configuration: {LastErr}",
"message": "Could not import selected configuration: {LastErr}",
"translation": "選択したファイルからインポートできませんでした: {LastErr}",
diff --git a/locales/ko/messages.gotext.json b/locales/ko/messages.gotext.json
new file mode 100644
index 00000000..d7a7040e
--- /dev/null
+++ b/locales/ko/messages.gotext.json
@@ -0,0 +1,11 @@
+{
+ "language": "ko",
+ "messages": [
+ {
+ "id": "Error",
+ "message": "Error",
+ "translation": "오류",
+ "translatorComment": "Copied from source."
+ }
+ ]
+} \ No newline at end of file
diff --git a/locales/pa-IN/messages.gotext.json b/locales/pa-IN/messages.gotext.json
index 1fe5c65d..e9626d24 100644
--- a/locales/pa-IN/messages.gotext.json
+++ b/locales/pa-IN/messages.gotext.json
@@ -422,6 +422,62 @@
"translatorComment": "Copied from source."
},
{
+ "id": "Invalid key: {Err}",
+ "message": "Invalid key: {Err}",
+ "translation": "ਗ਼ੈਰ-ਵਾਜਬ ਕੁੰਜੀ: {Err}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Err",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "err"
+ }
+ ]
+ },
+ {
+ "id": "Keys must decode to exactly 32 bytes",
+ "message": "Keys must decode to exactly 32 bytes",
+ "translation": "ਕੁੰਜੀਆਂ ਠੀਕ 32 ਬਾਈਟ ਲਈ ਡੀਕੋਡ ਹੋਣੀਆਂ ਚਾਹੀਦੀਆਂ ਹਨ",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Number must be a number between 0 and 2^64-1: {Err}",
+ "message": "Number must be a number between 0 and 2^64-1: {Err}",
+ "translation": "ਨੰਬਰ 0 ਅਤੇ 2^64-1 ਦੇ ਵਿਚਾਲੇ ਹੋਣਾ ਚਾਹੀਦਾ ਹੈ: {Err}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Err",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "err"
+ }
+ ]
+ },
+ {
+ "id": "Two commas in a row",
+ "message": "Two commas in a row",
+ "translation": "ਇੱਕ ਕਤਾਰ ਵਿੱਚ ਦੋ ਕੌਮੇ ਹਨ",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Tunnel name is not valid",
+ "message": "Tunnel name is not valid",
+ "translation": "ਟਨਲ ਦਾ ਨਾਂ ਠੀਕ ਨਹੀਂ ਹੈ",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Line must occur in a section",
+ "message": "Line must occur in a section",
+ "translation": "ਭਾਗ ਵਿੱਚ ਲਾਈਨ ਹੋਣੀ ਚਾਹੀਦੀ ਹੈ",
+ "translatorComment": "Copied from source."
+ },
+ {
"id": "[EnumerationSeparator]",
"message": "[EnumerationSeparator]",
"translation": ", ",
@@ -680,6 +736,12 @@
"translatorComment": "Copied from source."
},
{
+ "id": "&Block untunneled traffic (kill-switch)",
+ "message": "&Block untunneled traffic (kill-switch)",
+ "translation": "ਬਿਨਾਂ-ਟਨਲ ਵਾਲੇ ਟਰੈਫਿਕ ਉੱਤੇ ਪਾਬੰਦੀ ਲਾਓ (&B) (kill-switch)",
+ "translatorComment": "Copied from source."
+ },
+ {
"id": "&Save",
"message": "&Save",
"translation": "ਸੰਭਾਲੋ(&S)",
@@ -1112,18 +1174,106 @@
"translatorComment": "Copied from source."
},
{
+ "id": "Another tunnel already exists with the name ‘{Name}’",
+ "message": "Another tunnel already exists with the name ‘{Name}’",
+ "translation": "‘{Name}’ ਨਾਂ ਨਾਲ ਹੋਰ ਟਨਲ ਪਹਿਲਾਂ ਹੀ ਮੌਜੂਦ ਹੈ",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Name",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "unparsedConfig.Name"
+ }
+ ]
+ },
+ {
+ "id": "Unable to import configuration: {LastErr}",
+ "message": "Unable to import configuration: {LastErr}",
+ "translation": "ਸੰਰਚਨਾ ਇੰਪੋਰਟ ਕਰਨ ਲਈ ਅਸਮਰੱਥ: {LastErr}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "LastErr",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "lastErr"
+ }
+ ]
+ },
+ {
"id": "Imported tunnels",
"message": "Imported tunnels",
"translation": "ਇੰਪੋਰਟ ਕੀਤੀਆਂ ਟਨਲਾਂ",
"translatorComment": "Copied from source."
},
{
+ "id": "Imported {M} tunnels",
+ "message": "Imported {M} tunnels",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "M",
+ "cases": {
+ "one": {
+ "msg": "{M} ਟਨਲ ਇੰਪੋਰਟ ਕੀਤੀ"
+ },
+ "other": {
+ "msg": "{M} ਟਨਲਾਂ ਇੰਪੋਰਟ ਕੀਤੀਆਂ"
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "M",
+ "string": "%[1]d",
+ "type": "int",
+ "underlyingType": "int",
+ "argNum": 1,
+ "expr": "m"
+ }
+ ]
+ },
+ {
"id": "Unable to create tunnel",
"message": "Unable to create tunnel",
"translation": "ਟਨਲ ਬਣਾਉਣ ਲਈ ਅਸਮਰੱਥ",
"translatorComment": "Copied from source."
},
{
+ "id": "Delete {TunnelCount} tunnels",
+ "message": "Delete {TunnelCount} tunnels",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "TunnelCount",
+ "cases": {
+ "one": {
+ "msg": "{TunnelCount} ਟਨਲ ਹਟਾਓ"
+ },
+ "other": {
+ "msg": "{TunnelCount} ਟਨਲਾਂ ਹਟਾਓ"
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "TunnelCount",
+ "string": "%[1]d",
+ "type": "int",
+ "underlyingType": "int",
+ "argNum": 1,
+ "expr": "tunnelCount"
+ }
+ ]
+ },
+ {
"id": "Are you sure you would like to delete {TunnelCount} tunnels?",
"message": "Are you sure you would like to delete {TunnelCount} tunnels?",
"translation": {
@@ -1184,12 +1334,50 @@
]
},
{
+ "id": "{Question} You cannot undo this action.",
+ "message": "{Question} You cannot undo this action.",
+ "translation": "{Question} ਤੁਸੀਂ ਇਹ ਕਾਰਵਾਈ ਵਾਪਸ ਨਹੀਂ ਲੈ ਸਕਦੇ ਹੋ।",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Question",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "question"
+ }
+ ]
+ },
+ {
"id": "Unable to delete tunnel",
"message": "Unable to delete tunnel",
"translation": "ਟਨਲ ਹਟਾਉਣ ਲਈ ਅਸਮਰੱਥ",
"translatorComment": "Copied from source."
},
{
+ "id": "A tunnel was unable to be removed: {Error}",
+ "message": "A tunnel was unable to be removed: {Error}",
+ "translation": "ਟਨਲ ਹਟਾਉਣ ਲਈ ਅਸਮਰੱਥ ਹੈ: {Error}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Error",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "errors[0].Error()"
+ }
+ ]
+ },
+ {
+ "id": "Unable to delete tunnels",
+ "message": "Unable to delete tunnels",
+ "translation": "ਟਨਲਾਂ ਹਟਾਉਣ ਲਈ ਅਸਮਰੱਥ",
+ "translatorComment": "Copied from source."
+ },
+ {
"id": "Configuration Files (*.zip, *.conf)|*.zip;*.conf|All Files (*.*)|*.*",
"message": "Configuration Files (*.zip, *.conf)|*.zip;*.conf|All Files (*.*)|*.*",
"translation": "ਸੰਰਚਨਾ ਫ਼ਾਇਲਾਂ (*.zip, *.conf)|*.zip;*.conf|ਸਾਰੀਆਂ ਫ਼ਾਇਲਾਂ (*.*)|*.*",
@@ -1208,12 +1396,68 @@
"translatorComment": "Copied from source."
},
{
+ "id": "Error Exiting WireGuard",
+ "message": "Error Exiting WireGuard",
+ "translation": "WireGuard ਤੋਂ ਬਾਹਰ ਜਾਣ ਲਈ ਗ਼ਲਤੀ",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Unable to exit service due to: {Err}. You may want to stop WireGuard from the service manager.",
+ "message": "Unable to exit service due to: {Err}. You may want to stop WireGuard from the service manager.",
+ "translation": "ਸੇਵਾ ਤੋਂ ਬਾਹਰ ਜਾਣ ਲਈ ਅਸਮਰੱਥ, ਕਾਰਨ: {Err}। ਤੁਸੀਂ ਸੇਵਾ ਮੈਨੇਜਰ ਤੋਂ WireGuard ਨੂੰ ਰੋਕਣਾ ਚਾਹੋਗੇ।",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Err",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "err"
+ }
+ ]
+ },
+ {
+ "id": "An update to WireGuard is available. It is highly advisable to update without delay.",
+ "message": "An update to WireGuard is available. It is highly advisable to update without delay.",
+ "translation": "WireGuard ਲਈ ਅੱਪਡੇਟ ਮੌਜੂਦ ਹੈ। ਤੁਹਾਨੂੰ ਬਿਨਾਂ ਦੇਰ ਕੀਤਿਆਂ ਅੱਪਡੇਟ ਕਰਨ ਦੀ ਸਲਾਹ ਦਿੱਤੀ ਜਾਂਦੀ ਹੈ।",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Status: Waiting for user",
+ "message": "Status: Waiting for user",
+ "translation": "ਹਾਲਤ: ਵਰਤੋਂਕਾਰ ਲਈ ਉਡੀਕ ਕੀਤੀ ਜਾ ਰਹੀ ਹੈ",
+ "translatorComment": "Copied from source."
+ },
+ {
"id": "Update Now",
"message": "Update Now",
"translation": "ਹੁਣੇ ਅੱਪਡੇਟ ਕਰੋ",
"translatorComment": "Copied from source."
},
{
+ "id": "Status: Waiting for updater service",
+ "message": "Status: Waiting for updater service",
+ "translation": "ਹਾਲਤ: ਅੱਪਡੇਟਰ ਸੇਵਾ ਦੀ ਉਡੀਕ ਕੀਤੀ ਜਾ ਰਹੀ ਹੈ",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Error: {Err}. Please try again.",
+ "message": "Error: {Err}. Please try again.",
+ "translation": "ਗ਼ਲਤੀ: {Err}। ਫੇਰ ਕੋਸ਼ਿਸ਼ ਕਰੋ।",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Err",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "err"
+ }
+ ]
+ },
+ {
"id": "Status: Complete!",
"message": "Status: Complete!",
"translation": "ਸਥਿਤੀ: ਪੂਰਾ!",
diff --git a/locales/pl/messages.gotext.json b/locales/pl/messages.gotext.json
index 072fa8e4..e702e1ca 100644
--- a/locales/pl/messages.gotext.json
+++ b/locales/pl/messages.gotext.json
@@ -16,7 +16,7 @@
{
"id": "Usage: {Args0} [\n{String}]",
"message": "Usage: {Args0} [\n{String}]",
- "translation": "Użycie: {Args0} [{String}]",
+ "translation": "Użycie: {Args0} [\n{String}]",
"translatorComment": "Copied from source.",
"placeholders": [
{
@@ -62,7 +62,7 @@
{
"id": "You must use the native version of WireGuard on this computer.",
"message": "You must use the native version of WireGuard on this computer.",
- "translation": "Musisz użyć natywnej wersji WireGuard na tym komputerze.",
+ "translation": "Należy użyć natywnej wersji WireGuard na tym komputerze.",
"translatorComment": "Copied from source."
},
{
@@ -149,7 +149,7 @@
"msg": "{Years} lat"
},
"other": {
- "msg": "{Years} lata"
+ "msg": "{Years} lat"
}
}
}
@@ -217,7 +217,7 @@
"msg": "{Hours} godzin"
},
"other": {
- "msg": "{Hours} godziny"
+ "msg": "{Hours} godzin"
}
}
}
diff --git a/locales/si-LK/messages.gotext.json b/locales/si-LK/messages.gotext.json
new file mode 100644
index 00000000..81e82150
--- /dev/null
+++ b/locales/si-LK/messages.gotext.json
@@ -0,0 +1,715 @@
+{
+ "language": "si-LK",
+ "messages": [
+ {
+ "id": "Error",
+ "message": "Error",
+ "translation": "දෝෂයකි",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Usage: {Args0} [\n{String}]",
+ "message": "Usage: {Args0} [\n{String}]",
+ "translation": "භාවිතය: {Args0} [\n{String}]",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Args0",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "os.Args[0]"
+ },
+ {
+ "id": "String",
+ "string": "%[2]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 2,
+ "expr": "builder.String()"
+ }
+ ]
+ },
+ {
+ "id": "Now",
+ "message": "Now",
+ "translation": "දැන්",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "{Years} year(s)",
+ "message": "{Years} year(s)",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "Years",
+ "cases": {
+ "one": {
+ "msg": "අවුරුදු {Years}"
+ },
+ "other": {
+ "msg": "අවුරුදු {Years}"
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "Years",
+ "string": "%[1]d",
+ "type": "int64",
+ "underlyingType": "int64",
+ "argNum": 1,
+ "expr": "years"
+ }
+ ]
+ },
+ {
+ "id": "{Days} day(s)",
+ "message": "{Days} day(s)",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "Days",
+ "cases": {
+ "one": {
+ "msg": "දවස් {Days}"
+ },
+ "other": {
+ "msg": "දවස් {Days}"
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "Days",
+ "string": "%[1]d",
+ "type": "int64",
+ "underlyingType": "int64",
+ "argNum": 1,
+ "expr": "days"
+ }
+ ]
+ },
+ {
+ "id": "{Hours} hour(s)",
+ "message": "{Hours} hour(s)",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "Hours",
+ "cases": {
+ "one": {
+ "msg": "පැය {Hours}"
+ },
+ "other": {
+ "msg": "පැය {Hours}"
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "Hours",
+ "string": "%[1]d",
+ "type": "int64",
+ "underlyingType": "int64",
+ "argNum": 1,
+ "expr": "hours"
+ }
+ ]
+ },
+ {
+ "id": "{Minutes} minute(s)",
+ "message": "{Minutes} minute(s)",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "Minutes",
+ "cases": {
+ "one": {
+ "msg": "විනාඩි {Minutes}"
+ },
+ "other": {
+ "msg": "විනාඩි {Minutes}"
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "Minutes",
+ "string": "%[1]d",
+ "type": "int64",
+ "underlyingType": "int64",
+ "argNum": 1,
+ "expr": "minutes"
+ }
+ ]
+ },
+ {
+ "id": "{Seconds} second(s)",
+ "message": "{Seconds} second(s)",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "Seconds",
+ "cases": {
+ "one": {
+ "msg": "තත්පර {Seconds}"
+ },
+ "other": {
+ "msg": "තත්පර {Seconds}"
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "Seconds",
+ "string": "%[1]d",
+ "type": "int64",
+ "underlyingType": "int64",
+ "argNum": 1,
+ "expr": "seconds"
+ }
+ ]
+ },
+ {
+ "id": "{Timestamp} ago",
+ "message": "{Timestamp} ago",
+ "translation": "{Timestamp} ට පෙර",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Timestamp",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "timestamp"
+ }
+ ]
+ },
+ {
+ "id": "{Bytes} B",
+ "message": "{Bytes} B",
+ "translation": "බ. {Bytes}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Bytes",
+ "string": "%[1]d",
+ "type": "golang.zx2c4.com/wireguard/windows/conf.Bytes",
+ "underlyingType": "uint64",
+ "argNum": 1,
+ "expr": "b"
+ }
+ ]
+ },
+ {
+ "id": "{Float64b__1024} KiB",
+ "message": "{Float64b__1024} KiB",
+ "translation": "කි.බ. {Float64b__1024}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Float64b__1024",
+ "string": "%.2[1]f",
+ "type": "float64",
+ "underlyingType": "float64",
+ "argNum": 1,
+ "expr": "float64(b) / 1024"
+ }
+ ]
+ },
+ {
+ "id": "{Float64b__1024__1024} MiB",
+ "message": "{Float64b__1024__1024} MiB",
+ "translation": "මෙ.බ. {Float64b__1024__1024}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Float64b__1024__1024",
+ "string": "%.2[1]f",
+ "type": "float64",
+ "underlyingType": "float64",
+ "argNum": 1,
+ "expr": "float64(b) / (1024 * 1024)"
+ }
+ ]
+ },
+ {
+ "id": "{Float64b__1024__1024__1024} GiB",
+ "message": "{Float64b__1024__1024__1024} GiB",
+ "translation": "ගි.බ. {Float64b__1024__1024__1024}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Float64b__1024__1024__1024",
+ "string": "%.2[1]f",
+ "type": "float64",
+ "underlyingType": "float64",
+ "argNum": 1,
+ "expr": "float64(b) / (1024 * 1024 * 1024)"
+ }
+ ]
+ },
+ {
+ "id": "{Float64b__1024__1024__1024__1024} TiB",
+ "message": "{Float64b__1024__1024__1024__1024} TiB",
+ "translation": "ටෙ.බ. {Float64b__1024__1024__1024__1024}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Float64b__1024__1024__1024__1024",
+ "string": "%.2[1]f",
+ "type": "float64",
+ "underlyingType": "float64",
+ "argNum": 1,
+ "expr": "float64(b) / (1024 * 1024 * 1024) / 1024"
+ }
+ ]
+ },
+ {
+ "id": "{Why}: {Offender}",
+ "message": "{Why}: {Offender}",
+ "translation": "{Why}: {Offender}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Why",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "e.why"
+ },
+ {
+ "id": "Offender",
+ "string": "%[2]q",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 2,
+ "expr": "e.offender"
+ }
+ ]
+ },
+ {
+ "id": "Invalid IP address",
+ "message": "Invalid IP address",
+ "translation": "වලංගු නොවන අ.ජා.කෙ. ලිපිනයකි",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Invalid port",
+ "message": "Invalid port",
+ "translation": "වලංගු නොවන කෙවෙනියකි",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Invalid key: {Err}",
+ "message": "Invalid key: {Err}",
+ "translation": "වලංගු නොවන යතුර: {Err}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Err",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "err"
+ }
+ ]
+ },
+ {
+ "id": "Two commas in a row",
+ "message": "Two commas in a row",
+ "translation": "පේළියකට අල්පවිරාම දෙකක්",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Key must have a value",
+ "message": "Key must have a value",
+ "translation": "යතුරට අගයක් තිබිය යුතුය",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "An interface must have a private key",
+ "message": "An interface must have a private key",
+ "translation": "අතුරුමුහුතකට පුද්ගලික යතුරක් තිබිය යුතුය",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Protocol version must be 1",
+ "message": "Protocol version must be 1",
+ "translation": "කෙටුම්පතෙහි අනුවාදය 1 විය යුතුය",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "[EnumerationSeparator]",
+ "message": "[EnumerationSeparator]",
+ "translation": ", ",
+ "comment": "Text to insert between items when listing - most western languages will translate ‘[EnumerationSeparator]’ into ‘, ’ to produce lists like ‘apple, orange, strawberry’. Eastern languages might translate into ‘、’ to produce lists like ‘リンゴ、オレンジ、イチゴ’."
+ },
+ {
+ "id": "[UnitSeparator]",
+ "message": "[UnitSeparator]",
+ "translation": ", ",
+ "comment": "Text to insert when combining units of a measure - most languages will translate ‘[UnitSeparator]’ into ‘ ’ (space) to produce lists like ‘2 minuti 30 sekund’, or empty string ‘’ to produce ‘2分30秒’."
+ },
+ {
+ "id": "About WireGuard",
+ "message": "About WireGuard",
+ "translation": "වයර්ගාඩ් පිළිබඳව",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Close",
+ "message": "Close",
+ "translation": "වසන්න",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "♥ &Donate!",
+ "message": "♥ &Donate!",
+ "translation": "♥ &පරිත්‍යාග!",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Status:",
+ "message": "Status:",
+ "translation": "තත්වය:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Listen port:",
+ "message": "Listen port:",
+ "translation": "සවන්දීමේ කෙවෙනිය:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Addresses:",
+ "message": "Addresses:",
+ "translation": "ලිපින:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "DNS servers:",
+ "message": "DNS servers:",
+ "translation": "ව.නා.ප. සේවාදායක:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Allowed IPs:",
+ "message": "Allowed IPs:",
+ "translation": "ඉඩදුන් අ.ජා.කෙ.:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "enabled",
+ "message": "enabled",
+ "translation": "සබල කර ඇත",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "{String} received, {String_1} sent",
+ "message": "{String} received, {String_1} sent",
+ "translation": "{String} ලැබුණී, {String_1} යැවිණි",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "String",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "c.RxBytes.String()"
+ },
+ {
+ "id": "String_1",
+ "string": "%[2]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 2,
+ "expr": "c.TxBytes.String()"
+ }
+ ]
+ },
+ {
+ "id": "Interface: {Name}",
+ "message": "Interface: {Name}",
+ "translation": "අතුරුමුහුණත: {Name}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Name",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "config.Name"
+ }
+ ]
+ },
+ {
+ "id": "&Name:",
+ "message": "&Name:",
+ "translation": "&නම:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "(unknown)",
+ "message": "(unknown)",
+ "translation": "(නොදනී)",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Save",
+ "message": "&Save",
+ "translation": "&සුරකින්න",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Cancel",
+ "message": "Cancel",
+ "translation": "අවලංගු",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Configuration:",
+ "message": "&Configuration:",
+ "translation": "&වින්‍යාසය:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Invalid name",
+ "message": "Invalid name",
+ "translation": "වලංගු නොවන නමකි",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "A name is required.",
+ "message": "A name is required.",
+ "translation": "නමක් අවශ්‍යයි.",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Unable to create new configuration",
+ "message": "Unable to create new configuration",
+ "translation": "නව වින්‍යාසය සෑදීමට නොහැකියි",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Writing file failed",
+ "message": "Writing file failed",
+ "translation": "ගොනුව ලිවීමට අසමත්විය",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Activating",
+ "message": "Activating",
+ "translation": "ක්‍රියාත්මක වෙමින්",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Unknown state",
+ "message": "Unknown state",
+ "translation": "නොදන්නා තත්වයකි",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Copy",
+ "message": "&Copy",
+ "translation": "&පිටපත්",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Save to file…",
+ "message": "&Save to file…",
+ "translation": "&ගොනුවකට සුරකින්න…",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Time",
+ "message": "Time",
+ "translation": "වේලාව",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&About WireGuard…",
+ "message": "&About WireGuard…",
+ "translation": "&වයර්ගාඩ් පිළිබඳව…",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "{Title} (out of date)",
+ "message": "{Title} (out of date)",
+ "translation": "{Title} (කල් ඉකුත් වී ඇත)",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Title",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "mtw.Title()"
+ }
+ ]
+ },
+ {
+ "id": "Unable to wait for WireGuard window to appear: {Err}",
+ "message": "Unable to wait for WireGuard window to appear: {Err}",
+ "translation": "වයර්ගාඩ් කවුළුව පෙනෙන තෙක් රැඳීසිටිය නොහැකිය: {Err}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Err",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "err"
+ }
+ ]
+ },
+ {
+ "id": "Status: Unknown",
+ "message": "Status: Unknown",
+ "translation": "තත්වය: නොදනී",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "E&xit",
+ "message": "E&xit",
+ "translation": "පි&ටවන්න",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "WireGuard Activated",
+ "message": "WireGuard Activated",
+ "translation": "වයර්ගාඩ් ක්‍රියාත්මකයි",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Status: {StateText}",
+ "message": "Status: {StateText}",
+ "translation": "තත්වය: {StateText}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "StateText",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "stateText"
+ }
+ ]
+ },
+ {
+ "id": "Addresses: {EnumerationSeparator}",
+ "message": "Addresses: {EnumerationSeparator}",
+ "translation": "ලිපින: {EnumerationSeparator}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "EnumerationSeparator",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "strings.Join(addrs, l18n.EnumerationSeparator())"
+ }
+ ]
+ },
+ {
+ "id": "&Edit",
+ "message": "&Edit",
+ "translation": "&සංස්කරණය",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Unable to import configuration: {LastErr}",
+ "message": "Unable to import configuration: {LastErr}",
+ "translation": "වින්‍යාසය ආයාත කළ නොහැකිය: {LastErr}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "LastErr",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "lastErr"
+ }
+ ]
+ },
+ {
+ "id": "{Question} You cannot undo this action.",
+ "message": "{Question} You cannot undo this action.",
+ "translation": "{Question} මෙම ක්‍රියාමාර්ගය ආපසු හැරවිය නොහැකිය.",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Question",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "question"
+ }
+ ]
+ },
+ {
+ "id": "Error Exiting WireGuard",
+ "message": "Error Exiting WireGuard",
+ "translation": "වයර්ගාඩ් පිටවීමේදී දෝෂයකි",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Status: Waiting for user",
+ "message": "Status: Waiting for user",
+ "translation": "තත්වය: පරිශීලක සඳහා රැඳෙමින්",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Update Now",
+ "message": "Update Now",
+ "translation": "යාවත්කාල කරන්න",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Status: Waiting for updater service",
+ "message": "Status: Waiting for updater service",
+ "translation": "තත්වය: යාවත්කාල සේවාව සඳහා රැඳෙමින්",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Error: {Err}. Please try again.",
+ "message": "Error: {Err}. Please try again.",
+ "translation": "දෝෂය: {Err}. යළි උත්සාහ කරන්න.",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Err",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "err"
+ }
+ ]
+ },
+ {
+ "id": "Status: Complete!",
+ "message": "Status: Complete!",
+ "translation": "තත්වය: සම්පූර්ණයි!",
+ "translatorComment": "Copied from source."
+ }
+ ]
+} \ No newline at end of file
diff --git a/locales/sk/messages.gotext.json b/locales/sk/messages.gotext.json
index c8d05aa2..d5aeb165 100644
--- a/locales/sk/messages.gotext.json
+++ b/locales/sk/messages.gotext.json
@@ -60,6 +60,12 @@
]
},
{
+ "id": "You must use the native version of WireGuard on this computer.",
+ "message": "You must use the native version of WireGuard on this computer.",
+ "translation": "V tomto počítači musíte používať pôvodnú verziu programu WireGuard.",
+ "translatorComment": "Copied from source."
+ },
+ {
"id": "Unable to open current process token: {Err}",
"message": "Unable to open current process token: {Err}",
"translation": "Nepodarilo sa otvoriť token aktuálneho procesu: {Err}",
@@ -126,6 +132,40 @@
"translatorComment": "Copied from source."
},
{
+ "id": "{Years} year(s)",
+ "message": "{Years} year(s)",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "Years",
+ "cases": {
+ "one": {
+ "msg": "{Years} rok"
+ },
+ "few": {
+ "msg": "{Years} roky"
+ },
+ "many": {
+ "msg": "{Years} rokov"
+ },
+ "other": {
+ "msg": "{Years} rokov"
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "Years",
+ "string": "%[1]d",
+ "type": "int64",
+ "underlyingType": "int64",
+ "argNum": 1,
+ "expr": "years"
+ }
+ ]
+ },
+ {
"id": "{Days} day(s)",
"message": "{Days} day(s)",
"translation": {
@@ -576,6 +616,62 @@
"translatorComment": "Copied from source."
},
{
+ "id": "App version: {Number}\nGo backend version: {WireGuardGoVersion}\nGo version: {Version_go}-{GOARCH}\nOperating system: {OsName}\nArchitecture: {NativeArch}",
+ "message": "App version: {Number}\nGo backend version: {WireGuardGoVersion}\nGo version: {Version_go}-{GOARCH}\nOperating system: {OsName}\nArchitecture: {NativeArch}",
+ "translation": "Verzia aplikácie.: {Number}\nVerzia Go backendu: {WireGuardGoVersion}\nVerzia Go: {Version_go}-{GOARCH}\nOperačný systém: {OsName}\nArchitektúra: {NativeArch}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Number",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "version.Number"
+ },
+ {
+ "id": "WireGuardGoVersion",
+ "string": "%[2]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 2,
+ "expr": "device.WireGuardGoVersion"
+ },
+ {
+ "id": "Version_go",
+ "string": "%[3]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 3,
+ "expr": "strings.TrimPrefix(runtime.Version(), \"go\")"
+ },
+ {
+ "id": "GOARCH",
+ "string": "%[4]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 4,
+ "expr": "runtime.GOARCH"
+ },
+ {
+ "id": "OsName",
+ "string": "%[5]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 5,
+ "expr": "version.OsName()"
+ },
+ {
+ "id": "NativeArch",
+ "string": "%[6]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 6,
+ "expr": "version.NativeArch()"
+ }
+ ]
+ },
+ {
"id": "Close",
"message": "Close",
"translation": "Zatvoriť",
@@ -636,6 +732,12 @@
"translatorComment": "Copied from source."
},
{
+ "id": "Scripts:",
+ "message": "Scripts:",
+ "translation": "Skripty:",
+ "translatorComment": "Copied from source."
+ },
+ {
"id": "Preshared key:",
"message": "Preshared key:",
"translation": "Vopred zdieľaný kľúč:",
@@ -672,6 +774,36 @@
"translatorComment": "Copied from source."
},
{
+ "id": "pre-up",
+ "message": "pre-up",
+ "translation": "pred-zapnutím",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "post-up",
+ "message": "post-up",
+ "translation": "po-zapnutí",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "pre-down",
+ "message": "pre-down",
+ "translation": "pred-vypnutím",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "post-down",
+ "message": "post-down",
+ "translation": "po-vypnutí",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "disabled, per policy",
+ "message": "disabled, per policy",
+ "translation": "zakázané, na základe pravidla",
+ "translatorComment": "Copied from source."
+ },
+ {
"id": "enabled",
"message": "enabled",
"translation": "povolené",
@@ -778,6 +910,12 @@
"translatorComment": "Copied from source."
},
{
+ "id": "When a configuration has exactly one peer, and that peer has an allowed IPs containing at least one of 0.0.0.0/0 or ::/0, then the tunnel service engages a firewall ruleset to block all traffic that is neither to nor from the tunnel interface or is to the wrong DNS server, with special exceptions for DHCP and NDP.",
+ "message": "When a configuration has exactly one peer, and that peer has an allowed IPs containing at least one of 0.0.0.0/0 or ::/0, then the tunnel service engages a firewall ruleset to block all traffic that is neither to nor from the tunnel interface or is to the wrong DNS server, with special exceptions for DHCP and NDP.",
+ "translation": "Ak konfigurácia obsahuje práve jedného peera a tento má v povolených IP 0.0.0.0/0 alebo ::/0, tak tak tento tunel aktivuje pravidlo firewallu blokujúce komunikáciu, ktorá nepochádza z alebo nesmeruje na rozhranie tohto tunela alebo smeruje na nesprávny DNS server, špeciálnou výnimkou je DHCP a NDP komunikácia.",
+ "translatorComment": "Copied from source."
+ },
+ {
"id": "&Save",
"message": "&Save",
"translation": "&Uložiť",
@@ -910,12 +1048,138 @@
"translatorComment": "Copied from source."
},
{
+ "id": "Log",
+ "message": "Log",
+ "translation": "Denník udalostí",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Copy",
+ "message": "&Copy",
+ "translation": "&Kopírovať",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Select &all",
+ "message": "Select &all",
+ "translation": "Vybr&ať všetko",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Save to file…",
+ "message": "&Save to file…",
+ "translation": "Uložiť do &súboru…",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Time",
+ "message": "Time",
+ "translation": "Čas",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Log message",
+ "message": "Log message",
+ "translation": "Správa v denníku udalostí",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Text Files (*.txt)|*.txt|All Files (*.*)|*.*",
+ "message": "Text Files (*.txt)|*.txt|All Files (*.*)|*.*",
+ "translation": "Textové súbory (*.txt)|*.txt|Všetky súbory (*.*)|*.*",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Export log to file",
+ "message": "Export log to file",
+ "translation": "Exportovať denník udalostí do súboru",
+ "translatorComment": "Copied from source."
+ },
+ {
"id": "&About WireGuard…",
"message": "&About WireGuard…",
"translation": "&O WireGuard…",
"translatorComment": "Copied from source."
},
{
+ "id": "Tunnel Error",
+ "message": "Tunnel Error",
+ "translation": "Chyba tunela",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "{ErrMsg}\n\nPlease consult the log for more information.",
+ "message": "{ErrMsg}\n\nPlease consult the log for more information.",
+ "translation": "{ErrMsg}\n\nViac informácií nájdete v denníku udalostí.",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "ErrMsg",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "errMsg"
+ }
+ ]
+ },
+ {
+ "id": "{Title} (out of date)",
+ "message": "{Title} (out of date)",
+ "translation": "{Title} (neaktuány)",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Title",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "mtw.Title()"
+ }
+ ]
+ },
+ {
+ "id": "WireGuard Detection Error",
+ "message": "WireGuard Detection Error",
+ "translation": "Chyba detekcie WireGuard",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Unable to wait for WireGuard window to appear: {Err}",
+ "message": "Unable to wait for WireGuard window to appear: {Err}",
+ "translation": "Nie je možné čakať na zobrazenie WireGuard okna: {Err}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Err",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "err"
+ }
+ ]
+ },
+ {
+ "id": "WireGuard: Deactivated",
+ "message": "WireGuard: Deactivated",
+ "translation": "WireGuard: deaktivovaný",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Status: Unknown",
+ "message": "Status: Unknown",
+ "translation": "Stav: Nezámy",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Addresses: None",
+ "message": "Addresses: None",
+ "translation": "Adresa: žiadna",
+ "translatorComment": "Copied from source."
+ },
+ {
"id": "&Manage tunnels…",
"message": "&Manage tunnels…",
"translation": "&Spravovať tunely…",
@@ -934,6 +1198,62 @@
"translatorComment": "Copied from source."
},
{
+ "id": "&Tunnels",
+ "message": "&Tunnels",
+ "translation": "&Tunely",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "WireGuard Activated",
+ "message": "WireGuard Activated",
+ "translation": "WireGuard je aktivovaný",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "The {Name} tunnel has been activated.",
+ "message": "The {Name} tunnel has been activated.",
+ "translation": "Tunel {Name} bol aktivovaný.",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Name",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "tunnel.Name"
+ }
+ ]
+ },
+ {
+ "id": "WireGuard Deactivated",
+ "message": "WireGuard Deactivated",
+ "translation": "WireGuard je deaktivovaný",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "The {Name} tunnel has been deactivated.",
+ "message": "The {Name} tunnel has been deactivated.",
+ "translation": "Tunel {Name} bol deaktivovaný.",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Name",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "tunnel.Name"
+ }
+ ]
+ },
+ {
+ "id": "WireGuard Tunnel Error",
+ "message": "WireGuard Tunnel Error",
+ "translation": "Chyba WireGuard tunelu",
+ "translatorComment": "Copied from source."
+ },
+ {
"id": "WireGuard: {TextForStateglobalState_true}",
"message": "WireGuard: {TextForStateglobalState_true}",
"translation": "WireGuard: {TextForStateglobalState_true}",
@@ -948,6 +1268,560 @@
"expr": "textForState(globalState, true)"
}
]
+ },
+ {
+ "id": "Status: {StateText}",
+ "message": "Status: {StateText}",
+ "translation": "Stav: {StateText}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "StateText",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "stateText"
+ }
+ ]
+ },
+ {
+ "id": "Addresses: {EnumerationSeparator}",
+ "message": "Addresses: {EnumerationSeparator}",
+ "translation": "Adresa: {EnumerationSeparator}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "EnumerationSeparator",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "strings.Join(addrs, l18n.EnumerationSeparator())"
+ }
+ ]
+ },
+ {
+ "id": "An Update is Available!",
+ "message": "An Update is Available!",
+ "translation": "Je dostupná aktualizácia!",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "WireGuard Update Available",
+ "message": "WireGuard Update Available",
+ "translation": "Dostupná aktualizácia pre WireGuard",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "An update to WireGuard is now available. You are advised to update as soon as possible.",
+ "message": "An update to WireGuard is now available. You are advised to update as soon as possible.",
+ "translation": "Je k dispozícii aktualizácia programu WireGuard. Je odporúčané čo najskôr vykonať aktualizáciu.",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Tunnels",
+ "message": "Tunnels",
+ "translation": "Tunely",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Edit",
+ "message": "&Edit",
+ "translation": "&Upraviť",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Add &empty tunnel…",
+ "message": "Add &empty tunnel…",
+ "translation": "Pridať &prázdny tunel…",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Add Tunnel",
+ "message": "Add Tunnel",
+ "translation": "Pridať tunel",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Remove selected tunnel(s)",
+ "message": "Remove selected tunnel(s)",
+ "translation": "Odstrániť označený(é) tunel(y)",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Export all tunnels to zip",
+ "message": "Export all tunnels to zip",
+ "translation": "Export všetkých tunelov do zip súboru",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Toggle",
+ "message": "&Toggle",
+ "translation": "P&repnúť",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Export all tunnels to &zip…",
+ "message": "Export all tunnels to &zip…",
+ "translation": "Export všetkých tunelov do &zip súboru…",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Edit &selected tunnel…",
+ "message": "Edit &selected tunnel…",
+ "translation": "Upraviť &označený tunel…",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Remove selected tunnel(s)",
+ "message": "&Remove selected tunnel(s)",
+ "translation": "&Odstrániť označené tunely",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "no configuration files were found",
+ "message": "no configuration files were found",
+ "translation": "neboli nájdené žiadne konfiguračné súbory",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Could not import selected configuration: {LastErr}",
+ "message": "Could not import selected configuration: {LastErr}",
+ "translation": "Nepodarilo sa naimportovať vybrané konfigurácie: {LastErr}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "LastErr",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "lastErr"
+ }
+ ]
+ },
+ {
+ "id": "Could not enumerate existing tunnels: {LastErr}",
+ "message": "Could not enumerate existing tunnels: {LastErr}",
+ "translation": "Nepodarilo sa načítať existujúce tunely: {LastErr}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "LastErr",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "lastErr"
+ }
+ ]
+ },
+ {
+ "id": "Another tunnel already exists with the name ‘{Name}’",
+ "message": "Another tunnel already exists with the name ‘{Name}’",
+ "translation": "Už existuje tunel s názvom '{Name}'",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Name",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "unparsedConfig.Name"
+ }
+ ]
+ },
+ {
+ "id": "Unable to import configuration: {LastErr}",
+ "message": "Unable to import configuration: {LastErr}",
+ "translation": "Nepodarilo sa naimportovať konfiguráciu: {LastErr}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "LastErr",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "lastErr"
+ }
+ ]
+ },
+ {
+ "id": "Imported tunnels",
+ "message": "Imported tunnels",
+ "translation": "Naimportované tunely",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Imported {M} tunnels",
+ "message": "Imported {M} tunnels",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "M",
+ "cases": {
+ "one": {
+ "msg": "Importovaný {M} tunel"
+ },
+ "few": {
+ "msg": "Naimportované {M} tunely"
+ },
+ "many": {
+ "msg": "Naimportovaných {M} tunelov"
+ },
+ "other": {
+ "msg": "Naimportovaných {M} tunelov"
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "M",
+ "string": "%[1]d",
+ "type": "int",
+ "underlyingType": "int",
+ "argNum": 1,
+ "expr": "m"
+ }
+ ]
+ },
+ {
+ "id": "Imported {M} of {N} tunnels",
+ "message": "Imported {M} of {N} tunnels",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "N",
+ "cases": {
+ "one": {
+ "msg": "Naimportovaný {M} z {N} tunelov"
+ },
+ "few": {
+ "msg": "Naimportované {M} z {N} tunelov"
+ },
+ "many": {
+ "msg": "Naimportovaných {M} z {N} tunelov"
+ },
+ "other": {
+ "msg": "Naimportovaných {M} z {N} tunelov"
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "M",
+ "string": "%[1]d",
+ "type": "int",
+ "underlyingType": "int",
+ "argNum": 1,
+ "expr": "m"
+ },
+ {
+ "id": "N",
+ "string": "%[2]d",
+ "type": "int",
+ "underlyingType": "int",
+ "argNum": 2,
+ "expr": "n"
+ }
+ ]
+ },
+ {
+ "id": "Unable to create tunnel",
+ "message": "Unable to create tunnel",
+ "translation": "Tunel sa nedá vytvoriť",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Delete {TunnelCount} tunnels",
+ "message": "Delete {TunnelCount} tunnels",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "TunnelCount",
+ "cases": {
+ "one": {
+ "msg": "Odstránený {TunnelCount} tunel"
+ },
+ "few": {
+ "msg": "Odstránene {TunnelCount} tunely"
+ },
+ "many": {
+ "msg": "Odstránených {TunnelCount} tunelov"
+ },
+ "other": {
+ "msg": "Odstránených {TunnelCount} tunelov"
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "TunnelCount",
+ "string": "%[1]d",
+ "type": "int",
+ "underlyingType": "int",
+ "argNum": 1,
+ "expr": "tunnelCount"
+ }
+ ]
+ },
+ {
+ "id": "Are you sure you would like to delete {TunnelCount} tunnels?",
+ "message": "Are you sure you would like to delete {TunnelCount} tunnels?",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "TunnelCount",
+ "cases": {
+ "one": {
+ "msg": "Ste si istý, že si želáte odstrániť {TunnelCount} tunel?"
+ },
+ "few": {
+ "msg": "Ste si istý, že si želáte odstrániť {TunnelCount} tunely?"
+ },
+ "many": {
+ "msg": "Ste si istý, že si želáte odstrániť {TunnelCount} tunelov?"
+ },
+ "other": {
+ "msg": "Ste si istý, že si želáte odstrániť {TunnelCount} tunelov?"
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "TunnelCount",
+ "string": "%[1]d",
+ "type": "int",
+ "underlyingType": "int",
+ "argNum": 1,
+ "expr": "tunnelCount"
+ }
+ ]
+ },
+ {
+ "id": "Delete tunnel ‘{TunnelName}’",
+ "message": "Delete tunnel ‘{TunnelName}’",
+ "translation": "Odstránenie tunela ‘{TunnelName}’",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "TunnelName",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "tunnelName"
+ }
+ ]
+ },
+ {
+ "id": "Are you sure you would like to delete tunnel ‘{TunnelName}’?",
+ "message": "Are you sure you would like to delete tunnel ‘{TunnelName}’?",
+ "translation": "Ste si istý, že si želáte odstrániť tunel ‘{TunnelName}’?",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "TunnelName",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "tunnelName"
+ }
+ ]
+ },
+ {
+ "id": "{Question} You cannot undo this action.",
+ "message": "{Question} You cannot undo this action.",
+ "translation": "{Question} Túto akciu nemôže vrátiť späť.",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Question",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "question"
+ }
+ ]
+ },
+ {
+ "id": "Unable to delete tunnel",
+ "message": "Unable to delete tunnel",
+ "translation": "Tunel sa nedá odstrániť",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "A tunnel was unable to be removed: {Error}",
+ "message": "A tunnel was unable to be removed: {Error}",
+ "translation": "Nebolo možné odstrániť tunel: {Error}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Error",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "errors[0].Error()"
+ }
+ ]
+ },
+ {
+ "id": "Unable to delete tunnels",
+ "message": "Unable to delete tunnels",
+ "translation": "Tunely sa nedajú odstrániť",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "{Lenerrors} tunnels were unable to be removed.",
+ "message": "{Lenerrors} tunnels were unable to be removed.",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "Lenerrors",
+ "cases": {
+ "one": {
+ "msg": "{Lenerrors} tunel nebolo možné odstrániť."
+ },
+ "few": {
+ "msg": "{Lenerrors} tunely nebolo možné odstrániť."
+ },
+ "many": {
+ "msg": "{Lenerrors} tunelov nebolo možné odstrániť."
+ },
+ "other": {
+ "msg": "{Lenerrors} tunelov nebolo možné odstrániť."
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "Lenerrors",
+ "string": "%[1]d",
+ "type": "int",
+ "underlyingType": "int",
+ "argNum": 1,
+ "expr": "len(errors)"
+ }
+ ]
+ },
+ {
+ "id": "Configuration Files (*.zip, *.conf)|*.zip;*.conf|All Files (*.*)|*.*",
+ "message": "Configuration Files (*.zip, *.conf)|*.zip;*.conf|All Files (*.*)|*.*",
+ "translation": "Konfirugačné súbory (*.zip, *.conf)|*.zip;*.conf|Všetky súbory (*.*)|*.*",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Import tunnel(s) from file",
+ "message": "Import tunnel(s) from file",
+ "translation": "Importovať tunel(y) zo súboru",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Configuration ZIP Files (*.zip)|*.zip",
+ "message": "Configuration ZIP Files (*.zip)|*.zip",
+ "translation": "Konfiguračné ZIP súbry (*.zip)|*.zip",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Export tunnels to zip",
+ "message": "Export tunnels to zip",
+ "translation": "Export tunelov do zip súboru",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "{Title} (unsigned build, no updates)",
+ "message": "{Title} (unsigned build, no updates)",
+ "translation": "{Title} (nepodpísaná verzia, žiadne aktualizácie)",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Title",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "mtw.Title()"
+ }
+ ]
+ },
+ {
+ "id": "Error Exiting WireGuard",
+ "message": "Error Exiting WireGuard",
+ "translation": "Chyba ukončenia WireGuard",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Unable to exit service due to: {Err}. You may want to stop WireGuard from the service manager.",
+ "message": "Unable to exit service due to: {Err}. You may want to stop WireGuard from the service manager.",
+ "translation": "Nie je možné ukončiť služby z dôvodu: {Err}. Skúste zastaviť WireGuard v správcovi služieb.",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Err",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "err"
+ }
+ ]
+ },
+ {
+ "id": "An update to WireGuard is available. It is highly advisable to update without delay.",
+ "message": "An update to WireGuard is available. It is highly advisable to update without delay.",
+ "translation": "Je k dispozícii nová verzia programu WireGuard. Odporúčame bezodkladne vykonať aktualizáciu.",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Status: Waiting for user",
+ "message": "Status: Waiting for user",
+ "translation": "Stav: Čaká sa na užívateľa",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Update Now",
+ "message": "Update Now",
+ "translation": "Aktualizovať teraz",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Status: Waiting for updater service",
+ "message": "Status: Waiting for updater service",
+ "translation": "Stav: Čaká sa na aktualizačnú službu",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Error: {Err}. Please try again.",
+ "message": "Error: {Err}. Please try again.",
+ "translation": "Chyba: {Err}. Skúste to znova.",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Err",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "err"
+ }
+ ]
+ },
+ {
+ "id": "Status: Complete!",
+ "message": "Status: Complete!",
+ "translation": "Stav: Dokončené!",
+ "translatorComment": "Copied from source."
}
]
} \ No newline at end of file
diff --git a/locales/tr/messages.gotext.json b/locales/tr/messages.gotext.json
new file mode 100644
index 00000000..d51b67e8
--- /dev/null
+++ b/locales/tr/messages.gotext.json
@@ -0,0 +1,1847 @@
+{
+ "language": "tr",
+ "messages": [
+ {
+ "id": "Error",
+ "message": "Error",
+ "translation": "Hata",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "(no argument): elevate and install manager service",
+ "message": "(no argument): elevate and install manager service",
+ "translation": "(argüman verilmediyse): gerekli izinleri al ve yönetim hizmetini kur",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Usage: {Args0} [\n{String}]",
+ "message": "Usage: {Args0} [\n{String}]",
+ "translation": "Kullanım: {Args0} [\n{String}]",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Args0",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "os.Args[0]"
+ },
+ {
+ "id": "String",
+ "string": "%[2]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 2,
+ "expr": "builder.String()"
+ }
+ ]
+ },
+ {
+ "id": "Command Line Options",
+ "message": "Command Line Options",
+ "translation": "Komut Satırı Seçenekleri",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Unable to determine whether the process is running under WOW64: {Err}",
+ "message": "Unable to determine whether the process is running under WOW64: {Err}",
+ "translation": "İşlemin WOW64 altında çalıştığından emin olunamadı: {Err}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Err",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "err"
+ }
+ ]
+ },
+ {
+ "id": "You must use the native version of WireGuard on this computer.",
+ "message": "You must use the native version of WireGuard on this computer.",
+ "translation": "Bu bilgisayarda WireGuard'ın yerel sürümünü kullanmanız gerek.",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Unable to open current process token: {Err}",
+ "message": "Unable to open current process token: {Err}",
+ "translation": "Şu anki işlem jetonu açılamadı: {Err}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Err",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "err"
+ }
+ ]
+ },
+ {
+ "id": "WireGuard may only be used by users who are a member of the Builtin {AdminGroupName} group.",
+ "message": "WireGuard may only be used by users who are a member of the Builtin {AdminGroupName} group.",
+ "translation": "WireGuard sadece sisteme yerleşik {AdminGroupName} grubunun üyeleri tarafından kullanılabilir.",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "AdminGroupName",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "elevate.AdminGroupName()"
+ }
+ ]
+ },
+ {
+ "id": "WireGuard is running, but the UI is only accessible from desktops of the Builtin {AdminGroupName} group.",
+ "message": "WireGuard is running, but the UI is only accessible from desktops of the Builtin {AdminGroupName} group.",
+ "translation": "WireGuard çalışıyor, fakat kullanıcı arayüzü sadece sisteme yerleşik {AdminGroupName} grubunun üyesi olan kullanıcılar tarafından masaüstünde erişilebilir.",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "AdminGroupName",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "elevate.AdminGroupName()"
+ }
+ ]
+ },
+ {
+ "id": "WireGuard system tray icon did not appear after 30 seconds.",
+ "message": "WireGuard system tray icon did not appear after 30 seconds.",
+ "translation": "WireGuard sistem tepsisi ikonu 30 saniye sonunda belirmedi.",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Now",
+ "message": "Now",
+ "translation": "Şimdi",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "System clock wound backward!",
+ "message": "System clock wound backward!",
+ "translation": "Sistem saati geriye sarılmış!",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "{Years} year(s)",
+ "message": "{Years} year(s)",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "Years",
+ "cases": {
+ "one": {
+ "msg": "{Years} yıl"
+ },
+ "other": {
+ "msg": "{Years} yıl"
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "Years",
+ "string": "%[1]d",
+ "type": "int64",
+ "underlyingType": "int64",
+ "argNum": 1,
+ "expr": "years"
+ }
+ ]
+ },
+ {
+ "id": "{Days} day(s)",
+ "message": "{Days} day(s)",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "Days",
+ "cases": {
+ "one": {
+ "msg": "{Days} gün"
+ },
+ "other": {
+ "msg": "{Days} gün"
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "Days",
+ "string": "%[1]d",
+ "type": "int64",
+ "underlyingType": "int64",
+ "argNum": 1,
+ "expr": "days"
+ }
+ ]
+ },
+ {
+ "id": "{Hours} hour(s)",
+ "message": "{Hours} hour(s)",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "Hours",
+ "cases": {
+ "one": {
+ "msg": "{Hours} saat"
+ },
+ "other": {
+ "msg": "{Hours} saat"
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "Hours",
+ "string": "%[1]d",
+ "type": "int64",
+ "underlyingType": "int64",
+ "argNum": 1,
+ "expr": "hours"
+ }
+ ]
+ },
+ {
+ "id": "{Minutes} minute(s)",
+ "message": "{Minutes} minute(s)",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "Minutes",
+ "cases": {
+ "one": {
+ "msg": "{Minutes} dakika"
+ },
+ "other": {
+ "msg": "{Minutes} dakika"
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "Minutes",
+ "string": "%[1]d",
+ "type": "int64",
+ "underlyingType": "int64",
+ "argNum": 1,
+ "expr": "minutes"
+ }
+ ]
+ },
+ {
+ "id": "{Seconds} second(s)",
+ "message": "{Seconds} second(s)",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "Seconds",
+ "cases": {
+ "one": {
+ "msg": "{Seconds} saniye"
+ },
+ "other": {
+ "msg": "{Seconds} saniye"
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "Seconds",
+ "string": "%[1]d",
+ "type": "int64",
+ "underlyingType": "int64",
+ "argNum": 1,
+ "expr": "seconds"
+ }
+ ]
+ },
+ {
+ "id": "{Timestamp} ago",
+ "message": "{Timestamp} ago",
+ "translation": "{Timestamp} önce",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Timestamp",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "timestamp"
+ }
+ ]
+ },
+ {
+ "id": "{Bytes} B",
+ "message": "{Bytes} B",
+ "translation": "{Bytes} B",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Bytes",
+ "string": "%[1]d",
+ "type": "golang.zx2c4.com/wireguard/windows/conf.Bytes",
+ "underlyingType": "uint64",
+ "argNum": 1,
+ "expr": "b"
+ }
+ ]
+ },
+ {
+ "id": "{Float64b__1024} KiB",
+ "message": "{Float64b__1024} KiB",
+ "translation": "{Float64b__1024} KiB",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Float64b__1024",
+ "string": "%.2[1]f",
+ "type": "float64",
+ "underlyingType": "float64",
+ "argNum": 1,
+ "expr": "float64(b) / 1024"
+ }
+ ]
+ },
+ {
+ "id": "{Float64b__1024__1024} MiB",
+ "message": "{Float64b__1024__1024} MiB",
+ "translation": "{Float64b__1024__1024} MiB",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Float64b__1024__1024",
+ "string": "%.2[1]f",
+ "type": "float64",
+ "underlyingType": "float64",
+ "argNum": 1,
+ "expr": "float64(b) / (1024 * 1024)"
+ }
+ ]
+ },
+ {
+ "id": "{Float64b__1024__1024__1024} GiB",
+ "message": "{Float64b__1024__1024__1024} GiB",
+ "translation": "{Float64b__1024__1024__1024} GiB",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Float64b__1024__1024__1024",
+ "string": "%.2[1]f",
+ "type": "float64",
+ "underlyingType": "float64",
+ "argNum": 1,
+ "expr": "float64(b) / (1024 * 1024 * 1024)"
+ }
+ ]
+ },
+ {
+ "id": "{Float64b__1024__1024__1024__1024} TiB",
+ "message": "{Float64b__1024__1024__1024__1024} TiB",
+ "translation": "{Float64b__1024__1024__1024__1024} TiB",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Float64b__1024__1024__1024__1024",
+ "string": "%.2[1]f",
+ "type": "float64",
+ "underlyingType": "float64",
+ "argNum": 1,
+ "expr": "float64(b) / (1024 * 1024 * 1024) / 1024"
+ }
+ ]
+ },
+ {
+ "id": "{Why}: {Offender}",
+ "message": "{Why}: {Offender}",
+ "translation": "{Why}: {Offender}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Why",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "e.why"
+ },
+ {
+ "id": "Offender",
+ "string": "%[2]q",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 2,
+ "expr": "e.offender"
+ }
+ ]
+ },
+ {
+ "id": "Invalid IP address",
+ "message": "Invalid IP address",
+ "translation": "Geçersiz IP adresi",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Invalid network prefix length",
+ "message": "Invalid network prefix length",
+ "translation": "Ağ öneki uzunluğu geçersiz",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Missing port from endpoint",
+ "message": "Missing port from endpoint",
+ "translation": "Uç nokta port ayarı eksik",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Invalid endpoint host",
+ "message": "Invalid endpoint host",
+ "translation": "Geçersiz uç nokta",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Brackets must contain an IPv6 address",
+ "message": "Brackets must contain an IPv6 address",
+ "translation": "Parantezler bir IPv6 adresi içermelidir",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Invalid MTU",
+ "message": "Invalid MTU",
+ "translation": "Geçersiz MTU",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Invalid port",
+ "message": "Invalid port",
+ "translation": "Geçersiz port",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Invalid persistent keepalive",
+ "message": "Invalid persistent keepalive",
+ "translation": "Geçersiz kalıcı açık bırakma",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Invalid key: {Err}",
+ "message": "Invalid key: {Err}",
+ "translation": "Geçersiz anahtar: {Err}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Err",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "err"
+ }
+ ]
+ },
+ {
+ "id": "Keys must decode to exactly 32 bytes",
+ "message": "Keys must decode to exactly 32 bytes",
+ "translation": "Anahtarlar çözüldüğünde tam 32 byte olmalı",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Number must be a number between 0 and 2^64-1: {Err}",
+ "message": "Number must be a number between 0 and 2^64-1: {Err}",
+ "translation": "Sayı 0 ve 2^64-1 arasında bir sayı olmalı: {Err}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Err",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "err"
+ }
+ ]
+ },
+ {
+ "id": "Two commas in a row",
+ "message": "Two commas in a row",
+ "translation": "Yan yana iki virgül",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Tunnel name is not valid",
+ "message": "Tunnel name is not valid",
+ "translation": "Tünel adı geçerli değil",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Line must occur in a section",
+ "message": "Line must occur in a section",
+ "translation": "Satır bir bölümde olmalı",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Config key is missing an equals separator",
+ "message": "Config key is missing an equals separator",
+ "translation": "Yapılandırma anahtarında eşittir operatörü eksik",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Key must have a value",
+ "message": "Key must have a value",
+ "translation": "Anahtar bir değere sahip olmalı",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Invalid key for [Interface] section",
+ "message": "Invalid key for [Interface] section",
+ "translation": "[Interface] bölümü için geçersiz anahtar",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Invalid key for [Peer] section",
+ "message": "Invalid key for [Peer] section",
+ "translation": "[Peer] bölümü için geçersiz anahtar",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "An interface must have a private key",
+ "message": "An interface must have a private key",
+ "translation": "Bir arabirim gizli anahtara sahip olmalıdır",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "[none specified]",
+ "message": "[none specified]",
+ "translation": "[hiçbir şey belirtilmemiş}",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "All peers must have public keys",
+ "message": "All peers must have public keys",
+ "translation": "Tüm eşler açık anahtarlara sahip olmalı",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Error in getting configuration",
+ "message": "Error in getting configuration",
+ "translation": "Yapılandırma bilgisi alınırken hata oluştu",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Invalid key for interface section",
+ "message": "Invalid key for interface section",
+ "translation": "Arabirim bölümünde geçersiz anahtar",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Protocol version must be 1",
+ "message": "Protocol version must be 1",
+ "translation": "Protokol sürümü 1 olmak zorunda",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Invalid key for peer section",
+ "message": "Invalid key for peer section",
+ "translation": "Eş bölümünde geçersiz anahtar",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "[EnumerationSeparator]",
+ "message": "[EnumerationSeparator]",
+ "translation": ", ",
+ "comment": "Text to insert between items when listing - most western languages will translate ‘[EnumerationSeparator]’ into ‘, ’ to produce lists like ‘apple, orange, strawberry’. Eastern languages might translate into ‘、’ to produce lists like ‘リンゴ、オレンジ、イチゴ’."
+ },
+ {
+ "id": "[UnitSeparator]",
+ "message": "[UnitSeparator]",
+ "translation": ", ",
+ "comment": "Text to insert when combining units of a measure - most languages will translate ‘[UnitSeparator]’ into ‘ ’ (space) to produce lists like ‘2 minuti 30 sekund’, or empty string ‘’ to produce ‘2分30秒’."
+ },
+ {
+ "id": "About WireGuard",
+ "message": "About WireGuard",
+ "translation": "WireGuard Hakkında",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "WireGuard logo image",
+ "message": "WireGuard logo image",
+ "translation": "WireGuard logo resmi",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "App version: {Number}\nGo backend version: {WireGuardGoVersion}\nGo version: {Version_go}-{GOARCH}\nOperating system: {OsName}\nArchitecture: {NativeArch}",
+ "message": "App version: {Number}\nGo backend version: {WireGuardGoVersion}\nGo version: {Version_go}-{GOARCH}\nOperating system: {OsName}\nArchitecture: {NativeArch}",
+ "translation": "Uygulama sürümü: {Number}\nGo arkauç sürümü: {WireGuardGoVersion}\nGo sürümü: {Version_go}-{GOARCH}\nİşletim sistemi: {OsName}\nMimari: {NativeArch}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Number",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "version.Number"
+ },
+ {
+ "id": "WireGuardGoVersion",
+ "string": "%[2]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 2,
+ "expr": "device.WireGuardGoVersion"
+ },
+ {
+ "id": "Version_go",
+ "string": "%[3]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 3,
+ "expr": "strings.TrimPrefix(runtime.Version(), \"go\")"
+ },
+ {
+ "id": "GOARCH",
+ "string": "%[4]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 4,
+ "expr": "runtime.GOARCH"
+ },
+ {
+ "id": "OsName",
+ "string": "%[5]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 5,
+ "expr": "version.OsName()"
+ },
+ {
+ "id": "NativeArch",
+ "string": "%[6]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 6,
+ "expr": "version.NativeArch()"
+ }
+ ]
+ },
+ {
+ "id": "Close",
+ "message": "Close",
+ "translation": "Kapat",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "♥ &Donate!",
+ "message": "♥ &Donate!",
+ "translation": "♥ &Bağış yap!",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Status:",
+ "message": "Status:",
+ "translation": "Durum:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Deactivate",
+ "message": "&Deactivate",
+ "translation": "&Devre dışı bırak",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Activate",
+ "message": "&Activate",
+ "translation": "&Etkinleştir",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Public key:",
+ "message": "Public key:",
+ "translation": "Açık anahtar:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Listen port:",
+ "message": "Listen port:",
+ "translation": "Dinlenen port:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "MTU:",
+ "message": "MTU:",
+ "translation": "MTU:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Addresses:",
+ "message": "Addresses:",
+ "translation": "Adresler:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "DNS servers:",
+ "message": "DNS servers:",
+ "translation": "DNS sunucuları:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Scripts:",
+ "message": "Scripts:",
+ "translation": "Komut dosyaları:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Preshared key:",
+ "message": "Preshared key:",
+ "translation": "Önceden paylaşılmış anahtar:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Allowed IPs:",
+ "message": "Allowed IPs:",
+ "translation": "İzin verilen IP'ler:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Endpoint:",
+ "message": "Endpoint:",
+ "translation": "Uç nokta:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Persistent keepalive:",
+ "message": "Persistent keepalive:",
+ "translation": "Kalıcı açık tutma:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Latest handshake:",
+ "message": "Latest handshake:",
+ "translation": "En son el sıkışma:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Transfer:",
+ "message": "Transfer:",
+ "translation": "Aktarım:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "pre-up",
+ "message": "pre-up",
+ "translation": "bağlantı-öncesi",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "post-up",
+ "message": "post-up",
+ "translation": "bağlantı-sonrası",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "pre-down",
+ "message": "pre-down",
+ "translation": "bağlantı-kesme-öncesi",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "post-down",
+ "message": "post-down",
+ "translation": "bağlantı-kesme-sonrası",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "disabled, per policy",
+ "message": "disabled, per policy",
+ "translation": "ilke gereği kapalı",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "enabled",
+ "message": "enabled",
+ "translation": "etkin",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "{String} received, {String_1} sent",
+ "message": "{String} received, {String_1} sent",
+ "translation": "{String} alındı, {String_1} gönderildi",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "String",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "c.RxBytes.String()"
+ },
+ {
+ "id": "String_1",
+ "string": "%[2]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 2,
+ "expr": "c.TxBytes.String()"
+ }
+ ]
+ },
+ {
+ "id": "Failed to determine tunnel state",
+ "message": "Failed to determine tunnel state",
+ "translation": "Tünel durumu belirlenemedi",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Failed to activate tunnel",
+ "message": "Failed to activate tunnel",
+ "translation": "Tünel etkinleştirilemedi",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Failed to deactivate tunnel",
+ "message": "Failed to deactivate tunnel",
+ "translation": "Tünel devre dışı bırakılamadı",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Interface: {Name}",
+ "message": "Interface: {Name}",
+ "translation": "Arabirim: {Name}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Name",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "config.Name"
+ }
+ ]
+ },
+ {
+ "id": "Peer",
+ "message": "Peer",
+ "translation": "Eş",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Create new tunnel",
+ "message": "Create new tunnel",
+ "translation": "Yeni tünel oluştur",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Edit tunnel",
+ "message": "Edit tunnel",
+ "translation": "Tüneli düzenle",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Name:",
+ "message": "&Name:",
+ "translation": "&İsim:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Public key:",
+ "message": "&Public key:",
+ "translation": "&Açık anahtar:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "(unknown)",
+ "message": "(unknown)",
+ "translation": "(bilinmiyor)",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Block untunneled traffic (kill-switch)",
+ "message": "&Block untunneled traffic (kill-switch)",
+ "translation": "&Tünelden geçmeyen trafiği durdur (kill-switch)",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "When a configuration has exactly one peer, and that peer has an allowed IPs containing at least one of 0.0.0.0/0 or ::/0, then the tunnel service engages a firewall ruleset to block all traffic that is neither to nor from the tunnel interface or is to the wrong DNS server, with special exceptions for DHCP and NDP.",
+ "message": "When a configuration has exactly one peer, and that peer has an allowed IPs containing at least one of 0.0.0.0/0 or ::/0, then the tunnel service engages a firewall ruleset to block all traffic that is neither to nor from the tunnel interface or is to the wrong DNS server, with special exceptions for DHCP and NDP.",
+ "translation": "Bir yapılandırmada tam bir eş varsa, ve bu eş 0.0.0.0/0 veya ::/0 arasından en az birini içeren izin verilen IPler listesine sahipse, tünel hizmeti DHCP ve NDP için bazı özel istisnalar hariç tünel arabirimine gitmeyen veya bu arabirimden gelmeyen, veya yanlış DNS sunucusuna giden tüm trafiği durdurmak için güvenlik duvarında bir ilke kümesi ayarlar.",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Save",
+ "message": "&Save",
+ "translation": "&Kaydet",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Cancel",
+ "message": "Cancel",
+ "translation": "İptal",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Configuration:",
+ "message": "&Configuration:",
+ "translation": "&Yapılandırma:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Invalid name",
+ "message": "Invalid name",
+ "translation": "Geçersiz isim",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "A name is required.",
+ "message": "A name is required.",
+ "translation": "Bir isim gerekli.",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Tunnel name ‘{NewName}’ is invalid.",
+ "message": "Tunnel name ‘{NewName}’ is invalid.",
+ "translation": "`{NewName}` geçersiz bir tünel ismi.",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "NewName",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "newName"
+ }
+ ]
+ },
+ {
+ "id": "Unable to list existing tunnels",
+ "message": "Unable to list existing tunnels",
+ "translation": "Mevcut tüneller listelenemiyor",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Tunnel already exists",
+ "message": "Tunnel already exists",
+ "translation": "Tünel zaten mevcut",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Another tunnel already exists with the name ‘{NewName}’.",
+ "message": "Another tunnel already exists with the name ‘{NewName}’.",
+ "translation": "‘{NewName}’ adında başka bir tünel mevcut.",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "NewName",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "newName"
+ }
+ ]
+ },
+ {
+ "id": "Unable to create new configuration",
+ "message": "Unable to create new configuration",
+ "translation": "Yeni yapılandırma oluşturulamıyor",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Writing file failed",
+ "message": "Writing file failed",
+ "translation": "Dosya yazılamadı",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "File ‘{FilePath}’ already exists.\n\nDo you want to overwrite it?",
+ "message": "File ‘{FilePath}’ already exists.\n\nDo you want to overwrite it?",
+ "translation": "`{FilePath}` dosyası zaten mevcut.\n\nÜzerine yazmak ister misiniz?",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "FilePath",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "filePath"
+ }
+ ]
+ },
+ {
+ "id": "Active",
+ "message": "Active",
+ "translation": "Etkin",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Activating",
+ "message": "Activating",
+ "translation": "Etkinleştiriliyor",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Inactive",
+ "message": "Inactive",
+ "translation": "Etkin değil",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Deactivating",
+ "message": "Deactivating",
+ "translation": "Devre dışı bırakılıyor",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Unknown state",
+ "message": "Unknown state",
+ "translation": "Durum bilinmiyor",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Log",
+ "message": "Log",
+ "translation": "Günlük",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Copy",
+ "message": "&Copy",
+ "translation": "Kopyala (&c)",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Select &all",
+ "message": "Select &all",
+ "translation": "&tümünü seç",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Save to file…",
+ "message": "&Save to file…",
+ "translation": "Dosyaya kaydet (&s)…",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Time",
+ "message": "Time",
+ "translation": "Zaman",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Log message",
+ "message": "Log message",
+ "translation": "Günlük mesajı",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Text Files (*.txt)|*.txt|All Files (*.*)|*.*",
+ "message": "Text Files (*.txt)|*.txt|All Files (*.*)|*.*",
+ "translation": "Metin Dosyaları (*.txt)|*.txt|Tüm Dosyalar (*.*)|*.*",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Export log to file",
+ "message": "Export log to file",
+ "translation": "Günlük dosyasını dışa aktar",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&About WireGuard…",
+ "message": "&About WireGuard…",
+ "translation": "WireGuard Hakkında (&a)…",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Tunnel Error",
+ "message": "Tunnel Error",
+ "translation": "Tünel Hatası",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "{ErrMsg}\n\nPlease consult the log for more information.",
+ "message": "{ErrMsg}\n\nPlease consult the log for more information.",
+ "translation": "{ErrMsg}\n\nLütfen daha fazla bilgi için günlüğe göz atın.",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "ErrMsg",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "errMsg"
+ }
+ ]
+ },
+ {
+ "id": "{Title} (out of date)",
+ "message": "{Title} (out of date)",
+ "translation": "{Title} (eski sürüm)",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Title",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "mtw.Title()"
+ }
+ ]
+ },
+ {
+ "id": "WireGuard Detection Error",
+ "message": "WireGuard Detection Error",
+ "translation": "WireGuard Tespit Hatası",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Unable to wait for WireGuard window to appear: {Err}",
+ "message": "Unable to wait for WireGuard window to appear: {Err}",
+ "translation": "WireGuard penceresinin belirmesi beklenemedi: {Err}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Err",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "err"
+ }
+ ]
+ },
+ {
+ "id": "WireGuard: Deactivated",
+ "message": "WireGuard: Deactivated",
+ "translation": "WireGuard: Devre dışı",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Status: Unknown",
+ "message": "Status: Unknown",
+ "translation": "Durum: Bilinmiyor",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Addresses: None",
+ "message": "Addresses: None",
+ "translation": "Adresler: Yok",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Manage tunnels…",
+ "message": "&Manage tunnels…",
+ "translation": "Tünelleri yönet (&m)…",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Import tunnel(s) from file…",
+ "message": "&Import tunnel(s) from file…",
+ "translation": "Dosyadan tünelleri içe aktar (&i)…",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "E&xit",
+ "message": "E&xit",
+ "translation": "Çık (&x)",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Tunnels",
+ "message": "&Tunnels",
+ "translation": "Tüneller (&t)",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "WireGuard Activated",
+ "message": "WireGuard Activated",
+ "translation": "WireGuard Etkin",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "The {Name} tunnel has been activated.",
+ "message": "The {Name} tunnel has been activated.",
+ "translation": "{Name} tüneli etkinleştirildi.",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Name",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "tunnel.Name"
+ }
+ ]
+ },
+ {
+ "id": "WireGuard Deactivated",
+ "message": "WireGuard Deactivated",
+ "translation": "WireGuard Devre Dışı Bırakıldı",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "The {Name} tunnel has been deactivated.",
+ "message": "The {Name} tunnel has been deactivated.",
+ "translation": "{Name} tüneli devre dışı bırakıldı.",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Name",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "tunnel.Name"
+ }
+ ]
+ },
+ {
+ "id": "WireGuard Tunnel Error",
+ "message": "WireGuard Tunnel Error",
+ "translation": "WireGuard Tünel Hatası",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "WireGuard: {TextForStateglobalState_true}",
+ "message": "WireGuard: {TextForStateglobalState_true}",
+ "translation": "WireGuard: {TextForStateglobalState_true}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "TextForStateglobalState_true",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "textForState(globalState, true)"
+ }
+ ]
+ },
+ {
+ "id": "Status: {StateText}",
+ "message": "Status: {StateText}",
+ "translation": "Durum: {StateText}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "StateText",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "stateText"
+ }
+ ]
+ },
+ {
+ "id": "Addresses: {EnumerationSeparator}",
+ "message": "Addresses: {EnumerationSeparator}",
+ "translation": "Adresler: {EnumerationSeparator}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "EnumerationSeparator",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "strings.Join(addrs, l18n.EnumerationSeparator())"
+ }
+ ]
+ },
+ {
+ "id": "An Update is Available!",
+ "message": "An Update is Available!",
+ "translation": "Güncelleme Mevcut!",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "WireGuard Update Available",
+ "message": "WireGuard Update Available",
+ "translation": "WireGuard Güncellemesi Mevcut",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "An update to WireGuard is now available. You are advised to update as soon as possible.",
+ "message": "An update to WireGuard is now available. You are advised to update as soon as possible.",
+ "translation": "WireGuard için bir güncelleme mevcut. İlk fırsatta güncelleme yapmanız tavsiye edilir.",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Tunnels",
+ "message": "Tunnels",
+ "translation": "Tüneller",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Edit",
+ "message": "&Edit",
+ "translation": "&Edit",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Add &empty tunnel…",
+ "message": "Add &empty tunnel…",
+ "translation": "Boş tünel ekle (&e)…",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Add Tunnel",
+ "message": "Add Tunnel",
+ "translation": "Tünel Ekle",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Remove selected tunnel(s)",
+ "message": "Remove selected tunnel(s)",
+ "translation": "Seçilen tünelleri kaldır",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Export all tunnels to zip",
+ "message": "Export all tunnels to zip",
+ "translation": "Tüm tünelleri zip olarak dışa aktar",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Toggle",
+ "message": "&Toggle",
+ "translation": "&Değiştir",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Export all tunnels to &zip…",
+ "message": "Export all tunnels to &zip…",
+ "translation": "Tüm tünelleri &zip olarak dışa aktar…",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Edit &selected tunnel…",
+ "message": "Edit &selected tunnel…",
+ "translation": "&Seçilen tüneli düzenle…",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Remove selected tunnel(s)",
+ "message": "&Remove selected tunnel(s)",
+ "translation": "S&eçilen tünelleri kaldır",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "no configuration files were found",
+ "message": "no configuration files were found",
+ "translation": "yapılandırma dosyası bulunamadı",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Could not import selected configuration: {LastErr}",
+ "message": "Could not import selected configuration: {LastErr}",
+ "translation": "Seçilen yapılandırma içe aktarılamadı: {LastErr}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "LastErr",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "lastErr"
+ }
+ ]
+ },
+ {
+ "id": "Could not enumerate existing tunnels: {LastErr}",
+ "message": "Could not enumerate existing tunnels: {LastErr}",
+ "translation": "Mevcut tüneller numaralandırılamadı: {LastErr}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "LastErr",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "lastErr"
+ }
+ ]
+ },
+ {
+ "id": "Another tunnel already exists with the name ‘{Name}’",
+ "message": "Another tunnel already exists with the name ‘{Name}’",
+ "translation": "‘{Name}’ adında başka bir tünel mevcut",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Name",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "unparsedConfig.Name"
+ }
+ ]
+ },
+ {
+ "id": "Unable to import configuration: {LastErr}",
+ "message": "Unable to import configuration: {LastErr}",
+ "translation": "Yapılandırma içe aktarılamıyor: {LastErr}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "LastErr",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "lastErr"
+ }
+ ]
+ },
+ {
+ "id": "Imported tunnels",
+ "message": "Imported tunnels",
+ "translation": "Tüneller içe aktarıldı",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Imported {M} tunnels",
+ "message": "Imported {M} tunnels",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "M",
+ "cases": {
+ "one": {
+ "msg": "{M} tünel içe aktarıldı"
+ },
+ "other": {
+ "msg": "{M} tünel içe aktarıldı"
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "M",
+ "string": "%[1]d",
+ "type": "int",
+ "underlyingType": "int",
+ "argNum": 1,
+ "expr": "m"
+ }
+ ]
+ },
+ {
+ "id": "Imported {M} of {N} tunnels",
+ "message": "Imported {M} of {N} tunnels",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "N",
+ "cases": {
+ "one": {
+ "msg": "{N}/{M} tünel içe aktarıldı"
+ },
+ "other": {
+ "msg": "{N}/{M} tünel içe aktarıldı"
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "M",
+ "string": "%[1]d",
+ "type": "int",
+ "underlyingType": "int",
+ "argNum": 1,
+ "expr": "m"
+ },
+ {
+ "id": "N",
+ "string": "%[2]d",
+ "type": "int",
+ "underlyingType": "int",
+ "argNum": 2,
+ "expr": "n"
+ }
+ ]
+ },
+ {
+ "id": "Unable to create tunnel",
+ "message": "Unable to create tunnel",
+ "translation": "Tünel oluşturulamıyor",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Delete {TunnelCount} tunnels",
+ "message": "Delete {TunnelCount} tunnels",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "TunnelCount",
+ "cases": {
+ "one": {
+ "msg": "{TunnelCount} tüneli sil"
+ },
+ "other": {
+ "msg": "{TunnelCount} tüneli sil"
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "TunnelCount",
+ "string": "%[1]d",
+ "type": "int",
+ "underlyingType": "int",
+ "argNum": 1,
+ "expr": "tunnelCount"
+ }
+ ]
+ },
+ {
+ "id": "Are you sure you would like to delete {TunnelCount} tunnels?",
+ "message": "Are you sure you would like to delete {TunnelCount} tunnels?",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "TunnelCount",
+ "cases": {
+ "one": {
+ "msg": "{TunnelCount} tüneli silmek istediğinizden emin misiniz?"
+ },
+ "other": {
+ "msg": "{TunnelCount} tüneli silmek istediğinizden emin misiniz?"
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "TunnelCount",
+ "string": "%[1]d",
+ "type": "int",
+ "underlyingType": "int",
+ "argNum": 1,
+ "expr": "tunnelCount"
+ }
+ ]
+ },
+ {
+ "id": "Delete tunnel ‘{TunnelName}’",
+ "message": "Delete tunnel ‘{TunnelName}’",
+ "translation": "‘{TunnelName}’ tünelini sil",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "TunnelName",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "tunnelName"
+ }
+ ]
+ },
+ {
+ "id": "Are you sure you would like to delete tunnel ‘{TunnelName}’?",
+ "message": "Are you sure you would like to delete tunnel ‘{TunnelName}’?",
+ "translation": "‘{TunnelName}’ tünelini silmek istediğinizden emin misiniz?",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "TunnelName",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "tunnelName"
+ }
+ ]
+ },
+ {
+ "id": "{Question} You cannot undo this action.",
+ "message": "{Question} You cannot undo this action.",
+ "translation": "{Question} Bu işlemi geri alamazsınız.",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Question",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "question"
+ }
+ ]
+ },
+ {
+ "id": "Unable to delete tunnel",
+ "message": "Unable to delete tunnel",
+ "translation": "Tünel silinemiyor",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "A tunnel was unable to be removed: {Error}",
+ "message": "A tunnel was unable to be removed: {Error}",
+ "translation": "Bir tünel kaldırılamadı: {Error}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Error",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "errors[0].Error()"
+ }
+ ]
+ },
+ {
+ "id": "Unable to delete tunnels",
+ "message": "Unable to delete tunnels",
+ "translation": "Tüneller silinemiyor",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "{Lenerrors} tunnels were unable to be removed.",
+ "message": "{Lenerrors} tunnels were unable to be removed.",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "Lenerrors",
+ "cases": {
+ "one": {
+ "msg": "{Lenerrors} tünel kaldırılamadı."
+ },
+ "other": {
+ "msg": "{Lenerrors} tünel kaldırılamadı."
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "Lenerrors",
+ "string": "%[1]d",
+ "type": "int",
+ "underlyingType": "int",
+ "argNum": 1,
+ "expr": "len(errors)"
+ }
+ ]
+ },
+ {
+ "id": "Configuration Files (*.zip, *.conf)|*.zip;*.conf|All Files (*.*)|*.*",
+ "message": "Configuration Files (*.zip, *.conf)|*.zip;*.conf|All Files (*.*)|*.*",
+ "translation": "Yapılandırma Dosyaları (*.zip, *.conf)|*.zip;*.conf|Tüm Dosyalar (*.*)|*.*",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Import tunnel(s) from file",
+ "message": "Import tunnel(s) from file",
+ "translation": "Tünelleri dosyadan içe aktar",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Configuration ZIP Files (*.zip)|*.zip",
+ "message": "Configuration ZIP Files (*.zip)|*.zip",
+ "translation": "Yapılandırma ZIP Dosyası (*.zip)|*.zip",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Export tunnels to zip",
+ "message": "Export tunnels to zip",
+ "translation": "Tünelleri zip olarak dışa aktar",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "{Title} (unsigned build, no updates)",
+ "message": "{Title} (unsigned build, no updates)",
+ "translation": "{Title} (imzasız derleme, güncelleme yok)",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Title",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "mtw.Title()"
+ }
+ ]
+ },
+ {
+ "id": "Error Exiting WireGuard",
+ "message": "Error Exiting WireGuard",
+ "translation": "WireGuard Çıkış Hatası",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Unable to exit service due to: {Err}. You may want to stop WireGuard from the service manager.",
+ "message": "Unable to exit service due to: {Err}. You may want to stop WireGuard from the service manager.",
+ "translation": "Hizmet şu nedenden dolayı kapatılamıyor: {Err}. WireGuard'ı hizmet yöneticisinden durdurabilirsiniz.",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Err",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "err"
+ }
+ ]
+ },
+ {
+ "id": "An update to WireGuard is available. It is highly advisable to update without delay.",
+ "message": "An update to WireGuard is available. It is highly advisable to update without delay.",
+ "translation": "WireGuard için bir güncelleme mevcut. Bekletmeden güncelleme yapmanız önemle tavsiye edilir.",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Status: Waiting for user",
+ "message": "Status: Waiting for user",
+ "translation": "Durum: Kullanıcı bekleniyor",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Update Now",
+ "message": "Update Now",
+ "translation": "Şimdi Güncelle",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Status: Waiting for updater service",
+ "message": "Status: Waiting for updater service",
+ "translation": "Durum: Güncelleştirme hizmeti bekleniyor",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Error: {Err}. Please try again.",
+ "message": "Error: {Err}. Please try again.",
+ "translation": "Hata: {Err}. Lütfen yeniden deneyin.",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Err",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "err"
+ }
+ ]
+ },
+ {
+ "id": "Status: Complete!",
+ "message": "Status: Complete!",
+ "translation": "Durum: Tamamlandı!",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "http2: Framer {F}: failed to decode just-written frame",
+ "message": "http2: Framer {F}: failed to decode just-written frame",
+ "translation": "http2: Framer {F}: az önce yazılmış çerçeve çözülemedi",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "F",
+ "string": "%[1]p",
+ "type": "*net/http.http2Framer",
+ "underlyingType": "*net/http.http2Framer",
+ "argNum": 1,
+ "expr": "f"
+ }
+ ]
+ },
+ {
+ "id": "http2: Framer {F}: wrote {Http2summarizeFramefr}",
+ "message": "http2: Framer {F}: wrote {Http2summarizeFramefr}",
+ "translation": "http2: Framer {F}: {Http2summarizeFramefr} yazıldı",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "F",
+ "string": "%[1]p",
+ "type": "*net/http.http2Framer",
+ "underlyingType": "*net/http.http2Framer",
+ "argNum": 1,
+ "expr": "f"
+ },
+ {
+ "id": "Http2summarizeFramefr",
+ "string": "%[2]v",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 2,
+ "expr": "http2summarizeFrame(fr)"
+ }
+ ]
+ },
+ {
+ "id": "http2: Framer {Fr}: read {Http2summarizeFramef}",
+ "message": "http2: Framer {Fr}: read {Http2summarizeFramef}",
+ "translation": "http2: Framer {Fr}: {Http2summarizeFramef} okundu",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Fr",
+ "string": "%[1]p",
+ "type": "*net/http.http2Framer",
+ "underlyingType": "*net/http.http2Framer",
+ "argNum": 1,
+ "expr": "fr"
+ },
+ {
+ "id": "Http2summarizeFramef",
+ "string": "%[2]v",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 2,
+ "expr": "http2summarizeFrame(f)"
+ }
+ ]
+ },
+ {
+ "id": "http2: decoded hpack field {HeaderField}",
+ "message": "http2: decoded hpack field {HeaderField}",
+ "translation": "https2: {HeaderField} hpack alanı çözüldü",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "HeaderField",
+ "string": "%+[1]v",
+ "type": "vendor/golang.org/x/net/http2/hpack.HeaderField",
+ "underlyingType": "struct{Name string; Value string; Sensitive bool}",
+ "argNum": 1,
+ "expr": "hf"
+ }
+ ]
+ }
+ ]
+} \ No newline at end of file
diff --git a/locales/uk/messages.gotext.json b/locales/uk/messages.gotext.json
index ca6635da..7079e424 100644
--- a/locales/uk/messages.gotext.json
+++ b/locales/uk/messages.gotext.json
@@ -8,6 +8,36 @@
"translatorComment": "Copied from source."
},
{
+ "id": "(no argument): elevate and install manager service",
+ "message": "(no argument): elevate and install manager service",
+ "translation": "(немає аргумента): отримати права аднімістратора і встановити службу",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Usage: {Args0} [\n{String}]",
+ "message": "Usage: {Args0} [\n{String}]",
+ "translation": "Використання: {Args0} [\n{String}]",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Args0",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "os.Args[0]"
+ },
+ {
+ "id": "String",
+ "string": "%[2]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 2,
+ "expr": "builder.String()"
+ }
+ ]
+ },
+ {
"id": "Command Line Options",
"message": "Command Line Options",
"translation": "Параметри командного рядка",
@@ -30,6 +60,12 @@
]
},
{
+ "id": "You must use the native version of WireGuard on this computer.",
+ "message": "You must use the native version of WireGuard on this computer.",
+ "translation": "Ви повинні використовувати нативну версію WireGuard на цьому комп'ютері.",
+ "translatorComment": "Copied from source."
+ },
+ {
"id": "Unable to open current process token: {Err}",
"message": "Unable to open current process token: {Err}",
"translation": "Не вдалося відкрити токен поточного процесу: {Err}",
@@ -192,6 +228,30 @@
]
},
{
+ "id": "{Why}: {Offender}",
+ "message": "{Why}: {Offender}",
+ "translation": "{Why}: {Offender}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Why",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "e.why"
+ },
+ {
+ "id": "Offender",
+ "string": "%[2]q",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 2,
+ "expr": "e.offender"
+ }
+ ]
+ },
+ {
"id": "Invalid IP address",
"message": "Invalid IP address",
"translation": "Недійсна IP-адреса",
@@ -234,6 +294,12 @@
"translatorComment": "Copied from source."
},
{
+ "id": "Invalid persistent keepalive",
+ "message": "Invalid persistent keepalive",
+ "translation": "Некоректне значення keepalive",
+ "translatorComment": "Copied from source."
+ },
+ {
"id": "Invalid key: {Err}",
"message": "Invalid key: {Err}",
"translation": "Недійсний ключ: {Err}",
@@ -250,12 +316,40 @@
]
},
{
+ "id": "Keys must decode to exactly 32 bytes",
+ "message": "Keys must decode to exactly 32 bytes",
+ "translation": "Ключ повинен декодуватись до 32 байт",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Number must be a number between 0 and 2^64-1: {Err}",
+ "message": "Number must be a number between 0 and 2^64-1: {Err}",
+ "translation": "Номер повинен бути числом від 0 до 2^64-1: {Err}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Err",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "err"
+ }
+ ]
+ },
+ {
"id": "Two commas in a row",
"message": "Two commas in a row",
"translation": "Дві коми поспіль",
"translatorComment": "Copied from source."
},
{
+ "id": "Tunnel name is not valid",
+ "message": "Tunnel name is not valid",
+ "translation": "Назва тунелю некоректна",
+ "translatorComment": "Copied from source."
+ },
+ {
"id": "Line must occur in a section",
"message": "Line must occur in a section",
"translation": "Рядок повинен бути вказаним у розділі",
@@ -322,6 +416,24 @@
"translatorComment": "Copied from source."
},
{
+ "id": "Invalid key for peer section",
+ "message": "Invalid key for peer section",
+ "translation": "Хибний ключ для [Peer] розділу",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "[EnumerationSeparator]",
+ "message": "[EnumerationSeparator]",
+ "translation": ", ",
+ "comment": "Text to insert between items when listing - most western languages will translate ‘[EnumerationSeparator]’ into ‘, ’ to produce lists like ‘apple, orange, strawberry’. Eastern languages might translate into ‘、’ to produce lists like ‘リンゴ、オレンジ、イチゴ’."
+ },
+ {
+ "id": "[UnitSeparator]",
+ "message": "[UnitSeparator]",
+ "translation": ", ",
+ "comment": "Text to insert when combining units of a measure - most languages will translate ‘[UnitSeparator]’ into ‘ ’ (space) to produce lists like ‘2 minuti 30 sekund’, or empty string ‘’ to produce ‘2分30秒’."
+ },
+ {
"id": "About WireGuard",
"message": "About WireGuard",
"translation": "Про WireGuard",
@@ -334,6 +446,62 @@
"translatorComment": "Copied from source."
},
{
+ "id": "App version: {Number}\nGo backend version: {WireGuardGoVersion}\nGo version: {Version_go}-{GOARCH}\nOperating system: {OsName}\nArchitecture: {NativeArch}",
+ "message": "App version: {Number}\nGo backend version: {WireGuardGoVersion}\nGo version: {Version_go}-{GOARCH}\nOperating system: {OsName}\nArchitecture: {NativeArch}",
+ "translation": "Версія додатку: {Number}\nВерсія Go бекенду: {WireGuardGoVersion}\nВерсія Go: {Version_go}-{GOARCH}\nОпераційна система: {OsName}\nАрхітектура {NativeArch}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Number",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "version.Number"
+ },
+ {
+ "id": "WireGuardGoVersion",
+ "string": "%[2]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 2,
+ "expr": "device.WireGuardGoVersion"
+ },
+ {
+ "id": "Version_go",
+ "string": "%[3]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 3,
+ "expr": "strings.TrimPrefix(runtime.Version(), \"go\")"
+ },
+ {
+ "id": "GOARCH",
+ "string": "%[4]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 4,
+ "expr": "runtime.GOARCH"
+ },
+ {
+ "id": "OsName",
+ "string": "%[5]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 5,
+ "expr": "version.OsName()"
+ },
+ {
+ "id": "NativeArch",
+ "string": "%[6]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 6,
+ "expr": "version.NativeArch()"
+ }
+ ]
+ },
+ {
"id": "Close",
"message": "Close",
"translation": "Закрити",
@@ -368,6 +536,398 @@
"message": "Public key:",
"translation": "Відкритий ключ:",
"translatorComment": "Copied from source."
+ },
+ {
+ "id": "Listen port:",
+ "message": "Listen port:",
+ "translation": "Порт:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "MTU:",
+ "message": "MTU:",
+ "translation": "MTU:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Addresses:",
+ "message": "Addresses:",
+ "translation": "Адреси:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "DNS servers:",
+ "message": "DNS servers:",
+ "translation": "DNS-сервери:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Scripts:",
+ "message": "Scripts:",
+ "translation": "Скрипти:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Preshared key:",
+ "message": "Preshared key:",
+ "translation": "Preshared ключ:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Allowed IPs:",
+ "message": "Allowed IPs:",
+ "translation": "Дозволені IP адреси:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Endpoint:",
+ "message": "Endpoint:",
+ "translation": "Endpoint:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Persistent keepalive:",
+ "message": "Persistent keepalive:",
+ "translation": "Persistent keepalive:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Latest handshake:",
+ "message": "Latest handshake:",
+ "translation": "Останнє рукостискання:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Transfer:",
+ "message": "Transfer:",
+ "translation": "Передано:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "pre-up",
+ "message": "pre-up",
+ "translation": "перед-запуском",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "post-up",
+ "message": "post-up",
+ "translation": "після-запуску",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "pre-down",
+ "message": "pre-down",
+ "translation": "перед-зупинкою",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "post-down",
+ "message": "post-down",
+ "translation": "після-зупинки",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "disabled, per policy",
+ "message": "disabled, per policy",
+ "translation": "вимкнено, відповідно до політики",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "enabled",
+ "message": "enabled",
+ "translation": "увімкнено",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "{String} received, {String_1} sent",
+ "message": "{String} received, {String_1} sent",
+ "translation": "{String} отримано, {String_1} відправлено",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "String",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "c.RxBytes.String()"
+ },
+ {
+ "id": "String_1",
+ "string": "%[2]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 2,
+ "expr": "c.TxBytes.String()"
+ }
+ ]
+ },
+ {
+ "id": "Failed to determine tunnel state",
+ "message": "Failed to determine tunnel state",
+ "translation": "Не вдалося визначити стан тунелю",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Failed to activate tunnel",
+ "message": "Failed to activate tunnel",
+ "translation": "Не вдалося активувати тунель",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Failed to deactivate tunnel",
+ "message": "Failed to deactivate tunnel",
+ "translation": "Не вдалося деактивувати тунель",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Interface: {Name}",
+ "message": "Interface: {Name}",
+ "translation": "Інтерфейс: {Name}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Name",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "config.Name"
+ }
+ ]
+ },
+ {
+ "id": "Peer",
+ "message": "Peer",
+ "translation": "Пір",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Create new tunnel",
+ "message": "Create new tunnel",
+ "translation": "Створити новий тунель",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Edit tunnel",
+ "message": "Edit tunnel",
+ "translation": "Редагувати тунель",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Name:",
+ "message": "&Name:",
+ "translation": "&Назва:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Public key:",
+ "message": "&Public key:",
+ "translation": "&Публічний ключ:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "(unknown)",
+ "message": "(unknown)",
+ "translation": "(невідомий)",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Block untunneled traffic (kill-switch)",
+ "message": "&Block untunneled traffic (kill-switch)",
+ "translation": "&Блокувати трафік поза тунелем",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "When a configuration has exactly one peer, and that peer has an allowed IPs containing at least one of 0.0.0.0/0 or ::/0, then the tunnel service engages a firewall ruleset to block all traffic that is neither to nor from the tunnel interface or is to the wrong DNS server, with special exceptions for DHCP and NDP.",
+ "message": "When a configuration has exactly one peer, and that peer has an allowed IPs containing at least one of 0.0.0.0/0 or ::/0, then the tunnel service engages a firewall ruleset to block all traffic that is neither to nor from the tunnel interface or is to the wrong DNS server, with special exceptions for DHCP and NDP.",
+ "translation": "У випадку якщо в конфігурації вказаний лише один пір, та його дозволені ІР-адреси містять 0.0.0.0/0 або ::/0, сервіс тунелю вводить у дію правила фаєрволу що блокують увесь трафік поза тунелем або до невідповідних DNS серверів, з виключеннями для DHCP та NDP.",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Save",
+ "message": "&Save",
+ "translation": "&Зберегти",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Cancel",
+ "message": "Cancel",
+ "translation": "Скасувати",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Configuration:",
+ "message": "&Configuration:",
+ "translation": "&Налаштування:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Invalid name",
+ "message": "Invalid name",
+ "translation": "Хибне ім'я",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "A name is required.",
+ "message": "A name is required.",
+ "translation": "Необхідно ввести ім'я.",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Tunnel name ‘{NewName}’ is invalid.",
+ "message": "Tunnel name ‘{NewName}’ is invalid.",
+ "translation": "Ім'я тунелю '{NewName}' некоректне.",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "NewName",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "newName"
+ }
+ ]
+ },
+ {
+ "id": "Unable to list existing tunnels",
+ "message": "Unable to list existing tunnels",
+ "translation": "Не вдалося відобразити існуючі тунелі",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Tunnel already exists",
+ "message": "Tunnel already exists",
+ "translation": "Тунель вже існує",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Another tunnel already exists with the name ‘{NewName}’.",
+ "message": "Another tunnel already exists with the name ‘{NewName}’.",
+ "translation": "Тунель з ім'ям ‘{NewName}’ вже існує.",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "NewName",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "newName"
+ }
+ ]
+ },
+ {
+ "id": "no configuration files were found",
+ "message": "no configuration files were found",
+ "translation": "не знайдено файлів конфігурації",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Could not import selected configuration: {LastErr}",
+ "message": "Could not import selected configuration: {LastErr}",
+ "translation": "Не вдалося імпортувати вибрану конфігурацію: {LastErr}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "LastErr",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "lastErr"
+ }
+ ]
+ },
+ {
+ "id": "Could not enumerate existing tunnels: {LastErr}",
+ "message": "Could not enumerate existing tunnels: {LastErr}",
+ "translation": "Не вдалося перерахувати існуючі тунелі: {LastErr}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "LastErr",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "lastErr"
+ }
+ ]
+ },
+ {
+ "id": "Another tunnel already exists with the name ‘{Name}’",
+ "message": "Another tunnel already exists with the name ‘{Name}’",
+ "translation": "Тунель з ім'ям ‘{Name}’ вже існує",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Name",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "unparsedConfig.Name"
+ }
+ ]
+ },
+ {
+ "id": "Unable to import configuration: {LastErr}",
+ "message": "Unable to import configuration: {LastErr}",
+ "translation": "Не вдалося імпортувати конфігурацію: {LastErr}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "LastErr",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "lastErr"
+ }
+ ]
+ },
+ {
+ "id": "Imported tunnels",
+ "message": "Imported tunnels",
+ "translation": "Імпортовано тунелі",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Imported {M} tunnels",
+ "message": "Imported {M} tunnels",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "M",
+ "cases": {
+ "one": {
+ "msg": "Імпортовано {M} тунель"
+ },
+ "few": {
+ "msg": "Імпортовано {M} тунелі"
+ },
+ "many": {
+ "msg": "Імпортовано {M} тунелів"
+ },
+ "other": {
+ "msg": "Імпортовано {M} тунелів"
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "M",
+ "string": "%[1]d",
+ "type": "int",
+ "underlyingType": "int",
+ "argNum": 1,
+ "expr": "m"
+ }
+ ]
}
]
} \ No newline at end of file
diff --git a/locales/zh-CN/messages.gotext.json b/locales/zh-CN/messages.gotext.json
index 140a073c..5f70db44 100644
--- a/locales/zh-CN/messages.gotext.json
+++ b/locales/zh-CN/messages.gotext.json
@@ -495,13 +495,13 @@
{
"id": "Invalid key for [Interface] section",
"message": "Invalid key for [Interface] section",
- "translation": "[Interface] 段落的键无效",
+ "translation": "[Interface] 段落中的该键无效",
"translatorComment": "Copied from source."
},
{
"id": "Invalid key for [Peer] section",
"message": "Invalid key for [Peer] section",
- "translation": "[Peer] 段落的键无效",
+ "translation": "[Peer] 段落中的该键无效",
"translatorComment": "Copied from source."
},
{
@@ -519,7 +519,7 @@
{
"id": "All peers must have public keys",
"message": "All peers must have public keys",
- "translation": "所有节点必须拥有公钥。",
+ "translation": "每个节点都必须指定公钥",
"translatorComment": "Copied from source."
},
{
diff --git a/locales/zh-TW/messages.gotext.json b/locales/zh-TW/messages.gotext.json
index f6283b2e..d7ebe665 100644
--- a/locales/zh-TW/messages.gotext.json
+++ b/locales/zh-TW/messages.gotext.json
@@ -60,6 +60,12 @@
]
},
{
+ "id": "You must use the native version of WireGuard on this computer.",
+ "message": "You must use the native version of WireGuard on this computer.",
+ "translation": "您必須在此電腦上執行原生版本的 WireGuard。",
+ "translatorComment": "Copied from source."
+ },
+ {
"id": "Unable to open current process token: {Err}",
"message": "Unable to open current process token: {Err}",
"translation": "無法開啓目前處理程序的權杖: {Err}",
@@ -565,6 +571,62 @@
"translatorComment": "Copied from source."
},
{
+ "id": "App version: {Number}\nGo backend version: {WireGuardGoVersion}\nGo version: {Version_go}-{GOARCH}\nOperating system: {OsName}\nArchitecture: {NativeArch}",
+ "message": "App version: {Number}\nGo backend version: {WireGuardGoVersion}\nGo version: {Version_go}-{GOARCH}\nOperating system: {OsName}\nArchitecture: {NativeArch}",
+ "translation": "應用程式版本: {Number}\n後端程式(Go 實作)版本: {WireGuardGoVersion}\nGo 版本: {Version_go}-{GOARCH}\n作業系統: {OsName}\n架構: {NativeArch}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Number",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "version.Number"
+ },
+ {
+ "id": "WireGuardGoVersion",
+ "string": "%[2]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 2,
+ "expr": "device.WireGuardGoVersion"
+ },
+ {
+ "id": "Version_go",
+ "string": "%[3]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 3,
+ "expr": "strings.TrimPrefix(runtime.Version(), \"go\")"
+ },
+ {
+ "id": "GOARCH",
+ "string": "%[4]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 4,
+ "expr": "runtime.GOARCH"
+ },
+ {
+ "id": "OsName",
+ "string": "%[5]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 5,
+ "expr": "version.OsName()"
+ },
+ {
+ "id": "NativeArch",
+ "string": "%[6]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 6,
+ "expr": "version.NativeArch()"
+ }
+ ]
+ },
+ {
"id": "Close",
"message": "Close",
"translation": "關閉",
@@ -625,6 +687,12 @@
"translatorComment": "Copied from source."
},
{
+ "id": "Scripts:",
+ "message": "Scripts:",
+ "translation": "指令碼:",
+ "translatorComment": "Copied from source."
+ },
+ {
"id": "Preshared key:",
"message": "Preshared key:",
"translation": "預交換金鑰",
@@ -661,6 +729,36 @@
"translatorComment": "Copied from source."
},
{
+ "id": "pre-up",
+ "message": "pre-up",
+ "translation": "連接前",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "post-up",
+ "message": "post-up",
+ "translation": "連接後",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "pre-down",
+ "message": "pre-down",
+ "translation": "斷線前",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "post-down",
+ "message": "post-down",
+ "translation": "斷線後",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "disabled, per policy",
+ "message": "disabled, per policy",
+ "translation": "已關閉, 隨著策略",
+ "translatorComment": "Copied from source."
+ },
+ {
"id": "enabled",
"message": "enabled",
"translation": "已啓用",
@@ -1131,6 +1229,22 @@
]
},
{
+ "id": "Addresses: {EnumerationSeparator}",
+ "message": "Addresses: {EnumerationSeparator}",
+ "translation": "位址: {EnumerationSeparator}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "EnumerationSeparator",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "strings.Join(addrs, l18n.EnumerationSeparator())"
+ }
+ ]
+ },
+ {
"id": "An Update is Available!",
"message": "An Update is Available!",
"translation": "更新",
@@ -1209,6 +1323,12 @@
"translatorComment": "Copied from source."
},
{
+ "id": "no configuration files were found",
+ "message": "no configuration files were found",
+ "translation": "找不到設定檔",
+ "translatorComment": "Copied from source."
+ },
+ {
"id": "Could not import selected configuration: {LastErr}",
"message": "Could not import selected configuration: {LastErr}",
"translation": "無法匯入設定: {LastErr}",
diff --git a/main.go b/main.go
index 5862d4e3..62a0b559 100644
--- a/main.go
+++ b/main.go
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package main
@@ -9,6 +9,7 @@ import (
"debug/pe"
"errors"
"fmt"
+ "io"
"log"
"os"
"strconv"
@@ -16,8 +17,9 @@ import (
"time"
"golang.org/x/sys/windows"
- "golang.zx2c4.com/wireguard/tun"
+ "golang.zx2c4.com/wireguard/windows/conf"
+ "golang.zx2c4.com/wireguard/windows/driver"
"golang.zx2c4.com/wireguard/windows/elevate"
"golang.zx2c4.com/wireguard/windows/l18n"
"golang.zx2c4.com/wireguard/windows/manager"
@@ -27,21 +29,41 @@ import (
"golang.zx2c4.com/wireguard/windows/updater"
)
-func fatal(v ...interface{}) {
- windows.MessageBox(0, windows.StringToUTF16Ptr(fmt.Sprint(v...)), windows.StringToUTF16Ptr(l18n.Sprintf("Error")), windows.MB_ICONERROR)
- os.Exit(1)
+func setLogFile() {
+ logHandle, err := windows.GetStdHandle(windows.STD_ERROR_HANDLE)
+ if logHandle == 0 || err != nil {
+ logHandle, err = windows.GetStdHandle(windows.STD_OUTPUT_HANDLE)
+ }
+ if logHandle == 0 || err != nil {
+ log.SetOutput(io.Discard)
+ } else {
+ log.SetOutput(os.NewFile(uintptr(logHandle), "stderr"))
+ }
}
-func fatalf(format string, v ...interface{}) {
+func fatal(v ...any) {
+ if log.Writer() == io.Discard {
+ windows.MessageBox(0, windows.StringToUTF16Ptr(fmt.Sprint(v...)), windows.StringToUTF16Ptr(l18n.Sprintf("Error")), windows.MB_ICONERROR)
+ os.Exit(1)
+ } else {
+ log.Fatal(append([]any{l18n.Sprintf("Error: ")}, v...))
+ }
+}
+
+func fatalf(format string, v ...any) {
fatal(l18n.Sprintf(format, v...))
}
-func info(title string, format string, v ...interface{}) {
- windows.MessageBox(0, windows.StringToUTF16Ptr(l18n.Sprintf(format, v...)), windows.StringToUTF16Ptr(title), windows.MB_ICONINFORMATION)
+func info(title, format string, v ...any) {
+ if log.Writer() == io.Discard {
+ windows.MessageBox(0, windows.StringToUTF16Ptr(l18n.Sprintf(format, v...)), windows.StringToUTF16Ptr(title), windows.MB_ICONINFORMATION)
+ } else {
+ log.Printf(title+":\n"+format, v...)
+ }
}
func usage() {
- var flags = [...]string{
+ flags := [...]string{
l18n.Sprintf("(no argument): elevate and install manager service"),
"/installmanagerservice",
"/installtunnelservice CONFIG_PATH",
@@ -50,9 +72,9 @@ func usage() {
"/managerservice",
"/tunnelservice CONFIG_PATH",
"/ui CMD_READ_HANDLE CMD_WRITE_HANDLE CMD_EVENT_HANDLE LOG_MAPPING_HANDLE",
- "/dumplog OUTPUT_PATH",
- "/update [LOG_FILE]",
- "/removealladapters [LOG_FILE]",
+ "/dumplog [/tail]",
+ "/update",
+ "/removedriver",
}
builder := strings.Builder{}
for _, flag := range flags {
@@ -133,6 +155,7 @@ func main() {
panic("failed to restrict dll search path")
}
+ setLogFile()
checkForWow64()
if len(os.Args) <= 1 {
@@ -246,35 +269,31 @@ func main() {
ui.RunUI()
return
case "/dumplog":
- if len(os.Args) != 3 {
+ if len(os.Args) != 2 && len(os.Args) != 3 {
usage()
}
- file, err := os.Create(os.Args[2])
+ outputHandle, err := windows.GetStdHandle(windows.STD_OUTPUT_HANDLE)
if err != nil {
fatal(err)
}
+ if outputHandle == 0 {
+ fatal("Stdout must be set")
+ }
+ file := os.NewFile(uintptr(outputHandle), "stdout")
defer file.Close()
- err = ringlogger.DumpTo(file, true)
+ logPath, err := conf.LogFile(false)
+ if err != nil {
+ fatal(err)
+ }
+ err = ringlogger.DumpTo(logPath, file, len(os.Args) == 3 && os.Args[2] == "/tail")
if err != nil {
fatal(err)
}
return
case "/update":
- if len(os.Args) != 2 && len(os.Args) != 3 {
+ if len(os.Args) != 2 {
usage()
}
- var f *os.File
- var err error
- if len(os.Args) == 2 {
- f = os.Stdout
- } else {
- f, err = os.Create(os.Args[2])
- if err != nil {
- fatal(err)
- }
- defer f.Close()
- }
- l := log.New(f, "", log.LstdFlags)
for progress := range updater.DownloadVerifyAndExecute(0) {
if len(progress.Activity) > 0 {
if progress.BytesTotal > 0 || progress.BytesDownloaded > 0 {
@@ -282,40 +301,27 @@ func main() {
if progress.BytesTotal > 0 {
percent = float64(progress.BytesDownloaded) / float64(progress.BytesTotal) * 100.0
}
- l.Printf("%s: %d/%d (%.2f%%)\n", progress.Activity, progress.BytesDownloaded, progress.BytesTotal, percent)
+ log.Printf("%s: %d/%d (%.2f%%)\n", progress.Activity, progress.BytesDownloaded, progress.BytesTotal, percent)
} else {
- l.Println(progress.Activity)
+ log.Println(progress.Activity)
}
}
if progress.Error != nil {
- l.Printf("Error: %v\n", progress.Error)
+ log.Printf("Error: %v\n", progress.Error)
}
if progress.Complete || progress.Error != nil {
return
}
}
return
- case "/removealladapters":
- if len(os.Args) != 2 && len(os.Args) != 3 {
+ case "/removedriver":
+ if len(os.Args) != 2 {
usage()
}
- var f *os.File
- var err error
- if len(os.Args) == 2 {
- f = os.Stdout
- } else {
- f, err = os.Create(os.Args[2])
- if err != nil {
- fatal(err)
- }
- defer f.Close()
- }
- log.SetOutput(f)
- rebootRequired, err := tun.WintunPool.DeleteDriver()
+ _ = driver.UninstallLegacyWintun() // Best effort
+ err := driver.Uninstall()
if err != nil {
- log.Printf("Error: %v\n", err)
- } else if rebootRequired {
- log.Println("A reboot may be required")
+ fatal(err)
}
return
}
diff --git a/manager/install.go b/manager/install.go
index bd7d23c7..44a744cf 100644
--- a/manager/install.go
+++ b/manager/install.go
@@ -1,13 +1,15 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package manager
import (
"errors"
+ "log"
"os"
+ "strings"
"time"
"golang.org/x/sys/windows"
@@ -15,7 +17,6 @@ import (
"golang.org/x/sys/windows/svc/mgr"
"golang.zx2c4.com/wireguard/windows/conf"
- "golang.zx2c4.com/wireguard/windows/services"
)
var cachedServiceManager *mgr.Mgr
@@ -128,7 +129,7 @@ func InstallTunnel(configPath string) error {
return err
}
- serviceName, err := services.ServiceNameOfTunnel(name)
+ serviceName, err := conf.ServiceNameOfTunnel(name)
if err != nil {
return err
}
@@ -181,7 +182,7 @@ func UninstallTunnel(name string) error {
if err != nil {
return err
}
- serviceName, err := services.ServiceNameOfTunnel(name)
+ serviceName, err := conf.ServiceNameOfTunnel(name)
if err != nil {
return err
}
@@ -197,3 +198,45 @@ func UninstallTunnel(name string) error {
}
return err2
}
+
+func changeTunnelServiceConfigFilePath(name, oldPath, newPath string) {
+ var err error
+ defer func() {
+ if err != nil {
+ log.Printf("Unable to change tunnel service command line argument from %#q to %#q: %v", oldPath, newPath, err)
+ }
+ }()
+ m, err := serviceManager()
+ if err != nil {
+ return
+ }
+ serviceName, err := conf.ServiceNameOfTunnel(name)
+ if err != nil {
+ return
+ }
+ service, err := m.OpenService(serviceName)
+ if err == windows.ERROR_SERVICE_DOES_NOT_EXIST {
+ err = nil
+ return
+ } else if err != nil {
+ return
+ }
+ defer service.Close()
+ config, err := service.Config()
+ if err != nil {
+ return
+ }
+ exePath, err := os.Executable()
+ if err != nil {
+ return
+ }
+ args, err := windows.DecomposeCommandLine(config.BinaryPathName)
+ if err != nil || len(args) != 3 ||
+ !strings.EqualFold(args[0], exePath) || args[1] != "/tunnelservice" || !strings.EqualFold(args[2], oldPath) {
+ err = nil
+ return
+ }
+ args[2] = newPath
+ config.BinaryPathName = windows.ComposeCommandLine(args)
+ err = service.UpdateConfig(config)
+}
diff --git a/manager/interfacecleanup.go b/manager/interfacecleanup.go
deleted file mode 100644
index c270f4ab..00000000
--- a/manager/interfacecleanup.go
+++ /dev/null
@@ -1,56 +0,0 @@
-/* SPDX-License-Identifier: MIT
- *
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
- */
-
-package manager
-
-import (
- "log"
-
- "golang.org/x/sys/windows"
- "golang.org/x/sys/windows/svc"
- "golang.org/x/sys/windows/svc/mgr"
- "golang.zx2c4.com/wireguard/tun/wintun"
-
- "golang.zx2c4.com/wireguard/tun"
- "golang.zx2c4.com/wireguard/windows/services"
-)
-
-func cleanupStaleWintunInterfaces() {
- m, err := mgr.Connect()
- if err != nil {
- return
- }
- defer m.Disconnect()
-
- tun.WintunPool.DeleteMatchingAdapters(func(wintun *wintun.Adapter) bool {
- interfaceName, err := wintun.Name()
- if err != nil {
- log.Printf("Removing Wintun interface because determining interface name failed: %v", err)
- return true
- }
- serviceName, err := services.ServiceNameOfTunnel(interfaceName)
- if err != nil {
- log.Printf("Removing Wintun interface ‘%s’ because determining tunnel service name failed: %v", interfaceName, err)
- return true
- }
- service, err := m.OpenService(serviceName)
- if err == windows.ERROR_SERVICE_DOES_NOT_EXIST {
- log.Printf("Removing Wintun interface ‘%s’ because no service for it exists", interfaceName)
- return true
- } else if err != nil {
- return false
- }
- defer service.Close()
- status, err := service.Query()
- if err != nil {
- return false
- }
- if status.State == svc.Stopped {
- log.Printf("Removing Wintun interface ‘%s’ because its service is stopped", interfaceName)
- return true
- }
- return false
- }, false)
-}
diff --git a/manager/ipc_client.go b/manager/ipc_client.go
index 2f78a47e..8c9c4c04 100644
--- a/manager/ipc_client.go
+++ b/manager/ipc_client.go
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package manager
@@ -64,7 +64,7 @@ var (
)
type TunnelChangeCallback struct {
- cb func(tunnel *Tunnel, state TunnelState, globalState TunnelState, err error)
+ cb func(tunnel *Tunnel, state, globalState TunnelState, err error)
}
var tunnelChangeCallbacks = make(map[*TunnelChangeCallback]bool)
@@ -93,7 +93,7 @@ type UpdateProgressCallback struct {
var updateProgressCallbacks = make(map[*UpdateProgressCallback]bool)
-func InitializeIPCClient(reader *os.File, writer *os.File, events *os.File) {
+func InitializeIPCClient(reader, writer, events *os.File) {
rpcDecoder = gob.NewDecoder(reader)
rpcEncoder = gob.NewEncoder(writer)
go func() {
@@ -431,43 +431,52 @@ func IPCClientUpdate() error {
return rpcEncoder.Encode(UpdateMethodType)
}
-func IPCClientRegisterTunnelChange(cb func(tunnel *Tunnel, state TunnelState, globalState TunnelState, err error)) *TunnelChangeCallback {
+func IPCClientRegisterTunnelChange(cb func(tunnel *Tunnel, state, globalState TunnelState, err error)) *TunnelChangeCallback {
s := &TunnelChangeCallback{cb}
tunnelChangeCallbacks[s] = true
return s
}
+
func (cb *TunnelChangeCallback) Unregister() {
delete(tunnelChangeCallbacks, cb)
}
+
func IPCClientRegisterTunnelsChange(cb func()) *TunnelsChangeCallback {
s := &TunnelsChangeCallback{cb}
tunnelsChangeCallbacks[s] = true
return s
}
+
func (cb *TunnelsChangeCallback) Unregister() {
delete(tunnelsChangeCallbacks, cb)
}
+
func IPCClientRegisterManagerStopping(cb func()) *ManagerStoppingCallback {
s := &ManagerStoppingCallback{cb}
managerStoppingCallbacks[s] = true
return s
}
+
func (cb *ManagerStoppingCallback) Unregister() {
delete(managerStoppingCallbacks, cb)
}
+
func IPCClientRegisterUpdateFound(cb func(updateState UpdateState)) *UpdateFoundCallback {
s := &UpdateFoundCallback{cb}
updateFoundCallbacks[s] = true
return s
}
+
func (cb *UpdateFoundCallback) Unregister() {
delete(updateFoundCallbacks, cb)
}
+
func IPCClientRegisterUpdateProgress(cb func(dp updater.DownloadProgress)) *UpdateProgressCallback {
s := &UpdateProgressCallback{cb}
updateProgressCallbacks[s] = true
return s
}
+
func (cb *UpdateProgressCallback) Unregister() {
delete(updateProgressCallbacks, cb)
}
diff --git a/manager/ipc_driver.go b/manager/ipc_driver.go
new file mode 100644
index 00000000..6cb43c38
--- /dev/null
+++ b/manager/ipc_driver.go
@@ -0,0 +1,61 @@
+/* SPDX-License-Identifier: MIT
+ *
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
+ */
+
+package manager
+
+import (
+ "sync"
+
+ "golang.zx2c4.com/wireguard/windows/driver"
+)
+
+type lockedDriverAdapter struct {
+ *driver.Adapter
+ sync.Mutex
+}
+
+var (
+ driverAdapters = make(map[string]*lockedDriverAdapter)
+ driverAdaptersLock sync.RWMutex
+)
+
+func findDriverAdapter(tunnelName string) (*lockedDriverAdapter, error) {
+ driverAdaptersLock.RLock()
+ driverAdapter, ok := driverAdapters[tunnelName]
+ if ok {
+ driverAdapter.Lock()
+ driverAdaptersLock.RUnlock()
+ return driverAdapter, nil
+ }
+ driverAdaptersLock.RUnlock()
+ driverAdaptersLock.Lock()
+ defer driverAdaptersLock.Unlock()
+ driverAdapter, ok = driverAdapters[tunnelName]
+ if ok {
+ driverAdapter.Lock()
+ return driverAdapter, nil
+ }
+ driverAdapter = &lockedDriverAdapter{}
+ var err error
+ driverAdapter.Adapter, err = driver.OpenAdapter(tunnelName)
+ if err != nil {
+ return nil, err
+ }
+ driverAdapters[tunnelName] = driverAdapter
+ driverAdapter.Lock()
+ return driverAdapter, nil
+}
+
+func releaseDriverAdapter(tunnelName string) {
+ driverAdaptersLock.Lock()
+ defer driverAdaptersLock.Unlock()
+ driverAdapter, ok := driverAdapters[tunnelName]
+ if !ok {
+ return
+ }
+ driverAdapter.Lock()
+ delete(driverAdapters, tunnelName)
+ driverAdapter.Unlock()
+}
diff --git a/manager/ipc_server.go b/manager/ipc_server.go
index 8ba050f9..e21ffaf0 100644
--- a/manager/ipc_server.go
+++ b/manager/ipc_server.go
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package manager
@@ -20,14 +20,15 @@ import (
"golang.org/x/sys/windows/svc"
"golang.zx2c4.com/wireguard/windows/conf"
- "golang.zx2c4.com/wireguard/windows/services"
"golang.zx2c4.com/wireguard/windows/updater"
)
-var managerServices = make(map[*ManagerService]bool)
-var managerServicesLock sync.RWMutex
-var haveQuit uint32
-var quitManagersChan = make(chan struct{}, 1)
+var (
+ managerServices = make(map[*ManagerService]bool)
+ managerServicesLock sync.RWMutex
+ haveQuit uint32
+ quitManagersChan = make(chan struct{}, 1)
+)
type ManagerService struct {
events *os.File
@@ -51,33 +52,18 @@ func (s *ManagerService) RuntimeConfig(tunnelName string) (*conf.Config, error)
if err != nil {
return nil, err
}
- pipe, err := connectTunnelServicePipe(tunnelName)
- if err != nil {
- return nil, err
- }
- pipe.SetDeadline(time.Now().Add(time.Second * 2))
- _, err = pipe.Write([]byte("get=1\n\n"))
- if err == windows.ERROR_NO_DATA {
- log.Println("IPC pipe closed unexpectedly, so reopening")
- pipe.Unlock()
- disconnectTunnelServicePipe(tunnelName)
- pipe, err = connectTunnelServicePipe(tunnelName)
- if err != nil {
- return nil, err
- }
- pipe.SetDeadline(time.Now().Add(time.Second * 2))
- _, err = pipe.Write([]byte("get=1\n\n"))
- }
+ driverAdapter, err := findDriverAdapter(tunnelName)
if err != nil {
- pipe.Unlock()
- disconnectTunnelServicePipe(tunnelName)
return nil, err
}
- conf, err := conf.FromUAPI(pipe, storedConfig)
- pipe.Unlock()
+ runtimeConfig, err := driverAdapter.Configuration()
if err != nil {
+ driverAdapter.Unlock()
+ releaseDriverAdapter(tunnelName)
return nil, err
}
+ conf := conf.FromDriverConfiguration(runtimeConfig, storedConfig)
+ driverAdapter.Unlock()
if s.elevatedToken == 0 {
conf.Redact()
}
@@ -85,44 +71,47 @@ func (s *ManagerService) RuntimeConfig(tunnelName string) (*conf.Config, error)
}
func (s *ManagerService) Start(tunnelName string) error {
- // TODO: Rather than being lazy and gating this behind a knob (yuck!), we should instead keep track of the routes
- // of each tunnel, and only deactivate in the case of a tunnel with identical routes being added.
- if !conf.AdminBool("MultipleSimultaneousTunnels") {
- trackedTunnelsLock.Lock()
- tt := make([]string, 0, len(trackedTunnels))
- var inTransition string
- for t, state := range trackedTunnels {
- tt = append(tt, t)
- if len(t) > 0 && (state == TunnelStarting || state == TunnelUnknown) {
- inTransition = t
- break
- }
- }
- trackedTunnelsLock.Unlock()
- if len(inTransition) != 0 {
- return fmt.Errorf("Please allow the tunnel ‘%s’ to finish activating", inTransition)
- }
- go func() {
- for _, t := range tt {
- s.Stop(t)
- }
- for _, t := range tt {
- state, err := s.State(t)
- if err == nil && (state == TunnelStarted || state == TunnelStarting) {
- log.Printf("[%s] Trying again to stop zombie tunnel", t)
- s.Stop(t)
- time.Sleep(time.Millisecond * 100)
- }
- }
- }()
- }
- time.AfterFunc(time.Second*10, cleanupStaleWintunInterfaces)
-
- // After that process is started -- it's somewhat asynchronous -- we install the new one.
c, err := conf.LoadFromName(tunnelName)
if err != nil {
return err
}
+
+ // Figure out which tunnels have intersecting addresses/routes and stop those.
+ trackedTunnelsLock.Lock()
+ tt := make([]string, 0, len(trackedTunnels))
+ var inTransition string
+ for t, state := range trackedTunnels {
+ c2, err := conf.LoadFromName(t)
+ if err != nil || !c.IntersectsWith(c2) {
+ // If we can't get the config, assume it doesn't intersect.
+ continue
+ }
+ tt = append(tt, t)
+ if len(t) > 0 && (state == TunnelStarting || state == TunnelUnknown) {
+ inTransition = t
+ break
+ }
+ }
+ trackedTunnelsLock.Unlock()
+ if len(inTransition) != 0 {
+ return fmt.Errorf("Please allow the tunnel ‘%s’ to finish activating", inTransition)
+ }
+
+ // Stop those intersecting tunnels asynchronously.
+ go func() {
+ for _, t := range tt {
+ s.Stop(t)
+ }
+ for _, t := range tt {
+ state, err := s.State(t)
+ if err == nil && (state == TunnelStarted || state == TunnelStarting) {
+ log.Printf("[%s] Trying again to stop zombie tunnel", t)
+ s.Stop(t)
+ time.Sleep(time.Millisecond * 100)
+ }
+ }
+ }()
+ // After the stop process has begun, but before it's finished, we install the new one.
path, err := c.Path()
if err != nil {
return err
@@ -131,8 +120,6 @@ func (s *ManagerService) Start(tunnelName string) error {
}
func (s *ManagerService) Stop(tunnelName string) error {
- time.AfterFunc(time.Second*10, cleanupStaleWintunInterfaces)
-
err := UninstallTunnel(tunnelName)
if err == windows.ERROR_SERVICE_DOES_NOT_EXIST {
_, notExistsError := conf.LoadFromName(tunnelName)
@@ -144,7 +131,7 @@ func (s *ManagerService) Stop(tunnelName string) error {
}
func (s *ManagerService) WaitForStop(tunnelName string) error {
- serviceName, err := services.ServiceNameOfTunnel(tunnelName)
+ serviceName, err := conf.ServiceNameOfTunnel(tunnelName)
if err != nil {
return err
}
@@ -175,7 +162,7 @@ func (s *ManagerService) Delete(tunnelName string) error {
}
func (s *ManagerService) State(tunnelName string) (TunnelState, error) {
- serviceName, err := services.ServiceNameOfTunnel(tunnelName)
+ serviceName, err := conf.ServiceNameOfTunnel(tunnelName)
if err != nil {
return 0, err
}
@@ -230,7 +217,7 @@ func (s *ManagerService) Tunnels() ([]Tunnel, error) {
}
tunnels := make([]Tunnel, len(names))
for i := 0; i < len(tunnels); i++ {
- (tunnels)[i].Name = names[i]
+ tunnels[i].Name = names[i]
}
return tunnels, nil
// TODO: account for running ones that aren't in the configuration store somehow
@@ -267,9 +254,6 @@ func (s *ManagerService) Quit(stopTunnelsOnQuit bool) (alreadyQuit bool, err err
}
func (s *ManagerService) UpdateState() UpdateState {
- if s.elevatedToken == 0 {
- return UpdateStateUnknown
- }
return updateState
}
@@ -457,7 +441,7 @@ func (s *ManagerService) ServeConn(reader io.Reader, writer io.Writer) {
}
}
-func IPCServerListen(reader *os.File, writer *os.File, events *os.File, elevatedToken windows.Token) {
+func IPCServerListen(reader, writer, events *os.File, elevatedToken windows.Token) {
service := &ManagerService{
events: events,
elevatedToken: elevatedToken,
@@ -477,7 +461,7 @@ func IPCServerListen(reader *os.File, writer *os.File, events *os.File, elevated
}()
}
-func notifyAll(notificationType NotificationType, adminOnly bool, ifaces ...interface{}) {
+func notifyAll(notificationType NotificationType, adminOnly bool, ifaces ...any) {
if len(managerServices) == 0 {
return
}
@@ -528,7 +512,7 @@ func IPCServerNotifyTunnelsChange() {
}
func IPCServerNotifyUpdateFound(state UpdateState) {
- notifyAll(UpdateFoundNotificationType, true, state)
+ notifyAll(UpdateFoundNotificationType, false, state)
}
func IPCServerNotifyUpdateProgress(dp updater.DownloadProgress) {
diff --git a/manager/ipc_uapi.go b/manager/ipc_uapi.go
deleted file mode 100644
index 85477125..00000000
--- a/manager/ipc_uapi.go
+++ /dev/null
@@ -1,71 +0,0 @@
-/* SPDX-License-Identifier: MIT
- *
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
- */
-
-package manager
-
-import (
- "net"
- "sync"
-
- "golang.org/x/sys/windows"
- "golang.zx2c4.com/wireguard/ipc/winpipe"
-
- "golang.zx2c4.com/wireguard/windows/services"
-)
-
-type connectedTunnel struct {
- net.Conn
- sync.Mutex
-}
-
-var connectedTunnelServicePipes = make(map[string]*connectedTunnel)
-var connectedTunnelServicePipesLock sync.RWMutex
-
-func connectTunnelServicePipe(tunnelName string) (*connectedTunnel, error) {
- connectedTunnelServicePipesLock.RLock()
- pipe, ok := connectedTunnelServicePipes[tunnelName]
- if ok {
- pipe.Lock()
- connectedTunnelServicePipesLock.RUnlock()
- return pipe, nil
- }
- connectedTunnelServicePipesLock.RUnlock()
- connectedTunnelServicePipesLock.Lock()
- defer connectedTunnelServicePipesLock.Unlock()
- pipe, ok = connectedTunnelServicePipes[tunnelName]
- if ok {
- pipe.Lock()
- return pipe, nil
- }
- pipePath, err := services.PipePathOfTunnel(tunnelName)
- if err != nil {
- return nil, err
- }
- localSystem, err := windows.CreateWellKnownSid(windows.WinLocalSystemSid)
- if err != nil {
- return nil, err
- }
- pipe = &connectedTunnel{}
- pipe.Conn, err = winpipe.Dial(pipePath, nil, &winpipe.DialConfig{ExpectedOwner: localSystem})
- if err != nil {
- return nil, err
- }
- connectedTunnelServicePipes[tunnelName] = pipe
- pipe.Lock()
- return pipe, nil
-}
-
-func disconnectTunnelServicePipe(tunnelName string) {
- connectedTunnelServicePipesLock.Lock()
- defer connectedTunnelServicePipesLock.Unlock()
- pipe, ok := connectedTunnelServicePipes[tunnelName]
- if !ok {
- return
- }
- pipe.Lock()
- pipe.Close()
- delete(connectedTunnelServicePipes, tunnelName)
- pipe.Unlock()
-}
diff --git a/manager/legacystore.go b/manager/legacystore.go
deleted file mode 100644
index 4125cb86..00000000
--- a/manager/legacystore.go
+++ /dev/null
@@ -1,129 +0,0 @@
-/* SPDX-License-Identifier: MIT
- *
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
- */
-
-package manager
-
-import (
- "fmt"
- "log"
- "os"
- "path/filepath"
- "regexp"
- "strings"
-
- "golang.org/x/sys/windows"
- "golang.org/x/sys/windows/registry"
- "golang.org/x/sys/windows/svc/mgr"
-
- "golang.zx2c4.com/wireguard/windows/conf"
-)
-
-func moveConfigsFromLegacyStore() {
- oldRoot, err := windows.KnownFolderPath(windows.FOLDERID_LocalAppData, windows.KF_FLAG_DEFAULT)
- if err != nil {
- return
- }
- oldC := filepath.Join(oldRoot, "WireGuard", "Configurations")
- files, err := os.ReadDir(oldC)
- if err != nil {
- return
- }
- pendingDeletion := make(map[string]bool)
- if key, err := registry.OpenKey(registry.LOCAL_MACHINE, `SYSTEM\CurrentControlSet\Control\Session Manager`, registry.READ); err == nil {
- if ntPaths, _, err := key.GetStringsValue("PendingFileRenameOperations"); err == nil {
- for _, ntPath := range ntPaths {
- pendingDeletion[strings.ToLower(strings.TrimPrefix(ntPath, `\??\`))] = true
- }
- }
- key.Close()
- }
- migratedConfigs := make(map[string]string)
- for i := range files {
- if files[i].IsDir() {
- continue
- }
- fileName := files[i].Name()
- oldPath := filepath.Join(oldC, fileName)
- if pendingDeletion[strings.ToLower(oldPath)] {
- continue
- }
- config, err := conf.LoadFromPath(oldPath)
- if err != nil {
- continue
- }
- newPath, err := config.Path()
- if err != nil {
- continue
- }
- err = config.Save(false)
- if err != nil {
- continue
- }
- oldPath16, err := windows.UTF16PtrFromString(oldPath)
- if err == nil {
- windows.MoveFileEx(oldPath16, nil, windows.MOVEFILE_DELAY_UNTIL_REBOOT)
- }
- migratedConfigs[strings.ToLower(oldPath)] = newPath
- log.Printf("Migrated configuration from ‘%s’ to ‘%s’", oldPath, newPath)
- }
- oldC16, err := windows.UTF16PtrFromString(oldC)
- if err == nil {
- windows.MoveFileEx(oldC16, nil, windows.MOVEFILE_DELAY_UNTIL_REBOOT)
- }
- oldLog16, err := windows.UTF16PtrFromString(filepath.Join(oldRoot, "WireGuard", "log.bin"))
- if err == nil {
- windows.MoveFileEx(oldLog16, nil, windows.MOVEFILE_DELAY_UNTIL_REBOOT)
- }
- oldRoot16, err := windows.UTF16PtrFromString(filepath.Join(oldRoot, "WireGuard"))
- if err == nil {
- windows.MoveFileEx(oldRoot16, nil, windows.MOVEFILE_DELAY_UNTIL_REBOOT)
- }
- if len(migratedConfigs) == 0 {
- return
- }
- m, err := mgr.Connect()
- if err != nil {
- return
- }
- defer m.Disconnect()
- services, err := m.ListServices()
- if err != nil {
- return
- }
- matcher, err := regexp.Compile(" /tunnelservice \"?([^\"]+)\"?$")
- if err != nil {
- return
- }
- for _, svcName := range services {
- if !strings.HasPrefix(svcName, "WireGuardTunnel$") {
- continue
- }
- svc, err := m.OpenService(svcName)
- if err != nil {
- continue
- }
- config, err := svc.Config()
- if err != nil {
- continue
- }
- matches := matcher.FindStringSubmatchIndex(config.BinaryPathName)
- if len(matches) != 4 {
- svc.Close()
- continue
- }
- newName, found := migratedConfigs[strings.ToLower(config.BinaryPathName[matches[2]:])]
- if !found {
- svc.Close()
- continue
- }
- config.BinaryPathName = config.BinaryPathName[:matches[0]] + fmt.Sprintf(" /tunnelservice \"%s\"", newName)
- err = svc.UpdateConfig(config)
- svc.Close()
- if err != nil {
- continue
- }
- log.Printf("Migrated service command line arguments for ‘%s’", svcName)
- }
-}
diff --git a/manager/service.go b/manager/service.go
index 99187eab..47e20d45 100644
--- a/manager/service.go
+++ b/manager/service.go
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package manager
@@ -12,18 +12,17 @@ import (
"runtime"
"strconv"
"sync"
- "syscall"
"time"
"unsafe"
"golang.org/x/sys/windows"
"golang.org/x/sys/windows/svc"
+ "golang.zx2c4.com/wireguard/windows/driver"
"golang.zx2c4.com/wireguard/windows/conf"
"golang.zx2c4.com/wireguard/windows/elevate"
"golang.zx2c4.com/wireguard/windows/ringlogger"
"golang.zx2c4.com/wireguard/windows/services"
- "golang.zx2c4.com/wireguard/windows/version"
)
type managerService struct{}
@@ -43,38 +42,36 @@ func (service *managerService) Execute(args []string, r <-chan svc.ChangeRequest
changes <- svc.Status{State: svc.StopPending}
}()
- err = ringlogger.InitGlobalLogger("MGR")
+ var logFile string
+ logFile, err = conf.LogFile(true)
if err != nil {
serviceError = services.ErrorRingloggerOpen
return
}
-
- log.Println("Starting", version.UserAgent())
-
- path, err := os.Executable()
+ err = ringlogger.InitGlobalLogger(logFile, "MGR")
if err != nil {
- serviceError = services.ErrorDetermineExecutablePath
+ serviceError = services.ErrorRingloggerOpen
return
}
- devNull, err := os.OpenFile(os.DevNull, os.O_RDWR, 0)
+ services.PrintStarting()
+
+ path, err := os.Executable()
if err != nil {
- serviceError = services.ErrorOpenNULFile
+ serviceError = services.ErrorDetermineExecutablePath
return
}
- moveConfigsFromLegacyStore()
-
- err = trackExistingTunnels()
+ err = watchNewTunnelServices()
if err != nil {
serviceError = services.ErrorTrackTunnels
return
}
- conf.RegisterStoreChangeCallback(conf.MigrateUnencryptedConfigs)
+ conf.RegisterStoreChangeCallback(func() { conf.MigrateUnencryptedConfigs(changeTunnelServiceConfigFilePath) })
conf.RegisterStoreChangeCallback(IPCServerNotifyTunnelsChange)
- procs := make(map[uint32]*os.Process)
+ procs := make(map[uint32]*uiProcess)
aliveSessions := make(map[uint32]bool)
procsLock := sync.Mutex{}
stoppingManager := false
@@ -196,29 +193,22 @@ func (service *managerService) Execute(args []string, r <-chan svc.ChangeRequest
}
log.Printf("Starting UI process for user ‘%s@%s’ for session %d", username, domain, session)
- attr := &os.ProcAttr{
- Sys: &syscall.SysProcAttr{
- Token: syscall.Token(runToken),
- AdditionalInheritedHandles: []syscall.Handle{
- syscall.Handle(theirReader.Fd()),
- syscall.Handle(theirWriter.Fd()),
- syscall.Handle(theirEvents.Fd()),
- syscall.Handle(theirLogMapping)},
- },
- Files: []*os.File{devNull, devNull, devNull},
- Dir: userProfileDirectory,
- }
procsLock.Lock()
- var proc *os.Process
+ var proc *uiProcess
if alive := aliveSessions[session]; alive {
- proc, err = os.StartProcess(path, []string{
+ proc, err = launchUIProcess(path, []string{
path,
"/ui",
strconv.FormatUint(uint64(theirReader.Fd()), 10),
strconv.FormatUint(uint64(theirWriter.Fd()), 10),
strconv.FormatUint(uint64(theirEvents.Fd()), 10),
strconv.FormatUint(uint64(theirLogMapping), 10),
- }, attr)
+ }, userProfileDirectory, []windows.Handle{
+ windows.Handle(theirReader.Fd()),
+ windows.Handle(theirWriter.Fd()),
+ windows.Handle(theirEvents.Fd()),
+ theirLogMapping,
+ }, runToken)
} else {
err = errors.New("Session has logged out")
}
@@ -240,9 +230,7 @@ func (service *managerService) Execute(args []string, r <-chan svc.ChangeRequest
procsLock.Unlock()
sessionIsDead := false
- processStatus, err := proc.Wait()
- if err == nil {
- exitCode := processStatus.Sys().(syscall.WaitStatus).ExitCode
+ if exitCode, err := proc.Wait(); err == nil {
log.Printf("Exited UI process for user '%s@%s' for session %d with status %x", username, domain, session, exitCode)
const STATUS_DLL_INIT_FAILED_LOGOFF = 0xC000026B
sessionIsDead = exitCode == STATUS_DLL_INIT_FAILED_LOGOFF
@@ -271,8 +259,8 @@ func (service *managerService) Execute(args []string, r <-chan svc.ChangeRequest
}()
}
- time.AfterFunc(time.Second*10, cleanupStaleWintunInterfaces)
go checkForUpdates()
+ go driver.UninstallLegacyWintun() // We uninstall opportunistically here, so that we don't have to carry around the uninstaller code forever.
var sessionsPointer *windows.WTS_SESSION_INFO
var count uint32
@@ -281,12 +269,7 @@ func (service *managerService) Execute(args []string, r <-chan svc.ChangeRequest
serviceError = services.ErrorEnumerateSessions
return
}
- sessions := *(*[]windows.WTS_SESSION_INFO)(unsafe.Pointer(&struct {
- addr *windows.WTS_SESSION_INFO
- len int
- cap int
- }{sessionsPointer, int(count), int(count)}))
- for _, session := range sessions {
+ for _, session := range unsafe.Slice(sessionsPointer, count) {
if session.State != windows.WTSActive && session.State != windows.WTSDisconnected {
continue
}
diff --git a/manager/tunneltracker.go b/manager/tunneltracker.go
index b32450a3..9003d445 100644
--- a/manager/tunneltracker.go
+++ b/manager/tunneltracker.go
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package manager
@@ -24,31 +24,10 @@ import (
"golang.zx2c4.com/wireguard/windows/services"
)
-func trackExistingTunnels() error {
- m, err := serviceManager()
- if err != nil {
- return err
- }
- names, err := conf.ListConfigNames()
- if err != nil {
- return err
- }
- for _, name := range names {
- serviceName, err := services.ServiceNameOfTunnel(name)
- if err != nil {
- continue
- }
- service, err := m.OpenService(serviceName)
- if err != nil {
- continue
- }
- go trackTunnelService(name, service)
- }
- return nil
-}
-
-var trackedTunnels = make(map[string]TunnelState)
-var trackedTunnelsLock = sync.Mutex{}
+var (
+ trackedTunnels = make(map[string]TunnelState)
+ trackedTunnelsLock = sync.Mutex{}
+)
func trackedTunnelsGlobalState() (state TunnelState) {
state = TunnelStopped
@@ -196,16 +175,17 @@ func trackService(service *mgr.Service, callback func(status uint32) bool) error
}
func trackTunnelService(tunnelName string, service *mgr.Service) {
- defer func() {
- service.Close()
- log.Printf("[%s] Tunnel service tracker finished", tunnelName)
- }()
-
trackedTunnelsLock.Lock()
if _, found := trackedTunnels[tunnelName]; found {
trackedTunnelsLock.Unlock()
+ service.Close()
return
}
+
+ defer func() {
+ service.Close()
+ log.Printf("[%s] Tunnel service tracker finished", tunnelName)
+ }()
trackedTunnels[tunnelName] = TunnelUnknown
trackedTunnelsLock.Unlock()
defer func() {
@@ -214,6 +194,15 @@ func trackTunnelService(tunnelName string, service *mgr.Service) {
trackedTunnelsLock.Unlock()
}()
+ for i := 0; i < 20; i++ {
+ if i > 0 {
+ time.Sleep(time.Second / 5)
+ }
+ if status, err := service.Query(); err != nil || status.State != svc.Stopped {
+ break
+ }
+ }
+
checkForDisabled := func() (shouldReturn bool) {
config, err := service.Config()
if err == windows.ERROR_SERVICE_MARKED_FOR_DELETE || (err != nil && config.StartType == windows.SERVICE_DISABLED) {
@@ -273,5 +262,82 @@ func trackTunnelService(tunnelName string, service *mgr.Service) {
IPCServerNotifyTunnelChange(tunnelName, TunnelStopped, fmt.Errorf("Unable to continue monitoring service, so stopping: %w", err))
service.Control(svc.Stop)
}
- disconnectTunnelServicePipe(tunnelName)
+}
+
+func trackExistingTunnels() error {
+ m, err := serviceManager()
+ if err != nil {
+ return err
+ }
+ names, err := conf.ListConfigNames()
+ if err != nil {
+ return err
+ }
+ for _, name := range names {
+ trackedTunnelsLock.Lock()
+ if _, found := trackedTunnels[name]; found {
+ trackedTunnelsLock.Unlock()
+ continue
+ }
+ trackedTunnelsLock.Unlock()
+ serviceName, err := conf.ServiceNameOfTunnel(name)
+ if err != nil {
+ continue
+ }
+ service, err := m.OpenService(serviceName)
+ if err != nil {
+ continue
+ }
+ go trackTunnelService(name, service)
+ }
+ return nil
+}
+
+var servicesSubscriptionWatcherCallbackPtr = windows.NewCallback(func(notification uint32, context uintptr) uintptr {
+ trackExistingTunnels()
+ return 0
+})
+
+func watchNewTunnelServices() error {
+ m, err := serviceManager()
+ if err != nil {
+ return err
+ }
+ var subscription uintptr
+ err = windows.SubscribeServiceChangeNotifications(m.Handle, windows.SC_EVENT_DATABASE_CHANGE, servicesSubscriptionWatcherCallbackPtr, 0, &subscription)
+ if err == nil {
+ // We probably could do:
+ // defer windows.UnsubscribeServiceChangeNotifications(subscription)
+ // and then terminate after some point, but instead we just let this go forever; it's process-lived.
+ return trackExistingTunnels()
+ }
+ if !errors.Is(err, windows.ERROR_PROC_NOT_FOUND) {
+ return err
+ }
+
+ // TODO: Below this line is Windows 7 compatibility code, which hopefully we can delete at some point.
+ go func() {
+ runtime.LockOSThread()
+ notifier := &windows.SERVICE_NOTIFY{
+ Version: windows.SERVICE_NOTIFY_STATUS_CHANGE,
+ NotifyCallback: serviceTrackerCallbackPtr,
+ }
+ for {
+ err := windows.NotifyServiceStatusChange(m.Handle, windows.SERVICE_NOTIFY_CREATED, notifier)
+ if err == nil {
+ windows.SleepEx(windows.INFINITE, true)
+ if notifier.ServiceNames != nil {
+ windows.LocalFree(windows.Handle(unsafe.Pointer(notifier.ServiceNames)))
+ notifier.ServiceNames = nil
+ }
+ trackExistingTunnels()
+ } else if err == windows.ERROR_SERVICE_NOTIFY_CLIENT_LAGGING {
+ continue
+ } else {
+ time.Sleep(time.Second * 3)
+ trackExistingTunnels()
+ }
+ }
+ }()
+ return trackExistingTunnels()
}
diff --git a/manager/uiprocess.go b/manager/uiprocess.go
new file mode 100644
index 00000000..b33b1ad3
--- /dev/null
+++ b/manager/uiprocess.go
@@ -0,0 +1,103 @@
+/* SPDX-License-Identifier: MIT
+ *
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
+ */
+
+package manager
+
+import (
+ "errors"
+ "runtime"
+ "sync/atomic"
+ "syscall"
+ "unsafe"
+
+ "golang.org/x/sys/windows"
+)
+
+type uiProcess struct {
+ handle uintptr
+}
+
+func launchUIProcess(executable string, args []string, workingDirectory string, handles []windows.Handle, token windows.Token) (*uiProcess, error) {
+ executable16, err := windows.UTF16PtrFromString(executable)
+ if err != nil {
+ return nil, err
+ }
+ args16, err := windows.UTF16PtrFromString(windows.ComposeCommandLine(args))
+ if err != nil {
+ return nil, err
+ }
+ workingDirectory16, err := windows.UTF16PtrFromString(workingDirectory)
+ if err != nil {
+ return nil, err
+ }
+ var environmentBlock *uint16
+ err = windows.CreateEnvironmentBlock(&environmentBlock, token, false)
+ if err != nil {
+ return nil, err
+ }
+ defer windows.DestroyEnvironmentBlock(environmentBlock)
+ attributeList, err := windows.NewProcThreadAttributeList(1)
+ if err != nil {
+ return nil, err
+ }
+ defer attributeList.Delete()
+ si := &windows.StartupInfoEx{
+ StartupInfo: windows.StartupInfo{Cb: uint32(unsafe.Sizeof(windows.StartupInfoEx{}))},
+ ProcThreadAttributeList: attributeList.List(),
+ }
+ if len(handles) == 0 {
+ handles = []windows.Handle{0}
+ }
+ attributeList.Update(windows.PROC_THREAD_ATTRIBUTE_HANDLE_LIST, unsafe.Pointer(&handles[0]), uintptr(len(handles))*unsafe.Sizeof(handles[0]))
+ pi := new(windows.ProcessInformation)
+ err = windows.CreateProcessAsUser(token, executable16, args16, nil, nil, true, windows.CREATE_DEFAULT_ERROR_MODE|windows.CREATE_UNICODE_ENVIRONMENT|windows.EXTENDED_STARTUPINFO_PRESENT, environmentBlock, workingDirectory16, &si.StartupInfo, pi)
+ if err != nil {
+ return nil, err
+ }
+ windows.CloseHandle(pi.Thread)
+ uiProc := &uiProcess{handle: uintptr(pi.Process)}
+ runtime.SetFinalizer(uiProc, (*uiProcess).release)
+ return uiProc, nil
+}
+
+func (p *uiProcess) release() error {
+ handle := windows.Handle(atomic.SwapUintptr(&p.handle, uintptr(windows.InvalidHandle)))
+ if handle == windows.InvalidHandle {
+ return nil
+ }
+ err := windows.CloseHandle(handle)
+ if err != nil {
+ return err
+ }
+ runtime.SetFinalizer(p, nil)
+ return nil
+}
+
+func (p *uiProcess) Wait() (uint32, error) {
+ handle := windows.Handle(atomic.LoadUintptr(&p.handle))
+ s, err := windows.WaitForSingleObject(handle, syscall.INFINITE)
+ switch s {
+ case windows.WAIT_OBJECT_0:
+ case windows.WAIT_FAILED:
+ return 0, err
+ default:
+ return 0, errors.New("unexpected result from WaitForSingleObject")
+ }
+ var exitCode uint32
+ err = windows.GetExitCodeProcess(handle, &exitCode)
+ if err != nil {
+ return 0, err
+ }
+ p.release()
+ return exitCode, nil
+}
+
+func (p *uiProcess) Kill() error {
+ handle := windows.Handle(atomic.LoadUintptr(&p.handle))
+ if handle == windows.InvalidHandle {
+ return nil
+ }
+ return windows.TerminateProcess(handle, 1)
+}
diff --git a/manager/updatestate.go b/manager/updatestate.go
index 069e9b8a..d5a19c8d 100644
--- a/manager/updatestate.go
+++ b/manager/updatestate.go
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package manager
@@ -8,11 +8,16 @@ package manager
import (
"log"
"time"
+ _ "unsafe"
+ "golang.zx2c4.com/wireguard/windows/services"
"golang.zx2c4.com/wireguard/windows/updater"
"golang.zx2c4.com/wireguard/windows/version"
)
+//go:linkname fastrandn runtime.fastrandn
+func fastrandn(n uint32) uint32
+
type UpdateState uint32
const (
@@ -23,6 +28,10 @@ const (
var updateState = UpdateStateUnknown
+func jitterSleep(min, max time.Duration) {
+ time.Sleep(min + time.Millisecond*time.Duration(fastrandn(uint32((max-min+1)/time.Millisecond))))
+}
+
func checkForUpdates() {
if !version.IsRunningOfficialVersion() {
log.Println("Build is not official, so updates are disabled")
@@ -30,26 +39,27 @@ func checkForUpdates() {
IPCServerNotifyUpdateFound(updateState)
return
}
-
- first := true
+ if services.StartedAtBoot() {
+ jitterSleep(time.Minute*2, time.Minute*5)
+ }
+ noError, didNotify := true, false
for {
update, err := updater.CheckForUpdate()
- if err == nil && update != nil {
+ if err == nil && update != nil && !didNotify {
log.Println("An update is available")
updateState = UpdateStateFoundUpdate
IPCServerNotifyUpdateFound(updateState)
- return
- }
- if err != nil {
+ didNotify = true
+ } else if err != nil && !didNotify {
log.Printf("Update checker: %v", err)
- if first {
- time.Sleep(time.Minute * 4)
- first = false
+ if noError {
+ jitterSleep(time.Minute*4, time.Minute*6)
+ noError = false
} else {
- time.Sleep(time.Minute * 25)
+ jitterSleep(time.Minute*25, time.Minute*30)
}
} else {
- time.Sleep(time.Hour)
+ jitterSleep(time.Hour-time.Minute*3, time.Hour+time.Minute*3)
}
}
}
diff --git a/quickinstall.bat b/quickinstall.bat
index 95157bbd..47d66a30 100644
--- a/quickinstall.bat
+++ b/quickinstall.bat
@@ -1,6 +1,6 @@
@echo off
rem SPDX-License-Identifier: MIT
-rem Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+rem Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
setlocal
cd /d %~dp0 || exit /b 1
diff --git a/resources.rc b/resources.rc
index 464492c0..0601d938 100644
--- a/resources.rc
+++ b/resources.rc
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
#include <windows.h>
@@ -14,7 +14,7 @@ LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST manifest.xml
7 ICON ui/icon/wireguard.ico
8 ICON ui/icon/dot.ico
-wintun.dll RCDATA wintun.dll
+wireguard.dll RCDATA wireguard.dll
#define VERSIONINFO_TEMPLATE(block_id, lang_id, codepage_id, file_desc, comments) \
VS_VERSION_INFO VERSIONINFO \
@@ -32,7 +32,7 @@ BEGIN \
VALUE "FileDescription", file_desc \
VALUE "FileVersion", EXPAND(WIREGUARD_VERSION_STR) \
VALUE "InternalName", "wireguard-windows" \
- VALUE "LegalCopyright", "Copyright © 2015-2021 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved." \
+ VALUE "LegalCopyright", "Copyright © 2015-2022 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved." \
VALUE "OriginalFilename", "wireguard.exe" \
VALUE "ProductName", "WireGuard" \
VALUE "ProductVersion", EXPAND(WIREGUARD_VERSION_STR) \
diff --git a/ringlogger/cli_test.go b/ringlogger/cli_test.go
index 960fe547..12541c81 100644
--- a/ringlogger/cli_test.go
+++ b/ringlogger/cli_test.go
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package ringlogger
diff --git a/ringlogger/dump.go b/ringlogger/dump.go
index 8b5651e3..3c089751 100644
--- a/ringlogger/dump.go
+++ b/ringlogger/dump.go
@@ -1,27 +1,22 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package ringlogger
import (
+ "errors"
+ "fmt"
"io"
"os"
- "path/filepath"
+ "time"
"golang.org/x/sys/windows"
-
- "golang.zx2c4.com/wireguard/windows/conf"
)
-func DumpTo(out io.Writer, notSystem bool) error {
- root, err := conf.RootDirectory(!notSystem)
- if err != nil {
- return err
- }
- path := filepath.Join(root, "log.bin")
- file, err := os.Open(path)
+func DumpTo(inPath string, out io.Writer, continuous bool) error {
+ file, err := os.Open(inPath)
if err != nil {
return err
}
@@ -36,9 +31,26 @@ func DumpTo(out io.Writer, notSystem bool) error {
return err
}
defer rl.Close()
- _, err = rl.WriteTo(out)
- if err != nil {
- return err
+ if !continuous {
+ _, err = rl.WriteTo(out)
+ if err != nil {
+ return err
+ }
+ } else {
+ cursor := CursorAll
+ for {
+ var items []FollowLine
+ items, cursor = rl.FollowFromCursor(cursor)
+ for _, item := range items {
+ _, err = fmt.Fprintf(out, "%s: %s\n", item.Stamp.Format("2006-01-02 15:04:05.000000"), item.Line)
+ if errors.Is(err, io.EOF) {
+ return nil
+ } else if err != nil {
+ return err
+ }
+ }
+ time.Sleep(time.Millisecond * 100)
+ }
}
return nil
}
diff --git a/ringlogger/global.go b/ringlogger/global.go
index 4213e2f1..5c522a70 100644
--- a/ringlogger/global.go
+++ b/ringlogger/global.go
@@ -1,29 +1,23 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package ringlogger
import (
"log"
- "path/filepath"
"unsafe"
-
- "golang.zx2c4.com/wireguard/windows/conf"
)
var Global *Ringlogger
-func InitGlobalLogger(tag string) error {
+func InitGlobalLogger(file, tag string) error {
if Global != nil {
return nil
}
- root, err := conf.RootDirectory(true)
- if err != nil {
- return err
- }
- Global, err = NewRinglogger(filepath.Join(root, "log.bin"), tag)
+ var err error
+ Global, err = NewRinglogger(file, tag)
if err != nil {
return err
}
@@ -36,8 +30,10 @@ func InitGlobalLogger(tag string) error {
//go:linkname overrideWrite runtime.overrideWrite
var overrideWrite func(fd uintptr, p unsafe.Pointer, n int32) int32
-var globalBuffer [maxLogLineLength - 1 - maxTagLength - 3]byte
-var globalBufferLocation int
+var (
+ globalBuffer [maxLogLineLength - 1 - maxTagLength - 3]byte
+ globalBufferLocation int
+)
//go:nosplit
func globalWrite(fd uintptr, p unsafe.Pointer, n int32) int32 {
diff --git a/ringlogger/ringlogger.go b/ringlogger/ringlogger.go
index 2d7c0c8f..e932f88c 100644
--- a/ringlogger/ringlogger.go
+++ b/ringlogger/ringlogger.go
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package ringlogger
@@ -45,11 +45,11 @@ type Ringlogger struct {
readOnly bool
}
-func NewRinglogger(filename string, tag string) (*Ringlogger, error) {
+func NewRinglogger(filename, tag string) (*Ringlogger, error) {
if len(tag) > maxTagLength {
return nil, windows.ERROR_LABEL_TOO_LONG
}
- file, err := os.OpenFile(filename, os.O_RDWR|os.O_CREATE, 0600)
+ file, err := os.OpenFile(filename, os.O_RDWR|os.O_CREATE, 0o600)
if err != nil {
return nil, err
}
@@ -63,13 +63,14 @@ func NewRinglogger(filename string, tag string) (*Ringlogger, error) {
}
rl, err := newRingloggerFromMappingHandle(mapping, tag, windows.FILE_MAP_WRITE)
if err != nil {
+ windows.CloseHandle(mapping)
return nil, err
}
rl.file = file
return rl, nil
}
-func NewRingloggerFromInheritedMappingHandle(handleStr string, tag string) (*Ringlogger, error) {
+func NewRingloggerFromInheritedMappingHandle(handleStr, tag string) (*Ringlogger, error) {
handle, err := strconv.ParseUint(handleStr, 10, 64)
if err != nil {
return nil, err
@@ -82,10 +83,6 @@ func newRingloggerFromMappingHandle(mappingHandle windows.Handle, tag string, ac
if err != nil {
return nil, err
}
- if err != nil {
- windows.CloseHandle(mappingHandle)
- return nil, err
- }
log := (*logMem)(unsafe.Pointer(view))
if log.magic != magic {
bytes := (*[unsafe.Sizeof(logMem{})]byte)(unsafe.Pointer(log))
@@ -107,6 +104,12 @@ func newRingloggerFromMappingHandle(mappingHandle windows.Handle, tag string, ac
}
func (rl *Ringlogger) Write(p []byte) (n int, err error) {
+ // Race: This isn't synchronized with the fetch_add below, so items might be slightly out of order.
+ ts := time.Now().UnixNano()
+ return rl.WriteWithTimestamp(p, ts)
+}
+
+func (rl *Ringlogger) WriteWithTimestamp(p []byte, ts int64) (n int, err error) {
if rl.readOnly {
return 0, io.ErrShortWrite
}
@@ -116,9 +119,6 @@ func (rl *Ringlogger) Write(p []byte) (n int, err error) {
return ret, nil
}
- // Race: This isn't synchronized with the fetch_add below, so items might be slightly out of order.
- ts := time.Now().UnixNano()
-
if rl.log == nil {
return 0, io.EOF
}
@@ -136,7 +136,7 @@ func (rl *Ringlogger) Write(p []byte) (n int, err error) {
textLen := 3 + len(p) + len(rl.tag)
if textLen > maxLogLineLength-1 {
p = p[:maxLogLineLength-1-3-len(rl.tag)]
- textLen = maxLogLineLength-1
+ textLen = maxLogLineLength - 1
}
line.line[textLen] = 0
line.line[0] = 0 // Null out the beginning and only let it extend after the other writes have completed
diff --git a/services/boot.go b/services/boot.go
new file mode 100644
index 00000000..ae7aadda
--- /dev/null
+++ b/services/boot.go
@@ -0,0 +1,47 @@
+/* SPDX-License-Identifier: MIT
+ *
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
+ */
+
+package services
+
+import (
+ "errors"
+ "log"
+ "sync"
+ "time"
+
+ "golang.org/x/sys/windows"
+ "golang.org/x/sys/windows/svc"
+ "golang.zx2c4.com/wireguard/windows/version"
+)
+
+var (
+ startedAtBoot bool
+ startedAtBootOnce sync.Once
+)
+
+func StartedAtBoot() bool {
+ startedAtBootOnce.Do(func() {
+ if isService, err := svc.IsWindowsService(); err == nil && !isService {
+ return
+ }
+ if reason, err := svc.DynamicStartReason(); err == nil {
+ startedAtBoot = (reason&svc.StartReasonAuto) != 0 || (reason&svc.StartReasonDelayedAuto) != 0
+ } else if errors.Is(err, windows.ERROR_PROC_NOT_FOUND) {
+ // TODO: Below this line is Windows 7 compatibility code, which hopefully we can delete at some point.
+ startedAtBoot = windows.DurationSinceBoot() < time.Minute*10
+ } else {
+ log.Printf("Unable to determine service start reason: %v", err)
+ }
+ })
+ return startedAtBoot
+}
+
+func PrintStarting() {
+ boot := ""
+ if StartedAtBoot() {
+ boot = " at boot"
+ }
+ log.Printf("Starting%s %s", boot, version.UserAgent())
+}
diff --git a/services/errors.go b/services/errors.go
index e17cad88..c0588494 100644
--- a/services/errors.go
+++ b/services/errors.go
@@ -1,13 +1,12 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package services
import (
"fmt"
- "syscall"
"golang.org/x/sys/windows"
)
@@ -18,15 +17,15 @@ const (
ErrorSuccess Error = iota
ErrorRingloggerOpen
ErrorLoadConfiguration
- ErrorCreateWintun
- ErrorUAPIListen
+ ErrorCreateNetworkAdapter
ErrorDNSLookup
ErrorFirewall
ErrorDeviceSetConfig
+ ErrorDeviceBringUp
ErrorBindSocketsToDefaultRoutes
+ ErrorMonitorMTUChanges
ErrorSetNetConfig
ErrorDetermineExecutablePath
- ErrorOpenNULFile
ErrorTrackTunnels
ErrorEnumerateSessions
ErrorDropPrivileges
@@ -44,22 +43,22 @@ func (e Error) Error() string {
return "Unable to determine path of running executable"
case ErrorLoadConfiguration:
return "Unable to load configuration from path"
- case ErrorCreateWintun:
- return "Unable to create Wintun interface"
- case ErrorUAPIListen:
- return "Unable to listen on named pipe"
+ case ErrorCreateNetworkAdapter:
+ return "Unable to create network adapter"
case ErrorDNSLookup:
return "Unable to resolve one or more DNS hostname endpoints"
case ErrorFirewall:
return "Unable to enable firewall rules"
case ErrorDeviceSetConfig:
return "Unable to set device configuration"
+ case ErrorDeviceBringUp:
+ return "Unable to bring up adapter"
case ErrorBindSocketsToDefaultRoutes:
return "Unable to bind sockets to default route"
+ case ErrorMonitorMTUChanges:
+ return "Unable to monitor default route MTU for changes"
case ErrorSetNetConfig:
- return "Unable to set interface addresses, routes, dns, and/or interface settings"
- case ErrorOpenNULFile:
- return "Unable to open NUL file"
+ return "Unable to configure adapter network settings"
case ErrorTrackTunnels:
return "Unable to track existing tunnels"
case ErrorEnumerateSessions:
@@ -76,7 +75,7 @@ func (e Error) Error() string {
}
func DetermineErrorCode(err error, serviceError Error) (bool, uint32) {
- if syserr, ok := err.(syscall.Errno); ok {
+ if syserr, ok := err.(windows.Errno); ok {
return false, uint32(syserr)
} else if serviceError != ErrorSuccess {
return true, uint32(serviceError)
diff --git a/services/names.go b/services/names.go
deleted file mode 100644
index 2b9c1d64..00000000
--- a/services/names.go
+++ /dev/null
@@ -1,26 +0,0 @@
-/* SPDX-License-Identifier: MIT
- *
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
- */
-
-package services
-
-import (
- "errors"
-
- "golang.zx2c4.com/wireguard/windows/conf"
-)
-
-func ServiceNameOfTunnel(tunnelName string) (string, error) {
- if !conf.TunnelNameIsValid(tunnelName) {
- return "", errors.New("Tunnel name is not valid")
- }
- return "WireGuardTunnel$" + tunnelName, nil
-}
-
-func PipePathOfTunnel(tunnelName string) (string, error) {
- if !conf.TunnelNameIsValid(tunnelName) {
- return "", errors.New("Tunnel name is not valid")
- }
- return `\\.\pipe\ProtectedPrefix\Administrators\WireGuard\` + tunnelName, nil
-}
diff --git a/tunnel/addressconfig.go b/tunnel/addressconfig.go
index 44bfd8ae..a3ce6295 100644
--- a/tunnel/addressconfig.go
+++ b/tunnel/addressconfig.go
@@ -1,42 +1,30 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package tunnel
import (
- "bytes"
+ "fmt"
"log"
- "net"
- "sort"
+ "net/netip"
+ "time"
"golang.org/x/sys/windows"
- "golang.zx2c4.com/wireguard/tun"
-
"golang.zx2c4.com/wireguard/windows/conf"
+ "golang.zx2c4.com/wireguard/windows/services"
"golang.zx2c4.com/wireguard/windows/tunnel/firewall"
"golang.zx2c4.com/wireguard/windows/tunnel/winipcfg"
)
-func cleanupAddressesOnDisconnectedInterfaces(family winipcfg.AddressFamily, addresses []net.IPNet) {
+func cleanupAddressesOnDisconnectedInterfaces(family winipcfg.AddressFamily, addresses []netip.Prefix) {
if len(addresses) == 0 {
return
}
- includedInAddresses := func(a net.IPNet) bool {
- // TODO: this makes the whole algorithm O(n^2). But we can't stick net.IPNet in a Go hashmap. Bummer!
- for _, addr := range addresses {
- ip := addr.IP
- if ip4 := ip.To4(); ip4 != nil {
- ip = ip4
- }
- mA, _ := addr.Mask.Size()
- mB, _ := a.Mask.Size()
- if bytes.Equal(ip, a.IP) && mA == mB {
- return true
- }
- }
- return false
+ addrHash := make(map[netip.Addr]bool, len(addresses))
+ for i := range addresses {
+ addrHash[addresses[i].Addr()] = true
}
interfaces, err := winipcfg.GetAdaptersAddresses(family, winipcfg.GAAFlagDefault)
if err != nil {
@@ -47,147 +35,124 @@ func cleanupAddressesOnDisconnectedInterfaces(family winipcfg.AddressFamily, add
continue
}
for address := iface.FirstUnicastAddress; address != nil; address = address.Next {
- ip := address.Address.IP()
- ipnet := net.IPNet{IP: ip, Mask: net.CIDRMask(int(address.OnLinkPrefixLength), 8*len(ip))}
- if includedInAddresses(ipnet) {
- log.Printf("Cleaning up stale address %s from interface ‘%s’", ipnet.String(), iface.FriendlyName())
- iface.LUID.DeleteIPAddress(ipnet)
+ if ip, _ := netip.AddrFromSlice(address.Address.IP()); addrHash[ip] {
+ prefix := netip.PrefixFrom(ip, int(address.OnLinkPrefixLength))
+ log.Printf("Cleaning up stale address %s from interface ‘%s’", prefix.String(), iface.FriendlyName())
+ iface.LUID.DeleteIPAddress(prefix)
}
}
}
}
-func configureInterface(family winipcfg.AddressFamily, conf *conf.Config, tun *tun.NativeTun) error {
- luid := winipcfg.LUID(tun.LUID())
+func configureInterface(family winipcfg.AddressFamily, conf *conf.Config, luid winipcfg.LUID) error {
+ retryOnFailure := services.StartedAtBoot()
+ tryTimes := 0
+startOver:
+ var err error
+ if tryTimes > 0 {
+ log.Printf("Retrying interface configuration after failure because system just booted (T+%v): %v", windows.DurationSinceBoot(), err)
+ time.Sleep(time.Second)
+ retryOnFailure = retryOnFailure && tryTimes < 15
+ }
+ tryTimes++
estimatedRouteCount := 0
for _, peer := range conf.Peers {
estimatedRouteCount += len(peer.AllowedIPs)
}
- routes := make([]winipcfg.RouteData, 0, estimatedRouteCount)
- addresses := make([]net.IPNet, len(conf.Interface.Addresses))
- var haveV4Address, haveV6Address bool
- for i, addr := range conf.Interface.Addresses {
- addresses[i] = addr.IPNet()
- if addr.Bits() == 32 {
- haveV4Address = true
- } else if addr.Bits() == 128 {
- haveV6Address = true
- }
- }
+ routes := make(map[winipcfg.RouteData]bool, estimatedRouteCount)
foundDefault4 := false
foundDefault6 := false
for _, peer := range conf.Peers {
for _, allowedip := range peer.AllowedIPs {
- allowedip.MaskSelf()
- if (allowedip.Bits() == 32 && !haveV4Address) || (allowedip.Bits() == 128 && !haveV6Address) {
- continue
- }
route := winipcfg.RouteData{
- Destination: allowedip.IPNet(),
+ Destination: allowedip.Masked(),
Metric: 0,
}
- if allowedip.Bits() == 32 {
- if allowedip.Cidr == 0 {
+ if allowedip.Addr().Is4() {
+ if allowedip.Bits() == 0 {
foundDefault4 = true
}
- route.NextHop = net.IPv4zero
- } else if allowedip.Bits() == 128 {
- if allowedip.Cidr == 0 {
+ route.NextHop = netip.IPv4Unspecified()
+ } else if allowedip.Addr().Is6() {
+ if allowedip.Bits() == 0 {
foundDefault6 = true
}
- route.NextHop = net.IPv6zero
+ route.NextHop = netip.IPv6Unspecified()
}
- routes = append(routes, route)
+ routes[route] = true
}
}
- err := luid.SetIPAddressesForFamily(family, addresses)
- if err == windows.ERROR_OBJECT_ALREADY_EXISTS {
- cleanupAddressesOnDisconnectedInterfaces(family, addresses)
- err = luid.SetIPAddressesForFamily(family, addresses)
- }
- if err != nil {
- return err
+ deduplicatedRoutes := make([]*winipcfg.RouteData, 0, len(routes))
+ for route := range routes {
+ r := route
+ deduplicatedRoutes = append(deduplicatedRoutes, &r)
}
- deduplicatedRoutes := make([]*winipcfg.RouteData, 0, len(routes))
- sort.Slice(routes, func(i, j int) bool {
- if routes[i].Metric != routes[j].Metric {
- return routes[i].Metric < routes[j].Metric
- }
- if c := bytes.Compare(routes[i].NextHop, routes[j].NextHop); c != 0 {
- return c < 0
+ if !conf.Interface.TableOff {
+ err = luid.SetRoutesForFamily(family, deduplicatedRoutes)
+ if err == windows.ERROR_NOT_FOUND && retryOnFailure {
+ goto startOver
+ } else if err != nil {
+ return fmt.Errorf("unable to set routes: %w", err)
}
- if c := bytes.Compare(routes[i].Destination.IP, routes[j].Destination.IP); c != 0 {
- return c < 0
- }
- if c := bytes.Compare(routes[i].Destination.Mask, routes[j].Destination.Mask); c != 0 {
- return c < 0
- }
- return false
- })
- for i := 0; i < len(routes); i++ {
- if i > 0 && routes[i].Metric == routes[i-1].Metric &&
- bytes.Equal(routes[i].NextHop, routes[i-1].NextHop) &&
- bytes.Equal(routes[i].Destination.IP, routes[i-1].Destination.IP) &&
- bytes.Equal(routes[i].Destination.Mask, routes[i-1].Destination.Mask) {
- continue
- }
- deduplicatedRoutes = append(deduplicatedRoutes, &routes[i])
}
- err = luid.SetRoutesForFamily(family, deduplicatedRoutes)
- if err != nil {
- return err
+ err = luid.SetIPAddressesForFamily(family, conf.Interface.Addresses)
+ if err == windows.ERROR_OBJECT_ALREADY_EXISTS {
+ cleanupAddressesOnDisconnectedInterfaces(family, conf.Interface.Addresses)
+ err = luid.SetIPAddressesForFamily(family, conf.Interface.Addresses)
+ }
+ if err == windows.ERROR_NOT_FOUND && retryOnFailure {
+ goto startOver
+ } else if err != nil {
+ return fmt.Errorf("unable to set ips: %w", err)
}
- ipif, err := luid.IPInterface(family)
+ var ipif *winipcfg.MibIPInterfaceRow
+ ipif, err = luid.IPInterface(family)
if err != nil {
return err
}
+ ipif.RouterDiscoveryBehavior = winipcfg.RouterDiscoveryDisabled
+ ipif.DadTransmits = 0
+ ipif.ManagedAddressConfigurationSupported = false
+ ipif.OtherStatefulConfigurationSupported = false
if conf.Interface.MTU > 0 {
ipif.NLMTU = uint32(conf.Interface.MTU)
- tun.ForceMTU(int(ipif.NLMTU))
}
- if family == windows.AF_INET {
- if foundDefault4 {
- ipif.UseAutomaticMetric = false
- ipif.Metric = 0
- }
- } else if family == windows.AF_INET6 {
- if foundDefault6 {
- ipif.UseAutomaticMetric = false
- ipif.Metric = 0
- }
- ipif.DadTransmits = 0
- ipif.RouterDiscoveryBehavior = winipcfg.RouterDiscoveryDisabled
+ if (family == windows.AF_INET && foundDefault4) || (family == windows.AF_INET6 && foundDefault6) {
+ ipif.UseAutomaticMetric = false
+ ipif.Metric = 0
}
err = ipif.Set()
- if err != nil {
- return err
+ if err == windows.ERROR_NOT_FOUND && retryOnFailure {
+ goto startOver
+ } else if err != nil {
+ return fmt.Errorf("unable to set metric and MTU: %w", err)
}
- return luid.SetDNS(family, conf.Interface.DNS, conf.Interface.DNSSearch)
+ err = luid.SetDNS(family, conf.Interface.DNS, conf.Interface.DNSSearch)
+ if err == windows.ERROR_NOT_FOUND && retryOnFailure {
+ goto startOver
+ } else if err != nil {
+ return fmt.Errorf("unable to set DNS: %w", err)
+ }
+ return nil
}
-func enableFirewall(conf *conf.Config, tun *tun.NativeTun) error {
+func enableFirewall(conf *conf.Config, luid winipcfg.LUID) error {
doNotRestrict := true
- if len(conf.Peers) == 1 {
- nextallowedip:
+ if len(conf.Peers) == 1 && !conf.Interface.TableOff {
for _, allowedip := range conf.Peers[0].AllowedIPs {
- if allowedip.Cidr == 0 {
- for _, b := range allowedip.IP {
- if b != 0 {
- continue nextallowedip
- }
- }
+ if allowedip.Bits() == 0 && allowedip == allowedip.Masked() {
doNotRestrict = false
break
}
}
}
log.Println("Enabling firewall rules")
- return firewall.EnableFirewall(tun.LUID(), doNotRestrict, conf.Interface.DNS)
+ return firewall.EnableFirewall(uint64(luid), doNotRestrict, conf.Interface.DNS)
}
diff --git a/tunnel/deterministicguid.go b/tunnel/deterministicguid.go
index 455deaeb..405d33a3 100644
--- a/tunnel/deterministicguid.go
+++ b/tunnel/deterministicguid.go
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package tunnel
@@ -18,8 +18,10 @@ import (
"golang.zx2c4.com/wireguard/windows/conf"
)
-const deterministicGUIDLabel = "Deterministic WireGuard Windows GUID v1 jason@zx2c4.com"
-const fixedGUIDLabel = "Fixed WireGuard Windows GUID v1 jason@zx2c4.com"
+const (
+ deterministicGUIDLabel = "Deterministic WireGuard Windows GUID v1 jason@zx2c4.com"
+ fixedGUIDLabel = "Fixed WireGuard Windows GUID v1 jason@zx2c4.com"
+)
// Escape hatch for external consumers, not us.
var UseFixedGUIDInsteadOfDeterministic = false
@@ -80,13 +82,13 @@ func deterministicGUID(c *conf.Config) *windows.GUID {
b2Number(len(peer.AllowedIPs))
sortedAllowedIPs := peer.AllowedIPs
sort.Slice(sortedAllowedIPs, func(i, j int) bool {
- if bi, bj := sortedAllowedIPs[i].Bits(), sortedAllowedIPs[j].Bits(); bi != bj {
+ if bi, bj := sortedAllowedIPs[i].Addr().BitLen(), sortedAllowedIPs[j].Addr().BitLen(); bi != bj {
return bi < bj
}
- if sortedAllowedIPs[i].Cidr != sortedAllowedIPs[j].Cidr {
- return sortedAllowedIPs[i].Cidr < sortedAllowedIPs[j].Cidr
+ if sortedAllowedIPs[i].Bits() != sortedAllowedIPs[j].Bits() {
+ return sortedAllowedIPs[i].Bits() < sortedAllowedIPs[j].Bits()
}
- return bytes.Compare(sortedAllowedIPs[i].IP[:], sortedAllowedIPs[j].IP[:]) < 0
+ return sortedAllowedIPs[i].Addr().Compare(sortedAllowedIPs[j].Addr()) < 0
})
for _, allowedip := range sortedAllowedIPs {
b2String(allowedip.String())
diff --git a/tunnel/firewall/blocker.go b/tunnel/firewall/blocker.go
index 2cb2c7f2..8a4967ba 100644
--- a/tunnel/firewall/blocker.go
+++ b/tunnel/firewall/blocker.go
@@ -1,13 +1,13 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package firewall
import (
"errors"
- "net"
+ "net/netip"
"unsafe"
"golang.org/x/sys/windows"
@@ -101,7 +101,7 @@ func registerBaseObjects(session uintptr) (*baseObjects, error) {
return bo, nil
}
-func EnableFirewall(luid uint64, doNotRestrict bool, restrictToDNSServers []net.IP) error {
+func EnableFirewall(luid uint64, doNotRestrict bool, restrictToDNSServers []netip.Addr) error {
if wfpSession != 0 {
return errors.New("The firewall has already been enabled")
}
diff --git a/tunnel/firewall/helpers.go b/tunnel/firewall/helpers.go
index e3e4eac6..46e43aa5 100644
--- a/tunnel/firewall/helpers.go
+++ b/tunnel/firewall/helpers.go
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package firewall
diff --git a/tunnel/firewall/mksyscall.go b/tunnel/firewall/mksyscall.go
index d5ff98aa..fc108007 100644
--- a/tunnel/firewall/mksyscall.go
+++ b/tunnel/firewall/mksyscall.go
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package firewall
diff --git a/tunnel/firewall/rules.go b/tunnel/firewall/rules.go
index c4488a31..41632f98 100644
--- a/tunnel/firewall/rules.go
+++ b/tunnel/firewall/rules.go
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package firewall
@@ -8,7 +8,7 @@ package firewall
import (
"encoding/binary"
"errors"
- "net"
+ "net/netip"
"runtime"
"unsafe"
@@ -582,7 +582,6 @@ func permitDHCPIPv6(session uintptr, baseObjects *baseObjects, weight uint8) err
}
func permitNdp(session uintptr, baseObjects *baseObjects, weight uint8) error {
-
/* TODO: actually handle the hop limit somehow! The rules should vaguely be:
* - icmpv6 133: must be outgoing, dst must be FF02::2/128, hop limit must be 255
* - icmpv6 134: must be incoming, src must be FE80::/10, hop limit must be 255
@@ -985,7 +984,7 @@ func blockAll(session uintptr, baseObjects *baseObjects, weight uint8) error {
}
// Block all DNS traffic except towards specified DNS servers.
-func blockDNS(except []net.IP, session uintptr, baseObjects *baseObjects, weightAllow uint8, weightDeny uint8) error {
+func blockDNS(except []netip.Addr, session uintptr, baseObjects *baseObjects, weightAllow, weightDeny uint8) error {
if weightDeny >= weightAllow {
return errors.New("The allow weight must be greater than the deny weight")
}
@@ -1106,8 +1105,7 @@ func blockDNS(except []net.IP, session uintptr, baseObjects *baseObjects, weight
allowConditionsV4 := make([]wtFwpmFilterCondition0, 0, len(denyConditions)+len(except))
allowConditionsV4 = append(allowConditionsV4, denyConditions...)
for _, ip := range except {
- ip4 := ip.To4()
- if ip4 == nil {
+ if !ip.Is4() {
continue
}
allowConditionsV4 = append(allowConditionsV4, wtFwpmFilterCondition0{
@@ -1115,7 +1113,7 @@ func blockDNS(except []net.IP, session uintptr, baseObjects *baseObjects, weight
matchType: cFWP_MATCH_EQUAL,
conditionValue: wtFwpConditionValue0{
_type: cFWP_UINT32,
- value: uintptr(binary.BigEndian.Uint32(ip4)),
+ value: uintptr(binary.BigEndian.Uint32(ip.AsSlice())),
},
})
}
@@ -1124,11 +1122,10 @@ func blockDNS(except []net.IP, session uintptr, baseObjects *baseObjects, weight
allowConditionsV6 := make([]wtFwpmFilterCondition0, 0, len(denyConditions)+len(except))
allowConditionsV6 = append(allowConditionsV6, denyConditions...)
for _, ip := range except {
- if ip.To4() != nil {
+ if !ip.Is6() {
continue
}
- var address wtFwpByteArray16
- copy(address.byteArray16[:], ip)
+ address := wtFwpByteArray16{byteArray16: ip.As16()}
allowConditionsV6 = append(allowConditionsV6, wtFwpmFilterCondition0{
fieldKey: cFWPM_CONDITION_IP_REMOTE_ADDRESS,
matchType: cFWP_MATCH_EQUAL,
diff --git a/tunnel/firewall/syscall_windows.go b/tunnel/firewall/syscall_windows.go
index 661527d9..4d8eea42 100644
--- a/tunnel/firewall/syscall_windows.go
+++ b/tunnel/firewall/syscall_windows.go
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package firewall
diff --git a/tunnel/firewall/types_windows.go b/tunnel/firewall/types_windows.go
index 075daae4..54e2aad7 100644
--- a/tunnel/firewall/types_windows.go
+++ b/tunnel/firewall/types_windows.go
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package firewall
@@ -148,8 +148,10 @@ var cFWPM_CONDITION_IP_LOCAL_ADDRESS = windows.GUID{
Data4: [8]byte{0xbf, 0xe3, 0xff, 0xd8, 0xf5, 0xa0, 0x89, 0x57},
}
-var cFWPM_CONDITION_ICMP_TYPE = cFWPM_CONDITION_IP_LOCAL_PORT
-var cFWPM_CONDITION_ICMP_CODE = cFWPM_CONDITION_IP_REMOTE_PORT
+var (
+ cFWPM_CONDITION_ICMP_TYPE = cFWPM_CONDITION_IP_LOCAL_PORT
+ cFWPM_CONDITION_ICMP_CODE = cFWPM_CONDITION_IP_REMOTE_PORT
+)
// 7bc43cbf-37ba-45f1-b74a-82ff518eeb10
var cFWPM_CONDITION_L2_FLAGS = windows.GUID{
diff --git a/tunnel/firewall/types_windows_32.go b/tunnel/firewall/types_windows_32.go
index 83aced6e..29ae553a 100644
--- a/tunnel/firewall/types_windows_32.go
+++ b/tunnel/firewall/types_windows_32.go
@@ -1,8 +1,8 @@
-// +build 386 arm
+//go:build 386 || arm
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package firewall
diff --git a/tunnel/firewall/types_windows_64.go b/tunnel/firewall/types_windows_64.go
index 6e60aa5b..a476a745 100644
--- a/tunnel/firewall/types_windows_64.go
+++ b/tunnel/firewall/types_windows_64.go
@@ -1,8 +1,8 @@
-// +build amd64 arm64
+//go:build amd64 || arm64
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package firewall
diff --git a/tunnel/firewall/types_windows_test.go b/tunnel/firewall/types_windows_test.go
index 683e52ea..afa1988f 100644
--- a/tunnel/firewall/types_windows_test.go
+++ b/tunnel/firewall/types_windows_test.go
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package firewall
@@ -11,7 +11,6 @@ import (
)
func TestWtFwpByteBlobSize(t *testing.T) {
-
const actualWtFwpByteBlobSize = unsafe.Sizeof(wtFwpByteBlob{})
if actualWtFwpByteBlobSize != wtFwpByteBlob_Size {
@@ -21,7 +20,6 @@ func TestWtFwpByteBlobSize(t *testing.T) {
}
func TestWtFwpByteBlobOffsets(t *testing.T) {
-
s := wtFwpByteBlob{}
sp := uintptr(unsafe.Pointer(&s))
@@ -34,7 +32,6 @@ func TestWtFwpByteBlobOffsets(t *testing.T) {
}
func TestWtFwpmAction0Size(t *testing.T) {
-
const actualWtFwpmAction0Size = unsafe.Sizeof(wtFwpmAction0{})
if actualWtFwpmAction0Size != wtFwpmAction0_Size {
@@ -44,7 +41,6 @@ func TestWtFwpmAction0Size(t *testing.T) {
}
func TestWtFwpmAction0Offsets(t *testing.T) {
-
s := wtFwpmAction0{}
sp := uintptr(unsafe.Pointer(&s))
@@ -58,7 +54,6 @@ func TestWtFwpmAction0Offsets(t *testing.T) {
}
func TestWtFwpBitmapArray64Size(t *testing.T) {
-
const actualWtFwpBitmapArray64Size = unsafe.Sizeof(wtFwpBitmapArray64{})
if actualWtFwpBitmapArray64Size != wtFwpBitmapArray64_Size {
@@ -68,7 +63,6 @@ func TestWtFwpBitmapArray64Size(t *testing.T) {
}
func TestWtFwpByteArray6Size(t *testing.T) {
-
const actualWtFwpByteArray6Size = unsafe.Sizeof(wtFwpByteArray6{})
if actualWtFwpByteArray6Size != wtFwpByteArray6_Size {
@@ -78,7 +72,6 @@ func TestWtFwpByteArray6Size(t *testing.T) {
}
func TestWtFwpByteArray16Size(t *testing.T) {
-
const actualWtFwpByteArray16Size = unsafe.Sizeof(wtFwpByteArray16{})
if actualWtFwpByteArray16Size != wtFwpByteArray16_Size {
@@ -88,7 +81,6 @@ func TestWtFwpByteArray16Size(t *testing.T) {
}
func TestWtFwpConditionValue0Size(t *testing.T) {
-
const actualWtFwpConditionValue0Size = unsafe.Sizeof(wtFwpConditionValue0{})
if actualWtFwpConditionValue0Size != wtFwpConditionValue0_Size {
@@ -98,7 +90,6 @@ func TestWtFwpConditionValue0Size(t *testing.T) {
}
func TestWtFwpConditionValue0Offsets(t *testing.T) {
-
s := wtFwpConditionValue0{}
sp := uintptr(unsafe.Pointer(&s))
@@ -111,7 +102,6 @@ func TestWtFwpConditionValue0Offsets(t *testing.T) {
}
func TestWtFwpV4AddrAndMaskSize(t *testing.T) {
-
const actualWtFwpV4AddrAndMaskSize = unsafe.Sizeof(wtFwpV4AddrAndMask{})
if actualWtFwpV4AddrAndMaskSize != wtFwpV4AddrAndMask_Size {
@@ -121,7 +111,6 @@ func TestWtFwpV4AddrAndMaskSize(t *testing.T) {
}
func TestWtFwpV4AddrAndMaskOffsets(t *testing.T) {
-
s := wtFwpV4AddrAndMask{}
sp := uintptr(unsafe.Pointer(&s))
@@ -135,7 +124,6 @@ func TestWtFwpV4AddrAndMaskOffsets(t *testing.T) {
}
func TestWtFwpV6AddrAndMaskSize(t *testing.T) {
-
const actualWtFwpV6AddrAndMaskSize = unsafe.Sizeof(wtFwpV6AddrAndMask{})
if actualWtFwpV6AddrAndMaskSize != wtFwpV6AddrAndMask_Size {
@@ -145,7 +133,6 @@ func TestWtFwpV6AddrAndMaskSize(t *testing.T) {
}
func TestWtFwpV6AddrAndMaskOffsets(t *testing.T) {
-
s := wtFwpV6AddrAndMask{}
sp := uintptr(unsafe.Pointer(&s))
@@ -159,7 +146,6 @@ func TestWtFwpV6AddrAndMaskOffsets(t *testing.T) {
}
func TestWtFwpValue0Size(t *testing.T) {
-
const actualWtFwpValue0Size = unsafe.Sizeof(wtFwpValue0{})
if actualWtFwpValue0Size != wtFwpValue0_Size {
@@ -168,7 +154,6 @@ func TestWtFwpValue0Size(t *testing.T) {
}
func TestWtFwpValue0Offsets(t *testing.T) {
-
s := wtFwpValue0{}
sp := uintptr(unsafe.Pointer(&s))
@@ -181,7 +166,6 @@ func TestWtFwpValue0Offsets(t *testing.T) {
}
func TestWtFwpmDisplayData0Size(t *testing.T) {
-
const actualWtFwpmDisplayData0Size = unsafe.Sizeof(wtFwpmDisplayData0{})
if actualWtFwpmDisplayData0Size != wtFwpmDisplayData0_Size {
@@ -191,7 +175,6 @@ func TestWtFwpmDisplayData0Size(t *testing.T) {
}
func TestWtFwpmDisplayData0Offsets(t *testing.T) {
-
s := wtFwpmDisplayData0{}
sp := uintptr(unsafe.Pointer(&s))
@@ -205,7 +188,6 @@ func TestWtFwpmDisplayData0Offsets(t *testing.T) {
}
func TestWtFwpmFilterCondition0Size(t *testing.T) {
-
const actualWtFwpmFilterCondition0Size = unsafe.Sizeof(wtFwpmFilterCondition0{})
if actualWtFwpmFilterCondition0Size != wtFwpmFilterCondition0_Size {
@@ -215,7 +197,6 @@ func TestWtFwpmFilterCondition0Size(t *testing.T) {
}
func TestWtFwpmFilterCondition0Offsets(t *testing.T) {
-
s := wtFwpmFilterCondition0{}
sp := uintptr(unsafe.Pointer(&s))
@@ -237,7 +218,6 @@ func TestWtFwpmFilterCondition0Offsets(t *testing.T) {
}
func TestWtFwpmFilter0Size(t *testing.T) {
-
const actualWtFwpmFilter0Size = unsafe.Sizeof(wtFwpmFilter0{})
if actualWtFwpmFilter0Size != wtFwpmFilter0_Size {
@@ -247,7 +227,6 @@ func TestWtFwpmFilter0Size(t *testing.T) {
}
func TestWtFwpmFilter0Offsets(t *testing.T) {
-
s := wtFwpmFilter0{}
sp := uintptr(unsafe.Pointer(&s))
@@ -364,7 +343,6 @@ func TestWtFwpmFilter0Offsets(t *testing.T) {
}
func TestWtFwpProvider0Size(t *testing.T) {
-
const actualWtFwpProvider0Size = unsafe.Sizeof(wtFwpProvider0{})
if actualWtFwpProvider0Size != wtFwpProvider0_Size {
@@ -374,7 +352,6 @@ func TestWtFwpProvider0Size(t *testing.T) {
}
func TestWtFwpProvider0Offsets(t *testing.T) {
-
s := wtFwpProvider0{}
sp := uintptr(unsafe.Pointer(&s))
@@ -412,7 +389,6 @@ func TestWtFwpProvider0Offsets(t *testing.T) {
}
func TestWtFwpmSession0Size(t *testing.T) {
-
const actualWtFwpmSession0Size = unsafe.Sizeof(wtFwpmSession0{})
if actualWtFwpmSession0Size != wtFwpmSession0_Size {
@@ -422,7 +398,6 @@ func TestWtFwpmSession0Size(t *testing.T) {
}
func TestWtFwpmSession0Offsets(t *testing.T) {
-
s := wtFwpmSession0{}
sp := uintptr(unsafe.Pointer(&s))
@@ -482,7 +457,6 @@ func TestWtFwpmSession0Offsets(t *testing.T) {
}
func TestWtFwpmSublayer0Size(t *testing.T) {
-
const actualWtFwpmSublayer0Size = unsafe.Sizeof(wtFwpmSublayer0{})
if actualWtFwpmSublayer0Size != wtFwpmSublayer0_Size {
@@ -492,7 +466,6 @@ func TestWtFwpmSublayer0Size(t *testing.T) {
}
func TestWtFwpmSublayer0Offsets(t *testing.T) {
-
s := wtFwpmSublayer0{}
sp := uintptr(unsafe.Pointer(&s))
diff --git a/tunnel/interfacewatcher.go b/tunnel/interfacewatcher.go
index e12e5929..a831d06e 100644
--- a/tunnel/interfacewatcher.go
+++ b/tunnel/interfacewatcher.go
@@ -1,20 +1,20 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package tunnel
import (
+ "errors"
+ "fmt"
"log"
"sync"
+ "time"
"golang.org/x/sys/windows"
-
- "golang.zx2c4.com/wireguard/conn"
- "golang.zx2c4.com/wireguard/tun"
-
"golang.zx2c4.com/wireguard/windows/conf"
+ "golang.zx2c4.com/wireguard/windows/driver"
"golang.zx2c4.com/wireguard/windows/services"
"golang.zx2c4.com/wireguard/windows/tunnel/firewall"
"golang.zx2c4.com/wireguard/windows/tunnel/winipcfg"
@@ -24,63 +24,30 @@ type interfaceWatcherError struct {
serviceError services.Error
err error
}
+
type interfaceWatcherEvent struct {
luid winipcfg.LUID
family winipcfg.AddressFamily
}
+
type interfaceWatcher struct {
- errors chan interfaceWatcherError
+ errors chan interfaceWatcherError
+ started chan winipcfg.AddressFamily
- binder conn.BindSocketToInterface
- conf *conf.Config
- tun *tun.NativeTun
+ conf *conf.Config
+ adapter *driver.Adapter
+ luid winipcfg.LUID
setupMutex sync.Mutex
interfaceChangeCallback winipcfg.ChangeCallback
changeCallbacks4 []winipcfg.ChangeCallback
changeCallbacks6 []winipcfg.ChangeCallback
storedEvents []interfaceWatcherEvent
-}
-
-func hasDefaultRoute(family winipcfg.AddressFamily, peers []conf.Peer) bool {
- var (
- foundV401 bool
- foundV41281 bool
- foundV600001 bool
- foundV680001 bool
- foundV400 bool
- foundV600 bool
- v40 = [4]byte{}
- v60 = [16]byte{}
- v48 = [4]byte{0x80}
- v68 = [16]byte{0x80}
- )
- for _, peer := range peers {
- for _, allowedip := range peer.AllowedIPs {
- if allowedip.Cidr == 1 && len(allowedip.IP) == 16 && allowedip.IP.Equal(v60[:]) {
- foundV600001 = true
- } else if allowedip.Cidr == 1 && len(allowedip.IP) == 16 && allowedip.IP.Equal(v68[:]) {
- foundV680001 = true
- } else if allowedip.Cidr == 1 && len(allowedip.IP) == 4 && allowedip.IP.Equal(v40[:]) {
- foundV401 = true
- } else if allowedip.Cidr == 1 && len(allowedip.IP) == 4 && allowedip.IP.Equal(v48[:]) {
- foundV41281 = true
- } else if allowedip.Cidr == 0 && len(allowedip.IP) == 16 && allowedip.IP.Equal(v60[:]) {
- foundV600 = true
- } else if allowedip.Cidr == 0 && len(allowedip.IP) == 4 && allowedip.IP.Equal(v40[:]) {
- foundV400 = true
- }
- }
- }
- if family == windows.AF_INET {
- return foundV400 || (foundV401 && foundV41281)
- } else if family == windows.AF_INET6 {
- return foundV600 || (foundV600001 && foundV680001)
- }
- return false
+ watchdog *time.Timer
}
func (iw *interfaceWatcher) setup(family winipcfg.AddressFamily) {
+ iw.watchdog.Stop()
var changeCallbacks *[]winipcfg.ChangeCallback
var ipversion string
if family == windows.AF_INET {
@@ -100,25 +67,35 @@ func (iw *interfaceWatcher) setup(family winipcfg.AddressFamily) {
}
var err error
- log.Printf("Monitoring default %s routes", ipversion)
- *changeCallbacks, err = monitorDefaultRoutes(family, iw.binder, iw.conf.Interface.MTU == 0, hasDefaultRoute(family, iw.conf.Peers), iw.tun)
- if err != nil {
- iw.errors <- interfaceWatcherError{services.ErrorBindSocketsToDefaultRoutes, err}
- return
+ if iw.conf.Interface.MTU == 0 {
+ log.Printf("Monitoring MTU of default %s routes", ipversion)
+ *changeCallbacks, err = monitorMTU(family, iw.luid)
+ if err != nil {
+ iw.errors <- interfaceWatcherError{services.ErrorMonitorMTUChanges, err}
+ return
+ }
}
log.Printf("Setting device %s addresses", ipversion)
- err = configureInterface(family, iw.conf, iw.tun)
+ err = configureInterface(family, iw.conf, iw.luid)
if err != nil {
iw.errors <- interfaceWatcherError{services.ErrorSetNetConfig, err}
return
}
+ evaluateDynamicPitfalls(family, iw.conf, iw.luid)
+
+ iw.started <- family
}
func watchInterface() (*interfaceWatcher, error) {
iw := &interfaceWatcher{
- errors: make(chan interfaceWatcherError, 2),
+ errors: make(chan interfaceWatcherError, 2),
+ started: make(chan winipcfg.AddressFamily, 4),
}
+ iw.watchdog = time.AfterFunc(time.Duration(1<<63-1), func() {
+ iw.errors <- interfaceWatcherError{services.ErrorCreateNetworkAdapter, errors.New("TCP/IP interface for adapter did not appear after one minute")}
+ })
+ iw.watchdog.Stop()
var err error
iw.interfaceChangeCallback, err = winipcfg.RegisterInterfaceChangeCallback(func(notificationType winipcfg.MibNotificationType, iface *winipcfg.MibIPInterfaceRow) {
iw.setupMutex.Lock()
@@ -127,28 +104,41 @@ func watchInterface() (*interfaceWatcher, error) {
if notificationType != winipcfg.MibAddInstance {
return
}
- if iw.tun == nil {
+ if iw.luid == 0 {
iw.storedEvents = append(iw.storedEvents, interfaceWatcherEvent{iface.InterfaceLUID, iface.Family})
return
}
- if iface.InterfaceLUID != winipcfg.LUID(iw.tun.LUID()) {
+ if iface.InterfaceLUID != iw.luid {
return
}
iw.setup(iface.Family)
+
+ if state, err := iw.adapter.AdapterState(); err == nil && state == driver.AdapterStateDown {
+ log.Println("Reinitializing adapter configuration")
+ err = iw.adapter.SetConfiguration(iw.conf.ToDriverConfiguration())
+ if err != nil {
+ log.Println(fmt.Errorf("%v: %w", services.ErrorDeviceSetConfig, err))
+ }
+ err = iw.adapter.SetAdapterState(driver.AdapterStateUp)
+ if err != nil {
+ log.Println(fmt.Errorf("%v: %w", services.ErrorDeviceBringUp, err))
+ }
+ }
})
if err != nil {
- return nil, err
+ return nil, fmt.Errorf("unable to register interface change callback: %w", err)
}
return iw, nil
}
-func (iw *interfaceWatcher) Configure(binder conn.BindSocketToInterface, conf *conf.Config, tun *tun.NativeTun) {
+func (iw *interfaceWatcher) Configure(adapter *driver.Adapter, conf *conf.Config, luid winipcfg.LUID) {
iw.setupMutex.Lock()
defer iw.setupMutex.Unlock()
+ iw.watchdog.Reset(time.Minute)
- iw.binder, iw.conf, iw.tun = binder, conf, tun
+ iw.adapter, iw.conf, iw.luid = adapter, conf, luid
for _, event := range iw.storedEvents {
- if event.luid == winipcfg.LUID(iw.tun.LUID()) {
+ if event.luid == luid {
iw.setup(event.family)
}
}
@@ -157,10 +147,11 @@ func (iw *interfaceWatcher) Configure(binder conn.BindSocketToInterface, conf *c
func (iw *interfaceWatcher) Destroy() {
iw.setupMutex.Lock()
+ iw.watchdog.Stop()
changeCallbacks4 := iw.changeCallbacks4
changeCallbacks6 := iw.changeCallbacks6
interfaceChangeCallback := iw.interfaceChangeCallback
- tun := iw.tun
+ luid := iw.luid
iw.setupMutex.Unlock()
if interfaceChangeCallback != nil {
@@ -186,10 +177,9 @@ func (iw *interfaceWatcher) Destroy() {
changeCallbacks6 = changeCallbacks6[1:]
}
firewall.DisableFirewall()
- if tun != nil && iw.tun == tun {
+ if luid != 0 && iw.luid == luid {
// It seems that the Windows networking stack doesn't like it when we destroy interfaces that have active
// routes, so to be certain, just remove everything before destroying.
- luid := winipcfg.LUID(tun.LUID())
luid.FlushRoutes(windows.AF_INET)
luid.FlushIPAddresses(windows.AF_INET)
luid.FlushDNS(windows.AF_INET)
diff --git a/tunnel/ipcpermissions.go b/tunnel/ipcpermissions.go
deleted file mode 100644
index 3a676e4b..00000000
--- a/tunnel/ipcpermissions.go
+++ /dev/null
@@ -1,63 +0,0 @@
-/* SPDX-License-Identifier: MIT
- *
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
- */
-
-package tunnel
-
-import (
- "golang.org/x/sys/windows"
-
- "golang.zx2c4.com/wireguard/ipc"
-
- "golang.zx2c4.com/wireguard/windows/conf"
-)
-
-func CopyConfigOwnerToIPCSecurityDescriptor(filename string) error {
- if conf.PathIsEncrypted(filename) {
- return nil
- }
-
- fileSd, err := windows.GetNamedSecurityInfo(filename, windows.SE_FILE_OBJECT, windows.OWNER_SECURITY_INFORMATION)
- if err != nil {
- return err
- }
- fileOwner, _, err := fileSd.Owner()
- if err != nil {
- return err
- }
- if fileOwner.IsWellKnown(windows.WinLocalSystemSid) {
- return nil
- }
- additionalEntries := []windows.EXPLICIT_ACCESS{{
- AccessPermissions: windows.GENERIC_ALL,
- AccessMode: windows.GRANT_ACCESS,
- Trustee: windows.TRUSTEE{
- TrusteeForm: windows.TRUSTEE_IS_SID,
- TrusteeType: windows.TRUSTEE_IS_USER,
- TrusteeValue: windows.TrusteeValueFromSID(fileOwner),
- },
- }}
-
- sd, err := ipc.UAPISecurityDescriptor.ToAbsolute()
- if err != nil {
- return err
- }
- dacl, defaulted, _ := sd.DACL()
-
- newDacl, err := windows.ACLFromEntries(additionalEntries, dacl)
- if err != nil {
- return err
- }
- err = sd.SetDACL(newDacl, true, defaulted)
- if err != nil {
- return err
- }
- sd, err = sd.ToSelfRelative()
- if err != nil {
- return err
- }
- ipc.UAPISecurityDescriptor = sd
-
- return nil
-}
diff --git a/tunnel/defaultroutemonitor.go b/tunnel/mtumonitor.go
index aa0db675..c07823a2 100644
--- a/tunnel/defaultroutemonitor.go
+++ b/tunnel/mtumonitor.go
@@ -1,30 +1,23 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package tunnel
import (
- "log"
- "sync"
- "time"
-
"golang.org/x/sys/windows"
-
- "golang.zx2c4.com/wireguard/conn"
- "golang.zx2c4.com/wireguard/tun"
"golang.zx2c4.com/wireguard/windows/tunnel/winipcfg"
)
-func bindSocketRoute(family winipcfg.AddressFamily, binder conn.BindSocketToInterface, ourLUID winipcfg.LUID, lastLUID *winipcfg.LUID, lastIndex *uint32, blackholeWhenLoop bool) error {
+func findDefaultLUID(family winipcfg.AddressFamily, ourLUID winipcfg.LUID, lastLUID *winipcfg.LUID, lastIndex *uint32) error {
r, err := winipcfg.GetIPForwardTable2(family)
if err != nil {
return err
}
lowestMetric := ^uint32(0)
- index := uint32(0) // Zero is "unspecified", which for IP_UNICAST_IF resets the value, which is what we want.
- luid := winipcfg.LUID(0) // Hopefully luid zero is unspecified, but hard to find docs saying so.
+ index := uint32(0)
+ luid := winipcfg.LUID(0)
for i := range r {
if r[i].DestinationPrefix.PrefixLength != 0 || r[i].InterfaceLUID == ourLUID {
continue
@@ -50,36 +43,24 @@ func bindSocketRoute(family winipcfg.AddressFamily, binder conn.BindSocketToInte
}
*lastLUID = luid
*lastIndex = index
- blackhole := blackholeWhenLoop && index == 0
- if family == windows.AF_INET {
- log.Printf("Binding v4 socket to interface %d (blackhole=%v)", index, blackhole)
- return binder.BindSocketToInterface4(index, blackhole)
- } else if family == windows.AF_INET6 {
- log.Printf("Binding v6 socket to interface %d (blackhole=%v)", index, blackhole)
- return binder.BindSocketToInterface6(index, blackhole)
- }
return nil
}
-func monitorDefaultRoutes(family winipcfg.AddressFamily, binder conn.BindSocketToInterface, autoMTU bool, blackholeWhenLoop bool, tun *tun.NativeTun) ([]winipcfg.ChangeCallback, error) {
+func monitorMTU(family winipcfg.AddressFamily, ourLUID winipcfg.LUID) ([]winipcfg.ChangeCallback, error) {
var minMTU uint32
if family == windows.AF_INET {
minMTU = 576
} else if family == windows.AF_INET6 {
minMTU = 1280
}
- ourLUID := winipcfg.LUID(tun.LUID())
lastLUID := winipcfg.LUID(0)
lastIndex := ^uint32(0)
lastMTU := uint32(0)
doIt := func() error {
- err := bindSocketRoute(family, binder, ourLUID, &lastLUID, &lastIndex, blackholeWhenLoop)
+ err := findDefaultLUID(family, ourLUID, &lastLUID, &lastIndex)
if err != nil {
return err
}
- if !autoMTU {
- return nil
- }
mtu := uint32(0)
if lastLUID != 0 {
iface, err := lastLUID.Interface()
@@ -103,7 +84,6 @@ func monitorDefaultRoutes(family winipcfg.AddressFamily, binder conn.BindSocketT
if err != nil {
return err
}
- tun.ForceMTU(int(iface.NLMTU)) // TODO: having one MTU for both v4 and v6 kind of breaks the windows model, so right now this just gets the second one which is... bad.
lastMTU = mtu
}
return nil
@@ -112,32 +92,9 @@ func monitorDefaultRoutes(family winipcfg.AddressFamily, binder conn.BindSocketT
if err != nil {
return nil, err
}
-
- firstBurst := time.Time{}
- burstMutex := sync.Mutex{}
- burstTimer := time.AfterFunc(time.Hour*200, func() {
- burstMutex.Lock()
- firstBurst = time.Time{}
- doIt()
- burstMutex.Unlock()
- })
- burstTimer.Stop()
- bump := func() {
- burstMutex.Lock()
- burstTimer.Reset(time.Millisecond * 150)
- if firstBurst.IsZero() {
- firstBurst = time.Now()
- } else if time.Since(firstBurst) > time.Second*2 {
- firstBurst = time.Time{}
- burstTimer.Stop()
- doIt()
- }
- burstMutex.Unlock()
- }
-
cbr, err := winipcfg.RegisterRouteChangeCallback(func(notificationType winipcfg.MibNotificationType, route *winipcfg.MibIPforwardRow2) {
if route != nil && route.DestinationPrefix.PrefixLength == 0 {
- bump()
+ doIt()
}
})
if err != nil {
@@ -145,7 +102,7 @@ func monitorDefaultRoutes(family winipcfg.AddressFamily, binder conn.BindSocketT
}
cbi, err := winipcfg.RegisterInterfaceChangeCallback(func(notificationType winipcfg.MibNotificationType, iface *winipcfg.MibIPInterfaceRow) {
if notificationType == winipcfg.MibParameterNotification {
- bump()
+ doIt()
}
})
if err != nil {
diff --git a/tunnel/pitfalls.go b/tunnel/pitfalls.go
new file mode 100644
index 00000000..fdef6eb2
--- /dev/null
+++ b/tunnel/pitfalls.go
@@ -0,0 +1,177 @@
+/* SPDX-License-Identifier: MIT
+ *
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
+ */
+
+package tunnel
+
+import (
+ "log"
+ "net/netip"
+ "strings"
+ "unsafe"
+
+ "golang.org/x/sys/windows"
+ "golang.org/x/sys/windows/svc/mgr"
+ "golang.zx2c4.com/wireguard/windows/conf"
+ "golang.zx2c4.com/wireguard/windows/tunnel/winipcfg"
+)
+
+func evaluateStaticPitfalls() {
+ go func() {
+ pitfallDnsCacheDisabled()
+ pitfallVirtioNetworkDriver()
+ }()
+}
+
+func evaluateDynamicPitfalls(family winipcfg.AddressFamily, conf *conf.Config, luid winipcfg.LUID) {
+ go func() {
+ pitfallWeakHostSend(family, conf, luid)
+ }()
+}
+
+func pitfallDnsCacheDisabled() {
+ scm, err := mgr.Connect()
+ if err != nil {
+ return
+ }
+ defer scm.Disconnect()
+ svc := mgr.Service{Name: "dnscache"}
+ svc.Handle, err = windows.OpenService(scm.Handle, windows.StringToUTF16Ptr(svc.Name), windows.SERVICE_QUERY_CONFIG)
+ if err != nil {
+ return
+ }
+ defer svc.Close()
+ cfg, err := svc.Config()
+ if err != nil {
+ return
+ }
+ if cfg.StartType != mgr.StartDisabled {
+ return
+ }
+
+ log.Printf("Warning: the %q (dnscache) service is disabled; please re-enable it", cfg.DisplayName)
+}
+
+func pitfallVirtioNetworkDriver() {
+ var modules []windows.RTL_PROCESS_MODULE_INFORMATION
+ for bufferSize := uint32(128 * 1024); ; {
+ moduleBuffer := make([]byte, bufferSize)
+ err := windows.NtQuerySystemInformation(windows.SystemModuleInformation, unsafe.Pointer(&moduleBuffer[0]), bufferSize, &bufferSize)
+ switch err {
+ case windows.STATUS_INFO_LENGTH_MISMATCH:
+ continue
+ case nil:
+ break
+ default:
+ return
+ }
+ mods := (*windows.RTL_PROCESS_MODULES)(unsafe.Pointer(&moduleBuffer[0]))
+ modules = unsafe.Slice(&mods.Modules[0], mods.NumberOfModules)
+ break
+ }
+ for i := range modules {
+ if !strings.EqualFold(windows.ByteSliceToString(modules[i].FullPathName[modules[i].OffsetToFileName:]), "netkvm.sys") {
+ continue
+ }
+ driverPath := `\\?\GLOBALROOT` + windows.ByteSliceToString(modules[i].FullPathName[:])
+ var zero windows.Handle
+ infoSize, err := windows.GetFileVersionInfoSize(driverPath, &zero)
+ if err != nil {
+ return
+ }
+ versionInfo := make([]byte, infoSize)
+ err = windows.GetFileVersionInfo(driverPath, 0, infoSize, unsafe.Pointer(&versionInfo[0]))
+ if err != nil {
+ return
+ }
+ var fixedInfo *windows.VS_FIXEDFILEINFO
+ fixedInfoLen := uint32(unsafe.Sizeof(*fixedInfo))
+ err = windows.VerQueryValue(unsafe.Pointer(&versionInfo[0]), `\`, unsafe.Pointer(&fixedInfo), &fixedInfoLen)
+ if err != nil {
+ return
+ }
+ const minimumPlausibleVersion = 40 << 48
+ const minimumGoodVersion = (100 << 48) | (85 << 32) | (104 << 16) | (20800 << 0)
+ version := (uint64(fixedInfo.FileVersionMS) << 32) | uint64(fixedInfo.FileVersionLS)
+ if version >= minimumGoodVersion || version < minimumPlausibleVersion {
+ return
+ }
+ log.Println("Warning: the VirtIO network driver (NetKVM) is out of date and may cause known problems; please update to v100.85.104.20800 or later")
+ return
+ }
+}
+
+func pitfallWeakHostSend(family winipcfg.AddressFamily, conf *conf.Config, ourLUID winipcfg.LUID) {
+ routingTable, err := winipcfg.GetIPForwardTable2(family)
+ if err != nil {
+ return
+ }
+ type endpointRoute struct {
+ addr netip.Addr
+ name string
+ lowestMetric uint32
+ highestCIDR uint8
+ weakHostSend bool
+ finalIsOurs bool
+ }
+ endpoints := make([]endpointRoute, 0, len(conf.Peers))
+ for _, peer := range conf.Peers {
+ addr, err := netip.ParseAddr(peer.Endpoint.Host)
+ if err != nil || (addr.Is4() && family != windows.AF_INET) || (addr.Is6() && family != windows.AF_INET6) {
+ continue
+ }
+ endpoints = append(endpoints, endpointRoute{addr: addr, lowestMetric: ^uint32(0)})
+ }
+ for i := range routingTable {
+ var (
+ ifrow *winipcfg.MibIfRow2
+ ifacerow *winipcfg.MibIPInterfaceRow
+ metric uint32
+ )
+ for j := range endpoints {
+ r, e := &routingTable[i], &endpoints[j]
+ if r.DestinationPrefix.PrefixLength < e.highestCIDR {
+ continue
+ }
+ if !r.DestinationPrefix.Prefix().Contains(e.addr) {
+ continue
+ }
+ if ifrow == nil {
+ ifrow, err = r.InterfaceLUID.Interface()
+ if err != nil {
+ continue
+ }
+ }
+ if ifrow.OperStatus != winipcfg.IfOperStatusUp {
+ continue
+ }
+ if ifacerow == nil {
+ ifacerow, err = r.InterfaceLUID.IPInterface(family)
+ if err != nil {
+ continue
+ }
+ metric = r.Metric + ifacerow.Metric
+ }
+ if r.DestinationPrefix.PrefixLength == e.highestCIDR && metric > e.lowestMetric {
+ continue
+ }
+ e.lowestMetric = metric
+ e.highestCIDR = r.DestinationPrefix.PrefixLength
+ e.finalIsOurs = r.InterfaceLUID == ourLUID
+ if !e.finalIsOurs {
+ e.name = ifrow.Alias()
+ e.weakHostSend = ifacerow.ForwardingEnabled || ifacerow.WeakHostSend
+ }
+ }
+ }
+ problematicInterfaces := make(map[string]bool, len(endpoints))
+ for _, e := range endpoints {
+ if e.weakHostSend && e.finalIsOurs {
+ problematicInterfaces[e.name] = true
+ }
+ }
+ for iface := range problematicInterfaces {
+ log.Printf("Warning: the %q interface has Forwarding/WeakHostSend enabled, which will cause routing loops", iface)
+ }
+}
diff --git a/tunnel/scriptrunner.go b/tunnel/scriptrunner.go
index 450d8e21..eb97d98d 100644
--- a/tunnel/scriptrunner.go
+++ b/tunnel/scriptrunner.go
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package tunnel
diff --git a/tunnel/service.go b/tunnel/service.go
index 63cd243f..a56ed1f3 100644
--- a/tunnel/service.go
+++ b/tunnel/service.go
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package tunnel
@@ -9,7 +9,6 @@ import (
"bytes"
"fmt"
"log"
- "net"
"os"
"runtime"
"time"
@@ -17,16 +16,12 @@ import (
"golang.org/x/sys/windows"
"golang.org/x/sys/windows/svc"
"golang.org/x/sys/windows/svc/mgr"
- "golang.zx2c4.com/wireguard/conn"
- "golang.zx2c4.com/wireguard/device"
- "golang.zx2c4.com/wireguard/ipc"
- "golang.zx2c4.com/wireguard/tun"
-
"golang.zx2c4.com/wireguard/windows/conf"
+ "golang.zx2c4.com/wireguard/windows/driver"
"golang.zx2c4.com/wireguard/windows/elevate"
"golang.zx2c4.com/wireguard/windows/ringlogger"
"golang.zx2c4.com/wireguard/windows/services"
- "golang.zx2c4.com/wireguard/windows/version"
+ "golang.zx2c4.com/wireguard/windows/tunnel/winipcfg"
)
type tunnelService struct {
@@ -34,12 +29,12 @@ type tunnelService struct {
}
func (service *tunnelService) Execute(args []string, r <-chan svc.ChangeRequest, changes chan<- svc.Status) (svcSpecificEC bool, exitCode uint32) {
- changes <- svc.Status{State: svc.StartPending}
+ serviceState := svc.StartPending
+ changes <- svc.Status{State: serviceState}
- var dev *device.Device
- var uapi net.Listener
var watcher *interfaceWatcher
- var nativeTun *tun.NativeTun
+ var adapter *driver.Adapter
+ var luid winipcfg.LUID
var config *conf.Config
var err error
serviceError := services.ErrorSuccess
@@ -50,7 +45,8 @@ func (service *tunnelService) Execute(args []string, r <-chan svc.ChangeRequest,
if logErr != nil {
log.Println(logErr)
}
- changes <- svc.Status{State: svc.StopPending}
+ serviceState = svc.StopPending
+ changes <- svc.Status{State: serviceState}
stopIt := make(chan bool, 1)
go func() {
@@ -84,60 +80,63 @@ func (service *tunnelService) Execute(args []string, r <-chan svc.ChangeRequest,
}
}()
- if logErr == nil && dev != nil && config != nil {
+ if logErr == nil && adapter != nil && config != nil {
logErr = runScriptCommand(config.Interface.PreDown, config.Name)
}
if watcher != nil {
watcher.Destroy()
}
- if uapi != nil {
- uapi.Close()
- }
- if dev != nil {
- dev.Close()
+ if adapter != nil {
+ adapter.Close()
}
- if logErr == nil && dev != nil && config != nil {
+ if logErr == nil && adapter != nil && config != nil {
_ = runScriptCommand(config.Interface.PostDown, config.Name)
}
stopIt <- true
log.Println("Shutting down")
}()
- err = ringlogger.InitGlobalLogger("TUN")
+ var logFile string
+ logFile, err = conf.LogFile(true)
if err != nil {
serviceError = services.ErrorRingloggerOpen
return
}
-
- config, err = conf.LoadFromPath(service.Path)
+ err = ringlogger.InitGlobalLogger(logFile, "TUN")
if err != nil {
- serviceError = services.ErrorLoadConfiguration
+ serviceError = services.ErrorRingloggerOpen
return
}
- config.DeduplicateNetworkEntries()
- err = CopyConfigOwnerToIPCSecurityDescriptor(service.Path)
+
+ config, err = conf.LoadFromPath(service.Path)
if err != nil {
serviceError = services.ErrorLoadConfiguration
return
}
+ config.DeduplicateNetworkEntries()
log.SetPrefix(fmt.Sprintf("[%s] ", config.Name))
- log.Println("Starting", version.UserAgent())
+ services.PrintStarting()
- if m, err := mgr.Connect(); err == nil {
- if lockStatus, err := m.LockStatus(); err == nil && lockStatus.IsLocked {
- /* If we don't do this, then the Wintun installation will block forever, because
- * installing a Wintun device starts a service too. Apparently at boot time, Windows
- * 8.1 locks the SCM for each service start, creating a deadlock if we don't announce
- * that we're running before starting additional services.
- */
- log.Printf("SCM locked for %v by %s, marking service as started", lockStatus.Age, lockStatus.Owner)
- changes <- svc.Status{State: svc.Running}
+ if services.StartedAtBoot() {
+ if m, err := mgr.Connect(); err == nil {
+ if lockStatus, err := m.LockStatus(); err == nil && lockStatus.IsLocked {
+ /* If we don't do this, then the driver installation will block forever, because
+ * installing a network adapter starts the driver service too. Apparently at boot time,
+ * Windows 8.1 locks the SCM for each service start, creating a deadlock if we don't
+ * announce that we're running before starting additional services.
+ */
+ log.Printf("SCM locked for %v by %s, marking service as started", lockStatus.Age, lockStatus.Owner)
+ serviceState = svc.Running
+ changes <- svc.Status{State: serviceState}
+ }
+ m.Disconnect()
}
- m.Disconnect()
}
+ evaluateStaticPitfalls()
+
log.Println("Watching network interfaces")
watcher, err = watchInterface()
if err != nil {
@@ -146,34 +145,40 @@ func (service *tunnelService) Execute(args []string, r <-chan svc.ChangeRequest,
}
log.Println("Resolving DNS names")
- uapiConf, err := config.ToUAPI()
+ err = config.ResolveEndpoints()
if err != nil {
serviceError = services.ErrorDNSLookup
return
}
- log.Println("Creating Wintun interface")
- var wintun tun.Device
- for i := 0; i < 5; i++ {
+ log.Println("Creating network adapter")
+ for i := 0; i < 15; i++ {
if i > 0 {
time.Sleep(time.Second)
- log.Printf("Retrying Wintun creation after failure because system just booted (T+%v): %v", windows.DurationSinceBoot(), err)
+ log.Printf("Retrying adapter creation after failure because system just booted (T+%v): %v", windows.DurationSinceBoot(), err)
}
- wintun, err = tun.CreateTUNWithRequestedGUID(config.Name, deterministicGUID(config), 0)
- if err == nil || windows.DurationSinceBoot() > time.Minute*4 {
+ adapter, err = driver.CreateAdapter(config.Name, "WireGuard", deterministicGUID(config))
+ if err == nil || !services.StartedAtBoot() {
break
}
}
if err != nil {
- serviceError = services.ErrorCreateWintun
+ err = fmt.Errorf("Error creating adapter: %w", err)
+ serviceError = services.ErrorCreateNetworkAdapter
return
}
- nativeTun = wintun.(*tun.NativeTun)
- wintunVersion, err := nativeTun.RunningVersion()
+ luid = adapter.LUID()
+ driverVersion, err := driver.RunningVersion()
if err != nil {
- log.Printf("Warning: unable to determine Wintun version: %v", err)
+ log.Printf("Warning: unable to determine driver version: %v", err)
} else {
- log.Printf("Using Wintun/%d.%d", (wintunVersion>>16)&0xffff, wintunVersion&0xffff)
+ log.Printf("Using WireGuardNT/%d.%d", (driverVersion>>16)&0xffff, driverVersion&0xffff)
+ }
+ err = adapter.SetLogging(driver.AdapterLogOn)
+ if err != nil {
+ err = fmt.Errorf("Error enabling adapter logging: %w", err)
+ serviceError = services.ErrorCreateNetworkAdapter
+ return
}
err = runScriptCommand(config.Interface.PreUp, config.Name)
@@ -182,7 +187,7 @@ func (service *tunnelService) Execute(args []string, r <-chan svc.ChangeRequest,
return
}
- err = enableFirewall(config, nativeTun)
+ err = enableFirewall(config, luid)
if err != nil {
serviceError = services.ErrorFirewall
return
@@ -195,37 +200,18 @@ func (service *tunnelService) Execute(args []string, r <-chan svc.ChangeRequest,
return
}
- log.Println("Creating interface instance")
- bind := conn.NewDefaultBind()
- dev = device.NewDevice(wintun, bind, &device.Logger{log.Printf, log.Printf})
-
log.Println("Setting interface configuration")
- uapi, err = ipc.UAPIListen(config.Name)
+ err = adapter.SetConfiguration(config.ToDriverConfiguration())
if err != nil {
- serviceError = services.ErrorUAPIListen
+ serviceError = services.ErrorDeviceSetConfig
return
}
- err = dev.IpcSet(uapiConf)
+ err = adapter.SetAdapterState(driver.AdapterStateUp)
if err != nil {
- serviceError = services.ErrorDeviceSetConfig
+ serviceError = services.ErrorDeviceBringUp
return
}
-
- log.Println("Bringing peers up")
- dev.Up()
-
- watcher.Configure(bind.(conn.BindSocketToInterface), config, nativeTun)
-
- log.Println("Listening for UAPI requests")
- go func() {
- for {
- conn, err := uapi.Accept()
- if err != nil {
- continue
- }
- go dev.IpcHandle(conn)
- }
- }()
+ watcher.Configure(adapter, config, luid)
err = runScriptCommand(config.Interface.PostUp, config.Name)
if err != nil {
@@ -233,9 +219,9 @@ func (service *tunnelService) Execute(args []string, r <-chan svc.ChangeRequest,
return
}
- changes <- svc.Status{State: svc.Running, Accepts: svc.AcceptStop | svc.AcceptShutdown}
- log.Println("Startup complete")
+ changes <- svc.Status{State: serviceState, Accepts: svc.AcceptStop | svc.AcceptShutdown}
+ var started bool
for {
select {
case c := <-r:
@@ -247,8 +233,13 @@ func (service *tunnelService) Execute(args []string, r <-chan svc.ChangeRequest,
default:
log.Printf("Unexpected service control request #%d\n", c)
}
- case <-dev.Wait():
- return
+ case <-watcher.started:
+ if !started {
+ serviceState = svc.Running
+ changes <- svc.Status{State: serviceState, Accepts: svc.AcceptStop | svc.AcceptShutdown}
+ log.Println("Startup complete")
+ started = true
+ }
case e := <-watcher.errors:
serviceError, err = e.serviceError, e.err
return
@@ -261,7 +252,7 @@ func Run(confPath string) error {
if err != nil {
return err
}
- serviceName, err := services.ServiceNameOfTunnel(name)
+ serviceName, err := conf.ServiceNameOfTunnel(name)
if err != nil {
return err
}
diff --git a/tunnel/winipcfg/interface_change_handler.go b/tunnel/winipcfg/interface_change_handler.go
index 4d229e78..af29801a 100644
--- a/tunnel/winipcfg/interface_change_handler.go
+++ b/tunnel/winipcfg/interface_change_handler.go
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package winipcfg
diff --git a/tunnel/winipcfg/luid.go b/tunnel/winipcfg/luid.go
index 02ba65b4..0c898b89 100644
--- a/tunnel/winipcfg/luid.go
+++ b/tunnel/winipcfg/luid.go
@@ -1,13 +1,13 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package winipcfg
import (
"errors"
- "net"
+ "net/netip"
"strings"
"golang.org/x/sys/windows"
@@ -76,10 +76,10 @@ func LUIDFromIndex(index uint32) (LUID, error) {
// IPAddress method returns MibUnicastIPAddressRow struct that matches to provided 'ip' argument. Corresponds to GetUnicastIpAddressEntry
// (https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/nf-netioapi-getunicastipaddressentry)
-func (luid LUID) IPAddress(ip net.IP) (*MibUnicastIPAddressRow, error) {
+func (luid LUID) IPAddress(addr netip.Addr) (*MibUnicastIPAddressRow, error) {
row := &MibUnicastIPAddressRow{InterfaceLUID: luid}
- err := row.Address.SetIP(ip, 0)
+ err := row.Address.SetAddr(addr)
if err != nil {
return nil, err
}
@@ -94,22 +94,24 @@ func (luid LUID) IPAddress(ip net.IP) (*MibUnicastIPAddressRow, error) {
// AddIPAddress method adds new unicast IP address to the interface. Corresponds to CreateUnicastIpAddressEntry function
// (https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/nf-netioapi-createunicastipaddressentry).
-func (luid LUID) AddIPAddress(address net.IPNet) error {
+func (luid LUID) AddIPAddress(address netip.Prefix) error {
row := &MibUnicastIPAddressRow{}
row.Init()
row.InterfaceLUID = luid
- err := row.Address.SetIP(address.IP, 0)
+ row.DadState = DadStatePreferred
+ row.ValidLifetime = 0xffffffff
+ row.PreferredLifetime = 0xffffffff
+ err := row.Address.SetAddr(address.Addr())
if err != nil {
return err
}
- ones, _ := address.Mask.Size()
- row.OnLinkPrefixLength = uint8(ones)
+ row.OnLinkPrefixLength = uint8(address.Bits())
return row.Create()
}
// AddIPAddresses method adds multiple new unicast IP addresses to the interface. Corresponds to CreateUnicastIpAddressEntry function
// (https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/nf-netioapi-createunicastipaddressentry).
-func (luid LUID) AddIPAddresses(addresses []net.IPNet) error {
+func (luid LUID) AddIPAddresses(addresses []netip.Prefix) error {
for i := range addresses {
err := luid.AddIPAddress(addresses[i])
if err != nil {
@@ -120,7 +122,7 @@ func (luid LUID) AddIPAddresses(addresses []net.IPNet) error {
}
// SetIPAddresses method sets new unicast IP addresses to the interface.
-func (luid LUID) SetIPAddresses(addresses []net.IPNet) error {
+func (luid LUID) SetIPAddresses(addresses []netip.Prefix) error {
err := luid.FlushIPAddresses(windows.AF_UNSPEC)
if err != nil {
return err
@@ -129,16 +131,15 @@ func (luid LUID) SetIPAddresses(addresses []net.IPNet) error {
}
// SetIPAddressesForFamily method sets new unicast IP addresses for a specific family to the interface.
-func (luid LUID) SetIPAddressesForFamily(family AddressFamily, addresses []net.IPNet) error {
+func (luid LUID) SetIPAddressesForFamily(family AddressFamily, addresses []netip.Prefix) error {
err := luid.FlushIPAddresses(family)
if err != nil {
return err
}
for i := range addresses {
- asV4 := addresses[i].IP.To4()
- if asV4 == nil && family == windows.AF_INET {
+ if !addresses[i].Addr().Is4() && family == windows.AF_INET {
continue
- } else if asV4 != nil && family == windows.AF_INET6 {
+ } else if !addresses[i].Addr().Is6() && family == windows.AF_INET6 {
continue
}
err := luid.AddIPAddress(addresses[i])
@@ -151,17 +152,16 @@ func (luid LUID) SetIPAddressesForFamily(family AddressFamily, addresses []net.I
// DeleteIPAddress method deletes interface's unicast IP address. Corresponds to DeleteUnicastIpAddressEntry function
// (https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/nf-netioapi-deleteunicastipaddressentry).
-func (luid LUID) DeleteIPAddress(address net.IPNet) error {
+func (luid LUID) DeleteIPAddress(address netip.Prefix) error {
row := &MibUnicastIPAddressRow{}
row.Init()
row.InterfaceLUID = luid
- err := row.Address.SetIP(address.IP, 0)
+ err := row.Address.SetAddr(address.Addr())
if err != nil {
return err
}
// Note: OnLinkPrefixLength member is ignored by DeleteUnicastIpAddressEntry().
- ones, _ := address.Mask.Size()
- row.OnLinkPrefixLength = uint8(ones)
+ row.OnLinkPrefixLength = uint8(address.Bits())
return row.Delete()
}
@@ -185,15 +185,17 @@ func (luid LUID) FlushIPAddresses(family AddressFamily) error {
// Route method returns route determined with the input arguments. Corresponds to GetIpForwardEntry2 function
// (https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/nf-netioapi-getipforwardentry2).
// NOTE: If the corresponding route isn't found, the method will return error.
-func (luid LUID) Route(destination net.IPNet, nextHop net.IP) (*MibIPforwardRow2, error) {
+func (luid LUID) Route(destination netip.Prefix, nextHop netip.Addr) (*MibIPforwardRow2, error) {
row := &MibIPforwardRow2{}
row.Init()
row.InterfaceLUID = luid
- err := row.DestinationPrefix.SetIPNet(destination)
+ row.ValidLifetime = 0xffffffff
+ row.PreferredLifetime = 0xffffffff
+ err := row.DestinationPrefix.SetPrefix(destination)
if err != nil {
return nil, err
}
- err = row.NextHop.SetIP(nextHop, 0)
+ err = row.NextHop.SetAddr(nextHop)
if err != nil {
return nil, err
}
@@ -207,15 +209,15 @@ func (luid LUID) Route(destination net.IPNet, nextHop net.IP) (*MibIPforwardRow2
// AddRoute method adds a route to the interface. Corresponds to CreateIpForwardEntry2 function, with added splitDefault feature.
// (https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/nf-netioapi-createipforwardentry2)
-func (luid LUID) AddRoute(destination net.IPNet, nextHop net.IP, metric uint32) error {
+func (luid LUID) AddRoute(destination netip.Prefix, nextHop netip.Addr, metric uint32) error {
row := &MibIPforwardRow2{}
row.Init()
row.InterfaceLUID = luid
- err := row.DestinationPrefix.SetIPNet(destination)
+ err := row.DestinationPrefix.SetPrefix(destination)
if err != nil {
return err
}
- err = row.NextHop.SetIP(nextHop, 0)
+ err = row.NextHop.SetAddr(nextHop)
if err != nil {
return err
}
@@ -250,10 +252,9 @@ func (luid LUID) SetRoutesForFamily(family AddressFamily, routesData []*RouteDat
return err
}
for _, rd := range routesData {
- asV4 := rd.Destination.IP.To4()
- if asV4 == nil && family == windows.AF_INET {
+ if !rd.Destination.Addr().Is4() && family == windows.AF_INET {
continue
- } else if asV4 != nil && family == windows.AF_INET6 {
+ } else if !rd.Destination.Addr().Is6() && family == windows.AF_INET6 {
continue
}
err := luid.AddRoute(rd.Destination, rd.NextHop, rd.Metric)
@@ -266,15 +267,15 @@ func (luid LUID) SetRoutesForFamily(family AddressFamily, routesData []*RouteDat
// DeleteRoute method deletes a route that matches the criteria. Corresponds to DeleteIpForwardEntry2 function
// (https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/nf-netioapi-deleteipforwardentry2).
-func (luid LUID) DeleteRoute(destination net.IPNet, nextHop net.IP) error {
+func (luid LUID) DeleteRoute(destination netip.Prefix, nextHop netip.Addr) error {
row := &MibIPforwardRow2{}
row.Init()
row.InterfaceLUID = luid
- err := row.DestinationPrefix.SetIPNet(destination)
+ err := row.DestinationPrefix.SetPrefix(destination)
if err != nil {
return err
}
- err = row.NextHop.SetIP(nextHop, 0)
+ err = row.NextHop.SetAddr(nextHop)
if err != nil {
return err
}
@@ -307,17 +308,19 @@ func (luid LUID) FlushRoutes(family AddressFamily) error {
}
// DNS method returns all DNS server addresses associated with the adapter.
-func (luid LUID) DNS() ([]net.IP, error) {
+func (luid LUID) DNS() ([]netip.Addr, error) {
addresses, err := GetAdaptersAddresses(windows.AF_UNSPEC, GAAFlagDefault)
if err != nil {
return nil, err
}
- r := make([]net.IP, 0, len(addresses))
+ r := make([]netip.Addr, 0, len(addresses))
for _, addr := range addresses {
if addr.LUID == luid {
for dns := addr.FirstDNSServerAddress; dns != nil; dns = dns.Next {
if ip := dns.Address.IP(); ip != nil {
- r = append(r, ip)
+ if a, ok := netip.AddrFromSlice(ip); ok {
+ r = append(r, a)
+ }
} else {
return nil, windows.ERROR_INVALID_PARAMETER
}
@@ -328,17 +331,15 @@ func (luid LUID) DNS() ([]net.IP, error) {
}
// SetDNS method clears previous and associates new DNS servers and search domains with the adapter for a specific family.
-func (luid LUID) SetDNS(family AddressFamily, servers []net.IP, domains []string) error {
+func (luid LUID) SetDNS(family AddressFamily, servers []netip.Addr, domains []string) error {
if family != windows.AF_INET && family != windows.AF_INET6 {
return windows.ERROR_PROTOCOL_UNREACHABLE
}
var filteredServers []string
for _, server := range servers {
- if v4 := server.To4(); v4 != nil && family == windows.AF_INET {
- filteredServers = append(filteredServers, v4.String())
- } else if v6 := server.To16(); v4 == nil && v6 != nil && family == windows.AF_INET6 {
- filteredServers = append(filteredServers, v6.String())
+ if (server.Is4() && family == windows.AF_INET) || (server.Is6() && family == windows.AF_INET6) {
+ filteredServers = append(filteredServers, server.String())
}
}
servers16, err := windows.UTF16PtrFromString(strings.Join(filteredServers, ","))
@@ -353,17 +354,17 @@ func (luid LUID) SetDNS(family AddressFamily, servers []net.IP, domains []string
if err != nil {
return err
}
- var maybeV6 uint64
+ dnsInterfaceSettings := &DnsInterfaceSettings{
+ Version: DnsInterfaceSettingsVersion1,
+ Flags: DnsInterfaceSettingsFlagNameserver | DnsInterfaceSettingsFlagSearchList,
+ NameServer: servers16,
+ SearchList: domains16,
+ }
if family == windows.AF_INET6 {
- maybeV6 = disFlagsIPv6
+ dnsInterfaceSettings.Flags |= DnsInterfaceSettingsFlagIPv6
}
// For >= Windows 10 1809
- err = setInterfaceDnsSettings(*guid, &dnsInterfaceSettings{
- Version: disVersion1,
- Flags: disFlagsNameServer | disFlagsSearchList | maybeV6,
- NameServer: servers16,
- SearchList: domains16,
- })
+ err = SetInterfaceDnsSettings(*guid, dnsInterfaceSettings)
if err == nil || !errors.Is(err, windows.ERROR_PROC_NOT_FOUND) {
return err
}
diff --git a/tunnel/winipcfg/mksyscall.go b/tunnel/winipcfg/mksyscall.go
index e9e06676..d62d38df 100644
--- a/tunnel/winipcfg/mksyscall.go
+++ b/tunnel/winipcfg/mksyscall.go
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package winipcfg
diff --git a/tunnel/winipcfg/netsh.go b/tunnel/winipcfg/netsh.go
index 1f3d12d0..4f8e5b13 100644
--- a/tunnel/winipcfg/netsh.go
+++ b/tunnel/winipcfg/netsh.go
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package winipcfg
@@ -10,7 +10,7 @@ import (
"errors"
"fmt"
"io"
- "net"
+ "net/netip"
"os/exec"
"path/filepath"
"strings"
@@ -57,7 +57,7 @@ const (
netshCmdTemplateAdd6 = "interface ipv6 add dnsservers name=%d address=%s validate=no"
)
-func (luid LUID) fallbackSetDNSForFamily(family AddressFamily, dnses []net.IP) error {
+func (luid LUID) fallbackSetDNSForFamily(family AddressFamily, dnses []netip.Addr) error {
var templateFlush string
if family == windows.AF_INET {
templateFlush = netshCmdTemplateFlush4
@@ -72,10 +72,10 @@ func (luid LUID) fallbackSetDNSForFamily(family AddressFamily, dnses []net.IP) e
}
cmds = append(cmds, fmt.Sprintf(templateFlush, ipif.InterfaceIndex))
for i := 0; i < len(dnses); i++ {
- if v4 := dnses[i].To4(); v4 != nil && family == windows.AF_INET {
- cmds = append(cmds, fmt.Sprintf(netshCmdTemplateAdd4, ipif.InterfaceIndex, v4.String()))
- } else if v6 := dnses[i].To16(); v4 == nil && v6 != nil && family == windows.AF_INET6 {
- cmds = append(cmds, fmt.Sprintf(netshCmdTemplateAdd6, ipif.InterfaceIndex, v6.String()))
+ if dnses[i].Is4() && family == windows.AF_INET {
+ cmds = append(cmds, fmt.Sprintf(netshCmdTemplateAdd4, ipif.InterfaceIndex, dnses[i].String()))
+ } else if dnses[i].Is6() && family == windows.AF_INET6 {
+ cmds = append(cmds, fmt.Sprintf(netshCmdTemplateAdd6, ipif.InterfaceIndex, dnses[i].String()))
}
}
return runNetsh(cmds)
diff --git a/tunnel/winipcfg/route_change_handler.go b/tunnel/winipcfg/route_change_handler.go
index 75dcf82c..4b78331e 100644
--- a/tunnel/winipcfg/route_change_handler.go
+++ b/tunnel/winipcfg/route_change_handler.go
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package winipcfg
diff --git a/tunnel/winipcfg/types.go b/tunnel/winipcfg/types.go
index 02f7f788..8e8f4a59 100644
--- a/tunnel/winipcfg/types.go
+++ b/tunnel/winipcfg/types.go
@@ -1,12 +1,15 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package winipcfg
import (
- "net"
+ "encoding/binary"
+ "fmt"
+ "net/netip"
+ "strconv"
"unsafe"
"golang.org/x/sys/windows"
@@ -582,11 +585,15 @@ const (
// RouteData structure describes a route to add
type RouteData struct {
- Destination net.IPNet
- NextHop net.IP
+ Destination netip.Prefix
+ NextHop netip.Addr
Metric uint32
}
+func (routeData *RouteData) String() string {
+ return fmt.Sprintf("%+v", *routeData)
+}
+
// IPAdapterDNSSuffix structure stores a DNS suffix in a linked list of DNS suffixes for a particular adapter.
// https://docs.microsoft.com/en-us/windows/desktop/api/iptypes/ns-iptypes-_ip_adapter_dns_suffix
type IPAdapterDNSSuffix struct {
@@ -679,8 +686,7 @@ func (row *MibIPInterfaceRow) Set() error {
// get method returns all table rows as a Go slice.
func (tab *mibIPInterfaceTable) get() (s []MibIPInterfaceRow) {
- unsafeSlice(unsafe.Pointer(&s), unsafe.Pointer(&tab.table[0]), int(tab.numEntries))
- return
+ return unsafe.Slice(&tab.table[0], tab.numEntries)
}
// free method frees the buffer allocated by the functions that return tables of network interfaces, addresses, and routes.
@@ -717,8 +723,7 @@ func (row *MibIfRow2) get() (ret error) {
// get method returns all table rows as a Go slice.
func (tab *mibIfTable2) get() (s []MibIfRow2) {
- unsafeSlice(unsafe.Pointer(&s), unsafe.Pointer(&tab.table[0]), int(tab.numEntries))
- return
+ return unsafe.Slice(&tab.table[0], tab.numEntries)
}
// free method frees the buffer allocated by the functions that return tables of network interfaces, addresses, and routes.
@@ -734,45 +739,82 @@ type RawSockaddrInet struct {
data [26]byte
}
-// SetIP method sets family, address, and port to the given IPv4 or IPv6 address and port.
+func ntohs(i uint16) uint16 {
+ return binary.BigEndian.Uint16((*[2]byte)(unsafe.Pointer(&i))[:])
+}
+
+func htons(i uint16) uint16 {
+ b := make([]byte, 2)
+ binary.BigEndian.PutUint16(b, i)
+ return *(*uint16)(unsafe.Pointer(&b[0]))
+}
+
+// SetAddrPort method sets family, address, and port to the given IPv4 or IPv6 address and port.
// All other members of the structure are set to zero.
-func (addr *RawSockaddrInet) SetIP(ip net.IP, port uint16) error {
- if v4 := ip.To4(); v4 != nil {
+func (addr *RawSockaddrInet) SetAddrPort(addrPort netip.AddrPort) error {
+ if addrPort.Addr().Is4() {
addr4 := (*windows.RawSockaddrInet4)(unsafe.Pointer(addr))
addr4.Family = windows.AF_INET
- copy(addr4.Addr[:], v4)
- addr4.Port = port
+ addr4.Addr = addrPort.Addr().As4()
+ addr4.Port = htons(addrPort.Port())
for i := 0; i < 8; i++ {
addr4.Zero[i] = 0
}
return nil
- }
-
- if v6 := ip.To16(); v6 != nil {
+ } else if addrPort.Addr().Is6() {
addr6 := (*windows.RawSockaddrInet6)(unsafe.Pointer(addr))
addr6.Family = windows.AF_INET6
- addr6.Port = port
+ addr6.Addr = addrPort.Addr().As16()
+ addr6.Port = htons(addrPort.Port())
addr6.Flowinfo = 0
- copy(addr6.Addr[:], v6)
- addr6.Scope_id = 0
+ scopeId := uint32(0)
+ if z := addrPort.Addr().Zone(); z != "" {
+ if s, err := strconv.ParseUint(z, 10, 32); err == nil {
+ scopeId = uint32(s)
+ }
+ }
+ addr6.Scope_id = scopeId
return nil
}
-
return windows.ERROR_INVALID_PARAMETER
}
-// IP method returns IPv4 or IPv6 address.
-// If the address is neither IPv4 not IPv6 nil is returned.
-func (addr *RawSockaddrInet) IP() net.IP {
+// SetAddr method sets family and address to the given IPv4 or IPv6 address.
+// All other members of the structure are set to zero.
+func (addr *RawSockaddrInet) SetAddr(netAddr netip.Addr) error {
+ return addr.SetAddrPort(netip.AddrPortFrom(netAddr, 0))
+}
+
+// AddrPort returns the IP address and port.
+func (addr *RawSockaddrInet) AddrPort() netip.AddrPort {
+ return netip.AddrPortFrom(addr.Addr(), addr.Port())
+}
+
+// Addr returns IPv4 or IPv6 address, or an invalid address if the address is neither.
+func (addr *RawSockaddrInet) Addr() netip.Addr {
switch addr.Family {
case windows.AF_INET:
- return (*windows.RawSockaddrInet4)(unsafe.Pointer(addr)).Addr[:]
-
+ return netip.AddrFrom4((*windows.RawSockaddrInet4)(unsafe.Pointer(addr)).Addr)
case windows.AF_INET6:
- return (*windows.RawSockaddrInet6)(unsafe.Pointer(addr)).Addr[:]
+ raw := (*windows.RawSockaddrInet6)(unsafe.Pointer(addr))
+ a := netip.AddrFrom16(raw.Addr)
+ if raw.Scope_id != 0 {
+ a = a.WithZone(strconv.FormatUint(uint64(raw.Scope_id), 10))
+ }
+ return a
}
+ return netip.Addr{}
+}
- return nil
+// Port returns the port if the address if IPv4 or IPv6, or 0 if neither.
+func (addr *RawSockaddrInet) Port() uint16 {
+ switch addr.Family {
+ case windows.AF_INET:
+ return ntohs((*windows.RawSockaddrInet4)(unsafe.Pointer(addr)).Port)
+ case windows.AF_INET6:
+ return ntohs((*windows.RawSockaddrInet6)(unsafe.Pointer(addr)).Port)
+ }
+ return 0
}
// Init method initializes a MibUnicastIPAddressRow structure with default values for a unicast IP address entry on the local computer.
@@ -807,8 +849,7 @@ func (row *MibUnicastIPAddressRow) Delete() error {
// get method returns all table rows as a Go slice.
func (tab *mibUnicastIPAddressTable) get() (s []MibUnicastIPAddressRow) {
- unsafeSlice(unsafe.Pointer(&s), unsafe.Pointer(&tab.table[0]), int(tab.numEntries))
- return
+ return unsafe.Slice(&tab.table[0], tab.numEntries)
}
// free method frees the buffer allocated by the functions that return tables of network interfaces, addresses, and routes.
@@ -837,8 +878,7 @@ func (row *MibAnycastIPAddressRow) Delete() error {
// get method returns all table rows as a Go slice.
func (tab *mibAnycastIPAddressTable) get() (s []MibAnycastIPAddressRow) {
- unsafeSlice(unsafe.Pointer(&s), unsafe.Pointer(&tab.table[0]), int(tab.numEntries))
- return
+ return unsafe.Slice(&tab.table[0], tab.numEntries)
}
// free method frees the buffer allocated by the functions that return tables of network interfaces, addresses, and routes.
@@ -850,32 +890,30 @@ func (tab *mibAnycastIPAddressTable) free() {
// IPAddressPrefix structure stores an IP address prefix.
// https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/ns-netioapi-_ip_address_prefix
type IPAddressPrefix struct {
- Prefix RawSockaddrInet
+ RawPrefix RawSockaddrInet
PrefixLength uint8
_ [2]byte
}
-// SetIPNet method sets IP address prefix using net.IPNet.
-func (prefix *IPAddressPrefix) SetIPNet(net net.IPNet) error {
- err := prefix.Prefix.SetIP(net.IP, 0)
+// SetPrefix method sets IP address prefix using netip.Prefix.
+func (prefix *IPAddressPrefix) SetPrefix(netPrefix netip.Prefix) error {
+ err := prefix.RawPrefix.SetAddr(netPrefix.Addr())
if err != nil {
return err
}
- ones, _ := net.Mask.Size()
- prefix.PrefixLength = uint8(ones)
+ prefix.PrefixLength = uint8(netPrefix.Bits())
return nil
}
-// IPNet method returns IP address prefix as net.IPNet.
-// If the address is neither IPv4 not IPv6 an empty net.IPNet is returned. The resulting net.IPNet should be checked appropriately.
-func (prefix *IPAddressPrefix) IPNet() net.IPNet {
- switch prefix.Prefix.Family {
+// Prefix returns IP address prefix as netip.Prefix.
+func (prefix *IPAddressPrefix) Prefix() netip.Prefix {
+ switch prefix.RawPrefix.Family {
case windows.AF_INET:
- return net.IPNet{IP: (*windows.RawSockaddrInet4)(unsafe.Pointer(&prefix.Prefix)).Addr[:], Mask: net.CIDRMask(int(prefix.PrefixLength), 8*net.IPv4len)}
+ return netip.PrefixFrom(netip.AddrFrom4((*windows.RawSockaddrInet4)(unsafe.Pointer(&prefix.RawPrefix)).Addr), int(prefix.PrefixLength))
case windows.AF_INET6:
- return net.IPNet{IP: (*windows.RawSockaddrInet6)(unsafe.Pointer(&prefix.Prefix)).Addr[:], Mask: net.CIDRMask(int(prefix.PrefixLength), 8*net.IPv6len)}
+ return netip.PrefixFrom(netip.AddrFrom16((*windows.RawSockaddrInet6)(unsafe.Pointer(&prefix.RawPrefix)).Addr), int(prefix.PrefixLength))
}
- return net.IPNet{}
+ return netip.Prefix{}
}
// MibIPforwardRow2 structure stores information about an IP route entry.
@@ -930,8 +968,7 @@ func (row *MibIPforwardRow2) Delete() error {
// get method returns all table rows as a Go slice.
func (tab *mibIPforwardTable2) get() (s []MibIPforwardRow2) {
- unsafeSlice(unsafe.Pointer(&s), unsafe.Pointer(&tab.table[0]), int(tab.numEntries))
- return
+ return unsafe.Slice(&tab.table[0], tab.numEntries)
}
// free method frees the buffer allocated by the functions that return tables of network interfaces, addresses, and routes.
@@ -941,11 +978,11 @@ func (tab *mibIPforwardTable2) free() {
}
//
-// Undocumented DNS API
+// DNS API
//
-// dnsInterfaceSettings is mean to be used with setInterfaceDnsSettings
-type dnsInterfaceSettings struct {
+// DnsInterfaceSettings is meant to be used with SetInterfaceDnsSettings
+type DnsInterfaceSettings struct {
Version uint32
_ [4]byte
Flags uint64
@@ -960,37 +997,22 @@ type dnsInterfaceSettings struct {
}
const (
- disVersion1 = 1
- disVersion2 = 2
-
- disFlagsIPv6 = 0x1
- disFlagsNameServer = 0x2
- disFlagsSearchList = 0x4
- disFlagsRegistrationEnabled = 0x8
- disFlagsRegisterAdapterName = 0x10
- disFlagsDomain = 0x20
- disFlagsHostname = 0x40 // ??
- disFlagsEnableLLMNR = 0x80
- disFlagsQueryAdapterName = 0x100
- disFlagsProfileNameServer = 0x200
- disFlagsVersion2 = 0x400 // ?? - v2 only
- disFlagsMoreFlags = 0x800 // ?? - v2 only
+ DnsInterfaceSettingsVersion1 = 1 // for DnsInterfaceSettings
+ DnsInterfaceSettingsVersion2 = 2 // for DnsInterfaceSettingsEx
+ DnsInterfaceSettingsVersion3 = 3 // for DnsInterfaceSettings3
+
+ DnsInterfaceSettingsFlagIPv6 = 0x0001
+ DnsInterfaceSettingsFlagNameserver = 0x0002
+ DnsInterfaceSettingsFlagSearchList = 0x0004
+ DnsInterfaceSettingsFlagRegistrationEnabled = 0x0008
+ DnsInterfaceSettingsFlagRegisterAdapterName = 0x0010
+ DnsInterfaceSettingsFlagDomain = 0x0020
+ DnsInterfaceSettingsFlagHostname = 0x0040
+ DnsInterfaceSettingsFlagEnableLLMNR = 0x0080
+ DnsInterfaceSettingsFlagQueryAdapterName = 0x0100
+ DnsInterfaceSettingsFlagProfileNameserver = 0x0200
+ DnsInterfaceSettingsFlagDisableUnconstrainedQueries = 0x0400 // v2 only
+ DnsInterfaceSettingsFlagSupplementalSearchList = 0x0800 // v2 only
+ DnsInterfaceSettingsFlagDOH = 0x1000 // v3 only
+ DnsInterfaceSettingsFlagDOHProfile = 0x2000 // v3 only
)
-
-// unsafeSlice updates the slice slicePtr to be a slice
-// referencing the provided data with its length & capacity set to
-// lenCap.
-//
-// TODO: when Go 1.16 or Go 1.17 is the minimum supported version,
-// update callers to use unsafe.Slice instead of this.
-func unsafeSlice(slicePtr, data unsafe.Pointer, lenCap int) {
- type sliceHeader struct {
- Data unsafe.Pointer
- Len int
- Cap int
- }
- h := (*sliceHeader)(slicePtr)
- h.Data = data
- h.Len = lenCap
- h.Cap = lenCap
-}
diff --git a/tunnel/winipcfg/types_32.go b/tunnel/winipcfg/types_32.go
index 51a8d31c..1a8d4443 100644
--- a/tunnel/winipcfg/types_32.go
+++ b/tunnel/winipcfg/types_32.go
@@ -1,8 +1,8 @@
-// +build 386 arm
+//go:build 386 || arm
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package winipcfg
diff --git a/tunnel/winipcfg/types_64.go b/tunnel/winipcfg/types_64.go
index 6623ce54..3a1fe07f 100644
--- a/tunnel/winipcfg/types_64.go
+++ b/tunnel/winipcfg/types_64.go
@@ -1,8 +1,8 @@
-// +build amd64 arm64
+//go:build amd64 || arm64
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package winipcfg
diff --git a/tunnel/winipcfg/types_test.go b/tunnel/winipcfg/types_test.go
index 26268dbe..b72d73f5 100644
--- a/tunnel/winipcfg/types_test.go
+++ b/tunnel/winipcfg/types_test.go
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package winipcfg
@@ -957,7 +957,6 @@ func TestIPAddressPrefix(t *testing.T) {
offset := uintptr(unsafe.Pointer(&s.PrefixLength)) - sp
if offset != ipAddressPrefixPrefixLengthOffset {
t.Errorf("IPAddressPrefix.PrefixLength offset is %d although %d is expected", offset, ipAddressPrefixPrefixLengthOffset)
-
}
}
diff --git a/tunnel/winipcfg/types_test_32.go b/tunnel/winipcfg/types_test_32.go
index fa3f91d5..9e62bfef 100644
--- a/tunnel/winipcfg/types_test_32.go
+++ b/tunnel/winipcfg/types_test_32.go
@@ -1,8 +1,8 @@
-// +build 386 arm
+//go:build 386 || arm
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package winipcfg
diff --git a/tunnel/winipcfg/types_test_64.go b/tunnel/winipcfg/types_test_64.go
index d20cdb30..8a181575 100644
--- a/tunnel/winipcfg/types_test_64.go
+++ b/tunnel/winipcfg/types_test_64.go
@@ -1,8 +1,8 @@
-// +build amd64 arm64
+//go:build amd64 || arm64
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package winipcfg
diff --git a/tunnel/winipcfg/unicast_address_change_handler.go b/tunnel/winipcfg/unicast_address_change_handler.go
index 517ff037..cf4fcb3a 100644
--- a/tunnel/winipcfg/unicast_address_change_handler.go
+++ b/tunnel/winipcfg/unicast_address_change_handler.go
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package winipcfg
diff --git a/tunnel/winipcfg/winipcfg.go b/tunnel/winipcfg/winipcfg.go
index dd09d3a0..e24157b9 100644
--- a/tunnel/winipcfg/winipcfg.go
+++ b/tunnel/winipcfg/winipcfg.go
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package winipcfg
@@ -170,18 +170,18 @@ func GetIPForwardTable2(family AddressFamily) ([]MibIPforwardRow2, error) {
//sys cancelMibChangeNotify2(notificationHandle windows.Handle) (ret error) = iphlpapi.CancelMibChangeNotify2
//
-// Undocumented DNS API
+// DNS-related functions
//
-//sys setInterfaceDnsSettingsByPtr(guid *windows.GUID, settings *dnsInterfaceSettings) (ret error) = iphlpapi.SetInterfaceDnsSettings?
-//sys setInterfaceDnsSettingsByQwords(guid1 uintptr, guid2 uintptr, settings *dnsInterfaceSettings) (ret error) = iphlpapi.SetInterfaceDnsSettings?
-//sys setInterfaceDnsSettingsByDwords(guid1 uintptr, guid2 uintptr, guid3 uintptr, guid4 uintptr, settings *dnsInterfaceSettings) (ret error) = iphlpapi.SetInterfaceDnsSettings?
+//sys setInterfaceDnsSettingsByPtr(guid *windows.GUID, settings *DnsInterfaceSettings) (ret error) = iphlpapi.SetInterfaceDnsSettings?
+//sys setInterfaceDnsSettingsByQwords(guid1 uintptr, guid2 uintptr, settings *DnsInterfaceSettings) (ret error) = iphlpapi.SetInterfaceDnsSettings?
+//sys setInterfaceDnsSettingsByDwords(guid1 uintptr, guid2 uintptr, guid3 uintptr, guid4 uintptr, settings *DnsInterfaceSettings) (ret error) = iphlpapi.SetInterfaceDnsSettings?
// The GUID is passed by value, not by reference, which means different
// things on different calling conventions. On amd64, this means it's
// passed by reference anyway, while on arm, arm64, and 386, it's split
// into words.
-func setInterfaceDnsSettings(guid windows.GUID, settings *dnsInterfaceSettings) error {
+func SetInterfaceDnsSettings(guid windows.GUID, settings *DnsInterfaceSettings) error {
words := (*[4]uintptr)(unsafe.Pointer(&guid))
switch runtime.GOARCH {
case "amd64":
diff --git a/tunnel/winipcfg/winipcfg_test.go b/tunnel/winipcfg/winipcfg_test.go
index 7689a0c1..b49daf33 100644
--- a/tunnel/winipcfg/winipcfg_test.go
+++ b/tunnel/winipcfg/winipcfg_test.go
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
/*
@@ -8,8 +8,8 @@
Some tests in this file require:
- A dedicated network adapter
- Any network adapter will do. It may be virtual (Wintun etc.). The adapter name
- must contain string "winipcfg_test".
+ Any network adapter will do. It may be virtual (WireGuardNT, Wintun,
+ etc.). The adapter name must contain string "winipcfg_test".
Tests will add, remove, flush DNS servers, change adapter IP address, manipulate
routes etc.
The adapter will not be returned to previous state, so use an expendable one.
@@ -22,8 +22,7 @@ Some tests in this file require:
package winipcfg
import (
- "bytes"
- "net"
+ "net/netip"
"strings"
"syscall"
"testing"
@@ -38,22 +37,13 @@ const (
// TODO: Add IPv6 tests.
var (
- unexistentIPAddresToAdd = net.IPNet{
- IP: net.IP{172, 16, 1, 114},
- Mask: net.IPMask{255, 255, 255, 0},
- }
- unexistentRouteIPv4ToAdd = RouteData{
- Destination: net.IPNet{
- IP: net.IP{172, 16, 200, 0},
- Mask: net.IPMask{255, 255, 255, 0},
- },
- NextHop: net.IP{172, 16, 1, 2},
- Metric: 0,
- }
- dnsesToSet = []net.IP{
- net.IPv4(8, 8, 8, 8),
- net.IPv4(8, 8, 4, 4),
+ nonexistantIPv4ToAdd = netip.MustParsePrefix("172.16.1.114/24")
+ nonexistentRouteIPv4ToAdd = RouteData{
+ Destination: netip.MustParsePrefix("172.16.200.0/24"),
+ NextHop: netip.MustParseAddr("172.16.1.2"),
+ Metric: 0,
}
+ dnsesToSet = []netip.Addr{netip.MustParseAddr("8.8.8.8"), netip.MustParseAddr("8.8.4.4")}
)
func runningElevated() bool {
@@ -74,7 +64,7 @@ func getTestInterface() (*IPAdapterAddresses, error) {
marker := strings.ToLower(testInterfaceMarker)
for _, ifc := range ifcs {
- if strings.Index(strings.ToLower(ifc.FriendlyName()), marker) != -1 {
+ if strings.Contains(strings.ToLower(ifc.FriendlyName()), marker) {
return ifc, nil
}
}
@@ -380,9 +370,9 @@ func TestAddDeleteIPAddress(t *testing.T) {
return
}
- addr, err := ifc.LUID.IPAddress(unexistentIPAddresToAdd.IP)
+ addr, err := ifc.LUID.IPAddress(nonexistantIPv4ToAdd.Addr())
if err == nil {
- t.Errorf("Unicast address %s already exists. Please set unexistentIPAddresToAdd appropriately.", unexistentIPAddresToAdd.IP.String())
+ t.Errorf("Unicast address %s already exists. Please set nonexistantIPv4ToAdd appropriately.", nonexistantIPv4ToAdd.Addr().String())
return
} else if err != windows.ERROR_NOT_FOUND {
t.Errorf("LUID.IPAddress() returned an error: %w", err)
@@ -410,7 +400,7 @@ func TestAddDeleteIPAddress(t *testing.T) {
for addr := ifc.FirstUnicastAddress; addr != nil; addr = addr.Next {
count--
}
- err = ifc.LUID.AddIPAddresses([]net.IPNet{unexistentIPAddresToAdd})
+ err = ifc.LUID.AddIPAddresses([]netip.Prefix{nonexistantIPv4ToAdd})
if err != nil {
t.Errorf("LUID.AddIPAddresses() returned an error: %w", err)
}
@@ -424,26 +414,26 @@ func TestAddDeleteIPAddress(t *testing.T) {
if count != 1 {
t.Errorf("After adding there are %d new interface(s).", count)
}
- addr, err = ifc.LUID.IPAddress(unexistentIPAddresToAdd.IP)
+ addr, err = ifc.LUID.IPAddress(nonexistantIPv4ToAdd.Addr())
if err != nil {
t.Errorf("LUID.IPAddress() returned an error: %w", err)
} else if addr == nil {
- t.Errorf("Unicast address %s still doesn't exist, although it's added successfully.", unexistentIPAddresToAdd.IP.String())
+ t.Errorf("Unicast address %s still doesn't exist, although it's added successfully.", nonexistantIPv4ToAdd.Addr().String())
}
if !created {
t.Errorf("Notification handler has not been called on add.")
}
- err = ifc.LUID.DeleteIPAddress(unexistentIPAddresToAdd)
+ err = ifc.LUID.DeleteIPAddress(nonexistantIPv4ToAdd)
if err != nil {
t.Errorf("LUID.DeleteIPAddress() returned an error: %w", err)
}
time.Sleep(500 * time.Millisecond)
- addr, err = ifc.LUID.IPAddress(unexistentIPAddresToAdd.IP)
+ addr, err = ifc.LUID.IPAddress(nonexistantIPv4ToAdd.Addr())
if err == nil {
- t.Errorf("Unicast address %s still exists, although it's deleted successfully.", unexistentIPAddresToAdd.IP.String())
+ t.Errorf("Unicast address %s still exists, although it's deleted successfully.", nonexistantIPv4ToAdd.Addr().String())
} else if err != windows.ERROR_NOT_FOUND {
t.Errorf("LUID.IPAddress() returned an error: %w", err)
}
@@ -460,14 +450,13 @@ func TestGetRoutes(t *testing.T) {
}
func TestAddDeleteRoute(t *testing.T) {
- findRoute := func(luid LUID, dest net.IPNet) ([]MibIPforwardRow2, error) {
+ findRoute := func(luid LUID, dest netip.Prefix) ([]MibIPforwardRow2, error) {
var family AddressFamily
- switch {
- case dest.IP.To4() != nil:
+ if dest.Addr().Is4() {
family = windows.AF_INET
- case dest.IP.To16() != nil:
+ } else if dest.Addr().Is6() {
family = windows.AF_INET6
- default:
+ } else {
return nil, windows.ERROR_INVALID_PARAMETER
}
r, err := GetIPForwardTable2(family)
@@ -475,9 +464,8 @@ func TestAddDeleteRoute(t *testing.T) {
return nil, err
}
matches := make([]MibIPforwardRow2, 0, len(r))
- ones, _ := dest.Mask.Size()
for _, route := range r {
- if route.InterfaceLUID == luid && route.DestinationPrefix.PrefixLength == uint8(ones) && route.DestinationPrefix.Prefix.Family == family && route.DestinationPrefix.Prefix.IP().Equal(dest.IP) {
+ if route.InterfaceLUID == luid && route.DestinationPrefix.PrefixLength == uint8(dest.Bits()) && route.DestinationPrefix.RawPrefix.Family == family && route.DestinationPrefix.RawPrefix.Addr() == dest.Addr() {
matches = append(matches, route)
}
}
@@ -494,20 +482,20 @@ func TestAddDeleteRoute(t *testing.T) {
return
}
- _, err = ifc.LUID.Route(unexistentRouteIPv4ToAdd.Destination, unexistentRouteIPv4ToAdd.NextHop)
+ _, err = ifc.LUID.Route(nonexistentRouteIPv4ToAdd.Destination, nonexistentRouteIPv4ToAdd.NextHop)
if err == nil {
- t.Error("LUID.Route() returned a route although it isn't added yet. Have you forgot to set unexistentRouteIPv4ToAdd appropriately?")
+ t.Error("LUID.Route() returned a route although it isn't added yet. Have you forgot to set nonexistentRouteIPv4ToAdd appropriately?")
return
} else if err != windows.ERROR_NOT_FOUND {
t.Errorf("LUID.Route() returned an error: %w", err)
return
}
- routes, err := findRoute(ifc.LUID, unexistentRouteIPv4ToAdd.Destination)
+ routes, err := findRoute(ifc.LUID, nonexistentRouteIPv4ToAdd.Destination)
if err != nil {
t.Errorf("findRoute() returned an error: %w", err)
} else if len(routes) != 0 {
- t.Errorf("findRoute() returned %d items although the route isn't added yet. Have you forgot to set unexistentRouteIPv4ToAdd appropriately?", len(routes))
+ t.Errorf("findRoute() returned %d items although the route isn't added yet. Have you forgot to set nonexistentRouteIPv4ToAdd appropriately?", len(routes))
}
var created, deleted bool
@@ -524,42 +512,42 @@ func TestAddDeleteRoute(t *testing.T) {
} else {
defer cb.Unregister()
}
- err = ifc.LUID.AddRoute(unexistentRouteIPv4ToAdd.Destination, unexistentRouteIPv4ToAdd.NextHop, unexistentRouteIPv4ToAdd.Metric)
+ err = ifc.LUID.AddRoute(nonexistentRouteIPv4ToAdd.Destination, nonexistentRouteIPv4ToAdd.NextHop, nonexistentRouteIPv4ToAdd.Metric)
if err != nil {
t.Errorf("LUID.AddRoute() returned an error: %w", err)
}
time.Sleep(500 * time.Millisecond)
- route, err := ifc.LUID.Route(unexistentRouteIPv4ToAdd.Destination, unexistentRouteIPv4ToAdd.NextHop)
+ route, err := ifc.LUID.Route(nonexistentRouteIPv4ToAdd.Destination, nonexistentRouteIPv4ToAdd.NextHop)
if err == windows.ERROR_NOT_FOUND {
t.Error("LUID.Route() returned nil although the route is added successfully.")
} else if err != nil {
t.Errorf("LUID.Route() returned an error: %w", err)
- } else if !route.DestinationPrefix.Prefix.IP().Equal(unexistentRouteIPv4ToAdd.Destination.IP) || !route.NextHop.IP().Equal(unexistentRouteIPv4ToAdd.NextHop) {
+ } else if route.DestinationPrefix.RawPrefix.Addr() != nonexistentRouteIPv4ToAdd.Destination.Addr() || route.NextHop.Addr() != nonexistentRouteIPv4ToAdd.NextHop {
t.Error("LUID.Route() returned a wrong route!")
}
if !created {
t.Errorf("Route handler has not been called on add.")
}
- routes, err = findRoute(ifc.LUID, unexistentRouteIPv4ToAdd.Destination)
+ routes, err = findRoute(ifc.LUID, nonexistentRouteIPv4ToAdd.Destination)
if err != nil {
t.Errorf("findRoute() returned an error: %w", err)
} else if len(routes) != 1 {
t.Errorf("findRoute() returned %d items although %d is expected.", len(routes), 1)
- } else if !routes[0].DestinationPrefix.Prefix.IP().Equal(unexistentRouteIPv4ToAdd.Destination.IP) {
- t.Errorf("findRoute() returned a wrong route. Dest: %s; expected: %s.", routes[0].DestinationPrefix.Prefix.IP().String(), unexistentRouteIPv4ToAdd.Destination.IP.String())
+ } else if routes[0].DestinationPrefix.RawPrefix.Addr() != nonexistentRouteIPv4ToAdd.Destination.Addr() {
+ t.Errorf("findRoute() returned a wrong route. Dest: %s; expected: %s.", routes[0].DestinationPrefix.RawPrefix.Addr().String(), nonexistentRouteIPv4ToAdd.Destination.Addr().String())
}
- err = ifc.LUID.DeleteRoute(unexistentRouteIPv4ToAdd.Destination, unexistentRouteIPv4ToAdd.NextHop)
+ err = ifc.LUID.DeleteRoute(nonexistentRouteIPv4ToAdd.Destination, nonexistentRouteIPv4ToAdd.NextHop)
if err != nil {
t.Errorf("LUID.DeleteRoute() returned an error: %w", err)
}
time.Sleep(500 * time.Millisecond)
- _, err = ifc.LUID.Route(unexistentRouteIPv4ToAdd.Destination, unexistentRouteIPv4ToAdd.NextHop)
+ _, err = ifc.LUID.Route(nonexistentRouteIPv4ToAdd.Destination, nonexistentRouteIPv4ToAdd.NextHop)
if err == nil {
t.Error("LUID.Route() returned a route although it is removed successfully.")
} else if err != windows.ERROR_NOT_FOUND {
@@ -569,7 +557,7 @@ func TestAddDeleteRoute(t *testing.T) {
t.Errorf("Route handler has not been called on delete.")
}
- routes, err = findRoute(ifc.LUID, unexistentRouteIPv4ToAdd.Destination)
+ routes, err = findRoute(ifc.LUID, nonexistentRouteIPv4ToAdd.Destination)
if err != nil {
t.Errorf("findRoute() returned an error: %w", err)
} else if len(routes) != 0 {
@@ -606,7 +594,7 @@ func TestFlushDNS(t *testing.T) {
t.Errorf("LUID.DNS() returned an error: %w", err)
}
for _, a := range dns {
- if len(a) != 16 || a.To4() != nil || !((a[15] == 1 || a[15] == 2 || a[15] == 3) && bytes.HasPrefix(a, []byte{0xfe, 0xc0, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00})) {
+ if a.Is4() {
n++
}
}
@@ -651,7 +639,7 @@ func TestSetDNS(t *testing.T) {
t.Errorf("dnsesToSet contains %d items, while DNSServerAddresses contains %d.", len(dnsesToSet), len(newDNSes))
} else {
for i := range dnsesToSet {
- if !dnsesToSet[i].Equal(newDNSes[i]) {
+ if dnsesToSet[i] != newDNSes[i] {
t.Errorf("dnsesToSet[%d] = %s while DNSServerAddresses[%d] = %s.", i, dnsesToSet[i].String(), i, newDNSes[i].String())
}
}
diff --git a/tunnel/winipcfg/zwinipcfg_windows.go b/tunnel/winipcfg/zwinipcfg_windows.go
index ac89fec1..3a0d8680 100644
--- a/tunnel/winipcfg/zwinipcfg_windows.go
+++ b/tunnel/winipcfg/zwinipcfg_windows.go
@@ -289,7 +289,7 @@ func notifyUnicastIPAddressChange(family AddressFamily, callback uintptr, caller
return
}
-func setInterfaceDnsSettingsByDwords(guid1 uintptr, guid2 uintptr, guid3 uintptr, guid4 uintptr, settings *dnsInterfaceSettings) (ret error) {
+func setInterfaceDnsSettingsByDwords(guid1 uintptr, guid2 uintptr, guid3 uintptr, guid4 uintptr, settings *DnsInterfaceSettings) (ret error) {
ret = procSetInterfaceDnsSettings.Find()
if ret != nil {
return
@@ -301,24 +301,24 @@ func setInterfaceDnsSettingsByDwords(guid1 uintptr, guid2 uintptr, guid3 uintptr
return
}
-func setInterfaceDnsSettingsByPtr(guid *windows.GUID, settings *dnsInterfaceSettings) (ret error) {
+func setInterfaceDnsSettingsByQwords(guid1 uintptr, guid2 uintptr, settings *DnsInterfaceSettings) (ret error) {
ret = procSetInterfaceDnsSettings.Find()
if ret != nil {
return
}
- r0, _, _ := syscall.Syscall(procSetInterfaceDnsSettings.Addr(), 2, uintptr(unsafe.Pointer(guid)), uintptr(unsafe.Pointer(settings)), 0)
+ r0, _, _ := syscall.Syscall(procSetInterfaceDnsSettings.Addr(), 3, uintptr(guid1), uintptr(guid2), uintptr(unsafe.Pointer(settings)))
if r0 != 0 {
ret = syscall.Errno(r0)
}
return
}
-func setInterfaceDnsSettingsByQwords(guid1 uintptr, guid2 uintptr, settings *dnsInterfaceSettings) (ret error) {
+func setInterfaceDnsSettingsByPtr(guid *windows.GUID, settings *DnsInterfaceSettings) (ret error) {
ret = procSetInterfaceDnsSettings.Find()
if ret != nil {
return
}
- r0, _, _ := syscall.Syscall(procSetInterfaceDnsSettings.Addr(), 3, uintptr(guid1), uintptr(guid2), uintptr(unsafe.Pointer(settings)))
+ r0, _, _ := syscall.Syscall(procSetInterfaceDnsSettings.Addr(), 2, uintptr(unsafe.Pointer(guid)), uintptr(unsafe.Pointer(settings)), 0)
if r0 != 0 {
ret = syscall.Errno(r0)
}
diff --git a/tunnel/wintun_test.go b/tunnel/wintun_test.go
deleted file mode 100644
index 4e56ff65..00000000
--- a/tunnel/wintun_test.go
+++ /dev/null
@@ -1,202 +0,0 @@
-/* SPDX-License-Identifier: MIT
- *
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
- */
-
-package tunnel_test
-
-import (
- "bytes"
- "crypto/rand"
- "encoding/binary"
- "fmt"
- "net"
- "sync"
- "testing"
- "time"
-
- "golang.org/x/sys/windows"
-
- "golang.zx2c4.com/wireguard/tun"
-
- "golang.zx2c4.com/wireguard/windows/elevate"
- "golang.zx2c4.com/wireguard/windows/tunnel/winipcfg"
-)
-
-func TestWintunOrdering(t *testing.T) {
- var tunDevice tun.Device
- err := elevate.DoAsSystem(func() error {
- var err error
- tunDevice, err = tun.CreateTUNWithRequestedGUID("tunordertest", &windows.GUID{12, 12, 12, [8]byte{12, 12, 12, 12, 12, 12, 12, 12}}, 1500)
- return err
- })
- if err != nil {
- t.Fatal(err)
- }
- defer tunDevice.Close()
- nativeTunDevice := tunDevice.(*tun.NativeTun)
- luid := winipcfg.LUID(nativeTunDevice.LUID())
- ip, ipnet, _ := net.ParseCIDR("10.82.31.4/24")
- err = luid.SetIPAddresses([]net.IPNet{{ip, ipnet.Mask}})
- if err != nil {
- t.Fatal(err)
- }
- err = luid.SetRoutes([]*winipcfg.RouteData{{*ipnet, ipnet.IP, 0}})
- if err != nil {
- t.Fatal(err)
- }
- var token [32]byte
- _, err = rand.Read(token[:])
- if err != nil {
- t.Fatal(err)
- }
- var sockWrite net.Conn
- for i := 0; i < 1000; i++ {
- sockWrite, err = net.Dial("udp", "10.82.31.5:9999")
- if err == nil {
- defer sockWrite.Close()
- break
- }
- time.Sleep(time.Millisecond * 100)
- }
- if err != nil {
- t.Fatal(err)
- }
- var sockRead *net.UDPConn
- for i := 0; i < 1000; i++ {
- var listenAddress *net.UDPAddr
- listenAddress, err = net.ResolveUDPAddr("udp", "10.82.31.4:9999")
- if err != nil {
- continue
- }
- sockRead, err = net.ListenUDP("udp", listenAddress)
- if err == nil {
- defer sockRead.Close()
- break
- }
- time.Sleep(time.Millisecond * 100)
- }
- if err != nil {
- t.Fatal(err)
- }
- var wait sync.WaitGroup
- wait.Add(4)
- doneSockWrite := false
- doneTunWrite := false
- fatalErrors := make(chan error, 2)
- errors := make(chan error, 2)
- go func() {
- defer wait.Done()
- buffer := append(token[:], 0, 0, 0, 0, 0, 0, 0, 0)
- for sendingIndex := uint64(0); !doneSockWrite; sendingIndex++ {
- binary.LittleEndian.PutUint64(buffer[32:], sendingIndex)
- _, err := sockWrite.Write(buffer[:])
- if err != nil {
- fatalErrors <- err
- }
- }
- }()
- go func() {
- defer wait.Done()
- packet := [20 + 8 + 32 + 8]byte{
- 0x45, 0, 0, 20 + 8 + 32 + 8,
- 0, 0, 0, 0,
- 0x80, 0x11, 0, 0,
- 10, 82, 31, 5,
- 10, 82, 31, 4,
- 8888 >> 8, 8888 & 0xff, 9999 >> 8, 9999 & 0xff, 0, 8 + 32 + 8, 0, 0,
- }
- copy(packet[28:], token[:])
- for sendingIndex := uint64(0); !doneTunWrite; sendingIndex++ {
- binary.BigEndian.PutUint16(packet[4:], uint16(sendingIndex))
- var checksum uint32
- for i := 0; i < 20; i += 2 {
- if i != 10 {
- checksum += uint32(binary.BigEndian.Uint16(packet[i:]))
- }
- }
- binary.BigEndian.PutUint16(packet[10:], ^(uint16(checksum>>16) + uint16(checksum&0xffff)))
- binary.LittleEndian.PutUint64(packet[20+8+32:], sendingIndex)
- n, err := tunDevice.Write(packet[:], 0)
- if err != nil {
- fatalErrors <- err
- }
- if n == 0 {
- time.Sleep(time.Millisecond * 300)
- }
- }
- }()
- const packetsPerTest = 1 << 21
- go func() {
- defer func() {
- doneSockWrite = true
- wait.Done()
- }()
- var expectedIndex uint64
- for i := uint64(0); i < packetsPerTest; {
- var buffer [(1 << 16) - 1]byte
- bytesRead, err := tunDevice.Read(buffer[:], 0)
- if err != nil {
- fatalErrors <- err
- }
- if bytesRead < 0 || bytesRead > len(buffer) {
- continue
- }
- packet := buffer[:bytesRead]
- tokenPos := bytes.Index(packet, token[:])
- if tokenPos == -1 || tokenPos+32+8 > len(packet) {
- continue
- }
- foundIndex := binary.LittleEndian.Uint64(packet[tokenPos+32:])
- if foundIndex < expectedIndex {
- errors <- fmt.Errorf("Sock write, tun read: expected packet %d, received packet %d", expectedIndex, foundIndex)
- }
- expectedIndex = foundIndex + 1
- i++
- }
- }()
- go func() {
- defer func() {
- doneTunWrite = true
- wait.Done()
- }()
- var expectedIndex uint64
- for i := uint64(0); i < packetsPerTest; {
- var buffer [(1 << 16) - 1]byte
- bytesRead, err := sockRead.Read(buffer[:])
- if err != nil {
- fatalErrors <- err
- }
- if bytesRead < 0 || bytesRead > len(buffer) {
- continue
- }
- packet := buffer[:bytesRead]
- if len(packet) != 32+8 || !bytes.HasPrefix(packet, token[:]) {
- continue
- }
- foundIndex := binary.LittleEndian.Uint64(packet[32:])
- if foundIndex < expectedIndex {
- errors <- fmt.Errorf("Tun write, sock read: expected packet %d, received packet %d", expectedIndex, foundIndex)
- }
- expectedIndex = foundIndex + 1
- i++
- }
- }()
- done := make(chan bool, 2)
- doneFunc := func() {
- wait.Wait()
- done <- true
- }
- defer doneFunc()
- go doneFunc()
- for {
- select {
- case err := <-fatalErrors:
- t.Fatal(err)
- case err := <-errors:
- t.Error(err)
- case <-done:
- return
- }
- }
-}
diff --git a/ui/aboutdialog.go b/ui/aboutdialog.go
index f9be1f90..0f939b15 100644
--- a/ui/aboutdialog.go
+++ b/ui/aboutdialog.go
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package ui
@@ -12,13 +12,16 @@ import (
"github.com/lxn/walk"
"github.com/lxn/win"
"golang.org/x/sys/windows"
+ "golang.zx2c4.com/wireguard/windows/driver"
"golang.zx2c4.com/wireguard/windows/l18n"
"golang.zx2c4.com/wireguard/windows/version"
)
-var easterEggIndex = -1
-var showingAboutDialog *walk.Dialog
+var (
+ easterEggIndex = -1
+ showingAboutDialog *walk.Dialog
+)
func onAbout(owner walk.Form) {
showError(runAboutDialog(owner), owner)
@@ -95,7 +98,7 @@ func runAboutDialog(owner walk.Form) error {
return err
}
detailsLbl.SetTextAlignment(walk.AlignHCenterVNear)
- detailsLbl.SetText(l18n.Sprintf("App version: %s\nGo backend version: %s\nGo version: %s-%s\nOperating system: %s\nArchitecture: %s", version.Number, version.ProtoImplementation(), strings.TrimPrefix(runtime.Version(), "go"), runtime.GOARCH, version.OsName(), version.Arch()))
+ detailsLbl.SetText(l18n.Sprintf("App version: %s\nDriver version: %s\nGo version: %s\nOperating system: %s\nArchitecture: %s", version.Number, driver.Version(), strings.TrimPrefix(runtime.Version(), "go"), version.OsName(), version.Arch()))
copyrightLbl, err := walk.NewTextLabel(showingAboutDialog)
if err != nil {
@@ -104,7 +107,7 @@ func runAboutDialog(owner walk.Form) error {
copyrightFont, _ := walk.NewFont("Segoe UI", 7, 0)
copyrightLbl.SetFont(copyrightFont)
copyrightLbl.SetTextAlignment(walk.AlignHCenterVNear)
- copyrightLbl.SetText("Copyright © 2015-2021 Jason A. Donenfeld. All Rights Reserved.")
+ copyrightLbl.SetText("Copyright © 2015-2022 Jason A. Donenfeld. All Rights Reserved.")
buttonCP, err := walk.NewComposite(showingAboutDialog)
if err != nil {
diff --git a/ui/confview.go b/ui/confview.go
index f3ddbc9d..78e4df91 100644
--- a/ui/confview.go
+++ b/ui/confview.go
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package ui
@@ -51,6 +51,7 @@ type interfaceView struct {
addresses *labelTextLine
dns *labelTextLine
scripts *labelTextLine
+ table *labelTextLine
toggleActive *toggleActiveLine
lines []widgetsLine
}
@@ -307,6 +308,7 @@ func newInterfaceView(parent walk.Container) (*interfaceView, error) {
{l18n.Sprintf("Addresses:"), &iv.addresses},
{l18n.Sprintf("DNS servers:"), &iv.dns},
{l18n.Sprintf("Scripts:"), &iv.scripts},
+ {l18n.Sprintf("Table:"), &iv.table},
}
if iv.lines, err = createLabelTextLines(items, parent, &disposables); err != nil {
return nil, err
@@ -427,6 +429,12 @@ func (iv *interfaceView) apply(c *conf.Interface) {
} else {
iv.scripts.hide()
}
+
+ if c.TableOff {
+ iv.table.show(l18n.Sprintf("off"))
+ } else {
+ iv.table.hide()
+ }
}
func (pv *peerView) widgetsLines() []widgetsLine {
@@ -597,7 +605,7 @@ func (cv *ConfView) onToggleActiveClicked() {
}()
}
-func (cv *ConfView) onTunnelChanged(tunnel *manager.Tunnel, state manager.TunnelState, globalState manager.TunnelState, err error) {
+func (cv *ConfView) onTunnelChanged(tunnel *manager.Tunnel, state, globalState manager.TunnelState, err error) {
cv.Synchronize(func() {
cv.interfaze.toggleActive.updateGlobal(globalState)
if cv.tunnel != nil && cv.tunnel.Name == tunnel.Name {
@@ -620,7 +628,7 @@ func (cv *ConfView) onTunnelChanged(tunnel *manager.Tunnel, state manager.Tunnel
}
func (cv *ConfView) SetTunnel(tunnel *manager.Tunnel) {
- cv.tunnel = tunnel //XXX: This races with the read in the updateTicker, but it's pointer-sized!
+ cv.tunnel = tunnel // XXX: This races with the read in the updateTicker, but it's pointer-sized!
var config conf.Config
var state manager.TunnelState
diff --git a/ui/editdialog.go b/ui/editdialog.go
index 71b71150..45b25fd0 100644
--- a/ui/editdialog.go
+++ b/ui/editdialog.go
@@ -1,11 +1,12 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package ui
import (
+ "net/netip"
"strings"
"github.com/lxn/walk"
@@ -129,7 +130,7 @@ func newEditDialog(owner walk.Form, tunnel *manager.Tunnel) (*EditDialog, error)
return nil, err
}
dlg.blockUntunneledTrafficCB.SetText(l18n.Sprintf("&Block untunneled traffic (kill-switch)"))
- dlg.blockUntunneledTrafficCB.SetToolTipText(l18n.Sprintf("When a configuration has exactly one peer, and that peer has an allowed IPs containing at least one of 0.0.0.0/0 or ::/0, then the tunnel service engages a firewall ruleset to block all traffic that is neither to nor from the tunnel interface or is to the wrong DNS server, with special exceptions for DHCP and NDP."))
+ dlg.blockUntunneledTrafficCB.SetToolTipText(l18n.Sprintf("When a configuration has exactly one peer, and that peer has an allowed IPs containing at least one of 0.0.0.0/0 or ::/0, and the interface does not have table off, then the tunnel service engages a firewall ruleset to block all traffic that is neither to nor from the tunnel interface or is to the wrong DNS server, with special exceptions for DHCP and NDP."))
dlg.blockUntunneledTrafficCB.SetVisible(false)
dlg.blockUntunneledTrafficCB.CheckedChanged().Attach(dlg.onBlockUntunneledTrafficCBCheckedChanged)
@@ -185,15 +186,17 @@ func (dlg *EditDialog) onBlockUntunneledTrafficCBCheckedChanged() {
return
}
var (
- v40 = [4]byte{}
- v60 = [16]byte{}
- v48 = [4]byte{0x80}
- v68 = [16]byte{0x80}
+ v400 = netip.PrefixFrom(netip.IPv4Unspecified(), 0)
+ v600000 = netip.PrefixFrom(netip.IPv6Unspecified(), 0)
+ v401 = netip.PrefixFrom(netip.AddrFrom4([4]byte{}), 1)
+ v600001 = netip.PrefixFrom(netip.AddrFrom16([16]byte{}), 1)
+ v41281 = netip.PrefixFrom(netip.AddrFrom4([4]byte{0x80}), 1)
+ v680001 = netip.PrefixFrom(netip.AddrFrom16([16]byte{0x80}), 1)
)
block := dlg.blockUntunneledTrafficCB.Checked()
cfg, err := conf.FromWgQuick(dlg.syntaxEdit.Text(), "temporary")
- var newAllowedIPs []conf.IPCidr
+ var newAllowedIPs []netip.Prefix
if err != nil {
goto err
@@ -202,7 +205,7 @@ func (dlg *EditDialog) onBlockUntunneledTrafficCBCheckedChanged() {
goto err
}
- newAllowedIPs = make([]conf.IPCidr, 0, len(cfg.Peers[0].AllowedIPs))
+ newAllowedIPs = make([]netip.Prefix, 0, len(cfg.Peers[0].AllowedIPs))
if block {
var (
foundV401 bool
@@ -211,13 +214,13 @@ func (dlg *EditDialog) onBlockUntunneledTrafficCBCheckedChanged() {
foundV680001 bool
)
for _, allowedip := range cfg.Peers[0].AllowedIPs {
- if allowedip.Cidr == 1 && len(allowedip.IP) == 16 && allowedip.IP.Equal(v60[:]) {
+ if allowedip == v600001 {
foundV600001 = true
- } else if allowedip.Cidr == 1 && len(allowedip.IP) == 16 && allowedip.IP.Equal(v68[:]) {
+ } else if allowedip == v680001 {
foundV680001 = true
- } else if allowedip.Cidr == 1 && len(allowedip.IP) == 4 && allowedip.IP.Equal(v40[:]) {
+ } else if allowedip == v401 {
foundV401 = true
- } else if allowedip.Cidr == 1 && len(allowedip.IP) == 4 && allowedip.IP.Equal(v48[:]) {
+ } else if allowedip == v41281 {
foundV41281 = true
} else {
newAllowedIPs = append(newAllowedIPs, allowedip)
@@ -227,44 +230,44 @@ func (dlg *EditDialog) onBlockUntunneledTrafficCBCheckedChanged() {
goto err
}
if foundV401 && foundV41281 {
- newAllowedIPs = append(newAllowedIPs, conf.IPCidr{v40[:], 0})
+ newAllowedIPs = append(newAllowedIPs, v400)
} else if foundV401 {
- newAllowedIPs = append(newAllowedIPs, conf.IPCidr{v40[:], 1})
+ newAllowedIPs = append(newAllowedIPs, v401)
} else if foundV41281 {
- newAllowedIPs = append(newAllowedIPs, conf.IPCidr{v48[:], 1})
+ newAllowedIPs = append(newAllowedIPs, v41281)
}
if foundV600001 && foundV680001 {
- newAllowedIPs = append(newAllowedIPs, conf.IPCidr{v60[:], 0})
+ newAllowedIPs = append(newAllowedIPs, v600000)
} else if foundV600001 {
- newAllowedIPs = append(newAllowedIPs, conf.IPCidr{v60[:], 1})
+ newAllowedIPs = append(newAllowedIPs, v600001)
} else if foundV680001 {
- newAllowedIPs = append(newAllowedIPs, conf.IPCidr{v68[:], 1})
+ newAllowedIPs = append(newAllowedIPs, v680001)
}
cfg.Peers[0].AllowedIPs = newAllowedIPs
} else {
var (
- foundV400 bool
- foundV600 bool
+ foundV400 bool
+ foundV600000 bool
)
for _, allowedip := range cfg.Peers[0].AllowedIPs {
- if allowedip.Cidr == 0 && len(allowedip.IP) == 16 && allowedip.IP.Equal(v60[:]) {
- foundV600 = true
- } else if allowedip.Cidr == 0 && len(allowedip.IP) == 4 && allowedip.IP.Equal(v40[:]) {
+ if allowedip == v600000 {
+ foundV600000 = true
+ } else if allowedip == v400 {
foundV400 = true
} else {
newAllowedIPs = append(newAllowedIPs, allowedip)
}
}
- if !(foundV400 || foundV600) {
+ if !(foundV400 || foundV600000) {
goto err
}
if foundV400 {
- newAllowedIPs = append(newAllowedIPs, conf.IPCidr{v40[:], 1})
- newAllowedIPs = append(newAllowedIPs, conf.IPCidr{v48[:], 1})
+ newAllowedIPs = append(newAllowedIPs, v401)
+ newAllowedIPs = append(newAllowedIPs, v41281)
}
- if foundV600 {
- newAllowedIPs = append(newAllowedIPs, conf.IPCidr{v60[:], 1})
- newAllowedIPs = append(newAllowedIPs, conf.IPCidr{v68[:], 1})
+ if foundV600000 {
+ newAllowedIPs = append(newAllowedIPs, v600001)
+ newAllowedIPs = append(newAllowedIPs, v680001)
}
cfg.Peers[0].AllowedIPs = newAllowedIPs
}
diff --git a/ui/filesave.go b/ui/filesave.go
index 8cedec27..3a54f015 100644
--- a/ui/filesave.go
+++ b/ui/filesave.go
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package ui
@@ -24,7 +24,7 @@ func writeFileWithOverwriteHandling(owner walk.Form, filePath string, write func
return true
}
- file, err := os.OpenFile(filePath, os.O_CREATE|os.O_WRONLY|os.O_EXCL, 0600)
+ file, err := os.OpenFile(filePath, os.O_CREATE|os.O_WRONLY|os.O_EXCL, 0o600)
if err != nil {
if os.IsExist(err) {
if walk.DlgCmdNo == walk.MsgBox(owner, l18n.Sprintf("Writing file failed"), l18n.Sprintf(`File ‘%s’ already exists.
diff --git a/ui/iconprovider.go b/ui/iconprovider.go
index e3f810e3..154a1628 100644
--- a/ui/iconprovider.go
+++ b/ui/iconprovider.go
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package ui
@@ -121,6 +121,14 @@ func loadSystemIcon(dll string, index int32, size int) (icon *walk.Icon, err err
return
}
+func loadShieldIcon(size int) (icon *walk.Icon, err error) {
+ icon, err = loadSystemIcon("imageres", -1028, size)
+ if err != nil {
+ icon, err = loadSystemIcon("imageres", 1, size)
+ }
+ return
+}
+
var cachedLogoIconsForWidth = make(map[int]*walk.Icon)
func loadLogoIcon(size int) (icon *walk.Icon, err error) {
diff --git a/ui/listview.go b/ui/listview.go
index 13608b4e..609feb40 100644
--- a/ui/listview.go
+++ b/ui/listview.go
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package ui
@@ -32,7 +32,7 @@ func (t *ListModel) RowCount() int {
return len(t.tunnels)
}
-func (t *ListModel) Value(row, col int) interface{} {
+func (t *ListModel) Value(row, col int) any {
if col != 0 || row < 0 || row >= len(t.tunnels) {
return ""
}
@@ -181,7 +181,7 @@ func (tv *ListView) StyleCell(style *walk.CellStyle) {
}
}
-func (tv *ListView) onTunnelChange(tunnel *manager.Tunnel, state manager.TunnelState, globalState manager.TunnelState, err error) {
+func (tv *ListView) onTunnelChange(tunnel *manager.Tunnel, state, globalState manager.TunnelState, err error) {
tv.Synchronize(func() {
idx := -1
for i := range tv.model.tunnels {
diff --git a/ui/logpage.go b/ui/logpage.go
index 17c3c8f0..5b7681b3 100644
--- a/ui/logpage.go
+++ b/ui/logpage.go
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package ui
@@ -216,6 +216,6 @@ func newLogModel(lp *LogPage) *logModel {
return mdl
}
-func (mdl *logModel) Items() interface{} {
+func (mdl *logModel) Items() any {
return mdl.items
}
diff --git a/ui/managewindow.go b/ui/managewindow.go
index 74f205a9..30a1cedc 100644
--- a/ui/managewindow.go
+++ b/ui/managewindow.go
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package ui
@@ -161,7 +161,7 @@ func (mtw *ManageTunnelsWindow) updateProgressIndicator(globalState manager.Tunn
}
}
-func (mtw *ManageTunnelsWindow) onTunnelChange(tunnel *manager.Tunnel, state manager.TunnelState, globalState manager.TunnelState, err error) {
+func (mtw *ManageTunnelsWindow) onTunnelChange(tunnel *manager.Tunnel, state, globalState manager.TunnelState, err error) {
mtw.Synchronize(func() {
mtw.updateProgressIndicator(globalState)
@@ -179,7 +179,9 @@ func (mtw *ManageTunnelsWindow) UpdateFound() {
if mtw.updatePage != nil {
return
}
- mtw.SetTitle(l18n.Sprintf("%s (out of date)", mtw.Title()))
+ if IsAdmin {
+ mtw.SetTitle(l18n.Sprintf("%s (out of date)", mtw.Title()))
+ }
updatePage, err := NewUpdatePage()
if err == nil {
mtw.updatePage = updatePage
diff --git a/ui/raise.go b/ui/raise.go
index 2d748a5c..3cea8a88 100644
--- a/ui/raise.go
+++ b/ui/raise.go
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package ui
@@ -55,7 +55,7 @@ func WaitForRaiseUIThenQuit() {
var handle win.HWINEVENTHOOK
runtime.LockOSThread()
defer runtime.UnlockOSThread()
- handle, err := win.SetWinEventHook(win.EVENT_OBJECT_CREATE, win.EVENT_OBJECT_CREATE, 0, func(hWinEventHook win.HWINEVENTHOOK, event uint32, hwnd win.HWND, idObject int32, idChild int32, idEventThread uint32, dwmsEventTime uint32) uintptr {
+ handle, err := win.SetWinEventHook(win.EVENT_OBJECT_CREATE, win.EVENT_OBJECT_CREATE, 0, func(hWinEventHook win.HWINEVENTHOOK, event uint32, hwnd win.HWND, idObject, idChild int32, idEventThread, dwmsEventTime uint32) uintptr {
class := make([]uint16, len(manageWindowWindowClass)+2) /* Plus 2, one for the null terminator, and one to see if this is only a prefix */
n, err := win.GetClassName(hwnd, &class[0], len(class))
if err != nil || n != len(manageWindowWindowClass) || windows.UTF16ToString(class) != manageWindowWindowClass {
diff --git a/ui/syntax/highlighter.go b/ui/syntax/highlighter.go
index d49cab32..099a23b0 100644
--- a/ui/syntax/highlighter.go
+++ b/ui/syntax/highlighter.go
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*
* This is a direct translation of the original C, and for that reason, it's pretty unusual Go code:
* https://git.zx2c4.com/wireguard-tools/tree/contrib/highlighter/highlighter.c
@@ -26,6 +26,7 @@ const (
highlightKeepalive
highlightComment
highlightDelimiter
+ highlightTable
highlightCmd
highlightError
)
@@ -61,7 +62,7 @@ type stringSpan struct {
}
func (s stringSpan) at(i int) *byte {
- return (*byte)(unsafe.Pointer(uintptr(unsafe.Pointer(s.s)) + uintptr(i)))
+ return (*byte)(unsafe.Add(unsafe.Pointer(s.s), uintptr(i)))
}
func (s stringSpan) isSame(c string) bool {
@@ -221,7 +222,7 @@ func (s stringSpan) isValidIPv6() bool {
return true
}
-func (s stringSpan) isValidUint(supportHex bool, min uint64, max uint64) bool {
+func (s stringSpan) isValidUint(supportHex bool, min, max uint64) bool {
// Bound this around 32 bits, so that we don't have to write overflow logic.
if s.len > 10 || s.len == 0 {
return false
@@ -256,6 +257,10 @@ func (s stringSpan) isValidMTU() bool {
return s.isValidUint(false, 576, 65535)
}
+func (s stringSpan) isValidTable() bool {
+ return s.isSame("off") || s.isSame("auto") || s.isSame("main") || s.isValidUint(false, 0, (1<<32)-1)
+}
+
func (s stringSpan) isValidPersistentKeepAlive() bool {
if s.isSame("off") {
return true
@@ -360,6 +365,7 @@ const (
fieldAddress
fieldDNS
fieldMTU
+ fieldTable
fieldPreUp
fieldPostUp
fieldPreDown
@@ -395,6 +401,8 @@ func (s stringSpan) field() field {
return fieldDNS
case s.isCaselessSame("MTU"):
return fieldMTU
+ case s.isCaselessSame("Table"):
+ return fieldTable
case s.isCaselessSame("PublicKey"):
return fieldPublicKey
case s.isCaselessSame("PresharedKey"):
@@ -436,7 +444,7 @@ func (hsa *highlightSpanArray) append(o *byte, s stringSpan, t highlight) {
*hsa = append(*hsa, highlightSpan{t, int((uintptr(unsafe.Pointer(s.s))) - (uintptr(unsafe.Pointer(o)))), s.len})
}
-func (hsa *highlightSpanArray) highlightMultivalueValue(parent stringSpan, s stringSpan, section field) {
+func (hsa *highlightSpanArray) highlightMultivalueValue(parent, s stringSpan, section field) {
switch section {
case fieldDNS:
if s.isValidIPv4() || s.isValidIPv6() {
@@ -469,7 +477,7 @@ func (hsa *highlightSpanArray) highlightMultivalueValue(parent stringSpan, s str
}
}
-func (hsa *highlightSpanArray) highlightMultivalue(parent stringSpan, s stringSpan, section field) {
+func (hsa *highlightSpanArray) highlightMultivalue(parent, s stringSpan, section field) {
currentSpan := stringSpan{s.s, 0}
lenAtLastSpace := 0
for i := 0; i < s.len; i++ {
@@ -498,7 +506,7 @@ func (hsa *highlightSpanArray) highlightMultivalue(parent stringSpan, s stringSp
}
}
-func (hsa *highlightSpanArray) highlightValue(parent stringSpan, s stringSpan, section field) {
+func (hsa *highlightSpanArray) highlightValue(parent, s stringSpan, section field) {
switch section {
case fieldPrivateKey:
hsa.append(parent.s, s, validateHighlight(s.isValidKey(), highlightPrivateKey))
@@ -508,6 +516,8 @@ func (hsa *highlightSpanArray) highlightValue(parent stringSpan, s stringSpan, s
hsa.append(parent.s, s, validateHighlight(s.isValidKey(), highlightPresharedKey))
case fieldMTU:
hsa.append(parent.s, s, validateHighlight(s.isValidMTU(), highlightMTU))
+ case fieldTable:
+ hsa.append(parent.s, s, validateHighlight(s.isValidTable(), highlightTable))
case fieldPreUp, fieldPostUp, fieldPreDown, fieldPostDown:
hsa.append(parent.s, s, validateHighlight(s.isValidPrePostUpDown(), highlightCmd))
case fieldListenPort:
diff --git a/ui/syntax/syntaxedit.go b/ui/syntax/syntaxedit.go
index 26cd533f..a3c94d86 100644
--- a/ui/syntax/syntaxedit.go
+++ b/ui/syntax/syntaxedit.go
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package syntax
@@ -90,26 +90,29 @@ type spanStyle struct {
}
var stylemap = map[highlight]spanStyle{
- highlightSection: spanStyle{color: win.RGB(0x32, 0x6D, 0x74), effects: win.CFE_BOLD},
- highlightField: spanStyle{color: win.RGB(0x9B, 0x23, 0x93), effects: win.CFE_BOLD},
- highlightPrivateKey: spanStyle{color: win.RGB(0x64, 0x38, 0x20)},
- highlightPublicKey: spanStyle{color: win.RGB(0x64, 0x38, 0x20)},
- highlightPresharedKey: spanStyle{color: win.RGB(0x64, 0x38, 0x20)},
- highlightIP: spanStyle{color: win.RGB(0x0E, 0x0E, 0xFF)},
- highlightCidr: spanStyle{color: win.RGB(0x81, 0x5F, 0x03)},
- highlightHost: spanStyle{color: win.RGB(0x0E, 0x0E, 0xFF)},
- highlightPort: spanStyle{color: win.RGB(0x81, 0x5F, 0x03)},
- highlightMTU: spanStyle{color: win.RGB(0x1C, 0x00, 0xCF)},
- highlightKeepalive: spanStyle{color: win.RGB(0x1C, 0x00, 0xCF)},
- highlightComment: spanStyle{color: win.RGB(0x53, 0x65, 0x79), effects: win.CFE_ITALIC},
- highlightDelimiter: spanStyle{color: win.RGB(0x00, 0x00, 0x00)},
- highlightCmd: spanStyle{color: win.RGB(0x63, 0x75, 0x89)},
- highlightError: spanStyle{color: win.RGB(0xC4, 0x1A, 0x16), effects: win.CFE_UNDERLINE},
+ highlightSection: {color: win.RGB(0x32, 0x6D, 0x74), effects: win.CFE_BOLD},
+ highlightField: {color: win.RGB(0x9B, 0x23, 0x93), effects: win.CFE_BOLD},
+ highlightPrivateKey: {color: win.RGB(0x64, 0x38, 0x20)},
+ highlightPublicKey: {color: win.RGB(0x64, 0x38, 0x20)},
+ highlightPresharedKey: {color: win.RGB(0x64, 0x38, 0x20)},
+ highlightIP: {color: win.RGB(0x0E, 0x0E, 0xFF)},
+ highlightCidr: {color: win.RGB(0x81, 0x5F, 0x03)},
+ highlightHost: {color: win.RGB(0x0E, 0x0E, 0xFF)},
+ highlightPort: {color: win.RGB(0x81, 0x5F, 0x03)},
+ highlightMTU: {color: win.RGB(0x1C, 0x00, 0xCF)},
+ highlightTable: {color: win.RGB(0x1C, 0x00, 0xCF)},
+ highlightKeepalive: {color: win.RGB(0x1C, 0x00, 0xCF)},
+ highlightComment: {color: win.RGB(0x53, 0x65, 0x79), effects: win.CFE_ITALIC},
+ highlightDelimiter: {color: win.RGB(0x00, 0x00, 0x00)},
+ highlightCmd: {color: win.RGB(0x63, 0x75, 0x89)},
+ highlightError: {color: win.RGB(0xC4, 0x1A, 0x16), effects: win.CFE_UNDERLINE},
}
func (se *SyntaxEdit) evaluateUntunneledBlocking(cfg string, spans []highlightSpan) {
state := InevaluableBlockingUntunneledTraffic
var onAllowedIPs,
+ onTable,
+ tableOff,
seenPeer,
seen00v6,
seen00v4,
@@ -132,10 +135,13 @@ func (se *SyntaxEdit) evaluateUntunneledBlocking(cfg string, spans []highlightSp
} else {
goto done
}
- break
case highlightField:
onAllowedIPs = strings.EqualFold(cfg[span.s:span.s+span.len], "AllowedIPs")
- break
+ onTable = strings.EqualFold(cfg[span.s:span.s+span.len], "Table")
+ case highlightTable:
+ if onTable {
+ tableOff = cfg[span.s:span.s+span.len] == "off"
+ }
case highlightIP:
if !onAllowedIPs || !seenPeer {
break
@@ -166,9 +172,11 @@ func (se *SyntaxEdit) evaluateUntunneledBlocking(cfg string, spans []highlightSp
seen80001v6 = true
}
}
- break
}
}
+ if tableOff {
+ return
+ }
if seen00v4 || seen00v6 {
state = BlockingUntunneledTraffic
@@ -469,10 +477,10 @@ func NewSyntaxEdit(parent walk.Container) (*SyntaxEdit, error) {
se.GraphicsEffects().Add(walk.InteractionEffect)
se.GraphicsEffects().Add(walk.FocusEffect)
se.MustRegisterProperty("Text", walk.NewProperty(
- func() interface{} {
+ func() any {
return se.Text()
},
- func(v interface{}) error {
+ func(v any) error {
if s, ok := v.(string); ok {
return se.SetText(s)
}
diff --git a/ui/tray.go b/ui/tray.go
index 34e4b003..7771c966 100644
--- a/ui/tray.go
+++ b/ui/tray.go
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package ui
@@ -252,7 +252,7 @@ func (tray *Tray) rebalanceTunnelsMenu() {
}
}
-func (tray *Tray) onTunnelChange(tunnel *manager.Tunnel, state manager.TunnelState, globalState manager.TunnelState, err error) {
+func (tray *Tray) onTunnelChange(tunnel *manager.Tunnel, state, globalState manager.TunnelState, err error) {
tray.mtw.Synchronize(func() {
tray.updateGlobalState(globalState)
if err == nil {
@@ -343,7 +343,7 @@ func (tray *Tray) setTunnelState(tunnel *manager.Tunnel, state manager.TunnelSta
func (tray *Tray) UpdateFound() {
action := walk.NewAction()
action.SetText(l18n.Sprintf("An Update is Available!"))
- menuIcon, _ := loadSystemIcon("imageres", 1, 16)
+ menuIcon, _ := loadShieldIcon(16)
action.SetImage(menuIcon)
action.SetDefault(true)
showUpdateTab := func() {
@@ -358,7 +358,7 @@ func (tray *Tray) UpdateFound() {
tray.ContextMenu().Actions().Insert(tray.ContextMenu().Actions().Len()-2, action)
showUpdateBalloon := func() {
- icon, _ := loadSystemIcon("imageres", 1, 128)
+ icon, _ := loadShieldIcon(128)
tray.ShowCustom(l18n.Sprintf("WireGuard Update Available"), l18n.Sprintf("An update to WireGuard is now available. You are advised to update as soon as possible."), icon)
}
diff --git a/ui/tunnelspage.go b/ui/tunnelspage.go
index 10bf2f8e..d104f598 100644
--- a/ui/tunnelspage.go
+++ b/ui/tunnelspage.go
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package ui
@@ -91,8 +91,9 @@ func NewTunnelsPage() (*TunnelsPage, error) {
if err != nil {
return nil, err
}
- controlsContainer.SetLayout(walk.NewHBoxLayout())
- controlsContainer.Layout().SetMargins(walk.Margins{})
+ hlayout = walk.NewHBoxLayout()
+ hlayout.SetMargins(walk.Margins{})
+ controlsContainer.SetLayout(hlayout)
walk.NewHSpacer(controlsContainer)
@@ -279,7 +280,7 @@ func (tp *TunnelsPage) updateConfView() {
func (tp *TunnelsPage) importFiles(paths []string) {
go func() {
- syncedMsgBox := func(title string, message string, flags walk.MsgBoxStyle) {
+ syncedMsgBox := func(title, message string, flags walk.MsgBoxStyle) {
tp.Synchronize(func() {
walk.MsgBox(tp.Form(), title, message, flags)
})
@@ -421,7 +422,6 @@ func (tp *TunnelsPage) addTunnel(config *conf.Config) {
if err != nil {
showErrorCustom(tp.Form(), l18n.Sprintf("Unable to create tunnel"), err.Error())
}
-
}
// Handlers
@@ -518,7 +518,6 @@ func (tp *TunnelsPage) onDelete() {
tunnelsToDelete := make([]manager.Tunnel, len(indices))
for i, j := range indices {
tunnelsToDelete[i] = tp.listView.model.tunnels[j]
-
}
go func() {
tp.listView.SetSuspendTunnelsUpdate(true)
diff --git a/ui/ui.go b/ui/ui.go
index 55b846fc..569fc8ae 100644
--- a/ui/ui.go
+++ b/ui/ui.go
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package ui
@@ -20,10 +20,12 @@ import (
"golang.zx2c4.com/wireguard/windows/version"
)
-var noTrayAvailable = false
-var shouldQuitManagerWhenExiting = false
-var startTime = time.Now()
-var IsAdmin = false // A global, because this really is global for the process
+var (
+ noTrayAvailable = false
+ shouldQuitManagerWhenExiting = false
+ startTime = time.Now()
+ IsAdmin = false // A global, because this really is global for the process
+)
func RunUI() {
runtime.LockOSThread()
@@ -73,7 +75,7 @@ func RunUI() {
switch updateState {
case manager.UpdateStateFoundUpdate:
mtw.UpdateFound()
- if tray != nil {
+ if tray != nil && IsAdmin {
tray.UpdateFound()
}
case manager.UpdateStateUpdatesDisabledUnofficialBuild:
diff --git a/ui/updatepage.go b/ui/updatepage.go
index 88992ced..ff2bbe5f 100644
--- a/ui/updatepage.go
+++ b/ui/updatepage.go
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package ui
@@ -31,7 +31,7 @@ func NewUpdatePage() (*UpdatePage, error) {
up.SetTitle(l18n.Sprintf("An Update is Available!"))
- tabIcon, _ := loadSystemIcon("imageres", 1, 16)
+ tabIcon, _ := loadShieldIcon(16)
up.SetImage(tabIcon)
up.SetLayout(walk.NewVBoxLayout())
@@ -64,6 +64,12 @@ func NewUpdatePage() (*UpdatePage, error) {
button.SetImage(updateIcon)
button.SetText(l18n.Sprintf("Update Now"))
+ if !IsAdmin {
+ button.SetText(l18n.Sprintf("Please ask the system administrator to update."))
+ button.SetEnabled(false)
+ status.SetText(l18n.Sprintf("Status: Waiting for administrator"))
+ }
+
walk.NewVSpacer(up)
switchToUpdatingState := func() {
diff --git a/updater/authenticode.go b/updater/authenticode.go
index d6d80df5..1e0a25c0 100644
--- a/updater/authenticode.go
+++ b/updater/authenticode.go
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package updater
@@ -27,5 +27,8 @@ func verifyAuthenticode(path string) bool {
FilePath: path16,
}),
}
- return windows.WinVerifyTrustEx(windows.InvalidHWND, &windows.WINTRUST_ACTION_GENERIC_VERIFY_V2, data) == nil
+ verified := windows.WinVerifyTrustEx(windows.InvalidHWND, &windows.WINTRUST_ACTION_GENERIC_VERIFY_V2, data) == nil
+ data.StateAction = windows.WTD_STATEACTION_CLOSE
+ windows.WinVerifyTrustEx(windows.InvalidHWND, &windows.WINTRUST_ACTION_GENERIC_VERIFY_V2, data)
+ return verified
}
diff --git a/updater/constants.go b/updater/constants.go
index 04b972fe..cf0ced92 100644
--- a/updater/constants.go
+++ b/updater/constants.go
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package updater
diff --git a/updater/downloader.go b/updater/downloader.go
index b8b2763d..bf28db54 100644
--- a/updater/downloader.go
+++ b/updater/downloader.go
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package updater
diff --git a/updater/msirunner.go b/updater/msirunner.go
index 13495f46..ec6b1bd3 100644
--- a/updater/msirunner.go
+++ b/updater/msirunner.go
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package updater
@@ -38,7 +38,7 @@ func (t *tempFile) Delete() error {
if err != nil {
return err
}
- return windows.DeleteFile(name16) //TODO: how does this deal with reparse points?
+ return windows.DeleteFile(name16) // TODO: how does this deal with reparse points?
}
disposition := byte(1)
err := windows.SetFileInformationByHandle(t.originalHandle, windows.FileDispositionInfo, &disposition, 1)
diff --git a/updater/signify.go b/updater/signify.go
index eef9198a..de50fcba 100644
--- a/updater/signify.go
+++ b/updater/signify.go
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package updater
@@ -53,17 +53,17 @@ func readFileList(input []byte) (fileList, error) {
if len(line) == 0 && index == len(fileLines)-1 {
break
}
- components := strings.SplitN(line, " ", 2)
- if len(components) != 2 {
+ first, second, ok := strings.Cut(line, " ")
+ if !ok {
return nil, errors.New("File hash line has too few components")
}
- maybeHash, err := hex.DecodeString(components[0])
+ maybeHash, err := hex.DecodeString(first)
if err != nil || len(maybeHash) != blake2b.Size256 {
return nil, errors.New("File hash is invalid base64 or incorrect number of bytes")
}
var hash [blake2b.Size256]byte
copy(hash[:], maybeHash)
- fileHashes[components[1]] = hash
+ fileHashes[second] = hash
}
if len(fileHashes) == 0 {
return nil, errors.New("No file hashes found in signed input")
diff --git a/updater/updater_test.go b/updater/updater_test.go
index a90b13cb..809262bd 100644
--- a/updater/updater_test.go
+++ b/updater/updater_test.go
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package updater
diff --git a/updater/versions.go b/updater/versions.go
index 5b42a748..dfc4c665 100644
--- a/updater/versions.go
+++ b/updater/versions.go
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package updater
diff --git a/updater/winhttp/mksyscall.go b/updater/winhttp/mksyscall.go
index 1daedb08..54c06e85 100644
--- a/updater/winhttp/mksyscall.go
+++ b/updater/winhttp/mksyscall.go
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package winhttp
diff --git a/updater/winhttp/syscall_windows.go b/updater/winhttp/syscall_windows.go
index 77e733e6..4f967bfa 100644
--- a/updater/winhttp/syscall_windows.go
+++ b/updater/winhttp/syscall_windows.go
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package winhttp
@@ -256,6 +256,16 @@ const (
_INTERNET_SCHEME_FTP = 3
_INTERNET_SCHEME_SOCKS = 4
+ _WINHTTP_FLAG_SECURE_PROTOCOL_SSL2 = 0x00000008
+ _WINHTTP_FLAG_SECURE_PROTOCOL_SSL3 = 0x00000020
+ _WINHTTP_FLAG_SECURE_PROTOCOL_TLS1 = 0x00000080
+ _WINHTTP_FLAG_SECURE_PROTOCOL_TLS1_1 = 0x00000200
+ _WINHTTP_FLAG_SECURE_PROTOCOL_TLS1_2 = 0x00000800
+ _WINHTTP_FLAG_SECURE_PROTOCOL_TLS1_3 = 0x00002000
+ _WINHTTP_FLAG_SECURE_PROTOCOL_ALL = _WINHTTP_FLAG_SECURE_PROTOCOL_SSL2 | _WINHTTP_FLAG_SECURE_PROTOCOL_SSL3 | _WINHTTP_FLAG_SECURE_PROTOCOL_TLS1
+
+ _WINHTTP_PROTOCOL_FLAG_HTTP2 = 0x1
+
_WINHTTP_ERROR_BASE = 12000
_ERROR_WINHTTP_OUT_OF_HANDLES = Error(12000 + 1)
_ERROR_WINHTTP_TIMEOUT = Error(12000 + 2)
diff --git a/updater/winhttp/winhttp.go b/updater/winhttp/winhttp.go
index ac390a4f..cb19f194 100644
--- a/updater/winhttp/winhttp.go
+++ b/updater/winhttp/winhttp.go
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package winhttp
@@ -21,11 +21,13 @@ import (
type Session struct {
handle _HINTERNET
}
+
type Connection struct {
handle _HINTERNET
session *Session
https bool
}
+
type Response struct {
handle _HINTERNET
connection *Connection
@@ -48,6 +50,11 @@ func isWin7() bool {
return maj < 6 || (maj == 6 && min <= 1)
}
+func isWin8DotZeroOrBelow() bool {
+ maj, min, _ := windows.RtlGetNtVersionNumbers()
+ return maj < 6 || (maj == 6 && min <= 2)
+}
+
func NewSession(userAgent string) (session *Session, err error) {
session = new(Session)
defer convertError(&err)
@@ -69,9 +76,17 @@ func NewSession(userAgent string) (session *Session, err error) {
if err != nil {
return
}
- var enableHttp2 uint32 = 1
+ var enableHttp2 uint32 = _WINHTTP_PROTOCOL_FLAG_HTTP2
_ = winHttpSetOption(session.handle, _WINHTTP_OPTION_ENABLE_HTTP_PROTOCOL, unsafe.Pointer(&enableHttp2), uint32(unsafe.Sizeof(enableHttp2))) // Don't check return value, in case of old Windows
+ if isWin8DotZeroOrBelow() {
+ var enableTLS12 uint32 = _WINHTTP_FLAG_SECURE_PROTOCOL_TLS1_2
+ err = winHttpSetOption(session.handle, _WINHTTP_OPTION_SECURE_PROTOCOLS, unsafe.Pointer(&enableTLS12), uint32(unsafe.Sizeof(enableTLS12)))
+ if err != nil {
+ return
+ }
+ }
+
runtime.SetFinalizer(session, func(session *Session) {
session.Close()
})
diff --git a/updater/winhttp/winhttp_test.go b/updater/winhttp/winhttp_test.go
index 41fbeb6b..36017a48 100644
--- a/updater/winhttp/winhttp_test.go
+++ b/updater/winhttp/winhttp_test.go
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package winhttp
diff --git a/version/certificate_test.go b/version/certificate_test.go
index 677e6fdc..724c524f 100644
--- a/version/certificate_test.go
+++ b/version/certificate_test.go
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package version
diff --git a/version/official.go b/version/official.go
index 5998124c..2951c893 100644
--- a/version/official.go
+++ b/version/official.go
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package version
@@ -19,7 +19,7 @@ const (
policyExtensionOid = "2.5.29.32"
)
-// These are easily by-passable checks, which do not serve serve security purposes.
+// These are easily by-passable checks, which do not serve security purposes.
// DO NOT PLACE SECURITY-SENSITIVE FUNCTIONS IN THIS FILE
func IsRunningOfficialVersion() bool {
@@ -101,7 +101,7 @@ func extractCertificateNames(path string) ([]string, error) {
return names, nil
}
-func extractCertificatePolicies(path string, oid string) ([]string, error) {
+func extractCertificatePolicies(path, oid string) ([]string, error) {
path16, err := windows.UTF16PtrFromString(path)
if err != nil {
return nil, err
@@ -129,8 +129,7 @@ func extractCertificatePolicies(path string, oid string) ([]string, error) {
if cert == nil {
break
}
- ci := (*windows.CertInfo)(unsafe.Pointer(cert.CertInfo))
- ext := windows.CertFindExtension(oid8, ci.CountExtensions, ci.Extensions)
+ ext := windows.CertFindExtension(oid8, cert.CertInfo.CountExtensions, cert.CertInfo.Extensions)
if ext == nil {
continue
}
@@ -146,7 +145,7 @@ func extractCertificatePolicies(path string, oid string) ([]string, error) {
return nil, err
}
for i := uintptr(0); i < uintptr(certPoliciesInfo.Count); i++ {
- cp := (*windows.CertPolicyInfo)(unsafe.Pointer(uintptr(unsafe.Pointer(certPoliciesInfo.PolicyInfos)) + i*unsafe.Sizeof(*certPoliciesInfo.PolicyInfos)))
+ cp := (*windows.CertPolicyInfo)(unsafe.Add(unsafe.Pointer(certPoliciesInfo.PolicyInfos), i*unsafe.Sizeof(*certPoliciesInfo.PolicyInfos)))
policies = append(policies, windows.BytePtrToString(cp.Identifier))
}
}
diff --git a/version/os.go b/version/os.go
index fd6ae475..ff9188bb 100644
--- a/version/os.go
+++ b/version/os.go
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package version
diff --git a/version/protocol.go b/version/protocol.go
deleted file mode 100644
index 72a35e95..00000000
--- a/version/protocol.go
+++ /dev/null
@@ -1,28 +0,0 @@
-/* SPDX-License-Identifier: MIT
- *
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
- */
-
-package version
-
-import (
- "runtime/debug"
- "strings"
-)
-
-func ProtoImplementation() string {
- info, ok := debug.ReadBuildInfo()
- if !ok {
- return "unknown"
- }
- for _, dep := range info.Deps {
- if dep.Path == "golang.zx2c4.com/wireguard" {
- parts := strings.Split(dep.Version, "-")
- if len(parts) == 3 && len(parts[2]) == 12 {
- return parts[2][:7]
- }
- return dep.Version
- }
- }
- return "unknown"
-}
diff --git a/version/useragent.go b/version/useragent.go
index 698e185b..3b5240c6 100644
--- a/version/useragent.go
+++ b/version/useragent.go
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package version
diff --git a/version/version.go b/version/version.go
index b2405e59..a7f908e8 100644
--- a/version/version.go
+++ b/version/version.go
@@ -1,10 +1,10 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package version
const (
- Number = "0.3.9"
+ Number = "0.5.3"
)
diff --git a/zgotext.go b/zgotext.go
index b4baa53c..efbb9a80 100644
--- a/zgotext.go
+++ b/zgotext.go
@@ -27,6 +27,8 @@ func (d *dictionary) Lookup(key string) (data string, ok bool) {
func init() {
dict := map[string]catalog.Dictionary{
+ "ca": &dictionary{index: caIndex, data: caData},
+ "cs": &dictionary{index: csIndex, data: csData},
"de": &dictionary{index: deIndex, data: deData},
"en": &dictionary{index: enIndex, data: enData},
"es_ES": &dictionary{index: es_ESIndex, data: es_ESData},
@@ -36,12 +38,15 @@ func init() {
"id": &dictionary{index: idIndex, data: idData},
"it": &dictionary{index: itIndex, data: itData},
"ja": &dictionary{index: jaIndex, data: jaData},
+ "ko": &dictionary{index: koIndex, data: koData},
"pa_IN": &dictionary{index: pa_INIndex, data: pa_INData},
"pl": &dictionary{index: plIndex, data: plData},
"ro": &dictionary{index: roIndex, data: roData},
"ru": &dictionary{index: ruIndex, data: ruData},
+ "si_LK": &dictionary{index: si_LKIndex, data: si_LKData},
"sk": &dictionary{index: skIndex, data: skData},
"sl": &dictionary{index: slIndex, data: slData},
+ "tr": &dictionary{index: trIndex, data: trData},
"uk": &dictionary{index: ukIndex, data: ukData},
"vi": &dictionary{index: viIndex, data: viData},
"zh_CN": &dictionary{index: zh_CNIndex, data: zh_CNData},
@@ -56,244 +61,657 @@ func init() {
}
var messageKeyToIndex = map[string]int{
- "%.2f\u00a0GiB": 21,
- "%.2f\u00a0KiB": 19,
- "%.2f\u00a0MiB": 20,
- "%.2f\u00a0TiB": 22,
- "%d day(s)": 13,
- "%d hour(s)": 14,
- "%d minute(s)": 15,
- "%d second(s)": 16,
- "%d tunnels were unable to be removed.": 161,
- "%d year(s)": 12,
- "%d\u00a0B": 18,
- "%s\n\nPlease consult the log for more information.": 113,
- "%s (out of date)": 114,
- "%s (unsigned build, no updates)": 166,
- "%s You cannot undo this action.": 157,
- "%s ago": 17,
- "%s received, %s sent": 73,
- "%s: %q": 23,
- "&About WireGuard…": 111,
- "&Activate": 58,
- "&Block untunneled traffic (kill-switch)": 84,
- "&Configuration:": 88,
- "&Copy": 104,
- "&Deactivate": 57,
- "&Edit": 135,
- "&Import tunnel(s) from file…": 121,
- "&Manage tunnels…": 120,
- "&Name:": 81,
- "&Public key:": 82,
- "&Remove selected tunnel(s)": 143,
- "&Save": 86,
- "&Save to file…": 106,
- "&Toggle": 140,
- "&Tunnels": 179,
- "(no argument): elevate and install manager service": 1,
- "(unknown)": 83,
- "A name is required.": 90,
- "A tunnel was unable to be removed: %s": 159,
- "About WireGuard": 51,
- "Activating": 99,
- "Active": 98,
- "Add &empty tunnel…": 136,
- "Add Tunnel": 137,
- "Addresses:": 62,
- "Addresses: %s": 130,
- "Addresses: None": 119,
- "All peers must have public keys": 44,
- "Allowed IPs:": 66,
- "An Update is Available!": 131,
- "An interface must have a private key": 42,
- "An update to WireGuard is available. It is highly advisable to update without delay.": 169,
- "An update to WireGuard is now available. You are advised to update as soon as possible.": 133,
- "Another tunnel already exists with the name ‘%s’": 147,
- "Another tunnel already exists with the name ‘%s’.": 94,
- "App version: %s\nGo backend version: %s\nGo version: %s-%s\nOperating system: %s\nArchitecture: %s": 53,
- "Are you sure you would like to delete %d tunnels?": 154,
- "Are you sure you would like to delete tunnel ‘%s’?": 156,
- "Brackets must contain an IPv6 address": 28,
- "Cancel": 87,
- "Close": 54,
- "Command Line Options": 3,
- "Config key is missing an equals separator": 38,
- "Configuration Files (*.zip, *.conf)|*.zip;*.conf|All Files (*.*)|*.*": 162,
- "Configuration ZIP Files (*.zip)|*.zip": 164,
- "Could not enumerate existing tunnels: %v": 146,
- "Could not import selected configuration: %v": 145,
- "Create new tunnel": 79,
- "DNS servers:": 63,
- "Deactivating": 101,
- "Delete %d tunnels": 153,
- "Delete tunnel ‘%s’": 155,
- "E&xit": 122,
- "Edit &selected tunnel…": 142,
- "Edit tunnel": 80,
- "Endpoint:": 67,
- "Error": 0,
- "Error Exiting WireGuard": 167,
- "Error in getting configuration": 45,
- "Error: %v. Please try again.": 173,
- "Export all tunnels to &zip…": 141,
- "Export all tunnels to zip": 139,
- "Export log to file": 110,
- "Export tunnels to zip": 165,
- "Failed to activate tunnel": 75,
- "Failed to deactivate tunnel": 76,
- "Failed to determine tunnel state": 74,
- "File ‘%s’ already exists.\n\nDo you want to overwrite it?": 97,
- "Import tunnel(s) from file": 163,
- "Imported %d of %d tunnels": 151,
- "Imported %d tunnels": 150,
- "Imported tunnels": 149,
- "Inactive": 100,
- "Interface: %s": 77,
- "Invalid IP address": 24,
- "Invalid MTU": 29,
- "Invalid endpoint host": 27,
- "Invalid key for [Interface] section": 40,
- "Invalid key for [Peer] section": 41,
- "Invalid key for interface section": 46,
- "Invalid key for peer section": 48,
- "Invalid key: %v": 32,
- "Invalid name": 89,
- "Invalid network prefix length": 25,
- "Invalid persistent keepalive": 31,
- "Invalid port": 30,
- "Key must have a value": 39,
- "Keys must decode to exactly 32 bytes": 33,
- "Latest handshake:": 69,
- "Line must occur in a section": 37,
- "Listen port:": 60,
- "Log": 103,
- "Log message": 108,
- "MTU:": 61,
- "Missing port from endpoint": 26,
- "Now": 10,
- "Number must be a number between 0 and 2^64-1: %v": 34,
- "Peer": 78,
- "Persistent keepalive:": 68,
- "Preshared key:": 65,
- "Protocol version must be 1": 47,
- "Public key:": 59,
- "Remove selected tunnel(s)": 138,
- "Scripts:": 64,
- "Select &all": 105,
- "Status:": 56,
- "Status: %s": 129,
- "Status: Complete!": 174,
- "Status: Unknown": 118,
- "Status: Waiting for updater service": 172,
- "Status: Waiting for user": 170,
- "System clock wound backward!": 11,
- "Text Files (*.txt)|*.txt|All Files (*.*)|*.*": 109,
- "The %s tunnel has been activated.": 124,
- "The %s tunnel has been deactivated.": 126,
- "Time": 107,
- "Transfer:": 70,
- "Tunnel Error": 112,
- "Tunnel already exists": 93,
- "Tunnel name is not valid": 36,
- "Tunnel name ‘%s’ is invalid.": 91,
- "Tunnels": 134,
- "Two commas in a row": 35,
- "Unable to create new configuration": 95,
- "Unable to create tunnel": 152,
- "Unable to delete tunnel": 158,
- "Unable to delete tunnels": 160,
+ "%.2f\u00a0GiB": 20,
+ "%.2f\u00a0KiB": 18,
+ "%.2f\u00a0MiB": 19,
+ "%.2f\u00a0TiB": 21,
+ "%d day(s)": 12,
+ "%d hour(s)": 13,
+ "%d minute(s)": 14,
+ "%d second(s)": 15,
+ "%d tunnels were unable to be removed.": 169,
+ "%d year(s)": 11,
+ "%d\u00a0B": 17,
+ "%s\n\nPlease consult the log for more information.": 68,
+ "%s (out of date)": 69,
+ "%s (unsigned build, no updates)": 174,
+ "%s - Handshake did not complete after %d attempts, giving up": 234,
+ "%s - Handshake did not complete after %d seconds, retrying (try %d)": 235,
+ "%s - Removing all keys, since we haven't received a new one in %d seconds": 237,
+ "%s - Retrying handshake because we stopped hearing back after %d seconds": 236,
+ "%s You cannot undo this action.": 165,
+ "%s ago": 16,
+ "%s received, %s sent": 95,
+ "%s: %q": 22,
+ "%v": 255,
+ "%v - ConsumeMessageInitiation: handshake flood": 188,
+ "%v - ConsumeMessageInitiation: handshake replay @ %v": 187,
+ "%v - Failed to create initiation message: %v": 220,
+ "%v - Failed to create response message: %v": 223,
+ "%v - Failed to derive keypair: %v": 209,
+ "%v - Failed to send data packet: %v": 233,
+ "%v - Failed to send handshake initiation: %v": 221,
+ "%v - Failed to send handshake response: %v": 224,
+ "%v - Received handshake initiation": 205,
+ "%v - Received handshake response": 208,
+ "%v - Receiving keepalive packet": 212,
+ "%v - Routine: sequential receiver - started": 211,
+ "%v - Routine: sequential receiver - stopped": 210,
+ "%v - Routine: sequential sender - started": 232,
+ "%v - Sending handshake initiation": 219,
+ "%v - Sending handshake response": 222,
+ "%v - Sending keepalive packet": 218,
+ "%v - Starting": 189,
+ "%v - Stopping": 190,
+ "%v - UAPI: Adding allowedip": 266,
+ "%v - UAPI: Created": 260,
+ "%v - UAPI: Removing": 261,
+ "%v - UAPI: Removing all allowedips": 265,
+ "%v - UAPI: Updating endpoint": 263,
+ "%v - UAPI: Updating persistent keepalive interval": 264,
+ "%v - UAPI: Updating preshared key": 262,
+ "&About WireGuard…": 66,
+ "&Activate": 45,
+ "&Block untunneled traffic (kill-switch)": 106,
+ "&Configuration:": 109,
+ "&Copy": 60,
+ "&Deactivate": 44,
+ "&Edit": 143,
+ "&Import tunnel(s) from file…": 128,
+ "&Manage tunnels…": 127,
+ "&Name:": 103,
+ "&Public key:": 104,
+ "&Remove selected tunnel(s)": 151,
+ "&Save": 107,
+ "&Save to file…": 62,
+ "&Test experimental kernel driver": 269,
+ "&Toggle": 148,
+ "&Tunnels": 130,
+ "(no argument): elevate and install manager service": 1,
+ "(unknown)": 105,
+ "A name is required.": 111,
+ "A tunnel was unable to be removed: %s": 167,
+ "About WireGuard": 39,
+ "Activating": 120,
+ "Active": 119,
+ "Add &empty tunnel…": 144,
+ "Add Tunnel": 145,
+ "Addresses:": 49,
+ "Addresses: %s": 138,
+ "Addresses: None": 126,
+ "All peers must have public keys": 35,
+ "Allowed IPs:": 52,
+ "An Update is Available!": 139,
+ "An interface must have a private key": 83,
+ "An update to WireGuard is available. It is highly advisable to update without delay.": 71,
+ "An update to WireGuard is now available. You are advised to update as soon as possible.": 141,
+ "Another tunnel already exists with the name ‘%s’": 155,
+ "Another tunnel already exists with the name ‘%s’.": 115,
+ "App version: %s\nGo backend version: %s\nGo version: %s-%s\nOperating system: %s\nArchitecture: %s": 268,
+ "Are you sure you would like to delete %d tunnels?": 162,
+ "Are you sure you would like to delete tunnel ‘%s’?": 164,
+ "Bind close failed: %v": 182,
+ "Brackets must contain an IPv6 address": 76,
+ "Cancel": 108,
+ "Close": 41,
+ "Command Line Options": 3,
+ "Config key is missing an equals separator": 79,
+ "Configuration Files (*.zip, *.conf)|*.zip;*.conf|All Files (*.*)|*.*": 170,
+ "Configuration ZIP Files (*.zip)|*.zip": 172,
+ "Could not decrypt invalid cookie response": 200,
+ "Could not enumerate existing tunnels: %v": 154,
+ "Could not import selected configuration: %v": 153,
+ "Create new tunnel": 101,
+ "DNS servers:": 50,
+ "Deactivating": 57,
+ "Delete %d tunnels": 161,
+ "Delete tunnel ‘%s’": 163,
+ "Device closed": 185,
+ "Device closing": 184,
+ "E&xit": 129,
+ "Edit &selected tunnel…": 150,
+ "Edit tunnel": 102,
+ "Enable experimental kernel driver?": 270,
+ "Endpoint:": 53,
+ "Error": 0,
+ "Error Exiting WireGuard": 70,
+ "Error in getting configuration": 36,
+ "Error: ": 178,
+ "Error: %v. Please try again.": 73,
+ "Export all tunnels to &zip…": 149,
+ "Export all tunnels to zip": 147,
+ "Export log to file": 65,
+ "Export tunnels to zip": 173,
+ "Failed to activate tunnel": 97,
+ "Failed to create cookie reply: %v": 226,
+ "Failed to deactivate tunnel": 98,
+ "Failed to decode cookie reply": 198,
+ "Failed to decode initiation message": 203,
+ "Failed to decode response message": 206,
+ "Failed to determine tunnel state": 96,
+ "Failed to load updated MTU of device: %v": 239,
+ "Failed to read packet from TUN device: %v": 229,
+ "Failed to receive %s packet: %v": 193,
+ "Failed to write packet to TUN device: %v": 216,
+ "File ‘%s’ already exists.\n\nDo you want to overwrite it?": 118,
+ "IPv4 packet with disallowed source address from %v": 213,
+ "IPv6 packet with disallowed source address from %v": 214,
+ "Import tunnel(s) from file": 171,
+ "Imported %d of %d tunnels": 159,
+ "Imported %d tunnels": 158,
+ "Imported tunnels": 157,
+ "Inactive": 56,
+ "Interface closed, ignored requested state %s": 179,
+ "Interface down requested": 243,
+ "Interface state was %s, requested %s, now %s": 180,
+ "Interface up requested": 242,
+ "Interface: %s": 99,
+ "Invalid IP address": 23,
+ "Invalid MTU": 27,
+ "Invalid endpoint host": 26,
+ "Invalid key for [Interface] section": 81,
+ "Invalid key for [Peer] section": 82,
+ "Invalid key for interface section": 84,
+ "Invalid key for peer section": 86,
+ "Invalid key: %v": 30,
+ "Invalid name": 110,
+ "Invalid network prefix length": 24,
+ "Invalid packet ended up in the handshake queue": 202,
+ "Invalid persistent keepalive": 29,
+ "Invalid port": 28,
+ "Key must have a value": 80,
+ "Keys must decode to exactly 32 bytes": 77,
+ "Latest handshake:": 55,
+ "Line must occur in a section": 78,
+ "Listen port:": 47,
+ "Log": 59,
+ "Log message": 64,
+ "MTU not updated to negative value: %v": 240,
+ "MTU updated: %v%s": 241,
+ "MTU:": 48,
+ "Missing port from endpoint": 25,
+ "Now": 9,
+ "Number must be a number between 0 and 2^64-1: %v": 31,
+ "Packet with invalid IP version from %v": 215,
+ "Peer": 100,
+ "Persistent keepalive:": 54,
+ "Please ask the system administrator to update.": 275,
+ "Preshared key:": 51,
+ "Protocol version must be 1": 85,
+ "Public key:": 46,
+ "Received invalid initiation message from %s": 204,
+ "Received invalid response message from %s": 207,
+ "Received message with unknown type": 194,
+ "Received packet with invalid mac1": 201,
+ "Received packet with unknown IP version": 230,
+ "Receiving cookie response from %s": 199,
+ "Remove selected tunnel(s)": 146,
+ "Routine: TUN reader - started": 228,
+ "Routine: TUN reader - stopped": 227,
+ "Routine: decryption worker %d - started": 195,
+ "Routine: encryption worker %d - started": 231,
+ "Routine: event worker - started": 238,
+ "Routine: event worker - stopped": 244,
+ "Routine: handshake worker %d - started": 197,
+ "Routine: handshake worker %d - stopped": 196,
+ "Routine: receive incoming %s - started": 192,
+ "Routine: receive incoming %s - stopped": 191,
+ "Scripts:": 87,
+ "Select &all": 61,
+ "Sending cookie response for denied handshake message for %v": 225,
+ "Status:": 43,
+ "Status: %s": 137,
+ "Status: Complete!": 74,
+ "Status: Unknown": 125,
+ "Status: Waiting for administrator": 276,
+ "Status: Waiting for updater service": 177,
+ "Status: Waiting for user": 176,
+ "System clock wound backward!": 10,
+ "Table:": 272,
+ "Text Files (*.txt)|*.txt|All Files (*.*)|*.*": 121,
+ "The %s tunnel has been activated.": 132,
+ "The %s tunnel has been deactivated.": 134,
+ "The WireGuard project is currently testing a high performance kernel driver called WireGuardNT. It will eventually be enabled by default, but for now the project needs testers to try it out. Whether you encounter problems or you find that it works well, please do email team@wireguard.com about your experience.\n\nWould you like to enable the experimental kernel driver?": 271,
+ "Time": 63,
+ "Transfer:": 88,
+ "Trouble determining MTU, assuming default: %v": 183,
+ "Tunnel Error": 67,
+ "Tunnel already exists": 114,
+ "Tunnel name is not valid": 33,
+ "Tunnel name ‘%s’ is invalid.": 112,
+ "Tunnels": 142,
+ "Two commas in a row": 32,
+ "UAPI: Removing all peers": 259,
+ "UAPI: Updating fwmark": 258,
+ "UAPI: Updating listen port": 257,
+ "UAPI: Updating private key": 256,
+ "UDP bind has been updated": 186,
+ "Unable to create new configuration": 116,
+ "Unable to create tunnel": 160,
+ "Unable to delete tunnel": 166,
+ "Unable to delete tunnels": 168,
"Unable to determine whether the process is running under WOW64: %v": 4,
- "Unable to exit service due to: %v. You may want to stop WireGuard from the service manager.": 168,
- "Unable to import configuration: %v": 148,
- "Unable to list existing tunnels": 92,
- "Unable to open current process token: %v": 6,
- "Unable to wait for WireGuard window to appear: %v": 116,
- "Unknown state": 102,
- "Update Now": 171,
- "Usage: %s [\n%s]": 2,
- "When a configuration has exactly one peer, and that peer has an allowed IPs containing at least one of 0.0.0.0/0 or ::/0, then the tunnel service engages a firewall ruleset to block all traffic that is neither to nor from the tunnel interface or is to the wrong DNS server, with special exceptions for DHCP and NDP.": 85,
- "WireGuard Activated": 123,
- "WireGuard Deactivated": 125,
- "WireGuard Detection Error": 115,
- "WireGuard Tunnel Error": 127,
- "WireGuard Update Available": 132,
+ "Unable to exit service due to: %v. You may want to stop WireGuard from the service manager.": 175,
+ "Unable to flush packets: %v": 217,
+ "Unable to import configuration: %v": 156,
+ "Unable to list existing tunnels": 113,
+ "Unable to open current process token: %v": 6,
+ "Unable to update bind: %v": 181,
+ "Unable to wait for WireGuard window to appear: %v": 123,
+ "Unknown state": 58,
+ "Update Now": 72,
+ "Usage: %s [\n%s]": 2,
+ "When a configuration has exactly one peer, and that peer has an allowed IPs containing at least one of 0.0.0.0/0 or ::/0, and the interface does not have table off, then the tunnel service engages a firewall ruleset to block all traffic that is neither to nor from the tunnel interface or is to the wrong DNS server, with special exceptions for DHCP and NDP.": 274,
+ "WireGuard Activated": 131,
+ "WireGuard Deactivated": 133,
+ "WireGuard Detection Error": 122,
+ "WireGuard Tunnel Error": 135,
+ "WireGuard Update Available": 140,
"WireGuard is running, but the UI is only accessible from desktops of the Builtin %s group.": 8,
- "WireGuard logo image": 52,
+ "WireGuard logo image": 40,
"WireGuard may only be used by users who are a member of the Builtin %s group.": 7,
- "WireGuard system tray icon did not appear after 30 seconds.": 9,
- "WireGuard: %s": 128,
- "WireGuard: Deactivated": 117,
- "Writing file failed": 96,
+ "WireGuard system tray icon did not appear after 30 seconds.": 75,
+ "WireGuard: %s": 136,
+ "WireGuard: Deactivated": 124,
+ "Writing file failed": 117,
"You must use the native version of WireGuard on this computer.": 5,
- "[EnumerationSeparator]": 49,
- "[UnitSeparator]": 50,
- "[none specified]": 43,
- "disabled, per policy": 71,
- "enabled": 72,
- "no configuration files were found": 144,
- "post-down": 178,
- "post-up": 176,
- "pre-down": 177,
- "pre-up": 175,
- "♥ &Donate!": 55,
+ "[EnumerationSeparator]": 37,
+ "[UnitSeparator]": 38,
+ "[none specified]": 34,
+ "allowed_ip=%s/%d": 254,
+ "disabled, per policy": 93,
+ "enabled": 94,
+ "endpoint=%s": 248,
+ "fwmark=%d": 246,
+ "invalid UAPI operation: %v": 267,
+ "last_handshake_time_nsec=%d": 250,
+ "last_handshake_time_sec=%d": 249,
+ "listen_port=%d": 245,
+ "no configuration files were found": 152,
+ "off": 273,
+ "persistent_keepalive_interval=%d": 253,
+ "post-down": 92,
+ "post-up": 90,
+ "pre-down": 91,
+ "pre-up": 89,
+ "protocol_version=1": 247,
+ "rx_bytes=%d": 252,
+ "tx_bytes=%d": 251,
+ "♥ &Donate!": 42,
}
-var deIndex = []uint32{ // 181 elements
+var caIndex = []uint32{ // 278 elements
+ // Entry 0 - 1F
+ 0x00000000, 0x00000006, 0x00000042, 0x00000056,
+ 0x00000071, 0x000000b0, 0x000000f5, 0x0000012c,
+ 0x0000018c, 0x00000215, 0x00000219, 0x00000240,
+ 0x0000025e, 0x0000027c, 0x0000029c, 0x000002be,
+ 0x000002e0, 0x000002e9, 0x000002f2, 0x000002ff,
+ 0x0000030c, 0x00000319, 0x00000326, 0x00000333,
+ 0x00000348, 0x0000036c, 0x00000386, 0x000003a9,
+ 0x000003b7, 0x000003c5, 0x000003f1, 0x00000407,
+ // Entry 20 - 3F
+ 0x00000435, 0x00000448, 0x00000468, 0x00000479,
+ 0x000004a8, 0x000004c5, 0x000004c8, 0x000004cb,
+ 0x000004db, 0x000004ed, 0x000004f3, 0x000004ff,
+ 0x00000506, 0x00000511, 0x00000519, 0x00000528,
+ 0x00000538, 0x0000053d, 0x00000546, 0x00000555,
+ 0x00000569, 0x00000577, 0x0000057f, 0x0000059a,
+ 0x000005ac, 0x000005b4, 0x000005c0, 0x000005d1,
+ 0x000005da, 0x000005e1, 0x000005f3, 0x00000607,
+ // Entry 40 - 5F
+ 0x0000060d, 0x00000622, 0x0000063c, 0x00000650,
+ 0x00000660, 0x0000069f, 0x000006b6, 0x000006d3,
+ 0x0000072d, 0x0000073c, 0x0000076a, 0x0000077c,
+ 0x0000077c, 0x0000077c, 0x0000077c, 0x0000077c,
+ 0x0000077c, 0x0000077c, 0x0000077c, 0x0000077c,
+ 0x0000077c, 0x0000077c, 0x0000077c, 0x0000077c,
+ 0x0000077c, 0x0000077c, 0x0000077c, 0x0000077c,
+ 0x0000077c, 0x0000077c, 0x0000077c, 0x0000077c,
+ // Entry 60 - 7F
+ 0x0000077c, 0x0000077c, 0x0000077c, 0x0000077c,
+ 0x0000077c, 0x0000077c, 0x0000077c, 0x0000077c,
+ 0x0000077c, 0x0000077c, 0x0000077c, 0x0000077c,
+ 0x0000077c, 0x0000077c, 0x0000077c, 0x0000077c,
+ 0x0000077c, 0x0000077c, 0x0000077c, 0x0000077c,
+ 0x0000077c, 0x0000077c, 0x0000077c, 0x0000077c,
+ 0x0000077c, 0x0000077c, 0x0000077c, 0x0000077c,
+ 0x0000077c, 0x0000077c, 0x0000077c, 0x0000077c,
+ // Entry 80 - 9F
+ 0x0000077c, 0x0000077c, 0x0000077c, 0x0000077c,
+ 0x0000077c, 0x0000077c, 0x0000077c, 0x0000077c,
+ 0x0000077c, 0x0000077c, 0x0000077c, 0x0000077c,
+ 0x0000077c, 0x0000077c, 0x0000077c, 0x0000077c,
+ 0x0000077c, 0x0000077c, 0x0000077c, 0x0000077c,
+ 0x0000077c, 0x0000077c, 0x0000077c, 0x0000077c,
+ 0x0000077c, 0x0000077c, 0x0000077c, 0x0000077c,
+ 0x0000077c, 0x0000077c, 0x0000077c, 0x0000077c,
+ // Entry A0 - BF
+ 0x0000077c, 0x0000077c, 0x0000077c, 0x0000077c,
+ 0x0000077c, 0x0000077c, 0x0000077c, 0x0000077c,
+ 0x0000077c, 0x0000077c, 0x0000077c, 0x0000077c,
+ 0x0000077c, 0x0000077c, 0x0000077c, 0x0000077c,
+ 0x0000077c, 0x0000077c, 0x0000077c, 0x0000077c,
+ 0x0000077c, 0x0000077c, 0x0000077c, 0x0000077c,
+ 0x0000077c, 0x0000077c, 0x0000077c, 0x0000077c,
+ 0x0000077c, 0x0000077c, 0x0000077c, 0x0000077c,
+ // Entry C0 - DF
+ 0x0000077c, 0x0000077c, 0x0000077c, 0x0000077c,
+ 0x0000077c, 0x0000077c, 0x0000077c, 0x0000077c,
+ 0x0000077c, 0x0000077c, 0x0000077c, 0x0000077c,
+ 0x0000077c, 0x0000077c, 0x0000077c, 0x0000077c,
+ 0x0000077c, 0x0000077c, 0x0000077c, 0x0000077c,
+ 0x0000077c, 0x0000077c, 0x0000077c, 0x0000077c,
+ 0x0000077c, 0x0000077c, 0x0000077c, 0x0000077c,
+ 0x0000077c, 0x0000077c, 0x0000077c, 0x0000077c,
+ // Entry E0 - FF
+ 0x0000077c, 0x0000077c, 0x0000077c, 0x0000077c,
+ 0x0000077c, 0x0000077c, 0x0000077c, 0x0000077c,
+ 0x0000077c, 0x0000077c, 0x0000077c, 0x0000077c,
+ 0x0000077c, 0x0000077c, 0x0000077c, 0x0000077c,
+ 0x0000077c, 0x0000077c, 0x0000077c, 0x0000077c,
+ 0x0000077c, 0x0000077c, 0x0000077c, 0x0000077c,
+ 0x0000077c, 0x0000077c, 0x0000077c, 0x0000077c,
+ 0x0000077c, 0x0000077c, 0x0000077c, 0x0000077c,
+ // Entry 100 - 11F
+ 0x0000077c, 0x0000077c, 0x0000077c, 0x0000077c,
+ 0x0000077c, 0x0000077c, 0x0000077c, 0x0000077c,
+ 0x0000077c, 0x0000077c, 0x0000077c, 0x0000077c,
+ 0x0000077c, 0x0000077c, 0x0000077c, 0x0000077c,
+ 0x0000077c, 0x0000077c, 0x0000077c, 0x0000077c,
+ 0x0000077c, 0x0000077c,
+} // Size: 1136 bytes
+
+const caData string = "" + // Size: 1916 bytes
+ "\x02Error\x02(sense argument): eleva i instala el servei d'administrador" +
+ "\x02Ús: %[1]s [\x0a%[2]s]\x02Opcions de línia d'ordres\x02No s'ha pogut " +
+ "determinar si el procés corre sota WOW64: %[1]v\x02Heu de fer servir la " +
+ "versio nativa de WireGuard en aquest ordinador.\x02No s'ha pogut obrir e" +
+ "l token del procés actual: %[1]v\x02WireGuard només es pot fer servir pe" +
+ "r els usuaris que són membres del grup del sistema %[1]s.\x02WireGuard s" +
+ "'està executsnt, pero la interfície gràfica només és accessible als usua" +
+ "ris que són membres del grup del sistema %[1]s.\x02Ara\x02El rellotge de" +
+ "l sistema s'ha atraçat!\x14\x01\x81\x01\x00\x02\x0a\x02%[1]d any\x00\x0b" +
+ "\x02%[1]d anys\x14\x01\x81\x01\x00\x02\x0a\x02%[1]d dia\x00\x0b\x02%[1]d" +
+ " dies\x14\x01\x81\x01\x00\x02\x0b\x02%[1]d hora\x00\x0c\x02%[1]d hores" +
+ "\x14\x01\x81\x01\x00\x02\x0c\x02%[1]d minut\x00\x0d\x02%[1]d minuts\x14" +
+ "\x01\x81\x01\x00\x02\x0c\x02%[1]d segon\x00\x0d\x02%[1]d segons\x02Fa %[" +
+ "1]s\x02%[1]d\u00a0B\x02%.2[1]f\u00a0KiB\x02%.2[1]f\u00a0MiB\x02%.2[1]f" +
+ "\u00a0GiB\x02%.2[1]f\u00a0TiB\x02%[1]s: %[2]q\x02Adreça IP invàlida\x02T" +
+ "amany del prefix de xarxa invàlid\x02Falta el port de l'extrem\x02El for" +
+ "mat de l'extrem no és valid\x02MTU invàlida\x02Port invàlid\x02Temps de " +
+ "missatge de persistència invàlid\x02Clau invàlida: %[1]v\x02El nombre ha" +
+ " de estar entre 0 i 2^64-1: %[1]v\x02Dos comes seguides\x02El nom del tú" +
+ "nel no és vàlid\x02[no especificat]\x02Tots els parells han de tenir cla" +
+ "us públiques\x02Error obtenint configuració\x02, \x02, \x02Sobre WireGua" +
+ "rd\x02Logo de WireGuard\x02Tanca\x02♥ & Dona!\x02Estat:\x02&Desactiva" +
+ "\x02&Activa\x02Clau pública:\x02Port d'escolta:\x02MTU:\x02Adreces:\x02S" +
+ "ervidors DNS:\x02Clau precompartida:\x02IPs permeses:\x02Extrem:\x02Miss" +
+ "atge de persistència:\x02Últim handshake:\x02Inactiu\x02Desactivant\x02E" +
+ "stat desconegut\x02Registre\x02&Copia\x02Selecciona-ho tot\x02Desa en un" +
+ " arxiu…\x02Temps\x02Missatge de registre\x02Exporta registre a fitxer" +
+ "\x02&Sobre WireGuard…\x02Error de túnel\x02%[1]s\x0a\x0aSi us plau, cons" +
+ "ulteu el registre per més informació.\x02%[1]s (desactualitzat)\x02Error" +
+ " al sortir de WireGuard\x02Una actualització per WireGuard està disponib" +
+ "le. Es recomana actualitzar immediatament.\x02Actualitza ara\x02Error: %" +
+ "[1]v. Si us plau, torneu-ho a provar.\x02Estat: Completat!"
+
+var csIndex = []uint32{ // 278 elements
+ // Entry 0 - 1F
+ 0x00000000, 0x00000006, 0x0000004f, 0x00000069,
+ 0x0000008a, 0x000000bd, 0x00000106, 0x00000138,
+ 0x00000193, 0x00000201, 0x00000206, 0x0000022f,
+ 0x00000265, 0x0000029b, 0x000002da, 0x00000319,
+ 0x0000035c, 0x00000368, 0x00000371, 0x0000037e,
+ 0x0000038b, 0x00000398, 0x000003a5, 0x000003b2,
+ 0x000003c6, 0x000003eb, 0x00000401, 0x00000414,
+ 0x00000422, 0x00000431, 0x00000453, 0x0000046b,
+ // Entry 20 - 3F
+ 0x0000049d, 0x000004b3, 0x000004ce, 0x000004e5,
+ 0x00000512, 0x00000536, 0x00000539, 0x0000053c,
+ 0x00000551, 0x00000569, 0x00000572, 0x00000580,
+ 0x00000586, 0x00000593, 0x0000059e, 0x000005b0,
+ 0x000005c8, 0x000005cd, 0x000005d5, 0x000005e2,
+ 0x000005f9, 0x00000607, 0x00000611, 0x00000627,
+ 0x0000063c, 0x00000647, 0x00000652, 0x00000661,
+ 0x0000066a, 0x00000676, 0x00000683, 0x0000069a,
+ // Entry 40 - 5F
+ 0x0000069f, 0x000006ac, 0x000006ca, 0x000006e3,
+ 0x000006f0, 0x0000072b, 0x00000740, 0x0000076c,
+ 0x000007d5, 0x000007e8, 0x00000807, 0x00000819,
+ 0x00000865, 0x0000088a, 0x000008c0, 0x000008e5,
+ 0x00000925, 0x0000093f, 0x00000966, 0x00000988,
+ 0x000009b3, 0x000009d8, 0x000009f5, 0x00000a13,
+ 0x00000a1c, 0x00000a25, 0x00000a35, 0x00000a41,
+ 0x00000a51, 0x00000a5d, 0x00000a73, 0x00000a7b,
+ // Entry 60 - 7F
+ 0x00000a9b, 0x00000abe, 0x00000add, 0x00000afe,
+ 0x00000b0f, 0x00000b14, 0x00000b2a, 0x00000b38,
+ 0x00000b41, 0x00000b54, 0x00000b60, 0x00000b8d,
+ 0x00000b96, 0x00000b9e, 0x00000bab, 0x00000bbc,
+ 0x00000bd0, 0x00000bf4, 0x00000c20, 0x00000c34,
+ 0x00000c5b, 0x00000c86, 0x00000ca2, 0x00000cd6,
+ 0x00000cdf, 0x00000ce8, 0x00000d22, 0x00000d3f,
+ 0x00000d70, 0x00000d88, 0x00000d98, 0x00000da9,
+ // Entry 80 - 9F
+ 0x00000dbd, 0x00000de0, 0x00000dea, 0x00000df2,
+ 0x00000e07, 0x00000e23, 0x00000e3a, 0x00000e58,
+ 0x00000e6f, 0x00000e80, 0x00000e8c, 0x00000e9a,
+ 0x00000eb6, 0x00000edb, 0x00000f3d, 0x00000f44,
+ 0x00000f4d, 0x00000f69, 0x00000f77, 0x00000f91,
+ 0x00000fb3, 0x00000fbe, 0x00000fe4, 0x00000fff,
+ 0x0000101a, 0x0000104a, 0x00001077, 0x000010ac,
+ 0x000010d2, 0x000010f6, 0x0000110a, 0x0000117f,
+ // Entry A0 - BF
+ 0x00001214, 0x0000122a, 0x00001294, 0x0000133e,
+ 0x00001356, 0x0000137e, 0x000013a3, 0x000013b9,
+ 0x000013df, 0x000013f6, 0x000014a0, 0x000014ee,
+ 0x0000150d, 0x00001534, 0x0000154d, 0x0000157e,
+ 0x000015d8, 0x000015f6, 0x0000161e, 0x0000161e,
+ 0x0000161e, 0x0000161e, 0x0000161e, 0x0000161e,
+ 0x0000161e, 0x0000161e, 0x0000161e, 0x0000161e,
+ 0x0000161e, 0x0000161e, 0x0000161e, 0x0000161e,
+ // Entry C0 - DF
+ 0x0000161e, 0x0000161e, 0x0000161e, 0x0000161e,
+ 0x0000161e, 0x0000161e, 0x0000161e, 0x0000161e,
+ 0x0000161e, 0x0000161e, 0x0000161e, 0x0000161e,
+ 0x0000161e, 0x0000161e, 0x0000161e, 0x0000161e,
+ 0x0000161e, 0x0000161e, 0x0000161e, 0x0000161e,
+ 0x0000161e, 0x0000161e, 0x0000161e, 0x0000161e,
+ 0x0000161e, 0x0000161e, 0x0000161e, 0x0000161e,
+ 0x0000161e, 0x0000161e, 0x0000161e, 0x0000161e,
+ // Entry E0 - FF
+ 0x0000161e, 0x0000161e, 0x0000161e, 0x0000161e,
+ 0x0000161e, 0x0000161e, 0x0000161e, 0x0000161e,
+ 0x0000161e, 0x0000161e, 0x0000161e, 0x0000161e,
+ 0x0000161e, 0x0000161e, 0x0000161e, 0x0000161e,
+ 0x0000161e, 0x0000161e, 0x0000161e, 0x0000161e,
+ 0x0000161e, 0x0000161e, 0x0000161e, 0x0000161e,
+ 0x0000161e, 0x0000161e, 0x0000161e, 0x0000161e,
+ 0x0000161e, 0x0000161e, 0x0000161e, 0x0000161e,
+ // Entry 100 - 11F
+ 0x0000161e, 0x0000161e, 0x0000161e, 0x0000161e,
+ 0x0000161e, 0x0000161e, 0x0000161e, 0x0000161e,
+ 0x0000161e, 0x0000161e, 0x0000161e, 0x0000161e,
+ 0x0000161e, 0x0000161e, 0x0000161e, 0x0000161e,
+ 0x0000161e, 0x0000161e, 0x0000161e, 0x0000161e,
+ 0x0000161e, 0x0000161e,
+} // Size: 1136 bytes
+
+const csData string = "" + // Size: 5662 bytes
+ "\x02Chyba\x02(žádný argument): Zvýšit oprávnění a instalovat službu sprá" +
+ "vce\x02Použití: %[1]s [\x0a%[2]s]\x02Možnosti příkazového řádku\x02Nelze" +
+ " zjistit, zda proces běží pod WOW64: %[1]v\x02Musíte použít nativní verz" +
+ "i aplikace WireGuard na tomto počítači.\x02Nelze otevřít token aktuálníh" +
+ "o procesu: %[1]v\x02WireGuard můžou používat pouze uživatelé, kteří jsou" +
+ " členy Builtin skupiny %[1]s.\x02WireGuard je spuštěn, ale uživatelské r" +
+ "ozhraní je přístupné pouze uživatelům Builtin skupiny %[1]s.\x02Teď\x02S" +
+ "ystémové hodiny byly posunuty dozadu!\x14\x01\x81\x01\x00\x04\x0b\x02%[1" +
+ "]d roky\x05\x0a\x02%[1]d let\x02\x0a\x02%[1]d rok\x00\x0a\x02%[1]d let" +
+ "\x14\x01\x81\x01\x00\x04\x0a\x02%[1]d dny\x05\x0b\x02%[1]d dnů\x02\x0a" +
+ "\x02%[1]d den\x00\x0a\x02%[1]d dny\x14\x01\x81\x01\x00\x04\x0d\x02%[1]d " +
+ "hodiny\x05\x0c\x02%[1]d hodin\x02\x0d\x02%[1]d hodina\x00\x0c\x02%[1]d h" +
+ "odin\x14\x01\x81\x01\x00\x04\x0d\x02%[1]d minuty\x05\x0c\x02%[1]d minut" +
+ "\x02\x0d\x02%[1]d minuta\x00\x0c\x02%[1]d minut\x14\x01\x81\x01\x00\x04" +
+ "\x0e\x02%[1]d sekundy\x05\x0d\x02%[1]d sekund\x02\x0e\x02%[1]d sekunda" +
+ "\x00\x0d\x02%[1]d sekund\x02před %[1]s\x02%[1]d\u00a0B\x02%.2[1]f\u00a0K" +
+ "iB\x02%.2[1]f\u00a0MiB\x02%.2[1]f\u00a0GiB\x02%.2[1]f\u00a0TiB\x02%[1]s:" +
+ " %[2]q\x02Neplatná IP adresa\x02Neplatná délka síťového prefixu\x02Endpo" +
+ "intu chybí port\x02Neplatný endpoint\x02Neplatné MTU\x02Neplatný port" +
+ "\x02Neplatný persistentní keepalive\x02Neplatný klíč: %[1]v\x02Číslo mus" +
+ "í mít hodnotu mezi 0 a 2^64-1: %[1]v\x02Dvě čárky za sebou\x02Název tun" +
+ "elu je neplatný\x02[není specifikováno]\x02Všichni peeři musí mít veřejn" +
+ "é klíče\x02Chyba při načítání konfigurace\x02, \x02, \x02O aplikaci Wir" +
+ "eGuard\x02Obrázek loga WireGuard\x02Zavřít\x02♥ &Darovat!\x02Stav:\x02&D" +
+ "eaktivovat\x02&Aktivovat\x02Veřejný klíč:\x02Port pro naslouchání:\x02MT" +
+ "U:\x02Adresy:\x02DNS servery:\x02Předsdílený klíč:\x02Povolené IP:\x02En" +
+ "dpoint:\x02Persistent keepalive:\x02Poslední handshake:\x02Neaktivní\x02" +
+ "Deaktivuji\x02Neznámý stav\x02Záznamy\x02&Kopírovat\x02Vybr&at vše\x02&U" +
+ "ložit do souboru…\x02Čas\x02Zpráva logu\x02Exportovat záznam do souboru" +
+ "\x02&O aplikaci WireGuard…\x02Chyba tunelu\x02%[1]s\x0a\x0aPro více info" +
+ "rmací se prosím podívejte do logu.\x02%[1]s (neaktuální)\x02Chyba při uk" +
+ "ončování aplikace WireGuard\x02Aktualizace aplikace WireGuard je nyní k " +
+ "dispozici. Silně doporučujeme ji aktualizovat co nejdříve.\x02Aktualizov" +
+ "at nyní\x02Chyba: %[1]v. Zkuste to znovu.\x02Stav: Dokončeno!\x02Ikona W" +
+ "ireGuard se ani po 30 sekundách nezobrazila na systémové liště.\x02Závor" +
+ "ky musí obsahovat IPv6 adresu\x02Klíče musí být dekódovány přesně na 32 " +
+ "bajtů\x02Řádek musí být v některé sekci\x02Konfigurační klíč neobsahuje " +
+ "oddělovač (znak 'rovná se')\x02Klíč musí mít hodnotu\x02Neplatný klíč pr" +
+ "o sekci [Interface]\x02Neplatný klíč pro sekci [Peer]\x02Rozhraní musí o" +
+ "bsahovat soukromý klíč\x02Neplatný klíč pro sekci rozhraní\x02Verze prot" +
+ "okolu musí být 1\x02Neplatný klíč v sekci peer\x02Skripty:\x02Přenos:" +
+ "\x02před-zapnutím\x02po-zapnutí\x02před-vypnutím\x02po-vypnutí\x02vypnut" +
+ "o, podle zásad\x02zapnuto\x02%[1]s přijato, %[2]s odesláno\x02Nepodařilo" +
+ " se zjistit stav tunelu\x02Nepodařilo se aktivovat tunel\x02Nepodařilo s" +
+ "e deaktivovat tunel\x02Rozhraní: %[1]s\x02Peer\x02Vytvořit nový tunel" +
+ "\x02Upravit tunel\x02&Název:\x02&Veřejný klíč:\x02(neznámý)\x02&Blokovat" +
+ " netunelovaný provoz (kill-switch)\x02&Uložit\x02Zrušit\x02&Nastavení:" +
+ "\x02Neplatný název\x02Název je povinný.\x02Název tunelu '%[1]s' je nepla" +
+ "tný.\x02Nepodařilo se zobrazit existující tunely\x02Tunel již existuje" +
+ "\x02Tunel s názvem '%[1]s' již existuje.\x02Nepodařilo se vytvořit novou" +
+ " konfiguraci\x02Zápis souboru se nezdařil\x02Soubor \x22%[1]s\x22 již ex" +
+ "istuje.\x0a\x0aChcete jej přepsat?\x02Aktivní\x02Aktivuji\x02Textové sou" +
+ "bory (*.txt)|*.txt|Všechny soubory (*.*)|*.*\x02Chyba při detekci WireGu" +
+ "ard\x02Nelze čekat na zobrazení okna WireGuard: %[1]v\x02WireGuard: Deak" +
+ "tivován\x02Stav: Neznámý\x02Adresy: žádné\x02Spravovat tunely…\x02&Impor" +
+ "tovat tunel(y) ze souboru…\x02U&končit\x02&Tunely\x02WireGuard aktivován" +
+ "\x02Tunel %[1]s byl aktivován.\x02WireGuard deaktivován\x02Tunel %[1]s b" +
+ "yl deaktivován.\x02WireGuard Chyba Tunelu\x02WireGuard: %[1]s\x02Stav: %" +
+ "[1]s\x02Adresy: %[1]s\x02Aktualizace je k dispozici!\x02Aktualizace Wire" +
+ "Guard je k dispozici\x02Aktualizace aplikace WireGuard je nyní k dispozi" +
+ "ci. Doporučujeme ji aktualizovat co nejdříve.\x02Tunely\x02&Upravit\x02P" +
+ "řidat &prázdný tunel…\x02Přidat tunel\x02Odstranit vybrané tunely\x02Ex" +
+ "portovat všechny tunely do zip\x02&Přepnout\x02Exportovat všechny tunely" +
+ " do &zip…\x02Upravit &vybraný tunel…\x02&Odstranit vybrané tunely\x02neb" +
+ "yly nalezeny žádné konfigurační soubory\x02Nelze importovat vybranou kon" +
+ "figuraci: %[1]v\x02Nepodařilo se vyjmenovat existující tunely: %[1]v\x02" +
+ "Tunel s názvem '%[1]s' již existuje\x02Nelze importovat konfiguraci: %[1" +
+ "]v\x02Importované tunely\x14\x01\x81\x01\x00\x04\x1a\x02Importovány %[1]" +
+ "d tunely\x05\x1b\x02Importováno %[1]d tunelů\x02\x18\x02Importován %[1]d" +
+ " tunel\x00\x1b\x02Importováno %[1]d tunelů\x14\x02\x80\x01\x04#\x02Impor" +
+ "továno %[1]d z %[2]d tunelů\x05#\x02Importováno %[1]d z %[2]d tunelů\x02" +
+ " \x02Importován %[1]d z %[2]d tunel\x00#\x02Importováno %[1]d z %[2]d tu" +
+ "nelů\x02Nelze vytvořit tunel\x14\x01\x81\x01\x00\x04\x17\x02Odstranit %[" +
+ "1]d tunely\x05\x18\x02Odstranit %[1]d tunelů\x02\x16\x02Odstranit %[1]d " +
+ "tunel\x00\x18\x02Odstranit %[1]d tunelů\x14\x01\x81\x01\x00\x04'\x02Opra" +
+ "vdu chcete odstranit %[1]d tunely?\x05(\x02Opravdu chcete odstranit %[1]" +
+ "d tunelů?\x02&\x02Opravdu chcete odstranit %[1]d tunel?\x00(\x02Opravdu " +
+ "chcete odstranit %[1]d tunelů?\x02Odstranit tunel \x22%[1]s\x22\x02Oprav" +
+ "du chcete odstranit tunel \x22%[1]s\x22?\x02%[1]s Tuto akci nelze vrátit" +
+ " zpět.\x02Nelze odstranit tunel\x02Tunel nebylo možné odstranit: %[1]s" +
+ "\x02Nelze odstranit tunely\x14\x01\x81\x01\x00\x04'\x02%[1]d tunely neby" +
+ "lo možné odstranit.\x05(\x02%[1]d tunelů nebylo možné odstranit.\x02&" +
+ "\x02%[1]d tunel nebylo možné odstranit.\x00(\x02%[1]d tunelů nebylo možn" +
+ "é odstranit.\x02Konfigurace souborů (*.zip, *.conf)|*.zip; *.conf|Všech" +
+ "ny soubory (*.*)|*.*\x02Importovat tunel(y) ze souboru\x02Konfigurace so" +
+ "uborů ZIP (*.zip)|*.zip\x02Exportovat tunely do zip\x02%[1]s (nepodepsan" +
+ "á verze, žádné aktualizace)\x02Nelze ukončit službu z důvodu: %[1]v. Wi" +
+ "reGuard můžete zastavit ve správci služeb.\x02Stav: Čekání na uživatele" +
+ "\x02Stav: Čeká se na službu aktualizací"
+
+var deIndex = []uint32{ // 278 elements
// Entry 0 - 1F
0x00000000, 0x00000007, 0x00000059, 0x00000074,
0x0000008b, 0x000000e1, 0x00000137, 0x0000016b,
- 0x000001c2, 0x0000023a, 0x0000028a, 0x00000290,
- 0x000002b6, 0x000002d6, 0x000002f4, 0x00000318,
- 0x0000033c, 0x00000362, 0x0000036c, 0x00000375,
- 0x00000382, 0x0000038f, 0x0000039c, 0x000003a9,
- 0x000003b6, 0x000003cc, 0x000003f4, 0x00000412,
- 0x0000042c, 0x00000460, 0x0000046f, 0x00000480,
+ 0x000001c2, 0x0000023a, 0x00000240, 0x00000266,
+ 0x00000286, 0x000002a4, 0x000002c8, 0x000002ec,
+ 0x00000312, 0x0000031c, 0x00000325, 0x00000332,
+ 0x0000033f, 0x0000034c, 0x00000359, 0x00000366,
+ 0x0000037c, 0x000003a4, 0x000003c2, 0x000003dc,
+ 0x000003eb, 0x000003fc, 0x0000041c, 0x0000043a,
// Entry 20 - 3F
- 0x000004a0, 0x000004be, 0x000004f5, 0x00000521,
- 0x0000053d, 0x0000055a, 0x0000058b, 0x000005c6,
- 0x000005e4, 0x00000612, 0x0000063a, 0x00000674,
- 0x00000689, 0x000006c7, 0x000006ed, 0x0000071a,
- 0x0000073b, 0x00000763, 0x00000766, 0x00000769,
- 0x00000779, 0x00000788, 0x000007f6, 0x00000801,
- 0x0000080f, 0x00000817, 0x00000825, 0x00000831,
- 0x0000084b, 0x00000859, 0x0000085e, 0x00000868,
+ 0x00000466, 0x00000482, 0x0000049f, 0x000004b4,
+ 0x000004f2, 0x00000518, 0x0000051b, 0x0000051e,
+ 0x0000052e, 0x0000053d, 0x00000548, 0x00000556,
+ 0x0000055e, 0x0000056c, 0x00000578, 0x00000592,
+ 0x000005a0, 0x000005a5, 0x000005af, 0x000005bb,
+ 0x000005d1, 0x000005df, 0x000005e9, 0x000005fe,
+ 0x00000618, 0x00000620, 0x0000062c, 0x00000640,
+ 0x0000064a, 0x00000654, 0x00000665, 0x0000067c,
// Entry 40 - 5F
- 0x00000874, 0x0000087d, 0x00000893, 0x000008a1,
- 0x000008ab, 0x000008c0, 0x000008da, 0x000008e7,
- 0x00000903, 0x0000090d, 0x0000092d, 0x00000958,
- 0x0000097d, 0x000009a4, 0x000009b9, 0x000009c4,
- 0x000009e1, 0x000009f3, 0x000009fa, 0x00000a15,
- 0x00000a21, 0x00000a55, 0x00000bbd, 0x00000bc8,
- 0x00000bd2, 0x00000be2, 0x00000bf3, 0x00000c0b,
- 0x00000c2f, 0x00000c62, 0x00000c7b, 0x00000cb3,
+ 0x00000681, 0x00000692, 0x000006b0, 0x000006c4,
+ 0x000006d2, 0x00000713, 0x00000724, 0x00000746,
+ 0x000007b4, 0x000007c8, 0x000007f6, 0x00000806,
+ 0x00000856, 0x0000088a, 0x000008c1, 0x000008f2,
+ 0x0000092d, 0x0000094b, 0x00000979, 0x000009a1,
+ 0x000009db, 0x00000a08, 0x00000a29, 0x00000a51,
+ 0x00000a5a, 0x00000a67, 0x00000a7a, 0x00000a91,
+ 0x00000aa6, 0x00000abc, 0x00000ad8, 0x00000ae2,
// Entry 60 - 7F
- 0x00000ce1, 0x00000d01, 0x00000d46, 0x00000d4c,
- 0x00000d56, 0x00000d5e, 0x00000d6a, 0x00000d7e,
- 0x00000d88, 0x00000d92, 0x00000da3, 0x00000dba,
- 0x00000dbf, 0x00000dd0, 0x00000e01, 0x00000e1f,
- 0x00000e33, 0x00000e41, 0x00000e82, 0x00000e93,
- 0x00000eae, 0x00000ef6, 0x00000f0d, 0x00000f1f,
- 0x00000f2f, 0x00000f44, 0x00000f65, 0x00000f6e,
- 0x00000f82, 0x00000fa4, 0x00000fba, 0x00000fde,
+ 0x00000b02, 0x00000b2d, 0x00000b52, 0x00000b79,
+ 0x00000b8e, 0x00000b99, 0x00000bb6, 0x00000bc8,
+ 0x00000bcf, 0x00000bea, 0x00000bf6, 0x00000c2a,
+ 0x00000c35, 0x00000c3f, 0x00000c4f, 0x00000c60,
+ 0x00000c78, 0x00000c9c, 0x00000ccf, 0x00000ce8,
+ 0x00000d20, 0x00000d4e, 0x00000d6e, 0x00000db3,
+ 0x00000db9, 0x00000dc3, 0x00000df4, 0x00000e0f,
+ 0x00000e57, 0x00000e6e, 0x00000e80, 0x00000e90,
// Entry 80 - 9F
- 0x00000ff6, 0x00001007, 0x00001015, 0x00001025,
- 0x00001049, 0x0000106d, 0x000010e0, 0x000010e7,
- 0x000010f3, 0x00001117, 0x0000112a, 0x00001148,
- 0x00001172, 0x0000117e, 0x000011a3, 0x000011c7,
- 0x000011e8, 0x0000120d, 0x0000124e, 0x00001280,
- 0x000012ba, 0x000012ee, 0x00001300, 0x00001339,
- 0x00001385, 0x000013a5, 0x000013da, 0x0000144a,
- 0x00001466, 0x0000149d, 0x000014da, 0x000014f9,
+ 0x00000ea5, 0x00000ec6, 0x00000ecf, 0x00000ed7,
+ 0x00000eeb, 0x00000f0d, 0x00000f23, 0x00000f47,
+ 0x00000f5f, 0x00000f70, 0x00000f7e, 0x00000f8e,
+ 0x00000fb2, 0x00000fd6, 0x00001049, 0x00001050,
+ 0x0000105c, 0x00001080, 0x00001093, 0x000010b1,
+ 0x000010db, 0x000010e7, 0x0000110c, 0x00001130,
+ 0x00001151, 0x00001176, 0x000011b7, 0x000011e9,
+ 0x00001223, 0x00001257, 0x00001269, 0x000012a2,
// Entry A0 - BF
- 0x00001529, 0x0000154f, 0x000015b0, 0x000015fa,
- 0x00001616, 0x0000163f, 0x0000165e, 0x00001689,
- 0x000016ab, 0x00001717, 0x00001785, 0x0000179f,
- 0x000017b3, 0x000017dc, 0x0000180a, 0x0000181a,
- 0x0000181a, 0x0000181a, 0x0000181a, 0x0000181a,
- 0x0000181a,
-} // Size: 748 bytes
+ 0x000012ee, 0x0000130e, 0x00001343, 0x000013b3,
+ 0x000013cf, 0x00001406, 0x00001443, 0x00001462,
+ 0x00001492, 0x000014b8, 0x00001519, 0x00001563,
+ 0x0000157f, 0x000015a8, 0x000015c7, 0x000015f2,
+ 0x0000165e, 0x00001678, 0x000016a1, 0x000016a1,
+ 0x000016a1, 0x000016a1, 0x000016a1, 0x000016a1,
+ 0x000016a1, 0x000016a1, 0x000016a1, 0x000016a1,
+ 0x000016a1, 0x000016a1, 0x000016a1, 0x000016a1,
+ // Entry C0 - DF
+ 0x000016a1, 0x000016a1, 0x000016a1, 0x000016a1,
+ 0x000016a1, 0x000016a1, 0x000016a1, 0x000016a1,
+ 0x000016a1, 0x000016a1, 0x000016a1, 0x000016a1,
+ 0x000016a1, 0x000016a1, 0x000016a1, 0x000016a1,
+ 0x000016a1, 0x000016a1, 0x000016a1, 0x000016a1,
+ 0x000016a1, 0x000016a1, 0x000016a1, 0x000016a1,
+ 0x000016a1, 0x000016a1, 0x000016a1, 0x000016a1,
+ 0x000016a1, 0x000016a1, 0x000016a1, 0x000016a1,
+ // Entry E0 - FF
+ 0x000016a1, 0x000016a1, 0x000016a1, 0x000016a1,
+ 0x000016a1, 0x000016a1, 0x000016a1, 0x000016a1,
+ 0x000016a1, 0x000016a1, 0x000016a1, 0x000016a1,
+ 0x000016a1, 0x000016a1, 0x000016a1, 0x000016a1,
+ 0x000016a1, 0x000016a1, 0x000016a1, 0x000016a1,
+ 0x000016a1, 0x000016a1, 0x000016a1, 0x000016a1,
+ 0x000016a1, 0x000016a1, 0x000016a1, 0x000016a1,
+ 0x000016a1, 0x000016a1, 0x000016a1, 0x000016a1,
+ // Entry 100 - 11F
+ 0x000016a1, 0x000016a1, 0x000016a1, 0x000016a1,
+ 0x000016a1, 0x000016a1, 0x000016a1, 0x000016a1,
+ 0x000016a1, 0x000016a1, 0x000016a1, 0x000016a1,
+ 0x000016a1, 0x000016a1, 0x000016a1, 0x000016a1,
+ 0x000016a1, 0x000016a1, 0x000016a1, 0x000016a1,
+ 0x000016a1, 0x000016a1,
+} // Size: 1136 bytes
-const deData string = "" + // Size: 6170 bytes
+const deData string = "" + // Size: 5793 bytes
"\x02Fehler\x02(kein Argument): Als Administrator ausführen und den Manag" +
"er-Dienst installieren\x02Verwendung: %[1]s [\x0a%[2]s]\x02Kommandozeile" +
"noptionen\x02Es kann nicht festgestellt werden, ob der Prozess unter WOW" +
@@ -302,220 +720,239 @@ const deData string = "" + // Size: 6170 bytes
"en nicht öffnen: %[1]v\x02WireGuard kann nur von Benutzern verwendet wer" +
"den, die Mitglied der Gruppe %[1]s sind.\x02WireGuard wird ausgeführt, a" +
"ber auf die Benutzeroberfläche kann nur von Desktops der Gruppe %[1]s zu" +
- "gegriffen werden.\x02Das WireGuard-Taskleistensymbol ist nicht innerhalb" +
- " von 30 Sekunden erschienen.\x02Jetzt\x02Die Systemuhr wurde zurück gest" +
- "ellt!\x14\x01\x81\x01\x00\x02\x0b\x02%[1]d Jahr\x00\x0c\x02%[1]d Jahre" +
- "\x14\x01\x81\x01\x00\x02\x0a\x02%[1]d Tag\x00\x0b\x02%[1]d Tage\x14\x01" +
- "\x81\x01\x00\x02\x0d\x02%[1]d Stunde\x00\x0e\x02%[1]d Stunden\x14\x01" +
- "\x81\x01\x00\x02\x0d\x02%[1]d Minute\x00\x0e\x02%[1]d Minuten\x14\x01" +
- "\x81\x01\x00\x02\x0e\x02%[1]d Sekunde\x00\x0f\x02%[1]d Sekunden\x02vor %" +
- "[1]s\x02%[1]d\u00a0B\x02%.2[1]f\u00a0KiB\x02%.2[1]f\u00a0MiB\x02%.2[1]f" +
- "\u00a0GiB\x02%.2[1]f\u00a0TiB\x02%[1]s: %[2]q\x02Ungültige IP-Adresse" +
- "\x02Ungültige Länge des Netzwerkpräfixes\x02Fehlender Port des Endpunkte" +
- "s\x02Ungültiger Endpunkt-Host\x02Eckige Klammern müssen eine IPv6 Adress" +
- "e enthalten\x02Ungültige MTU\x02Ungültiger Port\x02Ungültiges Erhaltungs" +
- "intervall\x02Ungültiger Schlüssel: %[1]v\x02Schlüssel müssen auf exakt 3" +
- "2 Bytes dekodiert werden\x02Zahl muss zwischen 0 und 2^64-1 sein: %[1]v" +
- "\x02Zwei Kommata in einer Zeile\x02Der Tunnelname ist ungültig\x02Die Ze" +
- "ile muss innerhalb eines Abschnitts stehen\x02Konfigurationsschlüssel fe" +
- "hlt ein Gleichheitstrennzeichen\x02Eintrag muss einen Wert haben\x02Ungü" +
- "ltiger Eintrage im [Interface] Abschnitt\x02Ungültiger Eintrag im [Peer]" +
- " Abschnitt\x02Eine Schnittstelle muss einen privaten Schlssel enthalten" +
- "\x02[nicht spezifiziert]\x02Alle Teilnehmer (peers) müssen öffentliche S" +
- "chlüssel haben\x02Fehler beim Abrufen der Konfiguration\x02Ungültiger Ei" +
- "ntrag im Abschnitt [interface]\x02Die Protokollversion muss 1 sein\x02Un" +
- "gültiger Eintrag im Abschnitt [peer]\x02, \x02, \x02Über WireGuard\x02Wi" +
- "reGuard Logo\x02App Version: %[1]s\x0aGo backend Version: %[2]s\x0aGo Ve" +
- "rsion: %[3]s-%[4]s\x0aBetriebssystem: %[5]s\x0aArchitektur: %[6]s\x02Sch" +
- "ließen\x02♥ &Spenden!\x02Status:\x02&Deaktivieren\x02&Aktivieren\x02Öffe" +
- "ntlicher Schlüssel:\x02Eingangsport:\x02MTU:\x02Adressen:\x02DNS-Server:" +
- "\x02Skripte:\x02Geteilter Schlüssel:\x02Erlaubte IPs:\x02Endpunkt:\x02Er" +
- "haltungsintervall:\x02Letzter Schlüsseltausch:\x02Übertragen:\x02deaktiv" +
- "iert, per Richtlinie\x02aktiviert\x02%[1]s empfangen, %[2]s gesendet\x02" +
- "Tunnelstatus konnte nicht ermittelt werden\x02Tunnel aktivieren ist fehl" +
- "geschlagen\x02Tunnel deaktivieren ist fehlgeschlagen\x02Schnittstelle: %" +
- "[1]s\x02Teilnehmer\x02Einen neuen Tunnel erstellen\x02Tunnel bearbeiten" +
- "\x02&Name:\x02&Öffentlicher Schlüssel:\x02(unbekannt)\x02&Blockiere Verk" +
- "ehr außerhalb des Tunnels (Not-Aus)\x02Wenn eine Konfiguration genau ein" +
- "en Teilnehmer enthält und dieser einen der Einträge 0.0.0.0/0 oder ::/0 " +
- "in den erlaubten IPs enthält, dann erstellt der Tunneldienst ein Firewal" +
- "l-Regelsatz, der allen Verkehr (insbesondere zum falschen DNS-Server) bl" +
- "ockiert, der weder aus dem Tunnel stammt noch in den Tunnel geht, mit Au" +
- "snahmen für DHCP- und NDP-Verkehr.\x02&Speichern\x02Abbrechen\x02&Konfig" +
- "uration:\x02Ungültiger Name\x02Ein Name ist notwendig.\x02Der Name „%[1]" +
- "s“ ist ungültig.\x02Vorhandene Tunnel können nicht aufgelistet werden" +
- "\x02Tunnel existiert bereits\x02Ein Tunnel mit dem Namen „%[1]s“ existie" +
- "rt bereits.\x02Neue Konfiguration kann nicht erstellt werden\x02Schreibe" +
- "n der Datei schlug fehl\x02Die Datei „%[1]s“ existiert bereits.\x0a\x0aM" +
- "öchten Sie sie ersetzen?\x02Aktiv\x02Aktiviere\x02Inaktiv\x02Deaktivier" +
- "e\x02Unbekannter Zustand\x02Protokoll\x02&Kopieren\x02&Alles markieren" +
- "\x02&In Datei Speichern…\x02Zeit\x02Protokolleintrag\x02Textdateien (*.t" +
- "xt)|*.txt|Alle Dateien (*.*)|*.*\x02Exportiere Protokoll in Datei\x02&Üb" +
- "er WireGuard…\x02Tunnel Fehler\x02%[1]s\x0a\x0aBitte lesen Sie das Proto" +
- "koll für weitere Informationen.\x02%[1]s (veraltet)\x02WireGuard Erkennu" +
- "ngsfehler\x02Warten auf das Erscheinen des WireGuard Fensters nicht mögl" +
- "ich: %[1]v \x02WireGuard: Deaktiviert\x02Status: Unbekannt\x02Adressen: " +
- "Keine\x02Tunnel &verwalten…\x02Tunnel aus Datei &importieren…\x02&Beende" +
- "n\x02WireGuard aktiviert\x02Der Tunnel %[1]s wurde aktiviert.\x02WireGua" +
- "rd deaktiviert\x02Der Tunnel %[1]s wurde deaktiviert.\x02WireGuard Tunne" +
- "l Fehler\x02WireGuard: %[1]s\x02Status: %[1]s\x02Adressen: %[1]s\x02Eine" +
- " Aktualisierung ist verfügbar!\x02WireGuard Aktualisierung verfügbar\x02" +
- "Eine Aktualisierung für WireGuard ist jetzt verfügbar. Es wird empfohlen" +
- " diese schnellstmöglich durchzuführen.\x02Tunnel\x02&Bearbeiten\x02Einen" +
- " &leeren Tunnel hinzufügen…\x02Tunnel hinzufügen\x02Markierte(n) Tunnel " +
- "entfernen\x02Alle Tunnel in eine Zip-Datei exportieren\x02&Umschalten" +
- "\x02Exportiere alle Tunnel in &Zip-Datei\x02Ausgewählten Tunnel &bearbei" +
- "ten…\x02Ausgewählte(n) Tunnel &löschen\x02keine Konfigurationsdateien ge" +
- "funden\x02Ausgewählte Konfiguration konnte nicht importiert werden: %[1]" +
- "v\x02Konnte existierende Tunnel nicht auflisten: %[1]v\x02Es existiert b" +
- "ereits ein Tunnel mit dem Namen „%[1]s“\x02Importieren der Konfiguration" +
- " nicht möglich: %[1]v\x02Tunnel importiert\x14\x01\x81\x01\x00\x02\x18" +
- "\x02%[1]d Tunnel importiert\x00\x18\x02%[1]d Tunnel importiert\x14\x02" +
- "\x80\x01\x02\x22\x02%[1]d von %[2]d Tunnel importiert\x00\x22\x02%[1]d v" +
- "on %[2]d Tunnel importiert\x02Tunnel erstellen nicht möglich\x14\x01\x81" +
- "\x01\x00\x02\x16\x02%[1]d Tunnel löschen\x00\x16\x02%[1]d Tunnel löschen" +
- "\x14\x01\x81\x01\x00\x024\x02Möchten Sie diesen %[1]d Tunnel wirklich lö" +
- "schen?\x003\x02Möchten Sie diese %[1]d Tunnel wirklich löschen?\x02Tunne" +
- "l „%[1]s“ löschen\x02Möchten Sie den Tunnel „%[1]s“ wirklich löschen?" +
- "\x02%[1]s Dieser Schritt kann nicht rückgängig gemacht werden.\x02Tunnel" +
- " löschen nicht möglich\x02Ein Tunnel konnte nicht gelöscht werden: %[1]s" +
- "\x02Tunnel konnten nicht gelöscht werden\x14\x01\x81\x01\x00\x02+\x02%[1" +
- "]d Tunnel konnte nicht entfernt werden.\x00-\x02%[1]d Tunnel konnten nic" +
- "ht gelöscht werden.\x02Konfigurationsdateien (*.zip, *.conf)|*.zip;*.con" +
- "f|Alle Dateien (*.*)|*.*\x02Importiere Tunnel aus Datei\x02Konfiguration" +
- "s-ZIP-Dateien (*.zip)|*.zip\x02Exportiere Tunnel in Zip-Datei\x02%[1]s (" +
- "unsigniert, keine Aktualisierungen)\x02Fehler beim Beenden von WireGuard" +
- "\x02Der Dienst konnte nicht gestoppt werden: %[1]v. Versuchen Sie WireGu" +
- "ard in der Dienstverwaltung zu beenden.\x02Eine Aktualisierung für WireG" +
- "uard ist verfügbar. Es ist höchst empfehlenswert diese sofort durchzufüh" +
- "ren.\x02Status: Auf Nutzer warten\x02Jetzt aktualisieren\x02Status: Auf " +
- "Aktualisierungsdienst warten\x02Fehler: %[1]v. Bitte versuchen Sie es er" +
- "neut.\x02Status: Fertig!"
+ "gegriffen werden.\x02Jetzt\x02Die Systemuhr wurde zurück gestellt!\x14" +
+ "\x01\x81\x01\x00\x02\x0b\x02%[1]d Jahr\x00\x0c\x02%[1]d Jahre\x14\x01" +
+ "\x81\x01\x00\x02\x0a\x02%[1]d Tag\x00\x0b\x02%[1]d Tage\x14\x01\x81\x01" +
+ "\x00\x02\x0d\x02%[1]d Stunde\x00\x0e\x02%[1]d Stunden\x14\x01\x81\x01" +
+ "\x00\x02\x0d\x02%[1]d Minute\x00\x0e\x02%[1]d Minuten\x14\x01\x81\x01" +
+ "\x00\x02\x0e\x02%[1]d Sekunde\x00\x0f\x02%[1]d Sekunden\x02vor %[1]s\x02" +
+ "%[1]d\u00a0B\x02%.2[1]f\u00a0KiB\x02%.2[1]f\u00a0MiB\x02%.2[1]f\u00a0GiB" +
+ "\x02%.2[1]f\u00a0TiB\x02%[1]s: %[2]q\x02Ungültige IP-Adresse\x02Ungültig" +
+ "e Länge des Netzwerkpräfixes\x02Fehlender Port des Endpunktes\x02Ungülti" +
+ "ger Endpunkt-Host\x02Ungültige MTU\x02Ungültiger Port\x02Ungültiges Erha" +
+ "ltungsintervall\x02Ungültiger Schlüssel: %[1]v\x02Zahl muss zwischen 0 u" +
+ "nd 2^64-1 sein: %[1]v\x02Zwei Kommata in einer Zeile\x02Der Tunnelname i" +
+ "st ungültig\x02[nicht spezifiziert]\x02Alle Teilnehmer (peers) müssen öf" +
+ "fentliche Schlüssel haben\x02Fehler beim Abrufen der Konfiguration\x02, " +
+ "\x02, \x02Über WireGuard\x02WireGuard Logo\x02Schließen\x02♥ &Spenden!" +
+ "\x02Status:\x02&Deaktivieren\x02&Aktivieren\x02Öffentlicher Schlüssel:" +
+ "\x02Eingangsport:\x02MTU:\x02Adressen:\x02DNS-Server:\x02Geteilter Schlü" +
+ "ssel:\x02Erlaubte IPs:\x02Endpunkt:\x02Erhaltungsintervall:\x02Letzter S" +
+ "chlüsseltausch:\x02Inaktiv\x02Deaktiviere\x02Unbekannter Zustand\x02Prot" +
+ "okoll\x02&Kopieren\x02&Alles markieren\x02&In Datei Speichern…\x02Zeit" +
+ "\x02Protokolleintrag\x02Exportiere Protokoll in Datei\x02&Über WireGuard" +
+ "…\x02Tunnel Fehler\x02%[1]s\x0a\x0aBitte lesen Sie das Protokoll für w" +
+ "eitere Informationen.\x02%[1]s (veraltet)\x02Fehler beim Beenden von Wir" +
+ "eGuard\x02Eine Aktualisierung für WireGuard ist verfügbar. Es ist höchst" +
+ " empfehlenswert diese sofort durchzuführen.\x02Jetzt aktualisieren\x02Fe" +
+ "hler: %[1]v. Bitte versuchen Sie es erneut.\x02Status: Fertig!\x02Das Wi" +
+ "reGuard-Taskleistensymbol ist nicht innerhalb von 30 Sekunden erschienen" +
+ ".\x02Eckige Klammern müssen eine IPv6 Adresse enthalten\x02Schlüssel müs" +
+ "sen auf exakt 32 Bytes dekodiert werden\x02Die Zeile muss innerhalb eine" +
+ "s Abschnitts stehen\x02Konfigurationsschlüssel fehlt ein Gleichheitstren" +
+ "nzeichen\x02Eintrag muss einen Wert haben\x02Ungültiger Eintrage im [Int" +
+ "erface] Abschnitt\x02Ungültiger Eintrag im [Peer] Abschnitt\x02Eine Schn" +
+ "ittstelle muss einen privaten Schlssel enthalten\x02Ungültiger Eintrag i" +
+ "m Abschnitt [interface]\x02Die Protokollversion muss 1 sein\x02Ungültige" +
+ "r Eintrag im Abschnitt [peer]\x02Skripte:\x02Übertragen:\x02vor Verbinds" +
+ "aufbau\x02nach Verbindungsaufbau\x02vor Verbindungsabbau\x02nach Verbind" +
+ "ungsabbau\x02deaktiviert, per Richtlinie\x02aktiviert\x02%[1]s empfangen" +
+ ", %[2]s gesendet\x02Tunnelstatus konnte nicht ermittelt werden\x02Tunnel" +
+ " aktivieren ist fehlgeschlagen\x02Tunnel deaktivieren ist fehlgeschlagen" +
+ "\x02Schnittstelle: %[1]s\x02Teilnehmer\x02Einen neuen Tunnel erstellen" +
+ "\x02Tunnel bearbeiten\x02&Name:\x02&Öffentlicher Schlüssel:\x02(unbekann" +
+ "t)\x02&Blockiere Verkehr außerhalb des Tunnels (Not-Aus)\x02&Speichern" +
+ "\x02Abbrechen\x02&Konfiguration:\x02Ungültiger Name\x02Ein Name ist notw" +
+ "endig.\x02Der Name „%[1]s“ ist ungültig.\x02Vorhandene Tunnel können nic" +
+ "ht aufgelistet werden\x02Tunnel existiert bereits\x02Ein Tunnel mit dem " +
+ "Namen „%[1]s“ existiert bereits.\x02Neue Konfiguration kann nicht erstel" +
+ "lt werden\x02Schreiben der Datei schlug fehl\x02Die Datei „%[1]s“ existi" +
+ "ert bereits.\x0a\x0aMöchten Sie sie ersetzen?\x02Aktiv\x02Aktiviere\x02T" +
+ "extdateien (*.txt)|*.txt|Alle Dateien (*.*)|*.*\x02WireGuard Erkennungsf" +
+ "ehler\x02Warten auf das Erscheinen des WireGuard Fensters nicht möglich:" +
+ " %[1]v \x02WireGuard: Deaktiviert\x02Status: Unbekannt\x02Adressen: Kein" +
+ "e\x02Tunnel &verwalten…\x02Tunnel aus Datei &importieren…\x02&Beenden" +
+ "\x02&Tunnel\x02WireGuard aktiviert\x02Der Tunnel %[1]s wurde aktiviert." +
+ "\x02WireGuard deaktiviert\x02Der Tunnel %[1]s wurde deaktiviert.\x02Wire" +
+ "Guard Tunnel Fehler\x02WireGuard: %[1]s\x02Status: %[1]s\x02Adressen: %[" +
+ "1]s\x02Eine Aktualisierung ist verfügbar!\x02WireGuard Aktualisierung ve" +
+ "rfügbar\x02Eine Aktualisierung für WireGuard ist jetzt verfügbar. Es wir" +
+ "d empfohlen diese schnellstmöglich durchzuführen.\x02Tunnel\x02&Bearbeit" +
+ "en\x02Einen &leeren Tunnel hinzufügen…\x02Tunnel hinzufügen\x02Markierte" +
+ "(n) Tunnel entfernen\x02Alle Tunnel in eine Zip-Datei exportieren\x02&Um" +
+ "schalten\x02Exportiere alle Tunnel in &Zip-Datei\x02Ausgewählten Tunnel " +
+ "&bearbeiten…\x02Ausgewählte(n) Tunnel &löschen\x02keine Konfigurationsda" +
+ "teien gefunden\x02Ausgewählte Konfiguration konnte nicht importiert werd" +
+ "en: %[1]v\x02Konnte existierende Tunnel nicht auflisten: %[1]v\x02Es exi" +
+ "stiert bereits ein Tunnel mit dem Namen „%[1]s“\x02Importieren der Konfi" +
+ "guration nicht möglich: %[1]v\x02Tunnel importiert\x14\x01\x81\x01\x00" +
+ "\x02\x18\x02%[1]d Tunnel importiert\x00\x18\x02%[1]d Tunnel importiert" +
+ "\x14\x02\x80\x01\x02\x22\x02%[1]d von %[2]d Tunnel importiert\x00\x22" +
+ "\x02%[1]d von %[2]d Tunnel importiert\x02Tunnel erstellen nicht möglich" +
+ "\x14\x01\x81\x01\x00\x02\x16\x02%[1]d Tunnel löschen\x00\x16\x02%[1]d Tu" +
+ "nnel löschen\x14\x01\x81\x01\x00\x024\x02Möchten Sie diesen %[1]d Tunnel" +
+ " wirklich löschen?\x003\x02Möchten Sie diese %[1]d Tunnel wirklich lösch" +
+ "en?\x02Tunnel „%[1]s“ löschen\x02Möchten Sie den Tunnel „%[1]s“ wirklich" +
+ " löschen?\x02%[1]s Dieser Schritt kann nicht rückgängig gemacht werden." +
+ "\x02Tunnel löschen nicht möglich\x02Ein Tunnel konnte nicht gelöscht wer" +
+ "den: %[1]s\x02Tunnel konnten nicht gelöscht werden\x14\x01\x81\x01\x00" +
+ "\x02+\x02%[1]d Tunnel konnte nicht entfernt werden.\x00-\x02%[1]d Tunnel" +
+ " konnten nicht gelöscht werden.\x02Konfigurationsdateien (*.zip, *.conf)" +
+ "|*.zip;*.conf|Alle Dateien (*.*)|*.*\x02Importiere Tunnel aus Datei\x02K" +
+ "onfigurations-ZIP-Dateien (*.zip)|*.zip\x02Exportiere Tunnel in Zip-Date" +
+ "i\x02%[1]s (unsigniert, keine Aktualisierungen)\x02Der Dienst konnte nic" +
+ "ht gestoppt werden: %[1]v. Versuchen Sie WireGuard in der Dienstverwaltu" +
+ "ng zu beenden.\x02Status: Auf Nutzer warten\x02Status: Auf Aktualisierun" +
+ "gsdienst warten"
-var enIndex = []uint32{ // 181 elements
+var enIndex = []uint32{ // 278 elements
// Entry 0 - 1F
0x00000000, 0x00000006, 0x00000039, 0x0000004f,
0x00000064, 0x000000aa, 0x000000e9, 0x00000115,
- 0x00000166, 0x000001c4, 0x00000200, 0x00000204,
- 0x00000221, 0x00000241, 0x0000025f, 0x0000027f,
- 0x000002a3, 0x000002c7, 0x000002d1, 0x000002da,
- 0x000002e7, 0x000002f4, 0x00000301, 0x0000030e,
- 0x0000031b, 0x0000032e, 0x0000034c, 0x00000367,
- 0x0000037d, 0x000003a3, 0x000003af, 0x000003bc,
+ 0x00000166, 0x000001c4, 0x000001c8, 0x000001e5,
+ 0x00000205, 0x00000223, 0x00000243, 0x00000267,
+ 0x0000028b, 0x00000295, 0x0000029e, 0x000002ab,
+ 0x000002b8, 0x000002c5, 0x000002d2, 0x000002df,
+ 0x000002f2, 0x00000310, 0x0000032b, 0x00000341,
+ 0x0000034d, 0x0000035a, 0x00000377, 0x0000038a,
// Entry 20 - 3F
- 0x000003d9, 0x000003ec, 0x00000411, 0x00000445,
- 0x00000459, 0x00000472, 0x0000048f, 0x000004b9,
- 0x000004cf, 0x000004f3, 0x00000512, 0x00000537,
- 0x00000548, 0x00000568, 0x00000587, 0x000005a9,
- 0x000005c4, 0x000005e1, 0x000005e4, 0x000005e7,
- 0x000005f7, 0x0000060c, 0x0000067d, 0x00000683,
- 0x00000690, 0x00000698, 0x000006a4, 0x000006ae,
- 0x000006ba, 0x000006c7, 0x000006cc, 0x000006d7,
+ 0x000003be, 0x000003d2, 0x000003eb, 0x000003fc,
+ 0x0000041c, 0x0000043b, 0x0000043e, 0x00000441,
+ 0x00000451, 0x00000466, 0x0000046c, 0x00000479,
+ 0x00000481, 0x0000048d, 0x00000497, 0x000004a3,
+ 0x000004b0, 0x000004b5, 0x000004c0, 0x000004cd,
+ 0x000004dc, 0x000004e9, 0x000004f3, 0x00000509,
+ 0x0000051b, 0x00000524, 0x00000531, 0x0000053f,
+ 0x00000543, 0x00000549, 0x00000555, 0x00000566,
// Entry 40 - 5F
- 0x000006e4, 0x000006ed, 0x000006fc, 0x00000709,
- 0x00000713, 0x00000729, 0x0000073b, 0x00000745,
- 0x0000075a, 0x00000762, 0x0000077d, 0x0000079e,
- 0x000007b8, 0x000007d4, 0x000007e5, 0x000007ea,
- 0x000007fc, 0x00000808, 0x0000080f, 0x0000081c,
- 0x00000826, 0x0000084e, 0x0000098a, 0x00000990,
- 0x00000997, 0x000009a7, 0x000009b4, 0x000009c8,
- 0x000009ec, 0x00000a0c, 0x00000a22, 0x00000a5b,
+ 0x0000056b, 0x00000577, 0x0000058a, 0x0000059e,
+ 0x000005ab, 0x000005df, 0x000005f3, 0x0000060b,
+ 0x00000660, 0x0000066b, 0x0000068b, 0x0000069d,
+ 0x000006d9, 0x000006ff, 0x00000724, 0x00000741,
+ 0x0000076b, 0x00000781, 0x000007a5, 0x000007c4,
+ 0x000007e9, 0x0000080b, 0x00000826, 0x00000843,
+ 0x0000084c, 0x00000856, 0x0000085d, 0x00000865,
+ 0x0000086e, 0x00000878, 0x0000088d, 0x00000895,
// Entry 60 - 7F
- 0x00000a7e, 0x00000a92, 0x00000ad1, 0x00000ad8,
- 0x00000ae3, 0x00000aec, 0x00000af9, 0x00000b07,
- 0x00000b0b, 0x00000b11, 0x00000b1d, 0x00000b2e,
- 0x00000b33, 0x00000b3f, 0x00000b6c, 0x00000b7f,
- 0x00000b93, 0x00000ba0, 0x00000bd4, 0x00000be8,
- 0x00000c02, 0x00000c37, 0x00000c4e, 0x00000c5e,
- 0x00000c6e, 0x00000c81, 0x00000ca0, 0x00000ca6,
- 0x00000cba, 0x00000cdf, 0x00000cf5, 0x00000d1c,
+ 0x000008b0, 0x000008d1, 0x000008eb, 0x00000907,
+ 0x00000918, 0x0000091d, 0x0000092f, 0x0000093b,
+ 0x00000942, 0x0000094f, 0x00000959, 0x00000981,
+ 0x00000987, 0x0000098e, 0x0000099e, 0x000009ab,
+ 0x000009bf, 0x000009e3, 0x00000a03, 0x00000a19,
+ 0x00000a52, 0x00000a75, 0x00000a89, 0x00000ac8,
+ 0x00000acf, 0x00000ada, 0x00000b07, 0x00000b21,
+ 0x00000b56, 0x00000b6d, 0x00000b7d, 0x00000b8d,
// Entry 80 - 9F
- 0x00000d33, 0x00000d44, 0x00000d52, 0x00000d63,
- 0x00000d7b, 0x00000d96, 0x00000dee, 0x00000df6,
- 0x00000dfc, 0x00000e11, 0x00000e1c, 0x00000e36,
- 0x00000e50, 0x00000e58, 0x00000e76, 0x00000e8f,
- 0x00000eaa, 0x00000ecc, 0x00000efb, 0x00000f27,
- 0x00000f5f, 0x00000f85, 0x00000f96, 0x00000fcc,
- 0x00001013, 0x0000102b, 0x0000105d, 0x000010cf,
- 0x000010e9, 0x00001123, 0x00001146, 0x0000115e,
+ 0x00000ba0, 0x00000bbf, 0x00000bc5, 0x00000bce,
+ 0x00000be2, 0x00000c07, 0x00000c1d, 0x00000c44,
+ 0x00000c5b, 0x00000c6c, 0x00000c7a, 0x00000c8b,
+ 0x00000ca3, 0x00000cbe, 0x00000d16, 0x00000d1e,
+ 0x00000d24, 0x00000d39, 0x00000d44, 0x00000d5e,
+ 0x00000d78, 0x00000d80, 0x00000d9e, 0x00000db7,
+ 0x00000dd2, 0x00000df4, 0x00000e23, 0x00000e4f,
+ 0x00000e87, 0x00000ead, 0x00000ebe, 0x00000ef4,
// Entry A0 - BF
- 0x00001187, 0x000011a0, 0x000011f9, 0x0000123e,
- 0x00001259, 0x0000127f, 0x00001295, 0x000012b8,
- 0x000012d0, 0x0000132f, 0x00001384, 0x0000139d,
- 0x000013a8, 0x000013cc, 0x000013ec, 0x000013fe,
- 0x00001405, 0x0000140d, 0x00001416, 0x00001420,
- 0x00001429,
-} // Size: 748 bytes
+ 0x00000f3b, 0x00000f53, 0x00000f85, 0x00000ff7,
+ 0x00001011, 0x0000104b, 0x0000106e, 0x00001086,
+ 0x000010af, 0x000010c8, 0x00001121, 0x00001166,
+ 0x00001181, 0x000011a7, 0x000011bd, 0x000011e0,
+ 0x0000123f, 0x00001258, 0x0000127c, 0x00001288,
+ 0x000012b8, 0x000012ee, 0x0000130b, 0x00001324,
+ 0x00001355, 0x00001364, 0x00001372, 0x0000138c,
+ 0x000013c7, 0x000013f9, 0x0000140a, 0x0000141b,
+ // Entry C0 - DF
+ 0x00001445, 0x0000146f, 0x00001495, 0x000014b8,
+ 0x000014e3, 0x0000150d, 0x00001537, 0x00001555,
+ 0x0000157a, 0x000015a4, 0x000015c6, 0x000015f5,
+ 0x00001619, 0x00001648, 0x0000166e, 0x00001690,
+ 0x000016bd, 0x000016e1, 0x00001709, 0x00001738,
+ 0x00001767, 0x0000178a, 0x000017c0, 0x000017f6,
+ 0x00001820, 0x0000184c, 0x0000186b, 0x0000188c,
+ 0x000018b1, 0x000018e4, 0x00001917, 0x0000193a,
+ // Entry E0 - FF
+ 0x0000196b, 0x0000199c, 0x000019db, 0x00001a00,
+ 0x00001a1e, 0x00001a3c, 0x00001a69, 0x00001a91,
+ 0x00001abc, 0x00001ae9, 0x00001b13, 0x00001b56,
+ 0x00001ba3, 0x00001bf2, 0x00001c42, 0x00001c62,
+ 0x00001c8e, 0x00001cb7, 0x00001ccf, 0x00001ce6,
+ 0x00001cff, 0x00001d1f, 0x00001d31, 0x00001d3e,
+ 0x00001d51, 0x00001d60, 0x00001d7e, 0x00001d9d,
+ 0x00001dac, 0x00001dbb, 0x00001ddf, 0x00001df6,
+ // Entry 100 - 11F
+ 0x00001dfc, 0x00001e17, 0x00001e32, 0x00001e48,
+ 0x00001e61, 0x00001e77, 0x00001e8e, 0x00001eb3,
+ 0x00001ed3, 0x00001f08, 0x00001f2e, 0x00001f4d,
+ 0x00001f6b, 0x00001fdc, 0x00001ffd, 0x00002020,
+ 0x00002192, 0x00002199, 0x0000219d, 0x00002304,
+ 0x00002333, 0x00002355,
+} // Size: 1136 bytes
-const enData string = "" + // Size: 5161 bytes
+const enData string = "" + // Size: 9045 bytes
"\x02Error\x02(no argument): elevate and install manager service\x02Usage" +
": %[1]s [\x0a%[2]s]\x02Command Line Options\x02Unable to determine wheth" +
"er the process is running under WOW64: %[1]v\x02You must use the native " +
"version of WireGuard on this computer.\x02Unable to open current process" +
" token: %[1]v\x02WireGuard may only be used by users who are a member of" +
" the Builtin %[1]s group.\x02WireGuard is running, but the UI is only ac" +
- "cessible from desktops of the Builtin %[1]s group.\x02WireGuard system t" +
- "ray icon did not appear after 30 seconds.\x02Now\x02System clock wound b" +
- "ackward!\x14\x01\x81\x01\x00\x02\x0b\x02%[1]d year\x00\x0c\x02%[1]d year" +
- "s\x14\x01\x81\x01\x00\x02\x0a\x02%[1]d day\x00\x0b\x02%[1]d days\x14\x01" +
- "\x81\x01\x00\x02\x0b\x02%[1]d hour\x00\x0c\x02%[1]d hours\x14\x01\x81" +
- "\x01\x00\x02\x0d\x02%[1]d minute\x00\x0e\x02%[1]d minutes\x14\x01\x81" +
- "\x01\x00\x02\x0d\x02%[1]d second\x00\x0e\x02%[1]d seconds\x02%[1]s ago" +
- "\x02%[1]d\u00a0B\x02%.2[1]f\u00a0KiB\x02%.2[1]f\u00a0MiB\x02%.2[1]f" +
- "\u00a0GiB\x02%.2[1]f\u00a0TiB\x02%[1]s: %[2]q\x02Invalid IP address\x02I" +
- "nvalid network prefix length\x02Missing port from endpoint\x02Invalid en" +
- "dpoint host\x02Brackets must contain an IPv6 address\x02Invalid MTU\x02I" +
- "nvalid port\x02Invalid persistent keepalive\x02Invalid key: %[1]v\x02Key" +
- "s must decode to exactly 32 bytes\x02Number must be a number between 0 a" +
- "nd 2^64-1: %[1]v\x02Two commas in a row\x02Tunnel name is not valid\x02L" +
- "ine must occur in a section\x02Config key is missing an equals separator" +
- "\x02Key must have a value\x02Invalid key for [Interface] section\x02Inva" +
- "lid key for [Peer] section\x02An interface must have a private key\x02[n" +
- "one specified]\x02All peers must have public keys\x02Error in getting co" +
- "nfiguration\x02Invalid key for interface section\x02Protocol version mus" +
- "t be 1\x02Invalid key for peer section\x02, \x02, \x02About WireGuard" +
- "\x02WireGuard logo image\x02App version: %[1]s\x0aGo backend version: %[" +
- "2]s\x0aGo version: %[3]s-%[4]s\x0aOperating system: %[5]s\x0aArchitectur" +
- "e: %[6]s\x02Close\x02♥ &Donate!\x02Status:\x02&Deactivate\x02&Activate" +
- "\x02Public key:\x02Listen port:\x02MTU:\x02Addresses:\x02DNS servers:" +
- "\x02Scripts:\x02Preshared key:\x02Allowed IPs:\x02Endpoint:\x02Persisten" +
- "t keepalive:\x02Latest handshake:\x02Transfer:\x02disabled, per policy" +
- "\x02enabled\x02%[1]s received, %[2]s sent\x02Failed to determine tunnel " +
- "state\x02Failed to activate tunnel\x02Failed to deactivate tunnel\x02Int" +
- "erface: %[1]s\x02Peer\x02Create new tunnel\x02Edit tunnel\x02&Name:\x02&" +
- "Public key:\x02(unknown)\x02&Block untunneled traffic (kill-switch)\x02W" +
- "hen a configuration has exactly one peer, and that peer has an allowed I" +
- "Ps containing at least one of 0.0.0.0/0 or ::/0, then the tunnel service" +
- " engages a firewall ruleset to block all traffic that is neither to nor " +
- "from the tunnel interface or is to the wrong DNS server, with special ex" +
- "ceptions for DHCP and NDP.\x02&Save\x02Cancel\x02&Configuration:\x02Inva" +
- "lid name\x02A name is required.\x02Tunnel name ‘%[1]s’ is invalid.\x02Un" +
- "able to list existing tunnels\x02Tunnel already exists\x02Another tunnel" +
- " already exists with the name ‘%[1]s’.\x02Unable to create new configura" +
- "tion\x02Writing file failed\x02File ‘%[1]s’ already exists.\x0a\x0aDo yo" +
- "u want to overwrite it?\x02Active\x02Activating\x02Inactive\x02Deactivat" +
- "ing\x02Unknown state\x02Log\x02&Copy\x02Select &all\x02&Save to file…" +
- "\x02Time\x02Log message\x02Text Files (*.txt)|*.txt|All Files (*.*)|*.*" +
- "\x02Export log to file\x02&About WireGuard…\x02Tunnel Error\x02%[1]s\x0a" +
- "\x0aPlease consult the log for more information.\x02%[1]s (out of date)" +
- "\x02WireGuard Detection Error\x02Unable to wait for WireGuard window to " +
- "appear: %[1]v\x02WireGuard: Deactivated\x02Status: Unknown\x02Addresses:" +
- " None\x02&Manage tunnels…\x02&Import tunnel(s) from file…\x02E&xit\x02Wi" +
- "reGuard Activated\x02The %[1]s tunnel has been activated.\x02WireGuard D" +
- "eactivated\x02The %[1]s tunnel has been deactivated.\x02WireGuard Tunnel" +
- " Error\x02WireGuard: %[1]s\x02Status: %[1]s\x02Addresses: %[1]s\x02An Up" +
- "date is Available!\x02WireGuard Update Available\x02An update to WireGua" +
- "rd is now available. You are advised to update as soon as possible.\x02T" +
- "unnels\x02&Edit\x02Add &empty tunnel…\x02Add Tunnel\x02Remove selected t" +
- "unnel(s)\x02Export all tunnels to zip\x02&Toggle\x02Export all tunnels t" +
- "o &zip…\x02Edit &selected tunnel…\x02&Remove selected tunnel(s)\x02no co" +
- "nfiguration files were found\x02Could not import selected configuration:" +
- " %[1]v\x02Could not enumerate existing tunnels: %[1]v\x02Another tunnel " +
- "already exists with the name ‘%[1]s’\x02Unable to import configuration: " +
- "%[1]v\x02Imported tunnels\x14\x01\x81\x01\x00\x02\x16\x02Imported %[1]d " +
- "tunnel\x00\x17\x02Imported %[1]d tunnels\x14\x02\x80\x01\x02\x1f\x02Impo" +
- "rted %[1]d of %[2]d tunnel\x00 \x02Imported %[1]d of %[2]d tunnels\x02Un" +
- "able to create tunnel\x14\x01\x81\x01\x00\x02\x14\x02Delete %[1]d tunnel" +
+ "cessible from desktops of the Builtin %[1]s group.\x02Now\x02System cloc" +
+ "k wound backward!\x14\x01\x81\x01\x00\x02\x0b\x02%[1]d year\x00\x0c\x02%" +
+ "[1]d years\x14\x01\x81\x01\x00\x02\x0a\x02%[1]d day\x00\x0b\x02%[1]d day" +
+ "s\x14\x01\x81\x01\x00\x02\x0b\x02%[1]d hour\x00\x0c\x02%[1]d hours\x14" +
+ "\x01\x81\x01\x00\x02\x0d\x02%[1]d minute\x00\x0e\x02%[1]d minutes\x14" +
+ "\x01\x81\x01\x00\x02\x0d\x02%[1]d second\x00\x0e\x02%[1]d seconds\x02%[1" +
+ "]s ago\x02%[1]d\u00a0B\x02%.2[1]f\u00a0KiB\x02%.2[1]f\u00a0MiB\x02%.2[1]" +
+ "f\u00a0GiB\x02%.2[1]f\u00a0TiB\x02%[1]s: %[2]q\x02Invalid IP address\x02" +
+ "Invalid network prefix length\x02Missing port from endpoint\x02Invalid e" +
+ "ndpoint host\x02Invalid MTU\x02Invalid port\x02Invalid persistent keepal" +
+ "ive\x02Invalid key: %[1]v\x02Number must be a number between 0 and 2^64-" +
+ "1: %[1]v\x02Two commas in a row\x02Tunnel name is not valid\x02[none spe" +
+ "cified]\x02All peers must have public keys\x02Error in getting configura" +
+ "tion\x02, \x02, \x02About WireGuard\x02WireGuard logo image\x02Close\x02" +
+ "♥ &Donate!\x02Status:\x02&Deactivate\x02&Activate\x02Public key:\x02Li" +
+ "sten port:\x02MTU:\x02Addresses:\x02DNS servers:\x02Preshared key:\x02Al" +
+ "lowed IPs:\x02Endpoint:\x02Persistent keepalive:\x02Latest handshake:" +
+ "\x02Inactive\x02Deactivating\x02Unknown state\x02Log\x02&Copy\x02Select " +
+ "&all\x02&Save to file…\x02Time\x02Log message\x02Export log to file\x02&" +
+ "About WireGuard…\x02Tunnel Error\x02%[1]s\x0a\x0aPlease consult the log " +
+ "for more information.\x02%[1]s (out of date)\x02Error Exiting WireGuard" +
+ "\x02An update to WireGuard is available. It is highly advisable to updat" +
+ "e without delay.\x02Update Now\x02Error: %[1]v. Please try again.\x02Sta" +
+ "tus: Complete!\x02WireGuard system tray icon did not appear after 30 sec" +
+ "onds.\x02Brackets must contain an IPv6 address\x02Keys must decode to ex" +
+ "actly 32 bytes\x02Line must occur in a section\x02Config key is missing " +
+ "an equals separator\x02Key must have a value\x02Invalid key for [Interfa" +
+ "ce] section\x02Invalid key for [Peer] section\x02An interface must have " +
+ "a private key\x02Invalid key for interface section\x02Protocol version m" +
+ "ust be 1\x02Invalid key for peer section\x02Scripts:\x02Transfer:\x02pre" +
+ "-up\x02post-up\x02pre-down\x02post-down\x02disabled, per policy\x02enabl" +
+ "ed\x02%[1]s received, %[2]s sent\x02Failed to determine tunnel state\x02" +
+ "Failed to activate tunnel\x02Failed to deactivate tunnel\x02Interface: %" +
+ "[1]s\x02Peer\x02Create new tunnel\x02Edit tunnel\x02&Name:\x02&Public ke" +
+ "y:\x02(unknown)\x02&Block untunneled traffic (kill-switch)\x02&Save\x02C" +
+ "ancel\x02&Configuration:\x02Invalid name\x02A name is required.\x02Tunne" +
+ "l name ‘%[1]s’ is invalid.\x02Unable to list existing tunnels\x02Tunnel " +
+ "already exists\x02Another tunnel already exists with the name ‘%[1]s’." +
+ "\x02Unable to create new configuration\x02Writing file failed\x02File ‘%" +
+ "[1]s’ already exists.\x0a\x0aDo you want to overwrite it?\x02Active\x02A" +
+ "ctivating\x02Text Files (*.txt)|*.txt|All Files (*.*)|*.*\x02WireGuard D" +
+ "etection Error\x02Unable to wait for WireGuard window to appear: %[1]v" +
+ "\x02WireGuard: Deactivated\x02Status: Unknown\x02Addresses: None\x02&Man" +
+ "age tunnels…\x02&Import tunnel(s) from file…\x02E&xit\x02&Tunnels\x02Wir" +
+ "eGuard Activated\x02The %[1]s tunnel has been activated.\x02WireGuard De" +
+ "activated\x02The %[1]s tunnel has been deactivated.\x02WireGuard Tunnel " +
+ "Error\x02WireGuard: %[1]s\x02Status: %[1]s\x02Addresses: %[1]s\x02An Upd" +
+ "ate is Available!\x02WireGuard Update Available\x02An update to WireGuar" +
+ "d is now available. You are advised to update as soon as possible.\x02Tu" +
+ "nnels\x02&Edit\x02Add &empty tunnel…\x02Add Tunnel\x02Remove selected tu" +
+ "nnel(s)\x02Export all tunnels to zip\x02&Toggle\x02Export all tunnels to" +
+ " &zip…\x02Edit &selected tunnel…\x02&Remove selected tunnel(s)\x02no con" +
+ "figuration files were found\x02Could not import selected configuration: " +
+ "%[1]v\x02Could not enumerate existing tunnels: %[1]v\x02Another tunnel a" +
+ "lready exists with the name ‘%[1]s’\x02Unable to import configuration: %" +
+ "[1]v\x02Imported tunnels\x14\x01\x81\x01\x00\x02\x16\x02Imported %[1]d t" +
+ "unnel\x00\x17\x02Imported %[1]d tunnels\x14\x02\x80\x01\x02\x1f\x02Impor" +
+ "ted %[1]d of %[2]d tunnel\x00 \x02Imported %[1]d of %[2]d tunnels\x02Una" +
+ "ble to create tunnel\x14\x01\x81\x01\x00\x02\x14\x02Delete %[1]d tunnel" +
"\x00\x15\x02Delete %[1]d tunnels\x14\x01\x81\x01\x00\x024\x02Are you sur" +
"e you would like to delete %[1]d tunnel?\x005\x02Are you sure you would " +
"like to delete %[1]d tunnels?\x02Delete tunnel ‘%[1]s’\x02Are you sure y" +
@@ -525,127 +962,284 @@ const enData string = "" + // Size: 5161 bytes
"l was unable to be removed.\x00)\x02%[1]d tunnels were unable to be remo" +
"ved.\x02Configuration Files (*.zip, *.conf)|*.zip;*.conf|All Files (*.*)" +
"|*.*\x02Import tunnel(s) from file\x02Configuration ZIP Files (*.zip)|*." +
- "zip\x02Export tunnels to zip\x02%[1]s (unsigned build, no updates)\x02Er" +
- "ror Exiting WireGuard\x02Unable to exit service due to: %[1]v. You may w" +
- "ant to stop WireGuard from the service manager.\x02An update to WireGuar" +
- "d is available. It is highly advisable to update without delay.\x02Statu" +
- "s: Waiting for user\x02Update Now\x02Status: Waiting for updater service" +
- "\x02Error: %[1]v. Please try again.\x02Status: Complete!\x02pre-up\x02po" +
- "st-up\x02pre-down\x02post-down\x02&Tunnels"
+ "zip\x02Export tunnels to zip\x02%[1]s (unsigned build, no updates)\x02Un" +
+ "able to exit service due to: %[1]v. You may want to stop WireGuard from " +
+ "the service manager.\x02Status: Waiting for user\x02Status: Waiting for " +
+ "updater service\x04\x00\x01 \x07\x02Error:\x02Interface closed, ignored " +
+ "requested state %[1]s\x02Interface state was %[1]s, requested %[2]s, now" +
+ " %[3]s\x02Unable to update bind: %[1]v\x02Bind close failed: %[1]v\x02Tr" +
+ "ouble determining MTU, assuming default: %[1]v\x02Device closing\x02Devi" +
+ "ce closed\x02UDP bind has been updated\x02%[1]v - ConsumeMessageInitiati" +
+ "on: handshake replay @ %[2]v\x02%[1]v - ConsumeMessageInitiation: handsh" +
+ "ake flood\x02%[1]v - Starting\x02%[1]v - Stopping\x02Routine: receive in" +
+ "coming %[1]s - stopped\x02Routine: receive incoming %[1]s - started\x02F" +
+ "ailed to receive %[1]s packet: %[2]v\x02Received message with unknown ty" +
+ "pe\x02Routine: decryption worker %[1]d - started\x02Routine: handshake w" +
+ "orker %[1]d - stopped\x02Routine: handshake worker %[1]d - started\x02Fa" +
+ "iled to decode cookie reply\x02Receiving cookie response from %[1]s\x02C" +
+ "ould not decrypt invalid cookie response\x02Received packet with invalid" +
+ " mac1\x02Invalid packet ended up in the handshake queue\x02Failed to dec" +
+ "ode initiation message\x02Received invalid initiation message from %[1]s" +
+ "\x02%[1]v - Received handshake initiation\x02Failed to decode response m" +
+ "essage\x02Received invalid response message from %[1]s\x02%[1]v - Receiv" +
+ "ed handshake response\x02%[1]v - Failed to derive keypair: %[2]v\x02%[1]" +
+ "v - Routine: sequential receiver - stopped\x02%[1]v - Routine: sequentia" +
+ "l receiver - started\x02%[1]v - Receiving keepalive packet\x02IPv4 packe" +
+ "t with disallowed source address from %[1]v\x02IPv6 packet with disallow" +
+ "ed source address from %[1]v\x02Packet with invalid IP version from %[1]" +
+ "v\x02Failed to write packet to TUN device: %[1]v\x02Unable to flush pack" +
+ "ets: %[1]v\x02%[1]v - Sending keepalive packet\x02%[1]v - Sending handsh" +
+ "ake initiation\x02%[1]v - Failed to create initiation message: %[2]v\x02" +
+ "%[1]v - Failed to send handshake initiation: %[2]v\x02%[1]v - Sending ha" +
+ "ndshake response\x02%[1]v - Failed to create response message: %[2]v\x02" +
+ "%[1]v - Failed to send handshake response: %[2]v\x02Sending cookie respo" +
+ "nse for denied handshake message for %[1]v\x02Failed to create cookie re" +
+ "ply: %[1]v\x02Routine: TUN reader - stopped\x02Routine: TUN reader - sta" +
+ "rted\x02Failed to read packet from TUN device: %[1]v\x02Received packet " +
+ "with unknown IP version\x02Routine: encryption worker %[1]d - started" +
+ "\x02%[1]v - Routine: sequential sender - started\x02%[1]v - Failed to se" +
+ "nd data packet: %[2]v\x02%[1]s - Handshake did not complete after %[2]d " +
+ "attempts, giving up\x02%[1]s - Handshake did not complete after %[2]d se" +
+ "conds, retrying (try %[3]d)\x02%[1]s - Retrying handshake because we sto" +
+ "pped hearing back after %[2]d seconds\x02%[1]s - Removing all keys, sinc" +
+ "e we haven't received a new one in %[2]d seconds\x02Routine: event worke" +
+ "r - started\x02Failed to load updated MTU of device: %[1]v\x02MTU not up" +
+ "dated to negative value: %[1]v\x02MTU updated: %[1]v%[2]s\x02Interface u" +
+ "p requested\x02Interface down requested\x02Routine: event worker - stopp" +
+ "ed\x02listen_port=%[1]d\x02fwmark=%[1]d\x02protocol_version=1\x02endpoin" +
+ "t=%[1]s\x02last_handshake_time_sec=%[1]d\x02last_handshake_time_nsec=%[1" +
+ "]d\x02tx_bytes=%[1]d\x02rx_bytes=%[1]d\x02persistent_keepalive_interval=" +
+ "%[1]d\x02allowed_ip=%[1]s/%[2]d\x02%[1]v\x02UAPI: Updating private key" +
+ "\x02UAPI: Updating listen port\x02UAPI: Updating fwmark\x02UAPI: Removin" +
+ "g all peers\x02%[1]v - UAPI: Created\x02%[1]v - UAPI: Removing\x02%[1]v " +
+ "- UAPI: Updating preshared key\x02%[1]v - UAPI: Updating endpoint\x02%[1" +
+ "]v - UAPI: Updating persistent keepalive interval\x02%[1]v - UAPI: Remov" +
+ "ing all allowedips\x02%[1]v - UAPI: Adding allowedip\x02invalid UAPI ope" +
+ "ration: %[1]v\x02App version: %[1]s\x0aGo backend version: %[2]s\x0aGo v" +
+ "ersion: %[3]s-%[4]s\x0aOperating system: %[5]s\x0aArchitecture: %[6]s" +
+ "\x02&Test experimental kernel driver\x02Enable experimental kernel drive" +
+ "r?\x02The WireGuard project is currently testing a high performance kern" +
+ "el driver called WireGuardNT. It will eventually be enabled by default, " +
+ "but for now the project needs testers to try it out. Whether you encount" +
+ "er problems or you find that it works well, please do email team@wiregua" +
+ "rd.com about your experience.\x0a\x0aWould you like to enable the experi" +
+ "mental kernel driver?\x02Table:\x02off\x02When a configuration has exact" +
+ "ly one peer, and that peer has an allowed IPs containing at least one of" +
+ " 0.0.0.0/0 or ::/0, and the interface does not have table off, then the " +
+ "tunnel service engages a firewall ruleset to block all traffic that is n" +
+ "either to nor from the tunnel interface or is to the wrong DNS server, w" +
+ "ith special exceptions for DHCP and NDP.\x02Please ask the system admini" +
+ "strator to update.\x02Status: Waiting for administrator"
-var es_ESIndex = []uint32{ // 181 elements
+var es_ESIndex = []uint32{ // 278 elements
// Entry 0 - 1F
0x00000000, 0x00000006, 0x00000044, 0x00000058,
- 0x00000058, 0x00000058, 0x00000058, 0x00000058,
- 0x00000058, 0x00000058, 0x00000058, 0x00000058,
- 0x00000058, 0x00000058, 0x00000058, 0x00000058,
- 0x00000058, 0x00000058, 0x00000058, 0x00000058,
- 0x00000058, 0x00000058, 0x00000058, 0x00000058,
- 0x00000058, 0x00000058, 0x00000058, 0x00000058,
- 0x00000058, 0x00000058, 0x00000058, 0x00000058,
+ 0x00000077, 0x00000077, 0x00000077, 0x00000077,
+ 0x00000077, 0x00000077, 0x0000007d, 0x0000007d,
+ 0x0000009d, 0x000000bc, 0x000000dc, 0x00000100,
+ 0x00000126, 0x00000131, 0x00000139, 0x00000145,
+ 0x00000151, 0x0000015d, 0x00000169, 0x00000169,
+ 0x00000181, 0x000001a7, 0x000001c3, 0x000001df,
+ 0x000001ed, 0x000001ff, 0x000001ff, 0x00000217,
// Entry 20 - 3F
- 0x00000058, 0x00000058, 0x00000058, 0x00000058,
- 0x00000058, 0x00000058, 0x00000058, 0x00000058,
- 0x00000058, 0x00000058, 0x00000058, 0x00000058,
- 0x00000058, 0x00000058, 0x00000058, 0x00000058,
- 0x00000058, 0x00000058, 0x00000058, 0x00000058,
- 0x00000058, 0x00000058, 0x00000058, 0x00000058,
- 0x00000058, 0x00000058, 0x00000058, 0x00000058,
- 0x00000058, 0x00000058, 0x00000058, 0x00000058,
+ 0x00000217, 0x00000217, 0x00000217, 0x00000217,
+ 0x00000217, 0x00000217, 0x00000217, 0x00000217,
+ 0x0000022b, 0x00000248, 0x0000024f, 0x0000025b,
+ 0x00000263, 0x0000026f, 0x00000278, 0x00000288,
+ 0x0000029b, 0x000002a0, 0x000002ad, 0x000002bd,
+ 0x000002cf, 0x000002df, 0x000002df, 0x000002df,
+ 0x000002ef, 0x000002f8, 0x00000305, 0x00000318,
+ 0x00000321, 0x00000329, 0x0000033b, 0x00000352,
// Entry 40 - 5F
- 0x00000058, 0x00000058, 0x00000058, 0x00000058,
- 0x00000058, 0x00000058, 0x00000058, 0x00000058,
- 0x00000058, 0x00000058, 0x00000058, 0x00000058,
- 0x00000058, 0x00000058, 0x00000058, 0x00000058,
- 0x00000058, 0x00000058, 0x00000058, 0x00000058,
- 0x00000058, 0x00000058, 0x00000058, 0x00000058,
- 0x00000058, 0x00000058, 0x00000058, 0x00000058,
- 0x00000058, 0x00000058, 0x00000058, 0x00000058,
+ 0x00000359, 0x0000036e, 0x0000038b, 0x000003a3,
+ 0x000003b6, 0x000003f5, 0x000003f5, 0x000003f5,
+ 0x000003f5, 0x00000400, 0x00000423, 0x00000435,
+ 0x00000435, 0x00000435, 0x00000435, 0x00000435,
+ 0x00000435, 0x00000435, 0x00000435, 0x00000435,
+ 0x00000435, 0x00000435, 0x00000435, 0x00000435,
+ 0x00000435, 0x00000441, 0x00000441, 0x00000441,
+ 0x00000441, 0x00000441, 0x00000441, 0x0000044a,
// Entry 60 - 7F
- 0x00000058, 0x00000058, 0x00000058, 0x00000058,
- 0x00000058, 0x00000058, 0x00000058, 0x00000058,
- 0x00000058, 0x00000058, 0x00000058, 0x00000058,
- 0x00000058, 0x00000058, 0x00000058, 0x00000058,
- 0x00000058, 0x00000058, 0x00000058, 0x00000058,
- 0x00000058, 0x00000058, 0x00000058, 0x00000058,
- 0x00000058, 0x00000058, 0x00000058, 0x00000058,
- 0x00000058, 0x00000058, 0x00000058, 0x00000058,
+ 0x0000044a, 0x0000044a, 0x00000465, 0x00000483,
+ 0x00000493, 0x00000499, 0x000004af, 0x000004bd,
+ 0x000004c6, 0x000004d6, 0x000004e4, 0x000004e4,
+ 0x000004ed, 0x000004f6, 0x00000507, 0x00000519,
+ 0x00000530, 0x00000560, 0x00000560, 0x00000560,
+ 0x00000560, 0x00000560, 0x00000560, 0x00000560,
+ 0x00000567, 0x00000571, 0x000005ae, 0x000005ae,
+ 0x000005ae, 0x000005c5, 0x000005d9, 0x000005ee,
// Entry 80 - 9F
- 0x00000058, 0x00000058, 0x00000058, 0x00000058,
- 0x00000058, 0x00000058, 0x00000058, 0x00000058,
- 0x00000058, 0x00000058, 0x00000058, 0x00000058,
- 0x00000058, 0x00000058, 0x00000058, 0x00000058,
- 0x00000058, 0x00000058, 0x00000058, 0x00000058,
- 0x00000058, 0x00000058, 0x00000058, 0x00000058,
- 0x00000058, 0x00000058, 0x00000058, 0x00000058,
- 0x00000058, 0x00000058, 0x00000058, 0x00000058,
+ 0x000005ee, 0x000005ee, 0x000005f5, 0x000005ff,
+ 0x00000612, 0x00000612, 0x00000629, 0x00000629,
+ 0x00000649, 0x0000065a, 0x00000668, 0x0000067b,
+ 0x0000069e, 0x000006c5, 0x00000725, 0x0000072e,
+ 0x00000736, 0x00000750, 0x0000075f, 0x0000077f,
+ 0x000007a1, 0x000007ab, 0x000007ab, 0x000007ab,
+ 0x000007ab, 0x000007ab, 0x000007ab, 0x000007e0,
+ 0x0000080c, 0x00000838, 0x0000084c, 0x00000886,
// Entry A0 - BF
- 0x00000058, 0x00000058, 0x00000058, 0x00000058,
- 0x00000058, 0x00000058, 0x00000058, 0x00000058,
- 0x00000058, 0x00000058, 0x00000058, 0x00000058,
- 0x00000058, 0x00000058, 0x00000058, 0x00000058,
- 0x00000058, 0x00000058, 0x00000058, 0x00000058,
- 0x00000058,
-} // Size: 748 bytes
+ 0x000008d1, 0x000008ec, 0x00000923, 0x00000923,
+ 0x0000093f, 0x0000097b, 0x000009a2, 0x000009bf,
+ 0x000009e9, 0x00000a05, 0x00000a05, 0x00000a05,
+ 0x00000a05, 0x00000a05, 0x00000a05, 0x00000a05,
+ 0x00000a05, 0x00000a22, 0x00000a22, 0x00000a22,
+ 0x00000a22, 0x00000a22, 0x00000a22, 0x00000a22,
+ 0x00000a22, 0x00000a22, 0x00000a22, 0x00000a22,
+ 0x00000a22, 0x00000a22, 0x00000a22, 0x00000a22,
+ // Entry C0 - DF
+ 0x00000a22, 0x00000a22, 0x00000a22, 0x00000a22,
+ 0x00000a22, 0x00000a22, 0x00000a22, 0x00000a22,
+ 0x00000a22, 0x00000a22, 0x00000a22, 0x00000a22,
+ 0x00000a22, 0x00000a22, 0x00000a22, 0x00000a22,
+ 0x00000a22, 0x00000a22, 0x00000a22, 0x00000a22,
+ 0x00000a22, 0x00000a22, 0x00000a22, 0x00000a22,
+ 0x00000a22, 0x00000a22, 0x00000a22, 0x00000a22,
+ 0x00000a22, 0x00000a22, 0x00000a22, 0x00000a22,
+ // Entry E0 - FF
+ 0x00000a22, 0x00000a22, 0x00000a22, 0x00000a22,
+ 0x00000a22, 0x00000a22, 0x00000a22, 0x00000a22,
+ 0x00000a22, 0x00000a22, 0x00000a22, 0x00000a22,
+ 0x00000a22, 0x00000a22, 0x00000a22, 0x00000a22,
+ 0x00000a22, 0x00000a22, 0x00000a22, 0x00000a22,
+ 0x00000a22, 0x00000a22, 0x00000a22, 0x00000a22,
+ 0x00000a22, 0x00000a22, 0x00000a22, 0x00000a22,
+ 0x00000a22, 0x00000a22, 0x00000a22, 0x00000a22,
+ // Entry 100 - 11F
+ 0x00000a22, 0x00000a22, 0x00000a22, 0x00000a22,
+ 0x00000a22, 0x00000a22, 0x00000a22, 0x00000a22,
+ 0x00000a22, 0x00000a22, 0x00000a22, 0x00000a22,
+ 0x00000a22, 0x00000a22, 0x00000a22, 0x00000a22,
+ 0x00000a22, 0x00000a22, 0x00000a22, 0x00000a22,
+ 0x00000a22, 0x00000a22,
+} // Size: 1136 bytes
-const es_ESData string = "" + // Size: 88 bytes
+const es_ESData string = "" + // Size: 2594 bytes
"\x02Error\x02(sin argumento): eleva e instala el servicio de administrad" +
- "or\x02Uso: %[1]s [\x0a%[2]s]"
+ "or\x02Uso: %[1]s [\x0a%[2]s]\x02Opciones de línea de comandos\x02Ahora" +
+ "\x14\x01\x81\x01\x00\x02\x0b\x02%[1]d año\x00\x0c\x02%[1]d años\x14\x01" +
+ "\x81\x01\x00\x02\x0b\x02%[1]d día\x00\x0b\x02%[1]d dias\x14\x01\x81\x01" +
+ "\x00\x02\x0b\x02%[1]d hora\x00\x0c\x02%[1]d horas\x14\x01\x81\x01\x00" +
+ "\x02\x0d\x02%[1]d minuto\x00\x0e\x02%[1]d minutos\x14\x01\x81\x01\x00" +
+ "\x02\x0e\x02%[1]d segundo\x00\x0f\x02%[1]d segundos\x02hace %[1]s\x02%[1" +
+ "]d B\x02%.2[1]f KiB\x02%.2[1]f MiB\x02%.2[1]f GiB\x02%.2[1]f TiB\x02Dire" +
+ "cción IP inválida\x02Longitud de prefijo de red no válida\x02Falta el pu" +
+ "erto del extremo\x02Host de endpoint no válido\x02MTU no valido\x02Puert" +
+ "o no válido\x02Clave no válida: %[1]v\x02Acerca de WireGuard\x02Imagen d" +
+ "el logo de WireGuard\x02Cerrar\x02♥ &Donar!\x02Estado:\x02&Desactivar" +
+ "\x02&Activar\x02Clave pública:\x02Puerto de escucha:\x02MTU:\x02Direccio" +
+ "nes:\x02Servidores DNS:\x02Clave compartida:\x02IPs permitidas:\x02Últim" +
+ "o saludo:\x02Inactivo\x02Desactivando\x02Estado desconocido\x02Registro" +
+ "\x02&Copiar\x02Seleccionar &todo\x02&Guardar en archivo…\x02Tiempo\x02Re" +
+ "gistro de mensajes\x02Exportar archivo de registro\x02&Acerca de WireGua" +
+ "rd…\x02Error en el túnel\x02%[1]s\x0a\x0aPor favor, consulte el registro" +
+ " para más información.\x02Actualizar\x02Error: %[1]v. Inténtalo de nuevo" +
+ ".\x02Estado: Completo!\x02Transferir:\x02activado\x02Error al activar el" +
+ " túnel\x02Error al desactivar el túnel\x02Interfaz: %[1]s\x02Pares\x02Cr" +
+ "ear un túnel nuevo\x02Editar túnel\x02&Nombre:\x02Clave pública:\x02(des" +
+ "conocido)\x02&Guardar\x02Cancelar\x02&Configuración:\x02Nombre no válido" +
+ "\x02Se requiere un nombre.\x02El nombre del túnel ‘%[1]s’ no es válido." +
+ "\x02Activo\x02Activando\x02Archivos de texto (*.txt)|*.txt|Todos los arc" +
+ "hivos (*.*)|*.*\x02WireGuard: Desactivado\x02Estado: Desconocido\x02Dire" +
+ "cciones: Ninguna\x02&Salir\x02&Túneles\x02WireGuard Activado\x02WireGuar" +
+ "d: Desactivado\x02Error en el túnel de WireGuard\x02WireGuard: %[1]s\x02" +
+ "Estado: %[1]s\x02Direcciones: %[1]s\x02Hay una actualización disponible!" +
+ "\x02Actualización de WireGuard disponible\x02Ya está disponible una actu" +
+ "alización de WireGuard. Se recomienda actualizar lo antes posible.\x02Tú" +
+ "neles\x02&Editar\x02Añadir &túnel vacío…\x02Añadir túnel\x02Eliminar tún" +
+ "eles seleccionados\x02Exportar todos los túneles a zip\x02&Alternar\x02N" +
+ "o se pueden enumerar los túneles existentes: %[1]v\x02Ya existe otro tún" +
+ "el con el nombre '%[1]s'\x02Imposible importar la configuración: %[1]v" +
+ "\x02Túneles importados\x14\x01\x81\x01\x00\x02\x17\x02%[1]d túnel import" +
+ "ado\x00\x1a\x02%[1]d túneles importados\x14\x02\x80\x01\x02 \x02Importad" +
+ "o %[1]d de %[2]d túnel\x00#\x02Importados %[1]d de %[2]d túneles\x02No s" +
+ "e pudo crear el túnel\x14\x01\x81\x01\x00\x02\x16\x02Eliminar %[1]d túne" +
+ "l\x00\x18\x02Eliminar %[1]d túneles\x02Eliminar túnel ‘%[1]s’\x02¿Está s" +
+ "eguro de que desea eliminar el túnel ‘%[1]s’?\x02%[1]s No puedes deshace" +
+ "r esta acción.\x02No se pudo eliminar el tunel\x02No se ha podido elimin" +
+ "ar un túnel: %[1]s\x02Imposible eliminar túneles\x02Estado: Esperando al" +
+ " usuario"
-var faIndex = []uint32{ // 181 elements
+var faIndex = []uint32{ // 278 elements
// Entry 0 - 1F
0x00000000, 0x00000007, 0x00000007, 0x00000007,
0x0000002b, 0x0000002b, 0x0000002b, 0x0000002b,
- 0x0000002b, 0x0000002b, 0x0000002b, 0x0000003b,
- 0x0000003b, 0x0000005e, 0x00000081, 0x000000a8,
- 0x000000d3, 0x000000fe, 0x0000010b, 0x0000011b,
+ 0x0000002b, 0x0000002b, 0x0000003b, 0x0000003b,
+ 0x0000005e, 0x00000081, 0x000000a8, 0x000000d3,
+ 0x000000fe, 0x0000010b, 0x0000011b, 0x0000011b,
0x0000011b, 0x0000011b, 0x0000011b, 0x0000011b,
- 0x0000011b, 0x00000148, 0x00000148, 0x00000148,
- 0x00000148, 0x00000148, 0x00000162, 0x0000017a,
+ 0x00000148, 0x00000148, 0x00000148, 0x00000148,
+ 0x00000162, 0x0000017a, 0x0000017a, 0x0000017a,
// Entry 20 - 3F
- 0x0000017a, 0x0000017a, 0x0000017a, 0x0000017a,
- 0x0000017a, 0x0000017a, 0x0000017a, 0x0000017a,
- 0x000001b0, 0x000001b0, 0x000001b0, 0x000001b0,
- 0x000001c4, 0x00000214, 0x0000023e, 0x0000023e,
- 0x0000023e, 0x0000023e, 0x00000242, 0x00000246,
- 0x0000025d, 0x0000025d, 0x0000025d, 0x00000266,
- 0x0000027d, 0x00000289, 0x000002a4, 0x000002b9,
- 0x000002ce, 0x000002e1, 0x000002e6, 0x000002f9,
+ 0x0000017a, 0x0000017a, 0x0000017a, 0x0000018e,
+ 0x000001de, 0x00000208, 0x0000020c, 0x00000210,
+ 0x00000227, 0x00000227, 0x00000230, 0x00000247,
+ 0x00000253, 0x0000026e, 0x00000283, 0x00000298,
+ 0x000002ab, 0x000002b0, 0x000002c3, 0x000002d7,
+ 0x000002ff, 0x00000312, 0x00000327, 0x00000352,
+ 0x00000352, 0x00000361, 0x00000387, 0x000003a3,
+ 0x000003b9, 0x000003c7, 0x000003c7, 0x000003e8,
// Entry 40 - 5F
- 0x0000030d, 0x0000030d, 0x00000335, 0x00000348,
- 0x0000035d, 0x00000388, 0x00000388, 0x00000396,
- 0x00000396, 0x000003a6, 0x000003a6, 0x000003a6,
- 0x000003a6, 0x000003a6, 0x000003b6, 0x000003bf,
- 0x000003dc, 0x000003f2, 0x000003fb, 0x00000411,
- 0x00000424, 0x00000424, 0x00000424, 0x00000430,
- 0x00000437, 0x0000044a, 0x00000460, 0x00000481,
- 0x00000481, 0x000004c7, 0x000004f4, 0x000004f4,
+ 0x000003f1, 0x00000412, 0x0000044e, 0x00000469,
+ 0x0000047d, 0x0000047d, 0x0000047d, 0x000004b3,
+ 0x000004b3, 0x000004dc, 0x00000514, 0x0000052f,
+ 0x0000052f, 0x0000052f, 0x0000052f, 0x0000052f,
+ 0x0000052f, 0x00000565, 0x00000565, 0x00000565,
+ 0x00000565, 0x00000565, 0x00000565, 0x00000565,
+ 0x00000565, 0x00000573, 0x00000573, 0x00000573,
+ 0x00000573, 0x00000573, 0x00000573, 0x00000583,
// Entry 60 - 7F
- 0x000004f4, 0x000004f4, 0x000004f4, 0x000004fd,
- 0x0000051d, 0x0000052c, 0x00000552, 0x0000056e,
- 0x00000584, 0x00000592, 0x00000592, 0x000005b3,
- 0x000005bc, 0x000005dd, 0x000005dd, 0x00000619,
- 0x00000634, 0x00000648, 0x00000648, 0x00000648,
- 0x00000648, 0x00000648, 0x00000648, 0x00000665,
- 0x0000067f, 0x000006a0, 0x000006a0, 0x000006a0,
- 0x000006ba, 0x000006dc, 0x000006fa, 0x000006fa,
+ 0x00000583, 0x00000583, 0x00000583, 0x00000583,
+ 0x00000593, 0x0000059c, 0x000005b9, 0x000005cf,
+ 0x000005d8, 0x000005ee, 0x00000601, 0x00000601,
+ 0x0000060d, 0x00000614, 0x00000627, 0x0000063d,
+ 0x0000065e, 0x0000065e, 0x000006a4, 0x000006d1,
+ 0x000006d1, 0x000006d1, 0x000006d1, 0x000006d1,
+ 0x000006da, 0x000006fa, 0x000006fa, 0x000006fa,
+ 0x000006fa, 0x000006fa, 0x00000717, 0x00000731,
// Entry 80 - 9F
- 0x00000716, 0x00000716, 0x00000728, 0x00000728,
- 0x0000075d, 0x00000796, 0x00000796, 0x000007a6,
- 0x000007b4, 0x000007e2, 0x000007f8, 0x0000081d,
- 0x00000852, 0x00000852, 0x0000088b, 0x0000088b,
- 0x0000088b, 0x0000088b, 0x0000088b, 0x0000088b,
- 0x0000088b, 0x0000088b, 0x000008ad, 0x000008f0,
- 0x00000948, 0x00000975, 0x000009aa, 0x000009aa,
- 0x000009c6, 0x000009c6, 0x000009c6, 0x000009f8,
+ 0x00000752, 0x00000752, 0x00000752, 0x00000752,
+ 0x0000076c, 0x0000078e, 0x000007ac, 0x000007ac,
+ 0x000007c8, 0x000007c8, 0x000007da, 0x000007da,
+ 0x0000080f, 0x00000848, 0x00000848, 0x00000858,
+ 0x00000866, 0x00000894, 0x000008aa, 0x000008cf,
+ 0x00000904, 0x00000904, 0x0000093d, 0x0000093d,
+ 0x0000093d, 0x0000093d, 0x0000093d, 0x0000093d,
+ 0x0000093d, 0x0000093d, 0x0000095f, 0x000009a2,
// Entry A0 - BF
- 0x000009f8, 0x00000a2d, 0x00000a2d, 0x00000a2d,
- 0x00000a60, 0x00000a9c, 0x00000aca, 0x00000aca,
- 0x00000b00, 0x00000b00, 0x00000b00, 0x00000b31,
- 0x00000b5a, 0x00000ba3, 0x00000bdb, 0x00000bf6,
+ 0x000009fa, 0x00000a27, 0x00000a5c, 0x00000a5c,
+ 0x00000a78, 0x00000a78, 0x00000a78, 0x00000aaa,
+ 0x00000aaa, 0x00000adf, 0x00000adf, 0x00000adf,
+ 0x00000b12, 0x00000b4e, 0x00000b7c, 0x00000b7c,
+ 0x00000b7c, 0x00000bad, 0x00000bf6, 0x00000bf6,
+ 0x00000bf6, 0x00000bf6, 0x00000bf6, 0x00000bf6,
+ 0x00000bf6, 0x00000bf6, 0x00000bf6, 0x00000bf6,
+ 0x00000bf6, 0x00000bf6, 0x00000bf6, 0x00000bf6,
+ // Entry C0 - DF
+ 0x00000bf6, 0x00000bf6, 0x00000bf6, 0x00000bf6,
+ 0x00000bf6, 0x00000bf6, 0x00000bf6, 0x00000bf6,
+ 0x00000bf6, 0x00000bf6, 0x00000bf6, 0x00000bf6,
+ 0x00000bf6, 0x00000bf6, 0x00000bf6, 0x00000bf6,
+ 0x00000bf6, 0x00000bf6, 0x00000bf6, 0x00000bf6,
+ 0x00000bf6, 0x00000bf6, 0x00000bf6, 0x00000bf6,
+ 0x00000bf6, 0x00000bf6, 0x00000bf6, 0x00000bf6,
+ 0x00000bf6, 0x00000bf6, 0x00000bf6, 0x00000bf6,
+ // Entry E0 - FF
+ 0x00000bf6, 0x00000bf6, 0x00000bf6, 0x00000bf6,
+ 0x00000bf6, 0x00000bf6, 0x00000bf6, 0x00000bf6,
+ 0x00000bf6, 0x00000bf6, 0x00000bf6, 0x00000bf6,
+ 0x00000bf6, 0x00000bf6, 0x00000bf6, 0x00000bf6,
+ 0x00000bf6, 0x00000bf6, 0x00000bf6, 0x00000bf6,
+ 0x00000bf6, 0x00000bf6, 0x00000bf6, 0x00000bf6,
0x00000bf6, 0x00000bf6, 0x00000bf6, 0x00000bf6,
- 0x00000bf6,
-} // Size: 748 bytes
+ 0x00000bf6, 0x00000bf6, 0x00000bf6, 0x00000bf6,
+ // Entry 100 - 11F
+ 0x00000bf6, 0x00000bf6, 0x00000bf6, 0x00000bf6,
+ 0x00000bf6, 0x00000bf6, 0x00000bf6, 0x00000bf6,
+ 0x00000bf6, 0x00000bf6, 0x00000bf6, 0x00000bf6,
+ 0x00000bf6, 0x00000bf6, 0x00000bf6, 0x00000bf6,
+ 0x00000bf6, 0x00000bf6, 0x00000bf6, 0x00000bf6,
+ 0x00000bf6, 0x00000bf6,
+} // Size: 1136 bytes
const faData string = "" + // Size: 3062 bytes
"\x02خطا\x02گزینه\u200cهای خط فرمان\x02هم اکنون\x14\x01\x81\x01\x00\x02" +
@@ -654,165 +1248,223 @@ const faData string = "" + // Size: 3062 bytes
"\x00\x0f\x02%[1]d ساعت\x14\x01\x81\x01\x00\x02\x11\x02%[1]d دقیقه\x00" +
"\x11\x02%[1]d دقیقه\x14\x01\x81\x01\x00\x02\x11\x02%[1]d ثانیه\x00\x11" +
"\x02%[1]d ثانیه\x02%[1]s پیش\x02%[1]d\u00a0بایت\x02نشانی آی\u200cپی نامع" +
- "تبر است\x02MTU نامعتبر است\x02پورت نامعتبر\x02کلید باید یک مقدار داشته " +
- "باشد\x02[مشخص نشده]\x02همه همتاها باید کلید\u200cهای عمومی داشته باشند" +
- "\x02خطا در دریافت پیکربندی\x02، \x02، \x02درباره WireGuard\x02بستن\x02♥&" +
- "کمک\u200cمالی!\x02وضعیت:\x02&غیرفعال\u200cسازی\x02&فعال\u200cسازی\x02کل" +
- "ید عمومی:\x02پورت شنود:\x02MTU:\x02نشانی\u200cها:\x02سرورهای DNS:\x02کل" +
- "ید از پیش تقسیم شده:\x02IPهای مجاز:\x02نقطه پایان:\x02زنده نگه\u200cداش" +
- "تن پیوسته:\x02انتقال:\x02فعال شده\x02رابط: %[1]s\x02همتا\x02ایجاد تونل " +
- "جدید\x02ویرایش تونل\x02&نام:\x02&کلید عمومی:\x02(ناشناخته)\x02&ذخیره" +
- "\x02لغو\x02&پیکربندی:\x02نام نامعتبر\x02یک نام الزامی است.\x02نمی\u200cت" +
- "وان تونل\u200cهای موجود را فهرست کرد\x02تونل هم\u200cاکنون موجود است" +
- "\x02فعال\x02در حال فعال\u200cسازی\x02غیرفعال\x02در حال غیرفعال\u200cسازی" +
- "\x02وضعیت ناشناخته\x02گزارش وقایع\x02&روگرفت\x02&ذخیره در پرونده…\x02زما" +
- "ن\x02پیام گزارش رویداد\x02برون\u200cبرد گزارش رویداد به پرونده\x02&دربا" +
- "ره WireGuard…\x02خطالی تونل\x02وضعیت: ناشناخته\x02نشانی\u200cها: هیچ" +
- "\x02&مدیریت تونل\u200cها…\x02WireGuard فعال\u200cشد\x02تونل %[1]s فعال" +
- "\u200cشده.\x02WireGuard غیرفعال شد\x02خطای تونل WireGuard\x02وضعیت: %[1]" +
- "s\x02یک به\u200cروزرسانی در دسترس است!\x02به\u200cروزرسانی WireGuard در " +
- "دسترس است\x02تونل\u200cها\x02&ویرایش\x02افزودن &خالی\u200cکردن تونل…" +
- "\x02افزودن تونل\x02حذف تونل(ها) انتخابی\x02برون\u200cبری همه تونل\u200cه" +
- "ا به زیپ\x02برون\u200cبری همه تونل\u200cها به &زیپ…\x02تونل\u200cهای وا" +
- "رد شده\x14\x01\x81\x01\x00\x02\x1d\x02%[1]d تونل وارد شد\x00\x1d\x02%[1" +
- "]d تونل وارد شد\x14\x02\x80\x01\x02(\x02%[1]d از %[2]d تونل وارد شد\x00(" +
- "\x02%[1]d از %[2]d تونل وارد شد\x02نمی\u200cتوان تونل ایجاد کرد\x14\x01" +
- "\x81\x01\x00\x02\x16\x02حذف %[1]d تونل\x00\x16\x02حذف %[1]d تونل\x02حذف " +
- "تونل ‘%[1]s’\x02حذف تونل\u200c امکان\u200cپذیر نیست\x02نمی\u200cتوان تو" +
- "نل\u200cها را حذف کرد\x02وارد کردن تونل(ها) از پرونده\x02پرونده\u200cها" +
- "ی پیکربندی زیپ (*.zip)|*.zip\x02برون\u200cبری تونل\u200cها به زیپ\x02خط" +
- "ا در هنگام خارج شدن از WireGuard\x02وضعیت: درانتظار برای کاربر\x02اکنون" +
- " به\u200cروز رسانی کن\x02وضعیت: درانتظار برای سرویس به\u200cروزرسانی\x02" +
- "خطا: %[1]v. لطفا دوباره تلاش کنید.\x02وضعیت: کامل شد!"
+ "تبر است\x02MTU نامعتبر است\x02پورت نامعتبر\x02[مشخص نشده]\x02همه همتاها" +
+ " باید کلید\u200cهای عمومی داشته باشند\x02خطا در دریافت پیکربندی\x02، " +
+ "\x02، \x02درباره WireGuard\x02بستن\x02♥&کمک\u200cمالی!\x02وضعیت:\x02&غیر" +
+ "فعال\u200cسازی\x02&فعال\u200cسازی\x02کلید عمومی:\x02پورت شنود:\x02MTU:" +
+ "\x02نشانی\u200cها:\x02سرورهای DNS:\x02کلید از پیش تقسیم شده:\x02IPهای مج" +
+ "از:\x02نقطه پایان:\x02زنده نگه\u200cداشتن پیوسته:\x02غیرفعال\x02در حال " +
+ "غیرفعال\u200cسازی\x02وضعیت ناشناخته\x02گزارش وقایع\x02&روگرفت\x02&ذخیره" +
+ " در پرونده…\x02زمان\x02پیام گزارش رویداد\x02برون\u200cبرد گزارش رویداد ب" +
+ "ه پرونده\x02&درباره WireGuard…\x02خطالی تونل\x02خطا در هنگام خارج شدن ا" +
+ "ز WireGuard\x02اکنون به\u200cروز رسانی کن\x02خطا: %[1]v. لطفا دوباره تل" +
+ "اش کنید.\x02وضعیت: کامل شد!\x02کلید باید یک مقدار داشته باشد\x02انتقال:" +
+ "\x02فعال شده\x02رابط: %[1]s\x02همتا\x02ایجاد تونل جدید\x02ویرایش تونل" +
+ "\x02&نام:\x02&کلید عمومی:\x02(ناشناخته)\x02&ذخیره\x02لغو\x02&پیکربندی:" +
+ "\x02نام نامعتبر\x02یک نام الزامی است.\x02نمی\u200cتوان تونل\u200cهای موج" +
+ "ود را فهرست کرد\x02تونل هم\u200cاکنون موجود است\x02فعال\x02در حال فعال" +
+ "\u200cسازی\x02وضعیت: ناشناخته\x02نشانی\u200cها: هیچ\x02&مدیریت تونل" +
+ "\u200cها…\x02WireGuard فعال\u200cشد\x02تونل %[1]s فعال\u200cشده.\x02Wire" +
+ "Guard غیرفعال شد\x02خطای تونل WireGuard\x02وضعیت: %[1]s\x02یک به\u200cرو" +
+ "زرسانی در دسترس است!\x02به\u200cروزرسانی WireGuard در دسترس است\x02تونل" +
+ "\u200cها\x02&ویرایش\x02افزودن &خالی\u200cکردن تونل…\x02افزودن تونل\x02حذ" +
+ "ف تونل(ها) انتخابی\x02برون\u200cبری همه تونل\u200cها به زیپ\x02برون" +
+ "\u200cبری همه تونل\u200cها به &زیپ…\x02تونل\u200cهای وارد شده\x14\x01" +
+ "\x81\x01\x00\x02\x1d\x02%[1]d تونل وارد شد\x00\x1d\x02%[1]d تونل وارد شد" +
+ "\x14\x02\x80\x01\x02(\x02%[1]d از %[2]d تونل وارد شد\x00(\x02%[1]d از %[" +
+ "2]d تونل وارد شد\x02نمی\u200cتوان تونل ایجاد کرد\x14\x01\x81\x01\x00\x02" +
+ "\x16\x02حذف %[1]d تونل\x00\x16\x02حذف %[1]d تونل\x02حذف تونل ‘%[1]s’\x02" +
+ "حذف تونل\u200c امکان\u200cپذیر نیست\x02نمی\u200cتوان تونل\u200cها را حذ" +
+ "ف کرد\x02وارد کردن تونل(ها) از پرونده\x02پرونده\u200cهای پیکربندی زیپ (" +
+ "*.zip)|*.zip\x02برون\u200cبری تونل\u200cها به زیپ\x02وضعیت: درانتظار برا" +
+ "ی کاربر\x02وضعیت: درانتظار برای سرویس به\u200cروزرسانی"
-var fiIndex = []uint32{ // 181 elements
+var fiIndex = []uint32{ // 278 elements
// Entry 0 - 1F
0x00000000, 0x00000006, 0x00000006, 0x00000006,
0x00000006, 0x00000006, 0x00000006, 0x00000006,
- 0x00000006, 0x00000006, 0x00000006, 0x0000000a,
- 0x0000002a, 0x0000002a, 0x0000002a, 0x0000002a,
- 0x0000002a, 0x0000002a, 0x0000002a, 0x0000002a,
- 0x0000002a, 0x0000002a, 0x0000002a, 0x0000002a,
- 0x0000002a, 0x0000002a, 0x0000002a, 0x0000002a,
+ 0x00000006, 0x00000006, 0x0000000a, 0x0000002a,
0x0000002a, 0x0000002a, 0x0000002a, 0x0000002a,
+ 0x0000002a, 0x00000037, 0x0000003f, 0x0000003f,
+ 0x0000003f, 0x0000003f, 0x0000003f, 0x0000003f,
+ 0x0000003f, 0x0000003f, 0x0000003f, 0x0000003f,
+ 0x00000050, 0x00000064, 0x00000083, 0x0000009d,
// Entry 20 - 3F
- 0x00000049, 0x00000049, 0x00000049, 0x00000049,
- 0x00000049, 0x00000049, 0x00000049, 0x00000049,
- 0x00000049, 0x00000049, 0x00000049, 0x00000049,
- 0x00000049, 0x00000049, 0x00000049, 0x00000049,
- 0x00000049, 0x00000049, 0x0000004c, 0x0000004c,
- 0x00000061, 0x00000076, 0x00000076, 0x0000007c,
- 0x0000008b, 0x00000091, 0x00000091, 0x00000091,
- 0x00000091, 0x00000091, 0x00000096, 0x000000a1,
+ 0x0000009d, 0x0000009d, 0x0000009d, 0x0000009d,
+ 0x0000009d, 0x0000009d, 0x000000a0, 0x000000a3,
+ 0x000000b8, 0x000000cd, 0x000000d3, 0x000000e2,
+ 0x000000e8, 0x000000e8, 0x000000e8, 0x000000f8,
+ 0x0000010a, 0x0000010f, 0x0000011a, 0x0000012a,
+ 0x00000138, 0x0000014f, 0x0000015d, 0x00000170,
+ 0x00000184, 0x00000184, 0x00000184, 0x00000184,
+ 0x00000189, 0x00000191, 0x00000191, 0x00000191,
// Entry 40 - 5F
- 0x000000b1, 0x000000c0, 0x000000ce, 0x000000e5,
- 0x000000f3, 0x00000106, 0x0000011a, 0x00000123,
- 0x00000123, 0x00000123, 0x00000123, 0x00000123,
- 0x00000123, 0x00000123, 0x00000123, 0x0000012c,
- 0x0000013d, 0x0000014e, 0x00000155, 0x00000166,
- 0x00000173, 0x000001a3, 0x000001a3, 0x000001ad,
- 0x000001ad, 0x000001bd, 0x000001cf, 0x000001e3,
- 0x000001e3, 0x000001e3, 0x000001fa, 0x000001fa,
+ 0x00000191, 0x00000191, 0x00000191, 0x00000191,
+ 0x00000191, 0x00000191, 0x00000191, 0x00000191,
+ 0x00000191, 0x0000019f, 0x0000019f, 0x000001ad,
+ 0x000001ad, 0x000001ad, 0x000001ad, 0x000001ad,
+ 0x000001ad, 0x000001ad, 0x000001ad, 0x000001ad,
+ 0x000001ad, 0x000001ad, 0x000001ad, 0x000001ad,
+ 0x000001bc, 0x000001c5, 0x000001c5, 0x000001c5,
+ 0x000001c5, 0x000001c5, 0x000001c5, 0x000001d1,
// Entry 60 - 7F
- 0x000001fa, 0x000001fa, 0x000001fa, 0x000001fa,
- 0x000001fa, 0x000001fa, 0x000001fa, 0x000001fa,
- 0x000001ff, 0x00000207, 0x00000207, 0x00000207,
- 0x00000207, 0x00000207, 0x00000207, 0x00000207,
- 0x00000207, 0x00000207, 0x00000207, 0x00000207,
- 0x00000207, 0x00000207, 0x00000207, 0x00000207,
- 0x00000207, 0x00000207, 0x00000207, 0x00000207,
- 0x00000207, 0x00000207, 0x00000207, 0x00000207,
+ 0x000001f7, 0x000001f7, 0x000001f7, 0x000001f7,
+ 0x0000020b, 0x00000214, 0x00000225, 0x00000236,
+ 0x0000023d, 0x0000024e, 0x0000025b, 0x0000028b,
+ 0x00000295, 0x00000295, 0x000002a5, 0x000002b7,
+ 0x000002cb, 0x000002cb, 0x000002cb, 0x000002e2,
+ 0x000002e2, 0x000002e2, 0x000002e2, 0x000002e2,
+ 0x000002e2, 0x000002e2, 0x000002e2, 0x000002e2,
+ 0x000002e2, 0x000002e2, 0x000002e2, 0x000002e2,
// Entry 80 - 9F
- 0x00000207, 0x00000207, 0x00000207, 0x00000207,
- 0x00000220, 0x0000023f, 0x0000029f, 0x000002a7,
- 0x000002b0, 0x000002b0, 0x000002b0, 0x000002b0,
- 0x000002b0, 0x000002b0, 0x000002b0, 0x000002b0,
- 0x000002b0, 0x000002b0, 0x000002b0, 0x000002b0,
- 0x000002b0, 0x000002b0, 0x000002c0, 0x000002f2,
- 0x000002f2, 0x000002f2, 0x000002f2, 0x000002f2,
- 0x000002f2, 0x000002f2, 0x000002f2, 0x000002f2,
+ 0x000002e2, 0x00000301, 0x00000301, 0x00000301,
+ 0x00000301, 0x00000301, 0x00000301, 0x00000301,
+ 0x00000301, 0x00000301, 0x00000301, 0x00000301,
+ 0x0000031a, 0x00000339, 0x00000399, 0x000003a1,
+ 0x000003aa, 0x000003c5, 0x000003d5, 0x000003d5,
+ 0x000003d5, 0x000003d5, 0x000003d5, 0x000003d5,
+ 0x000003d5, 0x000003d5, 0x000003d5, 0x000003d5,
+ 0x000003d5, 0x000003d5, 0x000003e5, 0x00000417,
// Entry A0 - BF
- 0x000002f2, 0x0000030c, 0x0000030c, 0x0000030c,
- 0x00000327, 0x00000327, 0x00000327, 0x00000327,
- 0x00000327, 0x00000327, 0x00000327, 0x00000345,
- 0x00000353, 0x00000353, 0x00000353, 0x00000361,
- 0x00000361, 0x00000361, 0x00000361, 0x00000361,
- 0x00000361,
-} // Size: 748 bytes
+ 0x00000417, 0x00000417, 0x00000417, 0x00000417,
+ 0x00000417, 0x00000417, 0x00000417, 0x00000417,
+ 0x00000417, 0x00000431, 0x00000431, 0x00000431,
+ 0x0000044c, 0x0000044c, 0x0000044c, 0x0000044c,
+ 0x0000044c, 0x0000046a, 0x0000046a, 0x0000046a,
+ 0x0000046a, 0x0000046a, 0x0000046a, 0x0000046a,
+ 0x0000046a, 0x0000046a, 0x0000046a, 0x0000046a,
+ 0x0000046a, 0x0000046a, 0x0000046a, 0x0000046a,
+ // Entry C0 - DF
+ 0x0000046a, 0x0000046a, 0x0000046a, 0x0000046a,
+ 0x0000046a, 0x0000046a, 0x0000046a, 0x0000046a,
+ 0x0000046a, 0x0000046a, 0x0000046a, 0x0000046a,
+ 0x0000046a, 0x0000046a, 0x0000046a, 0x0000046a,
+ 0x0000046a, 0x0000046a, 0x0000046a, 0x0000046a,
+ 0x0000046a, 0x0000046a, 0x0000046a, 0x0000046a,
+ 0x0000046a, 0x0000046a, 0x0000046a, 0x0000046a,
+ 0x0000046a, 0x0000046a, 0x0000046a, 0x0000046a,
+ // Entry E0 - FF
+ 0x0000046a, 0x0000046a, 0x0000046a, 0x0000046a,
+ 0x0000046a, 0x0000046a, 0x0000046a, 0x0000046a,
+ 0x0000046a, 0x0000046a, 0x0000046a, 0x0000046a,
+ 0x0000046a, 0x0000046a, 0x0000046a, 0x0000046a,
+ 0x0000046a, 0x0000046a, 0x0000046a, 0x0000046a,
+ 0x0000046a, 0x0000046a, 0x0000046a, 0x0000046a,
+ 0x0000046a, 0x0000046a, 0x0000046a, 0x0000046a,
+ 0x0000046a, 0x0000046a, 0x0000046a, 0x0000046a,
+ // Entry 100 - 11F
+ 0x0000046a, 0x0000046a, 0x0000046a, 0x0000046a,
+ 0x0000046a, 0x0000046a, 0x0000046a, 0x0000046a,
+ 0x0000046a, 0x0000046a, 0x0000046a, 0x0000046a,
+ 0x0000046a, 0x0000046a, 0x0000046a, 0x0000046a,
+ 0x0000046a, 0x0000046a, 0x0000046a, 0x0000046a,
+ 0x0000046a, 0x0000046a,
+} // Size: 1136 bytes
-const fiData string = "" + // Size: 865 bytes
- "\x02Virhe\x02Nyt\x02Järjestelmän kello jättää!\x02Virheellinen jatkuva k" +
- "eepalive\x02, \x02Tietoa WireGuardista\x02WireGuard logon kuva\x02Sulje" +
- "\x02♥ &Lahjoita!\x02Tila:\x02MTU:\x02Osoitteet:\x02DNS palvelimet:\x02Ko" +
- "mentosarjat:\x02Jaettu avain:\x02Sallitut IP-osoitteet:\x02Päätepiste:" +
- "\x02Jatkuva keepalive:\x02Viimeisin kättely:\x02Siirrot:\x02Osapuoli\x02" +
- "Luo uusi tunneli\x02Muokkaa tunnelia\x02&Nimi:\x02&Julkinen avain:\x02(t" +
- "untematon)\x02&Estä tunneloimaton liikenne (pääkatkaisija)\x02&Tallenna" +
- "\x02&Konfiguraatio:\x02Virheellinen nimi\x02Nimi on pakollinen.\x02Tunne" +
- "li on jo olemassa\x02Loki\x02&Kopioi\x02Päivitys on saatavilla!\x02WireG" +
- "uard päivitys saatavilla\x02WireGuardin päivitys on nyt saatavilla. Sinu" +
- "a kehotetaan päivittämään mahdollisimman pian.\x02Tunneli\x02&Muokkaa" +
- "\x02Tuodut tunnelit\x14\x01\x81\x01\x00\x02\x14\x02Tuotu %[1]d tunneli" +
- "\x00\x15\x02Tuotu %[1]d tunnelia\x02Tunnelia ei voitu poistaa\x02Tuo tun" +
- "neli(t) tiedostosta\x02Tila: Odotetaan käyttäjää\x02Päivitä nyt\x02Tila:" +
- " Valmis!"
+const fiData string = "" + // Size: 1130 bytes
+ "\x02Virhe\x02Nyt\x02Järjestelmän kello jättää!\x02%[1]s sitten\x02%[1]d " +
+ "B\x02Virheellinen MTU\x02Virheellinen portti\x02Virheellinen jatkuva kee" +
+ "palive\x02Virheellinen avain: %[1]v\x02, \x02, \x02Tietoa WireGuardista" +
+ "\x02WireGuard logon kuva\x02Sulje\x02♥ &Lahjoita!\x02Tila:\x02Julkinen a" +
+ "vain:\x02Kuuntele porttia:\x02MTU:\x02Osoitteet:\x02DNS palvelimet:\x02J" +
+ "aettu avain:\x02Sallitut IP-osoitteet:\x02Päätepiste:\x02Jatkuva keepali" +
+ "ve:\x02Viimeisin kättely:\x02Loki\x02&Kopioi\x02Päivitä nyt\x02Tila: Val" +
+ "mis!\x02Komentosarjat:\x02Siirrot:\x02käytössä\x02%[1]s vastaanotettu, %" +
+ "[2]s lähetetty\x02Verkkoyhteys: %[1]s\x02Osapuoli\x02Luo uusi tunneli" +
+ "\x02Muokkaa tunnelia\x02&Nimi:\x02&Julkinen avain:\x02(tuntematon)\x02&E" +
+ "stä tunneloimaton liikenne (pääkatkaisija)\x02&Tallenna\x02&Konfiguraati" +
+ "o:\x02Virheellinen nimi\x02Nimi on pakollinen.\x02Tunneli on jo olemassa" +
+ "\x02Tuo tunnele&ita tiedostosta…\x02Päivitys on saatavilla!\x02WireGuard" +
+ " päivitys saatavilla\x02WireGuardin päivitys on nyt saatavilla. Sinua ke" +
+ "hotetaan päivittämään mahdollisimman pian.\x02Tunneli\x02&Muokkaa\x02Lis" +
+ "ää tyhjä tunn&eli…\x02Lisää tunneli\x02Tuodut tunnelit\x14\x01\x81\x01" +
+ "\x00\x02\x14\x02Tuotu %[1]d tunneli\x00\x15\x02Tuotu %[1]d tunnelia\x02T" +
+ "unnelia ei voitu poistaa\x02Tuo tunneli(t) tiedostosta\x02Tila: Odotetaa" +
+ "n käyttäjää"
-var frIndex = []uint32{ // 181 elements
+var frIndex = []uint32{ // 278 elements
// Entry 0 - 1F
0x00000000, 0x00000007, 0x00000046, 0x00000063,
0x00000083, 0x000000cb, 0x00000112, 0x0000014b,
- 0x000001ad, 0x00000225, 0x00000282, 0x0000028d,
- 0x000002b0, 0x000002cc, 0x000002ec, 0x0000030e,
- 0x00000332, 0x00000358, 0x00000365, 0x0000036e,
- 0x0000037b, 0x00000388, 0x00000395, 0x000003a2,
- 0x000003b0, 0x000003c6, 0x000003ee, 0x00000414,
- 0x0000043d, 0x00000475, 0x00000484, 0x00000494,
+ 0x000001ad, 0x00000225, 0x00000230, 0x00000253,
+ 0x0000026f, 0x0000028f, 0x000002b1, 0x000002d5,
+ 0x000002fb, 0x00000308, 0x00000311, 0x0000031e,
+ 0x0000032b, 0x00000338, 0x00000345, 0x00000353,
+ 0x00000369, 0x00000391, 0x000003b7, 0x000003e0,
+ 0x000003ef, 0x000003ff, 0x00000414, 0x0000042c,
// Entry 20 - 3F
- 0x000004a9, 0x000004c1, 0x000004ee, 0x00000526,
- 0x00000542, 0x0000055b, 0x00000587, 0x000005c2,
- 0x000005dd, 0x00000609, 0x00000630, 0x00000658,
- 0x00000670, 0x000006a4, 0x000006cb, 0x000006f7,
- 0x00000719, 0x00000745, 0x00000748, 0x0000074a,
- 0x00000761, 0x0000077c, 0x00000806, 0x0000080d,
- 0x00000821, 0x00000829, 0x00000836, 0x0000083f,
- 0x0000084f, 0x00000860, 0x00000866, 0x00000871,
+ 0x00000464, 0x00000480, 0x00000499, 0x000004b1,
+ 0x000004e5, 0x0000050c, 0x0000050f, 0x00000511,
+ 0x00000528, 0x00000543, 0x0000054a, 0x0000055e,
+ 0x00000566, 0x00000573, 0x0000057c, 0x0000058c,
+ 0x0000059d, 0x000005a3, 0x000005ae, 0x000005bd,
+ 0x000005d3, 0x000005ed, 0x00000604, 0x00000632,
+ 0x00000659, 0x00000662, 0x0000067a, 0x00000688,
+ 0x00000690, 0x00000698, 0x000006ac, 0x000006cc,
// Entry 40 - 5F
- 0x00000880, 0x0000088a, 0x000008a0, 0x000008ba,
- 0x000008d1, 0x000008ff, 0x00000926, 0x00000932,
- 0x00000950, 0x0000095b, 0x0000097c, 0x000009a8,
- 0x000009c7, 0x000009eb, 0x000009fd, 0x00000a07,
- 0x00000a20, 0x00000a33, 0x00000a3a, 0x00000a4b,
- 0x00000a58, 0x00000a8b, 0x00000c05, 0x00000c12,
- 0x00000c1a, 0x00000c2b, 0x00000c3a, 0x00000c52,
- 0x00000c7c, 0x00000cb1, 0x00000cc7, 0x00000cfb,
+ 0x000006d2, 0x000006e5, 0x00000709, 0x00000721,
+ 0x00000732, 0x0000077c, 0x0000078e, 0x000007ac,
+ 0x00000825, 0x0000083f, 0x00000864, 0x00000875,
+ 0x000008d2, 0x0000090a, 0x00000937, 0x00000963,
+ 0x0000099e, 0x000009b9, 0x000009e5, 0x00000a0c,
+ 0x00000a34, 0x00000a60, 0x00000a82, 0x00000aae,
+ 0x00000ab8, 0x00000ac4, 0x00000ad4, 0x00000ae4,
+ 0x00000af8, 0x00000b0c, 0x00000b2a, 0x00000b35,
// Entry 60 - 7F
- 0x00000d2b, 0x00000d49, 0x00000d88, 0x00000d91,
- 0x00000da5, 0x00000dae, 0x00000dc6, 0x00000dd4,
- 0x00000ddc, 0x00000de4, 0x00000df8, 0x00000e18,
- 0x00000e1e, 0x00000e31, 0x00000e6a, 0x00000e8e,
- 0x00000ea6, 0x00000eb7, 0x00000f01, 0x00000f13,
- 0x00000f35, 0x00000f77, 0x00000f8e, 0x00000f9e,
- 0x00000fb0, 0x00000fc8, 0x00000ffa, 0x00001003,
- 0x00001015, 0x00001033, 0x00001049, 0x0000106b,
+ 0x00000b56, 0x00000b82, 0x00000ba1, 0x00000bc5,
+ 0x00000bd7, 0x00000be1, 0x00000bfa, 0x00000c0d,
+ 0x00000c14, 0x00000c25, 0x00000c32, 0x00000c65,
+ 0x00000c72, 0x00000c7a, 0x00000c8b, 0x00000c9a,
+ 0x00000cb2, 0x00000cdc, 0x00000d11, 0x00000d27,
+ 0x00000d5b, 0x00000d8b, 0x00000da9, 0x00000de8,
+ 0x00000df1, 0x00000e05, 0x00000e3e, 0x00000e60,
+ 0x00000ea2, 0x00000eb9, 0x00000ec9, 0x00000edb,
// Entry 80 - 9F
- 0x00001086, 0x00001098, 0x000010a6, 0x000010b7,
- 0x000010d0, 0x000010f6, 0x0000116b, 0x00001173,
- 0x0000117d, 0x00001198, 0x000011aa, 0x000011d5,
- 0x000011f8, 0x00001202, 0x00001229, 0x0000124e,
- 0x0000127a, 0x000012a1, 0x000012df, 0x00001316,
- 0x00001342, 0x00001371, 0x00001383, 0x000013ba,
- 0x00001403, 0x00001422, 0x0000145a, 0x000014be,
- 0x000014de, 0x00001514, 0x00001543, 0x00001565,
+ 0x00000ef3, 0x00000f25, 0x00000f2e, 0x00000f38,
+ 0x00000f4a, 0x00000f68, 0x00000f7e, 0x00000fa0,
+ 0x00000fbb, 0x00000fcd, 0x00000fdb, 0x00000fec,
+ 0x00001005, 0x0000102b, 0x000010a0, 0x000010a8,
+ 0x000010b2, 0x000010cd, 0x000010df, 0x0000110a,
+ 0x0000112d, 0x00001137, 0x0000115e, 0x00001183,
+ 0x000011af, 0x000011d6, 0x00001214, 0x0000124b,
+ 0x00001277, 0x000012a6, 0x000012b8, 0x000012ef,
// Entry A0 - BF
- 0x0000159a, 0x000015be, 0x0000162a, 0x0000167d,
- 0x000016ab, 0x000016d7, 0x000016f5, 0x00001726,
- 0x00001744, 0x000017bf, 0x00001838, 0x0000185d,
- 0x00001877, 0x000018a6, 0x000018cb, 0x000018dc,
- 0x000018ec, 0x000018fc, 0x00001910, 0x00001924,
- 0x0000192e,
-} // Size: 748 bytes
+ 0x00001338, 0x00001357, 0x0000138f, 0x000013f3,
+ 0x00001413, 0x00001449, 0x00001478, 0x0000149a,
+ 0x000014cf, 0x000014f3, 0x0000155f, 0x000015b2,
+ 0x000015e0, 0x0000160c, 0x0000162a, 0x0000165b,
+ 0x000016d6, 0x000016fb, 0x0000172a, 0x0000172a,
+ 0x0000172a, 0x0000172a, 0x0000172a, 0x0000172a,
+ 0x0000172a, 0x0000172a, 0x0000172a, 0x0000172a,
+ 0x0000172a, 0x0000172a, 0x0000172a, 0x0000172a,
+ // Entry C0 - DF
+ 0x0000172a, 0x0000172a, 0x0000172a, 0x0000172a,
+ 0x0000172a, 0x0000172a, 0x0000172a, 0x0000172a,
+ 0x0000172a, 0x0000172a, 0x0000172a, 0x0000172a,
+ 0x0000172a, 0x0000172a, 0x0000172a, 0x0000172a,
+ 0x0000172a, 0x0000172a, 0x0000172a, 0x0000172a,
+ 0x0000172a, 0x0000172a, 0x0000172a, 0x0000172a,
+ 0x0000172a, 0x0000172a, 0x0000172a, 0x0000172a,
+ 0x0000172a, 0x0000172a, 0x0000172a, 0x0000172a,
+ // Entry E0 - FF
+ 0x0000172a, 0x0000172a, 0x0000172a, 0x0000172a,
+ 0x0000172a, 0x0000172a, 0x0000172a, 0x0000172a,
+ 0x0000172a, 0x0000172a, 0x0000172a, 0x0000172a,
+ 0x0000172a, 0x0000172a, 0x0000172a, 0x0000172a,
+ 0x0000172a, 0x0000172a, 0x0000172a, 0x0000172a,
+ 0x0000172a, 0x0000172a, 0x0000172a, 0x0000172a,
+ 0x0000172a, 0x0000172a, 0x0000172a, 0x0000172a,
+ 0x0000172a, 0x0000172a, 0x0000172a, 0x0000172a,
+ // Entry 100 - 11F
+ 0x0000172a, 0x0000172a, 0x0000172a, 0x0000172a,
+ 0x0000172a, 0x0000172a, 0x0000172a, 0x0000172a,
+ 0x0000172a, 0x0000172a, 0x0000172a, 0x0000172a,
+ 0x0000172a, 0x0000172a, 0x0000172a, 0x0000172a,
+ 0x0000172a, 0x0000172a, 0x0000172a, 0x0000172a,
+ 0x0000172a, 0x0000172a,
+} // Size: 1136 bytes
-const frData string = "" + // Size: 6446 bytes
+const frData string = "" + // Size: 5930 bytes
"\x02Erreur\x02(sans argument) : élever et installer service du gestionna" +
"ire\x02Utilisation : %[1]s [\x0a%[2]s]\x02Options de la ligne de command" +
"e\x02Impossible de détecter si le processus s’exécute sous WOW64 : %[1]v" +
@@ -820,64 +1472,61 @@ const frData string = "" + // Size: 6446 bytes
"r.\x02Impossible d'ouvrir le jeton du processus actuel : %[1]v\x02Seulem" +
"ent les utilisateurs qui sont membres du groupe intégré %[1]s peuvent ut" +
"iliser WireGuard.\x02WireGuard est en cours d'exécution, mais l'IU est a" +
- "ccessible seulement à partir des bureaux du group intégré %[1]s.\x02L’ic" +
- "ône de la barre d’état système du WireGuard n'est pas apparue après 30 " +
- "secondes.\x02Maintenant\x02L’horloge système est inversé!\x14\x01\x81" +
- "\x01\x00\x02\x09\x02%[1]d an\x00\x0a\x02%[1]d ans\x14\x01\x81\x01\x00" +
- "\x02\x0b\x02%[1]d jour\x00\x0c\x02%[1]d jours\x14\x01\x81\x01\x00\x02" +
- "\x0c\x02%[1]d heure\x00\x0d\x02%[1]d heures\x14\x01\x81\x01\x00\x02\x0d" +
- "\x02%[1]d minute\x00\x0e\x02%[1]d minutes\x14\x01\x81\x01\x00\x02\x0e" +
- "\x02%[1]d seconde\x00\x0f\x02%[1]d secondes\x02Il y a %[1]s\x02%[1]d" +
- "\u00a0o\x02%.2[1]f\u00a0Kio\x02%.2[1]f\u00a0Mio\x02%.2[1]f\u00a0Gio\x02%" +
- ".2[1]f\u00a0Tio\x02%[1]s : %[2]q\x02Adresse IP non valide\x02Longueur du" +
- " préfixe réseau non valide\x02Port manquant au point de terminaison\x02H" +
- "ôte du point de terminaison non valide\x02L’adresse IPv6 doit être cont" +
- "enue entre des crochets\x02MTU non valide\x02Port non valide\x02Keepaliv" +
- "e non valide\x02Clé non valide : %[1]v\x02Clés doivent être décodées sur" +
- " 32 octets\x02Le numéro doit être compris entre 0 et 2^64-1 : %[1]v\x02D" +
- "eux virgules consécutives\x02Nom du tunnel non valide\x02Une ligne doit " +
- "apparaître dans une section\x02Il manque le séparateur égal à la clé de " +
- "configuration\x02Clé doit avoir une valeur\x02Clé non valide pour la sec" +
- "tion [Interface]\x02Clé non valide pour la section [Peer]\x02L'interface" +
- " doit avoir une clé privée\x02[aucune spécification]\x02Toutes les pairs" +
- " doivent contenir une clé publique\x02Erreur d'obtention de la configura" +
- "tion\x02Clé non valide pour la section d'interface\x02Version du protoco" +
- "le doit être 1\x02Clé non valide pour la section d'homologue\x02, \x02 " +
- "\x02À propos du WireGuard\x02Image du logo du WireGuard\x02Version de l'" +
- "application : %[1]s\x0aVersion backend Go : %[2]s\x0aVersion Go : %[3]s-" +
- "%[4]s\x0aSystème d'exploitation : %[5]s\x0aArchitecture : %[6]s\x02Ferme" +
- "r\x02♥ &Faites un don!\x02État :\x02&Désactiver\x02&Activer\x02Clé publi" +
- "que :\x02Port d'écoute :\x02MTU :\x02Adresses :\x02Serveurs DNS :\x02Scr" +
- "ipts :\x02Clé pré-partagée :\x02Adresses IP autorisées :\x02Point de ter" +
- "minaison :\x02Conservation de connexion active permanente :\x02Dernier é" +
- "tablissement d'une liaison :\x02Transfert :\x02désactivé, par préférence" +
+ "ccessible seulement à partir des bureaux du group intégré %[1]s.\x02Main" +
+ "tenant\x02L’horloge système est inversé!\x14\x01\x81\x01\x00\x02\x09\x02" +
+ "%[1]d an\x00\x0a\x02%[1]d ans\x14\x01\x81\x01\x00\x02\x0b\x02%[1]d jour" +
+ "\x00\x0c\x02%[1]d jours\x14\x01\x81\x01\x00\x02\x0c\x02%[1]d heure\x00" +
+ "\x0d\x02%[1]d heures\x14\x01\x81\x01\x00\x02\x0d\x02%[1]d minute\x00\x0e" +
+ "\x02%[1]d minutes\x14\x01\x81\x01\x00\x02\x0e\x02%[1]d seconde\x00\x0f" +
+ "\x02%[1]d secondes\x02Il y a %[1]s\x02%[1]d\u00a0o\x02%.2[1]f\u00a0Kio" +
+ "\x02%.2[1]f\u00a0Mio\x02%.2[1]f\u00a0Gio\x02%.2[1]f\u00a0Tio\x02%[1]s : " +
+ "%[2]q\x02Adresse IP non valide\x02Longueur du préfixe réseau non valide" +
+ "\x02Port manquant au point de terminaison\x02Hôte du point de terminaiso" +
+ "n non valide\x02MTU non valide\x02Port non valide\x02Keepalive non valid" +
+ "e\x02Clé non valide : %[1]v\x02Le numéro doit être compris entre 0 et 2^" +
+ "64-1 : %[1]v\x02Deux virgules consécutives\x02Nom du tunnel non valide" +
+ "\x02[aucune spécification]\x02Toutes les pairs doivent contenir une clé " +
+ "publique\x02Erreur d'obtention de la configuration\x02, \x02 \x02À propo" +
+ "s du WireGuard\x02Image du logo du WireGuard\x02Fermer\x02♥ &Faites un d" +
+ "on!\x02État :\x02&Désactiver\x02&Activer\x02Clé publique :\x02Port d'éco" +
+ "ute :\x02MTU :\x02Adresses :\x02Serveurs DNS :\x02Clé pré-partagée :\x02" +
+ "Adresses IP autorisées :\x02Point de terminaison :\x02Conservation de co" +
+ "nnexion active permanente :\x02Dernier établissement d'une liaison :\x02" +
+ "Éteinte\x02Désactivation en cours\x02État inconnu\x02Journal\x02&Copier" +
+ "\x02Sélectionner &tout\x02&Enregistrer dans le fichier…\x02Temps\x02Mess" +
+ "age du journal\x02Exporter le journal vers le fichier\x02&À propos WireG" +
+ "uard…\x02Erreur du tunnel\x02%[1]s\x0a\x0aConsultez le journal pour plus" +
+ " d’informations, s'il vous plaît.\x02%[1]s (obsolète)\x02Erreur de sorti" +
+ "e du WireGuard\x02Une mise à jour du WireGuard est disponible. Il est fo" +
+ "rtement conseillé de metter votre WireGuard à jour sans délai.\x02Mettre" +
+ " à jour maintenant\x02Erreur : %[1]v. Veuillez réessayer.\x02État: Termi" +
+ "né!\x02L’icône de la barre d’état système du WireGuard n'est pas apparue" +
+ " après 30 secondes.\x02L’adresse IPv6 doit être contenue entre des croch" +
+ "ets\x02Clés doivent être décodées sur 32 octets\x02Une ligne doit appara" +
+ "ître dans une section\x02Il manque le séparateur égal à la clé de confi" +
+ "guration\x02Clé doit avoir une valeur\x02Clé non valide pour la section " +
+ "[Interface]\x02Clé non valide pour la section [Peer]\x02L'interface doit" +
+ " avoir une clé privée\x02Clé non valide pour la section d'interface\x02V" +
+ "ersion du protocole doit être 1\x02Clé non valide pour la section d'homo" +
+ "logue\x02Scripts :\x02Transfert :\x02pré-activation\x02post-activation" +
+ "\x02pré-désactivation\x02post-désactivation\x02désactivé, par préférence" +
"\x02activé(e)\x02%[1]s reçu(e), %[2]s envoyé(e)\x02Impossible de détermi" +
"ner l'état du tunnel\x02Impossible d'activer le tunnel\x02Impossible de " +
"désactiver le tunnel\x02Interface : %[1]s\x02Homologue\x02Créer un nouve" +
"au tunnel\x02Modifier le tunnel\x02&Nom :\x02&Clé publique :\x02(inconnu" +
- "(e))\x02&Bloquer tous le trafic hors tunnel (interrupteur)\x02Si la conf" +
- "iguration a exactement un homologue et si cet homologue a une adresse IP" +
- " autorisée contenant au moins un de 0.0.0.0/0\u00a0ou\u00a0::/0, le serv" +
- "ice de tunnel utilise un ensemble de règles du pare-feu afin de bloquer " +
- "tout le trafic qui n'est ni vers ni depuis l'interface de tunnel ou qui " +
- "est vers le mauvais serveur DNS, avec des exceptions spéciales pour les " +
- "DHCP et NDP.\x02&Enregistrer\x02Annuler\x02&Configuration :\x02Nom non v" +
- "alide\x02Le nom est obligatoire.\x02Nom de tunnel « %[1]s » est non vali" +
- "de.\x02Impossible de créer une liste des tunnels existants\x02Tunnel exi" +
- "ste déjà.\x02Nom « %[1]s » est déjà utilisé pour un tunnel.\x02Impossibl" +
- "e de créer une configuration nouvelle\x02Échec d'écriture du fichier\x02" +
- "Fichier « %[1]s » existe déjà.\x0a\x0aVoulez-vous le remplacer ?\x02Acti" +
- "vée\x02Activation en cours\x02Éteinte\x02Désactivation en cours\x02État " +
- "inconnu\x02Journal\x02&Copier\x02Sélectionner &tout\x02&Enregistrer dans" +
- " le fichier…\x02Temps\x02Message du journal\x02Fichiers texte (*.txt)|*." +
- "txt|Tous les fichiers (*.*)|*.*\x02Exporter le journal vers le fichier" +
- "\x02&À propos WireGuard…\x02Erreur du tunnel\x02%[1]s\x0a\x0aConsultez l" +
- "e journal pour plus d’informations, s'il vous plaît.\x02%[1]s (obsolète)" +
- "\x02Erreur de détection du WireGuard\x02Impossible d’attendre l'affichag" +
- "e du fenêtre WireGuard : %[1]v\x02WireGuard: Désactivé\x02État : Inconnu" +
- "\x02Adresses : Aucune\x02&Gestion des tunnels…\x02&Importer le(s) tunnel" +
- "(s) à partir du fichier…\x02Q&uitter\x02WireGuard activé\x02Tunnel %[1]s" +
- " a été activé.\x02WireGuard désactivé\x02Tunnel %[1]s a été désactivé." +
+ "(e))\x02&Bloquer tous le trafic hors tunnel (interrupteur)\x02&Enregistr" +
+ "er\x02Annuler\x02&Configuration :\x02Nom non valide\x02Le nom est obliga" +
+ "toire.\x02Nom de tunnel « %[1]s » est non valide.\x02Impossible de créer" +
+ " une liste des tunnels existants\x02Tunnel existe déjà.\x02Nom « %[1]s »" +
+ " est déjà utilisé pour un tunnel.\x02Impossible de créer une configurati" +
+ "on nouvelle\x02Échec d'écriture du fichier\x02Fichier « %[1]s » existe d" +
+ "éjà.\x0a\x0aVoulez-vous le remplacer ?\x02Activée\x02Activation en cour" +
+ "s\x02Fichiers texte (*.txt)|*.txt|Tous les fichiers (*.*)|*.*\x02Erreur " +
+ "de détection du WireGuard\x02Impossible d’attendre l'affichage du fenêtr" +
+ "e WireGuard : %[1]v\x02WireGuard: Désactivé\x02État : Inconnu\x02Adresse" +
+ "s : Aucune\x02&Gestion des tunnels…\x02&Importer le(s) tunnel(s) à parti" +
+ "r du fichier…\x02Q&uitter\x02& Tunnels\x02WireGuard activé\x02Tunnel %[1" +
+ "]s a été activé.\x02WireGuard désactivé\x02Tunnel %[1]s a été désactivé." +
"\x02Erreur du tunnel WireGuard\x02WireGuard : %[1]s\x02État : %[1]s\x02A" +
"dresses : %[1]s\x02Mise à jour disponible!\x02WireGuard mise à jour est " +
"disponible\x02Une mise à jour du WireGuard est disponible. Il est consei" +
@@ -904,70 +1553,92 @@ const frData string = "" + // Size: 6446 bytes
"tunnels.\x02Fichiers de configuration (*.zip, *.conf)|*.zip;*.conf|Tous " +
"les fichiers (*.*)|*.*\x02Importer le(s) tunnel(s) à partir du fichier" +
"\x02Fichiers de configuration ZIP (*.zip)|*.zip\x02Exporter les tunnels " +
- "vers zip\x02%[1]s (version non signée, aucune mise à jour)\x02Erreur de " +
- "sortie du WireGuard\x02Impossible de quitter le service en raison de : %" +
- "[1]v. Essayez d'arrêter WireGuard à partir du gestionnair des services." +
- "\x02Une mise à jour du WireGuard est disponible. Il est fortement consei" +
- "llé de metter votre WireGuard à jour sans délai.\x02État: En attente de " +
- "l’utilisateur\x02Mettre à jour maintenant\x02État: En attente du program" +
- "me de mise à jour\x02Erreur : %[1]v. Veuillez réessayer.\x02État: Termin" +
- "é!\x02pré-activation\x02post-activation\x02pré-désactivation\x02post-dé" +
- "sactivation\x02& Tunnels"
+ "vers zip\x02%[1]s (version non signée, aucune mise à jour)\x02Impossible" +
+ " de quitter le service en raison de : %[1]v. Essayez d'arrêter WireGuard" +
+ " à partir du gestionnair des services.\x02État: En attente de l’utilisat" +
+ "eur\x02État: En attente du programme de mise à jour"
-var idIndex = []uint32{ // 181 elements
+var idIndex = []uint32{ // 278 elements
// Entry 0 - 1F
0x00000000, 0x0000000a, 0x00000047, 0x00000062,
0x00000074, 0x000000bf, 0x000000bf, 0x000000f0,
- 0x00000148, 0x000001a1, 0x000001d6, 0x000001df,
- 0x000001f2, 0x00000211, 0x00000223, 0x00000234,
- 0x00000247, 0x0000025a, 0x0000026a, 0x00000272,
- 0x0000027e, 0x0000028a, 0x00000296, 0x000002a2,
- 0x000002af, 0x000002c5, 0x000002e0, 0x00000300,
- 0x0000031a, 0x00000340, 0x00000350, 0x00000361,
+ 0x00000148, 0x000001a1, 0x000001aa, 0x000001bd,
+ 0x000001dc, 0x000001ee, 0x000001ff, 0x00000212,
+ 0x00000225, 0x00000235, 0x0000023d, 0x00000249,
+ 0x00000255, 0x00000261, 0x0000026d, 0x0000027a,
+ 0x00000290, 0x000002ab, 0x000002cb, 0x000002e5,
+ 0x000002f5, 0x00000306, 0x00000327, 0x0000033d,
// Entry 20 - 3F
- 0x00000382, 0x00000398, 0x000003c0, 0x000003f2,
- 0x0000040c, 0x00000424, 0x00000441, 0x00000441,
- 0x0000045c, 0x00000486, 0x000004ab, 0x000004d0,
- 0x000004e1, 0x00000509, 0x0000052d, 0x00000557,
- 0x0000056e, 0x00000593, 0x00000596, 0x00000596,
- 0x000005a8, 0x000005a8, 0x000005a8, 0x000005ae,
- 0x000005bb, 0x000005c3, 0x000005c3, 0x000005c3,
- 0x000005c3, 0x000005c3, 0x000005c3, 0x000005c3,
+ 0x0000036f, 0x00000389, 0x000003a1, 0x000003b2,
+ 0x000003da, 0x000003fe, 0x00000401, 0x00000401,
+ 0x00000413, 0x00000413, 0x00000419, 0x00000426,
+ 0x0000042e, 0x0000042e, 0x0000042e, 0x0000042e,
+ 0x0000042e, 0x0000042e, 0x0000042e, 0x0000042e,
+ 0x0000042e, 0x0000042e, 0x0000042e, 0x0000042e,
+ 0x0000042e, 0x00000437, 0x00000445, 0x0000045c,
+ 0x00000464, 0x0000046a, 0x00000476, 0x00000493,
// Entry 40 - 5F
- 0x000005c3, 0x000005c3, 0x000005c3, 0x000005c3,
- 0x000005c3, 0x000005c3, 0x000005c3, 0x000005c3,
- 0x000005c3, 0x000005c3, 0x000005c3, 0x000005c3,
- 0x000005c3, 0x000005c3, 0x000005c3, 0x000005c3,
- 0x000005c3, 0x000005c3, 0x000005c3, 0x000005c3,
- 0x000005c3, 0x000005c3, 0x000005c3, 0x000005c3,
- 0x000005c3, 0x000005c3, 0x000005c3, 0x000005c3,
- 0x000005c3, 0x000005c3, 0x000005c3, 0x000005c3,
+ 0x00000499, 0x000004a3, 0x000004bb, 0x000004d1,
+ 0x000004dd, 0x00000513, 0x00000526, 0x00000526,
+ 0x00000526, 0x00000526, 0x00000526, 0x00000526,
+ 0x0000055b, 0x00000581, 0x000005a9, 0x000005c6,
+ 0x000005c6, 0x000005e1, 0x0000060b, 0x00000630,
+ 0x00000655, 0x0000067f, 0x00000696, 0x000006bb,
+ 0x000006bb, 0x000006bb, 0x000006bb, 0x000006bb,
+ 0x000006bb, 0x000006bb, 0x000006bb, 0x000006bb,
// Entry 60 - 7F
- 0x000005c3, 0x000005c3, 0x000005c3, 0x000005c9,
- 0x000005d6, 0x000005df, 0x000005ed, 0x00000604,
- 0x0000060c, 0x00000612, 0x0000061e, 0x0000063b,
- 0x00000641, 0x0000064b, 0x0000067b, 0x00000693,
- 0x000006a9, 0x000006b5, 0x000006eb, 0x000006fe,
- 0x00000715, 0x0000074a, 0x00000763, 0x0000077b,
- 0x0000078a, 0x0000079d, 0x000007b8, 0x000007c0,
- 0x000007c0, 0x000007c0, 0x000007c0, 0x000007c0,
+ 0x000006bb, 0x000006bb, 0x000006bb, 0x000006bb,
+ 0x000006bb, 0x000006bb, 0x000006bb, 0x000006bb,
+ 0x000006bb, 0x000006bb, 0x000006bb, 0x000006bb,
+ 0x000006bb, 0x000006bb, 0x000006bb, 0x000006bb,
+ 0x000006bb, 0x000006bb, 0x000006bb, 0x000006bb,
+ 0x000006bb, 0x000006bb, 0x000006bb, 0x000006bb,
+ 0x000006c1, 0x000006ce, 0x000006fe, 0x00000715,
+ 0x0000074a, 0x00000763, 0x0000077b, 0x0000078a,
// Entry 80 - 9F
+ 0x0000079d, 0x000007b8, 0x000007c0, 0x000007c0,
+ 0x000007c0, 0x000007c0, 0x000007c0, 0x000007c0,
0x000007d6, 0x000007e7, 0x000007f5, 0x000007f5,
0x000007f5, 0x000007f5, 0x000007f5, 0x000007f5,
0x000007f5, 0x000007f5, 0x000007f5, 0x000007f5,
0x000007f5, 0x000007f5, 0x00000814, 0x0000082d,
0x00000844, 0x00000844, 0x0000087a, 0x0000087a,
0x0000087a, 0x0000087a, 0x0000087a, 0x0000087a,
+ // Entry A0 - BF
+ 0x0000087a, 0x0000087a, 0x0000087a, 0x0000087a,
+ 0x0000087a, 0x0000087a, 0x0000087a, 0x0000087a,
+ 0x0000087a, 0x0000087a, 0x0000087a, 0x0000087a,
+ 0x0000087a, 0x0000087a, 0x0000087a, 0x0000087a,
+ 0x0000087a, 0x0000087a, 0x0000087a, 0x0000087a,
+ 0x0000087a, 0x0000087a, 0x0000087a, 0x0000087a,
+ 0x0000087a, 0x0000087a, 0x0000087a, 0x0000087a,
+ 0x0000087a, 0x0000087a, 0x0000087a, 0x0000087a,
+ // Entry C0 - DF
+ 0x0000087a, 0x0000087a, 0x0000087a, 0x0000087a,
+ 0x0000087a, 0x0000087a, 0x0000087a, 0x0000087a,
+ 0x0000087a, 0x0000087a, 0x0000087a, 0x0000087a,
+ 0x0000087a, 0x0000087a, 0x0000087a, 0x0000087a,
+ 0x0000087a, 0x0000087a, 0x0000087a, 0x0000087a,
+ 0x0000087a, 0x0000087a, 0x0000087a, 0x0000087a,
+ 0x0000087a, 0x0000087a, 0x0000087a, 0x0000087a,
+ 0x0000087a, 0x0000087a, 0x0000087a, 0x0000087a,
+ // Entry E0 - FF
+ 0x0000087a, 0x0000087a, 0x0000087a, 0x0000087a,
+ 0x0000087a, 0x0000087a, 0x0000087a, 0x0000087a,
+ 0x0000087a, 0x0000087a, 0x0000087a, 0x0000087a,
0x0000087a, 0x0000087a, 0x0000087a, 0x0000087a,
0x0000087a, 0x0000087a, 0x0000087a, 0x0000087a,
- // Entry A0 - BF
0x0000087a, 0x0000087a, 0x0000087a, 0x0000087a,
0x0000087a, 0x0000087a, 0x0000087a, 0x0000087a,
0x0000087a, 0x0000087a, 0x0000087a, 0x0000087a,
+ // Entry 100 - 11F
0x0000087a, 0x0000087a, 0x0000087a, 0x0000087a,
0x0000087a, 0x0000087a, 0x0000087a, 0x0000087a,
- 0x0000087a,
-} // Size: 748 bytes
+ 0x0000087a, 0x0000087a, 0x0000087a, 0x0000087a,
+ 0x0000087a, 0x0000087a, 0x0000087a, 0x0000087a,
+ 0x0000087a, 0x0000087a, 0x0000087a, 0x0000087a,
+ 0x0000087a, 0x0000087a,
+} // Size: 1136 bytes
const idData string = "" + // Size: 2170 bytes
"\x02Kesalahan\x02(tidak ada argumen): naikkan akses dan instal servis ma" +
@@ -976,463 +1647,672 @@ const idData string = "" + // Size: 2170 bytes
"ak dapat membuka token proses saat ini: %[1]v\x02WireGuard hanya dapat d" +
"igunakan oleh pengguna yang merupakan anggota grup Bawaan %[1]s.\x02Wire" +
"Guard sedang berjalan, tetapi UI hanya dapat diakses dari desktop grup B" +
- "awaan %[1]s.\x02Ikon sistem WireGuard tidak muncul setelah 30 detik.\x02" +
- "Sekarang\x02Jam sistem mundur!\x14\x01\x81\x01\x00\x00\x18\x02%[1]d tahu" +
- "n\x0a%[1]d tahun\x14\x01\x81\x01\x00\x00\x0b\x02%[1]d Hari\x14\x01\x81" +
- "\x01\x00\x00\x0a\x02%[1]d jam\x14\x01\x81\x01\x00\x00\x0c\x02%[1]d menit" +
- "\x14\x01\x81\x01\x00\x00\x0c\x02%[1]d detik\x02%[1]s yang lalu\x02%[1]d " +
- "B\x02%.2[1]f KiB\x02%.2[1]f MiB\x02%.2[1]f GiB\x02%.2[1]f TiB\x02%[1]s: " +
- "%[2]q\x02Alamat IP tidak valid\x02Network prefix tidak valid\x02Port bel" +
- "um terisi dari endpoint\x02Host endpoint tidak valid\x02Dalam Kurung har" +
- "us berisi alamat IPv6\x02MTU tidak valid\x02Port tidak valid\x02Persiste" +
- "nt keepalive tidak valid\x02Kunci tidak sah:%[1]v\x02Kunci harus diterje" +
- "mahkan tepat 32 byte\x02Nomor harus diantara 0 sampai dengan 2^64-1:%[1]" +
- "v\x02Dua koma dalam satu baris\x02Nama Tunnel tidak valid\x02Garis harus" +
- " muncul perbagian\x02Kunci harus memiliki value\x02Kunci tidak valid pad" +
- "a bagian [Interface]\x02Kunci tidak valid pada bagian [Peer]\x02Interfac" +
- "e harus memiliki Private Key\x02Tidak Ditetapkan\x02Semua peers harus me" +
- "miliki kunci publik\x02Eror ketika mendapatkan konfigurasi\x02Kunci tida" +
- "k valid pada bagian [Interface]\x02Versi protokol harus 1\x02Kunci tidak" +
- " valid pada bagian [Peer]\x02, \x02Tentang WireGuard\x02Tutup\x02♥ &Dona" +
- "si!\x02Status:\x02Aktif\x02Mengaktifkan\x02Nonaktif\x02Menonaktifkan\x02" +
- "Status tidak diketahui\x02Catatan\x02Salin\x02Pilih semua\x02Menyimpan k" +
- "e dalam berkas…\x02Waktu\x02Pesan log\x02Berkas Txt (*.Txt)|*.Txt|Semua " +
- "berkas (*.*)|*.*\x02Ekspor log kedalam file\x02&Tentang WireGuard…\x02Tu" +
- "nnel eror\x02%[1]s\x0a\x0aSilakan baca log untuk informasi lebih lanjut." +
- "\x02%[1]s (kadaluarsa)\x02Deteksi eror WireGuard\x02Tidak dapat menunggu" +
- " jendela WireGuard muncul: %[1]v\x02WireGuard: Dinonaktifkan\x02Status: " +
- "Tidak diketahui\x02Alamat: Kosong\x02&Manajer Tunnel…\x02&Impor tunnel d" +
- "ari file…\x02&Keluar\x02Wireguard Tunnel Eror\x02WireGuard: %[1]s\x02Sta" +
- "tus: %[1]s\x02Ekspor semua tunnel ke &zip…\x02Ubah tunnel &terpilih…\x02" +
- "&Hapus tunnel terpilih\x02Tidak dapat mengimpor konfigurasi yang dipilih" +
- ": %[1]v"
+ "awaan %[1]s.\x02Sekarang\x02Jam sistem mundur!\x14\x01\x81\x01\x00\x00" +
+ "\x18\x02%[1]d tahun\x0a%[1]d tahun\x14\x01\x81\x01\x00\x00\x0b\x02%[1]d " +
+ "Hari\x14\x01\x81\x01\x00\x00\x0a\x02%[1]d jam\x14\x01\x81\x01\x00\x00" +
+ "\x0c\x02%[1]d menit\x14\x01\x81\x01\x00\x00\x0c\x02%[1]d detik\x02%[1]s " +
+ "yang lalu\x02%[1]d B\x02%.2[1]f KiB\x02%.2[1]f MiB\x02%.2[1]f GiB\x02%.2" +
+ "[1]f TiB\x02%[1]s: %[2]q\x02Alamat IP tidak valid\x02Network prefix tida" +
+ "k valid\x02Port belum terisi dari endpoint\x02Host endpoint tidak valid" +
+ "\x02MTU tidak valid\x02Port tidak valid\x02Persistent keepalive tidak va" +
+ "lid\x02Kunci tidak sah:%[1]v\x02Nomor harus diantara 0 sampai dengan 2^6" +
+ "4-1:%[1]v\x02Dua koma dalam satu baris\x02Nama Tunnel tidak valid\x02Tid" +
+ "ak Ditetapkan\x02Semua peers harus memiliki kunci publik\x02Eror ketika " +
+ "mendapatkan konfigurasi\x02, \x02Tentang WireGuard\x02Tutup\x02♥ &Donasi" +
+ "!\x02Status:\x02Nonaktif\x02Menonaktifkan\x02Status tidak diketahui\x02C" +
+ "atatan\x02Salin\x02Pilih semua\x02Menyimpan ke dalam berkas…\x02Waktu" +
+ "\x02Pesan log\x02Ekspor log kedalam file\x02&Tentang WireGuard…\x02Tunne" +
+ "l eror\x02%[1]s\x0a\x0aSilakan baca log untuk informasi lebih lanjut." +
+ "\x02%[1]s (kadaluarsa)\x02Ikon sistem WireGuard tidak muncul setelah 30 " +
+ "detik.\x02Dalam Kurung harus berisi alamat IPv6\x02Kunci harus diterjema" +
+ "hkan tepat 32 byte\x02Garis harus muncul perbagian\x02Kunci harus memili" +
+ "ki value\x02Kunci tidak valid pada bagian [Interface]\x02Kunci tidak val" +
+ "id pada bagian [Peer]\x02Interface harus memiliki Private Key\x02Kunci t" +
+ "idak valid pada bagian [Interface]\x02Versi protokol harus 1\x02Kunci ti" +
+ "dak valid pada bagian [Peer]\x02Aktif\x02Mengaktifkan\x02Berkas Txt (*.T" +
+ "xt)|*.Txt|Semua berkas (*.*)|*.*\x02Deteksi eror WireGuard\x02Tidak dapa" +
+ "t menunggu jendela WireGuard muncul: %[1]v\x02WireGuard: Dinonaktifkan" +
+ "\x02Status: Tidak diketahui\x02Alamat: Kosong\x02&Manajer Tunnel…\x02&Im" +
+ "por tunnel dari file…\x02&Keluar\x02Wireguard Tunnel Eror\x02WireGuard: " +
+ "%[1]s\x02Status: %[1]s\x02Ekspor semua tunnel ke &zip…\x02Ubah tunnel &t" +
+ "erpilih…\x02&Hapus tunnel terpilih\x02Tidak dapat mengimpor konfigurasi " +
+ "yang dipilih: %[1]v"
-var itIndex = []uint32{ // 181 elements
+var itIndex = []uint32{ // 278 elements
// Entry 0 - 1F
0x00000000, 0x00000007, 0x00000044, 0x0000005d,
- 0x00000075, 0x000000bd, 0x000000bd, 0x000000f6,
- 0x0000014d, 0x000001be, 0x00000212, 0x00000216,
- 0x0000023d, 0x0000025c, 0x0000027f, 0x0000029c,
- 0x000002bf, 0x000002e4, 0x000002ed, 0x000002f6,
- 0x00000303, 0x00000310, 0x0000031d, 0x0000032a,
- 0x00000337, 0x0000034f, 0x00000379, 0x00000396,
- 0x000003b4, 0x000003e4, 0x000003f3, 0x00000404,
+ 0x00000075, 0x000000bd, 0x00000101, 0x0000013a,
+ 0x00000191, 0x00000202, 0x00000206, 0x0000022d,
+ 0x0000024c, 0x0000026f, 0x0000028c, 0x000002af,
+ 0x000002d4, 0x000002dd, 0x000002e6, 0x000002f3,
+ 0x00000300, 0x0000030d, 0x0000031a, 0x00000327,
+ 0x0000033f, 0x00000369, 0x00000386, 0x000003a4,
+ 0x000003b3, 0x000003c4, 0x000003e4, 0x000003fd,
// Entry 20 - 3F
- 0x00000424, 0x0000043d, 0x0000046f, 0x000004ae,
- 0x000004c6, 0x000004e7, 0x00000514, 0x00000514,
- 0x00000533, 0x00000560, 0x00000588, 0x000005b5,
- 0x000005c7, 0x000005f5, 0x00000625, 0x00000657,
- 0x00000680, 0x000006a6, 0x000006a9, 0x000006ab,
- 0x000006c5, 0x000006e4, 0x000006e4, 0x000006eb,
- 0x00000703, 0x0000070a, 0x00000715, 0x0000071d,
- 0x0000072e, 0x00000740, 0x00000745, 0x00000750,
+ 0x0000043c, 0x00000454, 0x00000475, 0x00000487,
+ 0x000004b5, 0x000004e5, 0x000004e8, 0x000004ea,
+ 0x00000504, 0x00000523, 0x0000052a, 0x00000542,
+ 0x00000549, 0x00000554, 0x0000055c, 0x0000056d,
+ 0x0000057f, 0x00000584, 0x0000058f, 0x0000059b,
+ 0x000005b1, 0x000005c0, 0x000005ca, 0x000005e0,
+ 0x000005f5, 0x000005fe, 0x0000060d, 0x0000061f,
+ 0x00000623, 0x0000062a, 0x0000063b, 0x0000064d,
// Entry 40 - 5F
- 0x0000075c, 0x0000075c, 0x00000772, 0x00000781,
- 0x0000078b, 0x000007a1, 0x000007b6, 0x000007c5,
- 0x000007c5, 0x000007cf, 0x000007ed, 0x00000820,
- 0x00000844, 0x0000086b, 0x0000087e, 0x00000883,
- 0x0000088f, 0x0000089f, 0x000008a6, 0x000008b8,
- 0x000008c6, 0x000008f6, 0x000008f6, 0x000008fd,
- 0x00000905, 0x00000916, 0x00000926, 0x0000093c,
- 0x0000096a, 0x00000992, 0x000009a8, 0x000009dd,
+ 0x00000653, 0x00000664, 0x00000678, 0x00000696,
+ 0x000006a8, 0x000006db, 0x000006ec, 0x00000714,
+ 0x00000779, 0x00000786, 0x000007a3, 0x000007b4,
+ 0x00000808, 0x00000838, 0x0000086a, 0x00000897,
+ 0x000008da, 0x000008f9, 0x00000926, 0x0000094e,
+ 0x0000097b, 0x000009ad, 0x000009d6, 0x000009fc,
+ 0x00000a04, 0x00000a13, 0x00000a1a, 0x00000a22,
+ 0x00000a2b, 0x00000a35, 0x00000a4f, 0x00000a59,
// Entry 60 - 7F
- 0x00000a08, 0x00000a28, 0x00000a5f, 0x00000a66,
- 0x00000a72, 0x00000a7b, 0x00000a8a, 0x00000a9c,
- 0x00000aa0, 0x00000aa7, 0x00000ab8, 0x00000aca,
- 0x00000ad0, 0x00000ae1, 0x00000b14, 0x00000b28,
- 0x00000b46, 0x00000b58, 0x00000b8b, 0x00000b9c,
- 0x00000bbf, 0x00000c04, 0x00000c1b, 0x00000c2e,
- 0x00000c41, 0x00000c57, 0x00000c72, 0x00000c78,
- 0x00000c8b, 0x00000cae, 0x00000cc4, 0x00000cea,
+ 0x00000a77, 0x00000aaa, 0x00000ace, 0x00000af5,
+ 0x00000b08, 0x00000b0d, 0x00000b19, 0x00000b29,
+ 0x00000b30, 0x00000b42, 0x00000b50, 0x00000b80,
+ 0x00000b87, 0x00000b8f, 0x00000ba0, 0x00000bb0,
+ 0x00000bc6, 0x00000bf4, 0x00000c1c, 0x00000c32,
+ 0x00000c67, 0x00000c92, 0x00000cb2, 0x00000ce9,
+ 0x00000cf0, 0x00000cfc, 0x00000d2f, 0x00000d52,
+ 0x00000d97, 0x00000dae, 0x00000dc1, 0x00000dd4,
// Entry 80 - 9F
- 0x00000d05, 0x00000d16, 0x00000d23, 0x00000d23,
- 0x00000d44, 0x00000d6b, 0x00000dca, 0x00000dd1,
- 0x00000ddb, 0x00000df2, 0x00000e02, 0x00000e1d,
- 0x00000e3b, 0x00000e44, 0x00000e63, 0x00000e86,
- 0x00000ea4, 0x00000ea4, 0x00000edf, 0x00000f0f,
- 0x00000f43, 0x00000f72, 0x00000f83, 0x00000fba,
- 0x00001002, 0x0000101f, 0x00001052, 0x000010b3,
- 0x000010ce, 0x00001103, 0x00001133, 0x00001153,
+ 0x00000dea, 0x00000e05, 0x00000e0b, 0x00000e13,
+ 0x00000e26, 0x00000e49, 0x00000e5f, 0x00000e85,
+ 0x00000ea0, 0x00000eb1, 0x00000ebe, 0x00000ecf,
+ 0x00000ef0, 0x00000f17, 0x00000f76, 0x00000f7d,
+ 0x00000f87, 0x00000fa1, 0x00000fb1, 0x00000fcc,
+ 0x00000fea, 0x00000ff3, 0x00001015, 0x00001038,
+ 0x00001056, 0x0000107c, 0x000010b7, 0x000010e7,
+ 0x0000111b, 0x0000114a, 0x0000115b, 0x00001192,
// Entry A0 - BF
- 0x00001185, 0x000011a4, 0x0000120b, 0x00001256,
- 0x0000126d, 0x00001296, 0x000012ac, 0x000012df,
- 0x00001307, 0x00001379, 0x000013de, 0x000013fb,
- 0x00001408, 0x00001437, 0x00001454, 0x00001465,
- 0x00001465, 0x00001465, 0x00001465, 0x00001465,
- 0x00001465,
-} // Size: 748 bytes
+ 0x000011da, 0x000011f7, 0x0000122a, 0x0000128b,
+ 0x000012a6, 0x000012db, 0x0000130b, 0x0000132b,
+ 0x0000135d, 0x0000137c, 0x000013e3, 0x0000142e,
+ 0x00001445, 0x0000146e, 0x00001484, 0x000014b7,
+ 0x00001529, 0x00001546, 0x00001575, 0x00001575,
+ 0x00001575, 0x00001575, 0x00001575, 0x00001575,
+ 0x00001575, 0x00001575, 0x00001575, 0x00001575,
+ 0x00001575, 0x00001575, 0x00001575, 0x00001575,
+ // Entry C0 - DF
+ 0x00001575, 0x00001575, 0x00001575, 0x00001575,
+ 0x00001575, 0x00001575, 0x00001575, 0x00001575,
+ 0x00001575, 0x00001575, 0x00001575, 0x00001575,
+ 0x00001575, 0x00001575, 0x00001575, 0x00001575,
+ 0x00001575, 0x00001575, 0x00001575, 0x00001575,
+ 0x00001575, 0x00001575, 0x00001575, 0x00001575,
+ 0x00001575, 0x00001575, 0x00001575, 0x00001575,
+ 0x00001575, 0x00001575, 0x00001575, 0x00001575,
+ // Entry E0 - FF
+ 0x00001575, 0x00001575, 0x00001575, 0x00001575,
+ 0x00001575, 0x00001575, 0x00001575, 0x00001575,
+ 0x00001575, 0x00001575, 0x00001575, 0x00001575,
+ 0x00001575, 0x00001575, 0x00001575, 0x00001575,
+ 0x00001575, 0x00001575, 0x00001575, 0x00001575,
+ 0x00001575, 0x00001575, 0x00001575, 0x00001575,
+ 0x00001575, 0x00001575, 0x00001575, 0x00001575,
+ 0x00001575, 0x00001575, 0x00001575, 0x00001575,
+ // Entry 100 - 11F
+ 0x00001575, 0x00001575, 0x00001575, 0x00001575,
+ 0x00001575, 0x00001575, 0x00001575, 0x00001575,
+ 0x00001575, 0x00001575, 0x00001575, 0x00001575,
+ 0x00001575, 0x00001575, 0x00001575, 0x00001575,
+ 0x00001575, 0x00001575, 0x00001575, 0x00001575,
+ 0x00001575, 0x00001575,
+} // Size: 1136 bytes
-const itData string = "" + // Size: 5221 bytes
+const itData string = "" + // Size: 5493 bytes
"\x02Errore\x02(nessun argomento): eleva e installa il servizio di gestio" +
"ne\x02Utilizzo: %[1]s [\x0a%[2]s]\x02Opzioni riga di comando\x02Impossib" +
- "ile determinare se il processo è in esecuzione in WOW64: %[1]v\x02Imposs" +
- "ibile aprire il token del processo corrente: %[1]v\x02WireGuard può esse" +
- "re utilizzato solo dagli utenti membri del gruppo %[1]s di sistema.\x02W" +
- "ireGuard è in esecuzione, ma l'interfaccia utente è accessibile solo dai" +
- " desktop del gruppo %[1]s di sistema.\x02L'icona della barra delle appli" +
- "cazioni di WireGuard non è apparsa dopo 30 secondi.\x02Ora\x02L'orologio" +
- " di sistema va all'indietro!\x14\x01\x81\x01\x00\x02\x0b\x02%[1]d anno" +
- "\x00\x0b\x02%[1]d anni\x14\x01\x81\x01\x00\x02\x0d\x02%[1]d giorno\x00" +
- "\x0d\x02%[1]d giorni\x14\x01\x81\x01\x00\x02\x0a\x02%[1]d ora\x00\x0a" +
- "\x02%[1]d ore\x14\x01\x81\x01\x00\x02\x0d\x02%[1]d minuto\x00\x0d\x02%[1" +
- "]d minuti\x14\x01\x81\x01\x00\x02\x0e\x02%[1]d secondo\x00\x0e\x02%[1]d " +
- "secondi\x02%[1]s fa\x02%[1]d\u00a0B\x02%.2[1]f\u00a0KiB\x02%.2[1]f\u00a0" +
- "MiB\x02%.2[1]f\u00a0GiB\x02%.2[1]f\u00a0TiB\x02%[1]s: %[2]q\x02Indirizzo" +
- " IP non valido\x02Lunghezza del prefisso di rete non valida\x02Manca la " +
- "porta dall'endpoint\x02Host dell'endpoint non valido\x02Le parentesi dev" +
- "ono contenere un indirizzo IPv6\x02MTU non valido\x02Porta non valida" +
- "\x02Keepalive permanente non valido\x02Chiave non valida: %[1]v\x02Le ch" +
- "iavi devono decodificare esattamente 32 byte\x02Il numero deve essere un" +
- " numero compreso tra 0 e 2^64-1: %[1]v\x02Due virgole in una riga\x02Il " +
- "nome del tunnel non è valido\x02Una riga deve essere presente in una sez" +
- "ione\x02La chiave deve avere un valore\x02Chiave non valida per la sezio" +
- "ne [Interface]\x02Chiave non valida per la sezione [Peer]\x02Un'interfac" +
- "cia deve avere una chiave privata\x02[non specificato]\x02Tutti i peer d" +
- "evono avere una chiave pubblica\x02Errore durante il recupero della conf" +
- "igurazione\x02Chiave non valida per la sezione dell'interfaccia\x02La ve" +
- "rsione del protocollo deve essere 1\x02Chiave non valida per la sezione " +
- "peer\x02, \x02 \x02Informazioni su WireGuard\x02Immagine del logo di Wir" +
- "eGuard\x02Chiudi\x02♥ Fai una &donazione!\x02Stato:\x02&Disattiva\x02&At" +
- "tiva\x02Chiave pubblica:\x02Porta in ascolto:\x02MTU:\x02Indirizzi:\x02S" +
- "erver DNS:\x02Chiave pre-condivisa:\x02IP consentiti:\x02Endpoint:\x02Ke" +
- "epalive permanente:\x02Ultima negoziazione:\x02Trasferimento:\x02abilita" +
- "to\x02%[1]s ricevuti, %[2]s inviati\x02Determinazione dello stato del tu" +
- "nnel non riuscita\x02Attivazione del tunnel non riuscita\x02Disattivazio" +
- "ne del tunnel non riuscita\x02Interfaccia: %[1]s\x02Peer\x02Crea tunnel" +
- "\x02Modifica tunnel\x02&Nome:\x02Chiave &pubblica:\x02(sconosciuto)\x02&" +
- "Blocca traffico fuori dal tunnel (kill-switch)\x02&Salva\x02Annulla\x02&" +
- "Configurazione:\x02Nome non valido\x02Un nome è richiesto.\x02Il nome de" +
- "l tunnel ‘%[1]s’ non è valido.\x02Impossibile elencare i tunnel esistent" +
- "i\x02Il tunnel esiste già\x02Un altro tunnel con il nome ‘%[1]s’ esiste " +
- "già.\x02Impossibile creare la nuova configurazione\x02Scrittura del file" +
- " non riuscita\x02Il file ‘%[1]s’ esiste già.\x0a\x0aVuoi sovrascriverlo?" +
- "\x02Attivo\x02Attivazione\x02Inattivo\x02Disattivazione\x02Stato sconosc" +
- "iuto\x02Log\x02&Copia\x02Selezion&a tutto\x02&Salva su file…\x02Tempo" +
- "\x02Messaggio di log\x02File di testo (*.txt)|*.txt|Tutti i file (*.*)|*" +
- ".*\x02Esporta log su file\x02Inform&azioni su WireGuard…\x02Errore del t" +
- "unnel\x02%[1]s\x0a\x0aConsulta il log per ulteriori Informazioni.\x02%[1" +
- "]s (obsoleto)\x02Errore di rilevamento di WireGuard\x02Impossibile atten" +
- "dere la comparsa della finestra di WireGuard: %[1]v\x02WireGuard: disatt" +
- "ivato\x02Stato: sconosciuto\x02Indirizzi: nessuno\x02&Gestisci i tunnel…" +
- "\x02&Importa tunnel da file…\x02E&sci\x02WireGuard attivato\x02Il tunnel" +
- " %[1]s è stato attivato.\x02WireGuard disattivato\x02Il tunnel %[1]s è s" +
- "tato disattivato.\x02Errore tunnel di WireGuard\x02WireGuard: %[1]s\x02S" +
- "tato: %[1]s\x02Un aggiornamento è disponibile!\x02Aggiornamento di WireG" +
- "uard disponibile\x02Un aggiornamento di WireGuard è disponibile. Ti cons" +
- "igliamo di aggiornare il prima possibile.\x02Tunnel\x02&Modifica\x02Aggi" +
- "ungi tunn&el vuoto\x02Aggiungi tunnel\x02Rimuovi tunnel selezionati\x02E" +
- "sporta tutti i tunnel in zip\x02Commu&ta\x02Esporta tutti i tunnel in &z" +
- "ip\x02Modifica il tunnel &selezionato…\x02&Rimuovi i tunnel selezionati" +
- "\x02Impossibile importare la configurazione selezionata: %[1]v\x02Imposs" +
- "ibile enumerare i tunnel esistenti: %[1]v\x02Un altro tunnel esiste già " +
- "con il nome ‘%[1]s‘\x02Impossibile importare la configurazione: %[1]v" +
- "\x02Tunnel importati\x14\x01\x81\x01\x00\x02\x17\x02%[1]d tunnel importa" +
- "to\x00\x17\x02%[1]d tunnel importati\x14\x02\x80\x01\x02 \x02%[1]d de %[" +
- "2]d tunnel importato\x00 \x02%[1]d di %[2]d tunnel importati\x02Impossib" +
- "ile creare il tunnel\x14\x01\x81\x01\x00\x02\x15\x02Elimina %[1]d tunnel" +
- "\x00\x15\x02Elimina %[1]d tunnel\x14\x01\x81\x01\x00\x02,\x02Sei sicuro " +
- "di voler eliminare %[1]d tunnel?\x00,\x02Sei sicuro di voler eliminare %" +
- "[1]d tunnel?\x02Elimina tunnel ‘%[1]s‘\x02Sei sicuro di voler eliminare " +
- "il tunnel ‘%[1]s‘?\x02%[1]s Non è possibile annullare questa azione.\x02" +
- "Impossibile eliminare il tunnel\x02Non è stato possibile rimuovere un tu" +
- "nnel: %[1]s\x02Impossibile eliminare i tunnel\x14\x01\x81\x01\x00\x02/" +
- "\x02Non è stato possibile eliminare %[1]d tunnel.\x00/\x02Non è stato po" +
- "ssibile eliminare %[1]d tunnel.\x02File di configurazione (*.zip, *.conf" +
- ")|*.zip;*.conf|Tutti i file (*.*)|*.*\x02Importa tunnel da file\x02File " +
- "di configurazione ZIP (*.zip)|*.zip\x02Esporta tunnel in zip\x02%[1]s (v" +
- "ersione non firmata, nessun aggiornamento)\x02Errore durante la chiusura" +
- " di WireGuard\x02Impossibile uscire dal servizio a causa di: %[1]v. Potr" +
- "esti voler interrompere WireGuard dal gestore dei servizi.\x02Un aggiorn" +
- "amento di WireGuard è disponibile. Ti consigliamo vivamente di aggiornar" +
- "e immediatamente.\x02Stato: in attesa dell'utente\x02Aggiorna ora\x02Sta" +
- "to: in attesa del servizio di aggiornamento\x02Errore: %[1]v. Prova anco" +
- "ra.\x02Stato: Completo!"
+ "ile determinare se il processo è in esecuzione in WOW64: %[1]v\x02Devi u" +
+ "tilizzare la versione nativa di WireGuard su questo computer.\x02Impossi" +
+ "bile aprire il token del processo corrente: %[1]v\x02WireGuard può esser" +
+ "e utilizzato solo dagli utenti membri del gruppo %[1]s di sistema.\x02Wi" +
+ "reGuard è in esecuzione, ma l'interfaccia utente è accessibile solo dai " +
+ "desktop del gruppo %[1]s di sistema.\x02Ora\x02L'orologio di sistema va " +
+ "all'indietro!\x14\x01\x81\x01\x00\x02\x0b\x02%[1]d anno\x00\x0b\x02%[1]d" +
+ " anni\x14\x01\x81\x01\x00\x02\x0d\x02%[1]d giorno\x00\x0d\x02%[1]d giorn" +
+ "i\x14\x01\x81\x01\x00\x02\x0a\x02%[1]d ora\x00\x0a\x02%[1]d ore\x14\x01" +
+ "\x81\x01\x00\x02\x0d\x02%[1]d minuto\x00\x0d\x02%[1]d minuti\x14\x01\x81" +
+ "\x01\x00\x02\x0e\x02%[1]d secondo\x00\x0e\x02%[1]d secondi\x02%[1]s fa" +
+ "\x02%[1]d\u00a0B\x02%.2[1]f\u00a0KiB\x02%.2[1]f\u00a0MiB\x02%.2[1]f" +
+ "\u00a0GiB\x02%.2[1]f\u00a0TiB\x02%[1]s: %[2]q\x02Indirizzo IP non valido" +
+ "\x02Lunghezza del prefisso di rete non valida\x02Manca la porta dall'end" +
+ "point\x02Host dell'endpoint non valido\x02MTU non valido\x02Porta non va" +
+ "lida\x02Keepalive permanente non valido\x02Chiave non valida: %[1]v\x02I" +
+ "l numero deve essere un numero compreso tra 0 e 2^64-1: %[1]v\x02Due vir" +
+ "gole in una riga\x02Il nome del tunnel non è valido\x02[non specificato]" +
+ "\x02Tutti i peer devono avere una chiave pubblica\x02Errore durante il r" +
+ "ecupero della configurazione\x02, \x02 \x02Informazioni su WireGuard\x02" +
+ "Immagine del logo di WireGuard\x02Chiudi\x02♥ Fai una &donazione!\x02Sta" +
+ "to:\x02&Disattiva\x02&Attiva\x02Chiave pubblica:\x02Porta in ascolto:" +
+ "\x02MTU:\x02Indirizzi:\x02Server DNS:\x02Chiave pre-condivisa:\x02IP con" +
+ "sentiti:\x02Endpoint:\x02Keepalive permanente:\x02Ultima negoziazione:" +
+ "\x02Inattivo\x02Disattivazione\x02Stato sconosciuto\x02Log\x02&Copia\x02" +
+ "Selezion&a tutto\x02&Salva su file…\x02Tempo\x02Messaggio di log\x02Espo" +
+ "rta log su file\x02Inform&azioni su WireGuard…\x02Errore del tunnel\x02%" +
+ "[1]s\x0a\x0aConsulta il log per ulteriori Informazioni.\x02%[1]s (obsole" +
+ "to)\x02Errore durante la chiusura di WireGuard\x02Un aggiornamento di Wi" +
+ "reGuard è disponibile. Ti consigliamo vivamente di aggiornare immediatam" +
+ "ente.\x02Aggiorna ora\x02Errore: %[1]v. Prova ancora.\x02Stato: Completo" +
+ "!\x02L'icona della barra delle applicazioni di WireGuard non è apparsa d" +
+ "opo 30 secondi.\x02Le parentesi devono contenere un indirizzo IPv6\x02Le" +
+ " chiavi devono decodificare esattamente 32 byte\x02Una riga deve essere " +
+ "presente in una sezione\x02Manca un separatore di uguaglianza per la chi" +
+ "ave di configurazione\x02La chiave deve avere un valore\x02Chiave non va" +
+ "lida per la sezione [Interface]\x02Chiave non valida per la sezione [Pee" +
+ "r]\x02Un'interfaccia deve avere una chiave privata\x02Chiave non valida " +
+ "per la sezione dell'interfaccia\x02La versione del protocollo deve esser" +
+ "e 1\x02Chiave non valida per la sezione peer\x02Script:\x02Trasferimento" +
+ ":\x02pre-up\x02post-up\x02pre-down\x02post-down\x02disattivato, per crit" +
+ "erio\x02abilitato\x02%[1]s ricevuti, %[2]s inviati\x02Determinazione del" +
+ "lo stato del tunnel non riuscita\x02Attivazione del tunnel non riuscita" +
+ "\x02Disattivazione del tunnel non riuscita\x02Interfaccia: %[1]s\x02Peer" +
+ "\x02Crea tunnel\x02Modifica tunnel\x02&Nome:\x02Chiave &pubblica:\x02(sc" +
+ "onosciuto)\x02&Blocca traffico fuori dal tunnel (kill-switch)\x02&Salva" +
+ "\x02Annulla\x02&Configurazione:\x02Nome non valido\x02Un nome è richiest" +
+ "o.\x02Il nome del tunnel ‘%[1]s’ non è valido.\x02Impossibile elencare i" +
+ " tunnel esistenti\x02Il tunnel esiste già\x02Un altro tunnel con il nome" +
+ " ‘%[1]s’ esiste già.\x02Impossibile creare la nuova configurazione\x02Sc" +
+ "rittura del file non riuscita\x02Il file ‘%[1]s’ esiste già.\x0a\x0aVuoi" +
+ " sovrascriverlo?\x02Attivo\x02Attivazione\x02File di testo (*.txt)|*.txt" +
+ "|Tutti i file (*.*)|*.*\x02Errore di rilevamento di WireGuard\x02Impossi" +
+ "bile attendere la comparsa della finestra di WireGuard: %[1]v\x02WireGua" +
+ "rd: disattivato\x02Stato: sconosciuto\x02Indirizzi: nessuno\x02&Gestisci" +
+ " i tunnel…\x02&Importa tunnel da file…\x02E&sci\x02&Tunnel\x02WireGuard " +
+ "attivato\x02Il tunnel %[1]s è stato attivato.\x02WireGuard disattivato" +
+ "\x02Il tunnel %[1]s è stato disattivato.\x02Errore tunnel di WireGuard" +
+ "\x02WireGuard: %[1]s\x02Stato: %[1]s\x02Indirizzi: %[1]s\x02Un aggiornam" +
+ "ento è disponibile!\x02Aggiornamento di WireGuard disponibile\x02Un aggi" +
+ "ornamento di WireGuard è disponibile. Ti consigliamo di aggiornare il pr" +
+ "ima possibile.\x02Tunnel\x02&Modifica\x02Aggiungi tunn&el vuoto...\x02Ag" +
+ "giungi tunnel\x02Rimuovi tunnel selezionati\x02Esporta tutti i tunnel in" +
+ " zip\x02Commu&ta\x02Esporta tutti i tunnel in &zip...\x02Modifica il tun" +
+ "nel &selezionato…\x02&Rimuovi i tunnel selezionati\x02nessun file di con" +
+ "figurazione trovato\x02Impossibile importare la configurazione seleziona" +
+ "ta: %[1]v\x02Impossibile enumerare i tunnel esistenti: %[1]v\x02Un altro" +
+ " tunnel esiste già con il nome ‘%[1]s‘\x02Impossibile importare la confi" +
+ "gurazione: %[1]v\x02Tunnel importati\x14\x01\x81\x01\x00\x02\x17\x02%[1]" +
+ "d tunnel importato\x00\x17\x02%[1]d tunnel importati\x14\x02\x80\x01\x02" +
+ " \x02%[1]d de %[2]d tunnel importato\x00 \x02%[1]d di %[2]d tunnel impor" +
+ "tati\x02Impossibile creare il tunnel\x14\x01\x81\x01\x00\x02\x15\x02Elim" +
+ "ina %[1]d tunnel\x00\x15\x02Elimina %[1]d tunnel\x14\x01\x81\x01\x00\x02" +
+ ",\x02Sei sicuro di voler eliminare %[1]d tunnel?\x00,\x02Sei sicuro di v" +
+ "oler eliminare %[1]d tunnel?\x02Elimina tunnel ‘%[1]s‘\x02Sei sicuro di " +
+ "voler eliminare il tunnel ‘%[1]s‘?\x02%[1]s Non è possibile annullare qu" +
+ "esta azione.\x02Impossibile eliminare il tunnel\x02Non è stato possibile" +
+ " rimuovere un tunnel: %[1]s\x02Impossibile eliminare i tunnel\x14\x01" +
+ "\x81\x01\x00\x02/\x02Non è stato possibile eliminare %[1]d tunnel.\x00/" +
+ "\x02Non è stato possibile eliminare %[1]d tunnel.\x02File di configurazi" +
+ "one (*.zip, *.conf)|*.zip;*.conf|Tutti i file (*.*)|*.*\x02Importa tunne" +
+ "l da file\x02File di configurazione ZIP (*.zip)|*.zip\x02Esporta tunnel " +
+ "in zip\x02%[1]s (versione non firmata, nessun aggiornamento)\x02Impossib" +
+ "ile uscire dal servizio a causa di: %[1]v. Potresti voler interrompere W" +
+ "ireGuard dal gestore dei servizi.\x02Stato: in attesa dell'utente\x02Sta" +
+ "to: in attesa del servizio di aggiornamento"
-var jaIndex = []uint32{ // 181 elements
+var jaIndex = []uint32{ // 278 elements
// Entry 0 - 1F
0x00000000, 0x0000000a, 0x0000005b, 0x00000075,
- 0x0000009a, 0x000000e6, 0x000000e6, 0x00000124,
- 0x0000017b, 0x000001fe, 0x00000253, 0x00000257,
- 0x0000027f, 0x00000290, 0x000002a1, 0x000002b5,
- 0x000002c6, 0x000002d7, 0x000002e1, 0x000002e9,
- 0x000002f6, 0x00000303, 0x00000310, 0x0000031d,
- 0x0000032a, 0x00000344, 0x00000378, 0x000003a6,
- 0x000003ce, 0x000003ff, 0x0000040d, 0x00000426,
+ 0x0000009a, 0x000000e6, 0x00000140, 0x0000017e,
+ 0x000001d5, 0x00000258, 0x0000025c, 0x00000284,
+ 0x00000295, 0x000002a6, 0x000002ba, 0x000002cb,
+ 0x000002dc, 0x000002e6, 0x000002ee, 0x000002fb,
+ 0x00000308, 0x00000315, 0x00000322, 0x0000032f,
+ 0x00000349, 0x0000037d, 0x000003ab, 0x000003d3,
+ 0x000003e1, 0x000003fa, 0x00000425, 0x00000439,
// Entry 20 - 3F
- 0x00000451, 0x00000465, 0x00000497, 0x000004ea,
- 0x0000050e, 0x0000052d, 0x00000558, 0x0000058f,
- 0x000005c0, 0x000005f5, 0x00000625, 0x0000065c,
- 0x0000066b, 0x0000069c, 0x000006d0, 0x00000703,
- 0x00000746, 0x00000774, 0x00000777, 0x00000779,
- 0x00000790, 0x000007a7, 0x000007a7, 0x000007b1,
- 0x000007cd, 0x000007d5, 0x000007e3, 0x000007f1,
- 0x000007fc, 0x00000813, 0x00000818, 0x00000826,
+ 0x0000048c, 0x000004b0, 0x000004cf, 0x000004de,
+ 0x0000050f, 0x00000543, 0x00000546, 0x00000548,
+ 0x0000055f, 0x00000576, 0x00000580, 0x0000059c,
+ 0x000005a4, 0x000005b2, 0x000005c0, 0x000005cb,
+ 0x000005e2, 0x000005e7, 0x000005f5, 0x00000604,
+ 0x00000615, 0x00000622, 0x00000639, 0x00000659,
+ 0x00000679, 0x00000680, 0x0000068d, 0x0000069d,
+ 0x000006a4, 0x000006b2, 0x000006c6, 0x000006e3,
// Entry 40 - 5F
- 0x00000835, 0x00000835, 0x00000846, 0x00000853,
- 0x0000086a, 0x0000088a, 0x000008aa, 0x000008b2,
- 0x000008b2, 0x000008b9, 0x000008e1, 0x00000912,
- 0x00000940, 0x0000096e, 0x0000098e, 0x00000995,
- 0x000009b1, 0x000009c7, 0x000009d3, 0x000009e2,
- 0x000009eb, 0x00000a44, 0x00000a44, 0x00000a4f,
- 0x00000a5f, 0x00000a6b, 0x00000a7b, 0x00000a94,
- 0x00000ac3, 0x00000af1, 0x00000b19, 0x00000b68,
+ 0x000006ea, 0x00000701, 0x0000072c, 0x00000749,
+ 0x0000075f, 0x00000794, 0x000007a9, 0x000007c3,
+ 0x00000828, 0x00000838, 0x0000086d, 0x0000087f,
+ 0x000008d4, 0x00000905, 0x00000937, 0x00000962,
+ 0x00000999, 0x000009ca, 0x000009ff, 0x00000a2f,
+ 0x00000a66, 0x00000a99, 0x00000adc, 0x00000b0a,
+ 0x00000b1b, 0x00000b23, 0x00000b2a, 0x00000b32,
+ 0x00000b3b, 0x00000b45, 0x00000b67, 0x00000b6e,
// Entry 60 - 7F
- 0x00000b99, 0x00000bbe, 0x00000c10, 0x00000c17,
- 0x00000c24, 0x00000c2b, 0x00000c38, 0x00000c48,
- 0x00000c4f, 0x00000c5d, 0x00000c71, 0x00000c8e,
- 0x00000c95, 0x00000cac, 0x00000cf6, 0x00000d21,
- 0x00000d3e, 0x00000d54, 0x00000d89, 0x00000d9e,
- 0x00000db8, 0x00000dfa, 0x00000e15, 0x00000e24,
- 0x00000e39, 0x00000e56, 0x00000e8e, 0x00000e99,
- 0x00000eb3, 0x00000ee5, 0x00000eff, 0x00000f31,
+ 0x00000b96, 0x00000bc7, 0x00000bf5, 0x00000c23,
+ 0x00000c43, 0x00000c4a, 0x00000c66, 0x00000c7c,
+ 0x00000c88, 0x00000c97, 0x00000ca0, 0x00000cf9,
+ 0x00000d04, 0x00000d14, 0x00000d20, 0x00000d30,
+ 0x00000d49, 0x00000d78, 0x00000da6, 0x00000dce,
+ 0x00000e1d, 0x00000e4e, 0x00000e73, 0x00000ec5,
+ 0x00000ecc, 0x00000ed9, 0x00000f23, 0x00000f3d,
+ 0x00000f7f, 0x00000f9a, 0x00000fa9, 0x00000fbe,
// Entry 80 - 9F
- 0x00000f51, 0x00000f62, 0x00000f70, 0x00000f70,
- 0x00000f8f, 0x00000fb8, 0x00001020, 0x0000102d,
- 0x00001038, 0x0000105b, 0x00001071, 0x00001093,
- 0x000010c7, 0x000010d8, 0x00001113, 0x0000113c,
- 0x00001162, 0x00001162, 0x000011af, 0x000011ed,
- 0x00001239, 0x00001271, 0x00001296, 0x000012ce,
- 0x00001312, 0x00001337, 0x0000135a, 0x00001396,
- 0x000013b9, 0x000013f4, 0x00001425, 0x0000144a,
+ 0x00000fdb, 0x00001013, 0x0000101e, 0x0000102d,
+ 0x00001047, 0x00001079, 0x00001093, 0x000010c5,
+ 0x000010e5, 0x000010f6, 0x00001104, 0x00001118,
+ 0x00001137, 0x00001160, 0x000011c8, 0x000011d5,
+ 0x000011e0, 0x00001203, 0x00001219, 0x0000123b,
+ 0x0000126f, 0x00001280, 0x000012bb, 0x000012e4,
+ 0x0000130a, 0x00001335, 0x00001382, 0x000013c0,
+ 0x0000140c, 0x00001444, 0x00001469, 0x000014a1,
// Entry A0 - BF
- 0x0000147f, 0x000014a4, 0x000014df, 0x00001532,
- 0x00001563, 0x0000158d, 0x000015b5, 0x000015eb,
- 0x00001605, 0x00001689, 0x000016ee, 0x00001718,
- 0x00001728, 0x0000175b, 0x00001790, 0x000017a2,
- 0x000017a2, 0x000017a2, 0x000017a2, 0x000017a2,
- 0x000017a2,
-} // Size: 748 bytes
+ 0x000014e5, 0x0000150a, 0x0000152d, 0x00001569,
+ 0x0000158c, 0x000015c7, 0x000015f8, 0x0000161d,
+ 0x00001652, 0x00001677, 0x000016b2, 0x00001705,
+ 0x00001736, 0x00001760, 0x00001788, 0x000017be,
+ 0x00001842, 0x0000186c, 0x0000189f, 0x0000189f,
+ 0x0000189f, 0x0000189f, 0x0000189f, 0x0000189f,
+ 0x0000189f, 0x0000189f, 0x0000189f, 0x0000189f,
+ 0x0000189f, 0x0000189f, 0x0000189f, 0x0000189f,
+ // Entry C0 - DF
+ 0x0000189f, 0x0000189f, 0x0000189f, 0x0000189f,
+ 0x0000189f, 0x0000189f, 0x0000189f, 0x0000189f,
+ 0x0000189f, 0x0000189f, 0x0000189f, 0x0000189f,
+ 0x0000189f, 0x0000189f, 0x0000189f, 0x0000189f,
+ 0x0000189f, 0x0000189f, 0x0000189f, 0x0000189f,
+ 0x0000189f, 0x0000189f, 0x0000189f, 0x0000189f,
+ 0x0000189f, 0x0000189f, 0x0000189f, 0x0000189f,
+ 0x0000189f, 0x0000189f, 0x0000189f, 0x0000189f,
+ // Entry E0 - FF
+ 0x0000189f, 0x0000189f, 0x0000189f, 0x0000189f,
+ 0x0000189f, 0x0000189f, 0x0000189f, 0x0000189f,
+ 0x0000189f, 0x0000189f, 0x0000189f, 0x0000189f,
+ 0x0000189f, 0x0000189f, 0x0000189f, 0x0000189f,
+ 0x0000189f, 0x0000189f, 0x0000189f, 0x0000189f,
+ 0x0000189f, 0x0000189f, 0x0000189f, 0x0000189f,
+ 0x0000189f, 0x0000189f, 0x0000189f, 0x0000189f,
+ 0x0000189f, 0x0000189f, 0x0000189f, 0x0000189f,
+ // Entry 100 - 11F
+ 0x0000189f, 0x0000189f, 0x0000189f, 0x0000189f,
+ 0x0000189f, 0x0000189f, 0x0000189f, 0x0000189f,
+ 0x0000189f, 0x0000189f, 0x0000189f, 0x0000189f,
+ 0x0000189f, 0x0000189f, 0x0000189f, 0x0000189f,
+ 0x0000189f, 0x0000189f, 0x0000189f, 0x0000189f,
+ 0x0000189f, 0x0000189f,
+} // Size: 1136 bytes
-const jaData string = "" + // Size: 6050 bytes
+const jaData string = "" + // Size: 6303 bytes
"\x02エラー\x02(引数なし): 管理者権限でmanagerサービスをインストールする\x02使い方: %[1]s [\x0a%[2]s]" +
- "\x02コマンドラインオプション\x02プロセスがWOW64下で動作しているか確認できません: %[1]v\x02現在のプロセスのトークンを開け" +
- "ません: %[1]v\x02WireGuard は組み込みの %[1]s グループのメンバーだけが使えます。\x02WireGuard は実" +
- "行中ですが、UI画面は組み込みの %[1]s グループのデスクトップからしか開けません。\x02WireGuard システムトレイアイコンは" +
- "30秒後に非表示になります。\x02今\x02システム時刻が巻き戻った!\x14\x01\x81\x01\x00\x00\x0a\x02%[1]" +
- "d 年\x14\x01\x81\x01\x00\x00\x0a\x02%[1]d 日\x14\x01\x81\x01\x00\x00\x0d" +
- "\x02%[1]d 時間\x14\x01\x81\x01\x00\x00\x0a\x02%[1]d 分\x14\x01\x81\x01\x00" +
- "\x00\x0a\x02%[1]d 秒\x02%[1]s 前\x02%[1]d B\x02%.2[1]f\u00a0KiB\x02%.2[1]f" +
- "\u00a0MiB\x02%.2[1]f\u00a0GiB\x02%.2[1]f\u00a0TiB\x02%[1]s: %[2]q\x02無効な" +
- " IP アドレス\x02無効なネットワークプレフィックス長\x02エンドポイントのポート指定なし\x02無効なエンドポイントホスト\x02カッコ" +
- "内は IPv6 アドレスが入ります\x02無効な MTU\x02無効なポート番号\x02無効な持続的キープアライブ値\x02不正な鍵: %[" +
- "1]v\x02鍵は 32 バイトでなければなりません\x02数値は0から2の64乗-1の範囲内の値でなければなりません: %[1]v\x021行" +
- "にカンマが2つあります\x02トンネル名が不正です\x02行がセクション内にありません\x02設定項目にイコール(=)セパレータがない" +
- "\x02キー項目に対応する値がありません\x02無効な [Interface] セクションのキー項目\x02無効な [Peer] セクションのキ" +
- "ー項目\x02インターフェースには秘密鍵が必須です\x02[指定なし]\x02すべてのピアには公開鍵が必須です\x02設定の読込中にエラーが" +
- "発生しました\x02無効な Interface セクションのキー項目\x02プロトコルバージョンは 1 でなければなりません\x02無効な " +
- "Peer セクションのキー項目\x02, \x02 \x02WireGuard について\x02WireGuard ロゴ画像\x02閉じる" +
- "\x02♥ 寄付のお願い!(&D)\x02状態:\x02無効化(&D)\x02有効化(&A)\x02公開鍵:\x02待受ポート番号:\x02MT" +
- "U:\x02アドレス:\x02DNS サーバ:\x02事前共有鍵:\x02Allowed IPs:\x02エンドポイント:\x02持続的キープア" +
- "ライブ:\x02直近のハンドシェイク:\x02転送:\x02有効\x02%[1]s 受信済み、%[2]s 送信済み\x02トンネルの状態取得" +
- "に失敗しました\x02トンネルの有効化に失敗しました\x02トンネルの無効化に失敗しました\x02インターフェース: %[1]s\x02ピア" +
- "\x02トンネルの新規作成\x02トンネルの編集\x02名前(&N):\x02公開鍵(&P):\x02(不明)\x02トンネルを通らないトラフィ" +
- "ックのブロック(キルスイッチ)(&B)\x02保存(&S)\x02キャンセル\x02設定(&C):\x02無効な名前\x02名前は必須です。" +
- "\x02トンネル名 ‘%[1]s’ は不正です。\x02既存のトンネルを表示できません\x02トンネルはすでに存在します\x02‘%[1]s’ " +
- "という名前の別のトンネルがすでに存在します。\x02新しい設定を作成できませんでした\x02ファイルの書き込みに失敗\x02ファイル ‘%[" +
- "1]s’ はすでに存在します。\x0a\x0a上書きしますか?\x02有効\x02有効化中\x02無効\x02無効化中\x02不明な状態\x02" +
- "ログ\x02コピー(&C)\x02すべて選択(&A)\x02ファイルに保存…(&S)\x02時刻\x02ログ メッセージ\x02テキストファ" +
- "イル (*.txt)|*.txt|すべてのファイル (*.*)|*.*\x02ログをファイルにエクスポート\x02WireGuardについて" +
- "…(&A)\x02トンネルエラー\x02%[1]s\x0a\x0a詳細はログを参照してください。\x02%[1]s (更新あり)\x02Wi" +
- "reGuard 検出エラー\x02WireGuard ウィンドウが表示できませんでした: %[1]v\x02WireGuard: 無効化済み" +
- "\x02状態: 不明\x02アドレス: なし\x02トンネルの管理…(&M)\x02トンネルをファイルからインポート…(&I)\x02終了(&X" +
- ")\x02WireGuard 有効化済み\x02トンネル %[1]s は有効になりました。\x02WireGuard 無効化済み\x02トンネル" +
- " %[1]s は無効になりました。\x02WireGuard トンネルエラー\x02WireGuard: %[1]s\x02状態: %[1]s" +
- "\x02更新が利用できます!\x02WireGuard の更新が利用可能です\x02WireGuard の更新が利用可能になりました。できるだけ" +
- "早く更新してください。\x02トンネル\x02編集(&E)\x02空のトンネルを追加…(&E)\x02トンネルの追加\x02選択したトンネル" +
- "の削除\x02すべてのトンネルをzipにエクスポート\x02切り替え(&T)\x02すべてのトンネルをzipにエクスポート…(&Z)\x02" +
- "選択したトンネルの編集…(&S)\x02選択したトンネルの削除(&R)\x02選択したファイルからインポートできませんでした: %[1]v" +
- "\x02既存のトンネルを表示できませんでした: %[1]v\x02‘%[1]s’ という名前の別のトンネルがすでに存在します\x02設定をインポ" +
- "ートできませんでした: %[1]v\x02トンネルのインポート結果\x14\x01\x81\x01\x00\x001\x02%[1]d トン" +
- "ネルをインポートしました\x14\x02\x80\x01\x00>\x02%[2]d 中の %[1]d トンネルをインポートしました\x02" +
- "トンネルを作成できません\x14\x01\x81\x01\x00\x00\x1c\x02%[1]d トンネルを削除\x14\x01\x81" +
- "\x01\x00\x005\x02本当に %[1]d トンネルを削除しますか?\x02トンネル ‘%[1]s’ を削除\x02本当にトンネル ‘" +
- "%[1]s’ を削除しますか?\x02%[1]s この操作はもとに戻せません。\x02トンネルを削除できません\x02トンネルを削除できませんで" +
- "した: %[1]s\x02トンネルを削除できません\x14\x01\x81\x01\x00\x004\x02%[1]d トンネルを削除できま" +
- "せんでした\x02設定ファイル (*.zip, *.conf)|*.zip;*.conf|すべてのファイル (*.*)|*.*\x02ファイ" +
- "ルからトンネルをインポート\x02ZIP形式設定ファイル (*.zip)|*.zip\x02トンネルをZIPにエクスポート\x02%[1]s" +
- " (未署名のビルド、更新の提供なし)\x02WireGuard 終了エラー\x02%[1]v のためサービスを終了できませんでした。サービスマネ" +
- "ージャから WireGuard を停止できます。\x02WireGuard の更新が利用可能です。速やかに更新することを強く推奨します。" +
- "\x02状態: ユーザーからの応答待ち\x02今すぐ更新\x02状態: アップデータサービスを待機中\x02エラー: %[1]v。再度実行してく" +
- "ださい。\x02状態: 完了!"
+ "\x02コマンドラインオプション\x02プロセスがWOW64下で動作しているか確認できません: %[1]v\x02このコンピュータではネイティブ" +
+ "版の WireGuard を使ってください。\x02現在のプロセスのトークンを開けません: %[1]v\x02WireGuard は組み込み" +
+ "の %[1]s グループのメンバーだけが使えます。\x02WireGuard は実行中ですが、UI画面は組み込みの %[1]s グループのデ" +
+ "スクトップからしか開けません。\x02今\x02システム時刻が巻き戻った!\x14\x01\x81\x01\x00\x00\x0a\x02%" +
+ "[1]d 年\x14\x01\x81\x01\x00\x00\x0a\x02%[1]d 日\x14\x01\x81\x01\x00\x00" +
+ "\x0d\x02%[1]d 時間\x14\x01\x81\x01\x00\x00\x0a\x02%[1]d 分\x14\x01\x81\x01" +
+ "\x00\x00\x0a\x02%[1]d 秒\x02%[1]s 前\x02%[1]d B\x02%.2[1]f\u00a0KiB\x02%.2" +
+ "[1]f\u00a0MiB\x02%.2[1]f\u00a0GiB\x02%.2[1]f\u00a0TiB\x02%[1]s: %[2]q" +
+ "\x02無効な IP アドレス\x02無効なネットワークプレフィックス長\x02エンドポイントのポート指定なし\x02無効なエンドポイントホスト" +
+ "\x02無効な MTU\x02無効なポート番号\x02無効な持続的キープアライブ値\x02不正な鍵: %[1]v\x02数値は0から2の64乗-" +
+ "1の範囲内の値でなければなりません: %[1]v\x021行にカンマが2つあります\x02トンネル名が不正です\x02[指定なし]\x02すべて" +
+ "のピアには公開鍵が必須です\x02設定の読込中にエラーが発生しました\x02, \x02 \x02WireGuard について\x02Wir" +
+ "eGuard ロゴ画像\x02閉じる\x02♥ 寄付のお願い!(&D)\x02状態:\x02無効化(&D)\x02有効化(&A)\x02公開鍵:" +
+ "\x02待受ポート番号:\x02MTU:\x02アドレス:\x02DNS サーバ:\x02事前共有鍵:\x02Allowed IPs:\x02エ" +
+ "ンドポイント:\x02持続的キープアライブ:\x02直近のハンドシェイク:\x02無効\x02無効化中\x02不明な状態\x02ログ\x02" +
+ "コピー(&C)\x02すべて選択(&A)\x02ファイルに保存…(&S)\x02時刻\x02ログ メッセージ\x02ログをファイルにエクスポ" +
+ "ート\x02WireGuardについて…(&A)\x02トンネルエラー\x02%[1]s\x0a\x0a詳細はログを参照してください。" +
+ "\x02%[1]s (更新あり)\x02WireGuard 終了エラー\x02WireGuard の更新が利用可能です。速やかに更新することを強" +
+ "く推奨します。\x02今すぐ更新\x02エラー: %[1]v。再度実行してください。\x02状態: 完了!\x02WireGuard システ" +
+ "ムトレイアイコンは30秒後に非表示になります。\x02カッコ内は IPv6 アドレスが入ります\x02鍵は 32 バイトでなければなりません" +
+ "\x02行がセクション内にありません\x02設定項目にイコール(=)セパレータがない\x02キー項目に対応する値がありません\x02無効な [I" +
+ "nterface] セクションのキー項目\x02無効な [Peer] セクションのキー項目\x02インターフェースには秘密鍵が必須です\x02無" +
+ "効な Interface セクションのキー項目\x02プロトコルバージョンは 1 でなければなりません\x02無効な Peer セクションの" +
+ "キー項目\x02スクリプト:\x02転送:\x02pre-up\x02post-up\x02pre-down\x02post-down" +
+ "\x02ポリシーにより無効です\x02有効\x02%[1]s 受信済み、%[2]s 送信済み\x02トンネルの状態取得に失敗しました\x02トン" +
+ "ネルの有効化に失敗しました\x02トンネルの無効化に失敗しました\x02インターフェース: %[1]s\x02ピア\x02トンネルの新規作成" +
+ "\x02トンネルの編集\x02名前(&N):\x02公開鍵(&P):\x02(不明)\x02トンネルを通らないトラフィックのブロック(キルスイッ" +
+ "チ)(&B)\x02保存(&S)\x02キャンセル\x02設定(&C):\x02無効な名前\x02名前は必須です。\x02トンネル名 ‘%[" +
+ "1]s’ は不正です。\x02既存のトンネルを表示できません\x02トンネルはすでに存在します\x02‘%[1]s’ という名前の別のトンネルが" +
+ "すでに存在します。\x02新しい設定を作成できませんでした\x02ファイルの書き込みに失敗\x02ファイル ‘%[1]s’ はすでに存在しま" +
+ "す。\x0a\x0a上書きしますか?\x02有効\x02有効化中\x02テキストファイル (*.txt)|*.txt|すべてのファイル (*" +
+ ".*)|*.*\x02WireGuard 検出エラー\x02WireGuard ウィンドウが表示できませんでした: %[1]v\x02WireG" +
+ "uard: 無効化済み\x02状態: 不明\x02アドレス: なし\x02トンネルの管理…(&M)\x02トンネルをファイルからインポート…(&" +
+ "I)\x02終了(&X)\x02& トンネル\x02WireGuard 有効化済み\x02トンネル %[1]s は有効になりました。\x02Wi" +
+ "reGuard 無効化済み\x02トンネル %[1]s は無効になりました。\x02WireGuard トンネルエラー\x02WireGuard" +
+ ": %[1]s\x02状態: %[1]s\x02アドレス: %[1]s\x02更新が利用できます!\x02WireGuard の更新が利用可能で" +
+ "す\x02WireGuard の更新が利用可能になりました。できるだけ早く更新してください。\x02トンネル\x02編集(&E)\x02空の" +
+ "トンネルを追加…(&E)\x02トンネルの追加\x02選択したトンネルの削除\x02すべてのトンネルをzipにエクスポート\x02切り替え(" +
+ "&T)\x02すべてのトンネルをzipにエクスポート…(&Z)\x02選択したトンネルの編集…(&S)\x02選択したトンネルの削除(&R)" +
+ "\x02設定ファイルが見つかりません\x02選択したファイルからインポートできませんでした: %[1]v\x02既存のトンネルを表示できませんで" +
+ "した: %[1]v\x02‘%[1]s’ という名前の別のトンネルがすでに存在します\x02設定をインポートできませんでした: %[1]v" +
+ "\x02トンネルのインポート結果\x14\x01\x81\x01\x00\x001\x02%[1]d トンネルをインポートしました\x14" +
+ "\x02\x80\x01\x00>\x02%[2]d 中の %[1]d トンネルをインポートしました\x02トンネルを作成できません\x14" +
+ "\x01\x81\x01\x00\x00\x1c\x02%[1]d トンネルを削除\x14\x01\x81\x01\x00\x005\x02本当" +
+ "に %[1]d トンネルを削除しますか?\x02トンネル ‘%[1]s’ を削除\x02本当にトンネル ‘%[1]s’ を削除しますか?" +
+ "\x02%[1]s この操作はもとに戻せません。\x02トンネルを削除できません\x02トンネルを削除できませんでした: %[1]s\x02トン" +
+ "ネルを削除できません\x14\x01\x81\x01\x00\x004\x02%[1]d トンネルを削除できませんでした\x02設定ファイル" +
+ " (*.zip, *.conf)|*.zip;*.conf|すべてのファイル (*.*)|*.*\x02ファイルからトンネルをインポート\x02" +
+ "ZIP形式設定ファイル (*.zip)|*.zip\x02トンネルをZIPにエクスポート\x02%[1]s (未署名のビルド、更新の提供なし)" +
+ "\x02%[1]v のためサービスを終了できませんでした。サービスマネージャから WireGuard を停止できます。\x02状態: ユーザーか" +
+ "らの応答待ち\x02状態: アップデータサービスを待機中"
-var pa_INIndex = []uint32{ // 181 elements
+var koIndex = []uint32{ // 278 elements
+ // Entry 0 - 1F
+ 0x00000000, 0x00000007, 0x00000007, 0x00000007,
+ 0x00000007, 0x00000007, 0x00000007, 0x00000007,
+ 0x00000007, 0x00000007, 0x00000007, 0x00000007,
+ 0x00000007, 0x00000007, 0x00000007, 0x00000007,
+ 0x00000007, 0x00000007, 0x00000007, 0x00000007,
+ 0x00000007, 0x00000007, 0x00000007, 0x00000007,
+ 0x00000007, 0x00000007, 0x00000007, 0x00000007,
+ 0x00000007, 0x00000007, 0x00000007, 0x00000007,
+ // Entry 20 - 3F
+ 0x00000007, 0x00000007, 0x00000007, 0x00000007,
+ 0x00000007, 0x00000007, 0x00000007, 0x00000007,
+ 0x00000007, 0x00000007, 0x00000007, 0x00000007,
+ 0x00000007, 0x00000007, 0x00000007, 0x00000007,
+ 0x00000007, 0x00000007, 0x00000007, 0x00000007,
+ 0x00000007, 0x00000007, 0x00000007, 0x00000007,
+ 0x00000007, 0x00000007, 0x00000007, 0x00000007,
+ 0x00000007, 0x00000007, 0x00000007, 0x00000007,
+ // Entry 40 - 5F
+ 0x00000007, 0x00000007, 0x00000007, 0x00000007,
+ 0x00000007, 0x00000007, 0x00000007, 0x00000007,
+ 0x00000007, 0x00000007, 0x00000007, 0x00000007,
+ 0x00000007, 0x00000007, 0x00000007, 0x00000007,
+ 0x00000007, 0x00000007, 0x00000007, 0x00000007,
+ 0x00000007, 0x00000007, 0x00000007, 0x00000007,
+ 0x00000007, 0x00000007, 0x00000007, 0x00000007,
+ 0x00000007, 0x00000007, 0x00000007, 0x00000007,
+ // Entry 60 - 7F
+ 0x00000007, 0x00000007, 0x00000007, 0x00000007,
+ 0x00000007, 0x00000007, 0x00000007, 0x00000007,
+ 0x00000007, 0x00000007, 0x00000007, 0x00000007,
+ 0x00000007, 0x00000007, 0x00000007, 0x00000007,
+ 0x00000007, 0x00000007, 0x00000007, 0x00000007,
+ 0x00000007, 0x00000007, 0x00000007, 0x00000007,
+ 0x00000007, 0x00000007, 0x00000007, 0x00000007,
+ 0x00000007, 0x00000007, 0x00000007, 0x00000007,
+ // Entry 80 - 9F
+ 0x00000007, 0x00000007, 0x00000007, 0x00000007,
+ 0x00000007, 0x00000007, 0x00000007, 0x00000007,
+ 0x00000007, 0x00000007, 0x00000007, 0x00000007,
+ 0x00000007, 0x00000007, 0x00000007, 0x00000007,
+ 0x00000007, 0x00000007, 0x00000007, 0x00000007,
+ 0x00000007, 0x00000007, 0x00000007, 0x00000007,
+ 0x00000007, 0x00000007, 0x00000007, 0x00000007,
+ 0x00000007, 0x00000007, 0x00000007, 0x00000007,
+ // Entry A0 - BF
+ 0x00000007, 0x00000007, 0x00000007, 0x00000007,
+ 0x00000007, 0x00000007, 0x00000007, 0x00000007,
+ 0x00000007, 0x00000007, 0x00000007, 0x00000007,
+ 0x00000007, 0x00000007, 0x00000007, 0x00000007,
+ 0x00000007, 0x00000007, 0x00000007, 0x00000007,
+ 0x00000007, 0x00000007, 0x00000007, 0x00000007,
+ 0x00000007, 0x00000007, 0x00000007, 0x00000007,
+ 0x00000007, 0x00000007, 0x00000007, 0x00000007,
+ // Entry C0 - DF
+ 0x00000007, 0x00000007, 0x00000007, 0x00000007,
+ 0x00000007, 0x00000007, 0x00000007, 0x00000007,
+ 0x00000007, 0x00000007, 0x00000007, 0x00000007,
+ 0x00000007, 0x00000007, 0x00000007, 0x00000007,
+ 0x00000007, 0x00000007, 0x00000007, 0x00000007,
+ 0x00000007, 0x00000007, 0x00000007, 0x00000007,
+ 0x00000007, 0x00000007, 0x00000007, 0x00000007,
+ 0x00000007, 0x00000007, 0x00000007, 0x00000007,
+ // Entry E0 - FF
+ 0x00000007, 0x00000007, 0x00000007, 0x00000007,
+ 0x00000007, 0x00000007, 0x00000007, 0x00000007,
+ 0x00000007, 0x00000007, 0x00000007, 0x00000007,
+ 0x00000007, 0x00000007, 0x00000007, 0x00000007,
+ 0x00000007, 0x00000007, 0x00000007, 0x00000007,
+ 0x00000007, 0x00000007, 0x00000007, 0x00000007,
+ 0x00000007, 0x00000007, 0x00000007, 0x00000007,
+ 0x00000007, 0x00000007, 0x00000007, 0x00000007,
+ // Entry 100 - 11F
+ 0x00000007, 0x00000007, 0x00000007, 0x00000007,
+ 0x00000007, 0x00000007, 0x00000007, 0x00000007,
+ 0x00000007, 0x00000007, 0x00000007, 0x00000007,
+ 0x00000007, 0x00000007, 0x00000007, 0x00000007,
+ 0x00000007, 0x00000007, 0x00000007, 0x00000007,
+ 0x00000007, 0x00000007,
+} // Size: 1136 bytes
+
+const koData string = "\x02오류"
+
+var pa_INIndex = []uint32{ // 278 elements
// Entry 0 - 1F
0x00000000, 0x00000010, 0x00000010, 0x00000030,
0x0000005d, 0x000000ea, 0x0000017f, 0x000001e6,
- 0x000002b4, 0x0000039c, 0x0000042d, 0x00000437,
- 0x00000479, 0x000004a2, 0x000004cb, 0x000004fa,
- 0x00000529, 0x0000055e, 0x00000577, 0x00000580,
- 0x0000058d, 0x0000059a, 0x000005a7, 0x000005b4,
- 0x000005c1, 0x000005ea, 0x0000062a, 0x00000671,
- 0x00000671, 0x00000671, 0x0000068f, 0x000006b6,
+ 0x000002b4, 0x0000039c, 0x000003a6, 0x000003e8,
+ 0x00000411, 0x0000043a, 0x00000469, 0x00000498,
+ 0x000004cd, 0x000004e6, 0x000004ef, 0x000004fc,
+ 0x00000509, 0x00000516, 0x00000523, 0x00000530,
+ 0x00000559, 0x00000599, 0x000005e0, 0x000005e0,
+ 0x000005fe, 0x00000625, 0x00000654, 0x00000685,
// Entry 20 - 3F
- 0x000006e5, 0x000006e5, 0x000006e5, 0x000006e5,
- 0x000006e5, 0x000006e5, 0x000006e5, 0x000006e5,
- 0x000006e5, 0x000006e5, 0x000006e5, 0x000006e5,
- 0x000006e5, 0x000006e5, 0x000006e5, 0x000006e5,
- 0x000006e5, 0x000006e5, 0x000006e8, 0x000006eb,
- 0x00000711, 0x00000711, 0x000007d7, 0x000007eb,
- 0x00000808, 0x00000819, 0x0000083e, 0x0000085c,
- 0x0000087d, 0x000008a5, 0x000008aa, 0x000008c1,
+ 0x000006ed, 0x0000072c, 0x00000765, 0x00000765,
+ 0x00000765, 0x00000765, 0x00000768, 0x0000076b,
+ 0x00000791, 0x00000791, 0x000007a5, 0x000007c2,
+ 0x000007d3, 0x000007f8, 0x00000816, 0x00000837,
+ 0x0000085f, 0x00000864, 0x0000087b, 0x0000088d,
+ 0x0000088d, 0x000008ae, 0x000008cc, 0x000008cc,
+ 0x000008cc, 0x000008e3, 0x00000922, 0x00000948,
+ 0x00000955, 0x00000970, 0x0000098e, 0x000009c5,
// Entry 40 - 5F
- 0x000008d3, 0x000008f0, 0x000008f0, 0x00000911,
- 0x0000092f, 0x0000092f, 0x0000092f, 0x00000946,
- 0x00000946, 0x0000095d, 0x00000984, 0x000009cf,
- 0x00000a11, 0x00000a5a, 0x00000a77, 0x00000a84,
- 0x00000aa8, 0x00000ac9, 0x00000ad8, 0x00000afd,
- 0x00000b15, 0x00000b15, 0x00000b15, 0x00000b2c,
- 0x00000b40, 0x00000b58, 0x00000b6f, 0x00000b96,
- 0x00000b96, 0x00000b96, 0x00000bd1, 0x00000c2f,
+ 0x000009d2, 0x000009ef, 0x00000a30, 0x00000a5d,
+ 0x00000a74, 0x00000aa8, 0x00000abc, 0x00000afe,
+ 0x00000bda, 0x00000c04, 0x00000c45, 0x00000c64,
+ 0x00000cf5, 0x00000cf5, 0x00000d6f, 0x00000dba,
+ 0x00000dba, 0x00000dba, 0x00000dba, 0x00000dba,
+ 0x00000dba, 0x00000dba, 0x00000dba, 0x00000dba,
+ 0x00000dd7, 0x00000dee, 0x00000dee, 0x00000dee,
+ 0x00000dee, 0x00000dee, 0x00000dee, 0x00000e05,
// Entry 60 - 7F
- 0x00000c80, 0x00000cbe, 0x00000d68, 0x00000d78,
- 0x00000db0, 0x00000dc7, 0x00000e06, 0x00000e2c,
- 0x00000e39, 0x00000e54, 0x00000e72, 0x00000ea9,
- 0x00000eb6, 0x00000ed3, 0x00000f37, 0x00000f78,
- 0x00000fa5, 0x00000fbc, 0x00000ff0, 0x00001004,
- 0x00001028, 0x00001028, 0x00001066, 0x0000108d,
- 0x000010be, 0x000010f9, 0x00001144, 0x00001155,
- 0x0000118b, 0x000011c9, 0x00001206, 0x0000124b,
+ 0x00000e2c, 0x00000e77, 0x00000eb9, 0x00000f02,
+ 0x00000f1f, 0x00000f2c, 0x00000f50, 0x00000f71,
+ 0x00000f80, 0x00000fa5, 0x00000fbd, 0x00001034,
+ 0x0000104b, 0x0000105f, 0x00001077, 0x0000108e,
+ 0x000010b5, 0x000010b5, 0x000010b5, 0x000010f0,
+ 0x0000114e, 0x0000119f, 0x000011dd, 0x00001287,
+ 0x00001297, 0x000012cf, 0x00001333, 0x00001357,
+ 0x00001357, 0x00001395, 0x000013bc, 0x000013ed,
// Entry 80 - 9F
- 0x0000127b, 0x0000129b, 0x000012b2, 0x000012d2,
- 0x000012fd, 0x00001340, 0x00001436, 0x00001446,
- 0x00001457, 0x00001482, 0x00001499, 0x000014d3,
- 0x00001534, 0x00001545, 0x000015a9, 0x000015d4,
- 0x00001612, 0x00001665, 0x00001665, 0x00001665,
- 0x00001665, 0x00001665, 0x0000169b, 0x0000169b,
- 0x0000169b, 0x000016cf, 0x000016cf, 0x000017a2,
- 0x000017cf, 0x00001837, 0x00001837, 0x0000186b,
+ 0x00001428, 0x00001473, 0x00001484, 0x00001492,
+ 0x000014c8, 0x00001506, 0x00001543, 0x00001588,
+ 0x000015b8, 0x000015d8, 0x000015ef, 0x0000160f,
+ 0x0000163a, 0x0000167d, 0x00001773, 0x00001783,
+ 0x00001794, 0x000017bf, 0x000017d6, 0x00001810,
+ 0x00001871, 0x00001882, 0x000018e6, 0x00001911,
+ 0x0000194f, 0x000019a2, 0x000019a2, 0x000019a2,
+ 0x00001a07, 0x00001a58, 0x00001a8e, 0x00001b03,
// Entry A0 - BF
- 0x0000186b, 0x0000186b, 0x0000186b, 0x000018e4,
- 0x00001928, 0x00001969, 0x00001969, 0x00001969,
- 0x00001969, 0x00001969, 0x00001969, 0x00001969,
- 0x00001993, 0x00001993, 0x00001993, 0x000019b2,
- 0x000019b2, 0x000019b2, 0x000019b2, 0x000019b2,
- 0x000019c0,
-} // Size: 748 bytes
+ 0x00001b03, 0x00001b37, 0x00001b80, 0x00001c53,
+ 0x00001c80, 0x00001ce8, 0x00001d50, 0x00001d84,
+ 0x00001dc6, 0x00001e00, 0x00001e00, 0x00001e79,
+ 0x00001ebd, 0x00001efe, 0x00001efe, 0x00001efe,
+ 0x00001fd2, 0x00002032, 0x0000209c, 0x0000209c,
+ 0x0000209c, 0x0000209c, 0x0000209c, 0x0000209c,
+ 0x0000209c, 0x0000209c, 0x0000209c, 0x0000209c,
+ 0x0000209c, 0x0000209c, 0x0000209c, 0x0000209c,
+ // Entry C0 - DF
+ 0x0000209c, 0x0000209c, 0x0000209c, 0x0000209c,
+ 0x0000209c, 0x0000209c, 0x0000209c, 0x0000209c,
+ 0x0000209c, 0x0000209c, 0x0000209c, 0x0000209c,
+ 0x0000209c, 0x0000209c, 0x0000209c, 0x0000209c,
+ 0x0000209c, 0x0000209c, 0x0000209c, 0x0000209c,
+ 0x0000209c, 0x0000209c, 0x0000209c, 0x0000209c,
+ 0x0000209c, 0x0000209c, 0x0000209c, 0x0000209c,
+ 0x0000209c, 0x0000209c, 0x0000209c, 0x0000209c,
+ // Entry E0 - FF
+ 0x0000209c, 0x0000209c, 0x0000209c, 0x0000209c,
+ 0x0000209c, 0x0000209c, 0x0000209c, 0x0000209c,
+ 0x0000209c, 0x0000209c, 0x0000209c, 0x0000209c,
+ 0x0000209c, 0x0000209c, 0x0000209c, 0x0000209c,
+ 0x0000209c, 0x0000209c, 0x0000209c, 0x0000209c,
+ 0x0000209c, 0x0000209c, 0x0000209c, 0x0000209c,
+ 0x0000209c, 0x0000209c, 0x0000209c, 0x0000209c,
+ 0x0000209c, 0x0000209c, 0x0000209c, 0x0000209c,
+ // Entry 100 - 11F
+ 0x0000209c, 0x0000209c, 0x0000209c, 0x0000209c,
+ 0x0000209c, 0x0000209c, 0x0000209c, 0x0000209c,
+ 0x0000209c, 0x0000209c, 0x0000209c, 0x0000209c,
+ 0x0000209c, 0x0000209c, 0x0000209c, 0x0000209c,
+ 0x0000209c, 0x0000209c, 0x0000209c, 0x0000209c,
+ 0x0000209c, 0x0000209c,
+} // Size: 1136 bytes
-const pa_INData string = "" + // Size: 6592 bytes
+const pa_INData string = "" + // Size: 8348 bytes
"\x02ਗ਼ਲਤੀ\x02ਵਰਤੋਂ: %[1]s [\x0a%[2]s]\x02ਕਮਾਂਡ ਲਾਈਨ ਚੋਣਾਂ\x02ਪਤਾ ਲਗਾਉਣ ਲ" +
"ਈ ਅਸਮਰੱਥ ਹੈ ਕਿ ਪਰੋਸੈਸ WOW64 ਅਧੀਨ ਚੱਲ ਰਿਹਾ ਹੈ: %[1]v\x02ਤੁਹਾਨੂੰ ਇਸ ਕੰਪਿ" +
"ਊਟਰ ਉੱਤੇ WireGuard ਦਾ ਮੂਲ ਵਰਜ਼ਨ ਵਰਤਣਾ ਚਾਹੀਦਾ ਹੈ।\x02ਮੌਜੂਦਾ ਪਰੋਸੈਸ ਟੋਕਨ " +
"ਖੋਲ੍ਹਣ ਲਈ ਅਸਮਰੱਥ: %[1]v\x02WireGuard ਨੂੰ ਸਿਰਫ਼ ਉਹੀ ਵਰਤੋਂਕਾਰ ਵਰਤ ਸਕਦੇ ਹ" +
"ਨ, ਜੋ ਕਿ ਪਹਿਲਾਂ ਮੌਜੂਦ %[1]s ਗਰੁੱਪ ਦੇ ਮੈਂਬਰ ਹਨ।\x02WireGuard ਚੱਲ ਰਿਹਾ ਹ" +
"ੈ, ਪਰ UI ਨੂੰ ਸਿਰਫ਼ ਪਹਿਲਾਂ ਮੌਜੂਦ %[1]s ਗਰੁੱਪ ਦੇ ਡੈਸਕਟਾਪ ਰਾਹੀਂ ਹੀ ਵਰਤਿਆ " +
- "ਜਾ ਸਕਦਾ ਹੈ।\x02WireGuard ਸਿਸਟਮ ਟਰੇ ਆਈਕਾਨ 30 ਸਕਿੰਟਾਂ ਬਾਅਦ ਦਿਖਾਈ ਨਹੀਂ ਦਿ" +
- "ੱਤਾ ਹੈ।\x02ਹੁਣ\x02ਸਿਸਟਮ ਘੜੀ ਪੁ਼ੱਠੀ ਮੋੜੀ ਗਈ!\x14\x01\x81\x01\x00\x02" +
- "\x10\x02%[1]d ਸਾਲ\x00\x10\x02%[1]d ਸਾਲ\x14\x01\x81\x01\x00\x02\x10\x02%[" +
- "1]d ਦਿਨ\x00\x10\x02%[1]d ਦਿਨ\x14\x01\x81\x01\x00\x02\x13\x02%[1]d ਘੰਟਾ" +
- "\x00\x13\x02%[1]d ਘੰਟੇ\x14\x01\x81\x01\x00\x02\x13\x02%[1]d ਮਿੰਟ\x00\x13" +
- "\x02%[1]d ਮਿੰਟ\x14\x01\x81\x01\x00\x02\x16\x02%[1]d ਸਕਿੰਟ\x00\x16\x02%[1" +
- "]d ਸਕਿੰਟ\x02%[1]s ਪਹਿਲਾਂ\x02%[1]d\u00a0B\x02%.2[1]f\u00a0KiB\x02%.2[1]f" +
- "\u00a0MiB\x02%.2[1]f\u00a0GiB\x02%.2[1]f\u00a0TiB\x02%[1]s: %[2]q\x02ਅਵੈ" +
- "ਧ IP ਸਿਰਨਾਵਾਂ\x02ਗਲਤ ਨੈੱਟਵਰਕ ਅਗੇਤਰ ਲੰਬਾਈ\x02ਐਂਡਪੁਆਇੰਟ ਤੋਂ ਪੋਰਟ ਗੁੰਮ ਹੈ" +
- "\x02ਗ਼ੈਰ-ਵਾਜਬ MTU\x02ਗ਼ੈਰ-ਵਾਜਬ ਪੋਰਟ\x02ਗ਼ੈਰ-ਵਾਜਬ persistent keepalive" +
- "\x02, \x02, \x02ਵਾਇਰਗਾਰਡ ਬਾਰੇ\x02ਐਪ ਦਾ ਵਰਜ਼ਨ: %[1]s\x0aਗੋ ਬੈਕਐਂਡ ਦਾ ਵਰਜ਼ਨ:" +
- " %[2]s\x0aਗੋ ਦਾ ਵਰਜ਼ਨ: %[3]s-%[4]s\x0aਓਪਰੇਟਿੰਗ ਸਿਸਟਮ: %[5]s\x0aਢਾਂਚਾ: %[6" +
- "]s\x02ਬੰਦ ਕਰੋ\x02♥ ਦਾਨ ਦਿਓ(&D)!\x02ਸਥਿਤੀ:\x02ਨਾ-ਸਰਗਰਮ ਕਰੋ(&D)\x02ਸਰਗਰਮ ਕ" +
- "ਰੋ(&A)\x02ਪਬਲਿਕ ਕੁੰਜੀ:\x02ਸੁਣਨ ਵਾਲੀ ਪੋਰਟ:\x02MTU:\x02ਸਿਰਨਾਵੇ:\x02DNS ਸ" +
- "ਰਵਰ:\x02ਸਕ੍ਰਿਪਟਾਂ:\x02ਮਨਜ਼ੂਰ ਕੀਤੇ IP:\x02ਐਂਡ-ਪੁਆਇੰਟ:\x02ਟਰਾਂਸਫਰ:\x02ਸਮਰ" +
- "ੱਥ ਹੈ\x02%[1]s ਮਿਲੇ, %[2]s ਭੇਜੇ\x02ਟਨਲ ਸਥਿਤੀ ਪਤਾ ਲਗਾਉਣ ਲਈ ਅਸਫ਼ਲ\x02ਟਨਲ" +
- " ਸਰਗਰਮ ਕਰਨ ਲਈ ਅਸਫ਼ਲ ਹੈ\x02ਟਨਲ ਨਾ-ਸਰਗਰਮ ਕਰਨ ਲਈ ਅਸਫ਼ਲ ਹੈ\x02ਇੰਟਰਫੇਸ: %[1]s" +
- "\x02ਪੀਅਰ\x02ਨਵੀਂ ਟਨਲ ਬਣਾਓ\x02ਟਨਲ ਨੂੰ ਸੋਧੋ\x02ਨਾਂ(&N):\x02ਪਬਲਿਕ ਕੁੰਜੀ(&P)" +
- ":\x02(ਅਣਪਛਾਤਾ)\x02ਸੰਭਾਲੋ(&S)\x02ਰੱਦ ਕਰੋ\x02ਸੰਰਚਨਾ(&C):\x02ਅਯੋਗ ਨਾਂ\x02ਨਾ" +
- "ਂ ਚਾਹੀਦਾ ਹੈ।\x02ਟਨਲ ਪਹਿਲਾਂ ਹੀ ਮੌਜੂਦ ਹੈ\x02ਨਾਂ ‘%[1]s’ ਨਾਲ ਟਨਲ ਪਹਿਲਾਂ ਹ" +
- "ੀ ਮੌਜੂਦ ਹੈ।\x02ਨਵੀਂ ਸੰਰਚਨਾ ਬਣਾਉਣ ਲਈ ਅਸਮਰੱਥ ਹੈ\x02ਫ਼ਾਇਲ ਬਣਾਉਣ ਲਈ ਅਸਫ਼ਲ " +
- "ਹੈ\x02‘%[1]s’ ਫ਼ਾਇਲ ਪਹਿਲਾਂ ਹੀ ਮੌਜੂਦ ਹੈ।\x0a\x0aਕੀ ਤੁਸੀਂ ਇਸ ਉੱਤੇ ਲਿਖਣਾ " +
- "ਚਾਹੁੰਦੇ ਹੋ?\x02ਸਰਗਰਮ\x02ਸਰਗਰਮ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ\x02ਨਾ-ਸਰਗਰਮ\x02ਨਾ-ਸਰਗਰਮ " +
- "ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ\x02ਅਣਪਛਾਤੀ ਸਥਿਤੀ\x02ਲਾਗੂ\x02ਕਾਪੀ ਕਰੋ(&C)\x02ਸਾਰੇ ਚੁਣੋ(" +
- "&a)\x02ਫ਼ਾਇਲ ਵਿੱਚ ਸੰਭਾਲੋ(&S)…\x02ਸਮਾਂ\x02ਲਾਗ ਸੁਨੇਹਾ\x02ਲਿਖਤ ਫ਼ਾਇਲਾਂ (*.t" +
- "xt)|*.txt|ਸਾਰੀਆਂ ਫ਼ਾਇਲਾਂ (*.*)|*.*\x02ਲਾਗ ਫ਼ਾਇਲ ਵਿੱਚ ਬਰਾਮਦ ਕਰੋ\x02ਵਾਇਰਗਾ" +
- "ਰਡ ਬਾਰੇ(&A)…\x02ਟਨਲ ਗਲਤੀ\x02%[1]s\x0a\x0aPlease consult the log for mo" +
- "re information.\x02%[1]s (out of date)\x02WireGuard ਖੋਜ ਗ਼ਲਤੀ\x02ਵਾਇਰਗਾਰ" +
- "ਡ: ਨਾ-ਸਰਗਰਮ ਕੀਤਾ\x02ਸਥਿਤੀ: ਅਣਪਛਾਤੀ\x02ਸਿਰਨਾਵੇਂ: ਕੋਈ ਨਹੀਂ\x02ਟਨਲਾਂ ਦਾ ਇ" +
- "ੰਤਜ਼ਾਮ ਕਰੋ(&M)…\x02ਫ਼ਾਇਲ ਤੋਂ ਟਨਲਾਂ ਦਰਾਮਦ ਕਰੋ(&I)…\x02ਬਾਹਰ(&x)\x02ਵਾਇਰਗਾ" +
- "ਰਡ ਸਰਗਰਮ ਕੀਤਾ\x02%[1]s ਟਨਲ ਸਰਗਰਮ ਕੀਤੀ ਗਈ ਹੈ।\x02ਵਾਇਰਗਾਰਡ ਨਾ-ਸਰਗਰਮ ਕੀਤਾ" +
- "\x02%[1]s ਟਨਲ ਨਾ-ਸਰਗਰਮ ਕੀਤੀ ਗਈ ਹੈ।\x02ਵਾਇਰਗਾਰਡ ਟਨਲ ਗਲਤੀ\x02ਵਾਇਰਗਾਰਡ: %[1" +
- "]s\x02ਸਥਿਤੀ: %[1]s\x02ਸਿਰਨਾਵੇਂ: %[1]s\x02ਅੱਪਡੇਟ ਮੌਜੂਦ ਹੈ!\x02ਵਾਇਰਗਾਰਡ ਅੱ" +
- "ਪਡੇਟ ਮੌਜੂਦ ਹੈ\x02ਵਾਇਰਗਾਰਡ ਲਈ ਅੱਪਡੇਟ ਹੁਣ ਮੌਜੂਦ ਹੈ। ਜਿੰਨਾ ਛੇਤੀ ਹੋ ਸਕੇ ਤੁ" +
- "ਹਾਨੂੰ ਅੱਪਡੇਟ ਕਰਨ ਦੀ ਸਲਾਹ ਦਿੱਤੀ ਜਾਂਦੀ ਹੈ।\x02ਟਨਲਾਂ\x02ਸੋਧੋ(&E)\x02…ਖਾਲੀ" +
- " ਟਨਲ ਜੋੜੋ(&e)\x02ਟਨਲ ਜੋੜੋ\x02ਚੁਣੀਆਂ ਟਨਲਾਂ ਨੂੰ ਹਟਾਓ\x02ਸਾਰੀਆਂ ਟਨਲਾਂ ਨੂੰ ਜ਼" +
- "ਿੱਪ ਵਜੋਂ ਬਰਾਮਦ ਕਰੋ\x02ਪਲਟੋ(&T)\x02ਸਾਰੀਆਂ ਟਨਲਾਂ ਨੂੰ ਜ਼ਿੱਪ ਵਜੋਂ ਬਰਾਮਦ ਕਰੋ" +
- "…\x02ਚੁਣੀ ਟਨਲ ਸੋਧੋ(&s)…\x02ਚੁਣੀਆਂ ਟਨਲਾਂ ਨੂੰ ਹਟਾਓ(&R)\x02ਕੋਈ ਸੰਰਚਨਾ ਫ਼ਾ" +
- "ਇਲਾਂ ਨਹੀਂ ਲੱਭੀਆਂ\x02ਇੰਪੋਰਟ ਕੀਤੀਆਂ ਟਨਲਾਂ\x02ਟਨਲ ਬਣਾਉਣ ਲਈ ਅਸਮਰੱਥ\x14\x01" +
- "\x81\x01\x00\x02b\x02ਕੀ ਤੁਸੀਂ %[1]d ਟਨਲ ਨੂੰ ਹਟਾਉਣਾ ਚਾਹੁੰਦੇ ਹੋ?\x00h\x02ਕ" +
- "ੀ ਤੁਸੀਂ %[1]d ਟਨਲਾਂ ਨੂੰ ਹਟਾਉਣਾ ਚਾਹੁੰਦੇ ਹੋ?\x02‘%[1]s’ ਟਨਲ ਨੂੰ ਹਟਾਓ\x02" +
- "ਕੀ ਤੁਸੀਂ ‘%[1]s‘ ਟਨਲ ਨੂੰ ਹਟਾਉਣਾ ਚਾਹੁੰਦੇ ਹੋ?\x02ਟਨਲ ਹਟਾਉਣ ਲਈ ਅਸਮਰੱਥ\x02" +
- "ਸੰਰਚਨਾ ਫ਼ਾਇਲਾਂ (*.zip, *.conf)|*.zip;*.conf|ਸਾਰੀਆਂ ਫ਼ਾਇਲਾਂ (*.*)|*.*" +
- "\x02ਫ਼ਾਇਲ ਤੋਂ ਟਨਲਾਂ ਦਰਾਮਦ ਕਰੋ\x02ਸੰਰਚਨਾ ਜ਼ਿੱਪ ਫਾਇਲਾਂ (*.zip)|*.zip\x02ਹੁਣ" +
- "ੇ ਅੱਪਡੇਟ ਕਰੋ\x02ਸਥਿਤੀ: ਪੂਰਾ!\x02ਟਨਲ(&T)"
+ "ਜਾ ਸਕਦਾ ਹੈ।\x02ਹੁਣ\x02ਸਿਸਟਮ ਘੜੀ ਪੁ਼ੱਠੀ ਮੋੜੀ ਗਈ!\x14\x01\x81\x01\x00" +
+ "\x02\x10\x02%[1]d ਸਾਲ\x00\x10\x02%[1]d ਸਾਲ\x14\x01\x81\x01\x00\x02\x10" +
+ "\x02%[1]d ਦਿਨ\x00\x10\x02%[1]d ਦਿਨ\x14\x01\x81\x01\x00\x02\x13\x02%[1]d " +
+ "ਘੰਟਾ\x00\x13\x02%[1]d ਘੰਟੇ\x14\x01\x81\x01\x00\x02\x13\x02%[1]d ਮਿੰਟ" +
+ "\x00\x13\x02%[1]d ਮਿੰਟ\x14\x01\x81\x01\x00\x02\x16\x02%[1]d ਸਕਿੰਟ\x00" +
+ "\x16\x02%[1]d ਸਕਿੰਟ\x02%[1]s ਪਹਿਲਾਂ\x02%[1]d\u00a0B\x02%.2[1]f\u00a0KiB" +
+ "\x02%.2[1]f\u00a0MiB\x02%.2[1]f\u00a0GiB\x02%.2[1]f\u00a0TiB\x02%[1]s: %" +
+ "[2]q\x02ਅਵੈਧ IP ਸਿਰਨਾਵਾਂ\x02ਗਲਤ ਨੈੱਟਵਰਕ ਅਗੇਤਰ ਲੰਬਾਈ\x02ਐਂਡਪੁਆਇੰਟ ਤੋਂ ਪੋਰ" +
+ "ਟ ਗੁੰਮ ਹੈ\x02ਗ਼ੈਰ-ਵਾਜਬ MTU\x02ਗ਼ੈਰ-ਵਾਜਬ ਪੋਰਟ\x02ਗ਼ੈਰ-ਵਾਜਬ persistent k" +
+ "eepalive\x02ਗ਼ੈਰ-ਵਾਜਬ ਕੁੰਜੀ: %[1]v\x02ਨੰਬਰ 0 ਅਤੇ 2^64-1 ਦੇ ਵਿਚਾਲੇ ਹੋਣਾ ਚ" +
+ "ਾਹੀਦਾ ਹੈ: %[1]v\x02ਇੱਕ ਕਤਾਰ ਵਿੱਚ ਦੋ ਕੌਮੇ ਹਨ\x02ਟਨਲ ਦਾ ਨਾਂ ਠੀਕ ਨਹੀਂ ਹੈ" +
+ "\x02, \x02, \x02ਵਾਇਰਗਾਰਡ ਬਾਰੇ\x02ਬੰਦ ਕਰੋ\x02♥ ਦਾਨ ਦਿਓ(&D)!\x02ਸਥਿਤੀ:\x02" +
+ "ਨਾ-ਸਰਗਰਮ ਕਰੋ(&D)\x02ਸਰਗਰਮ ਕਰੋ(&A)\x02ਪਬਲਿਕ ਕੁੰਜੀ:\x02ਸੁਣਨ ਵਾਲੀ ਪੋਰਟ:" +
+ "\x02MTU:\x02ਸਿਰਨਾਵੇ:\x02DNS ਸਰਵਰ:\x02ਮਨਜ਼ੂਰ ਕੀਤੇ IP:\x02ਐਂਡ-ਪੁਆਇੰਟ:\x02ਨਾ" +
+ "-ਸਰਗਰਮ\x02ਨਾ-ਸਰਗਰਮ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ\x02ਅਣਪਛਾਤੀ ਸਥਿਤੀ\x02ਲਾਗੂ\x02ਕਾਪੀ ਕਰੋ(" +
+ "&C)\x02ਸਾਰੇ ਚੁਣੋ(&a)\x02ਫ਼ਾਇਲ ਵਿੱਚ ਸੰਭਾਲੋ(&S)…\x02ਸਮਾਂ\x02ਲਾਗ ਸੁਨੇਹਾ\x02" +
+ "ਲਾਗ ਫ਼ਾਇਲ ਵਿੱਚ ਬਰਾਮਦ ਕਰੋ\x02ਵਾਇਰਗਾਰਡ ਬਾਰੇ(&A)…\x02ਟਨਲ ਗਲਤੀ\x02%[1]s" +
+ "\x0a\x0aPlease consult the log for more information.\x02%[1]s (out of da" +
+ "te)\x02WireGuard ਤੋਂ ਬਾਹਰ ਜਾਣ ਲਈ ਗ਼ਲਤੀ\x02WireGuard ਲਈ ਅੱਪਡੇਟ ਮੌਜੂਦ ਹੈ। " +
+ "ਤੁਹਾਨੂੰ ਬਿਨਾਂ ਦੇਰ ਕੀਤਿਆਂ ਅੱਪਡੇਟ ਕਰਨ ਦੀ ਸਲਾਹ ਦਿੱਤੀ ਜਾਂਦੀ ਹੈ।\x02ਹੁਣੇ ਅੱ" +
+ "ਪਡੇਟ ਕਰੋ\x02ਗ਼ਲਤੀ: %[1]v। ਫੇਰ ਕੋਸ਼ਿਸ਼ ਕਰੋ।\x02ਸਥਿਤੀ: ਪੂਰਾ!\x02WireGuard " +
+ "ਸਿਸਟਮ ਟਰੇ ਆਈਕਾਨ 30 ਸਕਿੰਟਾਂ ਬਾਅਦ ਦਿਖਾਈ ਨਹੀਂ ਦਿੱਤਾ ਹੈ।\x02ਕੁੰਜੀਆਂ ਠੀਕ 32" +
+ " ਬਾਈਟ ਲਈ ਡੀਕੋਡ ਹੋਣੀਆਂ ਚਾਹੀਦੀਆਂ ਹਨ\x02ਭਾਗ ਵਿੱਚ ਲਾਈਨ ਹੋਣੀ ਚਾਹੀਦੀ ਹੈ\x02ਸਕ੍" +
+ "ਰਿਪਟਾਂ:\x02ਟਰਾਂਸਫਰ:\x02ਸਮਰੱਥ ਹੈ\x02%[1]s ਮਿਲੇ, %[2]s ਭੇਜੇ\x02ਟਨਲ ਸਥਿਤੀ" +
+ " ਪਤਾ ਲਗਾਉਣ ਲਈ ਅਸਫ਼ਲ\x02ਟਨਲ ਸਰਗਰਮ ਕਰਨ ਲਈ ਅਸਫ਼ਲ ਹੈ\x02ਟਨਲ ਨਾ-ਸਰਗਰਮ ਕਰਨ ਲਈ " +
+ "ਅਸਫ਼ਲ ਹੈ\x02ਇੰਟਰਫੇਸ: %[1]s\x02ਪੀਅਰ\x02ਨਵੀਂ ਟਨਲ ਬਣਾਓ\x02ਟਨਲ ਨੂੰ ਸੋਧੋ" +
+ "\x02ਨਾਂ(&N):\x02ਪਬਲਿਕ ਕੁੰਜੀ(&P):\x02(ਅਣਪਛਾਤਾ)\x02ਬਿਨਾਂ-ਟਨਲ ਵਾਲੇ ਟਰੈਫਿਕ ਉ" +
+ "ੱਤੇ ਪਾਬੰਦੀ ਲਾਓ (&B) (kill-switch)\x02ਸੰਭਾਲੋ(&S)\x02ਰੱਦ ਕਰੋ\x02ਸੰਰਚਨਾ(&" +
+ "C):\x02ਅਯੋਗ ਨਾਂ\x02ਨਾਂ ਚਾਹੀਦਾ ਹੈ।\x02ਟਨਲ ਪਹਿਲਾਂ ਹੀ ਮੌਜੂਦ ਹੈ\x02ਨਾਂ ‘%[1]" +
+ "s’ ਨਾਲ ਟਨਲ ਪਹਿਲਾਂ ਹੀ ਮੌਜੂਦ ਹੈ।\x02ਨਵੀਂ ਸੰਰਚਨਾ ਬਣਾਉਣ ਲਈ ਅਸਮਰੱਥ ਹੈ\x02ਫ਼ਾਇ" +
+ "ਲ ਬਣਾਉਣ ਲਈ ਅਸਫ਼ਲ ਹੈ\x02‘%[1]s’ ਫ਼ਾਇਲ ਪਹਿਲਾਂ ਹੀ ਮੌਜੂਦ ਹੈ।\x0a\x0aਕੀ ਤੁਸ" +
+ "ੀਂ ਇਸ ਉੱਤੇ ਲਿਖਣਾ ਚਾਹੁੰਦੇ ਹੋ?\x02ਸਰਗਰਮ\x02ਸਰਗਰਮ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ\x02ਲਿਖਤ" +
+ " ਫ਼ਾਇਲਾਂ (*.txt)|*.txt|ਸਾਰੀਆਂ ਫ਼ਾਇਲਾਂ (*.*)|*.*\x02WireGuard ਖੋਜ ਗ਼ਲਤੀ" +
+ "\x02ਵਾਇਰਗਾਰਡ: ਨਾ-ਸਰਗਰਮ ਕੀਤਾ\x02ਸਥਿਤੀ: ਅਣਪਛਾਤੀ\x02ਸਿਰਨਾਵੇਂ: ਕੋਈ ਨਹੀਂ\x02ਟ" +
+ "ਨਲਾਂ ਦਾ ਇੰਤਜ਼ਾਮ ਕਰੋ(&M)…\x02ਫ਼ਾਇਲ ਤੋਂ ਟਨਲਾਂ ਦਰਾਮਦ ਕਰੋ(&I)…\x02ਬਾਹਰ(&x)" +
+ "\x02ਟਨਲ(&T)\x02ਵਾਇਰਗਾਰਡ ਸਰਗਰਮ ਕੀਤਾ\x02%[1]s ਟਨਲ ਸਰਗਰਮ ਕੀਤੀ ਗਈ ਹੈ।\x02ਵਾਇ" +
+ "ਰਗਾਰਡ ਨਾ-ਸਰਗਰਮ ਕੀਤਾ\x02%[1]s ਟਨਲ ਨਾ-ਸਰਗਰਮ ਕੀਤੀ ਗਈ ਹੈ।\x02ਵਾਇਰਗਾਰਡ ਟਨਲ " +
+ "ਗਲਤੀ\x02ਵਾਇਰਗਾਰਡ: %[1]s\x02ਸਥਿਤੀ: %[1]s\x02ਸਿਰਨਾਵੇਂ: %[1]s\x02ਅੱਪਡੇਟ ਮ" +
+ "ੌਜੂਦ ਹੈ!\x02ਵਾਇਰਗਾਰਡ ਅੱਪਡੇਟ ਮੌਜੂਦ ਹੈ\x02ਵਾਇਰਗਾਰਡ ਲਈ ਅੱਪਡੇਟ ਹੁਣ ਮੌਜੂਦ ਹ" +
+ "ੈ। ਜਿੰਨਾ ਛੇਤੀ ਹੋ ਸਕੇ ਤੁਹਾਨੂੰ ਅੱਪਡੇਟ ਕਰਨ ਦੀ ਸਲਾਹ ਦਿੱਤੀ ਜਾਂਦੀ ਹੈ।\x02ਟਨਲ" +
+ "ਾਂ\x02ਸੋਧੋ(&E)\x02…ਖਾਲੀ ਟਨਲ ਜੋੜੋ(&e)\x02ਟਨਲ ਜੋੜੋ\x02ਚੁਣੀਆਂ ਟਨਲਾਂ ਨੂੰ ਹ" +
+ "ਟਾਓ\x02ਸਾਰੀਆਂ ਟਨਲਾਂ ਨੂੰ ਜ਼ਿੱਪ ਵਜੋਂ ਬਰਾਮਦ ਕਰੋ\x02ਪਲਟੋ(&T)\x02ਸਾਰੀਆਂ ਟਨਲਾ" +
+ "ਂ ਨੂੰ ਜ਼ਿੱਪ ਵਜੋਂ ਬਰਾਮਦ ਕਰੋ…\x02ਚੁਣੀ ਟਨਲ ਸੋਧੋ(&s)…\x02ਚੁਣੀਆਂ ਟਨਲਾਂ ਨੂੰ ਹ" +
+ "ਟਾਓ(&R)\x02ਕੋਈ ਸੰਰਚਨਾ ਫ਼ਾਇਲਾਂ ਨਹੀਂ ਲੱਭੀਆਂ\x02‘%[1]s’ ਨਾਂ ਨਾਲ ਹੋਰ ਟਨਲ ਪ" +
+ "ਹਿਲਾਂ ਹੀ ਮੌਜੂਦ ਹੈ\x02ਸੰਰਚਨਾ ਇੰਪੋਰਟ ਕਰਨ ਲਈ ਅਸਮਰੱਥ: %[1]v\x02ਇੰਪੋਰਟ ਕੀਤੀ" +
+ "ਆਂ ਟਨਲਾਂ\x14\x01\x81\x01\x00\x020\x02%[1]d ਟਨਲ ਇੰਪੋਰਟ ਕੀਤੀ\x00<\x02%[1" +
+ "]d ਟਨਲਾਂ ਇੰਪੋਰਟ ਕੀਤੀਆਂ\x02ਟਨਲ ਬਣਾਉਣ ਲਈ ਅਸਮਰੱਥ\x14\x01\x81\x01\x00\x02" +
+ "\x1d\x02%[1]d ਟਨਲ ਹਟਾਓ\x00#\x02%[1]d ਟਨਲਾਂ ਹਟਾਓ\x14\x01\x81\x01\x00\x02b" +
+ "\x02ਕੀ ਤੁਸੀਂ %[1]d ਟਨਲ ਨੂੰ ਹਟਾਉਣਾ ਚਾਹੁੰਦੇ ਹੋ?\x00h\x02ਕੀ ਤੁਸੀਂ %[1]d ਟਨਲ" +
+ "ਾਂ ਨੂੰ ਹਟਾਉਣਾ ਚਾਹੁੰਦੇ ਹੋ?\x02‘%[1]s’ ਟਨਲ ਨੂੰ ਹਟਾਓ\x02ਕੀ ਤੁਸੀਂ ‘%[1]s‘ " +
+ "ਟਨਲ ਨੂੰ ਹਟਾਉਣਾ ਚਾਹੁੰਦੇ ਹੋ?\x02%[1]s ਤੁਸੀਂ ਇਹ ਕਾਰਵਾਈ ਵਾਪਸ ਨਹੀਂ ਲੈ ਸਕਦੇ " +
+ "ਹੋ।\x02ਟਨਲ ਹਟਾਉਣ ਲਈ ਅਸਮਰੱਥ\x02ਟਨਲ ਹਟਾਉਣ ਲਈ ਅਸਮਰੱਥ ਹੈ: %[1]s\x02ਟਨਲਾਂ ਹ" +
+ "ਟਾਉਣ ਲਈ ਅਸਮਰੱਥ\x02ਸੰਰਚਨਾ ਫ਼ਾਇਲਾਂ (*.zip, *.conf)|*.zip;*.conf|ਸਾਰੀਆਂ ਫ" +
+ "਼ਾਇਲਾਂ (*.*)|*.*\x02ਫ਼ਾਇਲ ਤੋਂ ਟਨਲਾਂ ਦਰਾਮਦ ਕਰੋ\x02ਸੰਰਚਨਾ ਜ਼ਿੱਪ ਫਾਇਲਾਂ (*" +
+ ".zip)|*.zip\x02ਸੇਵਾ ਤੋਂ ਬਾਹਰ ਜਾਣ ਲਈ ਅਸਮਰੱਥ, ਕਾਰਨ: %[1]v। ਤੁਸੀਂ ਸੇਵਾ ਮੈਨੇ" +
+ "ਜਰ ਤੋਂ WireGuard ਨੂੰ ਰੋਕਣਾ ਚਾਹੋਗੇ।\x02ਹਾਲਤ: ਵਰਤੋਂਕਾਰ ਲਈ ਉਡੀਕ ਕੀਤੀ ਜਾ ਰ" +
+ "ਹੀ ਹੈ\x02ਹਾਲਤ: ਅੱਪਡੇਟਰ ਸੇਵਾ ਦੀ ਉਡੀਕ ਕੀਤੀ ਜਾ ਰਹੀ ਹੈ"
-var plIndex = []uint32{ // 181 elements
+var plIndex = []uint32{ // 278 elements
// Entry 0 - 1F
- 0x00000000, 0x00000007, 0x0000004f, 0x00000066,
- 0x0000007d, 0x000000cb, 0x00000106, 0x0000013d,
- 0x000001a6, 0x00000226, 0x00000271, 0x00000277,
- 0x0000029a, 0x000002d1, 0x00000309, 0x0000034d,
- 0x0000038c, 0x000003cf, 0x000003da, 0x000003e3,
- 0x000003f0, 0x000003fd, 0x0000040a, 0x00000417,
- 0x00000424, 0x0000043c, 0x00000465, 0x00000487,
- 0x000004b2, 0x000004d6, 0x000004e9, 0x000004fd,
+ 0x00000000, 0x00000007, 0x0000004f, 0x00000067,
+ 0x0000007e, 0x000000cc, 0x00000108, 0x0000013f,
+ 0x000001a8, 0x00000228, 0x0000022e, 0x00000251,
+ 0x00000287, 0x000002bf, 0x00000302, 0x00000341,
+ 0x00000384, 0x0000038f, 0x00000398, 0x000003a5,
+ 0x000003b2, 0x000003bf, 0x000003cc, 0x000003d9,
+ 0x000003f1, 0x0000041a, 0x0000043c, 0x00000467,
+ 0x0000047a, 0x0000048e, 0x000004be, 0x000004da,
// Entry 20 - 3F
- 0x0000052d, 0x00000549, 0x00000584, 0x000005be,
- 0x000005d5, 0x000005f6, 0x00000617, 0x00000653,
- 0x0000066e, 0x0000069a, 0x000006c1, 0x000006e5,
- 0x000006f6, 0x00000727, 0x0000074e, 0x00000778,
- 0x00000796, 0x000007bb, 0x000007be, 0x000007c1,
- 0x000007d8, 0x000007e7, 0x00000870, 0x00000878,
- 0x00000886, 0x0000088e, 0x0000089a, 0x000008a3,
- 0x000008b4, 0x000008c4, 0x000008c9, 0x000008d1,
+ 0x00000514, 0x0000052b, 0x0000054c, 0x0000055d,
+ 0x0000058e, 0x000005b5, 0x000005b8, 0x000005bb,
+ 0x000005d2, 0x000005e1, 0x000005e9, 0x000005f7,
+ 0x000005ff, 0x0000060b, 0x00000614, 0x00000625,
+ 0x00000635, 0x0000063a, 0x00000642, 0x0000064f,
+ 0x00000654, 0x00000669, 0x0000067f, 0x00000698,
+ 0x000006bc, 0x000006c7, 0x000006d6, 0x000006e4,
+ 0x000006ed, 0x000006f5, 0x00000707, 0x0000071b,
// Entry 40 - 5F
- 0x000008de, 0x000008e7, 0x000008ec, 0x00000901,
- 0x00000917, 0x00000930, 0x00000954, 0x0000095e,
- 0x0000097f, 0x0000098a, 0x000009a9, 0x000009d1,
- 0x000009f3, 0x00000a13, 0x00000a24, 0x00000a29,
- 0x00000a3c, 0x00000a49, 0x00000a51, 0x00000a63,
- 0x00000a6e, 0x00000aa4, 0x00000bf7, 0x00000bff,
- 0x00000c06, 0x00000c15, 0x00000c2a, 0x00000c3f,
- 0x00000c6a, 0x00000c96, 0x00000caa, 0x00000ce3,
+ 0x00000720, 0x00000736, 0x00000752, 0x0000076d,
+ 0x0000077b, 0x000007bb, 0x000007cf, 0x000007f2,
+ 0x00000844, 0x00000855, 0x00000877, 0x0000088b,
+ 0x000008d6, 0x000008fa, 0x00000935, 0x00000956,
+ 0x00000992, 0x000009ad, 0x000009d9, 0x00000a00,
+ 0x00000a24, 0x00000a4e, 0x00000a6c, 0x00000a91,
+ 0x00000a9a, 0x00000aa4, 0x00000ab7, 0x00000ac6,
+ 0x00000ada, 0x00000aea, 0x00000b0b, 0x00000b16,
// Entry 60 - 7F
- 0x00000d0b, 0x00000d2a, 0x00000d63, 0x00000d6b,
- 0x00000d77, 0x00000d82, 0x00000d91, 0x00000d9f,
- 0x00000da8, 0x00000db0, 0x00000dc2, 0x00000dd6,
- 0x00000ddb, 0x00000df1, 0x00000e28, 0x00000e44,
- 0x00000e5f, 0x00000e6d, 0x00000ead, 0x00000ec1,
- 0x00000edb, 0x00000f19, 0x00000f32, 0x00000f43,
- 0x00000f50, 0x00000f68, 0x00000f8c, 0x00000f96,
- 0x00000fa8, 0x00000fc8, 0x00000fe0, 0x00001003,
+ 0x00000b35, 0x00000b5d, 0x00000b7f, 0x00000b9f,
+ 0x00000bb0, 0x00000bb5, 0x00000bc8, 0x00000bd5,
+ 0x00000bdd, 0x00000bef, 0x00000bfa, 0x00000c30,
+ 0x00000c38, 0x00000c3f, 0x00000c4e, 0x00000c63,
+ 0x00000c78, 0x00000ca3, 0x00000ccf, 0x00000ce3,
+ 0x00000d1c, 0x00000d44, 0x00000d63, 0x00000d9c,
+ 0x00000da4, 0x00000db0, 0x00000de7, 0x00000e01,
+ 0x00000e3f, 0x00000e58, 0x00000e69, 0x00000e76,
// Entry 80 - 9F
- 0x0000101b, 0x0000102c, 0x0000103a, 0x00001048,
- 0x00001065, 0x0000108b, 0x000010e2, 0x000010e9,
- 0x000010f1, 0x00001107, 0x00001113, 0x00001130,
- 0x0000115b, 0x00001167, 0x00001196, 0x000011af,
- 0x000011cd, 0x000011eb, 0x00001221, 0x00001251,
- 0x00001289, 0x000012b6, 0x000012cb, 0x00001343,
- 0x000013da, 0x000013f6, 0x0000144e, 0x00001506,
- 0x0000151e, 0x0000154e, 0x00001573, 0x0000158e,
+ 0x00000e8e, 0x00000eb2, 0x00000ebc, 0x00000ec4,
+ 0x00000ed6, 0x00000ef6, 0x00000f0e, 0x00000f31,
+ 0x00000f49, 0x00000f5a, 0x00000f68, 0x00000f76,
+ 0x00000f93, 0x00000fb9, 0x00001010, 0x00001017,
+ 0x0000101f, 0x00001035, 0x00001041, 0x0000105e,
+ 0x00001089, 0x00001095, 0x000010c4, 0x000010dd,
+ 0x000010fb, 0x00001119, 0x0000114f, 0x0000117f,
+ 0x000011b7, 0x000011e4, 0x000011f9, 0x00001271,
// Entry A0 - BF
- 0x000015b8, 0x000015d3, 0x0000167e, 0x000016c8,
- 0x000016e8, 0x0000170d, 0x0000172e, 0x0000175d,
- 0x00001780, 0x0000180a, 0x0000185c, 0x0000187b,
- 0x0000188c, 0x000018b4, 0x000018d6, 0x000018ea,
- 0x000018fd, 0x0000190c, 0x00001920, 0x00001930,
- 0x00001938,
-} // Size: 748 bytes
+ 0x00001308, 0x00001324, 0x0000137c, 0x00001434,
+ 0x0000144c, 0x0000147c, 0x000014a1, 0x000014bc,
+ 0x000014e6, 0x00001501, 0x000015ac, 0x000015f6,
+ 0x00001616, 0x0000163b, 0x0000165c, 0x0000168b,
+ 0x00001715, 0x00001734, 0x0000175c, 0x0000175c,
+ 0x0000175c, 0x0000175c, 0x0000175c, 0x0000175c,
+ 0x0000175c, 0x0000175c, 0x0000175c, 0x0000175c,
+ 0x0000175c, 0x0000175c, 0x0000175c, 0x0000175c,
+ // Entry C0 - DF
+ 0x0000175c, 0x0000175c, 0x0000175c, 0x0000175c,
+ 0x0000175c, 0x0000175c, 0x0000175c, 0x0000175c,
+ 0x0000175c, 0x0000175c, 0x0000175c, 0x0000175c,
+ 0x0000175c, 0x0000175c, 0x0000175c, 0x0000175c,
+ 0x0000175c, 0x0000175c, 0x0000175c, 0x0000175c,
+ 0x0000175c, 0x0000175c, 0x0000175c, 0x0000175c,
+ 0x0000175c, 0x0000175c, 0x0000175c, 0x0000175c,
+ 0x0000175c, 0x0000175c, 0x0000175c, 0x0000175c,
+ // Entry E0 - FF
+ 0x0000175c, 0x0000175c, 0x0000175c, 0x0000175c,
+ 0x0000175c, 0x0000175c, 0x0000175c, 0x0000175c,
+ 0x0000175c, 0x0000175c, 0x0000175c, 0x0000175c,
+ 0x0000175c, 0x0000175c, 0x0000175c, 0x0000175c,
+ 0x0000175c, 0x0000175c, 0x0000175c, 0x0000175c,
+ 0x0000175c, 0x0000175c, 0x0000175c, 0x0000175c,
+ 0x0000175c, 0x0000175c, 0x0000175c, 0x0000175c,
+ 0x0000175c, 0x0000175c, 0x0000175c, 0x0000175c,
+ // Entry 100 - 11F
+ 0x0000175c, 0x0000175c, 0x0000175c, 0x0000175c,
+ 0x0000175c, 0x0000175c, 0x0000175c, 0x0000175c,
+ 0x0000175c, 0x0000175c, 0x0000175c, 0x0000175c,
+ 0x0000175c, 0x0000175c, 0x0000175c, 0x0000175c,
+ 0x0000175c, 0x0000175c, 0x0000175c, 0x0000175c,
+ 0x0000175c, 0x0000175c,
+} // Size: 1136 bytes
-const plData string = "" + // Size: 6456 bytes
+const plData string = "" + // Size: 5980 bytes
"\x02Błąd\x02(brak argumentu): Podnieś uprawnienia i zainstaluj usługę me" +
- "nedżera\x02Użycie: %[1]s [%[2]s]\x02Opcje wiersza poleceń\x02Nie można o" +
- "kreślić, czy proces jest uruchomiony w środowisku WOW64: %[1]v\x02Musisz" +
- " użyć natywnej wersji WireGuard na tym komputerze.\x02Nie można otworzyć" +
- " bieżącego tokenu procesu: %[1]v\x02WireGuard może być używany tylko prz" +
- "ez użytkowników, którzy są członkami wbudowanej grupy %[1]s.\x02WireGuar" +
- "d jest uruchomiony, ale interfejs jest dostępny tylko z poziomu użytkown" +
- "ików należących do wbudowanej grupy %[1]s.\x02Ikona WireGuard nie pojawi" +
- "ła się po 30 sekundach w zasobniku systemowym.\x02Teraz\x02Zegar system" +
- "owy został cofnięty!\x14\x01\x81\x01\x00\x04\x0b\x02%[1]d lata\x05\x0a" +
- "\x02%[1]d lat\x02\x0a\x02%[1]d rok\x00\x0b\x02%[1]d lata\x14\x01\x81\x01" +
+ "nedżera\x02Użycie: %[1]s [\x0a%[2]s]\x02Opcje wiersza poleceń\x02Nie moż" +
+ "na określić, czy proces jest uruchomiony w środowisku WOW64: %[1]v\x02Na" +
+ "leży użyć natywnej wersji WireGuard na tym komputerze.\x02Nie można otwo" +
+ "rzyć bieżącego tokenu procesu: %[1]v\x02WireGuard może być używany tylko" +
+ " przez użytkowników, którzy są członkami wbudowanej grupy %[1]s.\x02Wire" +
+ "Guard jest uruchomiony, ale interfejs jest dostępny tylko z poziomu użyt" +
+ "kowników należących do wbudowanej grupy %[1]s.\x02Teraz\x02Zegar systemo" +
+ "wy został cofnięty!\x14\x01\x81\x01\x00\x04\x0b\x02%[1]d lata\x05\x0a" +
+ "\x02%[1]d lat\x02\x0a\x02%[1]d rok\x00\x0a\x02%[1]d lat\x14\x01\x81\x01" +
"\x00\x04\x0a\x02%[1]d dni\x05\x0a\x02%[1]d dni\x02\x0d\x02%[1]d dzień" +
"\x00\x0a\x02%[1]d dni\x14\x01\x81\x01\x00\x04\x0e\x02%[1]d godziny\x05" +
- "\x0d\x02%[1]d godzin\x02\x0e\x02%[1]d godzina\x00\x0e\x02%[1]d godziny" +
+ "\x0d\x02%[1]d godzin\x02\x0e\x02%[1]d godzina\x00\x0d\x02%[1]d godzin" +
"\x14\x01\x81\x01\x00\x04\x0d\x02%[1]d minuty\x05\x0c\x02%[1]d minut\x02" +
"\x0d\x02%[1]d minuta\x00\x0c\x02%[1]d minut\x14\x01\x81\x01\x00\x04\x0e" +
"\x02%[1]d sekundy\x05\x0d\x02%[1]d sekund\x02\x0e\x02%[1]d sekunda\x00" +
@@ -1440,143 +2320,164 @@ const plData string = "" + // Size: 6456 bytes
"\x02%.2[1]f\u00a0MiB\x02%.2[1]f\u00a0GiB\x02%.2[1]f\u00a0TiB\x02%[1]s: %" +
"[2]q\x02Nieprawidłowy adres IP\x02Nieprawidłowa długość prefiksu sieci" +
"\x02Brak portu urządzenia końcowego\x02Nieprawidłowy host (urządzenie ko" +
- "ńcowe)\x02Nawiasy muszą zawierać adres IPv6\x02Nieprawidłowe MTU\x02Nie" +
- "prawidłowy port\x02Nieprawidłowy parametr utrzymania połączenia\x02Niepr" +
- "awidłowy klucz: %[1]v\x02Klucze muszą zostać zdekodowane do dokładnie 32" +
- " bajtów\x02Liczba musi zawierać się w przedziale 0 - 2^64-1: %[1]v\x02Dw" +
- "a przecinki z rzędu\x02Nazwa tunelu jest nieprawidłowa\x02Linia musi wys" +
- "tępować w sekcji\x02Klucz konfiguracyjny nie zawiera separatora równorzę" +
- "dnego\x02Klucz musi mieć wartość\x02Nieprawidłowy klucz dla sekcji [Inte" +
- "rface]\x02Nieprawidłowy klucz dla sekcji [Peer]\x02Interfejs musi mieć k" +
- "lucz prywatny\x02[nie określono]\x02Wszyscy uczestnicy muszą mieć klucze" +
- " publiczne\x02Błąd podczas pobierania konfiguracji\x02Nieprawidłowy kluc" +
- "z dla sekcji interface\x02Wersja protokołu musi być 1\x02Nieprawidłowy k" +
- "lucz dla sekcji peer\x02, \x02, \x02Informacje o WireGuard\x02Logo WireG" +
- "uard\x02Wersja aplikacji: %[1]s\x0aWersja implementacji w jęz. Go: %[2]s" +
- "\x0aWersja jęz. Go: %[3]s-%[4]s\x0aSystem operacyjny: %[5]s\x0aArchitekt" +
- "ura: %[6]s\x02Zamknij\x02♥ &Wpłać!\x02Status:\x02&Dezaktywuj\x02&Aktywuj" +
- "\x02Klucz publiczny:\x02Port nasłuchu:\x02MTU:\x02Adresy:\x02Serwery DNS" +
- ":\x02Skrypty:\x02PSK:\x02Dozwolone adresy IP:\x02Urządzenie końcowe:\x02" +
- "Utrzymanie połączenia:\x02Ostatni uścisk dłoni (handshake):\x02Transfer:" +
- "\x02wyłączone, według zasad grupy\x02włączyć\x02%[1]s odebrano, %[2]s wy" +
- "słano\x02Nie udało się określić stanu tunelu\x02Nie udało się aktywować " +
- "tunelu\x02Nie można dezaktywować tunelu\x02Interfejs: %[1]s\x02Peer\x02U" +
- "twórz nowy tunel\x02Edytuj tunel\x02&Nazwa:\x02&Klucz publiczny:\x02(nie" +
- "znany)\x02Zablokuj niezabezpieczony ruch (wyłącznik awaryjny)\x02Jeżeli " +
- "konfiguracja ma dokładnie jednego peer'a i ma w liście dozwolonych IP pr" +
- "zynajmniej jeden adres 0.0.0.0/0 lub ::/0, wtedy usługa tunelowania dołą" +
- "cza do zapory sieciowej zestaw zasad, żeby zablokować ruch, który nie je" +
- "st z interfejsu sieciowego lub jest skierowany do złego serwera DNS, z w" +
- "yjątkiem dla serwera DHCP i NDP.\x02&Zapisz\x02Anuluj\x02&Konfiguracja:" +
- "\x02Nieprawidłowa nazwa\x02Nazwa jest wymagana.\x02Nazwa tunelu ‘%[1]s’ " +
- "jest niepoprawna.\x02Nie można wylistować istniejących tuneli\x02Tunel j" +
- "uż istnieje\x02Inny tunel już istnieje z tą samą nazwą ‘%[1]s’.\x02Nie m" +
- "ożna utworzyć nowej konfiguracji\x02Zapis pliku się nie powiódł\x02Plik " +
- "‘%[1]s’ już istnieje. Czy chcesz go nadpisać?\x02Aktywny\x02Aktywowani" +
- "e\x02Nieaktywny\x02Dezaktywowanie\x02Stan nieznany\x02Dziennik\x02&Kopiu" +
- "j\x02Wybierz &wszystko\x02&Zapisz do pliku…\x02Czas\x02Wiadomości dzienn" +
- "ika\x02Pliki tekstowe (*.txt)|*.txt|Wszystkie pliki (*.*)|*.*\x02Eksport" +
- "uj dziennik do pliku\x02&Informacje o WireGuard…\x02Błąd tunelu\x02%[1]s" +
- "\x0a\x0aAby uzyskać więcej informacji, zapoznaj się z logiem.\x02%[1]s (" +
- "nieaktualny)\x02Błąd detekcji WireGuard\x02Nie można poczekać na pojawie" +
- "nie się okna WireGuard: %[1]v\x02WireGuard: Dezaktywowany\x02Status: Nie" +
- "znany\x02Adresy: Brak\x02&Zarządzaj tunelami…\x02&Importuj tunel (tunele" +
- ") z pliku…\x02W&yjście\x02WireGuard Aktywny\x02Tunel %[1]s został aktywo" +
- "wany.\x02WireGuard Dezaktywowany\x02Tunel %[1]s został dezaktywowany." +
- "\x02Błąd tunelu WireGuard\x02WireGuard: %[1]s\x02Status: %[1]s\x02Adresy" +
- ": %[1]s\x02Dostępna nowa aktualizacja!\x02Aktualizacja WireGuard jest do" +
- "stępna\x02Aktualizacja WireGuard jest już dostępna. Zaleca się jak najsz" +
- "ybszą aktualizację.\x02Tunele\x02&Edytuj\x02Dodaj &pusty tunel…\x02Dodaj" +
- " Tunel\x02Usuń wybrany tunel (tunele)\x02Eksportuj wszystkie tunele do a" +
- "rchiwum ZIP\x02&Przełącz\x02Eksportuj wszystkie tunele do archiwum &zip…" +
- "\x02Edytuj &wybrany tunel…\x02&Usuń wybrany tunel (tunele)\x02brak plikó" +
- "w konfiguracyjnych\x02Nie można zaimportować wybranej konfiguracji: %[1]" +
- "v\x02Nie można wskazać istniejących tuneli: %[1]v\x02Inny tunel już istn" +
- "ieje z tą samą nazwą ‘%[1]s’\x02Nie można zaimportować konfiguracji: %[1" +
- "]v\x02Zaimportowane tunele\x14\x01\x81\x01\x00\x04\x1b\x02Zaimportowano " +
- "%[1]d tunele\x05\x1b\x02Zaimportowano %[1]d tuneli\x02\x1a\x02Zaimportow" +
- "ano %[1]d tunel\x00\x1b\x02Zaimportowano %[1]d tuneli\x14\x02\x80\x01" +
- "\x04#\x02Zaimportowano %[1]d z %[2]d tunele\x05#\x02Zaimportowano %[1]d " +
- "z %[2]d tuneli\x02\x22\x02Zaimportowano %[1]d z %[2]d tunel\x00#\x02Zaim" +
- "portowano %[1]d z %[2]d tuneli\x02Nie można utworzyć tunelu\x14\x01\x81" +
- "\x01\x00\x04\x13\x02Usuń %[1]d tunele\x05\x13\x02Usuń %[1]d tuneli\x02" +
- "\x12\x02Usuń %[1]d tunel\x00\x13\x02Usuń %[1]d tuneli\x14\x01\x81\x01" +
- "\x00\x04+\x02Czy na pewno chcesz usunąć %[1]d tunele?\x05+\x02Czy na pew" +
- "no chcesz usunąć %[1]d tuneli?\x02*\x02Czy na pewno chcesz usunąć %[1]d " +
- "tunel?\x00+\x02Czy na pewno chcesz usunąć %[1]d tuneli?\x02Usuń tunel ‘%" +
- "[1]s’\x02Czy na pewno chcesz usunąć tunel ‘%[1]s’?\x02%[1]s Tej akcji ni" +
- "e można cofnąć.\x02Nie można usunąć tunelu\x02Tunel nie mógł zostać usun" +
- "ięty: %[1]s\x02Nie można usunąć tuneli\x14\x01\x81\x01\x00\x04'\x02%[1]d" +
- " tunele nie mogą być usunięte.\x05'\x02%[1]d tunele nie mogą być usunięt" +
- "e.\x02)\x02%[1]d tunel nie może zostać usunięty.\x00'\x02%[1]d tunele ni" +
- "e mogą być usunięte.\x02Pliki konfiguracji (*.zip, *.conf)|*.zip;*.conf|" +
- "Wszystkie pliki (*.*)|*.*\x02Importuj tunel (tunele) z pliku\x02Pliki ZI" +
- "P konfiguracji (*.zip)|*.zip\x02Eksportuj tunele do archiwum ZIP\x02%[1]" +
- "s (wersja niepodpisana, brak aktualizacji)\x02Błąd podczas zamykania Wir" +
- "eGuard\x02Nie można wyłączyć usługi ze względu na: %[1]v. Jeśli chcesz w" +
- "yłączyć WireGuard możesz to zrobić z poziomu menedżera usług.\x02Aktuali" +
- "zacja WireGuard jest dostępna. Zaleca się natychmiastową aktualizację." +
- "\x02Status: Czekam na użytkownika\x02Uaktualnij teraz\x02Status: Czekam " +
- "na usługę aktualizacji\x02Błąd: %[1]v. Spróbuj ponownie.\x02Status: Ukoń" +
- "czone!\x02przed włączeniem\x02po włączeniu\x02przed wyłączeniem\x02po wy" +
- "łączeniu\x02&Tunele"
+ "ńcowe)\x02Nieprawidłowe MTU\x02Nieprawidłowy port\x02Nieprawidłowy para" +
+ "metr utrzymania połączenia\x02Nieprawidłowy klucz: %[1]v\x02Liczba musi " +
+ "zawierać się w przedziale 0 - 2^64-1: %[1]v\x02Dwa przecinki z rzędu\x02" +
+ "Nazwa tunelu jest nieprawidłowa\x02[nie określono]\x02Wszyscy uczestnicy" +
+ " muszą mieć klucze publiczne\x02Błąd podczas pobierania konfiguracji\x02" +
+ ", \x02, \x02Informacje o WireGuard\x02Logo WireGuard\x02Zamknij\x02♥ &Wp" +
+ "łać!\x02Status:\x02&Dezaktywuj\x02&Aktywuj\x02Klucz publiczny:\x02Port " +
+ "nasłuchu:\x02MTU:\x02Adresy:\x02Serwery DNS:\x02PSK:\x02Dozwolone adresy" +
+ " IP:\x02Urządzenie końcowe:\x02Utrzymanie połączenia:\x02Ostatni uścisk " +
+ "dłoni (handshake):\x02Nieaktywny\x02Dezaktywowanie\x02Stan nieznany\x02D" +
+ "ziennik\x02&Kopiuj\x02Wybierz &wszystko\x02&Zapisz do pliku…\x02Czas\x02" +
+ "Wiadomości dziennika\x02Eksportuj dziennik do pliku\x02&Informacje o Wir" +
+ "eGuard…\x02Błąd tunelu\x02%[1]s\x0a\x0aAby uzyskać więcej informacji, za" +
+ "poznaj się z logiem.\x02%[1]s (nieaktualny)\x02Błąd podczas zamykania Wi" +
+ "reGuard\x02Aktualizacja WireGuard jest dostępna. Zaleca się natychmiasto" +
+ "wą aktualizację.\x02Uaktualnij teraz\x02Błąd: %[1]v. Spróbuj ponownie." +
+ "\x02Status: Ukończone!\x02Ikona WireGuard nie pojawiła się po 30 sekunda" +
+ "ch w zasobniku systemowym.\x02Nawiasy muszą zawierać adres IPv6\x02Klucz" +
+ "e muszą zostać zdekodowane do dokładnie 32 bajtów\x02Linia musi występow" +
+ "ać w sekcji\x02Klucz konfiguracyjny nie zawiera separatora równorzędnego" +
+ "\x02Klucz musi mieć wartość\x02Nieprawidłowy klucz dla sekcji [Interface" +
+ "]\x02Nieprawidłowy klucz dla sekcji [Peer]\x02Interfejs musi mieć klucz " +
+ "prywatny\x02Nieprawidłowy klucz dla sekcji interface\x02Wersja protokołu" +
+ " musi być 1\x02Nieprawidłowy klucz dla sekcji peer\x02Skrypty:\x02Transf" +
+ "er:\x02przed włączeniem\x02po włączeniu\x02przed wyłączeniem\x02po wyłąc" +
+ "zeniu\x02wyłączone, według zasad grupy\x02włączyć\x02%[1]s odebrano, %[2" +
+ "]s wysłano\x02Nie udało się określić stanu tunelu\x02Nie udało się aktyw" +
+ "ować tunelu\x02Nie można dezaktywować tunelu\x02Interfejs: %[1]s\x02Peer" +
+ "\x02Utwórz nowy tunel\x02Edytuj tunel\x02&Nazwa:\x02&Klucz publiczny:" +
+ "\x02(nieznany)\x02Zablokuj niezabezpieczony ruch (wyłącznik awaryjny)" +
+ "\x02&Zapisz\x02Anuluj\x02&Konfiguracja:\x02Nieprawidłowa nazwa\x02Nazwa " +
+ "jest wymagana.\x02Nazwa tunelu ‘%[1]s’ jest niepoprawna.\x02Nie można wy" +
+ "listować istniejących tuneli\x02Tunel już istnieje\x02Inny tunel już ist" +
+ "nieje z tą samą nazwą ‘%[1]s’.\x02Nie można utworzyć nowej konfiguracji" +
+ "\x02Zapis pliku się nie powiódł\x02Plik ‘%[1]s’ już istnieje. Czy chcesz" +
+ " go nadpisać?\x02Aktywny\x02Aktywowanie\x02Pliki tekstowe (*.txt)|*.txt|" +
+ "Wszystkie pliki (*.*)|*.*\x02Błąd detekcji WireGuard\x02Nie można poczek" +
+ "ać na pojawienie się okna WireGuard: %[1]v\x02WireGuard: Dezaktywowany" +
+ "\x02Status: Nieznany\x02Adresy: Brak\x02&Zarządzaj tunelami…\x02&Importu" +
+ "j tunel (tunele) z pliku…\x02W&yjście\x02&Tunele\x02WireGuard Aktywny" +
+ "\x02Tunel %[1]s został aktywowany.\x02WireGuard Dezaktywowany\x02Tunel %" +
+ "[1]s został dezaktywowany.\x02Błąd tunelu WireGuard\x02WireGuard: %[1]s" +
+ "\x02Status: %[1]s\x02Adresy: %[1]s\x02Dostępna nowa aktualizacja!\x02Akt" +
+ "ualizacja WireGuard jest dostępna\x02Aktualizacja WireGuard jest już dos" +
+ "tępna. Zaleca się jak najszybszą aktualizację.\x02Tunele\x02&Edytuj\x02D" +
+ "odaj &pusty tunel…\x02Dodaj Tunel\x02Usuń wybrany tunel (tunele)\x02Eksp" +
+ "ortuj wszystkie tunele do archiwum ZIP\x02&Przełącz\x02Eksportuj wszystk" +
+ "ie tunele do archiwum &zip…\x02Edytuj &wybrany tunel…\x02&Usuń wybrany t" +
+ "unel (tunele)\x02brak plików konfiguracyjnych\x02Nie można zaimportować " +
+ "wybranej konfiguracji: %[1]v\x02Nie można wskazać istniejących tuneli: %" +
+ "[1]v\x02Inny tunel już istnieje z tą samą nazwą ‘%[1]s’\x02Nie można zai" +
+ "mportować konfiguracji: %[1]v\x02Zaimportowane tunele\x14\x01\x81\x01" +
+ "\x00\x04\x1b\x02Zaimportowano %[1]d tunele\x05\x1b\x02Zaimportowano %[1]" +
+ "d tuneli\x02\x1a\x02Zaimportowano %[1]d tunel\x00\x1b\x02Zaimportowano %" +
+ "[1]d tuneli\x14\x02\x80\x01\x04#\x02Zaimportowano %[1]d z %[2]d tunele" +
+ "\x05#\x02Zaimportowano %[1]d z %[2]d tuneli\x02\x22\x02Zaimportowano %[1" +
+ "]d z %[2]d tunel\x00#\x02Zaimportowano %[1]d z %[2]d tuneli\x02Nie można" +
+ " utworzyć tunelu\x14\x01\x81\x01\x00\x04\x13\x02Usuń %[1]d tunele\x05" +
+ "\x13\x02Usuń %[1]d tuneli\x02\x12\x02Usuń %[1]d tunel\x00\x13\x02Usuń %[" +
+ "1]d tuneli\x14\x01\x81\x01\x00\x04+\x02Czy na pewno chcesz usunąć %[1]d " +
+ "tunele?\x05+\x02Czy na pewno chcesz usunąć %[1]d tuneli?\x02*\x02Czy na " +
+ "pewno chcesz usunąć %[1]d tunel?\x00+\x02Czy na pewno chcesz usunąć %[1]" +
+ "d tuneli?\x02Usuń tunel ‘%[1]s’\x02Czy na pewno chcesz usunąć tunel ‘%[1" +
+ "]s’?\x02%[1]s Tej akcji nie można cofnąć.\x02Nie można usunąć tunelu\x02" +
+ "Tunel nie mógł zostać usunięty: %[1]s\x02Nie można usunąć tuneli\x14\x01" +
+ "\x81\x01\x00\x04'\x02%[1]d tunele nie mogą być usunięte.\x05'\x02%[1]d t" +
+ "unele nie mogą być usunięte.\x02)\x02%[1]d tunel nie może zostać usunięt" +
+ "y.\x00'\x02%[1]d tunele nie mogą być usunięte.\x02Pliki konfiguracji (*." +
+ "zip, *.conf)|*.zip;*.conf|Wszystkie pliki (*.*)|*.*\x02Importuj tunel (t" +
+ "unele) z pliku\x02Pliki ZIP konfiguracji (*.zip)|*.zip\x02Eksportuj tune" +
+ "le do archiwum ZIP\x02%[1]s (wersja niepodpisana, brak aktualizacji)\x02" +
+ "Nie można wyłączyć usługi ze względu na: %[1]v. Jeśli chcesz wyłączyć Wi" +
+ "reGuard możesz to zrobić z poziomu menedżera usług.\x02Status: Czekam na" +
+ " użytkownika\x02Status: Czekam na usługę aktualizacji"
-var roIndex = []uint32{ // 181 elements
+var roIndex = []uint32{ // 278 elements
// Entry 0 - 1F
0x00000000, 0x00000007, 0x0000005d, 0x00000077,
0x00000092, 0x000000d1, 0x0000011a, 0x0000014e,
- 0x000001b2, 0x0000022e, 0x00000278, 0x0000027d,
- 0x000002a4, 0x000002cf, 0x000002fc, 0x00000329,
- 0x0000035d, 0x00000396, 0x000003a1, 0x000003aa,
- 0x000003b7, 0x000003c4, 0x000003d1, 0x000003de,
- 0x000003eb, 0x00000400, 0x0000042d, 0x00000452,
- 0x00000475, 0x000004a6, 0x000004b4, 0x000004c1,
+ 0x000001b2, 0x0000022e, 0x00000233, 0x0000025a,
+ 0x00000285, 0x000002b2, 0x000002df, 0x00000313,
+ 0x0000034c, 0x00000357, 0x00000360, 0x0000036d,
+ 0x0000037a, 0x00000387, 0x00000394, 0x000003a1,
+ 0x000003b6, 0x000003e3, 0x00000408, 0x0000042b,
+ 0x00000439, 0x00000446, 0x00000469, 0x00000480,
// Entry 20 - 3F
- 0x000004e4, 0x000004fb, 0x00000540, 0x0000057c,
- 0x0000059e, 0x000005bd, 0x000005e8, 0x0000062f,
- 0x00000655, 0x00000683, 0x000006ac, 0x000006dd,
- 0x000006f4, 0x00000723, 0x00000747, 0x00000775,
- 0x0000079d, 0x000007c8, 0x000007cb, 0x000007ce,
- 0x000007df, 0x000007f8, 0x0000087c, 0x00000887,
- 0x00000896, 0x0000089d, 0x000008aa, 0x000008b4,
- 0x000008c4, 0x000008d7, 0x000008dc, 0x000008e4,
+ 0x000004bc, 0x000004de, 0x000004fd, 0x00000514,
+ 0x00000543, 0x00000567, 0x0000056a, 0x0000056d,
+ 0x0000057e, 0x00000597, 0x000005a2, 0x000005b1,
+ 0x000005b8, 0x000005c5, 0x000005cf, 0x000005df,
+ 0x000005f2, 0x000005f7, 0x000005ff, 0x0000060c,
+ 0x00000623, 0x00000633, 0x00000640, 0x0000065c,
+ 0x00000679, 0x00000681, 0x00000692, 0x000006a5,
+ 0x000006ac, 0x000006b5, 0x000006c8, 0x000006e0,
// Entry 40 - 5F
- 0x000008f1, 0x000008fc, 0x00000913, 0x00000923,
- 0x00000930, 0x0000094c, 0x00000969, 0x00000976,
- 0x00000994, 0x0000099e, 0x000009b9, 0x000009e5,
- 0x00000a03, 0x00000a24, 0x00000a37, 0x00000a3f,
- 0x00000a50, 0x00000a5e, 0x00000a65, 0x00000a76,
- 0x00000a85, 0x00000ad2, 0x00000c6e, 0x00000c77,
- 0x00000c7f, 0x00000c8f, 0x00000c9c, 0x00000cb2,
- 0x00000cdd, 0x00000d04, 0x00000d19, 0x00000d4a,
+ 0x000006e5, 0x000006f5, 0x00000712, 0x00000727,
+ 0x00000737, 0x0000076f, 0x00000784, 0x000007a5,
+ 0x00000802, 0x00000815, 0x00000838, 0x0000084c,
+ 0x00000896, 0x000008c7, 0x0000090c, 0x00000937,
+ 0x0000097e, 0x000009a4, 0x000009d2, 0x000009fb,
+ 0x00000a2c, 0x00000a5a, 0x00000a82, 0x00000aad,
+ 0x00000ab8, 0x00000ac5, 0x00000ad1, 0x00000ade,
+ 0x00000ae9, 0x00000af5, 0x00000b13, 0x00000b1d,
// Entry 60 - 7F
- 0x00000d6f, 0x00000d8d, 0x00000dd3, 0x00000dd9,
- 0x00000de7, 0x00000def, 0x00000e00, 0x00000e13,
- 0x00000e1a, 0x00000e23, 0x00000e36, 0x00000e4e,
- 0x00000e53, 0x00000e63, 0x00000e9a, 0x00000eb7,
- 0x00000ecc, 0x00000edc, 0x00000f14, 0x00000f29,
- 0x00000f47, 0x00000f85, 0x00000f9b, 0x00000faf,
- 0x00000fbf, 0x00000fd7, 0x00000ffc, 0x00001005,
- 0x00001017, 0x00001035, 0x0000104a, 0x0000106b,
+ 0x00000b38, 0x00000b64, 0x00000b82, 0x00000ba3,
+ 0x00000bb6, 0x00000bbe, 0x00000bcf, 0x00000bdd,
+ 0x00000be4, 0x00000bf5, 0x00000c04, 0x00000c51,
+ 0x00000c5a, 0x00000c62, 0x00000c72, 0x00000c7f,
+ 0x00000c95, 0x00000cc0, 0x00000ce7, 0x00000cfc,
+ 0x00000d2d, 0x00000d52, 0x00000d70, 0x00000db6,
+ 0x00000dbc, 0x00000dca, 0x00000e01, 0x00000e1f,
+ 0x00000e5d, 0x00000e73, 0x00000e87, 0x00000e97,
// Entry 80 - 9F
- 0x00001085, 0x00001096, 0x000010a3, 0x000010b1,
- 0x000010d2, 0x000010fc, 0x00001172, 0x0000117b,
- 0x00001184, 0x0000119c, 0x000011ac, 0x000011cd,
- 0x000011ef, 0x000011f9, 0x0000121f, 0x0000123a,
- 0x0000125c, 0x00001287, 0x000012c0, 0x000012f5,
- 0x00001325, 0x00001351, 0x00001364, 0x000013b7,
- 0x00001427, 0x00001441, 0x00001497, 0x00001541,
- 0x0000155d, 0x00001597, 0x000015c5, 0x000015e0,
+ 0x00000eaf, 0x00000ed4, 0x00000edd, 0x00000ee7,
+ 0x00000ef9, 0x00000f17, 0x00000f2c, 0x00000f4d,
+ 0x00000f67, 0x00000f78, 0x00000f85, 0x00000f93,
+ 0x00000fb4, 0x00000fde, 0x00001054, 0x0000105d,
+ 0x00001066, 0x0000107e, 0x0000108e, 0x000010af,
+ 0x000010d1, 0x000010db, 0x00001101, 0x0000111c,
+ 0x0000113e, 0x00001169, 0x000011a2, 0x000011d7,
+ 0x00001207, 0x00001233, 0x00001246, 0x00001299,
// Entry A0 - BF
- 0x00001607, 0x00001624, 0x000016a8, 0x000016f8,
- 0x00001719, 0x00001743, 0x0000175e, 0x0000178f,
- 0x000017b0, 0x00001811, 0x0000186e, 0x00001890,
- 0x000018a3, 0x000018d1, 0x000018f4, 0x00001908,
- 0x00001914, 0x00001921, 0x0000192c, 0x00001938,
- 0x00001942,
-} // Size: 748 bytes
+ 0x00001309, 0x00001323, 0x00001379, 0x00001423,
+ 0x0000143f, 0x00001479, 0x000014a7, 0x000014c2,
+ 0x000014e9, 0x00001506, 0x0000158a, 0x000015da,
+ 0x000015fb, 0x00001625, 0x00001640, 0x00001671,
+ 0x000016d2, 0x000016f4, 0x00001722, 0x00001722,
+ 0x00001722, 0x00001722, 0x00001722, 0x00001722,
+ 0x00001722, 0x00001722, 0x00001722, 0x00001722,
+ 0x00001722, 0x00001722, 0x00001722, 0x00001722,
+ // Entry C0 - DF
+ 0x00001722, 0x00001722, 0x00001722, 0x00001722,
+ 0x00001722, 0x00001722, 0x00001722, 0x00001722,
+ 0x00001722, 0x00001722, 0x00001722, 0x00001722,
+ 0x00001722, 0x00001722, 0x00001722, 0x00001722,
+ 0x00001722, 0x00001722, 0x00001722, 0x00001722,
+ 0x00001722, 0x00001722, 0x00001722, 0x00001722,
+ 0x00001722, 0x00001722, 0x00001722, 0x00001722,
+ 0x00001722, 0x00001722, 0x00001722, 0x00001722,
+ // Entry E0 - FF
+ 0x00001722, 0x00001722, 0x00001722, 0x00001722,
+ 0x00001722, 0x00001722, 0x00001722, 0x00001722,
+ 0x00001722, 0x00001722, 0x00001722, 0x00001722,
+ 0x00001722, 0x00001722, 0x00001722, 0x00001722,
+ 0x00001722, 0x00001722, 0x00001722, 0x00001722,
+ 0x00001722, 0x00001722, 0x00001722, 0x00001722,
+ 0x00001722, 0x00001722, 0x00001722, 0x00001722,
+ 0x00001722, 0x00001722, 0x00001722, 0x00001722,
+ // Entry 100 - 11F
+ 0x00001722, 0x00001722, 0x00001722, 0x00001722,
+ 0x00001722, 0x00001722, 0x00001722, 0x00001722,
+ 0x00001722, 0x00001722, 0x00001722, 0x00001722,
+ 0x00001722, 0x00001722, 0x00001722, 0x00001722,
+ 0x00001722, 0x00001722, 0x00001722, 0x00001722,
+ 0x00001722, 0x00001722,
+} // Size: 1136 bytes
-const roData string = "" + // Size: 6466 bytes
+const roData string = "" + // Size: 5922 bytes
"\x02Eroare\x02(fără argument): obținere drept administrativ și instalare" +
" serviciu de gestionare\x02Utilizare: %[1]s [\x0a%[2]s]\x02Opțiuni linie" +
" de comandă\x02Nu se poate determina dacă procesul rulează sub WOW64: %[" +
@@ -1585,8 +2486,7 @@ const roData string = "" + // Size: 6466 bytes
"d poate fi utilizat doar de către utilizatorii care sunt membri ai grupu" +
"lui Builtin %[1]s.\x02WireGuard rulează, dar interfața cu utilizatorul e" +
"ste accesibilă doar din spațiile de lucru ale grupului Builtin %[1]s." +
- "\x02Pictograma WireGuard din bara de sistem nu a apărut după 30 de secun" +
- "de.\x02Acum\x02Ceasul de sistem a fost dat în spate!\x14\x01\x81\x01\x00" +
+ "\x02Acum\x02Ceasul de sistem a fost dat în spate!\x14\x01\x81\x01\x00" +
"\x04\x0a\x02%[1]d ani\x02\x09\x02%[1]d an\x00\x0d\x02%[1]d de ani\x14" +
"\x01\x81\x01\x00\x04\x0b\x02%[1]d zile\x02\x09\x02%[1]d zi\x00\x0e\x02%[" +
"1]d de zile\x14\x01\x81\x01\x00\x04\x0a\x02%[1]d ore\x02\x0b\x02%[1]d or" +
@@ -1596,145 +2496,165 @@ const roData string = "" + // Size: 6466 bytes
"ecunde\x02acum %[1]s\x02%[1]d\u00a0B\x02%.2[1]f\u00a0KiB\x02%.2[1]f" +
"\u00a0MiB\x02%.2[1]f\u00a0GiB\x02%.2[1]f\u00a0TiB\x02%[1]s: %[2]q\x02Adr" +
"esă IP invalidă\x02Lungimea prefixului de rețea este invalidă\x02Lipseșt" +
- "e portul de la punctul final\x02Gazdă invalidă a punctului final\x02Para" +
- "ntezele trebuie să conțină o adresă IPv6\x02MTU invalidă\x02Port invalid" +
- "\x02Mesaj keepalive persistent invalid\x02Cheie invalidă: %[1]v\x02Rezul" +
- "tatul decodificat de chei trebuie să aibă exact 32 de octeți\x02Numărul " +
- "trebuie să fie cuprins între 0 și 2^64-1: %[1]v\x02Două virgule una după" +
- " cealaltă\x02Numele tunelului nu este valid\x02Linia trebuie să apară în" +
- "tr-o secțiune\x02Cheii de configurare îi lipsește un separator de forma " +
- "semnului egal\x02Cheia trebuie să conțină o valoare\x02Cheie invalidă pe" +
- "ntru secțiunea [Interface]\x02Cheie invalidă pentru secțiunea [Peer]\x02" +
- "O interfață trebuie să aibă o cheie privată\x02[niciuna specificată]\x02" +
- "Toate perechile trebuie să aibă chei publice\x02Eroare la obținerea conf" +
- "igurației\x02Cheie invalidă pentru secțiunea interfeței\x02Versiunea de " +
- "protocol trebuie să fie 1\x02Cheie invalidă pentru secțiunea perechii" +
- "\x02, \x02, \x02Despre WireGuard\x02Imagine siglă WireGuard\x02Versiunea" +
- " aplicației: %[1]s\x0aVersiunea bibliotecii Go: %[2]s\x0aVersiunea Go: %" +
- "[3]s-%[4]s\x0aSistem de operare: %[5]s\x0aArhitectură: %[6]s\x02Închider" +
- "e\x02♥ &Donează!\x02Stare:\x02&Dezactivare\x02&Activare\x02Cheie publică" +
- ":\x02Port de ascultare:\x02MTU:\x02Adrese:\x02Servere DNS:\x02Scripturi:" +
- "\x02Cheie predistribuită:\x02IP-uri permise:\x02Punct final:\x02Mesaj ke" +
- "epalive persistent:\x02Ultimul acord de interogare:\x02Transferare:\x02d" +
- "ezactivat, conform politicii\x02activată\x02%[1]s primit, %[2]s trimis" +
- "\x02Nu a putut fi determinată starea tunelului\x02Tunelul nu a putut fi " +
- "activat\x02Tunelul nu a putut fi dezactivat\x02Interfață: %[1]s\x02Perec" +
- "he\x02Creare tunel nou\x02Editare tunel\x02&Nume:\x02Cheie &publică:\x02" +
- "(necunoscută)\x02&Blochează traficul care nu trece prin tunel (întrerupă" +
- "tor de activitate)\x02Când o configurație conține exact o pereche, iar a" +
- "cea pereche are IP-uri permise care conțin cel puțin o variantă dintre 0" +
- ".0.0.0/0 sau ::/0, atunci serviciul tunelului activează un set de reguli" +
- " al paravanului de protecție pentru a bloca întregul trafic care nu prov" +
- "ine de la interfața tunelului sau care este direcționat către serverul D" +
- "NS greșit, existând excepții speciale pentru DHCP și NDP.\x02&Salvare" +
- "\x02Anulare\x02&Configurație:\x02Nume invalid\x02Este necesar un nume." +
- "\x02Numele tunelului „%[1]s” este invalid.\x02Tunelurile existente nu po" +
- "t fi listate\x02Tunelul există deja\x02Există deja un alt tunel cu numel" +
- "e „%[1]s”.\x02Nu se poate crea configurația nouă\x02Scrierea fișierului " +
- "a eșuat\x02Fișierul „%[1]s” există deja.\x0a\x0aDorești suprascrierea ac" +
- "estuia?\x02Activ\x02Se activează\x02Inactiv\x02Se dezactivează\x02Stare " +
- "necunoscută\x02Jurnal\x02&Copiere\x02Selectare &totală\x02&Salvare în fi" +
- "șier…\x02Timp\x02Mesaj de jurnal\x02Fișiere text (*.txt)|*.txt|Toate fi" +
- "șierele (*.*)|*.*\x02Exportare jurnal în fișier\x02&Despre WireGuard…" +
- "\x02Eroare de tunel\x02%[1]s\x0a\x0aConsultă jurnalul pentru mai multe i" +
- "nformații.\x02%[1]s (neactualizat)\x02Eroare de detectare WireGuard\x02N" +
- "u se poate aștepta ca fereastra WireGuard să apară: %[1]v\x02WireGuard: " +
- "dezactivat\x02Stare: necunoscută\x02Adrese: niciuna\x02&Gestionare tunel" +
- "uri…\x02&Importare tunel(uri) din fișier…\x02Ie&șire\x02WireGuard activa" +
- "t\x02Tunelul %[1]s a fost activat.\x02WireGuard dezactivat\x02Tunelul %[" +
- "1]s a fost dezactivat.\x02Eroare de tunel WireGuard\x02WireGuard: %[1]s" +
- "\x02Stare: %[1]s\x02Adrese: %[1]s\x02Este disponibilă o actualizare!\x02" +
- "Actualizare disponibilă pentru WireGuard\x02O actualizare pentru WireGua" +
- "rd este acum disponibilă. Se recomandă efectuarea actualizării cât mai r" +
- "apid posibil.\x02Tuneluri\x02&Editare\x02Adăugare tunel &gol…\x02Adăugar" +
- "e tunel\x02Eliminare tunel(uri) selectat(e)\x02Exportă toate tunelurile " +
- "în zip\x02&Comutare\x02Exportă toate tunelurile în &zip…\x02Editare tun" +
- "el &selectat…\x02&Eliminare tunel(uri) selectat(e)\x02nu au fost găsite " +
- "fișiere de configurare\x02Configurația selectată nu a putut fi importată" +
- ": %[1]v\x02Tunelurile existente nu au putut fi enumerate: %[1]v\x02Exist" +
- "ă deja un alt tunel cu numele „%[1]s”\x02Configurația nu poate fi impor" +
- "tată: %[1]v\x02Tuneluri importate\x14\x01\x81\x01\x00\x04\x18\x02Importa" +
- "t %[1]d tuneluri\x02\x15\x02Importat %[1]d tunel\x00\x1b\x02Importat %[1" +
- "]d de tuneluri\x14\x02\x80\x01\x04\x22\x02Importat %[1]d din %[2]d tunel" +
- "uri\x02\x1f\x02Importat %[1]d din %[2]d tunel\x00%\x02Importat %[1]d din" +
- " %[2]d de tuneluri\x02Tunelul nu poate fi creat\x14\x01\x81\x01\x00\x04" +
- "\x19\x02Ștergere %[1]d tuneluri\x02\x16\x02Ștergere %[1]d tunel\x00\x1c" +
- "\x02Ștergere %[1]d de tuneluri\x14\x01\x81\x01\x00\x045\x02Ești sigur că" +
- " dorești să ștergi %[1]d tuneluri?\x022\x02Ești sigur că dorești să șter" +
- "gi %[1]d tunel?\x008\x02Ești sigur că dorești să ștergi %[1]d de tunelur" +
- "i?\x02Ștergere tunel „%[1]s”\x02Ești sigur că dorești să ștergi tunelul " +
- "„%[1]s”?\x02%[1]s Această acțiune nu poate fi anulată.\x02Tunelul nu p" +
- "oate fi șters\x02Un tunel nu a putut fi eliminat: %[1]s\x02Nu se pot ște" +
- "rge tunelurile\x14\x01\x81\x01\x00\x04)\x02%[1]d tuneluri nu au putut fi" +
- " eliminate.\x02$\x02%[1]d tunel nu a putut fi eliminat.\x00,\x02%[1]d de" +
- " tuneluri nu au putut fi eliminate.\x02Fișiere de configurare (*.zip, *." +
- "conf)|*.zip;*.conf|Toate fișierele (*.*)|*.*\x02Importare tunel(uri) din" +
- " fișier\x02Fișiere ZIP de configurare (*.zip)|*.zip\x02Exportare tunelur" +
- "i în zip\x02%[1]s (versiune nesemnată, fără actualizări)\x02Eroare la ie" +
- "șirea din WireGuard\x02Nu se poate ieși din serviciu din cauza: %[1]v. " +
- "Poți opri WireGuard din managerul de servicii.\x02Este disponibilă o act" +
- "ualizare pentru WireGuard. Se recomandă ferm actualizarea imediată.\x02S" +
- "tare: se așteaptă utilizatorul\x02Actualizează acum\x02Stare: se așteapt" +
- "ă serviciul de actualizare\x02Eroare: %[1]v. Încearcă din nou.\x02Stare" +
- ": finalizată!\x02pre-pornire\x02post-pornire\x02pre-oprire\x02post-oprir" +
- "e\x02&Tuneluri"
+ "e portul de la punctul final\x02Gazdă invalidă a punctului final\x02MTU " +
+ "invalidă\x02Port invalid\x02Mesaj keepalive persistent invalid\x02Cheie " +
+ "invalidă: %[1]v\x02Numărul trebuie să fie cuprins între 0 și 2^64-1: %[1" +
+ "]v\x02Două virgule una după cealaltă\x02Numele tunelului nu este valid" +
+ "\x02[niciuna specificată]\x02Toate perechile trebuie să aibă chei public" +
+ "e\x02Eroare la obținerea configurației\x02, \x02, \x02Despre WireGuard" +
+ "\x02Imagine siglă WireGuard\x02Închidere\x02♥ &Donează!\x02Stare:\x02&De" +
+ "zactivare\x02&Activare\x02Cheie publică:\x02Port de ascultare:\x02MTU:" +
+ "\x02Adrese:\x02Servere DNS:\x02Cheie predistribuită:\x02IP-uri permise:" +
+ "\x02Punct final:\x02Mesaj keepalive persistent:\x02Ultimul acord de inte" +
+ "rogare:\x02Inactiv\x02Se dezactivează\x02Stare necunoscută\x02Jurnal\x02" +
+ "&Copiere\x02Selectare &totală\x02&Salvare în fișier…\x02Timp\x02Mesaj de" +
+ " jurnal\x02Exportare jurnal în fișier\x02&Despre WireGuard…\x02Eroare de" +
+ " tunel\x02%[1]s\x0a\x0aConsultă jurnalul pentru mai multe informații." +
+ "\x02%[1]s (neactualizat)\x02Eroare la ieșirea din WireGuard\x02Este disp" +
+ "onibilă o actualizare pentru WireGuard. Se recomandă ferm actualizarea i" +
+ "mediată.\x02Actualizează acum\x02Eroare: %[1]v. Încearcă din nou.\x02Sta" +
+ "re: finalizată!\x02Pictograma WireGuard din bara de sistem nu a apărut d" +
+ "upă 30 de secunde.\x02Parantezele trebuie să conțină o adresă IPv6\x02Re" +
+ "zultatul decodificat de chei trebuie să aibă exact 32 de octeți\x02Linia" +
+ " trebuie să apară într-o secțiune\x02Cheii de configurare îi lipsește un" +
+ " separator de forma semnului egal\x02Cheia trebuie să conțină o valoare" +
+ "\x02Cheie invalidă pentru secțiunea [Interface]\x02Cheie invalidă pentru" +
+ " secțiunea [Peer]\x02O interfață trebuie să aibă o cheie privată\x02Chei" +
+ "e invalidă pentru secțiunea interfeței\x02Versiunea de protocol trebuie " +
+ "să fie 1\x02Cheie invalidă pentru secțiunea perechii\x02Scripturi:\x02Tr" +
+ "ansferare:\x02pre-pornire\x02post-pornire\x02pre-oprire\x02post-oprire" +
+ "\x02dezactivat, conform politicii\x02activată\x02%[1]s primit, %[2]s tri" +
+ "mis\x02Nu a putut fi determinată starea tunelului\x02Tunelul nu a putut " +
+ "fi activat\x02Tunelul nu a putut fi dezactivat\x02Interfață: %[1]s\x02Pe" +
+ "reche\x02Creare tunel nou\x02Editare tunel\x02&Nume:\x02Cheie &publică:" +
+ "\x02(necunoscută)\x02&Blochează traficul care nu trece prin tunel (între" +
+ "rupător de activitate)\x02&Salvare\x02Anulare\x02&Configurație:\x02Nume " +
+ "invalid\x02Este necesar un nume.\x02Numele tunelului „%[1]s” este invali" +
+ "d.\x02Tunelurile existente nu pot fi listate\x02Tunelul există deja\x02E" +
+ "xistă deja un alt tunel cu numele „%[1]s”.\x02Nu se poate crea configura" +
+ "ția nouă\x02Scrierea fișierului a eșuat\x02Fișierul „%[1]s” există deja" +
+ ".\x0a\x0aDorești suprascrierea acestuia?\x02Activ\x02Se activează\x02Fiș" +
+ "iere text (*.txt)|*.txt|Toate fișierele (*.*)|*.*\x02Eroare de detectare" +
+ " WireGuard\x02Nu se poate aștepta ca fereastra WireGuard să apară: %[1]v" +
+ "\x02WireGuard: dezactivat\x02Stare: necunoscută\x02Adrese: niciuna\x02&G" +
+ "estionare tuneluri…\x02&Importare tunel(uri) din fișier…\x02Ie&șire\x02&" +
+ "Tuneluri\x02WireGuard activat\x02Tunelul %[1]s a fost activat.\x02WireGu" +
+ "ard dezactivat\x02Tunelul %[1]s a fost dezactivat.\x02Eroare de tunel Wi" +
+ "reGuard\x02WireGuard: %[1]s\x02Stare: %[1]s\x02Adrese: %[1]s\x02Este dis" +
+ "ponibilă o actualizare!\x02Actualizare disponibilă pentru WireGuard\x02O" +
+ " actualizare pentru WireGuard este acum disponibilă. Se recomandă efectu" +
+ "area actualizării cât mai rapid posibil.\x02Tuneluri\x02&Editare\x02Adău" +
+ "gare tunel &gol…\x02Adăugare tunel\x02Eliminare tunel(uri) selectat(e)" +
+ "\x02Exportă toate tunelurile în zip\x02&Comutare\x02Exportă toate tunelu" +
+ "rile în &zip…\x02Editare tunel &selectat…\x02&Eliminare tunel(uri) selec" +
+ "tat(e)\x02nu au fost găsite fișiere de configurare\x02Configurația selec" +
+ "tată nu a putut fi importată: %[1]v\x02Tunelurile existente nu au putut " +
+ "fi enumerate: %[1]v\x02Există deja un alt tunel cu numele „%[1]s”\x02Con" +
+ "figurația nu poate fi importată: %[1]v\x02Tuneluri importate\x14\x01\x81" +
+ "\x01\x00\x04\x18\x02Importat %[1]d tuneluri\x02\x15\x02Importat %[1]d tu" +
+ "nel\x00\x1b\x02Importat %[1]d de tuneluri\x14\x02\x80\x01\x04\x22\x02Imp" +
+ "ortat %[1]d din %[2]d tuneluri\x02\x1f\x02Importat %[1]d din %[2]d tunel" +
+ "\x00%\x02Importat %[1]d din %[2]d de tuneluri\x02Tunelul nu poate fi cre" +
+ "at\x14\x01\x81\x01\x00\x04\x19\x02Ștergere %[1]d tuneluri\x02\x16\x02Ște" +
+ "rgere %[1]d tunel\x00\x1c\x02Ștergere %[1]d de tuneluri\x14\x01\x81\x01" +
+ "\x00\x045\x02Ești sigur că dorești să ștergi %[1]d tuneluri?\x022\x02Eșt" +
+ "i sigur că dorești să ștergi %[1]d tunel?\x008\x02Ești sigur că dorești " +
+ "să ștergi %[1]d de tuneluri?\x02Ștergere tunel „%[1]s”\x02Ești sigur că " +
+ "dorești să ștergi tunelul „%[1]s”?\x02%[1]s Această acțiune nu poate fi " +
+ "anulată.\x02Tunelul nu poate fi șters\x02Un tunel nu a putut fi eliminat" +
+ ": %[1]s\x02Nu se pot șterge tunelurile\x14\x01\x81\x01\x00\x04)\x02%[1]d" +
+ " tuneluri nu au putut fi eliminate.\x02$\x02%[1]d tunel nu a putut fi el" +
+ "iminat.\x00,\x02%[1]d de tuneluri nu au putut fi eliminate.\x02Fișiere d" +
+ "e configurare (*.zip, *.conf)|*.zip;*.conf|Toate fișierele (*.*)|*.*\x02" +
+ "Importare tunel(uri) din fișier\x02Fișiere ZIP de configurare (*.zip)|*." +
+ "zip\x02Exportare tuneluri în zip\x02%[1]s (versiune nesemnată, fără actu" +
+ "alizări)\x02Nu se poate ieși din serviciu din cauza: %[1]v. Poți opri Wi" +
+ "reGuard din managerul de servicii.\x02Stare: se așteaptă utilizatorul" +
+ "\x02Stare: se așteaptă serviciul de actualizare"
-var ruIndex = []uint32{ // 181 elements
+var ruIndex = []uint32{ // 278 elements
// Entry 0 - 1F
0x00000000, 0x0000000d, 0x000000a9, 0x000000d4,
0x00000107, 0x00000166, 0x000001c9, 0x00000220,
- 0x000002a7, 0x0000034b, 0x000003b3, 0x000003c0,
- 0x000003fd, 0x0000042a, 0x00000457, 0x00000484,
- 0x000004c1, 0x000004fe, 0x0000050f, 0x00000518,
- 0x00000525, 0x00000532, 0x0000053f, 0x0000054c,
- 0x00000559, 0x00000580, 0x000005be, 0x000005fd,
- 0x0000062b, 0x00000663, 0x00000680, 0x000006a2,
+ 0x000002a7, 0x0000034b, 0x00000358, 0x00000395,
+ 0x000003c2, 0x000003ef, 0x0000041c, 0x00000459,
+ 0x00000496, 0x000004a7, 0x000004b0, 0x000004bd,
+ 0x000004ca, 0x000004d7, 0x000004e4, 0x000004f1,
+ 0x00000518, 0x00000556, 0x00000595, 0x000005c3,
+ 0x000005e0, 0x00000602, 0x00000658, 0x00000681,
// Entry 20 - 3F
- 0x000006f8, 0x00000721, 0x00000776, 0x000007b5,
- 0x000007d8, 0x00000817, 0x0000084a, 0x0000089f,
- 0x000008d1, 0x0000090b, 0x00000940, 0x0000098a,
- 0x000009a0, 0x000009e6, 0x00000a26, 0x00000a69,
- 0x00000aa1, 0x00000ae8, 0x00000aeb, 0x00000aee,
- 0x00000afb, 0x00000b14, 0x00000bcd, 0x00000bdc,
- 0x00000bfb, 0x00000c09, 0x00000c1d, 0x00000c33,
- 0x00000c50, 0x00000c5a, 0x00000c5f, 0x00000c70,
+ 0x000006c0, 0x000006e3, 0x00000722, 0x00000738,
+ 0x0000077e, 0x000007be, 0x000007c1, 0x000007c4,
+ 0x000007d1, 0x000007ea, 0x000007f9, 0x00000818,
+ 0x00000826, 0x0000083a, 0x00000850, 0x0000086d,
+ 0x00000877, 0x0000087c, 0x0000088d, 0x000008a1,
+ 0x000008b6, 0x000008de, 0x000008fc, 0x0000092d,
+ 0x00000958, 0x00000969, 0x0000097e, 0x000009a8,
+ 0x000009b5, 0x000009cd, 0x000009e4, 0x00000a07,
// Entry 40 - 5F
- 0x00000c84, 0x00000c94, 0x00000ca9, 0x00000cd1,
- 0x00000cef, 0x00000d20, 0x00000d4b, 0x00000d5d,
- 0x00000d87, 0x00000d98, 0x00000dcb, 0x00000e16,
- 0x00000e4e, 0x00000e84, 0x00000e9e, 0x00000ea5,
- 0x00000ec3, 0x00000eed, 0x00000f00, 0x00000f1e,
- 0x00000f35, 0x00000f7d, 0x00001186, 0x0000119a,
- 0x000011a7, 0x000011c2, 0x000011ec, 0x00001213,
- 0x00001257, 0x0000128f, 0x000012ba, 0x00001302,
+ 0x00000a12, 0x00000a34, 0x00000a5e, 0x00000a6f,
+ 0x00000a8b, 0x00000b06, 0x00000b1d, 0x00000b46,
+ 0x00000bce, 0x00000bec, 0x00000c25, 0x00000c47,
+ 0x00000caf, 0x00000ce7, 0x00000d3c, 0x00000d6f,
+ 0x00000dc4, 0x00000df6, 0x00000e30, 0x00000e65,
+ 0x00000eaf, 0x00000ef2, 0x00000f2a, 0x00000f71,
+ 0x00000f81, 0x00000f93, 0x00000fb7, 0x00000fd9,
+ 0x00000ffb, 0x0000101b, 0x00001045, 0x00001056,
// Entry 60 - 7F
- 0x00001349, 0x0000136e, 0x000013d0, 0x000013e3,
- 0x000013fa, 0x0000140b, 0x00001420, 0x0000144a,
- 0x00001457, 0x0000146f, 0x00001486, 0x000014a9,
- 0x000014b4, 0x000014d6, 0x0000151e, 0x00001548,
- 0x00001559, 0x00001575, 0x000015f0, 0x00001607,
- 0x00001635, 0x00001689, 0x000016af, 0x000016d2,
- 0x000016e7, 0x00001713, 0x00001745, 0x00001751,
- 0x0000176a, 0x00001793, 0x000017ae, 0x000017d5,
+ 0x00001089, 0x000010d4, 0x0000110c, 0x00001142,
+ 0x0000115c, 0x00001163, 0x00001181, 0x000011ab,
+ 0x000011be, 0x000011dc, 0x000011f3, 0x0000123b,
+ 0x0000124f, 0x0000125c, 0x00001277, 0x000012a1,
+ 0x000012c8, 0x0000130c, 0x00001344, 0x0000136f,
+ 0x000013b7, 0x000013fe, 0x00001423, 0x00001485,
+ 0x00001498, 0x000014af, 0x000014f7, 0x00001525,
+ 0x00001579, 0x0000159f, 0x000015c2, 0x000015d7,
// Entry 80 - 9F
- 0x000017fb, 0x0000180c, 0x00001820, 0x00001834,
- 0x0000185b, 0x0000188b, 0x00001916, 0x00001925,
- 0x00001941, 0x00001972, 0x00001992, 0x000019c3,
- 0x000019fe, 0x00001a16, 0x00001a55, 0x00001a96,
- 0x00001ac8, 0x00001b09, 0x00001b59, 0x00001bb3,
- 0x00001bfa, 0x00001c4a, 0x00001c78, 0x00001d4c,
- 0x00001e48, 0x00001e7a, 0x00001f1a, 0x00002062,
- 0x0000208c, 0x000020dc, 0x00002127, 0x00002159,
+ 0x00001603, 0x00001635, 0x00001641, 0x00001651,
+ 0x0000166a, 0x00001693, 0x000016ae, 0x000016d5,
+ 0x000016fb, 0x0000170c, 0x00001720, 0x00001734,
+ 0x0000175b, 0x0000178b, 0x00001816, 0x00001825,
+ 0x00001841, 0x00001872, 0x00001892, 0x000018c3,
+ 0x000018fe, 0x00001916, 0x00001955, 0x00001996,
+ 0x000019c8, 0x00001a09, 0x00001a59, 0x00001ab3,
+ 0x00001afa, 0x00001b4a, 0x00001b78, 0x00001c4c,
// Entry A0 - BF
- 0x00002193, 0x000021c5, 0x000022bc, 0x00002319,
- 0x00002347, 0x0000237f, 0x000023b1, 0x000023fe,
- 0x00002427, 0x000024c1, 0x00002549, 0x00002581,
- 0x0000259f, 0x000025d3, 0x0000260c, 0x0000262e,
- 0x00002652, 0x00002674, 0x00002696, 0x000026b6,
- 0x000026c6,
-} // Size: 748 bytes
+ 0x00001d48, 0x00001d7a, 0x00001e1a, 0x00001f62,
+ 0x00001f8c, 0x00001fdc, 0x00002027, 0x00002059,
+ 0x00002093, 0x000020c5, 0x000021bc, 0x00002219,
+ 0x00002247, 0x0000227f, 0x000022b1, 0x000022fe,
+ 0x00002398, 0x000023d0, 0x00002404, 0x00002404,
+ 0x00002404, 0x00002404, 0x00002404, 0x00002404,
+ 0x00002404, 0x00002404, 0x00002404, 0x00002404,
+ 0x00002404, 0x00002404, 0x00002404, 0x00002404,
+ // Entry C0 - DF
+ 0x00002404, 0x00002404, 0x00002404, 0x00002404,
+ 0x00002404, 0x00002404, 0x00002404, 0x00002404,
+ 0x00002404, 0x00002404, 0x00002404, 0x00002404,
+ 0x00002404, 0x00002404, 0x00002404, 0x00002404,
+ 0x00002404, 0x00002404, 0x00002404, 0x00002404,
+ 0x00002404, 0x00002404, 0x00002404, 0x00002404,
+ 0x00002404, 0x00002404, 0x00002404, 0x00002404,
+ 0x00002404, 0x00002404, 0x00002404, 0x00002404,
+ // Entry E0 - FF
+ 0x00002404, 0x00002404, 0x00002404, 0x00002404,
+ 0x00002404, 0x00002404, 0x00002404, 0x00002404,
+ 0x00002404, 0x00002404, 0x00002404, 0x00002404,
+ 0x00002404, 0x00002404, 0x00002404, 0x00002404,
+ 0x00002404, 0x00002404, 0x00002404, 0x00002404,
+ 0x00002404, 0x00002404, 0x00002404, 0x00002404,
+ 0x00002404, 0x00002404, 0x00002404, 0x00002404,
+ 0x00002404, 0x00002404, 0x00002404, 0x00002404,
+ // Entry 100 - 11F
+ 0x00002404, 0x00002404, 0x00002404, 0x00002404,
+ 0x00002404, 0x00002404, 0x00002404, 0x00002404,
+ 0x00002404, 0x00002404, 0x00002404, 0x00002404,
+ 0x00002404, 0x00002404, 0x00002404, 0x00002404,
+ 0x00002404, 0x00002404, 0x00002404, 0x00002404,
+ 0x00002404, 0x00002404,
+} // Size: 1136 bytes
-const ruData string = "" + // Size: 9926 bytes
+const ruData string = "" + // Size: 9220 bytes
"\x02Ошибка\x02(нет аргумента): получить права администратора и установит" +
"ь административную службу\x02Использование: %[1]s [\x0a%[2]s]\x02Параме" +
"тры командной строки\x02Ошибка определения или процесс работает как WOW" +
@@ -1742,255 +2662,459 @@ const ruData string = "" + // Size: 9926 bytes
"\x02Не удается открыть токен текущего процесса: %[1]v\x02WireGuard может" +
" использоваться только пользователями, входящими в группу %[1]s.\x02Wire" +
"Guard запущен, но пользовательский интерфейс доступен только с рабочих с" +
- "толов группы %[1]s.\x02Значок в системном трее WireGuard не появился по" +
- "сле 30 секунд.\x02Сейчас\x02Системные часы переведены назад!\x14\x01" +
- "\x81\x01\x00\x04\x08\x02%[1]dг\x05\x08\x02%[1]dг\x02\x08\x02%[1]dг\x00" +
- "\x08\x02%[1]dг\x14\x01\x81\x01\x00\x04\x08\x02%[1]dд\x05\x08\x02%[1]dд" +
- "\x02\x08\x02%[1]dд\x00\x08\x02%[1]dд\x14\x01\x81\x01\x00\x04\x08\x02%[1]" +
- "dч\x05\x08\x02%[1]dч\x02\x08\x02%[1]dч\x00\x08\x02%[1]dч\x14\x01\x81\x01" +
- "\x00\x04\x0c\x02%[1]dмин\x05\x0c\x02%[1]dмин\x02\x0c\x02%[1]dмин\x00\x0c" +
- "\x02%[1]dмин\x14\x01\x81\x01\x00\x04\x0c\x02%[1]dсек\x05\x0c\x02%[1]dсек" +
- "\x02\x0c\x02%[1]dсек\x00\x0c\x02%[1]dсек\x02%[1]s назад\x02%[1]d Б\x02%." +
- "2[1]f Кб\x02%.2[1]f Мб\x02%.2[1]f Гб\x02%.2[1]f Тб\x02%[1]s: %[2]q\x02Не" +
- "допустимый IP-адрес\x02Недопустимая длина префикса сети\x02Отсутствует " +
- "порт IP-адреса сервера\x02Неверный IP-адрес сервера\x02В скобках должен" +
- " быть IPv6 адрес\x02Недопустимый MTU\x02Недопустимый порт\x02Недопустимо" +
- "е значение поддержания соединения\x02Недопустимый ключ: %[1]v\x02Ключи " +
- "должны декодироваться ровно с 32 байтами\x02Число должно быть между 0 и" +
- " 2^64-1: %[1]v\x02Две запятые подряд\x02Название туннеля недействительно" +
- "\x02Строка должна быть в секции\x02В ключе конфигурации отсутствует разд" +
- "елитель\x02Ключ должен иметь значение\x02Неверный ключ для секции [Inte" +
- "rface]\x02Неверный ключ для секции [Peer]\x02В Интерфейсе должен быть пр" +
- "иватный ключ\x02[не указано]\x02Все пиры должны иметь публичные ключи" +
- "\x02Ошибка при получении конфигурации\x02Неверный ключ для секции Интерф" +
- "ейса\x02Версия протокола должна быть 1\x02Недействительный ключ для сек" +
- "ции пира\x02, \x02, \x02О WireGuard\x02Логотип WireGuard\x02Версия прил" +
- "ожения: %[1]s\x0aВерсия Go-бэкенда: %[2]s\x0aВерсия Go: %[3]s-%[4]s\x0a" +
- "Операционная система: %[5]s\x0aАрхитектура: %[6]s\x02Закрыть\x02♥ &Поже" +
- "ртвовать!\x02Статус:\x02&Отключить\x02&Подключить\x02Публичный ключ:" +
- "\x02Порт:\x02MTU:\x02IP-адреса:\x02DNS-серверы:\x02Скрипты:\x02Общий клю" +
- "ч:\x02Разрешенные IP-адреса:\x02IP-адрес сервера:\x02Поддерживание соед" +
- "инения:\x02Последнее рукопожатие:\x02Передача:\x02отключено, по политик" +
- "е\x02включено\x02Получено %[1]s, отправлено %[2]s\x02Не удалось определ" +
- "ить состояние туннеля\x02Не удалось подключить туннель\x02Не удалось от" +
- "ключить туннель\x02Интерфейс: %[1]s\x02Пир\x02Создать туннель\x02Редакт" +
- "ировать туннель\x02&Название:\x02&Публичный ключ:\x02(неизвестно)\x02&Б" +
- "локировать нетуннелированный трафик\x02Если конфигурация имеет ровно од" +
- "ин пир, а этот пир имеет разрешенные IP, содержащие хотя бы один из 0.0" +
- ".0.0/0 или ::/0, то туннельный сервис использует набор правил брандмауэр" +
- "а для блокирования всего трафика, который не проходит через туннель или" +
- " к неверным DNS-серверам, за исключением DHCP и NDP.\x02&Сохранить\x02От" +
- "мена\x02&Конфигурация:\x02Некорректное название\x02Необходимо название." +
- "\x02Название туннеля ‘%[1]s’ недопустимо.\x02Не удалось отобразить тунне" +
- "ли\x02Туннель уже существует\x02Туннель с именем ’%[1]s’ уже существует" +
- ".\x02Не удалось создать новую конфигурацию\x02Ошибка записи файла\x02Фай" +
- "л '%[1]s' уже существует!\x0a\x0aВы хотите перезаписать его?\x02Подключ" +
- "ен\x02Подключение\x02Отключен\x02Отключение\x02Неизвестное состояние" +
- "\x02Журнал\x02&Скопировать\x02Выбрать &все\x02&Сохранить в файл…\x02Врем" +
- "я\x02Сообщение журнала\x02Текстовые файлы (*.txt)|*.txt|Все файлы (*.*)" +
- "|*.*\x02Экспорт журнала в файл\x02&О WireGuard…\x02Ошибка туннеля\x02%[1" +
- "]s\x0a\x0aОбратитесь к журналу для получения дополнительной информации." +
- "\x02%[1]s (устарел)\x02Ошибка обнаружения WireGuard\x02Не удалось дождат" +
- "ься появления окна WireGuard: %[1]v\x02WireGuard: Деактивирован\x02Стат" +
- "ус: Неизвестен\x02Адреса: нет\x02&Управление туннелями…\x02&Импорт тунн" +
- "елей из файла…\x02Вы&ход\x02WireGuard Включен\x02Туннель %[1]s подключе" +
- "н.\x02WireGuard Выключен\x02Туннель %[1]s отключен.\x02Ошибка туннеля W" +
- "ireGuard\x02WireGuard: %[1]s\x02Статус: %[1]s\x02Адреса: %[1]s\x02Доступ" +
- "но обновление!\x02Доступно обновление WireGuard\x02Доступно обновление " +
- "для WireGuard. Рекомендуется обновить его как можно скорее.\x02Туннели" +
- "\x02&Редактировать\x02Добавить &пустой туннель…\x02Добавить туннель\x02У" +
- "далить выбранные туннели\x02Экспорт всех туннелей в zip-архив\x02&Перек" +
- "лючить\x02Экспорт всех туннелей в &zip-архив…\x02Редактировать &выбранн" +
- "ый туннель…\x02&Удалить выбранные туннели\x02файлы конфигурации не были" +
- " найдены\x02Невозможно импортировать конфигурацию: %[1]v\x02Не удалось п" +
- "еречислить существующие туннели: %[1]v\x02Туннель с именем ’%[1]s’ уже " +
- "существует\x02Невозможно импортировать конфигурацию: %[1]v\x02Импортиро" +
- "ванные туннели\x14\x01\x81\x01\x00\x041\x02Импортированы туннели: %[1]d" +
- "\x051\x02Импортированы туннели: %[1]d\x024\x02Импортированный %[1]d тунн" +
- "ель\x001\x02Импортированы туннели: %[1]d\x14\x02\x80\x01\x04<\x02Импорт" +
- "ированы туннели: %[1]d из %[2]d\x05<\x02Импортированы туннели: %[1]d из" +
- " %[2]d\x02<\x02Импортированы туннели: %[1]d из %[2]d\x00<\x02Импортирова" +
- "ны туннели: %[1]d из %[2]d\x02Не удалось создать туннель\x14\x01\x81" +
- "\x01\x00\x04%\x02Удалить туннели: %[1]d\x05%\x02Удалить туннели: %[1]d" +
- "\x02$\x02Удалить %[1]d туннель\x00%\x02Удалить туннели: %[1]d\x14\x01" +
- "\x81\x01\x00\x04O\x02Вы уверены, что хотите удалить туннели: %[1]d?\x05O" +
- "\x02Вы уверены, что хотите удалить туннели: %[1]d?\x02N\x02Вы уверены, ч" +
- "то хотите удалить %[1]d туннель?\x00O\x02Вы уверены, что хотите удалить" +
- " туннели: %[1]d?\x02Удалить туннель ‘%[1]s’\x02Вы уверены, что хотите уд" +
- "алить '%[1]s' туннель?\x02%[1]s Данное действие невозможно отменить." +
- "\x02Не удалось удалить туннель\x02Невозможно удалить туннель: %[1]s\x02Н" +
- "е удалось удалить туннели\x14\x01\x81\x01\x00\x04;\x02туннелей не удало" +
- "сь удалить: %[1]d\x05;\x02туннелей не удалось удалить: %[1]d\x029\x02%[" +
- "1]d туннель не удалось удалить.\x00;\x02туннелей не удалось удалить: %[1" +
- "]d\x02Файлы конфигурации (*.zip, *.conf)|*.zip;*.conf|Все файлы (*.*)|*." +
- "*\x02Импорт туннелей из файла\x02Конфигурация ZIP файлов (*.zip)|*.zip" +
- "\x02Экспорт туннелей в zip-архив\x02%[1]s (неподписанная сборка, нет обн" +
- "овлений)\x02Ошибка выхода из WireGuard\x02Не удается выйти из сервиса и" +
- "з-за: %[1]v. Вы можете остановить WireGuard из менеджера служб.\x02Дост" +
- "упно обновление WireGuard. Настоятельно рекомендуем обновить приложение" +
- ".\x02Статус: Ожидание пользователя\x02Обновить Сейчас\x02Статус: Ожидани" +
- "е обновления\x02Ошибка: %[1]v. Попробуйте еще раз.\x02Статус: Завершено" +
- "!\x02перед подключением\x02после подключения\x02перед отключением\x02пос" +
- "ле отключения\x02&Туннели"
+ "толов группы %[1]s.\x02Сейчас\x02Системные часы переведены назад!\x14" +
+ "\x01\x81\x01\x00\x04\x08\x02%[1]dг\x05\x08\x02%[1]dг\x02\x08\x02%[1]dг" +
+ "\x00\x08\x02%[1]dг\x14\x01\x81\x01\x00\x04\x08\x02%[1]dд\x05\x08\x02%[1]" +
+ "dд\x02\x08\x02%[1]dд\x00\x08\x02%[1]dд\x14\x01\x81\x01\x00\x04\x08\x02%[" +
+ "1]dч\x05\x08\x02%[1]dч\x02\x08\x02%[1]dч\x00\x08\x02%[1]dч\x14\x01\x81" +
+ "\x01\x00\x04\x0c\x02%[1]dмин\x05\x0c\x02%[1]dмин\x02\x0c\x02%[1]dмин\x00" +
+ "\x0c\x02%[1]dмин\x14\x01\x81\x01\x00\x04\x0c\x02%[1]dсек\x05\x0c\x02%[1]" +
+ "dсек\x02\x0c\x02%[1]dсек\x00\x0c\x02%[1]dсек\x02%[1]s назад\x02%[1]d Б" +
+ "\x02%.2[1]f Кб\x02%.2[1]f Мб\x02%.2[1]f Гб\x02%.2[1]f Тб\x02%[1]s: %[2]q" +
+ "\x02Недопустимый IP-адрес\x02Недопустимая длина префикса сети\x02Отсутст" +
+ "вует порт IP-адреса сервера\x02Неверный IP-адрес сервера\x02Недопустимы" +
+ "й MTU\x02Недопустимый порт\x02Недопустимое значение поддержания соедине" +
+ "ния\x02Недопустимый ключ: %[1]v\x02Число должно быть между 0 и 2^64-1: " +
+ "%[1]v\x02Две запятые подряд\x02Название туннеля недействительно\x02[не у" +
+ "казано]\x02Все пиры должны иметь публичные ключи\x02Ошибка при получени" +
+ "и конфигурации\x02, \x02, \x02О WireGuard\x02Логотип WireGuard\x02Закры" +
+ "ть\x02♥ &Пожертвовать!\x02Статус:\x02&Отключить\x02&Подключить\x02Публи" +
+ "чный ключ:\x02Порт:\x02MTU:\x02IP-адреса:\x02DNS-серверы:\x02Общий ключ" +
+ ":\x02Разрешенные IP-адреса:\x02IP-адрес сервера:\x02Поддерживание соедин" +
+ "ения:\x02Последнее рукопожатие:\x02Отключен\x02Отключение\x02Неизвестно" +
+ "е состояние\x02Журнал\x02&Скопировать\x02Выбрать &все\x02&Сохранить в ф" +
+ "айл…\x02Время\x02Сообщение журнала\x02Экспорт журнала в файл\x02&О Wire" +
+ "Guard…\x02Ошибка туннеля\x02%[1]s\x0a\x0aОбратитесь к журналу для получе" +
+ "ния дополнительной информации.\x02%[1]s (устарел)\x02Ошибка выхода из W" +
+ "ireGuard\x02Доступно обновление WireGuard. Настоятельно рекомендуем обно" +
+ "вить приложение.\x02Обновить Сейчас\x02Ошибка: %[1]v. Попробуйте еще ра" +
+ "з.\x02Статус: Завершено!\x02Значок в системном трее WireGuard не появил" +
+ "ся после 30 секунд.\x02В скобках должен быть IPv6 адрес\x02Ключи должны" +
+ " декодироваться ровно с 32 байтами\x02Строка должна быть в секции\x02В к" +
+ "люче конфигурации отсутствует разделитель\x02Ключ должен иметь значение" +
+ "\x02Неверный ключ для секции [Interface]\x02Неверный ключ для секции [Pe" +
+ "er]\x02В Интерфейсе должен быть приватный ключ\x02Неверный ключ для секц" +
+ "ии Интерфейса\x02Версия протокола должна быть 1\x02Недействительный клю" +
+ "ч для секции пира\x02Скрипты:\x02Передача:\x02перед подключением\x02пос" +
+ "ле подключения\x02перед отключением\x02после отключения\x02отключено, п" +
+ "о политике\x02включено\x02Получено %[1]s, отправлено %[2]s\x02Не удалос" +
+ "ь определить состояние туннеля\x02Не удалось подключить туннель\x02Не у" +
+ "далось отключить туннель\x02Интерфейс: %[1]s\x02Пир\x02Создать туннель" +
+ "\x02Редактировать туннель\x02&Название:\x02&Публичный ключ:\x02(неизвест" +
+ "но)\x02&Блокировать нетуннелированный трафик\x02&Сохранить\x02Отмена" +
+ "\x02&Конфигурация:\x02Некорректное название\x02Необходимо название.\x02Н" +
+ "азвание туннеля ‘%[1]s’ недопустимо.\x02Не удалось отобразить туннели" +
+ "\x02Туннель уже существует\x02Туннель с именем ’%[1]s’ уже существует." +
+ "\x02Не удалось создать новую конфигурацию\x02Ошибка записи файла\x02Файл" +
+ " '%[1]s' уже существует!\x0a\x0aВы хотите перезаписать его?\x02Подключен" +
+ "\x02Подключение\x02Текстовые файлы (*.txt)|*.txt|Все файлы (*.*)|*.*\x02" +
+ "Ошибка обнаружения WireGuard\x02Не удалось дождаться появления окна Wir" +
+ "eGuard: %[1]v\x02WireGuard: Деактивирован\x02Статус: Неизвестен\x02Адрес" +
+ "а: нет\x02&Управление туннелями…\x02&Импорт туннелей из файла…\x02Вы&хо" +
+ "д\x02&Туннели\x02WireGuard Включен\x02Туннель %[1]s подключен.\x02WireG" +
+ "uard Выключен\x02Туннель %[1]s отключен.\x02Ошибка туннеля WireGuard\x02" +
+ "WireGuard: %[1]s\x02Статус: %[1]s\x02Адреса: %[1]s\x02Доступно обновлени" +
+ "е!\x02Доступно обновление WireGuard\x02Доступно обновление для WireGuar" +
+ "d. Рекомендуется обновить его как можно скорее.\x02Туннели\x02&Редактиро" +
+ "вать\x02Добавить &пустой туннель…\x02Добавить туннель\x02Удалить выбран" +
+ "ные туннели\x02Экспорт всех туннелей в zip-архив\x02&Переключить\x02Экс" +
+ "порт всех туннелей в &zip-архив…\x02Редактировать &выбранный туннель…" +
+ "\x02&Удалить выбранные туннели\x02файлы конфигурации не были найдены\x02" +
+ "Невозможно импортировать конфигурацию: %[1]v\x02Не удалось перечислить " +
+ "существующие туннели: %[1]v\x02Туннель с именем ’%[1]s’ уже существует" +
+ "\x02Невозможно импортировать конфигурацию: %[1]v\x02Импортированные тунн" +
+ "ели\x14\x01\x81\x01\x00\x041\x02Импортированы туннели: %[1]d\x051\x02Им" +
+ "портированы туннели: %[1]d\x024\x02Импортированный %[1]d туннель\x001" +
+ "\x02Импортированы туннели: %[1]d\x14\x02\x80\x01\x04<\x02Импортированы т" +
+ "уннели: %[1]d из %[2]d\x05<\x02Импортированы туннели: %[1]d из %[2]d" +
+ "\x02<\x02Импортированы туннели: %[1]d из %[2]d\x00<\x02Импортированы тун" +
+ "нели: %[1]d из %[2]d\x02Не удалось создать туннель\x14\x01\x81\x01\x00" +
+ "\x04%\x02Удалить туннели: %[1]d\x05%\x02Удалить туннели: %[1]d\x02$\x02У" +
+ "далить %[1]d туннель\x00%\x02Удалить туннели: %[1]d\x14\x01\x81\x01\x00" +
+ "\x04O\x02Вы уверены, что хотите удалить туннели: %[1]d?\x05O\x02Вы увере" +
+ "ны, что хотите удалить туннели: %[1]d?\x02N\x02Вы уверены, что хотите у" +
+ "далить %[1]d туннель?\x00O\x02Вы уверены, что хотите удалить туннели: %" +
+ "[1]d?\x02Удалить туннель ‘%[1]s’\x02Вы уверены, что хотите удалить '%[1]" +
+ "s' туннель?\x02%[1]s Данное действие невозможно отменить.\x02Не удалось " +
+ "удалить туннель\x02Невозможно удалить туннель: %[1]s\x02Не удалось удал" +
+ "ить туннели\x14\x01\x81\x01\x00\x04;\x02туннелей не удалось удалить: %[" +
+ "1]d\x05;\x02туннелей не удалось удалить: %[1]d\x029\x02%[1]d туннель не " +
+ "удалось удалить.\x00;\x02туннелей не удалось удалить: %[1]d\x02Файлы ко" +
+ "нфигурации (*.zip, *.conf)|*.zip;*.conf|Все файлы (*.*)|*.*\x02Импорт т" +
+ "уннелей из файла\x02Конфигурация ZIP файлов (*.zip)|*.zip\x02Экспорт ту" +
+ "ннелей в zip-архив\x02%[1]s (неподписанная сборка, нет обновлений)\x02Н" +
+ "е удается выйти из сервиса из-за: %[1]v. Вы можете остановить WireGuard" +
+ " из менеджера служб.\x02Статус: Ожидание пользователя\x02Статус: Ожидани" +
+ "е обновления"
+
+var si_LKIndex = []uint32{ // 278 elements
+ // Entry 0 - 1F
+ 0x00000000, 0x00000013, 0x00000013, 0x00000036,
+ 0x00000036, 0x00000036, 0x00000036, 0x00000036,
+ 0x00000036, 0x00000036, 0x00000043, 0x00000043,
+ 0x00000084, 0x000000b3, 0x000000dc, 0x00000117,
+ 0x0000014c, 0x00000160, 0x0000016c, 0x00000180,
+ 0x00000194, 0x000001a8, 0x000001bc, 0x000001c9,
+ 0x00000212, 0x00000212, 0x00000212, 0x00000212,
+ 0x00000212, 0x0000024b, 0x0000024b, 0x0000027c,
+ // Entry 20 - 3F
+ 0x0000027c, 0x000002be, 0x000002be, 0x000002be,
+ 0x000002be, 0x000002be, 0x000002c1, 0x000002c4,
+ 0x000002f3, 0x000002f3, 0x00000303, 0x00000325,
+ 0x00000336, 0x00000336, 0x00000336, 0x00000336,
+ 0x00000366, 0x00000366, 0x00000377, 0x000003a1,
+ 0x000003a1, 0x000003c8, 0x000003c8, 0x000003c8,
+ 0x000003c8, 0x000003c8, 0x000003c8, 0x000003f4,
+ 0x000003f4, 0x00000408, 0x00000408, 0x0000043b,
+ // Entry 40 - 5F
+ 0x0000044b, 0x0000044b, 0x0000044b, 0x0000047e,
+ 0x0000047e, 0x0000047e, 0x000004ae, 0x000004f6,
+ 0x000004f6, 0x0000051f, 0x00000562, 0x00000593,
+ 0x00000593, 0x00000593, 0x00000593, 0x00000593,
+ 0x00000593, 0x000005d3, 0x000005d3, 0x000005d3,
+ 0x00000644, 0x00000644, 0x00000698, 0x00000698,
+ 0x00000698, 0x00000698, 0x00000698, 0x00000698,
+ 0x00000698, 0x00000698, 0x00000698, 0x000006b0,
+ // Entry 60 - 7F
+ 0x000006e3, 0x000006e3, 0x000006e3, 0x000006e3,
+ 0x0000070c, 0x0000070c, 0x0000070c, 0x0000070c,
+ 0x00000715, 0x00000715, 0x00000727, 0x00000727,
+ 0x00000741, 0x00000754, 0x00000772, 0x0000079c,
+ 0x000007c3, 0x000007c3, 0x000007c3, 0x000007c3,
+ 0x000007c3, 0x00000812, 0x0000084e, 0x0000084e,
+ 0x0000084e, 0x00000883, 0x00000883, 0x00000883,
+ 0x00000905, 0x00000905, 0x00000926, 0x00000926,
+ // Entry 80 - 9F
+ 0x00000926, 0x00000926, 0x0000093d, 0x0000093d,
+ 0x0000097e, 0x0000097e, 0x0000097e, 0x0000097e,
+ 0x0000097e, 0x0000097e, 0x00000995, 0x000009ac,
+ 0x000009ac, 0x000009ac, 0x000009ac, 0x000009ac,
+ 0x000009c6, 0x000009c6, 0x000009c6, 0x000009c6,
+ 0x000009c6, 0x000009c6, 0x000009c6, 0x000009c6,
+ 0x000009c6, 0x000009c6, 0x000009c6, 0x000009c6,
+ 0x000009c6, 0x00000a13, 0x00000a13, 0x00000a13,
+ // Entry A0 - BF
+ 0x00000a13, 0x00000a13, 0x00000a13, 0x00000a13,
+ 0x00000a13, 0x00000a13, 0x00000a82, 0x00000a82,
+ 0x00000a82, 0x00000a82, 0x00000a82, 0x00000a82,
+ 0x00000a82, 0x00000a82, 0x00000a82, 0x00000a82,
+ 0x00000a82, 0x00000acf, 0x00000b2f, 0x00000b2f,
+ 0x00000b2f, 0x00000b2f, 0x00000b2f, 0x00000b2f,
+ 0x00000b2f, 0x00000b2f, 0x00000b2f, 0x00000b2f,
+ 0x00000b2f, 0x00000b2f, 0x00000b2f, 0x00000b2f,
+ // Entry C0 - DF
+ 0x00000b2f, 0x00000b2f, 0x00000b2f, 0x00000b2f,
+ 0x00000b2f, 0x00000b2f, 0x00000b2f, 0x00000b2f,
+ 0x00000b2f, 0x00000b2f, 0x00000b2f, 0x00000b2f,
+ 0x00000b2f, 0x00000b2f, 0x00000b2f, 0x00000b2f,
+ 0x00000b2f, 0x00000b2f, 0x00000b2f, 0x00000b2f,
+ 0x00000b2f, 0x00000b2f, 0x00000b2f, 0x00000b2f,
+ 0x00000b2f, 0x00000b2f, 0x00000b2f, 0x00000b2f,
+ 0x00000b2f, 0x00000b2f, 0x00000b2f, 0x00000b2f,
+ // Entry E0 - FF
+ 0x00000b2f, 0x00000b2f, 0x00000b2f, 0x00000b2f,
+ 0x00000b2f, 0x00000b2f, 0x00000b2f, 0x00000b2f,
+ 0x00000b2f, 0x00000b2f, 0x00000b2f, 0x00000b2f,
+ 0x00000b2f, 0x00000b2f, 0x00000b2f, 0x00000b2f,
+ 0x00000b2f, 0x00000b2f, 0x00000b2f, 0x00000b2f,
+ 0x00000b2f, 0x00000b2f, 0x00000b2f, 0x00000b2f,
+ 0x00000b2f, 0x00000b2f, 0x00000b2f, 0x00000b2f,
+ 0x00000b2f, 0x00000b2f, 0x00000b2f, 0x00000b2f,
+ // Entry 100 - 11F
+ 0x00000b2f, 0x00000b2f, 0x00000b2f, 0x00000b2f,
+ 0x00000b2f, 0x00000b2f, 0x00000b2f, 0x00000b2f,
+ 0x00000b2f, 0x00000b2f, 0x00000b2f, 0x00000b2f,
+ 0x00000b2f, 0x00000b2f, 0x00000b2f, 0x00000b2f,
+ 0x00000b2f, 0x00000b2f, 0x00000b2f, 0x00000b2f,
+ 0x00000b2f, 0x00000b2f,
+} // Size: 1136 bytes
+
+const si_LKData string = "" + // Size: 2863 bytes
+ "\x02දෝෂයකි\x02භාවිතය: %[1]s [\x0a%[2]s]\x02දැන්\x14\x01\x81\x01\x00\x02" +
+ "\x1c\x02අවුරුදු %[1]d\x00\x1c\x02අවුරුදු %[1]d\x14\x01\x81\x01\x00\x02" +
+ "\x13\x02දවස් %[1]d\x00\x13\x02දවස් %[1]d\x14\x01\x81\x01\x00\x02\x10\x02" +
+ "පැය %[1]d\x00\x10\x02පැය %[1]d\x14\x01\x81\x01\x00\x02\x19\x02විනාඩි %" +
+ "[1]d\x00\x19\x02විනාඩි %[1]d\x14\x01\x81\x01\x00\x02\x16\x02තත්පර %[1]d" +
+ "\x00\x16\x02තත්පර %[1]d\x02%[1]s ට පෙර\x02බ.\u00a0%[1]d\x02කි.බ. %.2[1]f" +
+ "\x02මෙ.බ. %.2[1]f\x02ගි.බ. %.2[1]f\x02ටෙ.බ. %.2[1]f\x02%[1]s: %[2]q\x02ව" +
+ "ලංගු නොවන අ.ජා.කෙ. ලිපිනයකි\x02වලංගු නොවන කෙවෙනියකි\x02වලංගු නොවන යතුර" +
+ ": %[1]v\x02පේළියකට අල්පවිරාම දෙකක්\x02, \x02, \x02වයර්ගාඩ් පිළිබඳව\x02වස" +
+ "න්න\x02♥ &පරිත්\u200dයාග!\x02තත්වය:\x02සවන්දීමේ කෙවෙනිය:\x02ලිපින:\x02" +
+ "ව.නා.ප. සේවාදායක:\x02ඉඩදුන් අ.ජා.කෙ.:\x02නොදන්නා තත්වයකි\x02&පිටපත්" +
+ "\x02&ගොනුවකට සුරකින්න…\x02වේලාව\x02&වයර්ගාඩ් පිළිබඳව…\x02%[1]s (කල් ඉකුත" +
+ "් වී ඇත)\x02වයර්ගාඩ් පිටවීමේදී දෝෂයකි\x02යාවත්කාල කරන්න\x02දෝෂය: %[1]v" +
+ ". යළි උත්සාහ කරන්න.\x02තත්වය: සම්පූර්ණයි!\x02යතුරට අගයක් තිබිය යුතුය\x02" +
+ "අතුරුමුහුතකට පුද්ගලික යතුරක් තිබිය යුතුය\x02කෙටුම්පතෙහි අනුවාදය 1 විය " +
+ "යුතුය\x02සබල කර ඇත\x02%[1]s ලැබුණී, %[2]s යැවිණි\x02අතුරුමුහුණත: %[1]s" +
+ "\x02&නම:\x02(නොදනී)\x02&සුරකින්න\x02අවලංගු\x02&වින්\u200dයාසය:\x02වලංගු " +
+ "නොවන නමකි\x02නමක් අවශ්\u200dයයි.\x02නව වින්\u200dයාසය සෑදීමට නොහැකියි" +
+ "\x02ගොනුව ලිවීමට අසමත්විය\x02ක්\u200dරියාත්මක වෙමින්\x02වයර්ගාඩ් කවුළුව " +
+ "පෙනෙන තෙක් රැඳීසිටිය නොහැකිය: %[1]v\x02තත්වය: නොදනී\x02පි&ටවන්න\x02වයර" +
+ "්ගාඩ් ක්\u200dරියාත්මකයි\x02තත්වය: %[1]s\x02ලිපින: %[1]s\x02&සංස්කරණය" +
+ "\x02වින්\u200dයාසය ආයාත කළ නොහැකිය: %[1]v\x02%[1]s මෙම ක්\u200dරියාමාර්ග" +
+ "ය ආපසු හැරවිය නොහැකිය.\x02තත්වය: පරිශීලක සඳහා රැඳෙමින්\x02තත්වය: යාවත්" +
+ "කාල සේවාව සඳහා රැඳෙමින්"
-var skIndex = []uint32{ // 181 elements
+var skIndex = []uint32{ // 278 elements
// Entry 0 - 1F
0x00000000, 0x00000006, 0x0000005e, 0x00000078,
- 0x00000097, 0x000000d1, 0x000000d1, 0x00000109,
- 0x0000014b, 0x000001b5, 0x000001ff, 0x00000205,
- 0x0000022d, 0x0000022d, 0x00000265, 0x000002a6,
- 0x000002e9, 0x0000032e, 0x00000339, 0x00000342,
- 0x0000034f, 0x0000035c, 0x00000369, 0x00000376,
- 0x00000383, 0x00000397, 0x000003bd, 0x000003e2,
- 0x00000406, 0x0000042f, 0x0000043d, 0x0000044c,
+ 0x00000097, 0x000000d1, 0x0000011e, 0x00000156,
+ 0x00000198, 0x00000202, 0x00000208, 0x00000230,
+ 0x0000026a, 0x000002a2, 0x000002e3, 0x00000326,
+ 0x0000036b, 0x00000376, 0x0000037f, 0x0000038c,
+ 0x00000399, 0x000003a6, 0x000003b3, 0x000003c0,
+ 0x000003d4, 0x000003fa, 0x0000041f, 0x00000443,
+ 0x00000451, 0x00000460, 0x00000482, 0x0000049b,
// Entry 20 - 3F
- 0x0000046e, 0x00000487, 0x000004bc, 0x000004ef,
- 0x00000505, 0x00000522, 0x00000541, 0x00000583,
- 0x000005a4, 0x000005c9, 0x000005e9, 0x0000061c,
- 0x00000630, 0x00000665, 0x00000689, 0x000006ac,
- 0x000006ca, 0x000006e8, 0x000006eb, 0x000006ed,
- 0x000006f9, 0x00000711, 0x00000711, 0x0000071b,
- 0x0000072a, 0x00000730, 0x0000073f, 0x0000074c,
- 0x0000075e, 0x0000076e, 0x00000773, 0x0000077b,
+ 0x000004ce, 0x000004e4, 0x00000501, 0x00000515,
+ 0x0000054a, 0x0000056e, 0x00000571, 0x00000573,
+ 0x0000057f, 0x00000597, 0x000005a1, 0x000005b0,
+ 0x000005b6, 0x000005c5, 0x000005d2, 0x000005e4,
+ 0x000005f4, 0x000005f9, 0x00000601, 0x0000060e,
+ 0x00000629, 0x0000063e, 0x0000064c, 0x00000665,
+ 0x00000685, 0x00000690, 0x0000069e, 0x000006ac,
+ 0x000006be, 0x000006cb, 0x000006dc, 0x000006f4,
// Entry 40 - 5F
- 0x00000788, 0x00000788, 0x000007a3, 0x000007b8,
- 0x000007c6, 0x000007df, 0x000007ff, 0x00000807,
- 0x00000807, 0x00000811, 0x00000835, 0x00000857,
- 0x00000876, 0x00000897, 0x000008a8, 0x000008ad,
- 0x000008c3, 0x000008d2, 0x000008db, 0x000008ee,
- 0x000008f9, 0x00000927, 0x00000927, 0x00000931,
- 0x0000093a, 0x0000094a, 0x0000095b, 0x0000096f,
- 0x00000997, 0x000009cd, 0x000009e0, 0x00000a0a,
+ 0x000006f9, 0x00000716, 0x0000073f, 0x0000074f,
+ 0x0000075c, 0x00000794, 0x000007a7, 0x000007c2,
+ 0x00000825, 0x00000839, 0x00000859, 0x0000086c,
+ 0x000008b6, 0x000008df, 0x00000914, 0x00000933,
+ 0x00000975, 0x00000996, 0x000009bb, 0x000009db,
+ 0x00000a0e, 0x00000a31, 0x00000a4f, 0x00000a6d,
+ 0x00000a76, 0x00000a7e, 0x00000a8d, 0x00000a99,
+ 0x00000aa8, 0x00000ab4, 0x00000ad5, 0x00000adf,
// Entry 60 - 7F
- 0x00000a37, 0x00000a5a, 0x00000a97, 0x00000aa0,
- 0x00000aac, 0x00000ab7, 0x00000ac5, 0x00000ad3,
- 0x00000ad3, 0x00000ad3, 0x00000ad3, 0x00000ad3,
- 0x00000ad3, 0x00000ad3, 0x00000ad3, 0x00000ad3,
- 0x00000ae3, 0x00000ae3, 0x00000ae3, 0x00000ae3,
- 0x00000ae3, 0x00000ae3, 0x00000ae3, 0x00000ae3,
- 0x00000ae3, 0x00000af9, 0x00000b1d, 0x00000b28,
- 0x00000b28, 0x00000b28, 0x00000b28, 0x00000b28,
+ 0x00000b03, 0x00000b25, 0x00000b44, 0x00000b65,
+ 0x00000b76, 0x00000b7b, 0x00000b91, 0x00000ba0,
+ 0x00000ba9, 0x00000bbc, 0x00000bc7, 0x00000bf5,
+ 0x00000bff, 0x00000c08, 0x00000c18, 0x00000c29,
+ 0x00000c3d, 0x00000c65, 0x00000c9b, 0x00000cae,
+ 0x00000cd8, 0x00000d05, 0x00000d28, 0x00000d65,
+ 0x00000d6e, 0x00000d7a, 0x00000db3, 0x00000dcc,
+ 0x00000e07, 0x00000e20, 0x00000e2e, 0x00000e3e,
// Entry 80 - 9F
- 0x00000b28, 0x00000b39, 0x00000b39, 0x00000b39,
- 0x00000b39, 0x00000b39, 0x00000b39, 0x00000b39,
- 0x00000b39, 0x00000b39, 0x00000b39, 0x00000b39,
- 0x00000b39, 0x00000b39, 0x00000b39, 0x00000b39,
- 0x00000b39, 0x00000b39, 0x00000b39, 0x00000b39,
- 0x00000b39, 0x00000b39, 0x00000b39, 0x00000b39,
- 0x00000b39, 0x00000b39, 0x00000b39, 0x00000b39,
- 0x00000b39, 0x00000b39, 0x00000b39, 0x00000b39,
+ 0x00000e54, 0x00000e78, 0x00000e83, 0x00000e8b,
+ 0x00000ea4, 0x00000ec1, 0x00000edc, 0x00000efb,
+ 0x00000f12, 0x00000f23, 0x00000f2f, 0x00000f3d,
+ 0x00000f59, 0x00000f7f, 0x00000fe8, 0x00000fef,
+ 0x00000ff9, 0x00001014, 0x00001022, 0x00001046,
+ 0x0000106f, 0x0000107a, 0x000010a7, 0x000010c5,
+ 0x000010e4, 0x00001114, 0x0000114e, 0x00001181,
+ 0x000011a6, 0x000011d7, 0x000011ed, 0x0000126d,
// Entry A0 - BF
- 0x00000b39, 0x00000b39, 0x00000b39, 0x00000b39,
- 0x00000b39, 0x00000b39, 0x00000b39, 0x00000b39,
- 0x00000b39, 0x00000b39, 0x00000b39, 0x00000b39,
- 0x00000b39, 0x00000b39, 0x00000b39, 0x00000b39,
- 0x00000b39, 0x00000b39, 0x00000b39, 0x00000b39,
- 0x00000b39,
-} // Size: 748 bytes
+ 0x00001311, 0x0000132a, 0x000013a3, 0x00001491,
+ 0x000014b1, 0x000014ee, 0x0000151a, 0x00001535,
+ 0x0000155d, 0x0000157b, 0x0000162d, 0x0000167b,
+ 0x0000169b, 0x000016c3, 0x000016e1, 0x00001715,
+ 0x0000177b, 0x0000179b, 0x000017c5, 0x000017c5,
+ 0x000017c5, 0x000017c5, 0x000017c5, 0x000017c5,
+ 0x000017c5, 0x000017c5, 0x000017c5, 0x000017c5,
+ 0x000017c5, 0x000017c5, 0x000017c5, 0x000017c5,
+ // Entry C0 - DF
+ 0x000017c5, 0x000017c5, 0x000017c5, 0x000017c5,
+ 0x000017c5, 0x000017c5, 0x000017c5, 0x000017c5,
+ 0x000017c5, 0x000017c5, 0x000017c5, 0x000017c5,
+ 0x000017c5, 0x000017c5, 0x000017c5, 0x000017c5,
+ 0x000017c5, 0x000017c5, 0x000017c5, 0x000017c5,
+ 0x000017c5, 0x000017c5, 0x000017c5, 0x000017c5,
+ 0x000017c5, 0x000017c5, 0x000017c5, 0x000017c5,
+ 0x000017c5, 0x000017c5, 0x000017c5, 0x000017c5,
+ // Entry E0 - FF
+ 0x000017c5, 0x000017c5, 0x000017c5, 0x000017c5,
+ 0x000017c5, 0x000017c5, 0x000017c5, 0x000017c5,
+ 0x000017c5, 0x000017c5, 0x000017c5, 0x000017c5,
+ 0x000017c5, 0x000017c5, 0x000017c5, 0x000017c5,
+ 0x000017c5, 0x000017c5, 0x000017c5, 0x000017c5,
+ 0x000017c5, 0x000017c5, 0x000017c5, 0x000017c5,
+ 0x000017c5, 0x000017c5, 0x000017c5, 0x000017c5,
+ 0x000017c5, 0x000017c5, 0x000017c5, 0x000017c5,
+ // Entry 100 - 11F
+ 0x000017c5, 0x000017c5, 0x000017c5, 0x000017c5,
+ 0x000017c5, 0x000017c5, 0x000017c5, 0x000017c5,
+ 0x000017c5, 0x000017c5, 0x000017c5, 0x000017c5,
+ 0x000017c5, 0x000017c5, 0x000017c5, 0x000017c5,
+ 0x000017c5, 0x000017c5, 0x000017c5, 0x000017c5,
+ 0x000017c5, 0x000017c5,
+} // Size: 1136 bytes
-const skData string = "" + // Size: 2873 bytes
+const skData string = "" + // Size: 6085 bytes
"\x02Chyba\x02(bez argumentu): získať administrátorské práva a nainštalov" +
"ať službu manažéra\x02Použitie: %[1]s [\x0a%[2]s]\x02Možnosti príkazovéh" +
- "o riadku\x02Nepodarilo sa zistiť, či proces beží pod WOW64: %[1]v\x02Nep" +
- "odarilo sa otvoriť token aktuálneho procesu: %[1]v\x02WireGuard môžu pou" +
- "žívať iba členovia Builtin skupiny %[1]s.\x02WireGuard je spustený, ale" +
- " používateľské rozhranie je prístupné iba členom Builtin skupiny %[1]s." +
- "\x02WireGuard ikona sa ani po 30 sekundách neobjavila na systémovej lišt" +
- "e.\x02Teraz\x02Systémové hodiny sa vrátili v čase!\x14\x01\x81\x01\x00" +
- "\x04\x0a\x02%[1]d dni\x05\x0b\x02%[1]d dní\x02\x0b\x02%[1]d deň\x00\x0b" +
- "\x02%[1]d dní\x14\x01\x81\x01\x00\x04\x0d\x02%[1]d hodiny\x05\x0d\x02%[1" +
- "]d hodín\x02\x0d\x02%[1]d hodina\x00\x0d\x02%[1]d hodín\x14\x01\x81\x01" +
- "\x00\x04\x0e\x02%[1]d minúty\x05\x0d\x02%[1]d minút\x02\x0e\x02%[1]d min" +
- "úta\x00\x0d\x02%[1]d minút\x14\x01\x81\x01\x00\x04\x0e\x02%[1]d sekundy" +
- "\x05\x0e\x02%[1]d sekúnd\x02\x0e\x02%[1]d sekunda\x00\x0e\x02%[1]d sekún" +
- "d\x02Pred %[1]s\x02%[1]d\u00a0B\x02%.2[1]f\u00a0KiB\x02%.2[1]f\u00a0MiB" +
- "\x02%.2[1]f\u00a0GiB\x02%.2[1]f\u00a0TiB\x02%[1]s: %[2]q\x02Neplatná adr" +
- "esa IP\x02Neplatná dĺžka sieťového prefixu\x02Koncovému bodu chýba číslo" +
- " portu\x02Neplatný hostiteľ koncového bodu\x02Medzi zátvorkami musí byť " +
- "IPv6 adresa\x02Neplatné MTU\x02Neplatný port\x02Neplatný perzistentný ke" +
- "epalive\x02Neplatný kľúč: %[1]v\x02Dekódované kľúče musia mať veľkosť 32" +
- " bajtov\x02Číslo musí mať hodnotu medzi 0 a 2^64-1: %[1]v\x02Dve čiarky " +
- "v poradí\x02Názov tunela nie je platný\x02Sekcia musí obsahovať čiaru" +
- "\x02Konfiguračný kľúč neobsahuje separátor (znamienko rovnosti)\x02Kľúč " +
- "musí obsahovať hodnotu\x02Neplatný kľúč sekcie [Interface]\x02Neplatný k" +
- "ľúč sekcie [Peer]\x02Rozhranie musí mať priradený súkromný kľúč\x02[neš" +
- "pecifikované]\x02Všetci peeri musia mať priradený verejný kľúč\x02Chyba " +
- "pri získavaní konfigurácie\x02Neplatný kľúč sekcie rozhrania\x02Verzia p" +
- "rotokolu musí byť 1\x02Neplatný kľúč peer sekcie\x02, \x02 \x02O WireGua" +
- "rd\x02Obrázok WireGuard loga\x02Zatvoriť\x02♥ a Darovat!\x02Stav:\x02a D" +
- "eaktivovať\x02a Aktivovať\x02Verejný kľúč:\x02Otvorený port:\x02MTU:\x02" +
- "Adresy:\x02Servery DNS:\x02Vopred zdieľaný kľúč:\x02Povolené IP adresy:" +
- "\x02Koncový bod:\x02Perzistentný keepalive:\x02Posledné spojenie (handsh" +
- "ake):\x02Prenos:\x02povolené\x02%[1]s prijatých, %[2]s odoslaných\x02Nep" +
- "odarilo sa zistiť stav tunela\x02Nepodarilo sa aktivovať tunel\x02Nepoda" +
- "rilo sa deaktivovať tunel\x02Rozhranie: %[1]s\x02Peer\x02Vytvoriť nový t" +
- "unel\x02Upraviť tunel\x02&Názov:\x02&Verejný kľúč:\x02(neznámy)\x02&Blok" +
- "ovať netunelovaný prenos (kill-switch)\x02&Uložiť\x02Zrušiť\x02&Konfigur" +
- "ácia:\x02Neplatný názov\x02Názov je povinný.\x02Názov tunela ‘%[1]s’ je" +
- " neplatný.\x02Nepodarilo sa pripraviť zoznam existujúcich tunelov\x02Tun" +
- "el už existuje\x02Tunel s názvom ‘%[1]s’ už existuje.\x02Nie je možné vy" +
- "tvoriť novú konfiguráciu\x02Nepodarilo sa zapísať do súboru\x02Súbor ‘%[" +
- "1]s’ už existuje.\x0a\x0aŽeláte si ho prepísať?\x02Aktívny\x02Aktivuje s" +
- "a\x02Neaktívny\x02Deaktivuje sa\x02Neznámy stav\x02&O WireGuard…\x02&Spr" +
- "avovať tunely…\x02&Importovať tunel(y) zo súboru…\x02U&končiť\x02WireGua" +
- "rd: %[1]s"
+ "o riadku\x02Nepodarilo sa zistiť, či proces beží pod WOW64: %[1]v\x02V t" +
+ "omto počítači musíte používať pôvodnú verziu programu WireGuard.\x02Nepo" +
+ "darilo sa otvoriť token aktuálneho procesu: %[1]v\x02WireGuard môžu použ" +
+ "ívať iba členovia Builtin skupiny %[1]s.\x02WireGuard je spustený, ale " +
+ "používateľské rozhranie je prístupné iba členom Builtin skupiny %[1]s." +
+ "\x02Teraz\x02Systémové hodiny sa vrátili v čase!\x14\x01\x81\x01\x00\x04" +
+ "\x0b\x02%[1]d roky\x05\x0c\x02%[1]d rokov\x02\x0a\x02%[1]d rok\x00\x0c" +
+ "\x02%[1]d rokov\x14\x01\x81\x01\x00\x04\x0a\x02%[1]d dni\x05\x0b\x02%[1]" +
+ "d dní\x02\x0b\x02%[1]d deň\x00\x0b\x02%[1]d dní\x14\x01\x81\x01\x00\x04" +
+ "\x0d\x02%[1]d hodiny\x05\x0d\x02%[1]d hodín\x02\x0d\x02%[1]d hodina\x00" +
+ "\x0d\x02%[1]d hodín\x14\x01\x81\x01\x00\x04\x0e\x02%[1]d minúty\x05\x0d" +
+ "\x02%[1]d minút\x02\x0e\x02%[1]d minúta\x00\x0d\x02%[1]d minút\x14\x01" +
+ "\x81\x01\x00\x04\x0e\x02%[1]d sekundy\x05\x0e\x02%[1]d sekúnd\x02\x0e" +
+ "\x02%[1]d sekunda\x00\x0e\x02%[1]d sekúnd\x02Pred %[1]s\x02%[1]d\u00a0B" +
+ "\x02%.2[1]f\u00a0KiB\x02%.2[1]f\u00a0MiB\x02%.2[1]f\u00a0GiB\x02%.2[1]f" +
+ "\u00a0TiB\x02%[1]s: %[2]q\x02Neplatná adresa IP\x02Neplatná dĺžka sieťov" +
+ "ého prefixu\x02Koncovému bodu chýba číslo portu\x02Neplatný hostiteľ ko" +
+ "ncového bodu\x02Neplatné MTU\x02Neplatný port\x02Neplatný perzistentný k" +
+ "eepalive\x02Neplatný kľúč: %[1]v\x02Číslo musí mať hodnotu medzi 0 a 2^6" +
+ "4-1: %[1]v\x02Dve čiarky v poradí\x02Názov tunela nie je platný\x02[nešp" +
+ "ecifikované]\x02Všetci peeri musia mať priradený verejný kľúč\x02Chyba p" +
+ "ri získavaní konfigurácie\x02, \x02 \x02O WireGuard\x02Obrázok WireGuard" +
+ " loga\x02Zatvoriť\x02♥ a Darovat!\x02Stav:\x02a Deaktivovať\x02a Aktivov" +
+ "ať\x02Verejný kľúč:\x02Otvorený port:\x02MTU:\x02Adresy:\x02Servery DNS:" +
+ "\x02Vopred zdieľaný kľúč:\x02Povolené IP adresy:\x02Koncový bod:\x02Perz" +
+ "istentný keepalive:\x02Posledné spojenie (handshake):\x02Neaktívny\x02De" +
+ "aktivuje sa\x02Neznámy stav\x02Denník udalostí\x02&Kopírovať\x02Vybr&ať " +
+ "všetko\x02Uložiť do &súboru…\x02Čas\x02Správa v denníku udalostí\x02Expo" +
+ "rtovať denník udalostí do súboru\x02&O WireGuard…\x02Chyba tunela\x02%[1" +
+ "]s\x0a\x0aViac informácií nájdete v denníku udalostí.\x02%[1]s (neaktuán" +
+ "y)\x02Chyba ukončenia WireGuard\x02Je k dispozícii nová verzia programu " +
+ "WireGuard. Odporúčame bezodkladne vykonať aktualizáciu.\x02Aktualizovať " +
+ "teraz\x02Chyba: %[1]v. Skúste to znova.\x02Stav: Dokončené!\x02WireGuard" +
+ " ikona sa ani po 30 sekundách neobjavila na systémovej lište.\x02Medzi z" +
+ "átvorkami musí byť IPv6 adresa\x02Dekódované kľúče musia mať veľkosť 32" +
+ " bajtov\x02Sekcia musí obsahovať čiaru\x02Konfiguračný kľúč neobsahuje s" +
+ "eparátor (znamienko rovnosti)\x02Kľúč musí obsahovať hodnotu\x02Neplatný" +
+ " kľúč sekcie [Interface]\x02Neplatný kľúč sekcie [Peer]\x02Rozhranie mus" +
+ "í mať priradený súkromný kľúč\x02Neplatný kľúč sekcie rozhrania\x02Verz" +
+ "ia protokolu musí byť 1\x02Neplatný kľúč peer sekcie\x02Skripty:\x02Pren" +
+ "os:\x02pred-zapnutím\x02po-zapnutí\x02pred-vypnutím\x02po-vypnutí\x02zak" +
+ "ázané, na základe pravidla\x02povolené\x02%[1]s prijatých, %[2]s odosla" +
+ "ných\x02Nepodarilo sa zistiť stav tunela\x02Nepodarilo sa aktivovať tune" +
+ "l\x02Nepodarilo sa deaktivovať tunel\x02Rozhranie: %[1]s\x02Peer\x02Vytv" +
+ "oriť nový tunel\x02Upraviť tunel\x02&Názov:\x02&Verejný kľúč:\x02(neznám" +
+ "y)\x02&Blokovať netunelovaný prenos (kill-switch)\x02&Uložiť\x02Zrušiť" +
+ "\x02&Konfigurácia:\x02Neplatný názov\x02Názov je povinný.\x02Názov tunel" +
+ "a ‘%[1]s’ je neplatný.\x02Nepodarilo sa pripraviť zoznam existujúcich tu" +
+ "nelov\x02Tunel už existuje\x02Tunel s názvom ‘%[1]s’ už existuje.\x02Nie" +
+ " je možné vytvoriť novú konfiguráciu\x02Nepodarilo sa zapísať do súboru" +
+ "\x02Súbor ‘%[1]s’ už existuje.\x0a\x0aŽeláte si ho prepísať?\x02Aktívny" +
+ "\x02Aktivuje sa\x02Textové súbory (*.txt)|*.txt|Všetky súbory (*.*)|*.*" +
+ "\x02Chyba detekcie WireGuard\x02Nie je možné čakať na zobrazenie WireGua" +
+ "rd okna: %[1]v\x02WireGuard: deaktivovaný\x02Stav: Nezámy\x02Adresa: žia" +
+ "dna\x02&Spravovať tunely…\x02&Importovať tunel(y) zo súboru…\x02U&končiť" +
+ "\x02&Tunely\x02WireGuard je aktivovaný\x02Tunel %[1]s bol aktivovaný." +
+ "\x02WireGuard je deaktivovaný\x02Tunel %[1]s bol deaktivovaný.\x02Chyba " +
+ "WireGuard tunelu\x02WireGuard: %[1]s\x02Stav: %[1]s\x02Adresa: %[1]s\x02" +
+ "Je dostupná aktualizácia!\x02Dostupná aktualizácia pre WireGuard\x02Je k" +
+ " dispozícii aktualizácia programu WireGuard. Je odporúčané čo najskôr vy" +
+ "konať aktualizáciu.\x02Tunely\x02&Upraviť\x02Pridať &prázdny tunel…\x02P" +
+ "ridať tunel\x02Odstrániť označený(é) tunel(y)\x02Export všetkých tunelov" +
+ " do zip súboru\x02P&repnúť\x02Export všetkých tunelov do &zip súboru…" +
+ "\x02Upraviť &označený tunel…\x02&Odstrániť označené tunely\x02neboli náj" +
+ "dené žiadne konfiguračné súbory\x02Nepodarilo sa naimportovať vybrané ko" +
+ "nfigurácie: %[1]v\x02Nepodarilo sa načítať existujúce tunely: %[1]v\x02U" +
+ "ž existuje tunel s názvom '%[1]s'\x02Nepodarilo sa naimportovať konfigu" +
+ "ráciu: %[1]v\x02Naimportované tunely\x14\x01\x81\x01\x00\x04\x1c\x02Naim" +
+ "portované %[1]d tunely\x05\x1f\x02Naimportovaných %[1]d tunelov\x02\x19" +
+ "\x02Importovaný %[1]d tunel\x00\x1f\x02Naimportovaných %[1]d tunelov\x14" +
+ "\x02\x80\x01\x04%\x02Naimportované %[1]d z %[2]d tunelov\x05'\x02Naimpor" +
+ "tovaných %[1]d z %[2]d tunelov\x02%\x02Naimportovaný %[1]d z %[2]d tunel" +
+ "ov\x00'\x02Naimportovaných %[1]d z %[2]d tunelov\x02Tunel sa nedá vytvor" +
+ "iť\x14\x01\x81\x01\x00\x04\x19\x02Odstránene %[1]d tunely\x05\x1d\x02Ods" +
+ "tránených %[1]d tunelov\x02\x19\x02Odstránený %[1]d tunel\x00\x1d\x02Ods" +
+ "tránených %[1]d tunelov\x14\x01\x81\x01\x00\x048\x02Ste si istý, že si ž" +
+ "eláte odstrániť %[1]d tunely?\x059\x02Ste si istý, že si želáte odstráni" +
+ "ť %[1]d tunelov?\x027\x02Ste si istý, že si želáte odstrániť %[1]d tune" +
+ "l?\x009\x02Ste si istý, že si želáte odstrániť %[1]d tunelov?\x02Odstrán" +
+ "enie tunela ‘%[1]s’\x02Ste si istý, že si želáte odstrániť tunel ‘%[1]s’" +
+ "?\x02%[1]s Túto akciu nemôže vrátiť späť.\x02Tunel sa nedá odstrániť\x02" +
+ "Nebolo možné odstrániť tunel: %[1]s\x02Tunely sa nedajú odstrániť\x14" +
+ "\x01\x81\x01\x00\x04)\x02%[1]d tunely nebolo možné odstrániť.\x05*\x02%[" +
+ "1]d tunelov nebolo možné odstrániť.\x02(\x02%[1]d tunel nebolo možné ods" +
+ "trániť.\x00*\x02%[1]d tunelov nebolo možné odstrániť.\x02Konfirugačné sú" +
+ "bory (*.zip, *.conf)|*.zip;*.conf|Všetky súbory (*.*)|*.*\x02Importovať " +
+ "tunel(y) zo súboru\x02Konfiguračné ZIP súbry (*.zip)|*.zip\x02Export tun" +
+ "elov do zip súboru\x02%[1]s (nepodpísaná verzia, žiadne aktualizácie)" +
+ "\x02Nie je možné ukončiť služby z dôvodu: %[1]v. Skúste zastaviť WireGua" +
+ "rd v správcovi služieb.\x02Stav: Čaká sa na užívateľa\x02Stav: Čaká sa n" +
+ "a aktualizačnú službu"
-var slIndex = []uint32{ // 181 elements
+var slIndex = []uint32{ // 278 elements
// Entry 0 - 1F
0x00000000, 0x00000007, 0x00000058, 0x00000070,
0x00000089, 0x000000c1, 0x00000111, 0x00000148,
- 0x0000019a, 0x00000200, 0x00000244, 0x00000249,
- 0x00000268, 0x000002a0, 0x000002d7, 0x0000030b,
- 0x0000034b, 0x0000038f, 0x0000039b, 0x000003a4,
- 0x000003b1, 0x000003be, 0x000003cb, 0x000003d8,
- 0x000003e5, 0x000003f8, 0x0000041c, 0x0000043e,
- 0x00000467, 0x0000048d, 0x0000049a, 0x000004a9,
+ 0x0000019a, 0x00000200, 0x00000205, 0x00000224,
+ 0x0000025c, 0x00000293, 0x000002c7, 0x00000307,
+ 0x0000034b, 0x00000357, 0x00000360, 0x0000036d,
+ 0x0000037a, 0x00000387, 0x00000394, 0x000003a1,
+ 0x000003b4, 0x000003d8, 0x000003fa, 0x00000423,
+ 0x00000430, 0x0000043f, 0x00000463, 0x0000047a,
// Entry 20 - 3F
- 0x000004cd, 0x000004e4, 0x00000515, 0x00000549,
- 0x0000055e, 0x00000575, 0x00000590, 0x000005bf,
- 0x000005da, 0x000005ff, 0x0000061f, 0x00000641,
- 0x0000064f, 0x00000676, 0x00000696, 0x000006b8,
- 0x000006d6, 0x000006f8, 0x000006fb, 0x000006fd,
- 0x0000070a, 0x00000728, 0x000007a3, 0x000007a9,
- 0x000007b7, 0x000007bf, 0x000007cc, 0x000007d7,
- 0x000007e5, 0x000007f8, 0x000007fd, 0x00000806,
+ 0x000004ae, 0x000004c3, 0x000004da, 0x000004e8,
+ 0x0000050f, 0x0000052f, 0x00000532, 0x00000534,
+ 0x00000541, 0x0000055f, 0x00000565, 0x00000573,
+ 0x0000057b, 0x00000588, 0x00000593, 0x000005a1,
+ 0x000005b4, 0x000005b9, 0x000005c2, 0x000005d2,
+ 0x000005e8, 0x000005f9, 0x00000609, 0x00000625,
+ 0x00000637, 0x00000641, 0x0000064f, 0x0000065e,
+ 0x00000666, 0x0000066f, 0x0000067b, 0x00000693,
// Entry 40 - 5F
- 0x00000816, 0x0000081f, 0x00000835, 0x00000846,
- 0x00000856, 0x00000872, 0x00000884, 0x0000088c,
- 0x000008aa, 0x000008b5, 0x000008d2, 0x000008f6,
- 0x00000914, 0x00000934, 0x00000943, 0x0000094b,
- 0x0000095d, 0x00000969, 0x0000096f, 0x0000097e,
- 0x00000988, 0x000009b2, 0x00000af2, 0x00000afa,
- 0x00000b04, 0x00000b14, 0x00000b21, 0x00000b31,
- 0x00000b53, 0x00000b83, 0x00000b95, 0x00000bc0,
+ 0x00000698, 0x000006ae, 0x000006c8, 0x000006db,
+ 0x000006e9, 0x00000718, 0x0000072e, 0x0000074e,
+ 0x000007a1, 0x000007af, 0x000007d1, 0x000007e3,
+ 0x00000827, 0x0000084d, 0x0000087e, 0x00000899,
+ 0x000008c8, 0x000008e3, 0x00000908, 0x00000928,
+ 0x0000094a, 0x0000096c, 0x0000098a, 0x000009ac,
+ 0x000009b5, 0x000009bd, 0x000009cd, 0x000009db,
+ 0x000009ed, 0x000009fd, 0x00000a1b, 0x00000a26,
// Entry 60 - 7F
- 0x00000be7, 0x00000c05, 0x00000c40, 0x00000c48,
- 0x00000c54, 0x00000c5e, 0x00000c6c, 0x00000c7b,
- 0x00000c83, 0x00000c8c, 0x00000c98, 0x00000cb0,
- 0x00000cb5, 0x00000ccb, 0x00000d03, 0x00000d1d,
- 0x00000d30, 0x00000d3e, 0x00000d6d, 0x00000d83,
- 0x00000da0, 0x00000ddb, 0x00000df2, 0x00000e01,
- 0x00000e0f, 0x00000e26, 0x00000e45, 0x00000e4c,
- 0x00000e60, 0x00000e7e, 0x00000e94, 0x00000eb4,
+ 0x00000a43, 0x00000a67, 0x00000a85, 0x00000aa5,
+ 0x00000ab4, 0x00000abc, 0x00000ace, 0x00000ada,
+ 0x00000ae0, 0x00000aef, 0x00000af9, 0x00000b23,
+ 0x00000b2b, 0x00000b35, 0x00000b45, 0x00000b52,
+ 0x00000b62, 0x00000b84, 0x00000bb4, 0x00000bc6,
+ 0x00000bf1, 0x00000c18, 0x00000c36, 0x00000c71,
+ 0x00000c79, 0x00000c85, 0x00000cbd, 0x00000cda,
+ 0x00000d15, 0x00000d2c, 0x00000d3b, 0x00000d49,
// Entry 80 - 9F
- 0x00000ecc, 0x00000edd, 0x00000eeb, 0x00000efa,
- 0x00000f13, 0x00000f36, 0x00000f7b, 0x00000f82,
- 0x00000f89, 0x00000fa2, 0x00000fae, 0x00000fc6,
- 0x00000fde, 0x00000fe8, 0x00001006, 0x0000101f,
- 0x00001038, 0x0000105d, 0x0000108b, 0x000010be,
- 0x000010e3, 0x00001109, 0x00001119, 0x0000117d,
- 0x00001208, 0x00001229, 0x0000128e, 0x0000137b,
- 0x00001396, 0x000013d1, 0x000013fc, 0x00001416,
+ 0x00000d60, 0x00000d7f, 0x00000d86, 0x00000d8e,
+ 0x00000da2, 0x00000dc0, 0x00000dd6, 0x00000df6,
+ 0x00000e0e, 0x00000e1f, 0x00000e2d, 0x00000e3c,
+ 0x00000e55, 0x00000e78, 0x00000ebd, 0x00000ec4,
+ 0x00000ecb, 0x00000ee4, 0x00000ef0, 0x00000f08,
+ 0x00000f20, 0x00000f2a, 0x00000f48, 0x00000f61,
+ 0x00000f7a, 0x00000f9f, 0x00000fcd, 0x00001000,
+ 0x00001025, 0x0000104b, 0x0000105b, 0x000010bf,
// Entry A0 - BF
- 0x0000143e, 0x00001459, 0x0000150d, 0x0000155a,
- 0x00001573, 0x0000159e, 0x000015bb, 0x000015ec,
- 0x0000160c, 0x00001679, 0x000016cc, 0x000016e8,
- 0x000016f6, 0x0000171d, 0x0000173f, 0x00001751,
- 0x00001761, 0x0000176f, 0x00001781, 0x00001791,
- 0x00001799,
-} // Size: 748 bytes
+ 0x0000114a, 0x0000116b, 0x000011d0, 0x000012bd,
+ 0x000012d8, 0x00001313, 0x0000133e, 0x00001358,
+ 0x00001380, 0x0000139b, 0x0000144f, 0x0000149c,
+ 0x000014b5, 0x000014e0, 0x000014fd, 0x0000152e,
+ 0x0000159b, 0x000015b7, 0x000015de, 0x000015de,
+ 0x000015de, 0x000015de, 0x000015de, 0x000015de,
+ 0x000015de, 0x000015de, 0x000015de, 0x000015de,
+ 0x000015de, 0x000015de, 0x000015de, 0x000015de,
+ // Entry C0 - DF
+ 0x000015de, 0x000015de, 0x000015de, 0x000015de,
+ 0x000015de, 0x000015de, 0x000015de, 0x000015de,
+ 0x000015de, 0x000015de, 0x000015de, 0x000015de,
+ 0x000015de, 0x000015de, 0x000015de, 0x000015de,
+ 0x000015de, 0x000015de, 0x000015de, 0x000015de,
+ 0x000015de, 0x000015de, 0x000015de, 0x000015de,
+ 0x000015de, 0x000015de, 0x000015de, 0x000015de,
+ 0x000015de, 0x000015de, 0x000015de, 0x000015de,
+ // Entry E0 - FF
+ 0x000015de, 0x000015de, 0x000015de, 0x000015de,
+ 0x000015de, 0x000015de, 0x000015de, 0x000015de,
+ 0x000015de, 0x000015de, 0x000015de, 0x000015de,
+ 0x000015de, 0x000015de, 0x000015de, 0x000015de,
+ 0x000015de, 0x000015de, 0x000015de, 0x000015de,
+ 0x000015de, 0x000015de, 0x000015de, 0x000015de,
+ 0x000015de, 0x000015de, 0x000015de, 0x000015de,
+ 0x000015de, 0x000015de, 0x000015de, 0x000015de,
+ // Entry 100 - 11F
+ 0x000015de, 0x000015de, 0x000015de, 0x000015de,
+ 0x000015de, 0x000015de, 0x000015de, 0x000015de,
+ 0x000015de, 0x000015de, 0x000015de, 0x000015de,
+ 0x000015de, 0x000015de, 0x000015de, 0x000015de,
+ 0x000015de, 0x000015de, 0x000015de, 0x000015de,
+ 0x000015de, 0x000015de,
+} // Size: 1136 bytes
-const slData string = "" + // Size: 6041 bytes
+const slData string = "" + // Size: 5598 bytes
"\x02Napaka\x02(brez argumenta): povzdigni na skrbniške pravice in namest" +
"i skrbniško storitev\x02Uporaba: %[1]s [\x0a%[2]s]\x02Možnosti ukazne vr" +
"stice\x02Napaka pri določanju ali proces teče kot WOW64: %[1]v\x02Na tem" +
@@ -1998,9 +3122,8 @@ const slData string = "" + // Size: 6041 bytes
"\x02Napaka pri odpiranju žetona trenutnega procesa: %[1]v\x02WireGuard l" +
"ahko uporabljajo samo uporabniki, ki so člani vgrajene skupine %[1]s." +
"\x02WireGuard je zagnan, vendar je up. vmesnik dostopen samo z namizij u" +
- "porabnikov članov skupine %[1]s.\x02Ikona WireGuarda se po 30 sekundah n" +
- "i pojavila v sistemski vrstici.\x02Zdaj\x02Sistemska ura prevrtena nazaj" +
- "!\x14\x01\x81\x01\x00\x04\x0b\x02%[1]d leta\x02\x0b\x02%[1]d leto\x03" +
+ "porabnikov članov skupine %[1]s.\x02Zdaj\x02Sistemska ura prevrtena naza" +
+ "j!\x14\x01\x81\x01\x00\x04\x0b\x02%[1]d leta\x02\x0b\x02%[1]d leto\x03" +
"\x0b\x02%[1]d leti\x00\x0a\x02%[1]d let\x14\x01\x81\x01\x00\x04\x0a\x02%" +
"[1]d dni\x02\x0a\x02%[1]d dan\x03\x0c\x02%[1]d dneva\x00\x0a\x02%[1]d dn" +
"i\x14\x01\x81\x01\x00\x04\x0a\x02%[1]d ure\x02\x0a\x02%[1]d uro\x03\x0a" +
@@ -2011,215 +3134,452 @@ const slData string = "" + // Size: 6041 bytes
"1]d\u00a0B\x02%.2[1]f\u00a0KiB\x02%.2[1]f\u00a0MiB\x02%.2[1]f\u00a0GiB" +
"\x02%.2[1]f\u00a0TiB\x02%[1]s: %[2]q\x02Napačen naslov IP\x02Napačna dol" +
"žina predpone omrežja\x02Pri končni točki manjkajo vrata\x02Pri končni " +
- "točki je gostitelj napačen\x02Oklepaji morajo vsebovati naslov IPv6\x02N" +
- "apačen MTU\x02Napačna vrata\x02Napačno trajno ohranjanje povezave\x02Nap" +
- "ačen ključ: %[1]v\x02Dekodirani ključi morajo biti natanko 32 bajtov\x02" +
- "Številka mora biti število med 0 in 2^64-1: %[1]v\x02Dve zaporedni veji" +
- "ci\x02Ime tunela ni veljavno\x02Vrstica mora biti v odseku\x02Ključu v k" +
- "onfiguraciji manjka ločilo enačaj\x02Ključ mora imeti vrednost\x02Napače" +
- "n ključ za odsek [Interface]\x02Napačen ključ za odsek [Peer]\x02Vmesnik" +
- " mora imeti zasebni ključ\x02[ni navedeno]\x02Vsi vrstniki morajo imeti " +
- "javni ključ\x02Napaka pri branju konfiguracije\x02Napačen ključ za odsek" +
- " vmesnika\x02Verzija protokola mora biti 1\x02Napačen ključ za odsek vrs" +
- "tnika\x02, \x02 \x02O WireGuardu\x02Slika WireGuardovega logotipa\x02Ver" +
- "zija aplikacije: %[1]s\x0aVerzija wireguard-go: %[2]s\x0aVerzija Go: %[3" +
- "]s-%[4]s\x0aOperacijski sistem: %[5]s\x0aArhitektura: %[6]s\x02Zapri\x02" +
- "♥ &Doniraj!\x02Status:\x02&Deaktiviraj\x02&Aktiviraj\x02Javni ključ:" +
- "\x02Vrata poslušanja:\x02MTU:\x02Naslovi:\x02Strežniki DNS:\x02Skripta:" +
- "\x02Ključ v skupni rabi:\x02Dovoljeni IP-ji:\x02Končna točka:\x02Trajno " +
- "ohranjanje povezave:\x02Zadnje rokovanje:\x02Prenos:\x02onemogočeno, zar" +
- "adi politike\x02omogočeno\x02%[1]s prejeto, %[2]s poslano\x02Napaka pri " +
- "določanju stanja tunela\x02Napaka pri aktiviranju tunela\x02Napaka pri d" +
- "eaktiviranju tunela\x02Vmesnik: %[1]s\x02Vrstnik\x02Ustvari nov tunel" +
- "\x02Uredi tunel\x02&Ime:\x02&Javni ključ:\x02(neznano)\x02&Blokiraj prom" +
- "et izven tunela (varovalka)\x02Kadar ima konfiguracija natanko enega vrs" +
- "tnika in njegov spisek dovoljenih IP-jev vsebuje vsaj enega izmed 0.0.0." +
- "0/0 ali ::/0, bo storitev tunela vzpostavila pravila požarnega zidu, ki " +
- "bodo blokirala ves promet, ki ni niti za niti iz vmesnika tunela oz. za " +
- "napačen strežnik DNS, s posebnimi izjemami za DHCP and NDP.\x02&Shrani" +
- "\x02Prekliči\x02&Konfiguracija:\x02Napačno ime\x02Ime je obvezno.\x02Ime" +
- " tunela »%[1]s« ni veljavno.\x02Napaka pri pripravi seznama obstoječih t" +
- "unelov\x02Tunel že obstaja\x02Drug tunel z imenom »%[1]s« že obstaja." +
- "\x02Napaka pri izdelavi nove konfiguracije\x02Napaka pri pisanju v datot" +
- "eko\x02Datoteka »%[1]s« že obstaja.\x0a\x0aAli jo želite prepisati?\x02A" +
- "ktivno\x02Se aktivira\x02Neaktivno\x02Se deaktivira\x02Neznano stanje" +
- "\x02Dnevnik\x02&Kopiraj\x02&Izberi vse\x02&Shrani v datoteko\u00a0…\x02Č" +
- "as\x02Sporočilo v dnevniku\x02Tekstovne datoteke (*.txt)|*.txt|Vse datot" +
- "eke (*.*)|*.*\x02Izvozi dnevnik v datoteko\x02O WireGu&ardu\u00a0…\x02Na" +
- "paka tunela\x02%[1]s\x0a\x0aDodatne informacije najdete v dnevniku.\x02%" +
- "[1]s (neposodobljen)\x02Napaka zaznavanja WireGuarda\x02Čakanje, da se p" +
- "ojavi WireGuardovo okno, ni možno: %[1]v\x02WireGuard: Deaktiviran\x02St" +
- "atus: Neznan\x02Naslovi: Brez\x02&Upravljaj tunele\u00a0…\x02&Uvozi tune" +
- "l(e) iz datoteke…\x02I&zhod\x02WireGuard aktiviran\x02Tunel %[1]s je bil" +
- " aktiviran.\x02WireGuard deaktiviran\x02Tunel %[1]s je bil deaktiviran." +
- "\x02Napaka tunela WireGuard\x02WireGuard: %[1]s\x02Status: %[1]s\x02Nasl" +
- "ovi: %[1]s\x02Na voljo je posodobitev!\x02Posodobitev WireGuarda je na v" +
- "oljo\x02Posodobitev WireGuarda je na voljo. Svetujemo posodobitev čim pr" +
- "ej.\x02Tuneli\x02&Uredi\x02Dodaj &prazen tunel\u00a0…\x02Dodaj tunel\x02" +
- "Odstrani izbrane tunele\x02Izvozi vse tunele v zip\x02&Preklopi\x02Izvoz" +
- "i vse tunele v &zip\u00a0…\x02Uredi &izbran tunel\u00a0…\x02Odst&rani iz" +
- "brane tunele\x02ni najdenih konfiguracijskih datotek\x02Napaka pri uvozu" +
- " izbrane konfiguracije: %[1]v\x02Napaka pri preštevanju obstoječih tunel" +
- "ov: %[1]v\x02Tunel z imenom »%[1]s« že obstaja\x02Napaka pri uvozu konfi" +
- "guracije: %[1]v\x02Uvoženi tuneli\x14\x01\x81\x01\x00\x04\x16\x02Uvoženi" +
- " %[1]d tuneli\x02\x14\x02Uvožen %[1]d tunel\x03\x16\x02Uvožena %[1]d tun" +
- "ela\x00\x17\x02Uvoženo %[1]d tunelov\x14\x02\x80\x01\x04 \x02Uvoženi %[1" +
- "]d od %[2]d tunelov\x02\x1f\x02Uvožen %[1]d od %[2]d tunelov\x03 \x02Uvo" +
- "žena %[1]d od %[2]d tunelov\x00 \x02Uvoženo %[1]d od %[2]d tunelov\x02T" +
- "unela ni bilo mogoče ustvariti\x14\x01\x81\x01\x00\x04\x16\x02Izbriši %[" +
- "1]d tunele\x02\x15\x02Izbriši %[1]d tunel\x03\x16\x02Izbriši %[1]d tunel" +
- "a\x00\x17\x02Izbriši %[1]d tunelov\x14\x01\x81\x01\x00\x048\x02Ali ste p" +
- "repričani, da želite izbrisati %[1]d tunele?\x027\x02Ali ste prepričani," +
- " da želite izbrisati %[1]d tunel?\x038\x02Ali ste prepričani, da želite " +
- "izbrisati %[1]d tunela?\x009\x02Ali ste prepričani, da želite izbrisati " +
- "%[1]d tunelov?\x02Izbriši tunel ‘%[1]s’\x02Ali ste prepričani, da želite" +
- " izbrisati tunel »%[1]s«?\x02%[1]s Tega dejanja ne morete razveljaviti." +
- "\x02Napaka pri izbrisu tunela\x02Napaka pri odstranjevanju tunela: %[1]s" +
- "\x02Napaka pri izbrisu tunelov\x14\x01\x81\x01\x00\x04*\x02%[1]d tunelov" +
- " ni bilo mogoče odstraniti.\x02)\x02%[1]d tunela ni bilo mogoče odstrani" +
- "ti.\x03*\x02%[1]d tunelov ni bilo mogoče odstraniti.\x00*\x02%[1]d tunel" +
- "ov ni bilo mogoče odstraniti.\x02Konfiguracijske datoteke (*.zip, *.conf" +
- ")|*.zip;*.conf|Vse datoteke (*.*)|*.*\x02Uvozi tunele iz datoteke\x02Kon" +
- "figuracijske datoteke ZIP (*.zip)|*.zip\x02Izvozi tunele v datoteko zip" +
- "\x02%[1]s (nepodpisane različice, brez posodobitev)\x02Napaka pri izhodu" +
- " iz WireGuarda\x02Storitve ni bilo mogoče zaustaviti, ker: %[1]v. Poskus" +
- "ite zaustaviti WireGuard z uporabo programa Storitve.\x02Posodobitev Wir" +
- "eGuarda je na voljo. Zelo priporočamo posodobitev brez odlašanja.\x02Sta" +
- "tus: Čaka na uporabnika\x02Posodobi zdaj\x02Status: Čaka na servis za po" +
- "sodobitev\x02Napaka: %[1]v. Poskusite ponovno.\x02Status: Končano!\x02pr" +
- "ed-aktivacijo\x02po-aktivaciji\x02pred-deaktivacijo\x02po-deaktivaciji" +
- "\x02&Tuneli"
+ "točki je gostitelj napačen\x02Napačen MTU\x02Napačna vrata\x02Napačno tr" +
+ "ajno ohranjanje povezave\x02Napačen ključ: %[1]v\x02Številka mora biti š" +
+ "tevilo med 0 in 2^64-1: %[1]v\x02Dve zaporedni vejici\x02Ime tunela ni v" +
+ "eljavno\x02[ni navedeno]\x02Vsi vrstniki morajo imeti javni ključ\x02Nap" +
+ "aka pri branju konfiguracije\x02, \x02 \x02O WireGuardu\x02Slika WireGua" +
+ "rdovega logotipa\x02Zapri\x02♥ &Doniraj!\x02Status:\x02&Deaktiviraj\x02&" +
+ "Aktiviraj\x02Javni ključ:\x02Vrata poslušanja:\x02MTU:\x02Naslovi:\x02St" +
+ "režniki DNS:\x02Ključ v skupni rabi:\x02Dovoljeni IP-ji:\x02Končna točka" +
+ ":\x02Trajno ohranjanje povezave:\x02Zadnje rokovanje:\x02Neaktivno\x02Se" +
+ " deaktivira\x02Neznano stanje\x02Dnevnik\x02&Kopiraj\x02&Izberi vse\x02&" +
+ "Shrani v datoteko\u00a0…\x02Čas\x02Sporočilo v dnevniku\x02Izvozi dnevni" +
+ "k v datoteko\x02O WireGu&ardu\u00a0…\x02Napaka tunela\x02%[1]s\x0a\x0aDo" +
+ "datne informacije najdete v dnevniku.\x02%[1]s (neposodobljen)\x02Napaka" +
+ " pri izhodu iz WireGuarda\x02Posodobitev WireGuarda je na voljo. Zelo pr" +
+ "iporočamo posodobitev brez odlašanja.\x02Posodobi zdaj\x02Napaka: %[1]v." +
+ " Poskusite ponovno.\x02Status: Končano!\x02Ikona WireGuarda se po 30 sek" +
+ "undah ni pojavila v sistemski vrstici.\x02Oklepaji morajo vsebovati nasl" +
+ "ov IPv6\x02Dekodirani ključi morajo biti natanko 32 bajtov\x02Vrstica mo" +
+ "ra biti v odseku\x02Ključu v konfiguraciji manjka ločilo enačaj\x02Ključ" +
+ " mora imeti vrednost\x02Napačen ključ za odsek [Interface]\x02Napačen kl" +
+ "juč za odsek [Peer]\x02Vmesnik mora imeti zasebni ključ\x02Napačen ključ" +
+ " za odsek vmesnika\x02Verzija protokola mora biti 1\x02Napačen ključ za " +
+ "odsek vrstnika\x02Skripta:\x02Prenos:\x02pred-aktivacijo\x02po-aktivacij" +
+ "i\x02pred-deaktivacijo\x02po-deaktivaciji\x02onemogočeno, zaradi politik" +
+ "e\x02omogočeno\x02%[1]s prejeto, %[2]s poslano\x02Napaka pri določanju s" +
+ "tanja tunela\x02Napaka pri aktiviranju tunela\x02Napaka pri deaktiviranj" +
+ "u tunela\x02Vmesnik: %[1]s\x02Vrstnik\x02Ustvari nov tunel\x02Uredi tune" +
+ "l\x02&Ime:\x02&Javni ključ:\x02(neznano)\x02&Blokiraj promet izven tunel" +
+ "a (varovalka)\x02&Shrani\x02Prekliči\x02&Konfiguracija:\x02Napačno ime" +
+ "\x02Ime je obvezno.\x02Ime tunela »%[1]s« ni veljavno.\x02Napaka pri pri" +
+ "pravi seznama obstoječih tunelov\x02Tunel že obstaja\x02Drug tunel z ime" +
+ "nom »%[1]s« že obstaja.\x02Napaka pri izdelavi nove konfiguracije\x02Nap" +
+ "aka pri pisanju v datoteko\x02Datoteka »%[1]s« že obstaja.\x0a\x0aAli jo" +
+ " želite prepisati?\x02Aktivno\x02Se aktivira\x02Tekstovne datoteke (*.tx" +
+ "t)|*.txt|Vse datoteke (*.*)|*.*\x02Napaka zaznavanja WireGuarda\x02Čakan" +
+ "je, da se pojavi WireGuardovo okno, ni možno: %[1]v\x02WireGuard: Deakti" +
+ "viran\x02Status: Neznan\x02Naslovi: Brez\x02&Upravljaj tunele\u00a0…\x02" +
+ "&Uvozi tunel(e) iz datoteke…\x02I&zhod\x02&Tuneli\x02WireGuard aktiviran" +
+ "\x02Tunel %[1]s je bil aktiviran.\x02WireGuard deaktiviran\x02Tunel %[1]" +
+ "s je bil deaktiviran.\x02Napaka tunela WireGuard\x02WireGuard: %[1]s\x02" +
+ "Status: %[1]s\x02Naslovi: %[1]s\x02Na voljo je posodobitev!\x02Posodobit" +
+ "ev WireGuarda je na voljo\x02Posodobitev WireGuarda je na voljo. Svetuje" +
+ "mo posodobitev čim prej.\x02Tuneli\x02&Uredi\x02Dodaj &prazen tunel" +
+ "\u00a0…\x02Dodaj tunel\x02Odstrani izbrane tunele\x02Izvozi vse tunele v" +
+ " zip\x02&Preklopi\x02Izvozi vse tunele v &zip\u00a0…\x02Uredi &izbran tu" +
+ "nel\u00a0…\x02Odst&rani izbrane tunele\x02ni najdenih konfiguracijskih d" +
+ "atotek\x02Napaka pri uvozu izbrane konfiguracije: %[1]v\x02Napaka pri pr" +
+ "eštevanju obstoječih tunelov: %[1]v\x02Tunel z imenom »%[1]s« že obstaja" +
+ "\x02Napaka pri uvozu konfiguracije: %[1]v\x02Uvoženi tuneli\x14\x01\x81" +
+ "\x01\x00\x04\x16\x02Uvoženi %[1]d tuneli\x02\x14\x02Uvožen %[1]d tunel" +
+ "\x03\x16\x02Uvožena %[1]d tunela\x00\x17\x02Uvoženo %[1]d tunelov\x14" +
+ "\x02\x80\x01\x04 \x02Uvoženi %[1]d od %[2]d tunelov\x02\x1f\x02Uvožen %[" +
+ "1]d od %[2]d tunelov\x03 \x02Uvožena %[1]d od %[2]d tunelov\x00 \x02Uvož" +
+ "eno %[1]d od %[2]d tunelov\x02Tunela ni bilo mogoče ustvariti\x14\x01" +
+ "\x81\x01\x00\x04\x16\x02Izbriši %[1]d tunele\x02\x15\x02Izbriši %[1]d tu" +
+ "nel\x03\x16\x02Izbriši %[1]d tunela\x00\x17\x02Izbriši %[1]d tunelov\x14" +
+ "\x01\x81\x01\x00\x048\x02Ali ste prepričani, da želite izbrisati %[1]d t" +
+ "unele?\x027\x02Ali ste prepričani, da želite izbrisati %[1]d tunel?\x038" +
+ "\x02Ali ste prepričani, da želite izbrisati %[1]d tunela?\x009\x02Ali st" +
+ "e prepričani, da želite izbrisati %[1]d tunelov?\x02Izbriši tunel ‘%[1]s" +
+ "’\x02Ali ste prepričani, da želite izbrisati tunel »%[1]s«?\x02%[1]s T" +
+ "ega dejanja ne morete razveljaviti.\x02Napaka pri izbrisu tunela\x02Napa" +
+ "ka pri odstranjevanju tunela: %[1]s\x02Napaka pri izbrisu tunelov\x14" +
+ "\x01\x81\x01\x00\x04*\x02%[1]d tunelov ni bilo mogoče odstraniti.\x02)" +
+ "\x02%[1]d tunela ni bilo mogoče odstraniti.\x03*\x02%[1]d tunelov ni bil" +
+ "o mogoče odstraniti.\x00*\x02%[1]d tunelov ni bilo mogoče odstraniti." +
+ "\x02Konfiguracijske datoteke (*.zip, *.conf)|*.zip;*.conf|Vse datoteke (" +
+ "*.*)|*.*\x02Uvozi tunele iz datoteke\x02Konfiguracijske datoteke ZIP (*." +
+ "zip)|*.zip\x02Izvozi tunele v datoteko zip\x02%[1]s (nepodpisane različi" +
+ "ce, brez posodobitev)\x02Storitve ni bilo mogoče zaustaviti, ker: %[1]v." +
+ " Poskusite zaustaviti WireGuard z uporabo programa Storitve.\x02Status: " +
+ "Čaka na uporabnika\x02Status: Čaka na servis za posodobitev"
-var ukIndex = []uint32{ // 181 elements
+var trIndex = []uint32{ // 278 elements
// Entry 0 - 1F
- 0x00000000, 0x0000000f, 0x0000000f, 0x0000000f,
- 0x00000042, 0x0000009c, 0x0000009c, 0x000000f5,
- 0x00000191, 0x00000213, 0x0000026a, 0x00000275,
- 0x000002c8, 0x000002c8, 0x000002c8, 0x000002c8,
- 0x000002c8, 0x000002c8, 0x000002d7, 0x000002e0,
- 0x000002ed, 0x000002fa, 0x00000307, 0x00000314,
- 0x00000314, 0x00000335, 0x00000371, 0x000003ac,
- 0x000003e4, 0x0000041f, 0x00000436, 0x00000452,
+ 0x00000000, 0x00000005, 0x0000004c, 0x00000066,
+ 0x00000082, 0x000000c6, 0x0000010b, 0x00000136,
+ 0x0000018e, 0x0000022f, 0x00000236, 0x00000257,
+ 0x00000276, 0x00000295, 0x000002b4, 0x000002d7,
+ 0x000002fa, 0x00000306, 0x0000030f, 0x0000031c,
+ 0x00000329, 0x00000336, 0x00000343, 0x00000350,
+ 0x00000364, 0x00000383, 0x0000039f, 0x000003b3,
+ 0x000003c1, 0x000003d0, 0x000003f3, 0x0000040c,
// Entry 20 - 3F
- 0x00000452, 0x00000475, 0x00000475, 0x00000475,
- 0x00000494, 0x00000494, 0x000004da, 0x00000535,
- 0x00000567, 0x0000059f, 0x000005d2, 0x00000619,
- 0x0000063e, 0x0000068a, 0x000006cc, 0x00000713,
- 0x0000074d, 0x0000074d, 0x0000074d, 0x0000074d,
- 0x0000075e, 0x0000078e, 0x0000078e, 0x0000079d,
- 0x000007bc, 0x000007ca, 0x000007e4, 0x000007fa,
- 0x00000817, 0x00000817, 0x00000817, 0x00000817,
+ 0x00000441, 0x00000456, 0x00000472, 0x00000490,
+ 0x000004bd, 0x000004ed, 0x000004f0, 0x000004f3,
+ 0x00000507, 0x0000051c, 0x00000522, 0x00000535,
+ 0x0000053c, 0x00000552, 0x00000560, 0x00000570,
+ 0x0000057f, 0x00000584, 0x0000058e, 0x0000059f,
+ 0x000005c1, 0x000005d7, 0x000005e2, 0x000005f9,
+ 0x0000060f, 0x0000061c, 0x00000639, 0x0000064a,
+ 0x00000653, 0x00000660, 0x00000670, 0x00000687,
// Entry 40 - 5F
- 0x00000817, 0x00000817, 0x00000817, 0x00000817,
- 0x00000817, 0x00000817, 0x00000817, 0x00000817,
- 0x00000817, 0x00000817, 0x00000817, 0x00000817,
- 0x00000817, 0x00000817, 0x00000817, 0x00000817,
- 0x00000817, 0x00000817, 0x00000817, 0x00000817,
- 0x00000817, 0x00000817, 0x00000817, 0x00000817,
- 0x00000817, 0x00000817, 0x00000817, 0x00000817,
- 0x00000817, 0x00000817, 0x00000817, 0x00000817,
+ 0x0000068d, 0x0000069e, 0x000006c0, 0x000006dc,
+ 0x000006eb, 0x00000728, 0x0000073d, 0x00000759,
+ 0x000007bb, 0x000007cc, 0x000007f2, 0x00000806,
+ 0x00000842, 0x0000086b, 0x0000089d, 0x000008ba,
+ 0x000008f1, 0x00000913, 0x00000941, 0x0000096a,
+ 0x00000998, 0x000009c0, 0x000009e3, 0x00000a06,
+ 0x00000a18, 0x00000a22, 0x00000a35, 0x00000a49,
+ 0x00000a62, 0x00000a7c, 0x00000a91, 0x00000a97,
// Entry 60 - 7F
- 0x00000817, 0x00000817, 0x00000817, 0x00000817,
- 0x00000817, 0x00000817, 0x00000817, 0x00000817,
- 0x00000817, 0x00000817, 0x00000817, 0x00000817,
- 0x00000817, 0x00000817, 0x00000817, 0x00000817,
- 0x00000817, 0x00000817, 0x00000817, 0x00000817,
- 0x00000817, 0x00000817, 0x00000817, 0x00000817,
- 0x00000817, 0x00000817, 0x00000817, 0x00000817,
- 0x00000817, 0x00000817, 0x00000817, 0x00000817,
+ 0x00000ab9, 0x00000ad5, 0x00000af0, 0x00000b15,
+ 0x00000b25, 0x00000b29, 0x00000b3e, 0x00000b4f,
+ 0x00000b57, 0x00000b68, 0x00000b75, 0x00000ba8,
+ 0x00000bb0, 0x00000bb7, 0x00000bc8, 0x00000bd7,
+ 0x00000be9, 0x00000c0c, 0x00000c2c, 0x00000c40,
+ 0x00000c6e, 0x00000c94, 0x00000ca7, 0x00000ce6,
+ 0x00000cec, 0x00000cff, 0x00000d36, 0x00000d4f,
+ 0x00000d83, 0x00000d9c, 0x00000dae, 0x00000dbc,
// Entry 80 - 9F
- 0x00000817, 0x00000817, 0x00000817, 0x00000817,
- 0x00000817, 0x00000817, 0x00000817, 0x00000817,
- 0x00000817, 0x00000817, 0x00000817, 0x00000817,
- 0x00000817, 0x00000817, 0x00000817, 0x00000817,
- 0x00000817, 0x00000817, 0x00000817, 0x00000817,
- 0x00000817, 0x00000817, 0x00000817, 0x00000817,
- 0x00000817, 0x00000817, 0x00000817, 0x00000817,
- 0x00000817, 0x00000817, 0x00000817, 0x00000817,
+ 0x00000dd6, 0x00000dfd, 0x00000e08, 0x00000e17,
+ 0x00000e27, 0x00000e47, 0x00000e6c, 0x00000e96,
+ 0x00000eaf, 0x00000ec0, 0x00000ecd, 0x00000edd,
+ 0x00000ef1, 0x00000f10, 0x00000f6d, 0x00000f77,
+ 0x00000f7d, 0x00000f96, 0x00000fa2, 0x00000fbe,
+ 0x00000fe6, 0x00000ff2, 0x0000101e, 0x0000103c,
+ 0x00001059, 0x0000107d, 0x000010b0, 0x000010df,
+ 0x0000110c, 0x00001137, 0x00001152, 0x00001197,
// Entry A0 - BF
- 0x00000817, 0x00000817, 0x00000817, 0x00000817,
- 0x00000817, 0x00000817, 0x00000817, 0x00000817,
- 0x00000817, 0x00000817, 0x00000817, 0x00000817,
- 0x00000817, 0x00000817, 0x00000817, 0x00000817,
- 0x00000817, 0x00000817, 0x00000817, 0x00000817,
- 0x00000817,
-} // Size: 748 bytes
+ 0x000011e7, 0x00001200, 0x0000122d, 0x0000129c,
+ 0x000012b6, 0x000012f1, 0x00001316, 0x00001329,
+ 0x0000134c, 0x00001362, 0x000013a9, 0x000013f8,
+ 0x00001417, 0x00001441, 0x00001464, 0x0000148e,
+ 0x000014f9, 0x00001517, 0x00001542, 0x00001542,
+ 0x00001542, 0x00001542, 0x00001542, 0x00001542,
+ 0x00001542, 0x00001542, 0x00001542, 0x00001542,
+ 0x00001542, 0x00001542, 0x00001542, 0x00001542,
+ // Entry C0 - DF
+ 0x00001542, 0x00001542, 0x00001542, 0x00001542,
+ 0x00001542, 0x00001542, 0x00001542, 0x00001542,
+ 0x00001542, 0x00001542, 0x00001542, 0x00001542,
+ 0x00001542, 0x00001542, 0x00001542, 0x00001542,
+ 0x00001542, 0x00001542, 0x00001542, 0x00001542,
+ 0x00001542, 0x00001542, 0x00001542, 0x00001542,
+ 0x00001542, 0x00001542, 0x00001542, 0x00001542,
+ 0x00001542, 0x00001542, 0x00001542, 0x00001542,
+ // Entry E0 - FF
+ 0x00001542, 0x00001542, 0x00001542, 0x00001542,
+ 0x00001542, 0x00001542, 0x00001542, 0x00001542,
+ 0x00001542, 0x00001542, 0x00001542, 0x00001542,
+ 0x00001542, 0x00001542, 0x00001542, 0x00001542,
+ 0x00001542, 0x00001542, 0x00001542, 0x00001542,
+ 0x00001542, 0x00001542, 0x00001542, 0x00001542,
+ 0x00001542, 0x00001542, 0x00001542, 0x00001542,
+ 0x00001542, 0x00001542, 0x00001542, 0x00001542,
+ // Entry 100 - 11F
+ 0x00001542, 0x00001542, 0x00001542, 0x00001542,
+ 0x00001542, 0x00001542, 0x00001542, 0x00001542,
+ 0x00001542, 0x00001542, 0x00001542, 0x00001542,
+ 0x00001542, 0x00001542, 0x00001542, 0x00001542,
+ 0x00001542, 0x00001542, 0x00001542, 0x00001542,
+ 0x00001542, 0x00001542,
+} // Size: 1136 bytes
-const ukData string = "" + // Size: 2071 bytes
- "\x02Помилка\x02Параметри командного рядка\x02Неможливо визначити, чи пра" +
- "цює процес під WOW64: %[1]v\x02Не вдалося відкрити токен поточного проц" +
- "есу: %[1]v\x02WireGuard може бути використаний тільки користувачами, як" +
- "і є членами вбудованих %[1]s груп.\x02WireGuard запущено, але UI доступ" +
- "ний лише з комп\x22ютерів вбудованої %[1]s групи.\x02Значок системи Wir" +
- "eGuard не з'явився через 30 секунд.\x02Зараз\x02Системний годинник налаш" +
- "тований некоректно!\x02%[1]s тому\x02%[1]d Б\x02%.2[1]f КБ\x02%.2[1]f М" +
- "Б\x02%.2[1]f ГБ\x02%.2[1]f ТБ\x02Недійсна IP-адреса\x02Невірна довжина " +
- "префіксу мережі\x02Відсутній порт з кінцевої точки\x02Недійсний хост кі" +
- "нцевої точки\x02Дужки повинні містити адресу IPv6\x02Недійсний MTU\x02Н" +
- "едійсний порт\x02Недійсний ключ: %[1]v\x02Дві коми поспіль\x02Рядок пов" +
- "инен бути вказаним у розділі\x02Ключ конфігурації відсутній роздільник " +
- "рівності\x02Ключ повинен мати значення\x02Хибний ключ для [Interface] р" +
- "озділу\x02Хибний ключ для [Peer] розділу\x02Інтерфейс повинен мати особ" +
- "истий ключ\x02[жодного не вказано]\x02Всі учасники повинні мати відкрит" +
- "і ключі\x02Помилка при отриманні конфігурації\x02Недійсний ключ для роз" +
- "ділу інтерфейсу\x02Версія протоколу повинна бути 1\x02Про WireGuard\x02" +
- "Зображення логотипу WireGuard\x02Закрити\x02♥ &Пожертвувати!\x02Статус:" +
- "\x02&Деактивувати\x02&Активувати\x02Відкритий ключ:"
+const trData string = "" + // Size: 5442 bytes
+ "\x02Hata\x02(argüman verilmediyse): gerekli izinleri al ve yönetim hizme" +
+ "tini kur\x02Kullanım: %[1]s [\x0a%[2]s]\x02Komut Satırı Seçenekleri\x02İ" +
+ "şlemin WOW64 altında çalıştığından emin olunamadı: %[1]v\x02Bu bilgisay" +
+ "arda WireGuard'ın yerel sürümünü kullanmanız gerek.\x02Şu anki işlem jet" +
+ "onu açılamadı: %[1]v\x02WireGuard sadece sisteme yerleşik %[1]s grubunun" +
+ " üyeleri tarafından kullanılabilir.\x02WireGuard çalışıyor, fakat kullan" +
+ "ıcı arayüzü sadece sisteme yerleşik %[1]s grubunun üyesi olan kullanıcı" +
+ "lar tarafından masaüstünde erişilebilir.\x02Şimdi\x02Sistem saati geriye" +
+ " sarılmış!\x14\x01\x81\x01\x00\x02\x0b\x02%[1]d yıl\x00\x0b\x02%[1]d yıl" +
+ "\x14\x01\x81\x01\x00\x02\x0b\x02%[1]d gün\x00\x0b\x02%[1]d gün\x14\x01" +
+ "\x81\x01\x00\x02\x0b\x02%[1]d saat\x00\x0b\x02%[1]d saat\x14\x01\x81\x01" +
+ "\x00\x02\x0d\x02%[1]d dakika\x00\x0d\x02%[1]d dakika\x14\x01\x81\x01\x00" +
+ "\x02\x0d\x02%[1]d saniye\x00\x0d\x02%[1]d saniye\x02%[1]s önce\x02%[1]d" +
+ "\u00a0B\x02%.2[1]f\u00a0KiB\x02%.2[1]f\u00a0MiB\x02%.2[1]f\u00a0GiB\x02%" +
+ ".2[1]f\u00a0TiB\x02%[1]s: %[2]q\x02Geçersiz IP adresi\x02Ağ öneki uzunlu" +
+ "ğu geçersiz\x02Uç nokta port ayarı eksik\x02Geçersiz uç nokta\x02Geçers" +
+ "iz MTU\x02Geçersiz port\x02Geçersiz kalıcı açık bırakma\x02Geçersiz anah" +
+ "tar: %[1]v\x02Sayı 0 ve 2^64-1 arasında bir sayı olmalı: %[1]v\x02Yan ya" +
+ "na iki virgül\x02Tünel adı geçerli değil\x02[hiçbir şey belirtilmemiş}" +
+ "\x02Tüm eşler açık anahtarlara sahip olmalı\x02Yapılandırma bilgisi alın" +
+ "ırken hata oluştu\x02, \x02, \x02WireGuard Hakkında\x02WireGuard logo r" +
+ "esmi\x02Kapat\x02♥ &Bağış yap!\x02Durum:\x02&Devre dışı bırak\x02&Etkinl" +
+ "eştir\x02Açık anahtar:\x02Dinlenen port:\x02MTU:\x02Adresler:\x02DNS sun" +
+ "ucuları:\x02Önceden paylaşılmış anahtar:\x02İzin verilen IP'ler:\x02Uç n" +
+ "okta:\x02Kalıcı açık tutma:\x02En son el sıkışma:\x02Etkin değil\x02Devr" +
+ "e dışı bırakılıyor\x02Durum bilinmiyor\x02Günlük\x02Kopyala (&c)\x02&tüm" +
+ "ünü seç\x02Dosyaya kaydet (&s)…\x02Zaman\x02Günlük mesajı\x02Günlük dos" +
+ "yasını dışa aktar\x02WireGuard Hakkında (&a)…\x02Tünel Hatası\x02%[1]s" +
+ "\x0a\x0aLütfen daha fazla bilgi için günlüğe göz atın.\x02%[1]s (eski sü" +
+ "rüm)\x02WireGuard Çıkış Hatası\x02WireGuard için bir güncelleme mevcut. " +
+ "Bekletmeden güncelleme yapmanız önemle tavsiye edilir.\x02Şimdi Güncelle" +
+ "\x02Hata: %[1]v. Lütfen yeniden deneyin.\x02Durum: Tamamlandı!\x02WireGu" +
+ "ard sistem tepsisi ikonu 30 saniye sonunda belirmedi.\x02Parantezler bir" +
+ " IPv6 adresi içermelidir\x02Anahtarlar çözüldüğünde tam 32 byte olmalı" +
+ "\x02Satır bir bölümde olmalı\x02Yapılandırma anahtarında eşittir operatö" +
+ "rü eksik\x02Anahtar bir değere sahip olmalı\x02[Interface] bölümü için g" +
+ "eçersiz anahtar\x02[Peer] bölümü için geçersiz anahtar\x02Bir arabirim g" +
+ "izli anahtara sahip olmalıdır\x02Arabirim bölümünde geçersiz anahtar\x02" +
+ "Protokol sürümü 1 olmak zorunda\x02Eş bölümünde geçersiz anahtar\x02Komu" +
+ "t dosyaları:\x02Aktarım:\x02bağlantı-öncesi\x02bağlantı-sonrası\x02bağla" +
+ "ntı-kesme-öncesi\x02bağlantı-kesme-sonrası\x02ilke gereği kapalı\x02etki" +
+ "n\x02%[1]s alındı, %[2]s gönderildi\x02Tünel durumu belirlenemedi\x02Tün" +
+ "el etkinleştirilemedi\x02Tünel devre dışı bırakılamadı\x02Arabirim: %[1]" +
+ "s\x02Eş\x02Yeni tünel oluştur\x02Tüneli düzenle\x02&İsim:\x02&Açık anaht" +
+ "ar:\x02(bilinmiyor)\x02&Tünelden geçmeyen trafiği durdur (kill-switch)" +
+ "\x02&Kaydet\x02İptal\x02&Yapılandırma:\x02Geçersiz isim\x02Bir isim gere" +
+ "kli.\x02`%[1]s` geçersiz bir tünel ismi.\x02Mevcut tüneller listelenemiy" +
+ "or\x02Tünel zaten mevcut\x02‘%[1]s’ adında başka bir tünel mevcut.\x02Ye" +
+ "ni yapılandırma oluşturulamıyor\x02Dosya yazılamadı\x02`%[1]s` dosyası z" +
+ "aten mevcut.\x0a\x0aÜzerine yazmak ister misiniz?\x02Etkin\x02Etkinleşti" +
+ "riliyor\x02Metin Dosyaları (*.txt)|*.txt|Tüm Dosyalar (*.*)|*.*\x02WireG" +
+ "uard Tespit Hatası\x02WireGuard penceresinin belirmesi beklenemedi: %[1]" +
+ "v\x02WireGuard: Devre dışı\x02Durum: Bilinmiyor\x02Adresler: Yok\x02Tüne" +
+ "lleri yönet (&m)…\x02Dosyadan tünelleri içe aktar (&i)…\x02Çık (&x)\x02T" +
+ "üneller (&t)\x02WireGuard Etkin\x02%[1]s tüneli etkinleştirildi.\x02Wir" +
+ "eGuard Devre Dışı Bırakıldı\x02%[1]s tüneli devre dışı bırakıldı.\x02Wir" +
+ "eGuard Tünel Hatası\x02WireGuard: %[1]s\x02Durum: %[1]s\x02Adresler: %[1" +
+ "]s\x02Güncelleme Mevcut!\x02WireGuard Güncellemesi Mevcut\x02WireGuard i" +
+ "çin bir güncelleme mevcut. İlk fırsatta güncelleme yapmanız tavsiye edi" +
+ "lir.\x02Tüneller\x02&Edit\x02Boş tünel ekle (&e)…\x02Tünel Ekle\x02Seçil" +
+ "en tünelleri kaldır\x02Tüm tünelleri zip olarak dışa aktar\x02&Değiştir" +
+ "\x02Tüm tünelleri &zip olarak dışa aktar…\x02&Seçilen tüneli düzenle…" +
+ "\x02S&eçilen tünelleri kaldır\x02yapılandırma dosyası bulunamadı\x02Seçi" +
+ "len yapılandırma içe aktarılamadı: %[1]v\x02Mevcut tüneller numaralandır" +
+ "ılamadı: %[1]v\x02‘%[1]s’ adında başka bir tünel mevcut\x02Yapılandırma" +
+ " içe aktarılamıyor: %[1]v\x02Tüneller içe aktarıldı\x14\x01\x81\x01\x00" +
+ "\x02\x1e\x02%[1]d tünel içe aktarıldı\x00\x1e\x02%[1]d tünel içe aktarıl" +
+ "dı\x14\x02\x80\x01\x02$\x02%[2]d/%[1]d tünel içe aktarıldı\x00$\x02%[2]d" +
+ "/%[1]d tünel içe aktarıldı\x02Tünel oluşturulamıyor\x14\x01\x81\x01\x00" +
+ "\x02\x12\x02%[1]d tüneli sil\x00\x12\x02%[1]d tüneli sil\x14\x01\x81\x01" +
+ "\x00\x023\x02%[1]d tüneli silmek istediğinizden emin misiniz?\x003\x02%[" +
+ "1]d tüneli silmek istediğinizden emin misiniz?\x02‘%[1]s’ tünelini sil" +
+ "\x02‘%[1]s’ tünelini silmek istediğinizden emin misiniz?\x02%[1]s Bu işl" +
+ "emi geri alamazsınız.\x02Tünel silinemiyor\x02Bir tünel kaldırılamadı: %" +
+ "[1]s\x02Tüneller silinemiyor\x14\x01\x81\x01\x00\x02\x1f\x02%[1]d tünel " +
+ "kaldırılamadı.\x00\x1f\x02%[1]d tünel kaldırılamadı.\x02Yapılandırma Dos" +
+ "yaları (*.zip, *.conf)|*.zip;*.conf|Tüm Dosyalar (*.*)|*.*\x02Tünelleri " +
+ "dosyadan içe aktar\x02Yapılandırma ZIP Dosyası (*.zip)|*.zip\x02Tüneller" +
+ "i zip olarak dışa aktar\x02%[1]s (imzasız derleme, güncelleme yok)\x02Hi" +
+ "zmet şu nedenden dolayı kapatılamıyor: %[1]v. WireGuard'ı hizmet yönetic" +
+ "isinden durdurabilirsiniz.\x02Durum: Kullanıcı bekleniyor\x02Durum: Günc" +
+ "elleştirme hizmeti bekleniyor"
-var viIndex = []uint32{ // 181 elements
+var ukIndex = []uint32{ // 278 elements
+ // Entry 0 - 1F
+ 0x00000000, 0x0000000f, 0x0000008e, 0x000000b7,
+ 0x000000ea, 0x00000144, 0x000001c2, 0x0000021b,
+ 0x000002b7, 0x00000339, 0x00000344, 0x00000397,
+ 0x00000397, 0x00000397, 0x00000397, 0x00000397,
+ 0x00000397, 0x000003a6, 0x000003af, 0x000003bc,
+ 0x000003c9, 0x000003d6, 0x000003e3, 0x000003f0,
+ 0x00000411, 0x0000044d, 0x00000488, 0x000004c0,
+ 0x000004d7, 0x000004f3, 0x00000523, 0x00000546,
+ // Entry 20 - 3F
+ 0x00000592, 0x000005b1, 0x000005de, 0x00000603,
+ 0x0000064f, 0x00000691, 0x00000694, 0x00000697,
+ 0x000006a8, 0x000006d8, 0x000006e7, 0x00000706,
+ 0x00000714, 0x0000072e, 0x00000744, 0x00000761,
+ 0x0000076b, 0x00000770, 0x0000077e, 0x00000792,
+ 0x000007a6, 0x000007ca, 0x000007d4, 0x000007ea,
+ 0x00000815, 0x00000815, 0x00000815, 0x00000815,
+ 0x00000815, 0x00000815, 0x00000815, 0x00000815,
+ // Entry 40 - 5F
+ 0x00000815, 0x00000815, 0x00000815, 0x00000815,
+ 0x00000815, 0x00000815, 0x00000815, 0x00000815,
+ 0x00000815, 0x00000815, 0x00000815, 0x00000815,
+ 0x0000086c, 0x000008a7, 0x000008e9, 0x0000092f,
+ 0x0000098a, 0x000009bc, 0x000009f4, 0x00000a27,
+ 0x00000a6e, 0x00000ab5, 0x00000aef, 0x00000b22,
+ 0x00000b32, 0x00000b44, 0x00000b60, 0x00000b7a,
+ 0x00000b96, 0x00000bb0, 0x00000bed, 0x00000c00,
+ // Entry 60 - 7F
+ 0x00000c35, 0x00000c72, 0x00000ca8, 0x00000ce2,
+ 0x00000cfc, 0x00000d03, 0x00000d2c, 0x00000d4e,
+ 0x00000d5b, 0x00000d79, 0x00000d8e, 0x00000dc7,
+ 0x00000dd9, 0x00000dec, 0x00000e07, 0x00000e1a,
+ 0x00000e43, 0x00000e76, 0x00000ebd, 0x00000edc,
+ 0x00000f15, 0x00000f15, 0x00000f15, 0x00000f15,
+ 0x00000f15, 0x00000f15, 0x00000f15, 0x00000f15,
+ 0x00000f15, 0x00000f15, 0x00000f15, 0x00000f15,
+ // Entry 80 - 9F
+ 0x00000f15, 0x00000f15, 0x00000f15, 0x00000f15,
+ 0x00000f15, 0x00000f15, 0x00000f15, 0x00000f15,
+ 0x00000f15, 0x00000f15, 0x00000f15, 0x00000f15,
+ 0x00000f15, 0x00000f15, 0x00000f15, 0x00000f15,
+ 0x00000f15, 0x00000f15, 0x00000f15, 0x00000f15,
+ 0x00000f15, 0x00000f15, 0x00000f15, 0x00000f15,
+ 0x00000f15, 0x00000f51, 0x00000fab, 0x00000ffb,
+ 0x00001033, 0x0000107e, 0x000010a2, 0x0000115b,
+ // Entry A0 - BF
+ 0x0000115b, 0x0000115b, 0x0000115b, 0x0000115b,
+ 0x0000115b, 0x0000115b, 0x0000115b, 0x0000115b,
+ 0x0000115b, 0x0000115b, 0x0000115b, 0x0000115b,
+ 0x0000115b, 0x0000115b, 0x0000115b, 0x0000115b,
+ 0x0000115b, 0x0000115b, 0x0000115b, 0x0000115b,
+ 0x0000115b, 0x0000115b, 0x0000115b, 0x0000115b,
+ 0x0000115b, 0x0000115b, 0x0000115b, 0x0000115b,
+ 0x0000115b, 0x0000115b, 0x0000115b, 0x0000115b,
+ // Entry C0 - DF
+ 0x0000115b, 0x0000115b, 0x0000115b, 0x0000115b,
+ 0x0000115b, 0x0000115b, 0x0000115b, 0x0000115b,
+ 0x0000115b, 0x0000115b, 0x0000115b, 0x0000115b,
+ 0x0000115b, 0x0000115b, 0x0000115b, 0x0000115b,
+ 0x0000115b, 0x0000115b, 0x0000115b, 0x0000115b,
+ 0x0000115b, 0x0000115b, 0x0000115b, 0x0000115b,
+ 0x0000115b, 0x0000115b, 0x0000115b, 0x0000115b,
+ 0x0000115b, 0x0000115b, 0x0000115b, 0x0000115b,
+ // Entry E0 - FF
+ 0x0000115b, 0x0000115b, 0x0000115b, 0x0000115b,
+ 0x0000115b, 0x0000115b, 0x0000115b, 0x0000115b,
+ 0x0000115b, 0x0000115b, 0x0000115b, 0x0000115b,
+ 0x0000115b, 0x0000115b, 0x0000115b, 0x0000115b,
+ 0x0000115b, 0x0000115b, 0x0000115b, 0x0000115b,
+ 0x0000115b, 0x0000115b, 0x0000115b, 0x0000115b,
+ 0x0000115b, 0x0000115b, 0x0000115b, 0x0000115b,
+ 0x0000115b, 0x0000115b, 0x0000115b, 0x0000115b,
+ // Entry 100 - 11F
+ 0x0000115b, 0x0000115b, 0x0000115b, 0x0000115b,
+ 0x0000115b, 0x0000115b, 0x0000115b, 0x0000115b,
+ 0x0000115b, 0x0000115b, 0x0000115b, 0x0000115b,
+ 0x0000115b, 0x0000115b, 0x0000115b, 0x0000115b,
+ 0x0000115b, 0x0000115b, 0x0000115b, 0x0000115b,
+ 0x0000115b, 0x0000115b,
+} // Size: 1136 bytes
+
+const ukData string = "" + // Size: 4443 bytes
+ "\x02Помилка\x02(немає аргумента): отримати права аднімістратора і встано" +
+ "вити службу\x02Використання: %[1]s [\x0a%[2]s]\x02Параметри командного " +
+ "рядка\x02Неможливо визначити, чи працює процес під WOW64: %[1]v\x02Ви п" +
+ "овинні використовувати нативну версію WireGuard на цьому комп'ютері." +
+ "\x02Не вдалося відкрити токен поточного процесу: %[1]v\x02WireGuard може" +
+ " бути використаний тільки користувачами, які є членами вбудованих %[1]s " +
+ "груп.\x02WireGuard запущено, але UI доступний лише з комп\x22ютерів вбу" +
+ "дованої %[1]s групи.\x02Зараз\x02Системний годинник налаштований некоре" +
+ "ктно!\x02%[1]s тому\x02%[1]d Б\x02%.2[1]f КБ\x02%.2[1]f МБ\x02%.2[1]f Г" +
+ "Б\x02%.2[1]f ТБ\x02%[1]s: %[2]q\x02Недійсна IP-адреса\x02Невірна довжин" +
+ "а префіксу мережі\x02Відсутній порт з кінцевої точки\x02Недійсний хост " +
+ "кінцевої точки\x02Недійсний MTU\x02Недійсний порт\x02Некоректне значенн" +
+ "я keepalive\x02Недійсний ключ: %[1]v\x02Номер повинен бути числом від 0" +
+ " до 2^64-1: %[1]v\x02Дві коми поспіль\x02Назва тунелю некоректна\x02[жод" +
+ "ного не вказано]\x02Всі учасники повинні мати відкриті ключі\x02Помилка" +
+ " при отриманні конфігурації\x02, \x02, \x02Про WireGuard\x02Зображення л" +
+ "оготипу WireGuard\x02Закрити\x02♥ &Пожертвувати!\x02Статус:\x02&Деактив" +
+ "увати\x02&Активувати\x02Відкритий ключ:\x02Порт:\x02MTU:\x02Адреси:\x02" +
+ "DNS-сервери:\x02Preshared ключ:\x02Дозволені IP адреси:\x02Endpoint:\x02" +
+ "Persistent keepalive:\x02Останнє рукостискання:\x02Значок системи WireGu" +
+ "ard не з'явився через 30 секунд.\x02Дужки повинні містити адресу IPv6" +
+ "\x02Ключ повинен декодуватись до 32 байт\x02Рядок повинен бути вказаним " +
+ "у розділі\x02Ключ конфігурації відсутній роздільник рівності\x02Ключ по" +
+ "винен мати значення\x02Хибний ключ для [Interface] розділу\x02Хибний кл" +
+ "юч для [Peer] розділу\x02Інтерфейс повинен мати особистий ключ\x02Недій" +
+ "сний ключ для розділу інтерфейсу\x02Версія протоколу повинна бути 1\x02" +
+ "Хибний ключ для [Peer] розділу\x02Скрипти:\x02Передано:\x02перед-запуск" +
+ "ом\x02після-запуску\x02перед-зупинкою\x02після-зупинки\x02вимкнено, від" +
+ "повідно до політики\x02увімкнено\x02%[1]s отримано, %[2]s відправлено" +
+ "\x02Не вдалося визначити стан тунелю\x02Не вдалося активувати тунель\x02" +
+ "Не вдалося деактивувати тунель\x02Інтерфейс: %[1]s\x02Пір\x02Створити н" +
+ "овий тунель\x02Редагувати тунель\x02&Назва:\x02&Публічний ключ:\x02(нев" +
+ "ідомий)\x02&Блокувати трафік поза тунелем\x02&Зберегти\x02Скасувати\x02" +
+ "&Налаштування:\x02Хибне ім'я\x02Необхідно ввести ім'я.\x02Ім'я тунелю '%" +
+ "[1]s' некоректне.\x02Не вдалося відобразити існуючі тунелі\x02Тунель вже" +
+ " існує\x02Тунель з ім'ям ‘%[1]s’ вже існує.\x02не знайдено файлів конфіг" +
+ "урації\x02Не вдалося імпортувати вибрану конфігурацію: %[1]v\x02Не вдал" +
+ "ося перерахувати існуючі тунелі: %[1]v\x02Тунель з ім'ям ‘%[1]s’ вже іс" +
+ "нує\x02Не вдалося імпортувати конфігурацію: %[1]v\x02Імпортовано тунелі" +
+ "\x14\x01\x81\x01\x00\x04*\x02Імпортовано %[1]d тунелі\x05,\x02Імпортован" +
+ "о %[1]d тунелів\x02*\x02Імпортовано %[1]d тунель\x00,\x02Імпортовано %[" +
+ "1]d тунелів"
+
+var viIndex = []uint32{ // 278 elements
// Entry 0 - 1F
0x00000000, 0x00000006, 0x00000006, 0x00000006,
0x00000006, 0x00000006, 0x00000006, 0x00000006,
- 0x00000006, 0x00000006, 0x00000006, 0x00000011,
- 0x00000011, 0x00000023, 0x00000036, 0x00000049,
- 0x0000005c, 0x0000006f, 0x0000007e, 0x0000007e,
+ 0x00000006, 0x00000006, 0x00000011, 0x00000011,
+ 0x00000023, 0x00000036, 0x00000049, 0x0000005c,
+ 0x0000006f, 0x0000007e, 0x0000007e, 0x0000007e,
0x0000007e, 0x0000007e, 0x0000007e, 0x0000007e,
- 0x0000007e, 0x000000a0, 0x000000a0, 0x000000a0,
- 0x000000a0, 0x000000a0, 0x000000a0, 0x000000c0,
+ 0x000000a0, 0x000000a0, 0x000000a0, 0x000000a0,
+ 0x000000a0, 0x000000c0, 0x000000c0, 0x000000c0,
// Entry 20 - 3F
- 0x000000c0, 0x000000c0, 0x000000c0, 0x000000c0,
- 0x000000c0, 0x000000db, 0x000000db, 0x000000db,
+ 0x000000c0, 0x000000c0, 0x000000db, 0x000000db,
0x000000db, 0x000000db, 0x000000db, 0x000000db,
- 0x000000db, 0x000000db, 0x000000db, 0x000000db,
- 0x000000db, 0x000000db, 0x000000db, 0x000000db,
- 0x000000f5, 0x00000104, 0x00000104, 0x0000010b,
- 0x0000010b, 0x0000011a, 0x0000011a, 0x0000011a,
+ 0x000000f5, 0x00000104, 0x0000010b, 0x0000010b,
0x0000011a, 0x0000011a, 0x0000011a, 0x0000011a,
- // Entry 40 - 5F
0x0000011a, 0x0000011a, 0x0000011a, 0x0000011a,
+ 0x0000011a, 0x0000011a, 0x00000129, 0x00000129,
0x00000129, 0x00000129, 0x00000129, 0x00000129,
- 0x00000129, 0x0000013b, 0x00000155, 0x00000181,
- 0x0000019f, 0x000001c0, 0x000001c0, 0x000001d3,
- 0x000001dd, 0x000001ef, 0x000001ef, 0x000001ef,
- 0x000001ef, 0x000001ef, 0x000001ef, 0x000001ef,
- 0x000001f5, 0x000001f5, 0x0000020c, 0x00000224,
- 0x0000024a, 0x0000026b, 0x00000280, 0x000002ad,
+ 0x00000129, 0x00000129, 0x00000129, 0x00000129,
+ // Entry 40 - 5F
+ 0x00000129, 0x00000129, 0x00000129, 0x00000129,
+ 0x00000129, 0x00000129, 0x00000129, 0x00000129,
+ 0x00000129, 0x00000129, 0x00000129, 0x00000129,
+ 0x00000129, 0x00000129, 0x00000129, 0x00000129,
+ 0x00000129, 0x00000129, 0x00000129, 0x00000129,
+ 0x00000129, 0x00000129, 0x00000129, 0x00000129,
+ 0x00000129, 0x00000129, 0x00000129, 0x00000129,
+ 0x00000129, 0x00000129, 0x00000129, 0x0000013b,
// Entry 60 - 7F
+ 0x00000155, 0x00000181, 0x0000019f, 0x000001c0,
+ 0x000001c0, 0x000001d3, 0x000001dd, 0x000001ef,
+ 0x000001ef, 0x000001ef, 0x000001ef, 0x000001ef,
+ 0x000001ef, 0x000001f5, 0x000001f5, 0x0000020c,
+ 0x00000224, 0x0000024a, 0x0000026b, 0x00000280,
+ 0x000002ad, 0x000002ad, 0x000002ad, 0x000002ad,
0x000002ad, 0x000002ad, 0x000002ad, 0x000002ad,
0x000002ad, 0x000002ad, 0x000002ad, 0x000002ad,
+ // Entry 80 - 9F
0x000002ad, 0x000002ad, 0x000002ad, 0x000002ad,
0x000002ad, 0x000002ad, 0x000002ad, 0x000002ad,
0x000002ad, 0x000002ad, 0x000002ad, 0x000002ad,
0x000002ad, 0x000002ad, 0x000002ad, 0x000002ad,
0x000002ad, 0x000002ad, 0x000002ad, 0x000002ad,
0x000002ad, 0x000002ad, 0x000002ad, 0x000002ad,
- // Entry 80 - 9F
0x000002ad, 0x000002ad, 0x000002ad, 0x000002ad,
0x000002ad, 0x000002ad, 0x000002ad, 0x000002ad,
+ // Entry A0 - BF
0x000002ad, 0x000002ad, 0x000002ad, 0x000002ad,
0x000002ad, 0x000002ad, 0x000002ad, 0x000002ad,
0x000002ad, 0x000002ad, 0x000002ad, 0x000002ad,
0x000002ad, 0x000002ad, 0x000002ad, 0x000002ad,
0x000002ad, 0x000002ad, 0x000002ad, 0x000002ad,
0x000002ad, 0x000002ad, 0x000002ad, 0x000002ad,
- // Entry A0 - BF
+ 0x000002ad, 0x000002ad, 0x000002ad, 0x000002ad,
+ 0x000002ad, 0x000002ad, 0x000002ad, 0x000002ad,
+ // Entry C0 - DF
+ 0x000002ad, 0x000002ad, 0x000002ad, 0x000002ad,
+ 0x000002ad, 0x000002ad, 0x000002ad, 0x000002ad,
+ 0x000002ad, 0x000002ad, 0x000002ad, 0x000002ad,
+ 0x000002ad, 0x000002ad, 0x000002ad, 0x000002ad,
+ 0x000002ad, 0x000002ad, 0x000002ad, 0x000002ad,
+ 0x000002ad, 0x000002ad, 0x000002ad, 0x000002ad,
+ 0x000002ad, 0x000002ad, 0x000002ad, 0x000002ad,
+ 0x000002ad, 0x000002ad, 0x000002ad, 0x000002ad,
+ // Entry E0 - FF
+ 0x000002ad, 0x000002ad, 0x000002ad, 0x000002ad,
+ 0x000002ad, 0x000002ad, 0x000002ad, 0x000002ad,
+ 0x000002ad, 0x000002ad, 0x000002ad, 0x000002ad,
+ 0x000002ad, 0x000002ad, 0x000002ad, 0x000002ad,
+ 0x000002ad, 0x000002ad, 0x000002ad, 0x000002ad,
+ 0x000002ad, 0x000002ad, 0x000002ad, 0x000002ad,
+ 0x000002ad, 0x000002ad, 0x000002ad, 0x000002ad,
+ 0x000002ad, 0x000002ad, 0x000002ad, 0x000002ad,
+ // Entry 100 - 11F
0x000002ad, 0x000002ad, 0x000002ad, 0x000002ad,
0x000002ad, 0x000002ad, 0x000002ad, 0x000002ad,
0x000002ad, 0x000002ad, 0x000002ad, 0x000002ad,
0x000002ad, 0x000002ad, 0x000002ad, 0x000002ad,
0x000002ad, 0x000002ad, 0x000002ad, 0x000002ad,
- 0x000002ad,
-} // Size: 748 bytes
+ 0x000002ad, 0x000002ad,
+} // Size: 1136 bytes
const viData string = "" + // Size: 685 bytes
"\x02Lỗi\x02Vừa xong\x14\x01\x81\x01\x00\x00\x0b\x02%[1]d năm\x14\x01\x81" +
@@ -2234,204 +3594,257 @@ const viData string = "" + // Size: 685 bytes
"1]s' không hợp lệ.\x02Không thể liệt kê các VPN\x02VPN đã tồn tại\x02Đã " +
"tồn tại VPN với tên ‘%[1]s’."
-var zh_CNIndex = []uint32{ // 181 elements
+var zh_CNIndex = []uint32{ // 278 elements
// Entry 0 - 1F
0x00000000, 0x00000007, 0x00000030, 0x00000047,
0x00000057, 0x0000008b, 0x000000c9, 0x000000ef,
- 0x00000134, 0x0000018e, 0x000001c5, 0x000001cc,
- 0x000001e5, 0x000001f6, 0x00000207, 0x0000021b,
- 0x0000022f, 0x00000240, 0x0000024a, 0x00000252,
- 0x0000025f, 0x0000026c, 0x00000279, 0x00000286,
- 0x00000293, 0x000002a2, 0x000002bb, 0x000002dd,
- 0x00000304, 0x0000032c, 0x00000337, 0x00000344,
+ 0x00000134, 0x0000018e, 0x00000195, 0x000001ae,
+ 0x000001bf, 0x000001d0, 0x000001e4, 0x000001f8,
+ 0x00000209, 0x00000213, 0x0000021b, 0x00000228,
+ 0x00000235, 0x00000242, 0x0000024f, 0x0000025c,
+ 0x0000026b, 0x00000284, 0x000002a6, 0x000002cd,
+ 0x000002d8, 0x000002e5, 0x000002fe, 0x00000316,
// Entry 20 - 3F
- 0x0000035d, 0x00000375, 0x0000039f, 0x000003cd,
- 0x000003e6, 0x000003f9, 0x00000415, 0x0000043a,
- 0x0000044d, 0x0000046c, 0x00000486, 0x000004a2,
- 0x000004ae, 0x000004d0, 0x000004e6, 0x000004ff,
- 0x00000517, 0x00000530, 0x00000534, 0x00000536,
- 0x00000547, 0x0000055d, 0x000005c7, 0x000005ce,
- 0x000005df, 0x000005e7, 0x000005f3, 0x000005ff,
- 0x00000607, 0x00000615, 0x0000061a, 0x00000622,
+ 0x00000344, 0x0000035d, 0x00000370, 0x0000037c,
+ 0x0000039e, 0x000003b4, 0x000003b8, 0x000003ba,
+ 0x000003cb, 0x000003e1, 0x000003e8, 0x000003f9,
+ 0x00000401, 0x0000040d, 0x00000419, 0x00000421,
+ 0x0000042f, 0x00000434, 0x0000043c, 0x0000044b,
+ 0x0000045c, 0x0000046a, 0x00000472, 0x00000486,
+ 0x0000049a, 0x000004a4, 0x000004b1, 0x000004b8,
+ 0x000004bf, 0x000004cb, 0x000004d7, 0x000004e6,
// Entry 40 - 5F
- 0x00000631, 0x00000639, 0x0000064a, 0x00000658,
- 0x00000660, 0x00000674, 0x00000688, 0x00000690,
- 0x000006af, 0x000006b9, 0x000006d4, 0x000006ed,
- 0x00000700, 0x00000719, 0x00000727, 0x0000072e,
- 0x0000073e, 0x0000074b, 0x00000758, 0x00000765,
- 0x0000076e, 0x0000079d, 0x00000873, 0x0000087f,
- 0x00000886, 0x00000893, 0x000008a0, 0x000008b6,
- 0x000008d4, 0x000008ed, 0x000008fd, 0x0000091e,
+ 0x000004ed, 0x000004fa, 0x00000507, 0x00000520,
+ 0x0000052d, 0x00000553, 0x00000565, 0x00000580,
+ 0x000005b8, 0x000005c5, 0x000005e2, 0x000005f4,
+ 0x0000062b, 0x00000653, 0x0000067d, 0x00000699,
+ 0x000006be, 0x000006d1, 0x000006f6, 0x00000716,
+ 0x00000732, 0x0000074b, 0x00000763, 0x0000077c,
+ 0x00000784, 0x0000078c, 0x00000796, 0x000007a0,
+ 0x000007aa, 0x000007b4, 0x000007d3, 0x000007dd,
// Entry 60 - 7F
- 0x00000937, 0x0000094a, 0x00000985, 0x0000098f,
- 0x0000099c, 0x000009a6, 0x000009b3, 0x000009ba,
- 0x000009c1, 0x000009cd, 0x000009d9, 0x000009e8,
- 0x000009ef, 0x000009fc, 0x00000a2e, 0x00000a3b,
- 0x00000a54, 0x00000a61, 0x00000a87, 0x00000a99,
- 0x00000ab0, 0x00000adb, 0x00000af0, 0x00000aff,
- 0x00000b0b, 0x00000b20, 0x00000b3e, 0x00000b4a,
- 0x00000b5e, 0x00000b7c, 0x00000b90, 0x00000bb4,
+ 0x000007f8, 0x00000811, 0x00000824, 0x0000083d,
+ 0x0000084b, 0x00000852, 0x00000862, 0x0000086f,
+ 0x0000087c, 0x00000889, 0x00000892, 0x000008c1,
+ 0x000008cd, 0x000008d4, 0x000008e1, 0x000008ee,
+ 0x00000904, 0x00000922, 0x0000093b, 0x0000094b,
+ 0x0000096c, 0x00000985, 0x00000998, 0x000009d3,
+ 0x000009dd, 0x000009ea, 0x00000a1c, 0x00000a33,
+ 0x00000a5e, 0x00000a73, 0x00000a82, 0x00000a8e,
// Entry 80 - 9F
- 0x00000bcb, 0x00000bdc, 0x00000bea, 0x00000bf8,
- 0x00000c08, 0x00000c19, 0x00000c5b, 0x00000c62,
- 0x00000c6e, 0x00000c86, 0x00000c93, 0x00000ca6,
- 0x00000cc9, 0x00000ce1, 0x00000d0c, 0x00000d27,
- 0x00000d3f, 0x00000d55, 0x00000d6f, 0x00000d8f,
- 0x00000dbc, 0x00000dd6, 0x00000de3, 0x00000e04,
- 0x00000e3a, 0x00000e4d, 0x00000e6b, 0x00000e9e,
- 0x00000eb6, 0x00000ee0, 0x00000efe, 0x00000f11,
+ 0x00000aa3, 0x00000ac1, 0x00000acd, 0x00000ad9,
+ 0x00000aed, 0x00000b0b, 0x00000b1f, 0x00000b43,
+ 0x00000b5a, 0x00000b6b, 0x00000b79, 0x00000b87,
+ 0x00000b97, 0x00000ba8, 0x00000bea, 0x00000bf1,
+ 0x00000bfd, 0x00000c15, 0x00000c22, 0x00000c35,
+ 0x00000c58, 0x00000c70, 0x00000c9b, 0x00000cb6,
+ 0x00000cce, 0x00000ce4, 0x00000cfe, 0x00000d1e,
+ 0x00000d4b, 0x00000d65, 0x00000d72, 0x00000d93,
// Entry A0 - BF
- 0x00000f2b, 0x00000f3e, 0x00000f65, 0x00000fa6,
- 0x00000fbc, 0x00000fd7, 0x00000ffa, 0x00001027,
- 0x00001042, 0x000010a3, 0x000010db, 0x000010f0,
- 0x000010fd, 0x00001118, 0x00001135, 0x00001147,
- 0x00001151, 0x0000115b, 0x00001165, 0x0000116f,
- 0x0000117b,
-} // Size: 748 bytes
+ 0x00000dc9, 0x00000ddc, 0x00000dfa, 0x00000e2d,
+ 0x00000e45, 0x00000e6f, 0x00000e8d, 0x00000ea0,
+ 0x00000eba, 0x00000ecd, 0x00000ef4, 0x00000f35,
+ 0x00000f4b, 0x00000f66, 0x00000f89, 0x00000fb6,
+ 0x00001017, 0x0000102c, 0x00001047, 0x00001047,
+ 0x00001047, 0x00001047, 0x00001047, 0x00001047,
+ 0x00001047, 0x00001047, 0x00001047, 0x00001047,
+ 0x00001047, 0x00001047, 0x00001047, 0x00001047,
+ // Entry C0 - DF
+ 0x00001047, 0x00001047, 0x00001047, 0x00001047,
+ 0x00001047, 0x00001047, 0x00001047, 0x00001047,
+ 0x00001047, 0x00001047, 0x00001047, 0x00001047,
+ 0x00001047, 0x00001047, 0x00001047, 0x00001047,
+ 0x00001047, 0x00001047, 0x00001047, 0x00001047,
+ 0x00001047, 0x00001047, 0x00001047, 0x00001047,
+ 0x00001047, 0x00001047, 0x00001047, 0x00001047,
+ 0x00001047, 0x00001047, 0x00001047, 0x00001047,
+ // Entry E0 - FF
+ 0x00001047, 0x00001047, 0x00001047, 0x00001047,
+ 0x00001047, 0x00001047, 0x00001047, 0x00001047,
+ 0x00001047, 0x00001047, 0x00001047, 0x00001047,
+ 0x00001047, 0x00001047, 0x00001047, 0x00001047,
+ 0x00001047, 0x00001047, 0x00001047, 0x00001047,
+ 0x00001047, 0x00001047, 0x00001047, 0x00001047,
+ 0x00001047, 0x00001047, 0x00001047, 0x00001047,
+ 0x00001047, 0x00001047, 0x00001047, 0x00001047,
+ // Entry 100 - 11F
+ 0x00001047, 0x00001047, 0x00001047, 0x00001047,
+ 0x00001047, 0x00001047, 0x00001047, 0x00001047,
+ 0x00001047, 0x00001047, 0x00001047, 0x00001047,
+ 0x00001047, 0x00001047, 0x00001047, 0x00001047,
+ 0x00001047, 0x00001047, 0x00001047, 0x00001047,
+ 0x00001047, 0x00001047,
+} // Size: 1136 bytes
-const zh_CNData string = "" + // Size: 4475 bytes
+const zh_CNData string = "" + // Size: 4167 bytes
"\x02错误\x02(无参数): 提升并安装管理服务\x02用法: %[1]s [\x0a%[2]s]\x02命令行选项\x02无法确定该进程是" +
"否在WOW64下运行: %[1]v\x02您必须在此计算机上使用原生版本的 WireGuard。\x02无法打开当前进程令牌: %[1]v" +
"\x02WireGuard 可能只能被内建的 %[1]s 小组中的成员使用。\x02WireGuard 正在运行,但用户界面只能从内建的 %[1" +
- "]s 小组的桌面访问。\x02WireGuard 系统托盘图标在30秒后没有出现。\x02刚刚\x02系统时间倒退了!\x14\x01\x81" +
- "\x01\x00\x00\x0a\x02%[1]d 年\x14\x01\x81\x01\x00\x00\x0a\x02%[1]d 天\x14" +
- "\x01\x81\x01\x00\x00\x0d\x02%[1]d 小时\x14\x01\x81\x01\x00\x00\x0d\x02%[1]" +
- "d 分钟\x14\x01\x81\x01\x00\x00\x0a\x02%[1]d 秒\x02%[1]s 前\x02%[1]d B\x02%.2" +
- "[1]f\u00a0KiB\x02%.2[1]f\u00a0MiB\x02%.2[1]f\u00a0GiB\x02%.2[1]f\u00a0Ti" +
- "B\x02%[1]s: %[2]q\x02IP地址无效\x02网络前缀长度无效\x02对端 (endpoint) 中缺少端口\x02对端主机名 " +
- "(endpoint host) 无效\x02方括号中应包含一个 IPv6 地址\x02MTU 无效\x02端口无效\x02连接保活间隔无效" +
- "\x02无效的密钥:%[1]v\x02解码后的密钥长度必须为32字节\x02数值必须介于 0 至 2^64-1 之间: %[1]v\x02一行中" +
- "有两个逗号\x02隧道名称无效\x02行必须出现在段落中\x02配置项必须要有一个等于号\x02必须有一个值\x02[Interface] " +
- "段落的键无效\x02[Peer] 段落的键无效\x02接口必须有一个私钥\x02[未指定]\x02所有节点必须拥有公钥。\x02获取配置时出" +
- "错\x02接口段落的键无效\x02协议版本必须为 1\x02节点段落的键无效\x02、\x02 \x02关于 WireGuard\x02Wi" +
- "reGuard logo 图片\x02应用版本: %[1]s\x0aGo 后端版本: %[2]s\x0aGo 语言版本: %[3]s-%[4]s" +
- "\x0a操作系统: %[5]s\x0a架构: %[6]s\x02关闭\x02♥ 捐助! (&D)\x02状态:\x02断开 (&D)\x02连接" +
- " (&A)\x02公钥:\x02监听端口:\x02MTU:\x02地址:\x02DNS 服务器:\x02脚本:\x02预共享密钥:\x02允许的" +
- " IP:\x02对端:\x02连接保活间隔:\x02上次握手时间:\x02流量:\x02已禁用(依管理策略)\x02已启用\x02接收 %[1]" +
- "s, 发送 %[2]s\x02无法确认隧道状态\x02无法连接隧道\x02无法断开隧道连接\x02接口: %[1]s\x02节点\x02创建新隧" +
- "道\x02编辑隧道\x02名称 (&N):\x02公钥 (&P):\x02(未知)\x02拦截未经隧道的流量 (kill-switch) (" +
- "&B)\x02只有一个节点,且该节点允许的 IP 中包含 0.0.0.0/0 或 ::/0 时,使用防火墙规则拦截所有未通过隧道,或是发往错误的" +
- " DNS 服务器的流量。DHCP 和 NDP 流量不受影响。\x02保存 (&S)\x02取消\x02配置 (&C):\x02名称无效\x02必" +
- "须输入名称。\x02隧道名「%[1]s」无效。\x02无法列出现有隧道\x02隧道已存在\x02隧道名「%[1]s」已存在。\x02无法创建" +
- "新的配置\x02写入文件失败\x02文件「%[1]s」已存在。\x0a\x0a您确定要覆盖它吗?\x02已连接\x02正在连接\x02已断开" +
- "\x02正在断开\x02未知\x02日志\x02复制 (&C)\x02全选 (&A)\x02导出… (&S)\x02时间\x02日志消息\x02" +
- "文本文件 (*.txt)|*.txt|所有文件 (*.*)|*.*\x02导出日志\x02关于 WireGuard… (&A)\x02隧道错" +
- "误\x02%[1]s\x0a\x0a更多信息请查看日志。\x02%[1]s (已过时)\x02WireGuard 检测错误\x02无法等待 " +
- "WireGuard 窗口出现: %[1]v\x02WireGuard: 已断开\x02状态: 未知\x02地址: 无\x02管理隧道… (&M)" +
- "\x02从文件导入隧道… (&I)\x02退出 (&E)\x02WireGuard 已连接\x02隧道「%[1]s」已连接。\x02WireGu" +
- "ard 已断开\x02隧道「%[1]s」已断开连接。\x02WireGuard 隧道错误\x02WireGuard: %[1]s\x02状态: " +
- "%[1]s\x02地址: %[1]s\x02发现更新!\x02WireGuard 更新\x02新的 WireGuard 版本发布了。强烈建议您现" +
- "在安装。\x02隧道\x02编辑 (&E)\x02新建空隧道… (&E)\x02新建隧道\x02删除所选隧道\x02导出所有隧道 (ZIP " +
- "压缩包)\x02切换连接状态 (&T)\x02导出所有隧道 (ZIP 压缩包)… (&Z)\x02编辑所选隧道… (&E)\x02删除所选隧" +
- "道 (&R)\x02未找到配置文件\x02无法导入配置: %[1]v\x02无法列出现有隧道: %[1]v\x02另一个同名的隧道「%[1]" +
- "s」已存在\x02无法导入配置: %[1]v\x02导入隧道\x14\x01\x81\x01\x00\x00\x1a\x02导入了 %[1]d " +
- "个隧道\x14\x02\x80\x01\x000\x02导入了 %[2]d 个隧道中的 %[1]d 个隧道\x02无法创建隧道\x14" +
- "\x01\x81\x01\x00\x00\x17\x02删除 %[1]d 个隧道\x14\x01\x81\x01\x00\x00,\x02您确定" +
- "要删除这 %[1]d 个隧道吗?\x02删除隧道「%[1]s」\x02您确定要删除隧道「%[1]s」吗?\x02%[1]s此操作无法撤销。" +
- "\x02无法删除隧道\x02无法删除隧道: %[1]s\x02无法删除隧道\x14\x01\x81\x01\x00\x00 \x02无法删除 %" +
- "[1]d 个隧道。\x02配置文件 (*.zip, *.conf)|*.zip;*.conf|所有文件 (*.*)|*.*\x02从文件导入隧道" +
- "\x02配置文件 (*.zip)|*.zip\x02导出配置文件 (ZIP 压缩包)\x02%[1]s (未签名版本,禁用自动更新)\x02退出" +
- " WireGuard 时出错\x02无法停止服务: %[1]v。您可能需要在服务管理器中手动停止 WireGuard 服务。\x02发现新版 W" +
- "ireGuard。强烈建议您现在安装。\x02状态: 等待用户\x02立即更新\x02状态: 等待更新服务\x02错误: %[1]v。请重试。" +
- "\x02状态: 完成!\x02连接前\x02连接后\x02断开前\x02断开后\x02隧道 (&T)"
+ "]s 小组的桌面访问。\x02刚刚\x02系统时间倒退了!\x14\x01\x81\x01\x00\x00\x0a\x02%[1]d 年\x14" +
+ "\x01\x81\x01\x00\x00\x0a\x02%[1]d 天\x14\x01\x81\x01\x00\x00\x0d\x02%[1]d" +
+ " 小时\x14\x01\x81\x01\x00\x00\x0d\x02%[1]d 分钟\x14\x01\x81\x01\x00\x00\x0a" +
+ "\x02%[1]d 秒\x02%[1]s 前\x02%[1]d B\x02%.2[1]f\u00a0KiB\x02%.2[1]f\u00a0Mi" +
+ "B\x02%.2[1]f\u00a0GiB\x02%.2[1]f\u00a0TiB\x02%[1]s: %[2]q\x02IP地址无效\x02网" +
+ "络前缀长度无效\x02对端 (endpoint) 中缺少端口\x02对端主机名 (endpoint host) 无效\x02MTU 无效" +
+ "\x02端口无效\x02连接保活间隔无效\x02无效的密钥:%[1]v\x02数值必须介于 0 至 2^64-1 之间: %[1]v\x02一行" +
+ "中有两个逗号\x02隧道名称无效\x02[未指定]\x02每个节点都必须指定公钥\x02获取配置时出错\x02、\x02 \x02关于 Wi" +
+ "reGuard\x02WireGuard logo 图片\x02关闭\x02♥ 捐助! (&D)\x02状态:\x02断开 (&D)\x02连接" +
+ " (&A)\x02公钥:\x02监听端口:\x02MTU:\x02地址:\x02DNS 服务器:\x02预共享密钥:\x02允许的 IP:" +
+ "\x02对端:\x02连接保活间隔:\x02上次握手时间:\x02已断开\x02正在断开\x02未知\x02日志\x02复制 (&C)\x02全" +
+ "选 (&A)\x02导出… (&S)\x02时间\x02日志消息\x02导出日志\x02关于 WireGuard… (&A)\x02隧道错误" +
+ "\x02%[1]s\x0a\x0a更多信息请查看日志。\x02%[1]s (已过时)\x02退出 WireGuard 时出错\x02发现新版 W" +
+ "ireGuard。强烈建议您现在安装。\x02立即更新\x02错误: %[1]v。请重试。\x02状态: 完成!\x02WireGuard 系统" +
+ "托盘图标在30秒后没有出现。\x02方括号中应包含一个 IPv6 地址\x02解码后的密钥长度必须为32字节\x02行必须出现在段落中" +
+ "\x02配置项必须要有一个等于号\x02必须有一个值\x02[Interface] 段落中的该键无效\x02[Peer] 段落中的该键无效" +
+ "\x02接口必须有一个私钥\x02接口段落的键无效\x02协议版本必须为 1\x02节点段落的键无效\x02脚本:\x02流量:\x02连接前" +
+ "\x02连接后\x02断开前\x02断开后\x02已禁用(依管理策略)\x02已启用\x02接收 %[1]s, 发送 %[2]s\x02无法确认" +
+ "隧道状态\x02无法连接隧道\x02无法断开隧道连接\x02接口: %[1]s\x02节点\x02创建新隧道\x02编辑隧道\x02名称 (" +
+ "&N):\x02公钥 (&P):\x02(未知)\x02拦截未经隧道的流量 (kill-switch) (&B)\x02保存 (&S)\x02取" +
+ "消\x02配置 (&C):\x02名称无效\x02必须输入名称。\x02隧道名「%[1]s」无效。\x02无法列出现有隧道\x02隧道已存在" +
+ "\x02隧道名「%[1]s」已存在。\x02无法创建新的配置\x02写入文件失败\x02文件「%[1]s」已存在。\x0a\x0a您确定要覆盖它" +
+ "吗?\x02已连接\x02正在连接\x02文本文件 (*.txt)|*.txt|所有文件 (*.*)|*.*\x02WireGuard 检测" +
+ "错误\x02无法等待 WireGuard 窗口出现: %[1]v\x02WireGuard: 已断开\x02状态: 未知\x02地址: 无" +
+ "\x02管理隧道… (&M)\x02从文件导入隧道… (&I)\x02退出 (&E)\x02隧道 (&T)\x02WireGuard 已连接" +
+ "\x02隧道「%[1]s」已连接。\x02WireGuard 已断开\x02隧道「%[1]s」已断开连接。\x02WireGuard 隧道错误" +
+ "\x02WireGuard: %[1]s\x02状态: %[1]s\x02地址: %[1]s\x02发现更新!\x02WireGuard 更新" +
+ "\x02新的 WireGuard 版本发布了。强烈建议您现在安装。\x02隧道\x02编辑 (&E)\x02新建空隧道… (&E)\x02新建隧" +
+ "道\x02删除所选隧道\x02导出所有隧道 (ZIP 压缩包)\x02切换连接状态 (&T)\x02导出所有隧道 (ZIP 压缩包)… (&" +
+ "Z)\x02编辑所选隧道… (&E)\x02删除所选隧道 (&R)\x02未找到配置文件\x02无法导入配置: %[1]v\x02无法列出现有隧" +
+ "道: %[1]v\x02另一个同名的隧道「%[1]s」已存在\x02无法导入配置: %[1]v\x02导入隧道\x14\x01\x81" +
+ "\x01\x00\x00\x1a\x02导入了 %[1]d 个隧道\x14\x02\x80\x01\x000\x02导入了 %[2]d 个隧道中" +
+ "的 %[1]d 个隧道\x02无法创建隧道\x14\x01\x81\x01\x00\x00\x17\x02删除 %[1]d 个隧道\x14" +
+ "\x01\x81\x01\x00\x00,\x02您确定要删除这 %[1]d 个隧道吗?\x02删除隧道「%[1]s」\x02您确定要删除隧道「" +
+ "%[1]s」吗?\x02%[1]s此操作无法撤销。\x02无法删除隧道\x02无法删除隧道: %[1]s\x02无法删除隧道\x14\x01" +
+ "\x81\x01\x00\x00 \x02无法删除 %[1]d 个隧道。\x02配置文件 (*.zip, *.conf)|*.zip;*.con" +
+ "f|所有文件 (*.*)|*.*\x02从文件导入隧道\x02配置文件 (*.zip)|*.zip\x02导出配置文件 (ZIP 压缩包)" +
+ "\x02%[1]s (未签名版本,禁用自动更新)\x02无法停止服务: %[1]v。您可能需要在服务管理器中手动停止 WireGuard 服务。" +
+ "\x02状态: 等待用户\x02状态: 等待更新服务"
-var zh_TWIndex = []uint32{ // 181 elements
+var zh_TWIndex = []uint32{ // 278 elements
// Entry 0 - 1F
0x00000000, 0x00000007, 0x00000037, 0x00000056,
- 0x00000066, 0x000000a4, 0x000000a4, 0x000000d5,
- 0x00000118, 0x0000017d, 0x000001b9, 0x000001c6,
- 0x000001df, 0x000001f0, 0x00000201, 0x00000215,
- 0x00000229, 0x0000023a, 0x00000244, 0x0000024d,
- 0x0000025a, 0x00000267, 0x00000274, 0x00000281,
- 0x00000290, 0x000002a4, 0x000002c6, 0x000002e5,
- 0x000002ff, 0x00000327, 0x00000335, 0x00000345,
+ 0x00000066, 0x000000a4, 0x000000df, 0x00000110,
+ 0x00000153, 0x000001b8, 0x000001c5, 0x000001de,
+ 0x000001ef, 0x00000200, 0x00000214, 0x00000228,
+ 0x00000239, 0x00000243, 0x0000024c, 0x00000259,
+ 0x00000266, 0x00000273, 0x00000280, 0x0000028f,
+ 0x000002a3, 0x000002c5, 0x000002e4, 0x000002fe,
+ 0x0000030c, 0x0000031c, 0x00000342, 0x0000035b,
// Entry 20 - 3F
- 0x0000036b, 0x00000384, 0x000003a3, 0x000003cc,
- 0x000003e5, 0x000003f8, 0x00000414, 0x0000043c,
- 0x00000452, 0x00000471, 0x0000048b, 0x000004b1,
- 0x000004bd, 0x000004df, 0x000004fb, 0x00000518,
- 0x00000530, 0x00000548, 0x0000054c, 0x0000054e,
- 0x0000055f, 0x00000575, 0x00000575, 0x0000057c,
- 0x0000058f, 0x00000596, 0x000005a8, 0x000005b4,
- 0x000005bb, 0x000005c5, 0x000005c9, 0x000005d0,
+ 0x00000384, 0x0000039d, 0x000003b0, 0x000003bc,
+ 0x000003de, 0x000003fa, 0x000003fe, 0x00000400,
+ 0x00000411, 0x00000427, 0x0000042e, 0x00000441,
+ 0x00000448, 0x0000045a, 0x00000466, 0x0000046d,
+ 0x00000477, 0x0000047b, 0x00000482, 0x00000490,
+ 0x000004a0, 0x000004b0, 0x000004ba, 0x000004cb,
+ 0x000004de, 0x000004ee, 0x000004fe, 0x00000505,
+ 0x0000050c, 0x00000518, 0x00000524, 0x00000533,
// Entry 40 - 5F
- 0x000005de, 0x000005de, 0x000005ee, 0x000005fe,
- 0x00000608, 0x00000619, 0x0000062c, 0x00000633,
- 0x00000633, 0x0000063d, 0x0000065f, 0x00000678,
- 0x0000068b, 0x000006a4, 0x000006b3, 0x000006ba,
- 0x000006ca, 0x000006dd, 0x000006e9, 0x000006f5,
- 0x000006fe, 0x00000733, 0x00000733, 0x0000073f,
- 0x00000746, 0x00000752, 0x00000762, 0x00000778,
- 0x0000079c, 0x000007b5, 0x000007c5, 0x000007e6,
+ 0x0000053a, 0x00000547, 0x00000557, 0x0000056d,
+ 0x0000057a, 0x000005a9, 0x000005be, 0x000005d6,
+ 0x0000062b, 0x00000638, 0x0000065d, 0x00000673,
+ 0x000006af, 0x000006d7, 0x000006f6, 0x00000712,
+ 0x0000073a, 0x00000750, 0x0000076f, 0x00000789,
+ 0x000007af, 0x000007cc, 0x000007e4, 0x000007fc,
+ 0x00000809, 0x00000810, 0x0000081a, 0x00000824,
+ 0x0000082e, 0x00000838, 0x00000850, 0x0000085a,
// Entry 60 - 7F
- 0x00000805, 0x00000818, 0x0000084b, 0x00000855,
- 0x00000865, 0x00000875, 0x00000885, 0x0000088c,
- 0x00000893, 0x0000089f, 0x000008ab, 0x000008ba,
- 0x000008c1, 0x000008ce, 0x000008fd, 0x0000090d,
- 0x00000923, 0x00000930, 0x0000095f, 0x00000974,
- 0x0000098c, 0x000009b9, 0x000009cf, 0x000009df,
- 0x000009ec, 0x000009fe, 0x00000a16, 0x00000a22,
- 0x00000a36, 0x00000a51, 0x00000a6b, 0x00000a8f,
+ 0x0000087c, 0x00000895, 0x000008a8, 0x000008c1,
+ 0x000008d0, 0x000008d7, 0x000008e7, 0x000008fa,
+ 0x00000906, 0x00000912, 0x0000091b, 0x00000950,
+ 0x0000095c, 0x00000963, 0x0000096f, 0x0000097f,
+ 0x00000995, 0x000009b9, 0x000009d2, 0x000009e2,
+ 0x00000a03, 0x00000a22, 0x00000a35, 0x00000a68,
+ 0x00000a72, 0x00000a82, 0x00000ab1, 0x00000ac9,
+ 0x00000af6, 0x00000b0c, 0x00000b1c, 0x00000b29,
// Entry 80 - 9F
- 0x00000aa6, 0x00000ab8, 0x00000ac7, 0x00000ac7,
- 0x00000ace, 0x00000adf, 0x00000b38, 0x00000b3f,
- 0x00000b4b, 0x00000b63, 0x00000b70, 0x00000b83,
- 0x00000ba6, 0x00000bbe, 0x00000be3, 0x00000bfb,
- 0x00000c16, 0x00000c16, 0x00000c32, 0x00000c4e,
- 0x00000c78, 0x00000c94, 0x00000ca4, 0x00000cc5,
- 0x00000cf8, 0x00000d0b, 0x00000d29, 0x00000d59,
- 0x00000d6e, 0x00000d98, 0x00000dbe, 0x00000dd1,
+ 0x00000b3b, 0x00000b53, 0x00000b5f, 0x00000b5f,
+ 0x00000b73, 0x00000b8e, 0x00000ba8, 0x00000bcc,
+ 0x00000be3, 0x00000bf5, 0x00000c04, 0x00000c12,
+ 0x00000c19, 0x00000c2a, 0x00000c83, 0x00000c8a,
+ 0x00000c96, 0x00000cae, 0x00000cbb, 0x00000cce,
+ 0x00000cf1, 0x00000d09, 0x00000d2e, 0x00000d46,
+ 0x00000d61, 0x00000d74, 0x00000d90, 0x00000dac,
+ 0x00000dd6, 0x00000df2, 0x00000e02, 0x00000e23,
// Entry A0 - BF
- 0x00000ded, 0x00000e00, 0x00000e24, 0x00000e68,
- 0x00000e84, 0x00000ea2, 0x00000ebb, 0x00000ef1,
- 0x00000f09, 0x00000f6a, 0x00000fbf, 0x00000fd8,
- 0x00000fe5, 0x00001001, 0x00001026, 0x0000103c,
- 0x0000103c, 0x0000103c, 0x0000103c, 0x0000103c,
- 0x0000103c,
-} // Size: 748 bytes
+ 0x00000e56, 0x00000e69, 0x00000e87, 0x00000eb7,
+ 0x00000ecc, 0x00000ef6, 0x00000f1c, 0x00000f2f,
+ 0x00000f4b, 0x00000f5e, 0x00000f82, 0x00000fc6,
+ 0x00000fe2, 0x00001000, 0x00001019, 0x0000104f,
+ 0x000010b0, 0x000010c9, 0x000010e5, 0x000010e5,
+ 0x000010e5, 0x000010e5, 0x000010e5, 0x000010e5,
+ 0x000010e5, 0x000010e5, 0x000010e5, 0x000010e5,
+ 0x000010e5, 0x000010e5, 0x000010e5, 0x000010e5,
+ // Entry C0 - DF
+ 0x000010e5, 0x000010e5, 0x000010e5, 0x000010e5,
+ 0x000010e5, 0x000010e5, 0x000010e5, 0x000010e5,
+ 0x000010e5, 0x000010e5, 0x000010e5, 0x000010e5,
+ 0x000010e5, 0x000010e5, 0x000010e5, 0x000010e5,
+ 0x000010e5, 0x000010e5, 0x000010e5, 0x000010e5,
+ 0x000010e5, 0x000010e5, 0x000010e5, 0x000010e5,
+ 0x000010e5, 0x000010e5, 0x000010e5, 0x000010e5,
+ 0x000010e5, 0x000010e5, 0x000010e5, 0x000010e5,
+ // Entry E0 - FF
+ 0x000010e5, 0x000010e5, 0x000010e5, 0x000010e5,
+ 0x000010e5, 0x000010e5, 0x000010e5, 0x000010e5,
+ 0x000010e5, 0x000010e5, 0x000010e5, 0x000010e5,
+ 0x000010e5, 0x000010e5, 0x000010e5, 0x000010e5,
+ 0x000010e5, 0x000010e5, 0x000010e5, 0x000010e5,
+ 0x000010e5, 0x000010e5, 0x000010e5, 0x000010e5,
+ 0x000010e5, 0x000010e5, 0x000010e5, 0x000010e5,
+ 0x000010e5, 0x000010e5, 0x000010e5, 0x000010e5,
+ // Entry 100 - 11F
+ 0x000010e5, 0x000010e5, 0x000010e5, 0x000010e5,
+ 0x000010e5, 0x000010e5, 0x000010e5, 0x000010e5,
+ 0x000010e5, 0x000010e5, 0x000010e5, 0x000010e5,
+ 0x000010e5, 0x000010e5, 0x000010e5, 0x000010e5,
+ 0x000010e5, 0x000010e5, 0x000010e5, 0x000010e5,
+ 0x000010e5, 0x000010e5,
+} // Size: 1136 bytes
-const zh_TWData string = "" + // Size: 4156 bytes
+const zh_TWData string = "" + // Size: 4325 bytes
"\x02錯誤\x02(無參數):提升權限並安裝管理服務\x02使用方法: %[1]s [\x0a%[2]s]\x02命令列選項\x02無法確定該" +
- "處理程序是否在 WOW64 下執行: %[1]v\x02無法開啓目前處理程序的權杖: %[1]v\x02WireGuard 可能只能被內建的" +
- "「%[1]s」群組成員使用。\x02WireGuard 正在執行,但 UI 只能從內建的內建的「%[1]s」群組成員的桌面存取。\x02Wi" +
- "reGuard 的工作列圖示在 30 秒後並沒有顯示。\x02就是現在\x02系統時鐘倒退了!\x14\x01\x81\x01\x00\x00" +
+ "處理程序是否在 WOW64 下執行: %[1]v\x02您必須在此電腦上執行原生版本的 WireGuard。\x02無法開啓目前處理程序的權" +
+ "杖: %[1]v\x02WireGuard 可能只能被內建的「%[1]s」群組成員使用。\x02WireGuard 正在執行,但 UI 只能" +
+ "從內建的內建的「%[1]s」群組成員的桌面存取。\x02就是現在\x02系統時鐘倒退了!\x14\x01\x81\x01\x00\x00" +
"\x0a\x02%[1]d 年\x14\x01\x81\x01\x00\x00\x0a\x02%[1]d 天\x14\x01\x81\x01" +
"\x00\x00\x0d\x02%[1]d 小時\x14\x01\x81\x01\x00\x00\x0d\x02%[1]d 分鐘\x14\x01" +
"\x81\x01\x00\x00\x0a\x02%[1]d 秒\x02%[1]s 前\x02%[1]d\u00a0B\x02%.2[1]f" +
"\u00a0KiB\x02%.2[1]f\u00a0MiB\x02%.2[1]f\u00a0GiB\x02%.2[1]f\u00a0TiB" +
"\x02%[1]s: %[2]q\x02無效的 IP 位址\x02無效的網路位址首碼長度\x02Endpoint 中沒有指定埠號\x02無效的 " +
- "Endpoint 位址\x02括號中必須包含一個 IPv6 位址\x02無效的 MTU\x02無效的埠號\x02無效的 Persistent K" +
- "eepalive 設定\x02無效的金鑰: %[1]v\x02金鑰必須剛好長 32 bytes\x02數值必須介於 0 到 2^64-1: %[" +
- "1]v\x02一行中有兩個逗號\x02隧道名稱無效\x02行必須出現在段落中\x02設定的項目必須要有一個等號\x02必須要有一個值\x02[I" +
- "nterface] 中有無效選項\x02[Peer] 中有無效選項\x02Interface 中必須要有一把私鑰\x02[未指定]\x02每個 " +
- "Peer 都必須要有公鑰\x02讀取設定時發生錯誤\x02Interface 中的金鑰無效\x02協定版本必須為 1\x02Peer 中的金鑰無" +
- "效\x02、\x02 \x02關於 WireGuard\x02WireGuard logo 圖片\x02關閉\x02♥ 捐贈! (&D)" +
- "\x02狀態\x02中斷連線 (&D)\x02連線 (&A)\x02公鑰\x02監聽埠\x02MTU\x02位址\x02DNS 伺服器\x02預" +
- "交換金鑰\x02允許的位址\x02連接點\x02Keepalive 間隔\x02最後交握時間\x02流量\x02已啓用\x02已收到 %[1" +
- "]s;已傳送 %[2]s\x02無法確認隧道狀態\x02無法連接隧道\x02無法斷開隧道連線\x02[隧道] %[1]s\x02節點\x02建立" +
- "新隧道\x02編輯隧道設定\x02名稱 (&N)\x02公鑰 (&P)\x02(未知)\x02阻斷未經過隧道的流量(kill-switch)" +
- " (&B)\x02儲存 (&S)\x02取消\x02設定 (&C)\x02無效的名稱\x02必須填寫名稱。\x02無效的隧道名稱「%[1]s」。" +
- "\x02無法列出現有隧道\x02隧道已存在\x02已有同名隧道「%[1]s」。\x02無法建立新的隧道設定\x02檔案寫入失敗\x02檔案已存在" +
- ": %[1]s\x0a\x0a您確定要覆蓋嗎?\x02已連線\x02正在連線…\x02已中斷連線\x02正在中斷…\x02未知\x02日誌" +
- "\x02複製 (&C)\x02全選 (&A)\x02匯出… (&S)\x02時間\x02日誌訊息\x02純文字 (*.txt)|*.txt|所有" +
- "檔案 (*.*)|*.*\x02匯出日誌…\x02關於 WireGuard (&A)\x02隧道錯誤\x02%[1]s\x0a\x0a如需更" +
- "多資訊,請查看日誌。\x02%[1]s(已過時)\x02偵測 WireGuard 錯誤\x02無法等待 WireGuard 視窗開啓: %[" +
- "1]v\x02WireGuard - 未連線\x02[狀態] 未知\x02[位址] 無\x02管理隧道 (&M)\x02從檔案匯入… (&I)" +
- "\x02離開 (&X)\x02WireGuard 已連線\x02已連線至隧道 - %[1]s\x02WireGuard 已中斷連線\x02已中斷" +
- "與隧道的連線 - %[1]s\x02WireGuard 隧道錯誤\x02WireGuard - %[1]s\x02[狀態] %[1]s" +
- "\x02更新\x02WireGuard 更新\x02更新的 WireGuard 已經為您準備好了。\x0a強烈建議您立即更新 WireGuard" +
- "。\x02隧道\x02編輯 (&E)\x02新增隧道精靈 (&E)\x02新增隧道\x02刪除選取隧道\x02匯出所有隧道(ZIP 格式)" +
- "\x02切換連線狀態 (&T)\x02匯出所有隧道至 &ZIP 壓縮檔\x02編輯選取隧道 (&S)\x02刪除已選取隧道 (&R)\x02無法" +
- "匯入設定: %[1]v\x02無法列出隧道: %[1]v\x02已有另一個同名的隧道「%[1]s」\x02無法匯入設定: %[1]v\x02" +
- "已匯入隧道\x14\x01\x81\x01\x00\x00\x1a\x02已匯入 %[1]d 個隧道\x14\x02\x80\x01\x00" +
- "-\x02已匯入 %[1]d 個隧道(共 %[2]d 個)\x02無法建立隧道\x14\x01\x81\x01\x00\x00\x17\x02刪" +
- "除 %[1]d 個隧道\x14\x01\x81\x01\x00\x00)\x02您確定要刪除 %[1]d 個隧道嗎?\x02刪除隧道 - %" +
- "[1]s\x02您確定要刪除隧道「%[1]s」嗎?\x02%[1]s\x0a\x0a您將無法復原此操作。\x02無法刪除隧道\x02無法刪除隧道" +
- ": %[1]s\x02無法刪除隧道\x14\x01\x81\x01\x00\x00\x1d\x02無法刪除 %[1]d 個隧道\x02隧道設" +
- "定檔 (*.zip, *.conf)|*.zip;*.conf|所有檔案 (*.*)|*.*\x02從檔案中匯入隧道…\x02隧道設定檔 (" +
- "*.zip)|*.zip\x02匯出隧道設定至…\x02%[1]s(未簽署發行版本,無法自動更新)\x02離開 WireGuard 失敗\x02" +
- "無法結束服務: %[1]v。\x0a您可能需要手動從服務管理中結束 WireGuard 服務。\x02更新的 WireGuard 已經為您準" +
- "備好了。\x0a強烈建議您立即進行更新。\x02狀態:等待使用者\x02立即更新\x02狀態:等待更新服務\x02錯誤: %[1]v。請稍後" +
- "再試。\x02狀態:已完成!"
+ "Endpoint 位址\x02無效的 MTU\x02無效的埠號\x02無效的 Persistent Keepalive 設定\x02無效的金鑰:" +
+ " %[1]v\x02數值必須介於 0 到 2^64-1: %[1]v\x02一行中有兩個逗號\x02隧道名稱無效\x02[未指定]\x02每個 " +
+ "Peer 都必須要有公鑰\x02讀取設定時發生錯誤\x02、\x02 \x02關於 WireGuard\x02WireGuard logo 圖片" +
+ "\x02關閉\x02♥ 捐贈! (&D)\x02狀態\x02中斷連線 (&D)\x02連線 (&A)\x02公鑰\x02監聽埠\x02MTU" +
+ "\x02位址\x02DNS 伺服器\x02預交換金鑰\x02允許的位址\x02連接點\x02Keepalive 間隔\x02最後交握時間\x02" +
+ "已中斷連線\x02正在中斷…\x02未知\x02日誌\x02複製 (&C)\x02全選 (&A)\x02匯出… (&S)\x02時間\x02" +
+ "日誌訊息\x02匯出日誌…\x02關於 WireGuard (&A)\x02隧道錯誤\x02%[1]s\x0a\x0a如需更多資訊,請查看日" +
+ "誌。\x02%[1]s(已過時)\x02離開 WireGuard 失敗\x02更新的 WireGuard 已經為您準備好了。\x0a強烈建議" +
+ "您立即進行更新。\x02立即更新\x02錯誤: %[1]v。請稍後再試。\x02狀態:已完成!\x02WireGuard 的工作列圖示在 3" +
+ "0 秒後並沒有顯示。\x02括號中必須包含一個 IPv6 位址\x02金鑰必須剛好長 32 bytes\x02行必須出現在段落中\x02設定的項" +
+ "目必須要有一個等號\x02必須要有一個值\x02[Interface] 中有無效選項\x02[Peer] 中有無效選項\x02Interfa" +
+ "ce 中必須要有一把私鑰\x02Interface 中的金鑰無效\x02協定版本必須為 1\x02Peer 中的金鑰無效\x02指令碼:\x02" +
+ "流量\x02連接前\x02連接後\x02斷線前\x02斷線後\x02已關閉, 隨著策略\x02已啓用\x02已收到 %[1]s;已傳送 %[" +
+ "2]s\x02無法確認隧道狀態\x02無法連接隧道\x02無法斷開隧道連線\x02[隧道] %[1]s\x02節點\x02建立新隧道\x02編輯" +
+ "隧道設定\x02名稱 (&N)\x02公鑰 (&P)\x02(未知)\x02阻斷未經過隧道的流量(kill-switch) (&B)\x02" +
+ "儲存 (&S)\x02取消\x02設定 (&C)\x02無效的名稱\x02必須填寫名稱。\x02無效的隧道名稱「%[1]s」。\x02無法列" +
+ "出現有隧道\x02隧道已存在\x02已有同名隧道「%[1]s」。\x02無法建立新的隧道設定\x02檔案寫入失敗\x02檔案已存在: %[1" +
+ "]s\x0a\x0a您確定要覆蓋嗎?\x02已連線\x02正在連線…\x02純文字 (*.txt)|*.txt|所有檔案 (*.*)|*.*" +
+ "\x02偵測 WireGuard 錯誤\x02無法等待 WireGuard 視窗開啓: %[1]v\x02WireGuard - 未連線\x02" +
+ "[狀態] 未知\x02[位址] 無\x02管理隧道 (&M)\x02從檔案匯入… (&I)\x02離開 (&X)\x02WireGuard 已連" +
+ "線\x02已連線至隧道 - %[1]s\x02WireGuard 已中斷連線\x02已中斷與隧道的連線 - %[1]s\x02WireGua" +
+ "rd 隧道錯誤\x02WireGuard - %[1]s\x02[狀態] %[1]s\x02位址: %[1]s\x02更新\x02WireGua" +
+ "rd 更新\x02更新的 WireGuard 已經為您準備好了。\x0a強烈建議您立即更新 WireGuard。\x02隧道\x02編輯 (&E" +
+ ")\x02新增隧道精靈 (&E)\x02新增隧道\x02刪除選取隧道\x02匯出所有隧道(ZIP 格式)\x02切換連線狀態 (&T)\x02匯" +
+ "出所有隧道至 &ZIP 壓縮檔\x02編輯選取隧道 (&S)\x02刪除已選取隧道 (&R)\x02找不到設定檔\x02無法匯入設定: %[" +
+ "1]v\x02無法列出隧道: %[1]v\x02已有另一個同名的隧道「%[1]s」\x02無法匯入設定: %[1]v\x02已匯入隧道\x14" +
+ "\x01\x81\x01\x00\x00\x1a\x02已匯入 %[1]d 個隧道\x14\x02\x80\x01\x00-\x02已匯入 %[" +
+ "1]d 個隧道(共 %[2]d 個)\x02無法建立隧道\x14\x01\x81\x01\x00\x00\x17\x02刪除 %[1]d 個隧道" +
+ "\x14\x01\x81\x01\x00\x00)\x02您確定要刪除 %[1]d 個隧道嗎?\x02刪除隧道 - %[1]s\x02您確定要刪" +
+ "除隧道「%[1]s」嗎?\x02%[1]s\x0a\x0a您將無法復原此操作。\x02無法刪除隧道\x02無法刪除隧道: %[1]s\x02" +
+ "無法刪除隧道\x14\x01\x81\x01\x00\x00\x1d\x02無法刪除 %[1]d 個隧道\x02隧道設定檔 (*.zip, " +
+ "*.conf)|*.zip;*.conf|所有檔案 (*.*)|*.*\x02從檔案中匯入隧道…\x02隧道設定檔 (*.zip)|*.zip" +
+ "\x02匯出隧道設定至…\x02%[1]s(未簽署發行版本,無法自動更新)\x02無法結束服務: %[1]v。\x0a您可能需要手動從服務管理中" +
+ "結束 WireGuard 服務。\x02狀態:等待使用者\x02狀態:等待更新服務"
- // Total table size 99186 bytes (96KiB); checksum: FBC08C97
+ // Total table size 139447 bytes (136KiB); checksum: 43780019