device: accept any io.Reader in device.IpcSetOperation
Any io.Reader will do, and there are no performance concerns here.
This is technically backwards incompatible,
but it is very unlikely to break any existing code.
It is compatible with the existing uses in wireguard-{windows,android,apple}
and also will allow us to slightly simplify it if desired.
When running many concurrent test processing using
https://godoc.org/golang.org/x/tools/cmd/stress
the processing sometimes cannot complete a ping in under 300ms.
Increase the timeout to 5s to reduce the rate of false positives.
device: prevent spurious errors while closing a device
When closing a device, packets that are in flight
can make it to SendBuffer, which then returns an error.
Those errors add noise but no light;
they do not reflect an actual problem.
Adding the synchronization required to prevent
this from occurring is currently expensive and error-prone.
Instead, quietly drop such packets instead of
returning an error.
In each case, the starting waitgroup did nothing but ensure
that the goroutine has launched.
Nothing downstream depends on the order in which goroutines launch,
and if the Go runtime scheduler is so broken that goroutines
don't get launched reasonably promptly, we have much deeper problems.
Given all that, simplify the code.
Passed a race-enabled stress test 25,000 times without failure.
Picking two free ports to use for a test is difficult.
The free port we selected might no longer be free when we reach
for it a second time.
On my machine, this failure mode led to failures approximately
once per thousand test runs.
Since failures are rare, and threading through and checking for
all possible errors is complicated, fix this with a big hammer:
Retry if either device fails to come up.
Also, if you accidentally pick the same port twice, delightful confusion ensues.
The handshake failures manifest as crypto errors, which look scary.
Again, fix with retries.
To make these retries easier to implement, use testing.T.Cleanup
instead of defer to close devices. This requires Go 1.14.
Update go.mod accordingly. Go 1.13 is no longer supported anyway.
With these fixes, 'go test -race' ran 100,000 times without failure.
Simon Rozman [Wed, 22 Jul 2020 07:15:49 +0000 (09:15 +0200)]
wintun: migrate to wintun.dll API
Rather than having every application using Wintun driver reinvent the
wheel, the Wintun device/adapter/interface management has been moved
from wireguard-go to wintun.dll deployed with Wintun itself.
Tobias Klauser [Tue, 27 Oct 2020 13:39:36 +0000 (14:39 +0100)]
tun: use SockaddrCtl from golang.org/x/sys/unix on macOS
Direct syscalls using unix.Syscall(unix.SYS_*, ...) are discouraged on
macOS and might not be supported in future versions. Switch to use
unix.Connect with unix.SockaddrCtl instead.
Signed-off-by: Tobias Klauser <tklauser@distanz.ch> Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
Tobias Klauser [Tue, 27 Oct 2020 13:39:35 +0000 (14:39 +0100)]
tun: use Ioctl{Get,Set}IfreqMTU from golang.org/x/sys/unix on macOS
Direct syscalls using unix.Syscall(unix.SYS_*, ...) are discouraged on
macOS and might not be supported in future versions. Switch to use
unix.Ioctl{Get,Set}IfreqMTU to get and set an interface's MTU.
Signed-off-by: Tobias Klauser <tklauser@distanz.ch> Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
Tobias Klauser [Tue, 27 Oct 2020 13:39:34 +0000 (14:39 +0100)]
tun: use IoctlCtlInfo from golang.org/x/sys/unix on macOS
Direct syscalls using unix.Syscall(unix.SYS_*, ...) are discouraged on
macOS and might not be supported in future versions. Switch to use
unix.IoctlCtlInfo to get the kernel control info.
Signed-off-by: Tobias Klauser <tklauser@distanz.ch> Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
Tobias Klauser [Tue, 27 Oct 2020 13:39:33 +0000 (14:39 +0100)]
tun: use GetsockoptString in (*NativeTun).Name on macOS
Direct syscalls using unix.Syscall(unix.SYS_*, ...) are discouraged on
macOS and might not be supported in future versions. Instead, use the
existing unix.GetsockoptString wrapper to get the interface name.
Signed-off-by: Tobias Klauser <tklauser@distanz.ch> Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
device: wait for routines to stop before removing peers
Peers are currently removed after Device's goroutines are signaled to stop,
but without waiting for them to actually do so, which is racy.
For example, RoutineHandshake may be in Peer.SendKeepalive
when the corresponding peer is removed, which closes its nonce channel.
This causes a send on a closed channel, as observed in tailscale/tailscale#487.
This patch seems to be the correct synchronizing action:
Peer's goroutines are receivers and handle channel closure gracefully,
so Device's goroutines are the ones that should be fully stopped first.
David Crawshaw [Sat, 2 May 2020 06:28:33 +0000 (16:28 +1000)]
ipc: deduplicate some unix-specific code
Cleans up and splits out UAPIOpen to its own file.
Signed-off-by: David Crawshaw <crawshaw@tailscale.com>
[zx2c4: changed const to var for socketDirectory] Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
device: use atomic access for unlocked keypair.next
Go's GC semantics might not always guarantee the safety of this, and the
race detector gets upset too, so instead we wrap this all in atomic
accessors.
Reported-by: David Anderson <danderson@tailscale.com> Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
Simon Rozman [Sat, 2 May 2020 06:49:35 +0000 (08:49 +0200)]
wintun: make remaining HWID comparisons case insensitive
c85e4a410f27986a2967a49c0155633c716bf3ca introduced preliminary HWID
checking to speed up Wintun adapter enumeration. However, all HWID are
case insensitive by Windows convention.
Furthermore, a device might have multiple HWIDs. When DevInfo's
DeviceRegistryProperty(SPDRP_HARDWAREID) method returns []string, all
strings returned should be checked against given hardware ID.
This issue was discovered when researching Wintun and wireguard-go on
Windows 10 ARM64. The Wintun adapter was created using devcon.exe
utility with "wintun" hardware ID, causing wireguard-go fail to
enumerate the adapter properly.
Avery Pennarun [Wed, 6 Nov 2019 08:28:02 +0000 (00:28 -0800)]
tun: NetlinkListener: don't send EventDown before sending EventUp
This works around a startup race condition when competing with
HackListener, which is trying to do the same job. If HackListener
detects that the tundev is running while there is still an event in the
netlink queue that says it isn't running, then the device receives a
string of events like
EventUp (HackListener)
EventDown (NetlinkListener)
EventUp (NetlinkListener)
Unfortunately, after the first EventDown, the device stops itself,
thinking incorrectly that the administrator has downed its tundev.
The device is ignoring the initial EventDown anyway, so just don't emit
it.
David Anderson [Sun, 1 Mar 2020 08:39:24 +0000 (00:39 -0800)]
device: add test to ensure Peer fields are safe for atomic access on 32-bit
Adds a test that will fail consistently on 32-bit platforms if the
struct ever changes again to violate the rules. This is likely not
needed because unaligned access crashes reliably, but this will reliably
fail even if tests accidentally pass due to lucky alignment.
Signed-Off-By: David Anderson <danderson@tailscale.com>
David Crawshaw [Wed, 19 Feb 2020 15:09:24 +0000 (10:09 -0500)]
rwcancel: no-op builds for windows and darwin
This lets us include the package on those platforms in a
followup commit where we split out a conn package from device.
It also lets us run `go test ./...` when developing on macOS.
Signed-off-by: David Crawshaw <crawshaw@tailscale.com>
David Crawshaw [Sun, 8 Dec 2019 23:22:31 +0000 (18:22 -0500)]
ratelimiter: use a fake clock in tests and style cleanups
The existing test would occasionally flake out with:
--- FAIL: TestRatelimiter (0.12s)
ratelimiter_test.go:99: Test failed for 127.0.0.1 , on: 7 ( not having refilled enough ) expected: false got: true
FAIL
FAIL golang.zx2c4.com/wireguard/ratelimiter 0.171s
The fake clock also means the tests run much faster, so
testing this package with -count=1000 now takes < 100ms.
While here, several style cleanups. The most significant one
is unembeding the sync.Mutex fields in the rate limiter objects.
Embedded as they were, the lock methods were accessible
outside the ratelimiter package. As they aren't needed externally,
keep them internal to make them easier to reason about.
Passes `go test -race -count=10000 ./ratelimiter`
Signed-off-by: David Crawshaw <crawshaw@tailscale.com>
Tobias Klauser [Wed, 4 Mar 2020 16:21:54 +0000 (17:21 +0100)]
global: use RTMGRP_* consts from x/sys/unix
Update the golang.org/x/sys/unix dependency and use the newly introduced
RTMGRP_* consts instead of using the corresponding RTNLGRP_* const to
create a mask.
Some devices take ~2 seconds to enumerate on Windows if we try to get
their instance name. The hardware id property, on the other hand,
is available right away.
Signed-off-by: Avery Pennarun <apenwarr@gmail.com>
[zx2c4: inlined this to where it makes sense, reused setupapi const]
Avery Pennarun [Sat, 12 Oct 2019 07:46:13 +0000 (00:46 -0700)]
rwcancel: handle EINTR and EAGAIN in unixSelect()
On my Chromebook (Linux 4.19.44 in a VM) and on an AWS EC2
machine, select() was sometimes returning EINTR. This is
harmless and just means you should try again. So let's try
again.
This eliminates a problem where the tunnel fails to come up
correctly and the program needs to be restarted.