According to [1], the `capacity` parameter is specified as "the number
of instances of T in the re-bound region" and not the total size of the
rebound struct.
Without this patch, there are crashes in the extension with the
following error:
Fatal error: self must be a properly aligned pointer for types Pointee and T`
Since the subsequent line in the code only reads `sizeof(in_addr)` or
`sizeof(in6_addr)` anyway, change the `capacity` parameter to just be a
count of 1.
[1] https://developer.apple.com/documentation/swift/unsafepointer/withmemoryrebound(to:capacity:_:)
Signed-off-by: John Biggs <john.biggs@proton.ch>
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
Rather than hoping that the AF_SYSTEM fd is of type utun, and then
calling "2" on it to get the name -- which could be defined as something
else for a different AF_SYSTEM socket type -- instead simply query the
AF_SYSTEM control socket ID with getpeername. This has one catch, which
is that the ID is dynamically allocated, so we resolve it using the
qualified name. Normally we'd make a new AF_SYSTEM socket for this, but
since that's not allowed in the sandbox, we reuse the AF_SYSTEM socket
that we're checking. At this point in the flow, we know that it's a
proper AF_SYSTEM one, based on the first sockaddr member; we just don't
know that it's a utun variety.
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
This is a bit of a kludge, until I find something better. We simply
iterate through all FDs, and call getsockopt on each one until we find
the utun FD. This works, and completes rather quickly (fd is usually 6
or 7). Rather than maintain the old path for older kernels, just use
this for all versions, to get more coverage. Other techniques involve
undocumented APIs; this one has the advantage of using nothing
undocumented.
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
macOS will use the wrong source address unless we add explicit routes
that mention the self-pointing gateway. Actually, it won't add any
implicit routes on its own, so in order to route the masks of the
addresses, we have to add our own routes explicitly.
However, this still doesn't fix the problem while inside of the network
extension, even though it works outside it.
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
The general Network Extension framework is incredibly buggy, and a
timeout when setting the network settings does not necessarily imply
that the whole operation failed. Simply log the condition and move on.
This restores the app's old behavior.
Reported-by: Filipe Mendonça <cfilipem@gmail.com>
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
Prior, we would set matchDomains=[""] even if the user didn't provide
any DNS servers. This was kind of incoherent, but I guess we had in mind
some kind of non-sensical leakproof scheme that never really worked
anyway. NetworkExtension didn't like this, so setTunnelNetworkSettings
would, rather than return an error, simply timeout and never call its
callback function. But everything worked fine, so we had code in the UI
to check to make sure everything was okay after 5 seconds or so of no
callback. Recent changes made the timeout fatal on the network extension
side, so rather than succeed, configs with no DNS server started
erroring out, causing user reports.
This commit attempts to handle the root cause of the timeout issue by
not twiddling with DNS settings if no DNS server was specified. For now,
however, it leaves the hard-timeout semantics in place.
Reported-by: Filipe Mendonça <cfilipem@gmail.com>
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
This has been supported by Windows and Linux for quite some time. Add
support here for iOS and macOS.
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>