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)]
6/// Wraps `SCNetworkInterfaceRef`.
7pub struct NetworkInterface {
8    raw: bridge::OwnedHandle,
9}
10
11#[derive(Clone, Debug, Deserialize, Eq, PartialEq)]
12/// Wraps `SCNetworkInterfaceCopyMTU` results.
13pub struct NetworkInterfaceMtuInfo {
14    /// Wraps the current MTU returned by `SCNetworkInterfaceCopyMTU`.
15    pub current: i32,
16    /// Wraps the minimum MTU returned by `SCNetworkInterfaceCopyMTU`.
17    pub minimum: i32,
18    /// Wraps the maximum MTU returned by `SCNetworkInterfaceCopyMTU`.
19    pub maximum: i32,
20}
21
22#[derive(Clone, Debug)]
23/// Wraps `SCNetworkInterfaceCopyMediaOptions` results.
24pub struct NetworkInterfaceMediaOptions {
25    /// Wraps the current media options from `SCNetworkInterfaceCopyMediaOptions`.
26    pub current: Option<PropertyList>,
27    /// Wraps the active media options from `SCNetworkInterfaceCopyMediaOptions`.
28    pub active: Option<PropertyList>,
29    /// Wraps the available media options from `SCNetworkInterfaceCopyMediaOptions`.
30    pub available: Option<PropertyList>,
31}
32
33impl NetworkInterface {
34    /// Wraps `SCNetworkInterfaceGetTypeID`.
35    pub fn type_id() -> u64 {
36        unsafe { ffi::network_interface::sc_network_interface_get_type_id() }
37    }
38
39    /// Wraps `SCNetworkInterfaceCopyAll`.
40    pub fn copy_all() -> Result<Vec<Self>> {
41        let raw = unsafe { ffi::network_interface::sc_network_interface_copy_all() };
42        if raw.is_null() {
43            return Err(SystemConfigurationError::last(
44                "sc_network_interface_copy_all",
45            ));
46        }
47        Ok(bridge::take_handle_array(raw, Self::from_owned_handle))
48    }
49
50    /// Wraps `SCNetworkInterfaceCopyIPv4`.
51    pub fn ipv4() -> Result<Self> {
52        let raw = unsafe { ffi::network_interface::sc_network_interface_copy_ipv4() };
53        let raw = bridge::owned_handle_or_last("sc_network_interface_copy_ipv4", raw)?;
54        Ok(Self::from_owned_handle(raw))
55    }
56
57    /// Wraps `SCNetworkInterfaceCopySupportedInterfaceTypes`.
58    pub fn supported_interface_types(&self) -> Vec<String> {
59        bridge::take_string_array(unsafe {
60            ffi::network_interface::sc_network_interface_copy_supported_interface_types(
61                self.raw.as_ptr(),
62            )
63        })
64    }
65
66    /// Wraps `SCNetworkInterfaceCopySupportedProtocolTypes`.
67    pub fn supported_protocol_types(&self) -> Vec<String> {
68        bridge::take_string_array(unsafe {
69            ffi::network_interface::sc_network_interface_copy_supported_protocol_types(
70                self.raw.as_ptr(),
71            )
72        })
73    }
74
75    /// Wraps `SCNetworkInterfaceCreateWithInterface`.
76    pub fn create_layered_interface(&self, interface_type: &str) -> Result<Option<Self>> {
77        let interface_type =
78            bridge::cstring(interface_type, "sc_network_interface_create_with_interface")?;
79        let raw = unsafe {
80            ffi::network_interface::sc_network_interface_create_with_interface(
81                self.raw.as_ptr(),
82                interface_type.as_ptr(),
83            )
84        };
85        Ok(unsafe { bridge::OwnedHandle::from_raw(raw) }.map(Self::from_owned_handle))
86    }
87
88    /// Wraps `SCNetworkInterfaceCopyBSDName`.
89    pub fn bsd_name(&self) -> Result<Option<String>> {
90        Ok(bridge::take_optional_string(unsafe {
91            ffi::network_interface::sc_network_interface_copy_bsd_name(self.raw.as_ptr())
92        }))
93    }
94
95    /// Wraps `SCNetworkInterfaceCopyConfiguration`.
96    pub fn configuration(&self) -> Option<PropertyList> {
97        unsafe {
98            bridge::OwnedHandle::from_raw(
99                ffi::network_interface::sc_network_interface_copy_configuration(self.raw.as_ptr()),
100            )
101        }
102        .map(PropertyList::from_owned_handle)
103    }
104
105    /// Wraps `SCNetworkInterfaceCopyExtendedConfiguration`.
106    pub fn extended_configuration(&self, extended_type: &str) -> Result<Option<PropertyList>> {
107        let extended_type = bridge::cstring(
108            extended_type,
109            "sc_network_interface_copy_extended_configuration",
110        )?;
111        let raw = unsafe {
112            ffi::network_interface::sc_network_interface_copy_extended_configuration(
113                self.raw.as_ptr(),
114                extended_type.as_ptr(),
115            )
116        };
117        Ok(unsafe { bridge::OwnedHandle::from_raw(raw) }.map(PropertyList::from_owned_handle))
118    }
119
120    /// Wraps `SCNetworkInterfaceCopyHardwareAddress`.
121    pub fn hardware_address_string(&self) -> Result<Option<String>> {
122        Ok(bridge::take_optional_string(unsafe {
123            ffi::network_interface::sc_network_interface_copy_hardware_address(self.raw.as_ptr())
124        }))
125    }
126
127    /// Wraps `SCNetworkInterfaceCopyUnderlyingInterface`.
128    pub fn underlying_interface(&self) -> Option<Self> {
129        unsafe {
130            bridge::OwnedHandle::from_raw(
131                ffi::network_interface::sc_network_interface_copy_underlying_interface(
132                    self.raw.as_ptr(),
133                ),
134            )
135        }
136        .map(Self::from_owned_handle)
137    }
138
139    /// Wraps `SCNetworkInterfaceCopyInterfaceType`.
140    pub fn interface_type(&self) -> Result<Option<String>> {
141        Ok(bridge::take_optional_string(unsafe {
142            ffi::network_interface::sc_network_interface_copy_interface_type(self.raw.as_ptr())
143        }))
144    }
145
146    /// Wraps `SCNetworkInterfaceCopyLocalizedDisplayName`.
147    pub fn localized_display_name(&self) -> Result<Option<String>> {
148        Ok(bridge::take_optional_string(unsafe {
149            ffi::network_interface::sc_network_interface_copy_localized_display_name(
150                self.raw.as_ptr(),
151            )
152        }))
153    }
154
155    /// Wraps `SCNetworkInterfaceCopyMediaOptionsCurrent`.
156    pub fn media_options(&self, filter: bool) -> NetworkInterfaceMediaOptions {
157        let current = unsafe {
158            bridge::OwnedHandle::from_raw(
159                ffi::network_interface::sc_network_interface_copy_media_options_current(
160                    self.raw.as_ptr(),
161                    u8::from(filter),
162                ),
163            )
164        }
165        .map(PropertyList::from_owned_handle);
166        let active = unsafe {
167            bridge::OwnedHandle::from_raw(
168                ffi::network_interface::sc_network_interface_copy_media_options_active(
169                    self.raw.as_ptr(),
170                    u8::from(filter),
171                ),
172            )
173        }
174        .map(PropertyList::from_owned_handle);
175        let available = unsafe {
176            bridge::OwnedHandle::from_raw(
177                ffi::network_interface::sc_network_interface_copy_media_options_available(
178                    self.raw.as_ptr(),
179                    u8::from(filter),
180                ),
181            )
182        }
183        .map(PropertyList::from_owned_handle);
184        NetworkInterfaceMediaOptions {
185            current,
186            active,
187            available,
188        }
189    }
190
191    /// Wraps `SCNetworkInterfaceCopyMediaSubtypes`.
192    pub fn media_subtypes(available: &PropertyList) -> Vec<String> {
193        bridge::take_string_array(unsafe {
194            ffi::network_interface::sc_network_interface_copy_media_subtypes(available.as_ptr())
195        })
196    }
197
198    /// Wraps `SCNetworkInterfaceCopyMediaSubtypeOptions`.
199    pub fn media_subtype_options(
200        available: &PropertyList,
201        subtype: &str,
202    ) -> Result<Vec<Vec<String>>> {
203        let subtype = bridge::cstring(subtype, "sc_network_interface_copy_media_subtype_options")?;
204        bridge::parse_json("sc_network_interface_copy_media_subtype_options", unsafe {
205            ffi::network_interface::sc_network_interface_copy_media_subtype_options(
206                available.as_ptr(),
207                subtype.as_ptr(),
208            )
209        })
210    }
211
212    /// Wraps `SCNetworkInterfaceCopyMTUInfo`.
213    pub fn mtu_info(&self) -> Result<Option<NetworkInterfaceMtuInfo>> {
214        let raw = unsafe {
215            ffi::network_interface::sc_network_interface_copy_mtu_info(self.raw.as_ptr())
216        };
217        if raw.is_null() {
218            return Ok(None);
219        }
220        bridge::parse_json("sc_network_interface_copy_mtu_info", raw).map(Some)
221    }
222
223    /// Wraps `SCNetworkInterfaceSetConfiguration`.
224    pub fn set_configuration(&self, config: Option<&PropertyList>) -> Result<()> {
225        let ok = unsafe {
226            ffi::network_interface::sc_network_interface_set_configuration(
227                self.raw.as_ptr(),
228                config.map_or(std::ptr::null_mut(), PropertyList::as_ptr),
229            )
230        };
231        bridge::bool_result("sc_network_interface_set_configuration", ok)
232    }
233
234    /// Wraps `SCNetworkInterfaceSetExtendedConfiguration`.
235    pub fn set_extended_configuration(
236        &self,
237        extended_type: &str,
238        config: Option<&PropertyList>,
239    ) -> Result<()> {
240        let extended_type = bridge::cstring(
241            extended_type,
242            "sc_network_interface_set_extended_configuration",
243        )?;
244        let ok = unsafe {
245            ffi::network_interface::sc_network_interface_set_extended_configuration(
246                self.raw.as_ptr(),
247                extended_type.as_ptr(),
248                config.map_or(std::ptr::null_mut(), PropertyList::as_ptr),
249            )
250        };
251        bridge::bool_result("sc_network_interface_set_extended_configuration", ok)
252    }
253
254    /// Wraps `SCNetworkInterfaceSetMediaOptions`.
255    pub fn set_media_options<S: AsRef<str>>(
256        &self,
257        subtype: Option<&str>,
258        options: &[S],
259    ) -> Result<()> {
260        let subtype = bridge::optional_cstring(subtype, "sc_network_interface_set_media_options")?;
261        let options = bridge::CStringArray::new(options, "sc_network_interface_set_media_options")?;
262        let ok = unsafe {
263            ffi::network_interface::sc_network_interface_set_media_options(
264                self.raw.as_ptr(),
265                subtype
266                    .as_ref()
267                    .map_or(std::ptr::null(), |value| value.as_ptr()),
268                options.as_ptr(),
269                options.count(),
270            )
271        };
272        bridge::bool_result("sc_network_interface_set_media_options", ok)
273    }
274
275    /// Wraps `SCNetworkInterfaceSetMTU`.
276    pub fn set_mtu(&self, mtu: i32) -> Result<()> {
277        let ok =
278            unsafe { ffi::network_interface::sc_network_interface_set_mtu(self.raw.as_ptr(), mtu) };
279        bridge::bool_result("sc_network_interface_set_mtu", ok)
280    }
281
282    /// Wraps `SCNetworkInterfaceForceConfigurationRefresh`.
283    pub fn force_configuration_refresh(&self) -> Result<()> {
284        let ok = unsafe {
285            ffi::network_interface::sc_network_interface_force_configuration_refresh(
286                self.raw.as_ptr(),
287            )
288        };
289        bridge::bool_result("sc_network_interface_force_configuration_refresh", ok)
290    }
291
292    pub(crate) fn from_owned_handle(raw: bridge::OwnedHandle) -> Self {
293        Self { raw }
294    }
295
296    pub(crate) fn as_ptr(&self) -> bridge::RawHandle {
297        self.raw.as_ptr()
298    }
299}