summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorJoakim Hulthe <joakim@hulthe.net>2025-03-24 09:37:05 +0100
committerJoakim Hulthe <joakim.hulthe@mullvad.net>2025-04-01 09:22:48 +0200
commit67a4609e358190a1e5bb705ac058621813d749bd (patch)
tree8ae1e5480f170447f7a9cc6018aec9483d46d127
parentfc75028a644f2184a4f04d7f41702782964b1af4 (diff)
downloadmullvadvpn-67a4609e358190a1e5bb705ac058621813d749bd.tar.xz
mullvadvpn-67a4609e358190a1e5bb705ac058621813d749bd.zip
Remove some `unsafe` blocks
-rw-r--r--talpid-routing/src/unix/macos/interface.rs49
1 files changed, 32 insertions, 17 deletions
diff --git a/talpid-routing/src/unix/macos/interface.rs b/talpid-routing/src/unix/macos/interface.rs
index 7de3f84cc5..16f085c969 100644
--- a/talpid-routing/src/unix/macos/interface.rs
+++ b/talpid-routing/src/unix/macos/interface.rs
@@ -24,16 +24,21 @@ use system_configuration::{
dynamic_store::{SCDynamicStore, SCDynamicStoreBuilder, SCDynamicStoreCallBackContext},
network_configuration::SCNetworkSet,
preferences::SCPreferences,
- sys::schema_definitions::{
- kSCDynamicStorePropNetPrimaryInterface, kSCPropInterfaceName, kSCPropNetIPv4Addresses,
- kSCPropNetIPv4Router, kSCPropNetIPv6Addresses, kSCPropNetIPv6Router,
- },
};
const STATE_IPV4_KEY: &str = "State:/Network/Global/IPv4";
const STATE_IPV6_KEY: &str = "State:/Network/Global/IPv6";
const STATE_SERVICE_PATTERN: &str = "State:/Network/Service/.*/IP.*";
+/// Safely read a symbol in [system_configuration::sys::schema_definitions].
+macro_rules! schema_definition {
+ ($name:ident) => {
+ // SAFETY: system_configuration_sys is generated using bindgen, and all symbols in the
+ // schema_definitions module are to static string pointers, and should be safe to read.
+ unsafe { ::system_configuration::sys::schema_definitions::$name }
+ };
+}
+
#[derive(Debug, PartialEq, Clone, Copy)]
pub enum Family {
V4,
@@ -137,7 +142,11 @@ impl PrimaryInterfaceMonitor {
}
let run_loop_source = listener_store.create_run_loop_source();
- CFRunLoop::get_current().add_source(&run_loop_source, unsafe { kCFRunLoopCommonModes });
+
+ // SAFETY: this is just a static string pointer, referencing it should be safe.
+ let run_loop_common_modes = unsafe { kCFRunLoopCommonModes };
+
+ CFRunLoop::get_current().add_source(&run_loop_source, run_loop_common_modes);
CFRunLoop::run_current();
log::debug!("Interface listener exiting");
@@ -218,9 +227,11 @@ impl PrimaryInterfaceMonitor {
.store
.get(key)
.and_then(|v| v.downcast_into::<CFDictionary>())?;
- let name = get_dict_elem_as_string(&global_dict, unsafe {
- kSCDynamicStorePropNetPrimaryInterface
- })
+
+ let name = get_dict_elem_as_string(
+ &global_dict,
+ schema_definition!(kSCDynamicStorePropNetPrimaryInterface),
+ )
.or_else(|| {
log::debug!("Missing name for primary interface ({family})");
None
@@ -255,11 +266,15 @@ impl PrimaryInterfaceMonitor {
.store
.get(CFString::new(&service_key))
.and_then(|v| v.downcast_into::<CFDictionary>())?;
- let name = get_dict_elem_as_string(&service_dict, unsafe { kSCPropInterfaceName })
- .or_else(|| {
- log::debug!("Missing name for service {service_key} ({family})");
- None
- })?;
+
+ let name = get_dict_elem_as_string(
+ &service_dict,
+ schema_definition!(kSCPropInterfaceName),
+ )
+ .or_else(|| {
+ log::debug!("Missing name for service {service_key} ({family})");
+ None
+ })?;
let router_ip = get_service_router_ip(&service_dict, family).or_else(|| {
log::debug!("Missing router IP for {service_key} ({name}, {family})");
None
@@ -310,9 +325,9 @@ fn is_link_local_v6(addr: &Ipv6Addr) -> bool {
fn get_service_router_ip(service_dict: &CFDictionary, family: Family) -> Option<IpAddr> {
let router_key = if family == Family::V4 {
- unsafe { kSCPropNetIPv4Router }
+ schema_definition!(kSCPropNetIPv4Router)
} else {
- unsafe { kSCPropNetIPv6Router }
+ schema_definition!(kSCPropNetIPv6Router)
};
get_dict_elem_as_string(service_dict, router_key).and_then(|ip| ip.parse().ok())
}
@@ -323,9 +338,9 @@ fn get_service_router_ip(service_dict: &CFDictionary, family: Family) -> Option<
/// `kSCPropNetIPv6Addresses`, depending on the family.
fn get_service_first_ip(service_dict: &CFDictionary, family: Family) -> Option<IpAddr> {
let ip_key = if family == Family::V4 {
- unsafe { kSCPropNetIPv4Addresses }
+ schema_definition!(kSCPropNetIPv4Addresses)
} else {
- unsafe { kSCPropNetIPv6Addresses }
+ schema_definition!(kSCPropNetIPv6Addresses)
};
service_dict
.find(ip_key.to_void())