lokinet/llarp/apple/context_wrapper.h
Jason Rhinelander 9dd604820f
Unleak exit mode DNS via unbound DNS trampoline on (macOS)
When we enable/disable exit mode on this restarts the unbound DNS
responder with the DNS trampoline (or restores upstream, when disabling)
to properly route DNS requests through the tunnel (because libunbound's
direct requests don't get tunneled because unbound is inside the network
extension).
2021-09-02 14:17:10 -04:00

148 lines
6.4 KiB
C

#pragma once
// C-linkage wrappers for interacting with a lokinet context, so that we can call them from Swift
// code (which currently doesn't support C++ interoperability at all).
#ifdef __cplusplus
extern "C"
{
#endif
#include <unistd.h>
#include <sys/socket.h>
#include <uv.h>
// Port (on localhost) for our DNS trampoline for bouncing DNS requests through the exit route
// when in exit mode.
extern const uint16_t dns_trampoline_port;
/// C callback function for us to invoke when we need to write a packet
typedef void(*packet_writer_callback)(int af, const void* data, size_t size, void* ctx);
/// C callback function to invoke once we are ready to start receiving packets
typedef void(*start_reading_callback)(void* ctx);
/// C callback that bridges things into NSLog
typedef void(*ns_logger_callback)(const char* msg);
/// C callbacks to add/remove specific and default routes to the tunnel
typedef void(*llarp_route_ipv4_callback)(const char* addr, const char* netmask, void* ctx);
typedef void(*llarp_route_ipv6_callback)(const char* addr, int prefix, void* ctx);
typedef void(*llarp_default_route_callback)(void* ctx);
typedef struct llarp_route_callbacks {
/// Callback invoked to set up an IPv4 range that should be routed through the tunnel
/// interface. Called with the address and netmask.
llarp_route_ipv4_callback add_ipv4_route;
/// Callback invoked to set the tunnel as the default IPv4 route.
llarp_default_route_callback add_ipv4_default_route;
/// Callback invoked to remove a specific range from the tunnel IPv4 routes. Called with the
/// address and netmask.
llarp_route_ipv4_callback del_ipv4_route;
/// Callback invoked to set up an IPv6 range that should be routed through the tunnel
/// interface. Called with the address and netmask.
llarp_route_ipv6_callback add_ipv6_route;
/// Callback invoked to remove a specific range from the tunnel IPv6 routes. Called with the
/// address and netmask.
llarp_route_ipv6_callback del_ipv6_route;
/// Callback invoked to set the tunnel as the default IPv4/IPv6 route.
llarp_default_route_callback add_default_route;
/// Callback invoked to remove the tunnel as the default IPv4/IPv6 route.
llarp_default_route_callback del_default_route;
} llarp_route_callbacks;
/// Pack of crap to be passed into llarp_apple_init to initialize
typedef struct llarp_apple_config
{
/// lokinet configuration directory, expected to be the application-specific "home" directory,
/// which is where state files are stored and the lokinet.ini will be loaded (or created if it
/// doesn't exist).
const char* config_dir;
/// path to the default bootstrap.signed file included in installation, which will be used by
/// default when no specific bootstrap is in the config file.
const char* default_bootstrap;
/// llarp_apple_init writes the IP address for the primary tunnel IP address here,
/// null-terminated.
char tunnel_ipv4_ip[16];
/// llarp_apple_init writes the netmask of the tunnel address here, null-terminated.
char tunnel_ipv4_netmask[16];
/// The first upstream DNS server's IPv4 address the OS should use when in exit mode.
/// (Currently on mac in exit mode we only support querying the first such configured server).
char upstream_dns[16];
uint16_t upstream_dns_port;
/// \defgroup callbacks Callbacks
/// Callbacks we invoke for various operations that require glue into the Apple network
/// extension APIs. All of these except for ns_logger are passed the pointer provided to
/// llarp_apple_start when invoked.
/// @{
/// simple wrapper around NSLog for lokinet message logging
ns_logger_callback ns_logger;
/// C function callback that will be called when we need to write a packet to the packet
/// tunnel. Will be passed AF_INET or AF_INET6, a void pointer to the data, and the size of
/// the data in bytes.
packet_writer_callback packet_writer;
/// C function callback that will be called when lokinet is setup and ready to start receiving
/// packets from the packet tunnel. This should set up the read handler to deliver packets
/// via llarp_apple_incoming.
start_reading_callback start_reading;
/// Callbacks invoked to add/remove routes to the tunnel.
llarp_route_callbacks route_callbacks;
/// @}
} llarp_apple_config;
/// Initializes a lokinet instance by initializing various objects and loading the configuration
/// (if <config_dir>/lokinet.ini exists). Does not actually start lokinet (call llarp_apple_start
/// for that).
///
/// Returns NULL if there was a problem initializing/loading the configuration, otherwise returns
/// an opaque void pointer that should be passed into the other llarp_apple_* functions.
///
/// \param config pointer to a llarp_apple_config where we get the various settings needed
/// and return the ip/mask/dns fields needed for the tunnel.
void*
llarp_apple_init(llarp_apple_config* config);
/// Starts the lokinet instance in a new thread.
///
/// \param lokinet the void pointer returned by llarp_apple_init
///
/// \param callback_context Opaque pointer that is passed into the various callbacks provided to
/// llarp_apple_init. This code does nothing with this pointer aside from passing it through to
/// callbacks.
///
/// \returns 0 on succesful startup, -1 on failure.
int
llarp_apple_start(void* lokinet, void* callback_context);
/// Returns a pointer to the uv event loop. Must have called llarp_apple_start already.
uv_loop_t*
llarp_apple_get_uv_loop(void* lokinet);
/// Called to deliver an incoming packet from the apple layer into lokinet; returns 0 on success,
/// -1 if the packet could not be parsed, -2 if there is no current active VPNInterface associated
/// with the lokinet (which generally means llarp_apple_start wasn't called or failed, or lokinet
/// is in the process of shutting down).
int
llarp_apple_incoming(void* lokinet, const void* bytes, size_t size);
/// Stops a lokinet instance created with `llarp_apple_initialize`. This waits for lokinet to
/// shut down and rejoins the thread. After this call the given pointer is no longer valid.
void
llarp_apple_shutdown(void* lokinet);
#ifdef __cplusplus
} // extern "C"
#endif