summaryrefslogtreecommitdiff
Commit message (Collapse)AuthorAgeFilesLines
* global: bump copyrightJason A. Donenfeld2021-01-2886-86/+86
| | | | Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
* device: remove version stringJason A. Donenfeld2021-01-283-7/+7
| | | | | | This is what modules are for, and Go binaries can introspect. Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
* device: do not allow get to run while set runsJason A. Donenfeld2021-01-282-3/+7
| | | | Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
* device: avoid hex allocations in IpcGetJason A. Donenfeld2021-01-282-15/+14
| | | | | | | | | | | | | benchmark old ns/op new ns/op delta BenchmarkUAPIGet-16 2872 2157 -24.90% benchmark old allocs new allocs delta BenchmarkUAPIGet-16 30 18 -40.00% benchmark old bytes new bytes delta BenchmarkUAPIGet-16 737 256 -65.26% Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
* device: the psk is not a chapoly keyJason A. Donenfeld2021-01-282-8/+7
| | | | | | It's a separate type of key that gets hashed into the chain. Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
* device: get rid of nonce routineJason A. Donenfeld2021-01-278-167/+72
| | | | | | | | | | | | | This moves to a simple queue with no routine processing it, to reduce scheduler pressure. This splits latency in half! benchmark old ns/op new ns/op delta BenchmarkThroughput-16 2394 2364 -1.25% BenchmarkLatency-16 259652 120810 -53.47% Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
* tun: use %w for errors on linuxJason A. Donenfeld2021-01-271-9/+8
| | | | Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
* device: avoid deadlock when changing private key and removing self peersJason A. Donenfeld2021-01-271-0/+2
| | | | Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
* device: use linked list for per-peer allowed-ip traversalJason A. Donenfeld2021-01-274-44/+62
| | | | | | | | | | | | | | | | | | | | | | | This makes the IpcGet method much faster. We also refactor the traversal API to use a callback so that we don't need to allocate at all. Avoiding allocations we do self-masking on insertion, which in turn means that split intermediate nodes require a copy of the bits. benchmark old ns/op new ns/op delta BenchmarkUAPIGet-16 3243 2659 -18.01% benchmark old allocs new allocs delta BenchmarkUAPIGet-16 35 30 -14.29% benchmark old bytes new bytes delta BenchmarkUAPIGet-16 1218 737 -39.49% This benchmark is good, though it's only for a pair of peers, each with only one allowedips. As this grows, the delta expands considerably. Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
* device: combine debug and info log levels into 'verbose'Jason A. Donenfeld2021-01-2613-133/+109
| | | | | | | | | | | | There are very few cases, if any, in which a user only wants one of these levels, so combine it into a single level. While we're at it, reduce indirection on the loggers by using an empty function rather than a nil function pointer. It's not like we have retpolines anyway, and we were always calling through a function with a branch prior, so this seems like a net gain. Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
* device: change logging interface to use functionsJosh Bleecher Snyder2021-01-2611-182/+147
| | | | | | | | | | | | | | | | | | | | | This commit overhauls wireguard-go's logging. The primary, motivating change is to use a function instead of a *log.Logger as the basic unit of logging. Using functions provides a lot more flexibility for people to bring their own logging system. It also introduces logging helper methods on Device. These reduce line noise at the call site. They also allow for log functions to be nil; when nil, instead of generating a log line and throwing it away, we don't bother generating it at all. This spares allocation and pointless work. This is a breaking change, although the fix required of clients is fairly straightforward. Signed-off-by: Josh Bleecher Snyder <josh@tailscale.com>
* device: fix shadowing of err in IpcHandleJosh Bleecher Snyder2021-01-261-1/+2
| | | | | | | | | | | | | | | | | | | | | | | | The declaration of err in nextByte, err := buffered.ReadByte shadows the declaration of err in op, err := buffered.ReadString('\n') above. As a result, the assignments to err in err = ipcErrorf(ipc.IpcErrorInvalid, "trailing character in UAPI get: %c", nextByte) and in err = device.IpcGetOperation(buffered.Writer) do not modify the correct err variable. Found by staticcheck. Signed-off-by: Josh Bleecher Snyder <josh@tailscale.com>
* device: remove extra error argJosh Bleecher Snyder2021-01-261-1/+1
| | | | | Caught by go vet. Signed-off-by: Josh Bleecher Snyder <josh@tailscale.com>
* device: reduce allocs in Device.IpcGetOperationBrad Fitzpatrick2021-01-261-23/+27
| | | | | | | | | | | | | | | Plenty more to go, but a start: name old time/op new time/op delta UAPIGet-4 6.37µs ± 2% 5.56µs ± 1% -12.70% (p=0.000 n=8+8) name old alloc/op new alloc/op delta UAPIGet-4 1.98kB ± 0% 1.22kB ± 0% -38.71% (p=0.000 n=10+10) name old allocs/op new allocs/op delta UAPIGet-4 42.0 ± 0% 35.0 ± 0% -16.67% (p=0.000 n=10+10) Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
* device: add benchmark for UAPI Device.IpcGetOperationJosh Bleecher Snyder2021-01-261-0/+12
| | | | Signed-off-by: Josh Bleecher Snyder <josh@tailscale.com>
* conn: fix interface parameter name in Bind interface docsBrad Fitzpatrick2021-01-261-1/+1
| | | | Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
* device: allow pipelining UAPI requestsJason A. Donenfeld2021-01-251-30/+36
| | | | | | The original spec ends with \n\n especially for this reason. Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
* ipc: add missing Windows errnoJason A. Donenfeld2021-01-251-0/+1
| | | | Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
* device: serialize access to IpcSetOperationJosh Bleecher Snyder2021-01-252-0/+4
| | | | | | Interleaves IpcSetOperations would spell trouble. Signed-off-by: Josh Bleecher Snyder <josh@tailscale.com>
* device: simplify handling of IPC set endpointJosh Bleecher Snyder2021-01-251-12/+4
| | | | Signed-off-by: Josh Bleecher Snyder <josh@tailscale.com>
* device: remove close processing fwmarkJosh Bleecher Snyder2021-01-251-11/+2
| | | | | | | Also, a behavior change: Stop treating a blank value as 0. It's not in the spec. Signed-off-by: Josh Bleecher Snyder <josh@tailscale.com>
* device: remove unnecessary commentJosh Bleecher Snyder2021-01-251-1/+0
| | | | Signed-off-by: Josh Bleecher Snyder <josh@tailscale.com>
* device: introduce new IPC error message for unknown errorJosh Bleecher Snyder2021-01-252-2/+3
| | | | Signed-off-by: Josh Bleecher Snyder <josh@tailscale.com>
* device: correct IPC error number for I/O errorsJosh Bleecher Snyder2021-01-251-1/+4
| | | | Signed-off-by: Josh Bleecher Snyder <josh@tailscale.com>
* device: simplify IpcHandle error handlingJosh Bleecher Snyder2021-01-251-15/+6
| | | | | | | | | | Unify the handling of unexpected UAPI errors. The comment that says "should never happen" is incorrect; this could happen due to I/O errors. Correct it. Change error message capitalization for consistency. Signed-off-by: Josh Bleecher Snyder <josh@tailscale.com>
* device: split IpcSetOperation into partsJosh Bleecher Snyder2021-01-251-204/+198
| | | | | | | | | | | | | | | | The goal of this change is to make the structure of IpcSetOperation easier to follow. IpcSetOperation contains a small state machine: It starts by configuring the device, then shifts to configuring one peer at a time. Having the code all in one giant method obscured that structure. Split out the parts into helper functions and encapsulate the peer state. This makes the overall structure more apparent. Signed-off-by: Josh Bleecher Snyder <josh@tailscale.com>
* device: expand IPCErrorJosh Bleecher Snyder2021-01-251-51/+43
| | | | | | | | | | Expand IPCError to contain a wrapped error, and add a helper to make constructing such errors easier. Add a defer-based "log on returned error" to IpcSetOperation. This lets us simplify all of the error return paths. Signed-off-by: Josh Bleecher Snyder <josh@tailscale.com>
* device: remove dead codeJosh Bleecher Snyder2021-01-251-6/+1
| | | | | | | | If device.NewPeer returns a nil error, then the returned peer is always non-nil. Signed-off-by: Josh Bleecher Snyder <josh@tailscale.com>
* device: return errors from ipc scannerJosh Bleecher Snyder2021-01-251-1/+1
| | | | | | | | The code as written will drop any read errors on the floor. Fix that. Signed-off-by: Josh Bleecher Snyder <josh@tailscale.com>
* netstack: further sequester with own go.mod and go.sumJason A. Donenfeld2021-01-214-376/+400
| | | | | | | | In order to avoid even the flirtation with passing on these dependencies to ordinary consumers of wireguard-go, this commit makes a new go.mod that's entirely separate from the root one. Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
* netstack: introduce new module for gvisor tcp tun adapterJason A. Donenfeld2021-01-213-6/+106
| | | | | | | | | | | | | | The Go linker isn't smart enough to prevent gvisor from being pulled into modules that use other parts of tun/, due to the types exposed. So, we put this into its own standalone module. We use this as an opportunity to introduce some example code as well. I'm still not happy that this not only clutters this repo's go.sum, but all the other projects that consume it, but it seems like making a new module inside of this repo will lead to even greater confusion. Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
* device: allow compiling with Go 1.15Jason A. Donenfeld2021-01-204-6/+19
| | | | | | | | | Until we depend on Go 1.16 (which isn't released yet), alias our own variable to the private member of the net package. This will allow an easy find replace to make this go away when we eventually switch to 1.16. Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
* device: remove unused fields from DummyDatagram and DummyBindJosh Bleecher Snyder2021-01-201-3/+0
| | | | Signed-off-by: Josh Bleecher Snyder <josh@tailscale.com>
* device: remove unused trie test codeJosh Bleecher Snyder2021-01-201-20/+0
| | | | Signed-off-by: Josh Bleecher Snyder <josh@tailscale.com>
* conn: remove _ method receiverJosh Bleecher Snyder2021-01-201-1/+1
| | | | | | Minor style fix. Signed-off-by: Josh Bleecher Snyder <josh@tailscale.com>
* tun: fix fmt.Errorf format stringsJosh Bleecher Snyder2021-01-201-3/+3
| | | | | | | | | | | | Type tcpip.Error is not an error. I've filed https://github.com/google/gvisor/issues/5314 to fix this upstream. Until that is fixed, use %v instead of %w, to keep vet happy. Signed-off-by: Josh Bleecher Snyder <josh@tailscale.com>
* device: remove unnecessary zeroingJosh Bleecher Snyder2021-01-201-5/+0
| | | | | | Newly allocated objects are already zeroed. Signed-off-by: Josh Bleecher Snyder <josh@tailscale.com>
* device: remove QueueInboundElement.droppedJosh Bleecher Snyder2021-01-201-30/+5
| | | | | | | | | | | | Now that we block when enqueueing to the decryption queue, there is only one case in which we "drop" a inbound element, when decryption fails. We can use a simple, obvious, sync-free sentinel for that, elem.packet == nil. Also, we can return the message buffer to the pool slightly later, which further simplifies the code. Signed-off-by: Josh Bleecher Snyder <josh@tailscale.com>
* device: remove QueueOutboundElement.droppedJosh Bleecher Snyder2021-01-201-23/+0
| | | | | | | If we block when enqueuing encryption elements to the queue, then we never drop them. Signed-off-by: Josh Bleecher Snyder <josh@tailscale.com>
* tun/wintun/memmod: gofmtJosh Bleecher Snyder2021-01-201-1/+1
| | | | Signed-off-by: Josh Bleecher Snyder <josh@tailscale.com>
* tun/wintun/memmod: fix format verbJosh Bleecher Snyder2021-01-201-1/+1
| | | | | | Caught by 'go vet'. Signed-off-by: Josh Bleecher Snyder <josh@tailscale.com>
* device: check returned errors from NewPeer in TestNoiseHandshakeJosh Bleecher Snyder2021-01-201-2/+8
| | | | Signed-off-by: Josh Bleecher Snyder <josh@tailscale.com>
* device: remove selects from encrypt/decrypt/inbound/outbound enqueuingJosh Bleecher Snyder2021-01-202-38/+5
| | | | | | | Block instead. Backpressure here is fine, probably preferable. This reduces code complexity. Signed-off-by: Josh Bleecher Snyder <josh@tailscale.com>
* device: put handshake buffer in pool in FlushPacketQueuesJosh Bleecher Snyder2021-01-201-1/+2
| | | | | | This appears to have been an oversight. Signed-off-by: Josh Bleecher Snyder <josh@tailscale.com>
* device: use channel close to shut down and drain decryption channelJosh Bleecher Snyder2021-01-202-60/+50
| | | | | | | | | This is similar to commit e1fa1cc5560020e67d33aa7e74674853671cf0a0, but for the decryption channel. It is an alternative fix to f9f655567930a4cd78d40fa4ba0d58503335ae6a. Signed-off-by: Josh Bleecher Snyder <josh@tailscale.com>
* tun: add tcpip stack tunnel abstractionJason A. Donenfeld2021-01-133-0/+1192
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | This allows people to initiate connections over WireGuard without any underlying operating system support. I'm not crazy about the trash it adds to go.sum, but the code this actually adds to the binaries seems contained to the gvisor repo. For the TCP/IP implementation, it uses gvisor. And it borrows some internals from the Go standard library's resolver in order to bring Dial and DialContext to tun_net, along with the LookupHost helper function. This allows for things like HTTP2-over-TLS to work quite well: package main import ( "io" "log" "net" "net/http" "golang.zx2c4.com/wireguard/device" "golang.zx2c4.com/wireguard/tun" ) func main() { tun, tnet, err := tun.CreateNetTUN([]net.IP{net.ParseIP("192.168.4.29")}, []net.IP{net.ParseIP("8.8.8.8"), net.ParseIP("8.8.4.4")}, 1420) if err != nil { log.Panic(err) } dev := device.NewDevice(tun, &device.Logger{log.Default(), log.Default(), log.Default()}) dev.IpcSet(`private_key=a8dac1d8a70a751f0f699fb14ba1cff7b79cf4fbd8f09f44c6e6a90d0369604f public_key=25123c5dcd3328ff645e4f2a3fce0d754400d3887a0cb7c56f0267e20fbf3c5b endpoint=163.172.161.0:12912 allowed_ip=0.0.0.0/0 `) dev.Up() client := http.Client{ Transport: &http.Transport{ DialContext: tnet.DialContext, }, } resp, err := client.Get("https://www.zx2c4.com/ip") if err != nil { log.Panic(err) } body, err := io.ReadAll(resp.Body) if err != nil { log.Panic(err) } log.Println(string(body)) } Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
* device: receive: do not exit immediately on transient UDP receive errorsJason A. Donenfeld2021-01-084-23/+32
| | | | | | | | | | | | | | | | Some users report seeing lines like: > Routine: receive incoming IPv4 - stopped Popping up unexpectedly. Let's sleep and try again before failing, and also log the error, and perhaps we'll eventually understand this situation better in future versions. Because we have to distinguish between the socket being closed explicitly and whatever error this is, we bump the module to require Go 1.16. Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
* conn: linux: do not allow ReceiveIPvX to race with CloseJason A. Donenfeld2021-01-071-17/+32
| | | | | | | If Close is called after ReceiveIPvX, then ReceiveIPvX will block on an invalid or potentially reused fd. Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
* device: receive: drain decryption queue before exiting RoutineDecryptionJason A. Donenfeld2021-01-072-2/+18
| | | | | | | | | | | | It's possible for RoutineSequentialReceiver to try to lock an elem after RoutineDecryption has exited. Before this meant we didn't then unlock the elem, so the whole program deadlocked. As well, it looks like the flush code (which is now potentially unnecessary?) wasn't properly dropping the buffers for the not-already-dropped case. Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
* device: add latency and throughput benchmarksJosh Bleecher Snyder2021-01-071-0/+59
| | | | | | | | | | | These obviously don't perfectly capture real world performance, in which syscalls and network links have a significant impact. Nevertheless, they capture some of the internal performance factors, and they're easy and convenient to work with. Hat tip to Avery Pennarun for help designing the throughput benchmark. Signed-off-by: Josh Bleecher Snyder <josh@tailscale.com>