diff --git a/rust/connlib/clients/apple/src/lib.rs b/rust/connlib/clients/apple/src/lib.rs index 5ec45829f..9ff1d1293 100644 --- a/rust/connlib/clients/apple/src/lib.rs +++ b/rust/connlib/clients/apple/src/lib.rs @@ -73,11 +73,11 @@ mod ffi { // // `dns_servers` must not have any IPv6 scopes // - #[swift_bridge(swift_name = "setDns")] - fn set_dns(&mut self, dns_servers: String); + #[swift_bridge(swift_name = "setDns", return_with = err_to_string)] + fn set_dns(&mut self, dns_servers: String) -> Result<(), String>; - #[swift_bridge(swift_name = "setDisabledResources")] - fn set_disabled_resources(&mut self, disabled_resources: String); + #[swift_bridge(swift_name = "setDisabledResources", return_with = err_to_string)] + fn set_disabled_resources(&mut self, disabled_resources: String) -> Result<(), String>; fn disconnect(self); } @@ -300,18 +300,26 @@ impl WrappedSession { self.inner.reset() } - fn set_dns(&mut self, dns_servers: String) { - let dns_servers = - serde_json::from_str(&dns_servers).expect("Failed to deserialize DNS servers"); + fn set_dns(&mut self, dns_servers: String) -> Result<()> { + tracing::debug!(%dns_servers); - self.inner.set_dns(dns_servers) + let dns_servers = serde_json::from_str(&dns_servers) + .context("Failed to deserialize DNS servers from JSON")?; + + self.inner.set_dns(dns_servers); + + Ok(()) } - fn set_disabled_resources(&mut self, disabled_resources: String) { - let disabled_resources = serde_json::from_str(&disabled_resources) - .expect("Failed to deserialize disabled resources"); + fn set_disabled_resources(&mut self, disabled_resources: String) -> Result<()> { + tracing::debug!(%disabled_resources); - self.inner.set_disabled_resources(disabled_resources) + let disabled_resources = serde_json::from_str(&disabled_resources) + .context("Failed to deserialize disabled resources from JSON")?; + + self.inner.set_disabled_resources(disabled_resources); + + Ok(()) } fn disconnect(mut self) { @@ -320,12 +328,8 @@ impl WrappedSession { } } -fn err_to_string(result: Result) -> Result { - result.map_err(|e| { - tracing::error!("Failed to create session: {e:#}"); - - format!("{e:#}") - }) +fn err_to_string(result: Result) -> Result { + result.map_err(|e| format!("{e:#}")) } /// Installs the `ring` crypto provider for rustls. diff --git a/swift/apple/FirezoneNetworkExtension/Adapter.swift b/swift/apple/FirezoneNetworkExtension/Adapter.swift index c82b7bd39..1d34f638e 100644 --- a/swift/apple/FirezoneNetworkExtension/Adapter.swift +++ b/swift/apple/FirezoneNetworkExtension/Adapter.swift @@ -20,6 +20,10 @@ enum AdapterError: Error { /// connlib failed to start case connlibConnectError(String) + case setDnsError(String) + + case setDisabledResourcesError(String) + var localizedDescription: String { switch self { case .invalidSession(let session): @@ -27,6 +31,10 @@ enum AdapterError: Error { return message case .connlibConnectError(let error): return "connlib failed to start: \(error)" + case .setDnsError(let error): + return "failed to set new DNS serversn: \(error)" + case .setDisabledResourcesError(let error): + return "failed to set new disabled resources: \(error)" } } } @@ -136,7 +144,13 @@ class Adapter { let encoded = try? JSONEncoder().encode(resolvers), let jsonResolvers = String(data: encoded, encoding: .utf8)?.intoRustString() { - session?.setDns(jsonResolvers) + do { + try session?.setDns(jsonResolvers) + } catch let error { + // `toString` needed to deep copy the string and avoid a possible dangling pointer + let msg = (error as? RustString)?.toString() ?? "Unknown error" + Log.error(AdapterError.setDnsError(msg)) + } // Update our state tracker self.lastFetchedResolvers = resolvers @@ -307,7 +321,13 @@ class Adapter { fatalError("Should be able to encode 'disablingResources'") } - session?.setDisabledResources(toSet) + do { + try session?.setDisabledResources(toSet) + } catch let error { + // `toString` needed to deep copy the string and avoid a possible dangling pointer + let msg = (error as? RustString)?.toString() ?? "Unknown error" + Log.error(AdapterError.setDisabledResourcesError(msg)) + } } } diff --git a/swift/apple/FirezoneNetworkExtension/Connlib/Generated/connlib-client-apple/connlib-client-apple.h b/swift/apple/FirezoneNetworkExtension/Connlib/Generated/connlib-client-apple/connlib-client-apple.h index 662f4f926..7f8d035f8 100644 --- a/swift/apple/FirezoneNetworkExtension/Connlib/Generated/connlib-client-apple/connlib-client-apple.h +++ b/swift/apple/FirezoneNetworkExtension/Connlib/Generated/connlib-client-apple/connlib-client-apple.h @@ -13,8 +13,8 @@ void* __swift_bridge__$Vec_WrappedSession$as_ptr(void* vec_ptr); struct __private__ResultPtrAndPtr __swift_bridge__$WrappedSession$connect(void* api_url, void* token, void* device_id, void* account_slug, void* device_name_override, void* os_version_override, void* log_dir, void* log_filter, void* callback_handler, void* device_info); void __swift_bridge__$WrappedSession$reset(void* self); -void __swift_bridge__$WrappedSession$set_dns(void* self, void* dns_servers); -void __swift_bridge__$WrappedSession$set_disabled_resources(void* self, void* disabled_resources); +void* __swift_bridge__$WrappedSession$set_dns(void* self, void* dns_servers); +void* __swift_bridge__$WrappedSession$set_disabled_resources(void* self, void* disabled_resources); void __swift_bridge__$WrappedSession$disconnect(void* self); diff --git a/swift/apple/FirezoneNetworkExtension/Connlib/Generated/connlib-client-apple/connlib-client-apple.swift b/swift/apple/FirezoneNetworkExtension/Connlib/Generated/connlib-client-apple/connlib-client-apple.swift index e41456e2b..39bb89c88 100644 --- a/swift/apple/FirezoneNetworkExtension/Connlib/Generated/connlib-client-apple/connlib-client-apple.swift +++ b/swift/apple/FirezoneNetworkExtension/Connlib/Generated/connlib-client-apple/connlib-client-apple.swift @@ -46,12 +46,12 @@ extension WrappedSessionRefMut { __swift_bridge__$WrappedSession$reset(ptr) } - public func setDns(_ dns_servers: GenericIntoRustString) { - __swift_bridge__$WrappedSession$set_dns(ptr, { let rustString = dns_servers.intoRustString(); rustString.isOwned = false; return rustString.ptr }()) + public func setDns(_ dns_servers: GenericIntoRustString) throws -> () { + try { let val = __swift_bridge__$WrappedSession$set_dns(ptr, { let rustString = dns_servers.intoRustString(); rustString.isOwned = false; return rustString.ptr }()); if val != nil { throw RustString(ptr: val!) } else { return } }() } - public func setDisabledResources(_ disabled_resources: GenericIntoRustString) { - __swift_bridge__$WrappedSession$set_disabled_resources(ptr, { let rustString = disabled_resources.intoRustString(); rustString.isOwned = false; return rustString.ptr }()) + public func setDisabledResources(_ disabled_resources: GenericIntoRustString) throws -> () { + try { let val = __swift_bridge__$WrappedSession$set_disabled_resources(ptr, { let rustString = disabled_resources.intoRustString(); rustString.isOwned = false; return rustString.ptr }()); if val != nil { throw RustString(ptr: val!) } else { return } }() } } public class WrappedSessionRef { diff --git a/website/src/components/Changelog/Apple.tsx b/website/src/components/Changelog/Apple.tsx index a5f8d0714..1ebbc3f14 100644 --- a/website/src/components/Changelog/Apple.tsx +++ b/website/src/components/Changelog/Apple.tsx @@ -19,7 +19,11 @@ export default function Apple() { return ( {/* When you cut a release, remove any solved issues from the "known issues" lists over in `client-apps`. This must not be done when the issue's PR merges. */} - + + + Fixes a crash that occurred if the system reports invalid DNS servers. + + Fixes a rare crash that could occur when dismissing the update