Skip to main content

systemconfiguration/
network_interface.rs

1use serde::Deserialize;
2
3use crate::{bridge, error::Result, ffi, PropertyList, SystemConfigurationError};
4
5#[derive(Clone, Debug)]
6pub struct NetworkInterface {
7    raw: bridge::OwnedHandle,
8}
9
10#[derive(Clone, Debug, Deserialize, Eq, PartialEq)]
11pub struct NetworkInterfaceMtuInfo {
12    pub current: i32,
13    pub minimum: i32,
14    pub maximum: i32,
15}
16
17#[derive(Clone, Debug)]
18pub struct NetworkInterfaceMediaOptions {
19    pub current: Option<PropertyList>,
20    pub active: Option<PropertyList>,
21    pub available: Option<PropertyList>,
22}
23
24impl NetworkInterface {
25    pub fn type_id() -> u64 {
26        unsafe { ffi::network_interface::sc_network_interface_get_type_id() }
27    }
28
29    pub fn copy_all() -> Result<Vec<Self>> {
30        let raw = unsafe { ffi::network_interface::sc_network_interface_copy_all() };
31        if raw.is_null() {
32            return Err(SystemConfigurationError::last("sc_network_interface_copy_all"));
33        }
34        Ok(bridge::take_handle_array(raw, Self::from_owned_handle))
35    }
36
37    pub fn ipv4() -> Result<Self> {
38        let raw = unsafe { ffi::network_interface::sc_network_interface_copy_ipv4() };
39        let raw = bridge::owned_handle_or_last("sc_network_interface_copy_ipv4", raw)?;
40        Ok(Self::from_owned_handle(raw))
41    }
42
43    pub fn supported_interface_types(&self) -> Vec<String> {
44        bridge::take_string_array(unsafe {
45            ffi::network_interface::sc_network_interface_copy_supported_interface_types(self.raw.as_ptr())
46        })
47    }
48
49    pub fn supported_protocol_types(&self) -> Vec<String> {
50        bridge::take_string_array(unsafe {
51            ffi::network_interface::sc_network_interface_copy_supported_protocol_types(self.raw.as_ptr())
52        })
53    }
54
55    pub fn create_layered_interface(&self, interface_type: &str) -> Result<Option<Self>> {
56        let interface_type = bridge::cstring(interface_type, "sc_network_interface_create_with_interface")?;
57        let raw = unsafe {
58            ffi::network_interface::sc_network_interface_create_with_interface(
59                self.raw.as_ptr(),
60                interface_type.as_ptr(),
61            )
62        };
63        Ok(unsafe { bridge::OwnedHandle::from_raw(raw) }.map(Self::from_owned_handle))
64    }
65
66    pub fn bsd_name(&self) -> Result<Option<String>> {
67        Ok(bridge::take_optional_string(unsafe {
68            ffi::network_interface::sc_network_interface_copy_bsd_name(self.raw.as_ptr())
69        }))
70    }
71
72    pub fn configuration(&self) -> Option<PropertyList> {
73        unsafe { bridge::OwnedHandle::from_raw(ffi::network_interface::sc_network_interface_copy_configuration(self.raw.as_ptr())) }
74            .map(PropertyList::from_owned_handle)
75    }
76
77    pub fn extended_configuration(&self, extended_type: &str) -> Result<Option<PropertyList>> {
78        let extended_type = bridge::cstring(extended_type, "sc_network_interface_copy_extended_configuration")?;
79        let raw = unsafe {
80            ffi::network_interface::sc_network_interface_copy_extended_configuration(
81                self.raw.as_ptr(),
82                extended_type.as_ptr(),
83            )
84        };
85        Ok(unsafe { bridge::OwnedHandle::from_raw(raw) }.map(PropertyList::from_owned_handle))
86    }
87
88    pub fn hardware_address_string(&self) -> Result<Option<String>> {
89        Ok(bridge::take_optional_string(unsafe {
90            ffi::network_interface::sc_network_interface_copy_hardware_address(self.raw.as_ptr())
91        }))
92    }
93
94    pub fn underlying_interface(&self) -> Option<Self> {
95        unsafe {
96            bridge::OwnedHandle::from_raw(ffi::network_interface::sc_network_interface_copy_underlying_interface(
97                self.raw.as_ptr(),
98            ))
99        }
100        .map(Self::from_owned_handle)
101    }
102
103    pub fn interface_type(&self) -> Result<Option<String>> {
104        Ok(bridge::take_optional_string(unsafe {
105            ffi::network_interface::sc_network_interface_copy_interface_type(self.raw.as_ptr())
106        }))
107    }
108
109    pub fn localized_display_name(&self) -> Result<Option<String>> {
110        Ok(bridge::take_optional_string(unsafe {
111            ffi::network_interface::sc_network_interface_copy_localized_display_name(self.raw.as_ptr())
112        }))
113    }
114
115    pub fn media_options(&self, filter: bool) -> NetworkInterfaceMediaOptions {
116        let current = unsafe {
117            bridge::OwnedHandle::from_raw(ffi::network_interface::sc_network_interface_copy_media_options_current(
118                self.raw.as_ptr(),
119                u8::from(filter),
120            ))
121        }
122        .map(PropertyList::from_owned_handle);
123        let active = unsafe {
124            bridge::OwnedHandle::from_raw(ffi::network_interface::sc_network_interface_copy_media_options_active(
125                self.raw.as_ptr(),
126                u8::from(filter),
127            ))
128        }
129        .map(PropertyList::from_owned_handle);
130        let available = unsafe {
131            bridge::OwnedHandle::from_raw(ffi::network_interface::sc_network_interface_copy_media_options_available(
132                self.raw.as_ptr(),
133                u8::from(filter),
134            ))
135        }
136        .map(PropertyList::from_owned_handle);
137        NetworkInterfaceMediaOptions {
138            current,
139            active,
140            available,
141        }
142    }
143
144    pub fn media_subtypes(available: &PropertyList) -> Vec<String> {
145        bridge::take_string_array(unsafe {
146            ffi::network_interface::sc_network_interface_copy_media_subtypes(available.as_ptr())
147        })
148    }
149
150    pub fn media_subtype_options(available: &PropertyList, subtype: &str) -> Result<Vec<Vec<String>>> {
151        let subtype = bridge::cstring(subtype, "sc_network_interface_copy_media_subtype_options")?;
152        bridge::parse_json(
153            "sc_network_interface_copy_media_subtype_options",
154            unsafe {
155                ffi::network_interface::sc_network_interface_copy_media_subtype_options(
156                    available.as_ptr(),
157                    subtype.as_ptr(),
158                )
159            },
160        )
161    }
162
163    pub fn mtu_info(&self) -> Result<Option<NetworkInterfaceMtuInfo>> {
164        let raw = unsafe { ffi::network_interface::sc_network_interface_copy_mtu_info(self.raw.as_ptr()) };
165        if raw.is_null() {
166            return Ok(None);
167        }
168        bridge::parse_json("sc_network_interface_copy_mtu_info", raw).map(Some)
169    }
170
171    pub fn set_configuration(&self, config: Option<&PropertyList>) -> Result<()> {
172        let ok = unsafe {
173            ffi::network_interface::sc_network_interface_set_configuration(
174                self.raw.as_ptr(),
175                config.map_or(std::ptr::null_mut(), PropertyList::as_ptr),
176            )
177        };
178        bridge::bool_result("sc_network_interface_set_configuration", ok)
179    }
180
181    pub fn set_extended_configuration(
182        &self,
183        extended_type: &str,
184        config: Option<&PropertyList>,
185    ) -> Result<()> {
186        let extended_type = bridge::cstring(extended_type, "sc_network_interface_set_extended_configuration")?;
187        let ok = unsafe {
188            ffi::network_interface::sc_network_interface_set_extended_configuration(
189                self.raw.as_ptr(),
190                extended_type.as_ptr(),
191                config.map_or(std::ptr::null_mut(), PropertyList::as_ptr),
192            )
193        };
194        bridge::bool_result("sc_network_interface_set_extended_configuration", ok)
195    }
196
197    pub fn set_media_options<S: AsRef<str>>(&self, subtype: Option<&str>, options: &[S]) -> Result<()> {
198        let subtype = bridge::optional_cstring(subtype, "sc_network_interface_set_media_options")?;
199        let options = bridge::CStringArray::new(options, "sc_network_interface_set_media_options")?;
200        let ok = unsafe {
201            ffi::network_interface::sc_network_interface_set_media_options(
202                self.raw.as_ptr(),
203                subtype.as_ref().map_or(std::ptr::null(), |value| value.as_ptr()),
204                options.as_ptr(),
205                options.count(),
206            )
207        };
208        bridge::bool_result("sc_network_interface_set_media_options", ok)
209    }
210
211    pub fn set_mtu(&self, mtu: i32) -> Result<()> {
212        let ok = unsafe { ffi::network_interface::sc_network_interface_set_mtu(self.raw.as_ptr(), mtu) };
213        bridge::bool_result("sc_network_interface_set_mtu", ok)
214    }
215
216    pub fn force_configuration_refresh(&self) -> Result<()> {
217        let ok = unsafe { ffi::network_interface::sc_network_interface_force_configuration_refresh(self.raw.as_ptr()) };
218        bridge::bool_result("sc_network_interface_force_configuration_refresh", ok)
219    }
220
221    pub(crate) fn from_owned_handle(raw: bridge::OwnedHandle) -> Self {
222        Self { raw }
223    }
224
225    pub(crate) fn as_ptr(&self) -> bridge::RawHandle {
226        self.raw.as_ptr()
227    }
228}