systemconfiguration/
network_interface.rs1use 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}