mirror of
https://github.com/outbackdingo/firezone.git
synced 2026-01-27 10:18:54 +00:00
chore(rust): make most of the Rust code compile on MacOS (#8924)
When working on the Rust code of Firezone from a MacOS computer, it is useful to have pretty much all of the code at least compile to ensure detect problems early. Eventually, once we target features like a headless MacOS client, some of these stubs will actually be filled in an be functional.
This commit is contained in:
10
.github/actions/setup-rust/action.yml
vendored
10
.github/actions/setup-rust/action.yml
vendored
@@ -14,8 +14,14 @@ outputs:
|
||||
(runner.os == 'Linux' && '--help') ||
|
||||
(runner.os == 'macOS' && '--help') ||
|
||||
(runner.os == 'Windows' && '-p firezone-bin-shared') }}
|
||||
packages:
|
||||
description: Compilable / testable packages for the current OS
|
||||
compile-packages:
|
||||
description: Compilable packages for the current OS
|
||||
value: ${{
|
||||
(runner.os == 'Linux' && '--workspace') ||
|
||||
(runner.os == 'macOS' && '--workspace --exclude ebpf-turn-router --exclude gui-smoke-test') ||
|
||||
(runner.os == 'Windows' && '-p connlib-client-shared -p connlib-model -p firezone-bin-shared -p firezone-gui-client -p firezone-gui-client-common -p firezone-headless-client -p firezone-logging -p firezone-telemetry -p firezone-tunnel -p gui-smoke-test -p http-test-server -p ip-packet -p phoenix-channel -p snownet -p socket-factory -p tun') }}
|
||||
test-packages:
|
||||
description: Testable packages for the current OS
|
||||
value: ${{
|
||||
(runner.os == 'Linux' && '--workspace') ||
|
||||
(runner.os == 'macOS' && '-p connlib-client-apple -p connlib-client-shared -p firezone-tunnel -p snownet') ||
|
||||
|
||||
8
.github/workflows/_rust.yml
vendored
8
.github/workflows/_rust.yml
vendored
@@ -62,13 +62,13 @@ jobs:
|
||||
with:
|
||||
tool: bpf-linker
|
||||
- run: |
|
||||
cargo +${{ steps.setup-rust.outputs.nightly_version }} udeps --all-targets --all-features ${{ steps.setup-rust.outputs.packages }}
|
||||
cargo +${{ steps.setup-rust.outputs.nightly_version }} udeps --all-targets --all-features ${{ steps.setup-rust.outputs.compile-packages }}
|
||||
name: Check for unused dependencies
|
||||
- run: cargo fmt -- --check
|
||||
- run: cargo doc --all-features --no-deps --document-private-items ${{ steps.setup-rust.outputs.packages }}
|
||||
- run: cargo doc --all-features --no-deps --document-private-items ${{ steps.setup-rust.outputs.compile-packages }}
|
||||
name: "cargo doc"
|
||||
shell: bash
|
||||
- run: cargo clippy --all-targets --all-features ${{ steps.setup-rust.outputs.packages }}
|
||||
- run: cargo clippy --all-targets --all-features ${{ steps.setup-rust.outputs.compile-packages }}
|
||||
name: "cargo clippy"
|
||||
shell: bash
|
||||
- run: cargo deny check --hide-inclusion-graph --deny unnecessary-skip
|
||||
@@ -114,7 +114,7 @@ jobs:
|
||||
set -x
|
||||
|
||||
# First, run all tests.
|
||||
cargo test --all-features ${{ steps.setup-rust.outputs.packages }} -- --include-ignored --nocapture
|
||||
cargo test --all-features ${{ steps.setup-rust.outputs.test-packages }} -- --include-ignored --nocapture
|
||||
|
||||
# Poor man's test coverage testing: Grep the generated logs for specific patterns / lines.
|
||||
rg --count --no-ignore SendIcmpPacket $TESTCASES_DIR
|
||||
|
||||
@@ -37,7 +37,6 @@ mod platform {
|
||||
net::UdpSocket,
|
||||
time::{Instant, timeout},
|
||||
};
|
||||
use tun::Tun as _;
|
||||
|
||||
pub(crate) async fn perf() -> Result<()> {
|
||||
const MTU: usize = 1_280;
|
||||
|
||||
@@ -17,6 +17,12 @@ pub mod windows;
|
||||
#[cfg(target_os = "windows")]
|
||||
pub use windows as platform;
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
pub mod macos;
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
pub use macos as platform;
|
||||
|
||||
pub const TOKEN_ENV_KEY: &str = "FIREZONE_TOKEN";
|
||||
|
||||
// wintun automatically append " Tunnel" to this
|
||||
@@ -40,8 +46,5 @@ pub const BUNDLE_ID: &str = "dev.firezone.client";
|
||||
/// Mark for Firezone sockets to prevent routing loops on Linux.
|
||||
pub const FIREZONE_MARK: u32 = 0xfd002021;
|
||||
|
||||
#[cfg(any(target_os = "linux", target_os = "windows"))]
|
||||
pub use network_changes::{new_dns_notifier, new_network_notifier};
|
||||
|
||||
#[cfg(any(target_os = "linux", target_os = "windows"))]
|
||||
pub use tun_device_manager::TunDeviceManager;
|
||||
|
||||
8
rust/bin-shared/src/macos.rs
Normal file
8
rust/bin-shared/src/macos.rs
Normal file
@@ -0,0 +1,8 @@
|
||||
#[derive(clap::ValueEnum, Clone, Copy, Debug, Default)]
|
||||
pub enum DnsControlMethod {
|
||||
#[default]
|
||||
None,
|
||||
}
|
||||
|
||||
pub use socket_factory::tcp as tcp_socket_factory;
|
||||
pub use socket_factory::udp as udp_socket_factory;
|
||||
@@ -10,5 +10,8 @@ mod imp;
|
||||
#[path = "network_changes/windows.rs"]
|
||||
mod imp;
|
||||
|
||||
#[cfg(any(target_os = "windows", target_os = "linux"))]
|
||||
#[cfg(target_os = "macos")]
|
||||
#[path = "network_changes/macos.rs"]
|
||||
mod imp;
|
||||
|
||||
pub use imp::{new_dns_notifier, new_network_notifier};
|
||||
|
||||
32
rust/bin-shared/src/network_changes/macos.rs
Normal file
32
rust/bin-shared/src/network_changes/macos.rs
Normal file
@@ -0,0 +1,32 @@
|
||||
use crate::platform::DnsControlMethod;
|
||||
use anyhow::{Result, bail};
|
||||
|
||||
pub async fn new_dns_notifier(
|
||||
_tokio_handle: tokio::runtime::Handle,
|
||||
_method: DnsControlMethod,
|
||||
) -> Result<Worker> {
|
||||
bail!("Not implemented")
|
||||
}
|
||||
|
||||
pub async fn new_network_notifier(
|
||||
_tokio_handle: tokio::runtime::Handle,
|
||||
_method: DnsControlMethod,
|
||||
) -> Result<Worker> {
|
||||
bail!("Not implemented")
|
||||
}
|
||||
|
||||
pub struct Worker;
|
||||
|
||||
impl Worker {
|
||||
#[expect(
|
||||
clippy::unused_async,
|
||||
reason = "Signture must match other operating systems"
|
||||
)]
|
||||
pub async fn notified(&mut self) -> Result<()> {
|
||||
bail!("Not implemented")
|
||||
}
|
||||
|
||||
pub fn close(self) -> Result<()> {
|
||||
bail!("Not implemented")
|
||||
}
|
||||
}
|
||||
@@ -10,5 +10,9 @@ pub mod windows;
|
||||
#[cfg(target_os = "windows")]
|
||||
pub use windows as platform;
|
||||
|
||||
#[cfg(any(target_os = "linux", target_os = "windows"))]
|
||||
#[cfg(target_os = "macos")]
|
||||
pub mod macos;
|
||||
#[cfg(target_os = "macos")]
|
||||
pub use macos as platform;
|
||||
|
||||
pub use platform::TunDeviceManager;
|
||||
|
||||
@@ -75,8 +75,8 @@ impl TunDeviceManager {
|
||||
})
|
||||
}
|
||||
|
||||
pub fn make_tun(&mut self) -> Result<Tun> {
|
||||
Ok(Tun::new(self.num_threads)?)
|
||||
pub fn make_tun(&mut self) -> Result<Box<dyn tun::Tun>> {
|
||||
Ok(Box::new(Tun::new(self.num_threads)?))
|
||||
}
|
||||
|
||||
#[tracing::instrument(level = "trace", skip(self))]
|
||||
|
||||
37
rust/bin-shared/src/tun_device_manager/macos.rs
Normal file
37
rust/bin-shared/src/tun_device_manager/macos.rs
Normal file
@@ -0,0 +1,37 @@
|
||||
use std::net::{Ipv4Addr, Ipv6Addr};
|
||||
|
||||
use anyhow::{Result, bail};
|
||||
use ip_network::{Ipv4Network, Ipv6Network};
|
||||
use tun::Tun;
|
||||
|
||||
pub struct TunDeviceManager {}
|
||||
|
||||
impl TunDeviceManager {
|
||||
pub fn new(_mtu: usize, _num_threads: usize) -> Result<Self> {
|
||||
bail!("Not implemented")
|
||||
}
|
||||
|
||||
pub fn make_tun(&mut self) -> Result<Box<dyn Tun>> {
|
||||
bail!("Not implemented")
|
||||
}
|
||||
|
||||
#[expect(
|
||||
clippy::unused_async,
|
||||
reason = "Signture must match other operating systems"
|
||||
)]
|
||||
pub async fn set_ips(&mut self, _ipv4: Ipv4Addr, _ipv6: Ipv6Addr) -> Result<()> {
|
||||
bail!("Not implemented")
|
||||
}
|
||||
|
||||
#[expect(
|
||||
clippy::unused_async,
|
||||
reason = "Signture must match other operating systems"
|
||||
)]
|
||||
pub async fn set_routes(
|
||||
&mut self,
|
||||
_ipv4: Vec<Ipv4Network>,
|
||||
_ipv6: Vec<Ipv6Network>,
|
||||
) -> Result<()> {
|
||||
bail!("Not implemented")
|
||||
}
|
||||
}
|
||||
@@ -68,12 +68,12 @@ impl TunDeviceManager {
|
||||
})
|
||||
}
|
||||
|
||||
pub fn make_tun(&mut self) -> Result<Tun> {
|
||||
pub fn make_tun(&mut self) -> Result<Box<dyn tun::Tun>> {
|
||||
let tun = Tun::new(self.mtu)?;
|
||||
self.iface_idx = Some(tun.iface_idx());
|
||||
self.luid = Some(tun.luid);
|
||||
|
||||
Ok(tun)
|
||||
Ok(Box::new(tun))
|
||||
}
|
||||
|
||||
#[tracing::instrument(level = "trace", skip(self))]
|
||||
|
||||
@@ -37,7 +37,7 @@ async fn smoke() {
|
||||
let listen_addr = SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::new(100, 100, 111, 1), 53));
|
||||
let mut dns_server = dns_over_tcp::Server::new(Instant::now());
|
||||
dns_server.set_listen_addresses::<CLIENT_CONCURRENCY>(BTreeSet::from([listen_addr]));
|
||||
let mut eventloop = Eventloop::new(Box::new(tun), dns_server);
|
||||
let mut eventloop = Eventloop::new(tun, dns_server);
|
||||
|
||||
tokio::spawn(std::future::poll_fn(move |cx| eventloop.poll(cx)));
|
||||
|
||||
|
||||
@@ -27,7 +27,6 @@ ip-packet = { workspace = true }
|
||||
ip_network = { workspace = true }
|
||||
libc = { workspace = true, features = ["std", "const-extern-fn", "extra_traits"] }
|
||||
moka = { workspace = true, features = ["future"] }
|
||||
nix = { workspace = true }
|
||||
num_cpus = { workspace = true }
|
||||
opentelemetry = { workspace = true, features = ["metrics"] }
|
||||
opentelemetry-stdout = { workspace = true, features = ["metrics"] }
|
||||
@@ -50,6 +49,7 @@ uuid = { workspace = true, features = ["v4"] }
|
||||
[target.'cfg(target_os = "linux")'.dependencies]
|
||||
caps = { workspace = true }
|
||||
jemallocator = { workspace = true }
|
||||
nix = { workspace = true }
|
||||
|
||||
[dev-dependencies]
|
||||
serde_json = { workspace = true, features = ["std"] }
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#[cfg(all(unix, not(target_arch = "arm")))]
|
||||
#[cfg(all(target_os = "linux", not(target_arch = "arm")))]
|
||||
#[global_allocator]
|
||||
static GLOBAL: jemallocator::Jemalloc = jemallocator::Jemalloc;
|
||||
|
||||
@@ -159,7 +159,7 @@ async fn try_main(cli: Cli) -> Result<ExitCode> {
|
||||
let tun = tun_device_manager
|
||||
.make_tun()
|
||||
.context("Failed to create TUN device")?;
|
||||
tunnel.set_tun(Box::new(tun));
|
||||
tunnel.set_tun(tun);
|
||||
|
||||
let task = tokio::spawn(future::poll_fn({
|
||||
let mut eventloop = Eventloop::new(tunnel, portal, tun_device_manager);
|
||||
|
||||
@@ -8,6 +8,7 @@ use anyhow::{Context as _, Result, bail};
|
||||
use secrecy::{ExposeSecret, SecretString};
|
||||
use url::Url;
|
||||
|
||||
#[cfg(any(target_os = "linux", target_os = "windows"))]
|
||||
pub(crate) const FZ_SCHEME: &str = "firezone-fd0020211111";
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
|
||||
@@ -1,26 +1,28 @@
|
||||
//! Placeholder
|
||||
use std::path::PathBuf;
|
||||
|
||||
use anyhow::Result;
|
||||
use anyhow::{Result, bail};
|
||||
use secrecy::Secret;
|
||||
|
||||
pub(crate) struct Server {}
|
||||
pub struct Server {}
|
||||
|
||||
impl Server {
|
||||
pub(crate) fn new() -> Result<Self> {
|
||||
tracing::warn!("This is not the actual Mac client");
|
||||
tracing::trace!(scheme = super::FZ_SCHEME, "prevents dead code warning");
|
||||
Ok(Self {})
|
||||
#[expect(
|
||||
clippy::unused_async,
|
||||
reason = "Signture must match other operating systems"
|
||||
)]
|
||||
pub async fn new() -> Result<Self> {
|
||||
bail!("not implemented")
|
||||
}
|
||||
|
||||
pub(crate) async fn accept(self) -> Result<Option<Secret<Vec<u8>>>> {
|
||||
pub async fn accept(self) -> Result<Option<Secret<Vec<u8>>>> {
|
||||
futures::future::pending().await
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) async fn open(_url: &url::Url) -> Result<()> {
|
||||
Ok(())
|
||||
pub async fn open(_url: &url::Url) -> Result<()> {
|
||||
bail!("not implemented")
|
||||
}
|
||||
|
||||
pub(crate) fn register() -> Result<()> {
|
||||
Ok(())
|
||||
pub fn register(_path: PathBuf) -> Result<()> {
|
||||
bail!("not implemented")
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@ pub(crate) fn run() -> Result<()> {
|
||||
// Our elevation is correct (not elevated), just run the GUI
|
||||
Ok(true) => run_gui(cli),
|
||||
Ok(false) => bail!("The GUI should run as a normal user, not elevated"),
|
||||
#[cfg(not(target_os = "windows"))] // Windows elevation check never fails.
|
||||
#[cfg(target_os = "linux")] // Windows/MacOS elevation check never fails.
|
||||
Err(error) => {
|
||||
show_error_dialog(&error.user_friendly_msg())?;
|
||||
Err(error.into())
|
||||
|
||||
@@ -69,6 +69,19 @@ mod platform {
|
||||
pub(crate) enum Error {}
|
||||
}
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
mod platform {
|
||||
use anyhow::Result;
|
||||
|
||||
#[expect(clippy::unnecessary_wraps)]
|
||||
pub(crate) fn gui_check() -> Result<bool, Error> {
|
||||
Ok(true)
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, thiserror::Error)]
|
||||
pub(crate) enum Error {}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
// Make sure it doesn't panic
|
||||
|
||||
@@ -30,10 +30,8 @@ pub(crate) mod system_tray;
|
||||
#[path = "gui/os_linux.rs"]
|
||||
mod os;
|
||||
|
||||
// Stub only
|
||||
#[cfg(target_os = "macos")]
|
||||
#[path = "gui/os_macos.rs"]
|
||||
#[expect(clippy::unnecessary_wraps)]
|
||||
mod os;
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
|
||||
@@ -1,23 +1,20 @@
|
||||
//! This file is a stub only to do Tauri UI dev natively on a Mac.
|
||||
use super::{ControllerRequest, CtlrTx};
|
||||
use anyhow::Result;
|
||||
use secrecy::SecretString;
|
||||
use super::CtlrTx;
|
||||
use anyhow::{Result, bail};
|
||||
|
||||
pub(crate) fn open_url(_app: &tauri::AppHandle, _url: &SecretString) -> Result<()> {
|
||||
unimplemented!()
|
||||
pub(crate) async fn set_autostart(_enabled: bool) -> Result<()> {
|
||||
bail!("Not implemented")
|
||||
}
|
||||
|
||||
/// Show a notification in the bottom right of the screen
|
||||
pub(crate) fn show_notification(_title: &str, _body: &str) -> Result<()> {
|
||||
unimplemented!()
|
||||
pub(crate) fn show_notification(_app: &tauri::AppHandle, _title: &str, _body: &str) -> Result<()> {
|
||||
bail!("Not implemented")
|
||||
}
|
||||
|
||||
/// Show a notification that signals `Controller` when clicked
|
||||
pub(crate) fn show_clickable_notification(
|
||||
_title: &str,
|
||||
pub(crate) fn show_update_notification(
|
||||
_app: &tauri::AppHandle,
|
||||
_ctlr_tx: CtlrTx,
|
||||
_body: &str,
|
||||
_tx: CtlrTx,
|
||||
_req: ControllerRequest,
|
||||
_url: url::Url,
|
||||
) -> Result<()> {
|
||||
unimplemented!()
|
||||
bail!("Not implemented")
|
||||
}
|
||||
|
||||
@@ -58,9 +58,6 @@ resolv-conf = { workspace = true }
|
||||
rtnetlink = { workspace = true }
|
||||
sd-notify = "0.4.5" # This is a pure Rust re-implementation, so it isn't vulnerable to CVE-2024-3094
|
||||
|
||||
[target.'cfg(target_os = "macos")'.dependencies]
|
||||
dirs = { workspace = true }
|
||||
|
||||
[target.'cfg(target_os = "windows")'.dependencies]
|
||||
ipconfig = "0.3.2"
|
||||
itertools = { workspace = true }
|
||||
|
||||
@@ -19,6 +19,11 @@ mod windows;
|
||||
#[cfg(target_os = "windows")]
|
||||
use windows as platform;
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
mod macos;
|
||||
#[cfg(target_os = "macos")]
|
||||
use macos as platform;
|
||||
|
||||
use platform::system_resolvers;
|
||||
|
||||
/// Controls system-wide DNS.
|
||||
|
||||
32
rust/headless-client/src/dns_control/macos.rs
Normal file
32
rust/headless-client/src/dns_control/macos.rs
Normal file
@@ -0,0 +1,32 @@
|
||||
use std::net::IpAddr;
|
||||
|
||||
use super::DnsController;
|
||||
use anyhow::{Result, bail};
|
||||
use dns_types::DomainName;
|
||||
use firezone_bin_shared::macos::DnsControlMethod;
|
||||
|
||||
impl DnsController {
|
||||
pub fn deactivate(&mut self) -> Result<()> {
|
||||
bail!("Not implemented")
|
||||
}
|
||||
|
||||
#[expect(
|
||||
clippy::unused_async,
|
||||
reason = "Signture must match other operating systems"
|
||||
)]
|
||||
pub async fn set_dns(
|
||||
&mut self,
|
||||
_dns_config: Vec<IpAddr>,
|
||||
_search_domain: Option<DomainName>,
|
||||
) -> Result<()> {
|
||||
bail!("Not implemented")
|
||||
}
|
||||
|
||||
pub fn flush(&self) -> Result<()> {
|
||||
bail!("Not implemented")
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn system_resolvers(_dns_control_method: DnsControlMethod) -> Result<Vec<IpAddr>> {
|
||||
bail!("Not implemented")
|
||||
}
|
||||
@@ -30,7 +30,7 @@ use std::{
|
||||
time::Duration,
|
||||
};
|
||||
use tokio::{sync::mpsc, time::Instant};
|
||||
use tracing_subscriber::{EnvFilter, Layer, Registry, layer::SubscriberExt};
|
||||
use tracing_subscriber::{Layer, Registry, layer::SubscriberExt};
|
||||
use url::Url;
|
||||
|
||||
pub mod ipc;
|
||||
@@ -48,13 +48,9 @@ pub mod platform;
|
||||
#[path = "ipc_service/windows.rs"]
|
||||
pub mod platform;
|
||||
|
||||
/// Default log filter for the IPC service
|
||||
#[cfg(debug_assertions)]
|
||||
const SERVICE_RUST_LOG: &str = "debug";
|
||||
|
||||
/// Default log filter for the IPC service
|
||||
#[cfg(not(debug_assertions))]
|
||||
const SERVICE_RUST_LOG: &str = "info";
|
||||
#[cfg(target_os = "macos")]
|
||||
#[path = "ipc_service/macos.rs"]
|
||||
pub mod platform;
|
||||
|
||||
#[derive(clap::Parser)]
|
||||
#[command(author, version, about, long_about = None)]
|
||||
@@ -616,7 +612,7 @@ impl<'a> Handler<'a> {
|
||||
.make_tun()
|
||||
.context("Failed to create TUN device")?
|
||||
};
|
||||
connlib.set_tun(Box::new(tun));
|
||||
connlib.set_tun(tun);
|
||||
|
||||
let session = Session { cb_rx, connlib };
|
||||
self.session = Some(session);
|
||||
@@ -652,7 +648,7 @@ fn setup_logging(
|
||||
std::fs::create_dir_all(&log_dir)
|
||||
.context("We should have permissions to create our log dir")?;
|
||||
|
||||
let directives = get_log_filter().context("Couldn't read log filter")?;
|
||||
let directives = crate::get_log_filter().context("Couldn't read log filter")?;
|
||||
|
||||
let (file_filter, file_reloader) = firezone_logging::try_filter(&directives)?;
|
||||
let (stdout_filter, stdout_reloader) = firezone_logging::try_filter(&directives)?;
|
||||
@@ -679,31 +675,6 @@ fn setup_logging(
|
||||
Ok((file_handle, file_reloader.merge(stdout_reloader)))
|
||||
}
|
||||
|
||||
/// Reads the log filter for the IPC service or for debug commands
|
||||
///
|
||||
/// e.g. `info`
|
||||
///
|
||||
/// Reads from:
|
||||
/// 1. `RUST_LOG` env var
|
||||
/// 2. `known_dirs::ipc_log_filter()` file
|
||||
/// 3. Hard-coded default `SERVICE_RUST_LOG`
|
||||
///
|
||||
/// Errors if something is badly wrong, e.g. the directory for the config file
|
||||
/// can't be computed
|
||||
pub(crate) fn get_log_filter() -> Result<String> {
|
||||
if let Ok(filter) = std::env::var(EnvFilter::DEFAULT_ENV) {
|
||||
return Ok(filter);
|
||||
}
|
||||
|
||||
if let Ok(filter) =
|
||||
std::fs::read_to_string(known_dirs::ipc_log_filter()?).map(|s| s.trim().to_string())
|
||||
{
|
||||
return Ok(filter);
|
||||
}
|
||||
|
||||
Ok(SERVICE_RUST_LOG.to_string())
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::{Cli, Cmd};
|
||||
|
||||
@@ -16,6 +16,10 @@ mod platform;
|
||||
#[path = "ipc/windows.rs"]
|
||||
pub mod platform;
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
#[path = "ipc/macos.rs"]
|
||||
pub mod platform;
|
||||
|
||||
pub(crate) use platform::Server;
|
||||
use platform::{ClientStream, ServerStream};
|
||||
|
||||
|
||||
34
rust/headless-client/src/ipc_service/ipc/macos.rs
Normal file
34
rust/headless-client/src/ipc_service/ipc/macos.rs
Normal file
@@ -0,0 +1,34 @@
|
||||
use super::ServiceId;
|
||||
use anyhow::{Result, bail};
|
||||
use tokio::net::UnixStream;
|
||||
|
||||
pub(crate) struct Server {}
|
||||
|
||||
pub type ClientStream = UnixStream;
|
||||
pub(crate) type ServerStream = UnixStream;
|
||||
|
||||
#[expect(
|
||||
clippy::unused_async,
|
||||
reason = "Signture must match other operating systems"
|
||||
)]
|
||||
pub async fn connect_to_service(_id: ServiceId) -> Result<ClientStream> {
|
||||
bail!("not implemented")
|
||||
}
|
||||
|
||||
impl Server {
|
||||
#[expect(
|
||||
clippy::unused_async,
|
||||
reason = "Signture must match other operating systems"
|
||||
)]
|
||||
pub(crate) async fn new(_id: ServiceId) -> Result<Self> {
|
||||
bail!("not implemented")
|
||||
}
|
||||
|
||||
#[expect(
|
||||
clippy::unused_async,
|
||||
reason = "Signture must match other operating systems"
|
||||
)]
|
||||
pub(crate) async fn next_client(&mut self) -> Result<ServerStream> {
|
||||
bail!("not implemented")
|
||||
}
|
||||
}
|
||||
17
rust/headless-client/src/ipc_service/macos.rs
Normal file
17
rust/headless-client/src/ipc_service/macos.rs
Normal file
@@ -0,0 +1,17 @@
|
||||
use super::CliCommon;
|
||||
use anyhow::{Result, bail};
|
||||
|
||||
pub(crate) fn run_ipc_service(cli: CliCommon) -> Result<()> {
|
||||
// We call this here to avoid a dead-code warning.
|
||||
let (_handle, _log_filter_reloader) = super::setup_logging(cli.log_dir)?;
|
||||
|
||||
bail!("not implemented")
|
||||
}
|
||||
|
||||
pub(crate) fn elevation_check() -> Result<bool> {
|
||||
bail!("not implemented")
|
||||
}
|
||||
|
||||
pub(crate) fn install_ipc_service() -> Result<()> {
|
||||
bail!("not implemented")
|
||||
}
|
||||
@@ -1,3 +1,5 @@
|
||||
use std::path::PathBuf;
|
||||
|
||||
pub fn ipc_service_config() -> Option<PathBuf> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ use std::{
|
||||
path::PathBuf,
|
||||
};
|
||||
use tokio::sync::mpsc;
|
||||
use tracing_subscriber::{Layer as _, Registry, fmt, layer::SubscriberExt as _};
|
||||
use tracing_subscriber::{EnvFilter, Layer as _, Registry, fmt, layer::SubscriberExt as _};
|
||||
|
||||
mod clear_logs;
|
||||
/// Generate a persistent device ID, stores it to disk, and reads it back.
|
||||
@@ -57,6 +57,10 @@ pub struct CliCommon {
|
||||
#[arg(long, env = "FIREZONE_DNS_CONTROL", default_value = "nrpt")]
|
||||
pub dns_control: DnsControlMethod,
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
#[arg(long, env = "FIREZONE_DNS_CONTROL", default_value = "none")]
|
||||
pub dns_control: DnsControlMethod,
|
||||
|
||||
/// File logging directory. Should be a path that's writeable by the current user.
|
||||
#[arg(short, long, env = "LOG_DIR")]
|
||||
pub log_dir: Option<PathBuf>,
|
||||
@@ -135,7 +139,7 @@ impl Callbacks for CallbackHandler {
|
||||
|
||||
/// Sets up logging for stdout only, with INFO level by default
|
||||
pub fn setup_stdout_logging() -> Result<FilterReloadHandle> {
|
||||
let directives = ipc_service::get_log_filter().context("Can't read log filter")?;
|
||||
let directives = get_log_filter().context("Can't read log filter")?;
|
||||
let (filter, reloader) = firezone_logging::try_filter(&directives)?;
|
||||
let layer = fmt::layer()
|
||||
.event_format(firezone_logging::Format::new())
|
||||
@@ -146,6 +150,36 @@ pub fn setup_stdout_logging() -> Result<FilterReloadHandle> {
|
||||
Ok(reloader)
|
||||
}
|
||||
|
||||
/// Reads the log filter for the IPC service or for debug commands
|
||||
///
|
||||
/// e.g. `info`
|
||||
///
|
||||
/// Reads from:
|
||||
/// 1. `RUST_LOG` env var
|
||||
/// 2. `known_dirs::ipc_log_filter()` file
|
||||
/// 3. Hard-coded default `SERVICE_RUST_LOG`
|
||||
///
|
||||
/// Errors if something is badly wrong, e.g. the directory for the config file
|
||||
/// can't be computed
|
||||
pub(crate) fn get_log_filter() -> Result<String> {
|
||||
#[cfg(not(debug_assertions))]
|
||||
const DEFAULT_LOG_FILTER: &str = "info";
|
||||
#[cfg(debug_assertions)]
|
||||
const DEFAULT_LOG_FILTER: &str = "debug";
|
||||
|
||||
if let Ok(filter) = std::env::var(EnvFilter::DEFAULT_ENV) {
|
||||
return Ok(filter);
|
||||
}
|
||||
|
||||
if let Ok(filter) =
|
||||
std::fs::read_to_string(known_dirs::ipc_log_filter()?).map(|s| s.trim().to_string())
|
||||
{
|
||||
return Ok(filter);
|
||||
}
|
||||
|
||||
Ok(DEFAULT_LOG_FILTER.to_string())
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
15
rust/headless-client/src/macos.rs
Normal file
15
rust/headless-client/src/macos.rs
Normal file
@@ -0,0 +1,15 @@
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
use anyhow::{Result, bail};
|
||||
|
||||
pub(crate) fn check_token_permissions(_path: &Path) -> Result<()> {
|
||||
bail!("Not implemented")
|
||||
}
|
||||
|
||||
pub(crate) fn default_token_path() -> PathBuf {
|
||||
PathBuf::from("/etc/dummy")
|
||||
}
|
||||
|
||||
pub(crate) fn notify_service_controller() -> Result<()> {
|
||||
bail!("Not implemented")
|
||||
}
|
||||
@@ -36,6 +36,10 @@ mod platform;
|
||||
#[path = "windows.rs"]
|
||||
mod platform;
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
#[path = "macos.rs"]
|
||||
mod platform;
|
||||
|
||||
use platform::default_token_path;
|
||||
|
||||
/// Command-line args for the headless Client
|
||||
@@ -260,7 +264,7 @@ fn main() -> Result<()> {
|
||||
|
||||
tun_device.make_tun()?
|
||||
};
|
||||
session.set_tun(Box::new(tun));
|
||||
session.set_tun(tun);
|
||||
session.set_dns(dns_controller.system_resolvers());
|
||||
|
||||
drop(connect_span);
|
||||
|
||||
@@ -6,4 +6,8 @@ mod platform;
|
||||
#[path = "signals/windows.rs"]
|
||||
mod platform;
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
#[path = "signals/macos.rs"]
|
||||
mod platform;
|
||||
|
||||
pub use platform::{Hangup, Terminate};
|
||||
|
||||
34
rust/headless-client/src/signals/macos.rs
Normal file
34
rust/headless-client/src/signals/macos.rs
Normal file
@@ -0,0 +1,34 @@
|
||||
use anyhow::{Result, bail};
|
||||
use futures::task::{Context, Poll};
|
||||
|
||||
pub struct Terminate {}
|
||||
|
||||
pub struct Hangup {}
|
||||
|
||||
impl Terminate {
|
||||
pub fn new() -> Result<Self> {
|
||||
bail!("Not implemented")
|
||||
}
|
||||
|
||||
pub fn poll_recv(&mut self, _cx: &mut Context<'_>) -> Poll<()> {
|
||||
Poll::Pending
|
||||
}
|
||||
|
||||
#[expect(
|
||||
clippy::unused_async,
|
||||
reason = "Signture must match other operating systems"
|
||||
)]
|
||||
pub async fn recv(&mut self) {}
|
||||
}
|
||||
|
||||
impl Hangup {
|
||||
pub fn new() -> Result<Self> {
|
||||
bail!("Not implemented")
|
||||
}
|
||||
|
||||
#[expect(
|
||||
clippy::unused_async,
|
||||
reason = "Signture must match other operating systems"
|
||||
)]
|
||||
pub async fn recv(&mut self) {}
|
||||
}
|
||||
@@ -45,6 +45,13 @@ pub fn get() -> Option<Duration> {
|
||||
Some(Duration::from_millis(ret))
|
||||
}
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
pub fn get() -> Option<Duration> {
|
||||
debug_assert!(false, "Not implemented on macOS");
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
#[test]
|
||||
|
||||
@@ -62,7 +62,7 @@ opentelemetry_sdk = { workspace = true, features = ["testing"] }
|
||||
test-strategy = { workspace = true }
|
||||
tokio = { workspace = true, features = ["process", "macros", "net"] }
|
||||
|
||||
[build-dependencies]
|
||||
[target.'cfg(target_os = "linux")'.build-dependencies]
|
||||
anyhow = "1"
|
||||
aya-build = { workspace = true }
|
||||
|
||||
|
||||
@@ -12,11 +12,11 @@ use crate::{AllocationPort, ClientSocket, PeerSocket};
|
||||
pub struct Program {}
|
||||
|
||||
impl Program {
|
||||
pub fn try_load(_: &'static str) -> Result<Self> {
|
||||
pub fn try_load(_: &str) -> Result<Self> {
|
||||
Err(anyhow::anyhow!("Platform not supported"))
|
||||
}
|
||||
|
||||
pub fn add_channel_binding_ipv4(
|
||||
pub fn add_channel_binding(
|
||||
&mut self,
|
||||
_: ClientSocket,
|
||||
_: ChannelNumber,
|
||||
@@ -26,7 +26,7 @@ impl Program {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn remove_channel_binding_ipv4(
|
||||
pub fn remove_channel_binding(
|
||||
&mut self,
|
||||
_: ClientSocket,
|
||||
_: ChannelNumber,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#![cfg_attr(test, allow(clippy::unwrap_used))]
|
||||
|
||||
#[cfg(all(unix, not(target_arch = "arm")))]
|
||||
#[cfg(all(target_os = "linux", not(target_arch = "arm")))]
|
||||
#[global_allocator]
|
||||
static GLOBAL: jemallocator::Jemalloc = jemallocator::Jemalloc;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user