Compare commits

...

72 Commits

Author SHA1 Message Date
226166bdaf Version bump
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2019-10-12 22:20:37 +02:00
80fa72cabc iOS: UI: abort is optimized out in release builds
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2019-10-12 22:20:37 +02:00
d976d159d0 Keychain: make verification errors only happen when we're sure it's due to not found
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2019-10-11 22:07:18 +02:00
84ca7fcf40 ui: add donation link
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2019-10-11 21:44:12 +02:00
f120a6aab0 wireguard-go-bridge: reduce version checks and cleanup
We now rely on -trimpath which restricts us to >= 1.13, and the patch
application should fail too. This has the downside that the user will
need to clean their xcode project when they upgrade go, though.

Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2019-10-08 16:59:02 +02:00
0d8108d8da wireguard-go-bridge: update for 1.13
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2019-10-04 18:28:53 +02:00
e072ebee58 UI: iOS: set CFBundleDisplayName to satisfy new ITMS-90783 error
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2019-06-28 14:42:43 +02:00
c6767d9007 Version bump
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2019-06-28 13:51:32 +02:00
bb5760cca4 WgQuickConfig: Swift treats \r\n as a single character
let blah = "hello\nworld\ndoes\nthis\nwork"
print(blah.split(separator: "\n"))
//output: ["hello", "world", "does", "this", "work"]

let blah2 = "hello\r\nworld\r\ndoes\r\nthis\r\nwork"
print(blah2.split(separator: "\n"))
//output: ["hello\r\nworld\r\ndoes\r\nthis\r\nwork"]
//expected: ["hello\r", "world\r", "does\r", "this\r", "work\r"]

In blah2, the string splitting fails because swift considers \r\n to be
its own character.

Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2019-06-28 12:26:39 +02:00
26b7971ba6 UI: macOS: Show useful error message on .conf import
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2019-06-28 12:07:18 +02:00
b286ede3c6 iOS: Importing: If tunnelsManager isn't ready yet, we should wait for it
Signed-off-by: Roopesh Chander <roop@roopc.net>
2019-06-13 23:02:54 +05:30
4ef7afe3ca macOS: Tunnel detail: Handle deletion outside app, again
This was previously done in commit f281b93, but the changes in commit
1507a97 for handling deletion of multiple tunnels undid this capability.

Signed-off-by: Roopesh Chander <roop@roopc.net>
2019-06-13 22:21:31 +05:30
377f2f0496 TunnelsManager: store UID on macOS for keychain availability
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2019-06-11 02:18:42 +02:00
7ed5893fc6 Version bump
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2019-06-10 18:58:18 +02:00
e70c397e54 TunnelProvider: remove all cleverness
This will cause more socket flaps than necessary but hopefully will fix
some bugs.

Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2019-06-10 18:47:39 +02:00
6a6be9edde on-demand: iOS: Fix crash on selecting Any SSID when already selected
Signed-off-by: Roopesh Chander <roop@roopc.net>
2019-06-09 23:55:44 +05:30
37f8500fe6 on-demand: Don't crash on encountering unexpected on-demand rules
Signed-off-by: Roopesh Chander <roop@roopc.net>
2019-06-09 23:55:39 +05:30
207f82dd9d macOS: Remove unused strings
Signed-off-by: Roopesh Chander <roop@roopc.net>
2019-06-09 11:39:06 +02:00
de8fedf87a Version bump
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2019-06-09 11:39:06 +02:00
98d306da5b macOS: remove store update escape hatch
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2019-06-09 11:39:06 +02:00
c7b7b1247b TunnelProvider: store the entire NWPath
Otherwise [utun0, en0] == [en0, utun0] before WiFi has connected, and we
wind up not rebinding after WiFi does successfully connect, which means
people have trouble when resuming from sleep.

Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2019-06-09 11:39:06 +02:00
a66f13eb01 README: update repo location
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2019-06-09 11:39:06 +02:00
f50e7ae686 Version bump
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2019-06-06 10:27:39 +02:00
4d6692548c macOS: App menu > Quit shall show a prompt to quit or close window
Signed-off-by: Roopesh Chander <roop@roopc.net>
2019-06-06 10:27:11 +02:00
1dccd39818 macOS: Save/restore the log window's size
Signed-off-by: Roopesh Chander <roop@roopc.net>
2019-06-04 20:34:37 +05:30
4cb775c72f macOS: Log view: Allow resizing horizontally
Signed-off-by: Roopesh Chander <roop@roopc.net>
2019-06-04 15:48:42 +05:30
4cb783c447 go-bridge: bump version
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2019-05-31 19:20:51 +02:00
d20daa345a Version bump
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2019-05-31 17:30:06 +02:00
168ba2da8a NetworkExtension: bump sockets on path change
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2019-05-31 17:29:29 +02:00
714d6a41bd macOS: Dismiss modals correctly
Previously, the presented vc were leaking when discarding edits
or when closing the log view controller.

Signed-off-by: Roopesh Chander <roop@roopc.net>
2019-05-31 17:29:29 +02:00
9b92a8f933 macOS: Update app icon
Reduce the size and add a drop shadow

Signed-off-by: Roopesh Chander <roop@roopc.net>
2019-05-31 17:29:29 +02:00
5e9780ef8f iOS: Should be able to re-show tunnel detail
Fixes a bug introduced in the refactoring in
commit 7322fb084087774e8b58e347902f6d7036cbde5c

Signed-off-by: Roopesh Chander <roop@roopc.net>
2019-05-27 15:36:39 +05:30
9faf814e8b macOS: Tunnel detail: No need to update runtime info on tunnelSaved()
Signed-off-by: Roopesh Chander <roop@roopc.net>
2019-05-27 14:43:41 +05:30
30da10a0e9 macOS: Start refreshing runtime info in viewWillAppear(), not init()
Because when the window is closed and reopened, we should start
refreshing runtime info again.

Signed-off-by: Roopesh Chander <roop@roopc.net>
2019-05-27 14:38:17 +05:30
a18614d6b3 macOS: Fix residual menu highlight on reopen
If we close the window with Cmd+W or Cmd+Q and then re-launch the app,
the main menu shows residual highlight from the close action. This
commit fixes that.

Signed-off-by: Roopesh Chander <roop@roopc.net>
2019-05-26 00:12:47 +05:30
5100e597aa macOS: do not call out to recent tunnels tracker
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2019-05-26 00:12:47 +05:30
0340641c4c NetworkExtension: apparently the extension process is scoped properly anyway
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2019-05-26 00:12:47 +05:30
813dea6902 NetworkExtension: use excludedRoutes instead of binding on iOS
The networking stack there is to flaky and the notifier doesn't always
fire correctly. Hopefully excludedRoutes works well with XLAT; otherwise
we're in trouble.

Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2019-05-26 00:12:47 +05:30
c30d491edc iOS: Should be able to call showTunnelDetail multiple times
And the detail views should not stack up.

Signed-off-by: Roopesh Chander <roop@roopc.net>
2019-05-26 00:12:42 +05:30
88c80d6694 iOS: Refactor showing of the tunnel detail
Signed-off-by: Roopesh Chander <roop@roopc.net>
2019-05-25 13:24:01 +02:00
393718dfaf iOS: Show Home screen quick actions for recent tunnels
Signed-off-by: Roopesh Chander <roop@roopc.net>
2019-05-25 13:24:01 +02:00
f852b6f919 iOS: Keep track of most-recently-activated tunnels
Signed-off-by: Roopesh Chander <roop@roopc.net>
2019-05-25 13:24:01 +02:00
8926434682 macOS: Workaround for unresponsive main menu when launched from Xcode
Signed-off-by: Roopesh Chander <roop@roopc.net>
2019-05-22 19:52:21 +05:30
493c7b102e macOS: Ignore bogus reopen because of login item helper
The bogus reopen occurs because the SMLoginItemSetEnabled actually runs
the helper app immediately. The helper app attempts to launch the main
app, causing a reopen Apple event (rapp) to be sent.

Signed-off-by: Roopesh Chander <roop@roopc.net>
2019-05-22 19:52:21 +05:30
717bc8a26f macOS: Workaround for unresponsive main menu after reopen
Signed-off-by: Roopesh Chander <roop@roopc.net>
2019-05-22 19:52:12 +05:30
e582155a10 macOS: Ensure window is shown on app reopening
Signed-off-by: Roopesh Chander <roop@roopc.net>
2019-05-22 15:19:57 +05:30
70d19691a7 macOS: Simplify detecting the type of an Apple event
Signed-off-by: Roopesh Chander <roop@roopc.net>
2019-05-20 16:42:28 +05:30
40b1f0bac8 macOS: Don't show manage window when launched at login
Signed-off-by: Roopesh Chander <roop@roopc.net>
2019-05-20 16:42:28 +05:30
52ac9b82c2 macOS: Login item: Get helper app version from xcconfig
Signed-off-by: Roopesh Chander <roop@roopc.net>
2019-05-20 16:42:27 +05:30
fc1fdbbcdb macOS: Login item: Fix Info.plist path
Signed-off-by: Roopesh Chander <roop@roopc.net>
2019-05-20 16:42:27 +05:30
300268daa0 macOS: Show Manage Tunnels window on startup
Signed-off-by: Roopesh Chander <roop@roopc.net>
2019-05-20 16:42:27 +05:30
9bf304a9ac macOS: Minor refactor of StatusMenuWindowDelegate
Signed-off-by: Roopesh Chander <roop@roopc.net>
2019-05-20 16:42:27 +05:30
586a592b68 macOS: Disable 'Delete Selected' when nothing is selected
Signed-off-by: Roopesh Chander <roop@roopc.net>
2019-05-20 16:42:27 +05:30
c0526d2efb macOS: Some menu item titles are automatically inferred
Signed-off-by: Roopesh Chander <roop@roopc.net>
2019-05-20 16:42:27 +05:30
fdbd4f875e macOS: Use title-style capitalization for menu items
As per https://developer.apple.com/design/human-interface-guidelines/macos/menus/menu-anatomy/

Signed-off-by: Roopesh Chander <roop@roopc.net>
2019-05-20 16:42:27 +05:30
4a037cc706 macOS: Make it clear that status menu Quit quits the app
Signed-off-by: Roopesh Chander <roop@roopc.net>
2019-05-20 16:42:27 +05:30
5190fc2249 macOS: Quit in main menu shall just close the window
Signed-off-by: Roopesh Chander <roop@roopc.net>
2019-05-20 16:42:27 +05:30
3f25d54dcc macOS: Get back removing tunnel using the Delete key
This now works only when the list view has focus

Signed-off-by: Roopesh Chander <roop@roopc.net>
2019-05-20 16:42:27 +05:30
f9880907a2 macOS: Both list and detail main menu items should be always enabled
Signed-off-by: Roopesh Chander <roop@roopc.net>
2019-05-20 16:42:27 +05:30
404fa741e8 macOS: swiftlint: Suppress incorrect warnings
Signed-off-by: Roopesh Chander <roop@roopc.net>
2019-05-20 16:42:27 +05:30
6e1f03e41c macOS: Set a main menu for the app
The main menu would be shown only when the manage tunnels window
is visible.

Signed-off-by: Roopesh Chander <roop@roopc.net>
2019-05-20 16:42:27 +05:30
6d8965e97d macOS: Remove custom key event handling
Signed-off-by: Roopesh Chander <roop@roopc.net>
2019-05-20 16:42:27 +05:30
5e5481b69b macOS: Show app in dock when showing the manage tunnels window
This way, the app can participate in Cmd+Tab

Signed-off-by: Roopesh Chander <roop@roopc.net>
2019-05-20 16:42:27 +05:30
69b33c0fad macOS: Edit view: Save on Cmd+S
Signed-off-by: Roopesh Chander <roop@roopc.net>
2019-05-12 15:45:26 +05:30
167e4f0bf2 macOS: Edit view: Dismiss on Esc
Signed-off-by: Roopesh Chander <roop@roopc.net>
2019-05-12 13:23:52 +05:30
6e3b28852a macOS: Log view: Dismiss on Esc
Signed-off-by: Roopesh Chander <roop@roopc.net>
2019-05-12 13:21:42 +05:30
5914e868ab iOS: Log view: Improve the look
Signed-off-by: Roopesh Chander <roop@roopc.net>
2019-04-28 14:29:22 +05:30
83ea9d6fa7 wireguard-go-bridge: add missing format specifier for error
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2019-04-24 13:24:03 +02:00
b954e9a4fd Version bump
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
2019-04-23 06:49:16 +02:00
76894fba68 Xcode: Use dwarf for debug and dwarf-with-dsym for release
Signed-off-by: Roopesh Chander <roop@roopc.net>
2019-04-21 18:22:31 +05:30
89a564ce62 Swift 5 migration: Make use of Result type
Signed-off-by: Roopesh Chander <roop@roopc.net>
2019-04-21 17:51:42 +05:30
178fe86d36 macOS: Detect when updating from the App Store
And show an alert when tunnels are active during updation -- that
might cause the update to not work correctly.

Signed-off-by: Roopesh Chander <roop@roopc.net>
2019-04-21 15:43:10 +05:30
57 changed files with 1016 additions and 786 deletions

View File

@ -1,12 +1,14 @@
# [WireGuard](https://www.wireguard.com/) for iOS and macOS
This project contains an application for iOS and for macOS, as well as many components shared between the two of them. You may toggle between the two platforms by selecting the target from within Xcode.
## Building
- Clone this repo recursively:
- Clone this repo:
```
$ git clone --recursive https://git.zx2c4.com/wireguard-ios
$ cd wireguard-ios
$ git clone https://git.zx2c4.com/wireguard-apple
$ cd wireguard-apple
```
- Rename and populate developer team ID file:

View File

@ -112,6 +112,6 @@ class Keychain {
static func verifyReference(called ref: Data) -> Bool {
return SecItemCopyMatching([kSecClass as String: kSecClassGenericPassword,
kSecValuePersistentRef as String: ref] as CFDictionary,
nil) == errSecSuccess
nil) != errSecItemNotFound
}
}

View File

@ -22,6 +22,9 @@ extension NETunnelProviderProtocol {
if passwordReference == nil {
return nil
}
#if os(macOS)
providerConfiguration = ["UID": getuid()]
#endif
let endpoints = tunnelConfiguration.peers.compactMap { $0.endpoint }
if endpoints.count == 1 {
@ -60,11 +63,25 @@ extension NETunnelProviderProtocol {
* in the keychain. But it's still useful to keep the migration
* around so that .mobileconfig files are easier.
*/
guard let oldConfig = providerConfiguration?["WgQuickConfig"] as? String else { return false }
providerConfiguration = nil
guard passwordReference == nil else { return true }
wg_log(.debug, message: "Migrating tunnel configuration '\(name)'")
passwordReference = Keychain.makeReference(containing: oldConfig, called: name)
return true
if let oldConfig = providerConfiguration?["WgQuickConfig"] as? String {
#if os(macOS)
providerConfiguration = ["UID": getuid()]
#elseif os(iOS)
providerConfiguration = nil
#else
#error("Unimplemented")
#endif
guard passwordReference == nil else { return true }
wg_log(.debug, message: "Migrating tunnel configuration '\(name)'")
passwordReference = Keychain.makeReference(containing: oldConfig, called: name)
return true
}
#if os(macOS)
if passwordReference != nil && providerConfiguration?["UID"] == nil && verifyConfigurationReference() {
providerConfiguration = ["UID": getuid()]
return true
}
#endif
return false
}
}

View File

@ -39,7 +39,7 @@ extension TunnelConfiguration {
var interfaceConfiguration: InterfaceConfiguration?
var peerConfigurations = [PeerConfiguration]()
let lines = wgQuickConfig.split(separator: "\n")
let lines = wgQuickConfig.split { $0.isNewline }
var parserState = ParserState.notInASection
var attributes = [String: String]()

View File

@ -52,6 +52,10 @@
6F0F44CB222D55FD00B0FF04 /* EditableTextCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F0F44CA222D55FD00B0FF04 /* EditableTextCell.swift */; };
6F1075642258AE9800D78929 /* DeleteTunnelsConfirmationAlert.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F1075632258AE9800D78929 /* DeleteTunnelsConfirmationAlert.swift */; };
6F19D30422402B8700A126F2 /* ConfirmationAlertPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F19D30322402B8700A126F2 /* ConfirmationAlertPresenter.swift */; };
6F2449E8226587B90047B9E9 /* MacAppStoreUpdateDetector.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F2449E7226587B80047B9E9 /* MacAppStoreUpdateDetector.swift */; };
6F3E02E9228000F6001FE7E3 /* MainMenu.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F3E02E8228000F6001FE7E3 /* MainMenu.swift */; };
6F29A9432278518D00DC6A6B /* RecentTunnelsTracker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F29A9422278518D00DC6A6B /* RecentTunnelsTracker.swift */; };
6F29A94722787B1600DC6A6B /* QuickActionItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F29A94622787B1600DC6A6B /* QuickActionItem.swift */; };
6F4DD16B21DA558800690EAE /* TunnelListRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F4DD16A21DA558800690EAE /* TunnelListRow.swift */; };
6F4DD16C21DA558F00690EAE /* NSTableView+Reuse.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F4DD16721DA552B00690EAE /* NSTableView+Reuse.swift */; };
6F4DD16E21DBEA0700690EAE /* ManageTunnelsRootViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F4DD16D21DBEA0700690EAE /* ManageTunnelsRootViewController.swift */; };
@ -66,6 +70,7 @@
6F628C3D217F09E9003482A3 /* TunnelViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F628C3C217F09E9003482A3 /* TunnelViewModel.swift */; };
6F628C3F217F3413003482A3 /* DNSServer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F628C3E217F3413003482A3 /* DNSServer.swift */; };
6F628C41217F47DB003482A3 /* TunnelDetailTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F628C40217F47DB003482A3 /* TunnelDetailTableViewController.swift */; };
6F6483E7229293300075BA15 /* LaunchedAtLoginDetector.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F6483E6229293300075BA15 /* LaunchedAtLoginDetector.swift */; };
6F6899A62180447E0012E523 /* x25519.c in Sources */ = {isa = PBXBuildFile; fileRef = 6F6899A52180447E0012E523 /* x25519.c */; };
6F6899A8218044FC0012E523 /* Curve25519.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F6899A7218044FC0012E523 /* Curve25519.swift */; };
6F693A562179E556008551C1 /* Endpoint.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F693A552179E556008551C1 /* Endpoint.swift */; };
@ -298,6 +303,10 @@
6F0F44CA222D55FD00B0FF04 /* EditableTextCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EditableTextCell.swift; sourceTree = "<group>"; };
6F1075632258AE9800D78929 /* DeleteTunnelsConfirmationAlert.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeleteTunnelsConfirmationAlert.swift; sourceTree = "<group>"; };
6F19D30322402B8700A126F2 /* ConfirmationAlertPresenter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConfirmationAlertPresenter.swift; sourceTree = "<group>"; };
6F2449E7226587B80047B9E9 /* MacAppStoreUpdateDetector.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MacAppStoreUpdateDetector.swift; sourceTree = "<group>"; };
6F3E02E8228000F6001FE7E3 /* MainMenu.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MainMenu.swift; sourceTree = "<group>"; };
6F29A9422278518D00DC6A6B /* RecentTunnelsTracker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RecentTunnelsTracker.swift; sourceTree = "<group>"; };
6F29A94622787B1600DC6A6B /* QuickActionItem.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = QuickActionItem.swift; sourceTree = "<group>"; };
6F4DD16721DA552B00690EAE /* NSTableView+Reuse.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NSTableView+Reuse.swift"; sourceTree = "<group>"; };
6F4DD16A21DA558800690EAE /* TunnelListRow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TunnelListRow.swift; sourceTree = "<group>"; };
6F4DD16D21DBEA0700690EAE /* ManageTunnelsRootViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ManageTunnelsRootViewController.swift; sourceTree = "<group>"; };
@ -316,6 +325,7 @@
6F628C3C217F09E9003482A3 /* TunnelViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TunnelViewModel.swift; sourceTree = "<group>"; };
6F628C3E217F3413003482A3 /* DNSServer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DNSServer.swift; sourceTree = "<group>"; };
6F628C40217F47DB003482A3 /* TunnelDetailTableViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TunnelDetailTableViewController.swift; sourceTree = "<group>"; };
6F6483E6229293300075BA15 /* LaunchedAtLoginDetector.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LaunchedAtLoginDetector.swift; sourceTree = "<group>"; };
6F689999218043390012E523 /* WireGuard-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "WireGuard-Bridging-Header.h"; sourceTree = "<group>"; };
6F6899A42180447E0012E523 /* x25519.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = x25519.h; sourceTree = "<group>"; };
6F6899A52180447E0012E523 /* x25519.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = x25519.c; sourceTree = "<group>"; };
@ -562,6 +572,8 @@
6F919EC2218A2AE90023B400 /* ErrorPresenter.swift */,
6F19D30322402B8700A126F2 /* ConfirmationAlertPresenter.swift */,
5F45417C21C1B23600994C13 /* UITableViewCell+Reuse.swift */,
6F29A9422278518D00DC6A6B /* RecentTunnelsTracker.swift */,
6F29A94622787B1600DC6A6B /* QuickActionItem.swift */,
6FF4AC23211EC472002C96EB /* Info.plist */,
6FF4AC482120B9E0002C96EB /* WireGuard.entitlements */,
);
@ -629,9 +641,12 @@
6FB1BD5F21D2607A00A991BF /* AppDelegate.swift */,
6F89E17921EDEB0E00C97BB9 /* StatusItemController.swift */,
6FBA101621D655340051C35F /* StatusMenu.swift */,
6F3E02E8228000F6001FE7E3 /* MainMenu.swift */,
6F89E17B21F090CC00C97BB9 /* TunnelsTracker.swift */,
6FBA104121D6BC210051C35F /* ErrorPresenter.swift */,
6FCD99AE21E0EA1700BA4C82 /* ImportPanelPresenter.swift */,
6F2449E7226587B80047B9E9 /* MacAppStoreUpdateDetector.swift */,
6F6483E6229293300075BA15 /* LaunchedAtLoginDetector.swift */,
6FB1BD6121D2607E00A991BF /* Assets.xcassets */,
6FB1BD6621D2607E00A991BF /* Info.plist */,
6FB1BD6721D2607E00A991BF /* WireGuard.entitlements */,
@ -1286,8 +1301,10 @@
6F4DD16B21DA558800690EAE /* TunnelListRow.swift in Sources */,
6FDB6D15224CB2CE00EE4BC3 /* LogViewCell.swift in Sources */,
6FE3661D21F64F6B00F78C7D /* ConfTextColorTheme.swift in Sources */,
6F3E02E9228000F6001FE7E3 /* MainMenu.swift in Sources */,
5F52D0BF21E3788900283CEA /* NSColor+Hex.swift in Sources */,
6FB1BDBE21D50F0200A991BF /* Logger.swift in Sources */,
6F6483E7229293300075BA15 /* LaunchedAtLoginDetector.swift in Sources */,
6FB1BDBF21D50F0200A991BF /* TunnelConfiguration+WgQuickConfig.swift in Sources */,
6FADE96C2254B8C300B838A4 /* UnusableTunnelDetailViewController.swift in Sources */,
6FFACD2021E4D8D500E9A2A5 /* ParseError+WireGuardAppError.swift in Sources */,
@ -1304,6 +1321,7 @@
6FBA104321D6BC250051C35F /* ErrorPresenter.swift in Sources */,
6FB1BDC521D50F0300A991BF /* Endpoint.swift in Sources */,
6FB1BDC621D50F0300A991BF /* DNSServer.swift in Sources */,
6F2449E8226587B90047B9E9 /* MacAppStoreUpdateDetector.swift in Sources */,
6FB1BDC721D50F0300A991BF /* InterfaceConfiguration.swift in Sources */,
6F907C9D224663A2003CED21 /* LogViewHelper.swift in Sources */,
6FB1BDC821D50F0300A991BF /* PeerConfiguration.swift in Sources */,
@ -1343,6 +1361,7 @@
buildActionMask = 2147483647;
files = (
6FE1765A21C90E87002690EA /* LocalizationHelper.swift in Sources */,
6F29A94722787B1600DC6A6B /* QuickActionItem.swift in Sources */,
6FF3527221C2616C0008484E /* ringlogger.c in Sources */,
6F0F44CB222D55FD00B0FF04 /* EditableTextCell.swift in Sources */,
6FF3527321C2616C0008484E /* Logger.swift in Sources */,
@ -1383,6 +1402,7 @@
6F7774EA217229DB006A79B3 /* IPAddressRange.swift in Sources */,
6F7774E82172020C006A79B3 /* TunnelConfiguration.swift in Sources */,
6FDEF7FB21863B6100D8FBF6 /* unzip.c in Sources */,
6F29A9432278518D00DC6A6B /* RecentTunnelsTracker.swift in Sources */,
6F6899A8218044FC0012E523 /* Curve25519.swift in Sources */,
6F0F44C9222D55BB00B0FF04 /* TextCell.swift in Sources */,
5F4541A021C2D6B700994C13 /* TunnelListCell.swift in Sources */,
@ -1513,7 +1533,7 @@
buildSettings = {
CODE_SIGN_ENTITLEMENTS = WireGuard/UI/macOS/LoginItemHelper/LoginItemHelper.entitlements;
CODE_SIGN_IDENTITY = "Mac Developer";
INFOPLIST_FILE = WireGuard/UI/macOS/Info.plist;
INFOPLIST_FILE = WireGuard/UI/macOS/LoginItemHelper/Info.plist;
PRODUCT_BUNDLE_IDENTIFIER = "$(APP_ID_MACOS).login-item-helper";
PRODUCT_NAME = WireGuardLoginItemHelper;
SDKROOT = macosx;
@ -1526,7 +1546,7 @@
buildSettings = {
CODE_SIGN_ENTITLEMENTS = WireGuard/UI/macOS/LoginItemHelper/LoginItemHelper.entitlements;
CODE_SIGN_IDENTITY = "Mac Developer";
INFOPLIST_FILE = WireGuard/UI/macOS/Info.plist;
INFOPLIST_FILE = WireGuard/UI/macOS/LoginItemHelper/Info.plist;
PRODUCT_BUNDLE_IDENTIFIER = "$(APP_ID_MACOS).login-item-helper";
PRODUCT_NAME = WireGuardLoginItemHelper;
SDKROOT = macosx;
@ -1687,6 +1707,7 @@
CLANG_WARN_UNREACHABLE_CODE = YES_AGGRESSIVE;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_HARDENED_RUNTIME = YES;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
@ -1752,6 +1773,7 @@
CLANG_WARN_UNREACHABLE_CODE = YES_AGGRESSIVE;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_HARDENED_RUNTIME = YES;
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;

View File

@ -291,19 +291,41 @@
"alertSystemErrorMessageTunnelConfigurationReadWriteFailed" = "Reading or writing the configuration failed.";
"alertSystemErrorMessageTunnelConfigurationUnknown" = "Unknown system error.";
// Mac status bar menu / pulldown menu
// Mac status bar menu / pulldown menu / main menu
"macMenuNetworks (%@)" = "Networks: %@";
"macMenuNetworksNone" = "Networks: None";
"macMenuTitle" = "WireGuard";
"macMenuManageTunnels" = "Manage tunnels";
"macMenuImportTunnels" = "Import tunnel(s) from file…";
"macMenuAddEmptyTunnel" = "Add empty tunnel…";
"macMenuViewLog" = "View log";
"macMenuExportTunnels" = "Export tunnels to zip…";
"macMenuManageTunnels" = "Manage Tunnels";
"macMenuImportTunnels" = "Import Tunnel(s) from File…";
"macMenuAddEmptyTunnel" = "Add Empty Tunnel…";
"macMenuViewLog" = "View Log";
"macMenuExportTunnels" = "Export Tunnels to Zip…";
"macMenuAbout" = "About WireGuard";
"macMenuQuit" = "Quit";
"macMenuQuit" = "Quit WireGuard";
"macMenuHideApp" = "Hide WireGuard";
"macMenuHideOtherApps" = "Hide Others";
"macMenuShowAllApps" = "Show All";
"macMenuFile" = "File";
"macMenuCloseWindow" = "Close Window";
"macMenuEdit" = "Edit";
"macMenuCut" = "Cut";
"macMenuCopy" = "Copy";
"macMenuPaste" = "Paste";
"macMenuSelectAll" = "Select All";
"macMenuTunnel" = "Tunnel";
"macMenuToggleStatus" = "Toggle Status";
"macMenuEditTunnel" = "Edit…";
"macMenuDeleteSelected" = "Delete Selected";
"macMenuWindow" = "Window";
"macMenuMinimize" = "Minimize";
"macMenuZoom" = "Zoom";
// Mac manage tunnels window
@ -383,10 +405,14 @@
// Mac alert
"macConfirmAndQuitAlertMessage" = "Do you want to close the tunnels manager or quit WireGuard entirely?";
"macConfirmAndQuitAlertInfo" = "If you close the tunnels manager, WireGuard will continue to be available from the menu bar icon.";
"macConfirmAndQuitInfoWithActiveTunnel (%@)" = "If you close the tunnels manager, WireGuard will continue to be available from the menu bar icon.\n\nNote that if you quit WireGuard entirely the currently active tunnel ('%@') will still remain active until you deactivate it from this application or through the Network panel in System Preferences.";
"macConfirmAndQuitAlertQuitWireGuard" = "Quit WireGuard";
"macConfirmAndQuitAlertCloseWindow" = "Close Tunnels Manager";
"macAppExitingWithActiveTunnelMessage" = "WireGuard is exiting with an active tunnel";
"macAppExitingWithActiveTunnelInfo" = "The tunnel will remain active after exiting. You may disable it by reopening this application or through the Network panel in System Preferences.";
"macPrivacyNoticeMessage" = "Privacy notice: be sure you trust this configuration file";
"macPrivacyNoticeInfo" = "You will be prompted by the system to allow or disallow adding a VPN configuration. While this application does not send any information to the WireGuard project, information is by design sent to the servers specified inside of the configuration file you have just added, which configures your computer to use those servers as a VPN. Be certain that you trust this configuration before clicking “Allow” in the following dialog.";
// Mac tooltip
@ -405,3 +431,13 @@
"macUnusableTunnelMessage" = "The configuration for this tunnel cannot be found in the keychain.";
"macUnusableTunnelInfo" = "In case this tunnel was created by another user, only that user can view, edit, or activate this tunnel.";
"macUnusableTunnelButtonTitleDeleteTunnel" = "Delete tunnel";
// Mac App Store updating alert
"macAppStoreUpdatingAlertMessage" = "App Store would like to update WireGuard";
"macAppStoreUpdatingAlertInfoWithOnDemand (%@)" = "Please disable on-demand for tunnel %@, deactivate it, and then continue updating in App Store.";
"macAppStoreUpdatingAlertInfoWithoutOnDemand (%@)" = "Please deactivate tunnel %@ and then continue updating in App Store.";
// Donation
"donateLink" = "♥ Donate to the WireGuard Project";

View File

@ -1,2 +1,2 @@
VERSION_NAME = 0.0.20190409
VERSION_ID = 7
VERSION_NAME = 0.0.20191012
VERSION_ID = 14

View File

@ -46,46 +46,59 @@ extension ActivateOnDemandOption {
}
init(from tunnelProviderManager: NETunnelProviderManager) {
let rules = tunnelProviderManager.onDemandRules ?? []
let activateOnDemandOption: ActivateOnDemandOption
if tunnelProviderManager.isOnDemandEnabled, let onDemandRules = tunnelProviderManager.onDemandRules {
self = ActivateOnDemandOption.create(from: onDemandRules)
} else {
self = .off
}
}
private static func create(from rules: [NEOnDemandRule]) -> ActivateOnDemandOption {
switch rules.count {
case 0:
activateOnDemandOption = .off
return .off
case 1:
let rule = rules[0]
precondition(rule.action == .connect)
activateOnDemandOption = .anyInterface(.anySSID)
guard rule.action == .connect else { return .off }
return .anyInterface(.anySSID)
case 2:
let connectRule = rules.first(where: { $0.action == .connect })!
let disconnectRule = rules.first(where: { $0.action == .disconnect })!
guard let connectRule = rules.first(where: { $0.action == .connect }) else {
wg_log(.error, message: "Unexpected onDemandRules set on tunnel provider manager: \(rules.count) rules found but no connect rule.")
return .off
}
guard let disconnectRule = rules.first(where: { $0.action == .disconnect }) else {
wg_log(.error, message: "Unexpected onDemandRules set on tunnel provider manager: \(rules.count) rules found but no disconnect rule.")
return .off
}
if connectRule.interfaceTypeMatch == .wiFi && disconnectRule.interfaceTypeMatch == nonWiFiInterfaceType {
activateOnDemandOption = .wiFiInterfaceOnly(.anySSID)
return .wiFiInterfaceOnly(.anySSID)
} else if connectRule.interfaceTypeMatch == nonWiFiInterfaceType && disconnectRule.interfaceTypeMatch == .wiFi {
activateOnDemandOption = .nonWiFiInterfaceOnly
return .nonWiFiInterfaceOnly
} else {
fatalError("Unexpected onDemandRules set on tunnel provider manager")
wg_log(.error, message: "Unexpected onDemandRules set on tunnel provider manager: \(rules.count) rules found but interface types are inconsistent.")
return .off
}
case 3:
let ssidRule = rules.first(where: { $0.interfaceTypeMatch == .wiFi && $0.ssidMatch != nil })!
let nonWiFiRule = rules.first(where: { $0.interfaceTypeMatch == nonWiFiInterfaceType })!
guard let ssidRule = rules.first(where: { $0.interfaceTypeMatch == .wiFi && $0.ssidMatch != nil }) else { return .off }
guard let nonWiFiRule = rules.first(where: { $0.interfaceTypeMatch == nonWiFiInterfaceType }) else { return .off }
let ssids = ssidRule.ssidMatch!
switch (ssidRule.action, nonWiFiRule.action) {
case (.connect, .connect):
activateOnDemandOption = .anyInterface(.onlySpecificSSIDs(ssids))
return .anyInterface(.onlySpecificSSIDs(ssids))
case (.connect, .disconnect):
activateOnDemandOption = .wiFiInterfaceOnly(.onlySpecificSSIDs(ssids))
return .wiFiInterfaceOnly(.onlySpecificSSIDs(ssids))
case (.disconnect, .connect):
activateOnDemandOption = .anyInterface(.exceptSpecificSSIDs(ssids))
return .anyInterface(.exceptSpecificSSIDs(ssids))
case (.disconnect, .disconnect):
activateOnDemandOption = .wiFiInterfaceOnly(.exceptSpecificSSIDs(ssids))
return .wiFiInterfaceOnly(.exceptSpecificSSIDs(ssids))
default:
fatalError("Unexpected SSID onDemandRules set on tunnel provider manager")
wg_log(.error, message: "Unexpected onDemandRules set on tunnel provider manager: \(rules.count) rules found")
return .off
}
default:
fatalError("Unexpected number of onDemandRules set on tunnel provider manager")
wg_log(.error, message: "Unexpected number of onDemandRules set on tunnel provider manager: \(rules.count) rules found")
return .off
}
self = activateOnDemandOption
}
}

View File

@ -33,7 +33,7 @@ class TunnelsManager {
startObservingTunnelConfigurations()
}
static func create(completionHandler: @escaping (WireGuardResult<TunnelsManager>) -> Void) {
static func create(completionHandler: @escaping (Result<TunnelsManager, TunnelsManagerError>) -> Void) {
#if targetEnvironment(simulator)
completionHandler(.success(TunnelsManager(tunnelProviders: MockTunnels.createMockTunnels())))
#else
@ -46,7 +46,11 @@ class TunnelsManager {
var tunnelManagers = managers ?? []
var refs: Set<Data> = []
var tunnelNames: Set<String> = []
for (index, tunnelManager) in tunnelManagers.enumerated().reversed() {
if let tunnelName = tunnelManager.localizedDescription {
tunnelNames.insert(tunnelName)
}
guard let proto = tunnelManager.protocolConfiguration as? NETunnelProviderProtocol else { continue }
if proto.migrateConfigurationIfNeeded(called: tunnelManager.localizedDescription ?? "unknown") {
tunnelManager.saveToPreferences { _ in }
@ -54,18 +58,27 @@ class TunnelsManager {
#if os(iOS)
let passwordRef = proto.verifyConfigurationReference() ? proto.passwordReference : nil
#elseif os(macOS)
let passwordRef = proto.passwordReference // To handle multiple users in macOS, we skip verifying
let passwordRef: Data?
if proto.providerConfiguration?["UID"] as? uid_t == getuid() {
passwordRef = proto.verifyConfigurationReference() ? proto.passwordReference : nil
} else {
passwordRef = proto.passwordReference // To handle multiple users in macOS, we skip verifying
}
#else
#error("Unimplemented")
#endif
if let ref = passwordRef {
refs.insert(ref)
} else {
wg_log(.info, message: "Removing orphaned tunnel with non-verifying keychain entry: \(tunnelManager.localizedDescription ?? "<unknown>")")
tunnelManager.removeFromPreferences { _ in }
tunnelManagers.remove(at: index)
}
}
Keychain.deleteReferences(except: refs)
#if os(iOS)
RecentTunnelsTracker.cleanupTunnels(except: tunnelNames)
#endif
completionHandler(.success(TunnelsManager(tunnelProviders: tunnelManagers)))
}
#endif
@ -104,7 +117,7 @@ class TunnelsManager {
}
}
func add(tunnelConfiguration: TunnelConfiguration, onDemandOption: ActivateOnDemandOption = .off, completionHandler: @escaping (WireGuardResult<TunnelContainer>) -> Void) {
func add(tunnelConfiguration: TunnelConfiguration, onDemandOption: ActivateOnDemandOption = .off, completionHandler: @escaping (Result<TunnelContainer, TunnelsManagerError>) -> Void) {
let tunnelName = tunnelConfiguration.name ?? ""
if tunnelName.isEmpty {
completionHandler(.failure(TunnelsManagerError.tunnelNameEmpty))
@ -167,9 +180,15 @@ class TunnelsManager {
let tail = tunnelConfigurations.dropFirst()
add(tunnelConfiguration: head) { [weak self, tail] result in
DispatchQueue.main.async {
let numberSuccessful = numberSuccessful + (result.isSuccess ? 1 : 0)
let lastError = lastError ?? (result.error as? TunnelsManagerError)
self?.addMultiple(tunnelConfigurations: tail, numberSuccessful: numberSuccessful, lastError: lastError, completionHandler: completionHandler)
var numberSuccessfulCount = numberSuccessful
var lastError: TunnelsManagerError?
switch result {
case .failure(let error):
lastError = error
case .success:
numberSuccessfulCount = numberSuccessful + 1
}
self?.addMultiple(tunnelConfigurations: tail, numberSuccessful: numberSuccessfulCount, lastError: lastError, completionHandler: completionHandler)
}
}
}
@ -182,7 +201,8 @@ class TunnelsManager {
}
let tunnelProviderManager = tunnel.tunnelProvider
let isNameChanged = tunnelName != tunnelProviderManager.localizedDescription
let oldName = tunnelProviderManager.localizedDescription ?? ""
let isNameChanged = tunnelName != oldName
if isNameChanged {
guard !tunnels.contains(where: { $0.name == tunnelName }) else {
completionHandler(TunnelsManagerError.tunnelAlreadyExistsWithThatName)
@ -214,6 +234,9 @@ class TunnelsManager {
self.tunnels.sort { TunnelsManager.tunnelNameIsLessThan($0.name, $1.name) }
let newIndex = self.tunnels.firstIndex(of: tunnel)!
self.tunnelsListDelegate?.tunnelMoved(from: oldIndex, to: newIndex)
#if os(iOS)
RecentTunnelsTracker.handleTunnelRenamed(oldName: oldName, newName: tunnelName)
#endif
}
self.tunnelsListDelegate?.tunnelModified(at: self.tunnels.firstIndex(of: tunnel)!)
@ -245,10 +268,15 @@ class TunnelsManager {
func remove(tunnel: TunnelContainer, completionHandler: @escaping (TunnelsManagerError?) -> Void) {
let tunnelProviderManager = tunnel.tunnelProvider
if tunnel.isTunnelConfigurationAvailableInKeychain {
#if os(macOS)
if tunnel.isTunnelAvailableToUser {
(tunnelProviderManager.protocolConfiguration as? NETunnelProviderProtocol)?.destroyConfigurationReference()
}
#elseif os(iOS)
(tunnelProviderManager.protocolConfiguration as? NETunnelProviderProtocol)?.destroyConfigurationReference()
#else
#error("Unimplemented")
#endif
tunnelProviderManager.removeFromPreferences { [weak self] error in
guard error == nil else {
wg_log(.error, message: "Remove: Saving configuration failed: \(error!)")
@ -260,6 +288,10 @@ class TunnelsManager {
self.tunnelsListDelegate?.tunnelRemoved(at: index, tunnel: tunnel)
}
completionHandler(nil)
#if os(iOS)
RecentTunnelsTracker.handleTunnelRemoved(tunnelName: tunnel.name)
#endif
}
}
@ -292,6 +324,10 @@ class TunnelsManager {
return tunnels[index]
}
func mapTunnels<T>(transform: (TunnelContainer) throws -> T) rethrows -> [T] {
return try tunnels.map(transform)
}
func index(of tunnel: TunnelContainer) -> Int? {
return tunnels.firstIndex(of: tunnel)
}
@ -337,6 +373,10 @@ class TunnelsManager {
#else
tunnel.startActivation(activationDelegate: activationDelegate)
#endif
#if os(iOS)
RecentTunnelsTracker.handleTunnelActivated(tunnelName: tunnel.name)
#endif
}
func startDeactivation(of tunnel: TunnelContainer) {
@ -464,14 +504,16 @@ class TunnelContainer: NSObject {
return tunnelProvider.tunnelConfiguration
}
var isTunnelConfigurationAvailableInKeychain: Bool {
return tunnelProvider.isTunnelConfigurationAvailableInKeychain
}
var onDemandOption: ActivateOnDemandOption {
return ActivateOnDemandOption(from: tunnelProvider)
}
#if os(macOS)
var isTunnelAvailableToUser: Bool {
return (tunnelProvider.protocolConfiguration as? NETunnelProviderProtocol)?.providerConfiguration?["UID"] as? uid_t == getuid()
}
#endif
init(tunnel: NETunnelProviderManager) {
name = tunnel.localizedDescription ?? "Unnamed"
let status = TunnelStatus(from: tunnel.connection.status)
@ -580,18 +622,8 @@ class TunnelContainer: NSObject {
}
extension NETunnelProviderManager {
private static var cachedIsConfigAvailableInKeychainKey: UInt8 = 0
private static var cachedConfigKey: UInt8 = 0
var isTunnelConfigurationAvailableInKeychain: Bool {
if let cachedNumber = objc_getAssociatedObject(self, &NETunnelProviderManager.cachedIsConfigAvailableInKeychainKey) as? NSNumber {
return cachedNumber.boolValue
}
let isAvailable = (protocolConfiguration as? NETunnelProviderProtocol)?.verifyConfigurationReference() ?? false
objc_setAssociatedObject(self, &NETunnelProviderManager.cachedIsConfigAvailableInKeychainKey, NSNumber(value: isAvailable), objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC)
return isAvailable
}
var tunnelConfiguration: TunnelConfiguration? {
if let cached = objc_getAssociatedObject(self, &NETunnelProviderManager.cachedConfigKey) as? TunnelConfiguration {
return cached
@ -607,17 +639,9 @@ extension NETunnelProviderManager {
protocolConfiguration = NETunnelProviderProtocol(tunnelConfiguration: tunnelConfiguration, previouslyFrom: protocolConfiguration)
localizedDescription = tunnelConfiguration.name
objc_setAssociatedObject(self, &NETunnelProviderManager.cachedConfigKey, tunnelConfiguration, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC)
objc_setAssociatedObject(self, &NETunnelProviderManager.cachedIsConfigAvailableInKeychainKey, NSNumber(value: true), objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC)
}
func isEquivalentTo(_ tunnel: TunnelContainer) -> Bool {
switch (isTunnelConfigurationAvailableInKeychain, tunnel.isTunnelConfigurationAvailableInKeychain) {
case (true, true):
return tunnelConfiguration == tunnel.tunnelConfiguration
case (false, false):
return localizedDescription == tunnel.name
default:
return false
}
return localizedDescription == tunnel.name && tunnelConfiguration == tunnel.tunnelConfiguration
}
}

View File

@ -16,10 +16,10 @@ class TunnelImporter {
if url.pathExtension.lowercased() == "zip" {
dispatchGroup.enter()
ZipImporter.importConfigFiles(from: url) { result in
if let error = result.error {
switch result {
case .failure(let error):
lastFileImportErrorText = error.alertText
}
if let configsInZip = result.value {
case .success(let configsInZip):
configs.append(contentsOf: configsInZip)
}
dispatchGroup.leave()
@ -44,10 +44,20 @@ class TunnelImporter {
}
return
}
let tunnelConfiguration = try? TunnelConfiguration(fromWgQuickConfig: fileContents, called: fileBaseName)
var parseError: Error?
var tunnelConfiguration: TunnelConfiguration?
do {
tunnelConfiguration = try TunnelConfiguration(fromWgQuickConfig: fileContents, called: fileBaseName)
} catch let error {
parseError = error
}
DispatchQueue.main.async {
if tunnelConfiguration == nil {
lastFileImportErrorText = (title: tr("alertBadConfigImportTitle"), message: tr(format: "alertBadConfigImportMessage (%@)", fileName))
if parseError != nil {
if let parseError = parseError as? WireGuardAppError {
lastFileImportErrorText = parseError.alertText
} else {
lastFileImportErrorText = (title: tr("alertBadConfigImportTitle"), message: tr(format: "alertBadConfigImportMessage (%@)", fileName))
}
}
configs.append(tunnelConfiguration)
dispatchGroup.leave()

View File

@ -9,10 +9,17 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
var mainVC: MainViewController?
var isLaunchedForSpecificAction = false
func application(_ application: UIApplication, willFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
Logger.configureGlobal(tagged: "APP", withFilePath: FileManager.logFileURL?.path)
if let launchOptions = launchOptions {
if launchOptions[.url] != nil || launchOptions[.shortcutItem] != nil {
isLaunchedForSpecificAction = true
}
}
let window = UIWindow(frame: UIScreen.main.bounds)
window.backgroundColor = .white
self.window = window
@ -27,16 +34,28 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
}
func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey: Any] = [:]) -> Bool {
guard let tunnelsManager = mainVC?.tunnelsManager else { return true }
TunnelImporter.importFromFile(urls: [url], into: tunnelsManager, sourceVC: mainVC, errorPresenterType: ErrorPresenter.self) {
_ = FileManager.deleteFile(at: url)
}
mainVC?.importFromDisposableFile(url: url)
return true
}
func applicationDidBecomeActive(_ application: UIApplication) {
mainVC?.refreshTunnelConnectionStatuses()
}
func applicationWillResignActive(_ application: UIApplication) {
guard let allTunnelNames = mainVC?.allTunnelNames() else { return }
application.shortcutItems = QuickActionItem.createItems(allTunnelNames: allTunnelNames)
}
func application(_ application: UIApplication, performActionFor shortcutItem: UIApplicationShortcutItem, completionHandler: @escaping (Bool) -> Void) {
guard shortcutItem.type == QuickActionItem.type else {
completionHandler(false)
return
}
let tunnelName = shortcutItem.localizedTitle
mainVC?.showTunnelDetailForTunnel(named: tunnelName, animated: false, shouldToggleStatus: true)
completionHandler(true)
}
}
extension AppDelegate {
@ -45,7 +64,7 @@ extension AppDelegate {
}
func application(_ application: UIApplication, shouldRestoreApplicationState coder: NSCoder) -> Bool {
return true
return !self.isLaunchedForSpecificAction
}
func application(_ application: UIApplication, viewControllerWithRestorationIdentifierPath identifierComponents: [String], coder: NSCoder) -> UIViewController? {
@ -58,7 +77,7 @@ extension AppDelegate {
}
} else {
// Show it when tunnelsManager is available
mainVC?.showTunnelDetailForTunnel(named: tunnelName, animated: false)
mainVC?.showTunnelDetailForTunnel(named: tunnelName, animated: false, shouldToggleStatus: false)
}
}
return nil

View File

@ -64,6 +64,8 @@
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleDisplayName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>

View File

@ -0,0 +1,25 @@
// SPDX-License-Identifier: MIT
// Copyright © 2018-2019 WireGuard LLC. All Rights Reserved.
import UIKit
class QuickActionItem: UIApplicationShortcutItem {
static let type = "WireGuardTunnelActivateAndShow"
init(tunnelName: String) {
super.init(type: QuickActionItem.type, localizedTitle: tunnelName, localizedSubtitle: nil, icon: nil, userInfo: nil)
}
static func createItems(allTunnelNames: [String]) -> [QuickActionItem] {
let numberOfItems = 10
// Currently, only 4 items shown by iOS, but that can increase in the future.
// iOS will discard additional items we give it.
var tunnelNames = RecentTunnelsTracker.recentlyActivatedTunnelNames(limit: numberOfItems)
let numberOfSlotsRemaining = numberOfItems - tunnelNames.count
if numberOfSlotsRemaining > 0 {
let moreTunnels = allTunnelNames.filter { !tunnelNames.contains($0) }.prefix(numberOfSlotsRemaining)
tunnelNames.append(contentsOf: moreTunnels)
}
return tunnelNames.map { QuickActionItem(tunnelName: $0) }
}
}

View File

@ -0,0 +1,72 @@
// SPDX-License-Identifier: MIT
// Copyright © 2018-2019 WireGuard LLC. All Rights Reserved.
import Foundation
class RecentTunnelsTracker {
private static let keyRecentlyActivatedTunnelNames = "recentlyActivatedTunnelNames"
private static let maxNumberOfTunnels = 10
private static var userDefaults: UserDefaults? {
guard let appGroupId = FileManager.appGroupId else {
wg_log(.error, staticMessage: "Cannot obtain app group ID from bundle for tracking recently used tunnels")
return nil
}
guard let userDefaults = UserDefaults(suiteName: appGroupId) else {
wg_log(.error, staticMessage: "Cannot obtain shared user defaults for tracking recently used tunnels")
return nil
}
return userDefaults
}
static func handleTunnelActivated(tunnelName: String) {
guard let userDefaults = RecentTunnelsTracker.userDefaults else { return }
var recentTunnels = userDefaults.stringArray(forKey: keyRecentlyActivatedTunnelNames) ?? []
if let existingIndex = recentTunnels.firstIndex(of: tunnelName) {
recentTunnels.remove(at: existingIndex)
}
recentTunnels.insert(tunnelName, at: 0)
if recentTunnels.count > maxNumberOfTunnels {
recentTunnels.removeLast(recentTunnels.count - maxNumberOfTunnels)
}
userDefaults.set(recentTunnels, forKey: keyRecentlyActivatedTunnelNames)
}
static func handleTunnelRemoved(tunnelName: String) {
guard let userDefaults = RecentTunnelsTracker.userDefaults else { return }
var recentTunnels = userDefaults.stringArray(forKey: keyRecentlyActivatedTunnelNames) ?? []
if let existingIndex = recentTunnels.firstIndex(of: tunnelName) {
recentTunnels.remove(at: existingIndex)
userDefaults.set(recentTunnels, forKey: keyRecentlyActivatedTunnelNames)
}
}
static func handleTunnelRenamed(oldName: String, newName: String) {
guard let userDefaults = RecentTunnelsTracker.userDefaults else { return }
var recentTunnels = userDefaults.stringArray(forKey: keyRecentlyActivatedTunnelNames) ?? []
if let existingIndex = recentTunnels.firstIndex(of: oldName) {
recentTunnels[existingIndex] = newName
userDefaults.set(recentTunnels, forKey: keyRecentlyActivatedTunnelNames)
}
}
static func cleanupTunnels(except tunnelNamesToKeep: Set<String>) {
guard let userDefaults = RecentTunnelsTracker.userDefaults else { return }
var recentTunnels = userDefaults.stringArray(forKey: keyRecentlyActivatedTunnelNames) ?? []
let oldCount = recentTunnels.count
recentTunnels.removeAll { !tunnelNamesToKeep.contains($0) }
if oldCount != recentTunnels.count {
userDefaults.set(recentTunnels, forKey: keyRecentlyActivatedTunnelNames)
}
}
static func recentlyActivatedTunnelNames(limit: Int) -> [String] {
guard let userDefaults = RecentTunnelsTracker.userDefaults else { return [] }
var recentTunnels = userDefaults.stringArray(forKey: keyRecentlyActivatedTunnelNames) ?? []
if limit < recentTunnels.count {
recentTunnels.removeLast(recentTunnels.count - limit)
}
return recentTunnels
}
}

View File

@ -20,6 +20,15 @@ class LogViewController: UIViewController {
return busyIndicator
}()
let paragraphStyle: NSParagraphStyle = {
let paragraphStyle = NSMutableParagraphStyle()
paragraphStyle.setParagraphStyle(NSParagraphStyle.default)
paragraphStyle.lineHeightMultiple = 1.2
return paragraphStyle
}()
var isNextLineHighlighted = false
var logViewHelper: LogViewHelper?
var isFetchingLogEntries = false
private var updateLogEntriesTimer: Timer?
@ -68,9 +77,20 @@ class LogViewController: UIViewController {
}
guard !fetchedLogEntries.isEmpty else { return }
let isScrolledToEnd = self.textView.contentSize.height - self.textView.bounds.height - self.textView.contentOffset.y < 1
let text = fetchedLogEntries.reduce("") { $0 + $1.text() + "\n" }
let font = UIFont.preferredFont(forTextStyle: UIFont.TextStyle.body)
let richText = NSAttributedString(string: text, attributes: [.font: font])
let richText = NSMutableAttributedString()
let bodyFont = UIFont.preferredFont(forTextStyle: UIFont.TextStyle.body)
let captionFont = UIFont.preferredFont(forTextStyle: UIFont.TextStyle.caption1)
let lightGrayColor = UIColor(white: 0.88, alpha: 1.0)
for logEntry in fetchedLogEntries {
let bgColor = self.isNextLineHighlighted ? lightGrayColor : UIColor.white
let timestampText = NSAttributedString(string: logEntry.timestamp + "\n", attributes: [.font: captionFont, .backgroundColor: bgColor, .paragraphStyle: self.paragraphStyle])
let messageText = NSAttributedString(string: logEntry.message + "\n", attributes: [.font: bodyFont, .backgroundColor: bgColor, .paragraphStyle: self.paragraphStyle])
richText.append(timestampText)
richText.append(messageText)
self.isNextLineHighlighted.toggle()
}
self.textView.textStorage.append(richText)
if isScrolledToEnd {
let endOfCurrentText = NSRange(location: (self.textView.text as NSString).length, length: 0)

View File

@ -42,22 +42,25 @@ class MainViewController: UISplitViewController {
TunnelsManager.create { [weak self] result in
guard let self = self else { return }
if let error = result.error {
switch result {
case .failure(let error):
ErrorPresenter.showErrorAlert(error: error, from: self)
return
case .success(let tunnelsManager):
self.tunnelsManager = tunnelsManager
self.tunnelsListVC?.setTunnelsManager(tunnelsManager: tunnelsManager)
tunnelsManager.activationDelegate = self
self.onTunnelsManagerReady?(tunnelsManager)
self.onTunnelsManagerReady = nil
}
let tunnelsManager: TunnelsManager = result.value!
self.tunnelsManager = tunnelsManager
self.tunnelsListVC?.setTunnelsManager(tunnelsManager: tunnelsManager)
tunnelsManager.activationDelegate = self
self.onTunnelsManagerReady?(tunnelsManager)
self.onTunnelsManagerReady = nil
}
}
func allTunnelNames() -> [String]? {
guard let tunnelsManager = self.tunnelsManager else { return nil }
return tunnelsManager.mapTunnels { $0.name }
}
}
extension MainViewController: TunnelsManagerActivationDelegate {
@ -85,19 +88,17 @@ extension MainViewController {
}
}
func showTunnelDetailForTunnel(named tunnelName: String, animated: Bool) {
func showTunnelDetailForTunnel(named tunnelName: String, animated: Bool, shouldToggleStatus: Bool) {
let showTunnelDetailBlock: (TunnelsManager) -> Void = { [weak self] tunnelsManager in
guard let self = self else { return }
guard let tunnelsListVC = self.tunnelsListVC else { return }
if let tunnel = tunnelsManager.tunnel(named: tunnelName) {
let tunnelDetailVC = TunnelDetailTableViewController(tunnelsManager: tunnelsManager, tunnel: tunnel)
let tunnelDetailNC = UINavigationController(rootViewController: tunnelDetailVC)
tunnelDetailNC.restorationIdentifier = "DetailNC"
if let self = self {
if animated {
self.showDetailViewController(tunnelDetailNC, sender: self)
} else {
UIView.performWithoutAnimation {
self.showDetailViewController(tunnelDetailNC, sender: self)
}
tunnelsListVC.showTunnelDetail(for: tunnel, animated: false)
if shouldToggleStatus {
if tunnel.status == .inactive {
tunnelsManager.startActivation(of: tunnel)
} else if tunnel.status == .active {
tunnelsManager.startDeactivation(of: tunnel)
}
}
}
@ -108,6 +109,19 @@ extension MainViewController {
onTunnelsManagerReady = showTunnelDetailBlock
}
}
func importFromDisposableFile(url: URL) {
let importFromFileBlock: (TunnelsManager) -> Void = { [weak self] tunnelsManager in
TunnelImporter.importFromFile(urls: [url], into: tunnelsManager, sourceVC: self, errorPresenterType: ErrorPresenter.self) {
_ = FileManager.deleteFile(at: url)
}
}
if let tunnelsManager = tunnelsManager {
importFromFileBlock(tunnelsManager)
} else {
onTunnelsManagerReady = importFromFileBlock
}
}
}
extension MainViewController: UISplitViewControllerDelegate {

View File

@ -266,6 +266,10 @@ extension SSIDOptionEditTableViewController {
case .ssidOption:
let previousOption = selectedOption
selectedOption = ssidOptionFields[indexPath.row]
guard previousOption != selectedOption else {
tableView.deselectRow(at: indexPath, animated: true)
return
}
loadSections()
if previousOption == .anySSID {
let indexSet = IndexSet(1 ... 2)

View File

@ -11,6 +11,7 @@ class SettingsTableViewController: UITableViewController {
case goBackendVersion
case exportZipArchive
case viewLog
case donateLink
var localizedUIString: String {
switch self {
@ -18,12 +19,13 @@ class SettingsTableViewController: UITableViewController {
case .goBackendVersion: return tr("settingsVersionKeyWireGuardGoBackend")
case .exportZipArchive: return tr("settingsExportZipButtonTitle")
case .viewLog: return tr("settingsViewLogButtonTitle")
case .donateLink: return tr("donateLink")
}
}
}
let settingsFieldsBySection: [[SettingsFields]] = [
[.iosAppVersion, .goBackendVersion],
[.iosAppVersion, .goBackendVersion, .donateLink],
[.exportZipArchive],
[.viewLog]
]
@ -160,14 +162,23 @@ extension SettingsTableViewController {
self?.exportConfigurationsAsZipFile(sourceView: cell.button)
}
return cell
} else {
assert(field == .viewLog)
} else if field == .viewLog {
let cell: ButtonCell = tableView.dequeueReusableCell(for: indexPath)
cell.buttonText = field.localizedUIString
cell.onTapped = { [weak self] in
self?.presentLogView()
}
return cell
} else if field == .donateLink {
let cell: ButtonCell = tableView.dequeueReusableCell(for: indexPath)
cell.buttonText = field.localizedUIString
cell.onTapped = {
if let url = URL(string: "https://www.wireguard.com/donations/"), UIApplication.shared.canOpenURL(url) {
UIApplication.shared.open(url, options: [:])
}
}
return cell
}
fatalError()
}
}

View File

@ -127,10 +127,10 @@ class TunnelEditTableViewController: UITableViewController {
} else {
// We're adding a new tunnel
tunnelsManager.add(tunnelConfiguration: tunnelConfiguration, onDemandOption: onDemandOption) { [weak self] result in
if let error = result.error {
switch result {
case .failure(let error):
ErrorPresenter.showErrorAlert(error: error, from: self)
} else {
let tunnel: TunnelContainer = result.value!
case .success(let tunnel):
self?.dismiss(animated: true, completion: nil)
self?.delegate?.tunnelSaved(tunnel: tunnel)
}

View File

@ -251,6 +251,24 @@ class TunnelsListTableViewController: UIViewController {
}
}
}
func showTunnelDetail(for tunnel: TunnelContainer, animated: Bool) {
guard let tunnelsManager = tunnelsManager else { return }
guard let splitViewController = splitViewController else { return }
guard let navController = navigationController else { return }
let tunnelDetailVC = TunnelDetailTableViewController(tunnelsManager: tunnelsManager,
tunnel: tunnel)
let tunnelDetailNC = UINavigationController(rootViewController: tunnelDetailVC)
tunnelDetailNC.restorationIdentifier = "DetailNC"
if splitViewController.isCollapsed && navController.viewControllers.count > 1 {
navController.setViewControllers([self, tunnelDetailNC], animated: animated)
} else {
splitViewController.showDetailViewController(tunnelDetailNC, sender: self, animated: animated)
}
detailDisplayedTunnel = tunnel
self.presentedViewController?.dismiss(animated: false, completion: nil)
}
}
extension TunnelsListTableViewController: UIDocumentPickerDelegate {
@ -264,9 +282,10 @@ extension TunnelsListTableViewController: QRScanViewControllerDelegate {
func addScannedQRCode(tunnelConfiguration: TunnelConfiguration, qrScanViewController: QRScanViewController,
completionHandler: (() -> Void)?) {
tunnelsManager?.add(tunnelConfiguration: tunnelConfiguration) { result in
if let error = result.error {
switch result {
case .failure(let error):
ErrorPresenter.showErrorAlert(error: error, from: qrScanViewController, onDismissal: completionHandler)
} else {
case .success:
completionHandler?()
}
}
@ -308,12 +327,7 @@ extension TunnelsListTableViewController: UITableViewDelegate {
}
guard let tunnelsManager = tunnelsManager else { return }
let tunnel = tunnelsManager.tunnel(at: indexPath.row)
let tunnelDetailVC = TunnelDetailTableViewController(tunnelsManager: tunnelsManager,
tunnel: tunnel)
let tunnelDetailNC = UINavigationController(rootViewController: tunnelDetailVC)
tunnelDetailNC.restorationIdentifier = "DetailNC"
showDetailViewController(tunnelDetailNC, sender: self) // Shall get propagated up to the split-vc
detailDisplayedTunnel = tunnel
showTunnelDetail(for: tunnel, animated: true)
}
func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) {
@ -386,3 +400,15 @@ extension TunnelsListTableViewController: TunnelsManagerListDelegate {
}
}
}
extension UISplitViewController {
func showDetailViewController(_ vc: UIViewController, sender: Any?, animated: Bool) {
if animated {
showDetailViewController(vc, sender: sender)
} else {
UIView.performWithoutAnimation {
showDetailViewController(vc, sender: sender)
}
}
}
}

View File

@ -13,33 +13,95 @@ class AppDelegate: NSObject, NSApplicationDelegate {
var manageTunnelsRootVC: ManageTunnelsRootViewController?
var manageTunnelsWindowObject: NSWindow?
var onAppDeactivation: (() -> Void)?
func applicationWillFinishLaunching(_ notification: Notification) {
// To workaround a possible AppKit bug that causes the main menu to become unresponsive sometimes
// (especially when launched through Xcode) if we call setActivationPolicy(.regular) in
// in applicationDidFinishLaunching, we set it to .prohibited here.
// Setting it to .regular would fix that problem too, but at this point, we don't know
// whether the app was launched at login or not, so we're not sure whether we should
// show the app icon in the dock or not.
NSApp.setActivationPolicy(.prohibited)
}
func applicationDidFinishLaunching(_ aNotification: Notification) {
Logger.configureGlobal(tagged: "APP", withFilePath: FileManager.logFileURL?.path)
registerLoginItem(shouldLaunchAtLogin: true)
var isLaunchedAtLogin = false
if let appleEvent = NSAppleEventManager.shared().currentAppleEvent {
isLaunchedAtLogin = LaunchedAtLoginDetector.isLaunchedAtLogin(openAppleEvent: appleEvent)
}
NSApp.mainMenu = MainMenu()
setDockIconAndMainMenuVisibility(isVisible: !isLaunchedAtLogin)
TunnelsManager.create { [weak self] result in
guard let self = self else { return }
if let error = result.error {
switch result {
case .failure(let error):
ErrorPresenter.showErrorAlert(error: error, from: nil)
return
case .success(let tunnelsManager):
let statusMenu = StatusMenu(tunnelsManager: tunnelsManager)
statusMenu.windowDelegate = self
let statusItemController = StatusItemController()
statusItemController.statusItem.menu = statusMenu
let tunnelsTracker = TunnelsTracker(tunnelsManager: tunnelsManager)
tunnelsTracker.statusMenu = statusMenu
tunnelsTracker.statusItemController = statusItemController
self.tunnelsManager = tunnelsManager
self.tunnelsTracker = tunnelsTracker
self.statusItemController = statusItemController
if !isLaunchedAtLogin {
self.showManageTunnelsWindow(completion: nil)
}
}
}
}
let tunnelsManager: TunnelsManager = result.value!
func applicationShouldHandleReopen(_ sender: NSApplication, hasVisibleWindows: Bool) -> Bool {
if let appleEvent = NSAppleEventManager.shared().currentAppleEvent {
if LaunchedAtLoginDetector.isReopenedByLoginItemHelper(reopenAppleEvent: appleEvent) {
return false
}
}
if hasVisibleWindows {
return true
}
showManageTunnelsWindow(completion: nil)
return false
}
let statusMenu = StatusMenu(tunnelsManager: tunnelsManager)
statusMenu.windowDelegate = self
@objc func confirmAndQuit() {
let alert = NSAlert()
alert.messageText = tr("macConfirmAndQuitAlertMessage")
if let currentTunnel = tunnelsTracker?.currentTunnel, currentTunnel.status == .active || currentTunnel.status == .activating {
alert.informativeText = tr(format: "macConfirmAndQuitInfoWithActiveTunnel (%@)", currentTunnel.name)
} else {
alert.informativeText = tr("macConfirmAndQuitAlertInfo")
}
alert.addButton(withTitle: tr("macConfirmAndQuitAlertCloseWindow"))
alert.addButton(withTitle: tr("macConfirmAndQuitAlertQuitWireGuard"))
let statusItemController = StatusItemController()
statusItemController.statusItem.menu = statusMenu
let tunnelsTracker = TunnelsTracker(tunnelsManager: tunnelsManager)
tunnelsTracker.statusMenu = statusMenu
tunnelsTracker.statusItemController = statusItemController
self.tunnelsManager = tunnelsManager
self.tunnelsTracker = tunnelsTracker
self.statusItemController = statusItemController
NSApp.activate(ignoringOtherApps: true)
if let manageWindow = manageTunnelsWindowObject {
manageWindow.orderFront(self)
alert.beginSheetModal(for: manageWindow) { response in
switch response {
case .alertFirstButtonReturn:
manageWindow.close()
case .alertSecondButtonReturn:
NSApp.terminate(nil)
default:
break
}
}
}
}
@ -68,12 +130,105 @@ class AppDelegate: NSObject, NSApplicationDelegate {
NSApp.terminate(nil)
}
}
func applicationShouldTerminate(_ sender: NSApplication) -> NSApplication.TerminateReply {
guard let currentTunnel = tunnelsTracker?.currentTunnel, currentTunnel.status == .active || currentTunnel.status == .activating else {
return .terminateNow
}
guard let appleEvent = NSAppleEventManager.shared().currentAppleEvent else {
return .terminateNow
}
guard MacAppStoreUpdateDetector.isUpdatingFromMacAppStore(quitAppleEvent: appleEvent) else {
return .terminateNow
}
let alert = NSAlert()
alert.messageText = tr("macAppStoreUpdatingAlertMessage")
if currentTunnel.isActivateOnDemandEnabled {
alert.informativeText = tr(format: "macAppStoreUpdatingAlertInfoWithOnDemand (%@)", currentTunnel.name)
} else {
alert.informativeText = tr(format: "macAppStoreUpdatingAlertInfoWithoutOnDemand (%@)", currentTunnel.name)
}
NSApp.activate(ignoringOtherApps: true)
if let manageWindow = manageTunnelsWindowObject {
alert.beginSheetModal(for: manageWindow) { _ in }
} else {
alert.runModal()
}
return .terminateCancel
}
func applicationShouldTerminateAfterLastWindowClosed(_ application: NSApplication) -> Bool {
DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(200)) { [weak self] in
self?.setDockIconAndMainMenuVisibility(isVisible: false)
}
return false
}
private func setDockIconAndMainMenuVisibility(isVisible: Bool, completion: (() -> Void)? = nil) {
let currentActivationPolicy = NSApp.activationPolicy()
let newActivationPolicy: NSApplication.ActivationPolicy = isVisible ? .regular : .accessory
guard currentActivationPolicy != newActivationPolicy else {
if newActivationPolicy == .regular {
NSApp.activate(ignoringOtherApps: true)
}
completion?()
return
}
if newActivationPolicy == .regular && NSApp.isActive {
// To workaround a possible AppKit bug that causes the main menu to become unresponsive,
// we should deactivate the app first and then set the activation policy.
// NSApp.deactivate() doesn't always deactivate the app, so we instead use
// setActivationPolicy(.prohibited).
onAppDeactivation = {
NSApp.setActivationPolicy(.regular)
NSApp.activate(ignoringOtherApps: true)
completion?()
}
NSApp.setActivationPolicy(.prohibited)
} else {
NSApp.setActivationPolicy(newActivationPolicy)
if newActivationPolicy == .regular {
NSApp.activate(ignoringOtherApps: true)
}
completion?()
}
}
func applicationDidResignActive(_ notification: Notification) {
onAppDeactivation?()
onAppDeactivation = nil
}
}
extension AppDelegate {
@objc func aboutClicked() {
var appVersion = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String ?? "Unknown"
if let appBuild = Bundle.main.infoDictionary?["CFBundleVersion"] as? String {
appVersion += " (\(appBuild))"
}
let appVersionString = [
tr(format: "macAppVersion (%@)", appVersion),
tr(format: "macGoBackendVersion (%@)", WIREGUARD_GO_VERSION)
].joined(separator: "\n")
let donateString = NSMutableAttributedString(string: tr("donateLink"))
donateString.addAttribute(.link, value: "https://www.wireguard.com/donations/", range: NSRange(location: 0, length: donateString.length))
NSApp.activate(ignoringOtherApps: true)
NSApp.orderFrontStandardAboutPanel(options: [
.applicationVersion: appVersionString,
.version: "",
.credits: donateString
])
}
}
extension AppDelegate: StatusMenuWindowDelegate {
func manageTunnelsWindow() -> NSWindow {
func showManageTunnelsWindow(completion: ((NSWindow?) -> Void)?) {
guard let tunnelsManager = tunnelsManager else {
completion?(nil)
return
}
if manageTunnelsWindowObject == nil {
manageTunnelsRootVC = ManageTunnelsRootViewController(tunnelsManager: tunnelsManager!)
manageTunnelsRootVC = ManageTunnelsRootViewController(tunnelsManager: tunnelsManager)
let window = NSWindow(contentViewController: manageTunnelsRootVC!)
window.title = tr("macWindowTitleManageTunnels")
window.setContentSize(NSSize(width: 800, height: 480))
@ -81,7 +236,10 @@ extension AppDelegate: StatusMenuWindowDelegate {
manageTunnelsWindowObject = window
tunnelsTracker?.manageTunnelsRootVC = manageTunnelsRootVC
}
return manageTunnelsWindowObject!
setDockIconAndMainMenuVisibility(isVisible: true) { [weak manageTunnelsWindowObject] in
manageTunnelsWindowObject?.makeKeyAndOrderFront(self)
completion?(manageTunnelsWindowObject)
}
}
}

View File

@ -5,18 +5,6 @@ import Cocoa
class Application: NSApplication {
private let characterKeyCommands = [
"x": #selector(NSText.cut(_:)),
"c": #selector(NSText.copy(_:)),
"v": #selector(NSText.paste(_:)),
"z": #selector(UndoActionRespondable.undo(_:)),
"a": #selector(NSResponder.selectAll(_:)),
"Z": #selector(UndoActionRespondable.redo(_:)),
"w": #selector(NSWindow.performClose(_:)),
"m": #selector(NSWindow.performMiniaturize(_:)),
"q": #selector(AppDelegate.quit)
]
private var appDelegate: AppDelegate? //swiftlint:disable:this weak_delegate
override init() {
@ -28,21 +16,4 @@ class Application: NSApplication {
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func sendEvent(_ event: NSEvent) {
let modifierFlags = event.modifierFlags.rawValue & NSEvent.ModifierFlags.deviceIndependentFlagsMask.rawValue
if event.type == .keyDown,
(modifierFlags == NSEvent.ModifierFlags.command.rawValue || modifierFlags == NSEvent.ModifierFlags.command.rawValue | NSEvent.ModifierFlags.shift.rawValue),
let selector = characterKeyCommands[event.charactersIgnoringModifiers ?? ""] {
sendAction(selector, to: nil, from: self)
} else {
super.sendEvent(event)
}
}
}
@objc protocol UndoActionRespondable {
func undo(_ sender: AnyObject)
func redo(_ sender: AnyObject)
}

View File

@ -65,4 +65,4 @@
"version" : 1,
"author" : "xcode"
}
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 104 KiB

After

Width:  |  Height:  |  Size: 88 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.6 KiB

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 995 B

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 47 KiB

After

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 47 KiB

After

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.5 KiB

After

Width:  |  Height:  |  Size: 4.9 KiB

View File

@ -0,0 +1,28 @@
// SPDX-License-Identifier: MIT
// Copyright © 2018-2019 WireGuard LLC. All Rights Reserved.
import Cocoa
class LaunchedAtLoginDetector {
static let launchCode = "LaunchedByWireGuardLoginItemHelper"
static func isLaunchedAtLogin(openAppleEvent: NSAppleEventDescriptor) -> Bool {
guard isOpenEvent(openAppleEvent) else { return false }
guard let propData = openAppleEvent.paramDescriptor(forKeyword: keyAEPropData) else { return false }
return propData.stringValue == launchCode
}
static func isReopenedByLoginItemHelper(reopenAppleEvent: NSAppleEventDescriptor) -> Bool {
guard isReopenEvent(reopenAppleEvent) else { return false }
guard let propData = reopenAppleEvent.paramDescriptor(forKeyword: keyAEPropData) else { return false }
return propData.stringValue == launchCode
}
}
private func isOpenEvent(_ event: NSAppleEventDescriptor) -> Bool {
return event.eventClass == kCoreEventClass && event.eventID == kAEOpenApplication
}
private func isReopenEvent(_ event: NSAppleEventDescriptor) -> Bool {
return event.eventClass == kCoreEventClass && event.eventID == kAEReopenApplication
}

View File

@ -19,9 +19,9 @@
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<string>$(VERSION_NAME)</string>
<key>CFBundleVersion</key>
<string>1</string>
<string>$(VERSION_ID)</string>
<key>LSMinimumSystemVersion</key>
<string>$(MACOSX_DEPLOYMENT_TARGET)</string>
<key>NSHumanReadableCopyright</key>
@ -30,5 +30,7 @@
<string>NSApplication</string>
<key>LSBackgroundOnly</key>
<true/>
<key>com.wireguard.macos.app_id</key>
<string>$(APP_ID_MACOS)</string>
</dict>
</plist>

View File

@ -5,12 +5,13 @@
int main(int argc, char *argv[])
{
NSURL *bundleURL = [NSBundle.mainBundle bundleURL];
NSString *appIdInfoDictionaryKey = @"com.wireguard.macos.app_id";
NSString *appId = [NSBundle.mainBundle objectForInfoDictionaryKey:appIdInfoDictionaryKey];
// From <path>/WireGuard.app/Contents/Library/LoginItems/WireGuardLoginItemHelper.app, derive <path>/WireGuard.app
for (int i = 0; i < 4; ++i)
bundleURL = [bundleURL URLByDeletingLastPathComponent];
NSString *launchCode = @"LaunchedByWireGuardLoginItemHelper";
NSAppleEventDescriptor *paramDescriptor = [NSAppleEventDescriptor descriptorWithString:launchCode];
[NSWorkspace.sharedWorkspace launchApplication:[bundleURL path]];
[NSWorkspace.sharedWorkspace launchAppWithBundleIdentifier:appId options:NSWorkspaceLaunchWithoutActivation
additionalEventParamDescriptor:paramDescriptor launchIdentifier:NULL];
return 0;
}

View File

@ -0,0 +1,35 @@
// SPDX-License-Identifier: MIT
// Copyright © 2018-2019 WireGuard LLC. All Rights Reserved.
import Cocoa
class MacAppStoreUpdateDetector {
static func isUpdatingFromMacAppStore(quitAppleEvent: NSAppleEventDescriptor) -> Bool {
guard isQuitEvent(quitAppleEvent) else { return false }
guard let senderPIDDescriptor = quitAppleEvent.attributeDescriptor(forKeyword: keySenderPIDAttr) else { return false }
let pid = senderPIDDescriptor.int32Value
guard let executablePath = getExecutablePath(from: pid) else { return false }
wg_log(.debug, message: "aevt/quit Apple event received from: \(executablePath)")
if executablePath.hasPrefix("/System/Library/") {
let executableName = URL(fileURLWithPath: executablePath, isDirectory: false).lastPathComponent
return executableName == "com.apple.CommerceKit.StoreAEService"
}
return false
}
}
private func isQuitEvent(_ event: NSAppleEventDescriptor) -> Bool {
return event.eventClass == kCoreEventClass && event.eventID == kAEQuitApplication
}
private func getExecutablePath(from pid: pid_t) -> String? {
let bufferSize = Int(PATH_MAX)
var buffer = Data(capacity: bufferSize)
return buffer.withUnsafeMutableBytes { (ptr: UnsafeMutableRawBufferPointer) -> String? in
if let basePtr = ptr.baseAddress {
let byteCount = proc_pidpath(pid, basePtr, UInt32(bufferSize))
return byteCount > 0 ? String(cString: basePtr.bindMemory(to: CChar.self, capacity: bufferSize)) : nil
}
return nil
}
}

View File

@ -0,0 +1,130 @@
// SPDX-License-Identifier: MIT
// Copyright © 2018 WireGuard LLC. All Rights Reserved.
import Cocoa
// swiftlint:disable colon
class MainMenu: NSMenu {
init() {
super.init(title: "")
addSubmenu(createApplicationMenu())
addSubmenu(createFileMenu())
addSubmenu(createEditMenu())
addSubmenu(createTunnelMenu())
addSubmenu(createWindowMenu())
}
required init(coder decoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
private func addSubmenu(_ menu: NSMenu) {
let menuItem = self.addItem(withTitle: "", action: nil, keyEquivalent: "")
self.setSubmenu(menu, for: menuItem)
}
private func createApplicationMenu() -> NSMenu {
let menu = NSMenu()
let aboutMenuItem = menu.addItem(withTitle: tr("macMenuAbout"),
action: #selector(AppDelegate.aboutClicked), keyEquivalent: "")
aboutMenuItem.target = NSApp.delegate
menu.addItem(NSMenuItem.separator())
menu.addItem(withTitle: tr("macMenuViewLog"),
action: #selector(TunnelsListTableViewController.handleViewLogAction), keyEquivalent: "")
menu.addItem(NSMenuItem.separator())
let hideMenuItem = menu.addItem(withTitle: tr("macMenuHideApp"),
action: #selector(NSApplication.hide), keyEquivalent: "h")
hideMenuItem.target = NSApp
let hideOthersMenuItem = menu.addItem(withTitle: tr("macMenuHideOtherApps"),
action: #selector(NSApplication.hideOtherApplications), keyEquivalent: "h")
hideOthersMenuItem.keyEquivalentModifierMask = [.command, .option]
hideOthersMenuItem.target = NSApp
let showAllMenuItem = menu.addItem(withTitle: tr("macMenuShowAllApps"),
action: #selector(NSApplication.unhideAllApplications), keyEquivalent: "")
showAllMenuItem.target = NSApp
menu.addItem(NSMenuItem.separator())
menu.addItem(withTitle: tr("macMenuQuit"),
action: #selector(AppDelegate.confirmAndQuit), keyEquivalent: "q")
return menu
}
private func createFileMenu() -> NSMenu {
let menu = NSMenu(title: tr("macMenuFile"))
menu.addItem(withTitle: tr("macMenuAddEmptyTunnel"),
action: #selector(TunnelsListTableViewController.handleAddEmptyTunnelAction), keyEquivalent: "n")
menu.addItem(withTitle: tr("macMenuImportTunnels"),
action: #selector(TunnelsListTableViewController.handleImportTunnelAction), keyEquivalent: "o")
menu.addItem(NSMenuItem.separator())
menu.addItem(withTitle: tr("macMenuExportTunnels"),
action: #selector(TunnelsListTableViewController.handleExportTunnelsAction), keyEquivalent: "")
menu.addItem(NSMenuItem.separator())
menu.addItem(withTitle: tr("macMenuCloseWindow"), action: #selector(NSWindow.performClose(_:)), keyEquivalent:"w")
return menu
}
private func createEditMenu() -> NSMenu {
let menu = NSMenu(title: tr("macMenuEdit"))
menu.addItem(withTitle: "", action: #selector(UndoActionRespondable.undo(_:)), keyEquivalent:"z")
menu.addItem(withTitle: "", action: #selector(UndoActionRespondable.redo(_:)), keyEquivalent:"Z")
menu.addItem(NSMenuItem.separator())
menu.addItem(withTitle: tr("macMenuCut"), action: #selector(NSText.cut(_:)), keyEquivalent:"x")
menu.addItem(withTitle: tr("macMenuCopy"), action: #selector(NSText.copy(_:)), keyEquivalent:"c")
menu.addItem(withTitle: tr("macMenuPaste"), action: #selector(NSText.paste(_:)), keyEquivalent:"v")
menu.addItem(NSMenuItem.separator())
menu.addItem(withTitle: tr("macMenuSelectAll"), action: #selector(NSText.selectAll(_:)), keyEquivalent:"a")
return menu
}
private func createTunnelMenu() -> NSMenu {
let menu = NSMenu(title: tr("macMenuTunnel"))
menu.addItem(withTitle: tr("macMenuToggleStatus"), action: #selector(TunnelDetailTableViewController.handleToggleActiveStatusAction), keyEquivalent:"t")
menu.addItem(NSMenuItem.separator())
menu.addItem(withTitle: tr("macMenuEditTunnel"), action: #selector(TunnelDetailTableViewController.handleEditTunnelAction), keyEquivalent:"e")
menu.addItem(withTitle: tr("macMenuDeleteSelected"), action: #selector(TunnelsListTableViewController.handleRemoveTunnelAction), keyEquivalent: "")
return menu
}
private func createWindowMenu() -> NSMenu {
let menu = NSMenu(title: tr("macMenuWindow"))
menu.addItem(withTitle: tr("macMenuMinimize"), action: #selector(NSWindow.performMiniaturize(_:)), keyEquivalent:"m")
menu.addItem(withTitle: tr("macMenuZoom"), action: #selector(NSWindow.performZoom(_:)), keyEquivalent:"")
menu.addItem(NSMenuItem.separator())
let fullScreenMenuItem = menu.addItem(withTitle: "", action: #selector(NSWindow.toggleFullScreen(_:)), keyEquivalent:"f")
fullScreenMenuItem.keyEquivalentModifierMask = [.command, .control]
return menu
}
}
@objc protocol UndoActionRespondable {
func undo(_ sender: AnyObject)
func redo(_ sender: AnyObject)
}

View File

@ -4,7 +4,7 @@
import Cocoa
protocol StatusMenuWindowDelegate: class {
func manageTunnelsWindow() -> NSWindow
func showManageTunnelsWindow(completion: ((NSWindow?) -> Void)?)
}
class StatusMenu: NSMenu {
@ -127,8 +127,8 @@ class StatusMenu: NSMenu {
}
func addApplicationItems() {
let aboutItem = NSMenuItem(title: tr("macMenuAbout"), action: #selector(aboutClicked), keyEquivalent: "")
aboutItem.target = self
let aboutItem = NSMenuItem(title: tr("macMenuAbout"), action: #selector(AppDelegate.aboutClicked), keyEquivalent: "")
aboutItem.target = NSApp.delegate
addItem(aboutItem)
let quitItem = NSMenuItem(title: tr("macMenuQuit"), action: #selector(AppDelegate.quit), keyEquivalent: "")
quitItem.target = NSApp.delegate
@ -151,32 +151,16 @@ class StatusMenu: NSMenu {
}
@objc func manageTunnelsClicked() {
NSApp.activate(ignoringOtherApps: true)
guard let manageTunnelsWindow = windowDelegate?.manageTunnelsWindow() else { return }
manageTunnelsWindow.makeKeyAndOrderFront(self)
windowDelegate?.showManageTunnelsWindow(completion: nil)
}
@objc func importTunnelsClicked() {
NSApp.activate(ignoringOtherApps: true)
guard let manageTunnelsWindow = windowDelegate?.manageTunnelsWindow() else { return }
manageTunnelsWindow.makeKeyAndOrderFront(self)
ImportPanelPresenter.presentImportPanel(tunnelsManager: tunnelsManager, sourceVC: manageTunnelsWindow.contentViewController)
}
@objc func aboutClicked() {
var appVersion = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String ?? "Unknown"
if let appBuild = Bundle.main.infoDictionary?["CFBundleVersion"] as? String {
appVersion += " (\(appBuild))"
windowDelegate?.showManageTunnelsWindow { [weak self] manageTunnelsWindow in
guard let self = self else { return }
guard let manageTunnelsWindow = manageTunnelsWindow else { return }
ImportPanelPresenter.presentImportPanel(tunnelsManager: self.tunnelsManager,
sourceVC: manageTunnelsWindow.contentViewController)
}
let appVersionString = [
tr(format: "macAppVersion (%@)", appVersion),
tr(format: "macGoBackendVersion (%@)", WIREGUARD_GO_VERSION)
].joined(separator: "\n")
NSApp.activate(ignoringOtherApps: true)
NSApp.orderFrontStandardAboutPanel(options: [
.applicationVersion: appVersionString,
.version: ""
])
}
}
@ -184,7 +168,7 @@ extension StatusMenu {
func insertTunnelMenuItem(for tunnel: TunnelContainer, at tunnelIndex: Int) {
let menuItem = TunnelMenuItem(tunnel: tunnel, action: #selector(tunnelClicked(sender:)))
menuItem.target = self
menuItem.isHidden = !tunnel.isTunnelConfigurationAvailableInKeychain
menuItem.isHidden = !tunnel.isTunnelAvailableToUser
insertItem(menuItem, at: firstTunnelMenuItemIndex + tunnelIndex)
if numberOfTunnelMenuItems == 0 {
insertItem(NSMenuItem.separator(), at: firstTunnelMenuItemIndex + tunnelIndex + 1)

View File

@ -3,13 +3,25 @@
import Cocoa
class LogViewCell: NSTextField {
class LogViewCell: NSTableCellView {
var text: String = "" {
didSet { textField?.stringValue = text }
}
init() {
super.init(frame: .zero)
isSelectable = false
isEditable = false
isBordered = false
backgroundColor = .clear
let textField = NSTextField(wrappingLabelWithString: "")
addSubview(textField)
textField.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
textField.leadingAnchor.constraint(equalTo: self.leadingAnchor),
textField.trailingAnchor.constraint(equalTo: self.trailingAnchor),
textField.topAnchor.constraint(equalTo: self.topAnchor),
textField.bottomAnchor.constraint(equalTo: self.bottomAnchor)
])
self.textField = textField
}
required init?(coder: NSCoder) {
@ -17,19 +29,19 @@ class LogViewCell: NSTextField {
}
override func prepareForReuse() {
stringValue = ""
preferredMaxLayoutWidth = 0
textField?.stringValue = ""
}
}
class LogViewTimestampCell: LogViewCell {
override init() {
super.init()
maximumNumberOfLines = 1
lineBreakMode = .byClipping
preferredMaxLayoutWidth = 0
setContentCompressionResistancePriority(.defaultHigh, for: .vertical)
setContentHuggingPriority(.defaultLow, for: .vertical)
if let textField = textField {
textField.maximumNumberOfLines = 1
textField.lineBreakMode = .byClipping
textField.setContentCompressionResistancePriority(.defaultHigh, for: .vertical)
textField.setContentHuggingPriority(.defaultLow, for: .vertical)
}
}
required init?(coder: NSCoder) {
@ -40,10 +52,12 @@ class LogViewTimestampCell: LogViewCell {
class LogViewMessageCell: LogViewCell {
override init() {
super.init()
maximumNumberOfLines = 0
lineBreakMode = .byWordWrapping
setContentCompressionResistancePriority(.required, for: .vertical)
setContentHuggingPriority(.required, for: .vertical)
if let textField = textField {
textField.maximumNumberOfLines = 0
textField.lineBreakMode = .byWordWrapping
textField.setContentCompressionResistancePriority(.required, for: .vertical)
textField.setContentHuggingPriority(.required, for: .vertical)
}
}
required init?(coder: NSCoder) {

View File

@ -146,7 +146,8 @@ class LogViewController: NSViewController {
])
NSLayoutConstraint.activate([
containerView.widthAnchor.constraint(equalToConstant: 640),
containerView.widthAnchor.constraint(greaterThanOrEqualToConstant: 640),
containerView.widthAnchor.constraint(lessThanOrEqualToConstant: 1200),
containerView.heightAnchor.constraint(greaterThanOrEqualToConstant: 240)
])
@ -192,6 +193,10 @@ class LogViewController: NSViewController {
updateLogEntriesTimer = nil
}
override func viewWillAppear() {
view.window?.setFrameAutosaveName(NSWindow.FrameAutosaveName("LogWindow"))
}
override func viewWillDisappear() {
super.viewWillDisappear()
stopUpdatingLogEntries()
@ -220,7 +225,8 @@ class LogViewController: NSViewController {
return
}
DispatchQueue.main.async { [weak self] in
self?.dismiss(self)
guard let self = self else { return }
self.presentingViewController?.dismiss(self)
}
}
@ -228,7 +234,7 @@ class LogViewController: NSViewController {
}
@objc func closeClicked() {
dismiss(self)
presentingViewController?.dismiss(self)
}
@objc func copy(_ sender: Any?) {
@ -249,15 +255,20 @@ extension LogViewController: NSTableViewDelegate {
func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView? {
if LogColumn.time.isRepresenting(tableColumn: tableColumn) {
let cell: LogViewTimestampCell = tableView.dequeueReusableCell()
cell.stringValue = logEntries[row].timestamp
cell.text = logEntries[row].timestamp
return cell
} else if LogColumn.logMessage.isRepresenting(tableColumn: tableColumn) {
let cell: LogViewMessageCell = tableView.dequeueReusableCell()
cell.stringValue = logEntries[row].message
cell.preferredMaxLayoutWidth = tableColumn?.width ?? 0
cell.text = logEntries[row].message
return cell
} else {
fatalError()
}
}
}
extension LogViewController {
override func cancelOperation(_ sender: Any?) {
closeClicked()
}
}

View File

@ -81,7 +81,7 @@ extension ManageTunnelsRootViewController: TunnelsListTableViewControllerDelegat
assert(!tunnelIndices.isEmpty)
if tunnelIndices.count == 1 {
let tunnel = tunnelsManager.tunnel(at: tunnelIndices.first!)
if tunnel.isTunnelConfigurationAvailableInKeychain {
if tunnel.isTunnelAvailableToUser {
let tunnelDetailVC = TunnelDetailTableViewController(tunnelsManager: tunnelsManager, tunnel: tunnel)
setTunnelDetailContentVC(tunnelDetailVC)
self.tunnelDetailVC = tunnelDetailVC
@ -117,25 +117,19 @@ extension ManageTunnelsRootViewController: TunnelsListTableViewControllerDelegat
}
extension ManageTunnelsRootViewController {
override func keyDown(with event: NSEvent) {
let modifierFlags = event.modifierFlags.rawValue & NSEvent.ModifierFlags.deviceIndependentFlagsMask.rawValue
let isCmdOrCmdShiftDown = (modifierFlags == NSEvent.ModifierFlags.command.rawValue || modifierFlags == NSEvent.ModifierFlags.command.rawValue | NSEvent.ModifierFlags.shift.rawValue)
if event.specialKey == .delete {
tunnelsListVC?.handleRemoveTunnelAction()
} else if isCmdOrCmdShiftDown {
switch event.charactersIgnoringModifiers {
case "n":
tunnelsListVC?.handleAddEmptyTunnelAction()
case "o":
tunnelsListVC?.handleImportTunnelAction()
case "t":
tunnelDetailVC?.handleToggleActiveStatusAction()
case "e":
tunnelDetailVC?.handleEditTunnelAction()
default:
break
}
override func supplementalTarget(forAction action: Selector, sender: Any?) -> Any? {
switch action {
case #selector(TunnelsListTableViewController.handleViewLogAction),
#selector(TunnelsListTableViewController.handleAddEmptyTunnelAction),
#selector(TunnelsListTableViewController.handleImportTunnelAction),
#selector(TunnelsListTableViewController.handleExportTunnelsAction),
#selector(TunnelsListTableViewController.handleRemoveTunnelAction):
return tunnelsListVC
case #selector(TunnelDetailTableViewController.handleToggleActiveStatusAction),
#selector(TunnelDetailTableViewController.handleEditTunnelAction):
return tunnelDetailVC
default:
return super.supplementalTarget(forAction: action, sender: sender)
}
}
}

View File

@ -101,9 +101,14 @@ class TunnelDetailTableViewController: NSViewController {
super.init(nibName: nil, bundle: nil)
updateTableViewModelRowsBySection()
updateTableViewModelRows()
updateStatus()
statusObservationToken = tunnel.observe(\TunnelContainer.status) { [weak self] _, _ in
self?.updateStatus()
guard let self = self else { return }
if tunnel.status == .active {
self.startUpdatingRuntimeConfiguration()
} else if tunnel.status == .inactive {
self.reloadRuntimeConfiguration()
self.stopUpdatingRuntimeConfiguration()
}
}
}
@ -200,15 +205,6 @@ class TunnelDetailTableViewController: NSViewController {
tableViewModelRows = tableViewModelRowsBySection.flatMap { $0.filter { $0.isVisible }.map { $0.modelRow } }
}
func updateStatus() {
if tunnel.status == .active {
startUpdatingRuntimeConfiguration()
} else if tunnel.status == .inactive {
reloadRuntimeConfiguration()
stopUpdatingRuntimeConfiguration()
}
}
@objc func handleEditTunnelAction() {
PrivateDataConfirmation.confirmAccess(to: tr("macViewPrivateData")) { [weak self] in
guard let self = self else { return }
@ -227,6 +223,12 @@ class TunnelDetailTableViewController: NSViewController {
}
}
override func viewWillAppear() {
if tunnel.status == .active {
startUpdatingRuntimeConfiguration()
}
}
override func viewWillDisappear() {
super.viewWillDisappear()
if let tunnelEditVC = tunnelEditVC {
@ -503,7 +505,6 @@ extension TunnelDetailTableViewController: TunnelEditViewControllerDelegate {
onDemandViewModel = ActivateOnDemandViewModel(tunnel: tunnel)
updateTableViewModelRowsBySection()
updateTableViewModelRows()
updateStatus()
tableView.reloadData()
self.tunnelEditVC = nil
}

View File

@ -73,6 +73,8 @@ class TunnelEditViewController: NSViewController {
button.title = tr("macEditSave")
button.setButtonType(.momentaryPushIn)
button.bezelStyle = .rounded
button.keyEquivalent = "s"
button.keyEquivalentModifierMask = [.command]
return button
}()
@ -235,32 +237,34 @@ class TunnelEditViewController: NSViewController {
if let tunnel = tunnel {
// We're modifying an existing tunnel
tunnelsManager.modify(tunnel: tunnel, tunnelConfiguration: tunnelConfiguration, onDemandOption: onDemandOption) { [weak self] error in
self?.setUserInteractionEnabled(true)
guard let self = self else { return }
self.setUserInteractionEnabled(true)
if let error = error {
ErrorPresenter.showErrorAlert(error: error, from: self)
return
}
self?.dismiss(self)
self?.delegate?.tunnelSaved(tunnel: tunnel)
self.delegate?.tunnelSaved(tunnel: tunnel)
self.presentingViewController?.dismiss(self)
}
} else {
// We're creating a new tunnel
self.tunnelsManager.add(tunnelConfiguration: tunnelConfiguration, onDemandOption: onDemandOption) { [weak self] result in
self?.setUserInteractionEnabled(true)
if let error = result.error {
guard let self = self else { return }
self.setUserInteractionEnabled(true)
switch result {
case .failure(let error):
ErrorPresenter.showErrorAlert(error: error, from: self)
return
case .success(let tunnel):
self.delegate?.tunnelSaved(tunnel: tunnel)
self.presentingViewController?.dismiss(self)
}
let tunnel: TunnelContainer = result.value!
self?.dismiss(self)
self?.delegate?.tunnelSaved(tunnel: tunnel)
}
}
}
@objc func handleDiscardAction() {
delegate?.tunnelEditingCancelled()
dismiss(self)
presentingViewController?.dismiss(self)
}
func updateExcludePrivateIPsVisibility(singlePeerAllowedIPs: [String]?) {
@ -287,3 +291,9 @@ class TunnelEditViewController: NSViewController {
}
}
}
extension TunnelEditViewController {
override func cancelOperation(_ sender: Any?) {
handleDiscardAction()
}
}

View File

@ -12,7 +12,7 @@ class TunnelsListTableViewController: NSViewController {
let tunnelsManager: TunnelsManager
weak var delegate: TunnelsListTableViewControllerDelegate?
var isRemovingTunnels = false
var isRemovingTunnelsFromWithinTheApp = false
let tableView: NSTableView = {
let tableView = NSTableView()
@ -183,8 +183,10 @@ class TunnelsListTableViewController: NSViewController {
guard let self = self else { return }
self.selectTunnel(at: nextSelection)
let selectedTunnels = selectedTunnelIndices.map { self.tunnelsManager.tunnel(at: $0) }
self.isRemovingTunnelsFromWithinTheApp = true
self.tunnelsManager.removeMultiple(tunnels: selectedTunnels) { [weak self] error in
guard let self = self else { return }
self.isRemovingTunnelsFromWithinTheApp = false
defer { completion() }
if let error = error {
ErrorPresenter.showErrorAlert(error: error, from: self)
@ -281,9 +283,14 @@ extension TunnelsListTableViewController {
}
func tunnelRemoved(at index: Int) {
let selectedIndices = tableView.selectedRowIndexes
let isSingleSelectedTunnelBeingRemoved = selectedIndices.contains(index) && selectedIndices.count == 1
tableView.removeRows(at: IndexSet(integer: index), withAnimation: .slideLeft)
if tunnelsManager.numberOfTunnels() == 0 {
delegate?.tunnelsListEmpty()
} else if !isRemovingTunnelsFromWithinTheApp && isSingleSelectedTunnelBeingRemoved {
let newSelection = min(index, tunnelsManager.numberOfTunnels() - 1)
tableView.selectRowIndexes(IndexSet(integer: newSelection), byExtendingSelection: false)
}
}
}
@ -309,6 +316,23 @@ extension TunnelsListTableViewController: NSTableViewDelegate {
}
}
extension TunnelsListTableViewController {
override func keyDown(with event: NSEvent) {
if event.specialKey == .delete {
handleRemoveTunnelAction()
}
}
}
extension TunnelsListTableViewController: NSMenuItemValidation {
func validateMenuItem(_ menuItem: NSMenuItem) -> Bool {
if menuItem.action == #selector(TunnelsListTableViewController.handleRemoveTunnelAction) {
return !tableView.selectedRowIndexes.isEmpty
}
return true
}
}
class FillerButton: NSButton {
override var intrinsicContentSize: NSSize {
return NSSize(width: NSView.noIntrinsicMetric, height: NSView.noIntrinsicMetric)

View File

@ -5,3 +5,8 @@
#include "ringlogger.h"
#include "highlighter.h"
#include "key.h"
#import "TargetConditionals.h"
#if TARGET_OS_OSX
#include <libproc.h>
#endif

View File

@ -7,6 +7,7 @@ enum ZipArchiveError: WireGuardAppError {
case cantOpenInputZipFile
case cantOpenOutputZipFileForWriting
case badArchive
case noTunnelsInZipArchive
var alertText: AlertText {
switch self {
@ -16,6 +17,8 @@ enum ZipArchiveError: WireGuardAppError {
return (tr("alertCantOpenOutputZipFileForWritingTitle"), tr("alertCantOpenOutputZipFileForWritingMessage"))
case .badArchive:
return (tr("alertBadArchiveTitle"), tr("alertBadArchiveMessage"))
case .noTunnelsInZipArchive:
return (tr("alertNoTunnelsInImportedZipArchiveTitle"), tr("alertNoTunnelsInImportedZipArchiveMessage"))
}
}
}

View File

@ -3,16 +3,8 @@
import Foundation
enum ZipImporterError: WireGuardAppError {
case noTunnelsInZipArchive
var alertText: AlertText {
return (tr("alertNoTunnelsInImportedZipArchiveTitle"), tr("alertNoTunnelsInImportedZipArchiveMessage"))
}
}
class ZipImporter {
static func importConfigFiles(from url: URL, completion: @escaping (WireGuardResult<[TunnelConfiguration?]>) -> Void) {
static func importConfigFiles(from url: URL, completion: @escaping (Result<[TunnelConfiguration?], ZipArchiveError>) -> Void) {
DispatchQueue.global(qos: .userInitiated).async {
var unarchivedFiles: [(fileBaseName: String, contents: Data)]
do {
@ -28,9 +20,9 @@ class ZipImporter {
}
if unarchivedFiles.isEmpty {
throw ZipImporterError.noTunnelsInZipArchive
throw ZipArchiveError.noTunnelsInZipArchive
}
} catch let error as WireGuardAppError {
} catch let error as ZipArchiveError {
DispatchQueue.main.async { completion(.failure(error)) }
return
} catch {

View File

@ -143,18 +143,13 @@ class PacketTunnelProvider: NEPacketTunnelProvider {
private func pathUpdate(path: Network.NWPath) {
guard let handle = handle else { return }
wg_log(.debug, message: "Network change detected with \(path.status) route and interface order \(path.availableInterfaces)")
#if os(iOS)
if let packetTunnelSettingsGenerator = packetTunnelSettingsGenerator {
_ = packetTunnelSettingsGenerator.endpointUapiConfiguration().withGoString { return wgSetConfig(handle, $0) }
}
#endif
var interfaces = path.availableInterfaces
if let ifname = ifname {
interfaces = interfaces.filter { $0.name != ifname }
}
if let ifscope = interfaces.first?.index {
wgBindInterfaceScope(handle, Int32(ifscope))
}
wgBumpSockets(handle)
}
}

View File

@ -14,60 +14,37 @@ LIPO ?= lipo
DESTDIR ?= $(CONFIGURATION_BUILD_DIR)
BUILDDIR ?= $(CONFIGURATION_TEMP_DIR)/wireguard-go-bridge
UPSTREAM_FILES := $(filter-out %/main.go %/queueconstants.go,$(wildcard ../wireguard-go/*/*.go) $(wildcard ../wireguard-go/*.go)) ../wireguard-go/go.mod ../wireguard-go/go.sum
DOWNSTREAM_FILES := $(wildcard src/*.go) $(wildcard src/*/*.go)
CFLAGS_PREFIX := $(if $(DEPLOYMENT_TARGET_CLANG_FLAG_NAME),-$(DEPLOYMENT_TARGET_CLANG_FLAG_NAME)=$($(DEPLOYMENT_TARGET_CLANG_ENV_NAME)),) -Wno-unused-command-line-argument -isysroot $(SDKROOT) -arch
GOARCH_arm64 := arm64
GOARCH_armv7 := arm
GOARCH_x86_64 := amd64
export GOOS := darwin
export CGO_ENABLED := 1
build: $(DESTDIR)/libwg-go.a
version-header: $(DESTDIR)/wireguard-go-version.h
GOBUILDVERSION_NEEDED := go version go1.12.1 darwin/amd64
GOBUILDVERSION_CURRENT := $(shell go version 2>/dev/null)
export REAL_GOROOT := $(shell go env GOROOT 2>/dev/null)
REAL_GOROOT := $(shell go env GOROOT 2>/dev/null)
export GOROOT := $(BUILDDIR)/goroot
export GOPATH := $(BUILDDIR)/gopath
export PATH := $(GOPATH)/bin:$(PATH)
GOBUILDVERSION_FAKE := $(shell $(GOROOT)/bin/go version 2>/dev/null)
ifneq ($(GOBUILDVERSION_NEEDED),$(GOBUILDVERSION_CURRENT))
$(error This requires $(GOBUILDVERSION_NEEDED))
endif
ifneq ($(GOBUILDVERSION_NEEDED),$(GOBUILDVERSION_FAKE))
$(shell rm -f $(GOROOT)/.prepared)
endif
$(GOROOT)/.prepared:
[ -n "$(REAL_GOROOT)" ]
mkdir -p "$(GOROOT)"
rsync -a --delete --exclude=pkg/obj/go-build "$(REAL_GOROOT)/" "$(GOROOT)/"
cat goruntime-*.diff | patch -p1 -f -N -r- -d "$(GOROOT)"
rm -rf "$(GOPATH)/pkg/mod"
go get -d -tags ios; chmod -fR +w "$(GOPATH)/pkg/mod"
for sys in "$(GOPATH)/pkg/mod/golang.org/x/sys@"*; do cat sys-unix-*.diff | patch -p1 -f -N -r- -d "$$sys"; done
patch -p1 -f -N -r- -d "$(GOROOT)" < goruntime-boottime-over-monotonic.diff
touch "$@"
$(shell test "$$(cat "$(BUILDDIR)/.gobuildversion" 2>/dev/null)" = "$(GOBUILDVERSION_CURRENT)" || rm -f "$(DESTDIR)/libwg-go.a")
define libwg-go-a
$(BUILDDIR)/libwg-go-$(1).a: $(GOROOT)/.prepared
CGO_CFLAGS="$(CFLAGS_PREFIX) $(ARCH)" \
CGO_LDFLAGS="$(CFLAGS_PREFIX) $(ARCH)" \
GOARCH="$(GOARCH_$(1))" \
go build -tags ios -ldflags=-w -v -o "$(BUILDDIR)/libwg-go-$(1).a" -buildmode c-archive && go version > "$(BUILDDIR)/.gobuildversion"; \
chmod -fR +w "$(GOPATH)/pkg/mod"; \
ret=$$$$?; \
rm -f "$(BUILDDIR)/libwg-go-$(1).h"; \
exit $$$$ret
$(BUILDDIR)/libwg-go-$(1).a: export CGO_ENABLED := 1
$(BUILDDIR)/libwg-go-$(1).a: export CGO_CFLAGS := $(CFLAGS_PREFIX) $(ARCH)
$(BUILDDIR)/libwg-go-$(1).a: export CGO_LDFLAGS := $(CFLAGS_PREFIX) $(ARCH)
$(BUILDDIR)/libwg-go-$(1).a: export GOOS := darwin
$(BUILDDIR)/libwg-go-$(1).a: export GOARCH := $(GOARCH_$(1))
$(BUILDDIR)/libwg-go-$(1).a: $(GOROOT)/.prepared go.mod
go build -tags ios -ldflags=-w -trimpath -v -o "$(BUILDDIR)/libwg-go-$(1).a" -buildmode c-archive
rm -f "$(BUILDDIR)/libwg-go-$(1).h"
endef
$(foreach ARCH,$(ARCHS),$(eval $(call libwg-go-a,$(ARCH))))
$(DESTDIR)/wireguard-go-version.h: go.mod $(GOROOT)/.prepared
wggo="$(GOPATH)/pkg/mod/$$(sed -n 's/.*\(golang\.zx2c4\.com\/wireguard\) \(.*\)$$/\1@\2/p' go.mod)"; \
sed -n 's/.*WireGuardGoVersion = "\(.*\)"/#define WIREGUARD_GO_VERSION "\1"/p' "$$wggo/device/version.go" > "$@"
$(DESTDIR)/wireguard-go-version.h: $(GOROOT)/.prepared go.mod
go list -m golang.zx2c4.com/wireguard | sed -n 's/.*v\([0-9.]*\).*/#define WIREGUARD_GO_VERSION "\1"/p' > "$@"
$(DESTDIR)/libwg-go.a: $(foreach ARCH,$(ARCHS),$(BUILDDIR)/libwg-go-$(ARCH).a)
@mkdir -vp "$(DESTDIR)"

View File

@ -165,22 +165,14 @@ func wgGetConfig(tunnelHandle int32) *C.char {
writer.Flush()
return C.CString(settings.String())
}
//export wgBindInterfaceScope
func wgBindInterfaceScope(tunnelHandle int32, ifscope int32) {
//export wgBumpSockets
func wgBumpSockets(tunnelHandle int32) {
device, ok := tunnelHandles[tunnelHandle]
if !ok {
return
}
device.Info.Printf("Binding sockets to interface %d\n", ifscope)
err := device.BindSocketToInterface4(uint32(ifscope))
if err != nil {
device.Error.Printf("Unable to bind v4 socket to interface:", err)
}
err = device.BindSocketToInterface6(uint32(ifscope))
if err != nil {
device.Error.Printf("Unable to bind v6 socket to interface:", err)
}
device.BindUpdate()
device.SendKeepalivesToPeersWithCurrentKeypair()
}
//export wgVersion

View File

@ -1,8 +1,9 @@
module golang.zx2c4.com/wireguard/ios
go 1.12
go 1.13
require (
golang.org/x/sys v0.0.0-20190405154228-4b34438f7a67
golang.zx2c4.com/wireguard v0.0.0-20190409083948-18fa27047265
golang.org/x/net v0.0.0-20191007182048-72f939374954 // indirect
golang.org/x/sys v0.0.0-20191008105621-543471e840be
golang.zx2c4.com/wireguard v0.0.20190909-0.20191008144818-222f0f8000e8
)

View File

@ -1,13 +1,20 @@
github.com/Microsoft/go-winio v0.4.12/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190320223903-b7391e95e576 h1:aUX/1G2gFSs4AsJJg2cL3HuoRhCSCz733FE5GUSuaT4=
golang.org/x/crypto v0.0.0-20190320223903-b7391e95e576/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/net v0.0.0-20190320064053-1272bf9dcd53 h1:kcXqo9vE6fsZY5X5Rd7R1l7fTgnWaDCVmln65REefiE=
golang.org/x/net v0.0.0-20190320064053-1272bf9dcd53/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/crypto v0.0.0-20191002192127-34f69633bfdc h1:c0o/qxkaO2LF5t6fQrT4b5hzyggAkLLlCUjqfRxd8Q4=
golang.org/x/crypto v0.0.0-20191002192127-34f69633bfdc/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20191003171128-d98b1b443823 h1:Ypyv6BNJh07T1pUSrehkLemqPKXhus2MkfktJ91kRh4=
golang.org/x/net v0.0.0-20191003171128-d98b1b443823/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20191007182048-72f939374954 h1:JGZucVF/L/TotR719NbujzadOZ2AgnYlqphQGHDCKaU=
golang.org/x/net v0.0.0-20191007182048-72f939374954/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190321052220-f7bb7a8bee54/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190405154228-4b34438f7a67 h1:1Fzlr8kkDLQwqMP8GxrhptBLqZG/EDpiATneiZHY998=
golang.org/x/sys v0.0.0-20190405154228-4b34438f7a67/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191003212358-c178f38b412c h1:6Zx7DRlKXf79yfxuQ/7GqV3w2y7aDsk6bGg0MzF5RVU=
golang.org/x/sys v0.0.0-20191003212358-c178f38b412c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191008105621-543471e840be h1:QAcqgptGM8IQBC9K/RC4o+O9YmqEm0diQn9QmZw/0mU=
golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.zx2c4.com/wireguard v0.0.0-20190409083948-18fa27047265 h1:ujM5BaP4MD/2MJZ1n7pmw6IIsyyS7SyPl0fDefnx/2o=
golang.zx2c4.com/wireguard v0.0.0-20190409083948-18fa27047265/go.mod h1:u0Cl3X+pyWdXaax3S583DQrnGDuTASO0QdlKFrs8r/8=
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.zx2c4.com/wireguard v0.0.20190909-0.20191008144818-222f0f8000e8 h1:BqfQHKZLrdq0j5Z/R9coISbr1nYcSE+3BdyF5LidO+g=
golang.zx2c4.com/wireguard v0.0.20190909-0.20191008144818-222f0f8000e8/go.mod h1:P2HsVp8SKwZEufsnezXZA4GRX/T49/HlU7DGuelXsU4=

View File

@ -1,4 +1,4 @@
From 74523c5a12d37fa792e77a252bcc569484c3d41a Mon Sep 17 00:00:00 2001
From 04f5695b83cd221e99e9fa6171b57e45177d5ad3 Mon Sep 17 00:00:00 2001
From: "Jason A. Donenfeld" <Jason@zx2c4.com>
Date: Wed, 27 Feb 2019 05:33:01 +0100
Subject: [PATCH] runtime: use libc_mach_continuous_time in nanotime on Darwin
@ -18,10 +18,10 @@ Fixes #24595
5 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/src/runtime/sys_darwin.go b/src/runtime/sys_darwin.go
index f34ac88352..416fcb673f 100644
index 376f76dbc5..a0677a83f6 100644
--- a/src/runtime/sys_darwin.go
+++ b/src/runtime/sys_darwin.go
@@ -403,7 +403,7 @@ func closeonexec(fd int32) {
@@ -431,7 +431,7 @@ func setNonblock(fd int32) {
//go:cgo_import_dynamic libc_usleep usleep "/usr/lib/libSystem.B.dylib"
//go:cgo_import_dynamic libc_mach_timebase_info mach_timebase_info "/usr/lib/libSystem.B.dylib"
@ -31,10 +31,10 @@ index f34ac88352..416fcb673f 100644
//go:cgo_import_dynamic libc_sigaction sigaction "/usr/lib/libSystem.B.dylib"
//go:cgo_import_dynamic libc_pthread_sigmask pthread_sigmask "/usr/lib/libSystem.B.dylib"
diff --git a/src/runtime/sys_darwin_386.s b/src/runtime/sys_darwin_386.s
index 1bc1a63c28..34a3561350 100644
index e653c54f61..5a43fcbdc1 100644
--- a/src/runtime/sys_darwin_386.s
+++ b/src/runtime/sys_darwin_386.s
@@ -184,7 +184,7 @@ TEXT runtime·nanotime_trampoline(SB),NOSPLIT,$0
@@ -199,7 +199,7 @@ TEXT runtime·nanotime_trampoline(SB),NOSPLIT,$0
PUSHL BP
MOVL SP, BP
SUBL $8+(machTimebaseInfo__size+15)/16*16, SP
@ -44,10 +44,10 @@ index 1bc1a63c28..34a3561350 100644
MOVL AX, 0(CX)
MOVL DX, 4(CX)
diff --git a/src/runtime/sys_darwin_amd64.s b/src/runtime/sys_darwin_amd64.s
index f99cb00ab8..8b99316983 100644
index 87c8db8c82..f962f24339 100644
--- a/src/runtime/sys_darwin_amd64.s
+++ b/src/runtime/sys_darwin_amd64.s
@@ -86,7 +86,7 @@ TEXT runtime·nanotime_trampoline(SB),NOSPLIT,$0
@@ -97,7 +97,7 @@ TEXT runtime·nanotime_trampoline(SB),NOSPLIT,$0
PUSHQ BP
MOVQ SP, BP
MOVQ DI, BX
@ -57,10 +57,10 @@ index f99cb00ab8..8b99316983 100644
MOVL timebase<>+machTimebaseInfo_numer(SB), SI
MOVL timebase<>+machTimebaseInfo_denom(SB), DI // atomic read
diff --git a/src/runtime/sys_darwin_arm.s b/src/runtime/sys_darwin_arm.s
index 54c7afbf34..a4f06fdb85 100644
index 996f8028a3..5bd34b51be 100644
--- a/src/runtime/sys_darwin_arm.s
+++ b/src/runtime/sys_darwin_arm.s
@@ -118,7 +118,7 @@ GLOBL timebase<>(SB),NOPTR,$(machTimebaseInfo__size)
@@ -126,7 +126,7 @@ GLOBL timebase<>(SB),NOPTR,$(machTimebaseInfo__size)
TEXT runtime·nanotime_trampoline(SB),NOSPLIT,$0
MOVW R0, R8
@ -70,10 +70,10 @@ index 54c7afbf34..a4f06fdb85 100644
MOVW R1, 4(R8)
MOVW timebase<>+machTimebaseInfo_numer(SB), R6
diff --git a/src/runtime/sys_darwin_arm64.s b/src/runtime/sys_darwin_arm64.s
index 29951d8ad7..cdaf0a630e 100644
index ac3ca74f63..5e91540f94 100644
--- a/src/runtime/sys_darwin_arm64.s
+++ b/src/runtime/sys_darwin_arm64.s
@@ -113,7 +113,7 @@ GLOBL timebase<>(SB),NOPTR,$(machTimebaseInfo__size)
@@ -121,7 +121,7 @@ GLOBL timebase<>(SB),NOPTR,$(machTimebaseInfo__size)
TEXT runtime·nanotime_trampoline(SB),NOSPLIT,$40
MOVD R0, R19
@ -83,5 +83,5 @@ index 29951d8ad7..cdaf0a630e 100644
MOVW timebase<>+machTimebaseInfo_numer(SB), R20
MOVD $timebase<>+machTimebaseInfo_denom(SB), R21
--
2.20.1
2.23.0

View File

@ -1,279 +0,0 @@
From bc77ad792117829909eeeca3aa492d6f292d004d Mon Sep 17 00:00:00 2001
From: "Jason A. Donenfeld" <Jason@zx2c4.com>
Date: Tue, 19 Mar 2019 13:55:44 -0600
Subject: [PATCH] syscall: do not link against ___getdirentries64
---
.../x/sys/unix/syscall_darwin_386.go | 5 ++++-
.../x/sys/unix/syscall_darwin_amd64.go | 5 ++++-
.../x/sys/unix/zsyscall_darwin_386.go | 22 -------------------
.../x/sys/unix/zsyscall_darwin_386.s | 2 --
.../x/sys/unix/zsyscall_darwin_amd64.go | 22 -------------------
.../x/sys/unix/zsyscall_darwin_amd64.s | 2 --
src/syscall/syscall_darwin_386.go | 5 ++++-
src/syscall/syscall_darwin_amd64.go | 5 ++++-
src/syscall/zsyscall_darwin_386.go | 20 -----------------
src/syscall/zsyscall_darwin_386.s | 2 --
src/syscall/zsyscall_darwin_amd64.go | 20 -----------------
src/syscall/zsyscall_darwin_amd64.s | 2 --
12 files changed, 16 insertions(+), 96 deletions(-)
diff --git a/src/cmd/vendor/golang.org/x/sys/unix/syscall_darwin_386.go b/src/cmd/vendor/golang.org/x/sys/unix/syscall_darwin_386.go
index 489726fa9b..900dd7c91f 100644
--- a/src/cmd/vendor/golang.org/x/sys/unix/syscall_darwin_386.go
+++ b/src/cmd/vendor/golang.org/x/sys/unix/syscall_darwin_386.go
@@ -56,8 +56,11 @@ const SYS___SYSCTL = SYS_SYSCTL
//sys Fstat(fd int, stat *Stat_t) (err error) = SYS_FSTAT64
//sys Fstatat(fd int, path string, stat *Stat_t, flags int) (err error) = SYS_FSTATAT64
//sys Fstatfs(fd int, stat *Statfs_t) (err error) = SYS_FSTATFS64
-//sys Getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) = SYS_GETDIRENTRIES64
//sys getfsstat(buf unsafe.Pointer, size uintptr, flags int) (n int, err error) = SYS_GETFSSTAT64
//sys Lstat(path string, stat *Stat_t) (err error) = SYS_LSTAT64
//sys Stat(path string, stat *Stat_t) (err error) = SYS_STAT64
//sys Statfs(path string, stat *Statfs_t) (err error) = SYS_STATFS64
+
+func Getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) {
+ return 0, ENOSYS
+}
diff --git a/src/cmd/vendor/golang.org/x/sys/unix/syscall_darwin_amd64.go b/src/cmd/vendor/golang.org/x/sys/unix/syscall_darwin_amd64.go
index 914b89bde5..95e245fff7 100644
--- a/src/cmd/vendor/golang.org/x/sys/unix/syscall_darwin_amd64.go
+++ b/src/cmd/vendor/golang.org/x/sys/unix/syscall_darwin_amd64.go
@@ -56,8 +56,11 @@ const SYS___SYSCTL = SYS_SYSCTL
//sys Fstat(fd int, stat *Stat_t) (err error) = SYS_FSTAT64
//sys Fstatat(fd int, path string, stat *Stat_t, flags int) (err error) = SYS_FSTATAT64
//sys Fstatfs(fd int, stat *Statfs_t) (err error) = SYS_FSTATFS64
-//sys Getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) = SYS_GETDIRENTRIES64
//sys getfsstat(buf unsafe.Pointer, size uintptr, flags int) (n int, err error) = SYS_GETFSSTAT64
//sys Lstat(path string, stat *Stat_t) (err error) = SYS_LSTAT64
//sys Stat(path string, stat *Stat_t) (err error) = SYS_STAT64
//sys Statfs(path string, stat *Statfs_t) (err error) = SYS_STATFS64
+
+func Getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) {
+ return 0, ENOSYS
+}
diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_darwin_386.go b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_darwin_386.go
index 23346dc68f..db4f1eaf1c 100644
--- a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_darwin_386.go
+++ b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_darwin_386.go
@@ -2408,28 +2408,6 @@ func libc_fstatfs64_trampoline()
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-func Getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) {
- var _p0 unsafe.Pointer
- if len(buf) > 0 {
- _p0 = unsafe.Pointer(&buf[0])
- } else {
- _p0 = unsafe.Pointer(&_zero)
- }
- r0, _, e1 := syscall_syscall6(funcPC(libc___getdirentries64_trampoline), uintptr(fd), uintptr(_p0), uintptr(len(buf)), uintptr(unsafe.Pointer(basep)), 0, 0)
- n = int(r0)
- if e1 != 0 {
- err = errnoErr(e1)
- }
- return
-}
-
-func libc___getdirentries64_trampoline()
-
-//go:linkname libc___getdirentries64 libc___getdirentries64
-//go:cgo_import_dynamic libc___getdirentries64 __getdirentries64 "/usr/lib/libSystem.B.dylib"
-
-// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-
func getfsstat(buf unsafe.Pointer, size uintptr, flags int) (n int, err error) {
r0, _, e1 := syscall_syscall(funcPC(libc_getfsstat64_trampoline), uintptr(buf), uintptr(size), uintptr(flags))
n = int(r0)
diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_darwin_386.s b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_darwin_386.s
index 37b85b4f61..6165f70e33 100644
--- a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_darwin_386.s
+++ b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_darwin_386.s
@@ -272,8 +272,6 @@ TEXT ·libc_fstatat64_trampoline(SB),NOSPLIT,$0-0
JMP libc_fstatat64(SB)
TEXT ·libc_fstatfs64_trampoline(SB),NOSPLIT,$0-0
JMP libc_fstatfs64(SB)
-TEXT ·libc___getdirentries64_trampoline(SB),NOSPLIT,$0-0
- JMP libc___getdirentries64(SB)
TEXT ·libc_getfsstat64_trampoline(SB),NOSPLIT,$0-0
JMP libc_getfsstat64(SB)
TEXT ·libc_lstat64_trampoline(SB),NOSPLIT,$0-0
diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.go b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.go
index b50178d679..dea5dee75e 100644
--- a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.go
+++ b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.go
@@ -2408,28 +2408,6 @@ func libc_fstatfs64_trampoline()
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-func Getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) {
- var _p0 unsafe.Pointer
- if len(buf) > 0 {
- _p0 = unsafe.Pointer(&buf[0])
- } else {
- _p0 = unsafe.Pointer(&_zero)
- }
- r0, _, e1 := syscall_syscall6(funcPC(libc___getdirentries64_trampoline), uintptr(fd), uintptr(_p0), uintptr(len(buf)), uintptr(unsafe.Pointer(basep)), 0, 0)
- n = int(r0)
- if e1 != 0 {
- err = errnoErr(e1)
- }
- return
-}
-
-func libc___getdirentries64_trampoline()
-
-//go:linkname libc___getdirentries64 libc___getdirentries64
-//go:cgo_import_dynamic libc___getdirentries64 __getdirentries64 "/usr/lib/libSystem.B.dylib"
-
-// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-
func getfsstat(buf unsafe.Pointer, size uintptr, flags int) (n int, err error) {
r0, _, e1 := syscall_syscall(funcPC(libc_getfsstat64_trampoline), uintptr(buf), uintptr(size), uintptr(flags))
n = int(r0)
diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.s b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.s
index da9b900a8c..f1e2d7e9a4 100644
--- a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.s
+++ b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.s
@@ -272,8 +272,6 @@ TEXT ·libc_fstatat64_trampoline(SB),NOSPLIT,$0-0
JMP libc_fstatat64(SB)
TEXT ·libc_fstatfs64_trampoline(SB),NOSPLIT,$0-0
JMP libc_fstatfs64(SB)
-TEXT ·libc___getdirentries64_trampoline(SB),NOSPLIT,$0-0
- JMP libc___getdirentries64(SB)
TEXT ·libc_getfsstat64_trampoline(SB),NOSPLIT,$0-0
JMP libc_getfsstat64(SB)
TEXT ·libc_lstat64_trampoline(SB),NOSPLIT,$0-0
diff --git a/src/syscall/syscall_darwin_386.go b/src/syscall/syscall_darwin_386.go
index 045ebc726b..826d76f569 100644
--- a/src/syscall/syscall_darwin_386.go
+++ b/src/syscall/syscall_darwin_386.go
@@ -16,7 +16,6 @@ func setTimeval(sec, usec int64) Timeval {
//sys Fstat(fd int, stat *Stat_t) (err error) = SYS_fstat64
//sys Fstatfs(fd int, stat *Statfs_t) (err error) = SYS_fstatfs64
-//sys Getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) = SYS___getdirentries64
//sysnb Gettimeofday(tp *Timeval) (err error)
//sys Lstat(path string, stat *Stat_t) (err error) = SYS_lstat64
//sys Stat(path string, stat *Stat_t) (err error) = SYS_stat64
@@ -63,3 +62,7 @@ func libc_sendfile_trampoline()
func syscall9(fn, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, err Errno)
func Syscall9(num, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, err Errno) // sic
+
+func Getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) {
+ return 0, ENOSYS
+}
diff --git a/src/syscall/syscall_darwin_amd64.go b/src/syscall/syscall_darwin_amd64.go
index 7b6493bf9f..3868790049 100644
--- a/src/syscall/syscall_darwin_amd64.go
+++ b/src/syscall/syscall_darwin_amd64.go
@@ -16,7 +16,6 @@ func setTimeval(sec, usec int64) Timeval {
//sys Fstat(fd int, stat *Stat_t) (err error) = SYS_fstat64
//sys Fstatfs(fd int, stat *Statfs_t) (err error) = SYS_fstatfs64
-//sys Getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) = SYS___getdirentries64
//sysnb Gettimeofday(tp *Timeval) (err error)
//sys Lstat(path string, stat *Stat_t) (err error) = SYS_lstat64
//sys Stat(path string, stat *Stat_t) (err error) = SYS_stat64
@@ -63,3 +62,7 @@ func libc_sendfile_trampoline()
func syscallX(fn, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno)
func Syscall9(trap, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, err Errno)
+
+func Getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) {
+ return 0, ENOSYS
+}
diff --git a/src/syscall/zsyscall_darwin_386.go b/src/syscall/zsyscall_darwin_386.go
index 758ff7b129..a666a1f65e 100644
--- a/src/syscall/zsyscall_darwin_386.go
+++ b/src/syscall/zsyscall_darwin_386.go
@@ -1845,27 +1845,7 @@ func libc_fstatfs64_trampoline()
//go:linkname libc_fstatfs64 libc_fstatfs64
//go:cgo_import_dynamic libc_fstatfs64 fstatfs64 "/usr/lib/libSystem.B.dylib"
-// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-
-func Getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) {
- var _p0 unsafe.Pointer
- if len(buf) > 0 {
- _p0 = unsafe.Pointer(&buf[0])
- } else {
- _p0 = unsafe.Pointer(&_zero)
- }
- r0, _, e1 := syscall6(funcPC(libc___getdirentries64_trampoline), uintptr(fd), uintptr(_p0), uintptr(len(buf)), uintptr(unsafe.Pointer(basep)), 0, 0)
- n = int(r0)
- if e1 != 0 {
- err = errnoErr(e1)
- }
- return
-}
-
-func libc___getdirentries64_trampoline()
-//go:linkname libc___getdirentries64 libc___getdirentries64
-//go:cgo_import_dynamic libc___getdirentries64 __getdirentries64 "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Gettimeofday(tp *Timeval) (err error) {
diff --git a/src/syscall/zsyscall_darwin_386.s b/src/syscall/zsyscall_darwin_386.s
index a688192501..a5af9b64b9 100644
--- a/src/syscall/zsyscall_darwin_386.s
+++ b/src/syscall/zsyscall_darwin_386.s
@@ -235,8 +235,6 @@ TEXT ·libc_fstat64_trampoline(SB),NOSPLIT,$0-0
JMP libc_fstat64(SB)
TEXT ·libc_fstatfs64_trampoline(SB),NOSPLIT,$0-0
JMP libc_fstatfs64(SB)
-TEXT ·libc___getdirentries64_trampoline(SB),NOSPLIT,$0-0
- JMP libc___getdirentries64(SB)
TEXT ·libc_gettimeofday_trampoline(SB),NOSPLIT,$0-0
JMP libc_gettimeofday(SB)
TEXT ·libc_lstat64_trampoline(SB),NOSPLIT,$0-0
diff --git a/src/syscall/zsyscall_darwin_amd64.go b/src/syscall/zsyscall_darwin_amd64.go
index afc3d72d8d..bb87aef1f9 100644
--- a/src/syscall/zsyscall_darwin_amd64.go
+++ b/src/syscall/zsyscall_darwin_amd64.go
@@ -1845,27 +1845,7 @@ func libc_fstatfs64_trampoline()
//go:linkname libc_fstatfs64 libc_fstatfs64
//go:cgo_import_dynamic libc_fstatfs64 fstatfs64 "/usr/lib/libSystem.B.dylib"
-// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-
-func Getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) {
- var _p0 unsafe.Pointer
- if len(buf) > 0 {
- _p0 = unsafe.Pointer(&buf[0])
- } else {
- _p0 = unsafe.Pointer(&_zero)
- }
- r0, _, e1 := syscall6(funcPC(libc___getdirentries64_trampoline), uintptr(fd), uintptr(_p0), uintptr(len(buf)), uintptr(unsafe.Pointer(basep)), 0, 0)
- n = int(r0)
- if e1 != 0 {
- err = errnoErr(e1)
- }
- return
-}
-
-func libc___getdirentries64_trampoline()
-//go:linkname libc___getdirentries64 libc___getdirentries64
-//go:cgo_import_dynamic libc___getdirentries64 __getdirentries64 "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
func Gettimeofday(tp *Timeval) (err error) {
diff --git a/src/syscall/zsyscall_darwin_amd64.s b/src/syscall/zsyscall_darwin_amd64.s
index 21ab38e3ee..409320dea5 100644
--- a/src/syscall/zsyscall_darwin_amd64.s
+++ b/src/syscall/zsyscall_darwin_amd64.s
@@ -235,8 +235,6 @@ TEXT ·libc_fstat64_trampoline(SB),NOSPLIT,$0-0
JMP libc_fstat64(SB)
TEXT ·libc_fstatfs64_trampoline(SB),NOSPLIT,$0-0
JMP libc_fstatfs64(SB)
-TEXT ·libc___getdirentries64_trampoline(SB),NOSPLIT,$0-0
- JMP libc___getdirentries64(SB)
TEXT ·libc_gettimeofday_trampoline(SB),NOSPLIT,$0-0
JMP libc_gettimeofday(SB)
TEXT ·libc_lstat64_trampoline(SB),NOSPLIT,$0-0
--
2.21.0

View File

@ -1,143 +0,0 @@
From 3efe4df9b66d4af86363e37768ea469abb8f7bdc Mon Sep 17 00:00:00 2001
From: "Jason A. Donenfeld" <Jason@zx2c4.com>
Date: Tue, 19 Mar 2019 14:01:21 -0600
Subject: [PATCH] unix: do not link against ___getdirentries64
---
unix/syscall_darwin_386.go | 5 ++++-
unix/syscall_darwin_amd64.go | 5 ++++-
unix/zsyscall_darwin_386.go | 22 ----------------------
unix/zsyscall_darwin_386.s | 2 --
unix/zsyscall_darwin_amd64.go | 22 ----------------------
unix/zsyscall_darwin_amd64.s | 2 --
6 files changed, 8 insertions(+), 50 deletions(-)
diff --git a/unix/syscall_darwin_386.go b/unix/syscall_darwin_386.go
index 489726f..900dd7c 100644
--- a/unix/syscall_darwin_386.go
+++ b/unix/syscall_darwin_386.go
@@ -56,8 +56,11 @@ const SYS___SYSCTL = SYS_SYSCTL
//sys Fstat(fd int, stat *Stat_t) (err error) = SYS_FSTAT64
//sys Fstatat(fd int, path string, stat *Stat_t, flags int) (err error) = SYS_FSTATAT64
//sys Fstatfs(fd int, stat *Statfs_t) (err error) = SYS_FSTATFS64
-//sys Getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) = SYS_GETDIRENTRIES64
//sys getfsstat(buf unsafe.Pointer, size uintptr, flags int) (n int, err error) = SYS_GETFSSTAT64
//sys Lstat(path string, stat *Stat_t) (err error) = SYS_LSTAT64
//sys Stat(path string, stat *Stat_t) (err error) = SYS_STAT64
//sys Statfs(path string, stat *Statfs_t) (err error) = SYS_STATFS64
+
+func Getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) {
+ return 0, ENOSYS
+}
diff --git a/unix/syscall_darwin_amd64.go b/unix/syscall_darwin_amd64.go
index 914b89b..95e245f 100644
--- a/unix/syscall_darwin_amd64.go
+++ b/unix/syscall_darwin_amd64.go
@@ -56,8 +56,11 @@ const SYS___SYSCTL = SYS_SYSCTL
//sys Fstat(fd int, stat *Stat_t) (err error) = SYS_FSTAT64
//sys Fstatat(fd int, path string, stat *Stat_t, flags int) (err error) = SYS_FSTATAT64
//sys Fstatfs(fd int, stat *Statfs_t) (err error) = SYS_FSTATFS64
-//sys Getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) = SYS_GETDIRENTRIES64
//sys getfsstat(buf unsafe.Pointer, size uintptr, flags int) (n int, err error) = SYS_GETFSSTAT64
//sys Lstat(path string, stat *Stat_t) (err error) = SYS_LSTAT64
//sys Stat(path string, stat *Stat_t) (err error) = SYS_STAT64
//sys Statfs(path string, stat *Statfs_t) (err error) = SYS_STATFS64
+
+func Getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) {
+ return 0, ENOSYS
+}
diff --git a/unix/zsyscall_darwin_386.go b/unix/zsyscall_darwin_386.go
index 23346dc..db4f1ea 100644
--- a/unix/zsyscall_darwin_386.go
+++ b/unix/zsyscall_darwin_386.go
@@ -2408,28 +2408,6 @@ func libc_fstatfs64_trampoline()
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-func Getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) {
- var _p0 unsafe.Pointer
- if len(buf) > 0 {
- _p0 = unsafe.Pointer(&buf[0])
- } else {
- _p0 = unsafe.Pointer(&_zero)
- }
- r0, _, e1 := syscall_syscall6(funcPC(libc___getdirentries64_trampoline), uintptr(fd), uintptr(_p0), uintptr(len(buf)), uintptr(unsafe.Pointer(basep)), 0, 0)
- n = int(r0)
- if e1 != 0 {
- err = errnoErr(e1)
- }
- return
-}
-
-func libc___getdirentries64_trampoline()
-
-//go:linkname libc___getdirentries64 libc___getdirentries64
-//go:cgo_import_dynamic libc___getdirentries64 __getdirentries64 "/usr/lib/libSystem.B.dylib"
-
-// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-
func getfsstat(buf unsafe.Pointer, size uintptr, flags int) (n int, err error) {
r0, _, e1 := syscall_syscall(funcPC(libc_getfsstat64_trampoline), uintptr(buf), uintptr(size), uintptr(flags))
n = int(r0)
diff --git a/unix/zsyscall_darwin_386.s b/unix/zsyscall_darwin_386.s
index 37b85b4..6165f70 100644
--- a/unix/zsyscall_darwin_386.s
+++ b/unix/zsyscall_darwin_386.s
@@ -272,8 +272,6 @@ TEXT ·libc_fstatat64_trampoline(SB),NOSPLIT,$0-0
JMP libc_fstatat64(SB)
TEXT ·libc_fstatfs64_trampoline(SB),NOSPLIT,$0-0
JMP libc_fstatfs64(SB)
-TEXT ·libc___getdirentries64_trampoline(SB),NOSPLIT,$0-0
- JMP libc___getdirentries64(SB)
TEXT ·libc_getfsstat64_trampoline(SB),NOSPLIT,$0-0
JMP libc_getfsstat64(SB)
TEXT ·libc_lstat64_trampoline(SB),NOSPLIT,$0-0
diff --git a/unix/zsyscall_darwin_amd64.go b/unix/zsyscall_darwin_amd64.go
index c142e33..126f993 100644
--- a/unix/zsyscall_darwin_amd64.go
+++ b/unix/zsyscall_darwin_amd64.go
@@ -2423,28 +2423,6 @@ func libc_fstatfs64_trampoline()
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-func Getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) {
- var _p0 unsafe.Pointer
- if len(buf) > 0 {
- _p0 = unsafe.Pointer(&buf[0])
- } else {
- _p0 = unsafe.Pointer(&_zero)
- }
- r0, _, e1 := syscall_syscall6(funcPC(libc___getdirentries64_trampoline), uintptr(fd), uintptr(_p0), uintptr(len(buf)), uintptr(unsafe.Pointer(basep)), 0, 0)
- n = int(r0)
- if e1 != 0 {
- err = errnoErr(e1)
- }
- return
-}
-
-func libc___getdirentries64_trampoline()
-
-//go:linkname libc___getdirentries64 libc___getdirentries64
-//go:cgo_import_dynamic libc___getdirentries64 __getdirentries64 "/usr/lib/libSystem.B.dylib"
-
-// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-
func getfsstat(buf unsafe.Pointer, size uintptr, flags int) (n int, err error) {
r0, _, e1 := syscall_syscall(funcPC(libc_getfsstat64_trampoline), uintptr(buf), uintptr(size), uintptr(flags))
n = int(r0)
diff --git a/unix/zsyscall_darwin_amd64.s b/unix/zsyscall_darwin_amd64.s
index 1a39151..a19c4f5 100644
--- a/unix/zsyscall_darwin_amd64.s
+++ b/unix/zsyscall_darwin_amd64.s
@@ -274,8 +274,6 @@ TEXT ·libc_fstatat64_trampoline(SB),NOSPLIT,$0-0
JMP libc_fstatat64(SB)
TEXT ·libc_fstatfs64_trampoline(SB),NOSPLIT,$0-0
JMP libc_fstatfs64(SB)
-TEXT ·libc___getdirentries64_trampoline(SB),NOSPLIT,$0-0
- JMP libc___getdirentries64(SB)
TEXT ·libc_getfsstat64_trampoline(SB),NOSPLIT,$0-0
JMP libc_getfsstat64(SB)
TEXT ·libc_lstat64_trampoline(SB),NOSPLIT,$0-0
--
2.21.0

View File

@ -18,7 +18,7 @@ extern int wgTurnOn(gostring_t settings, int32_t tun_fd);
extern void wgTurnOff(int handle);
extern int64_t wgSetConfig(int handle, gostring_t settings);
extern char *wgGetConfig(int handle);
extern void wgBindInterfaceScope(int handle, int32_t ifscope);
extern void wgBumpSockets(int handle);
extern const char *wgVersion();
#endif