@@ -11,6 +11,7 @@ use std::{
11
11
} ;
12
12
13
13
use super :: data:: { Destination , RouteMessage } ;
14
+ use system_configuration:: core_foundation:: string:: CFStringRef ;
14
15
use system_configuration:: {
15
16
core_foundation:: {
16
17
array:: CFArray ,
@@ -212,62 +213,29 @@ impl PrimaryInterfaceMonitor {
212
213
}
213
214
214
215
fn get_primary_interface ( & self , family : Family ) -> Option < NetworkServiceDetails > {
215
- let global_name = if family == Family :: V4 {
216
+ let key = if family == Family :: V4 {
216
217
STATE_IPV4_KEY
217
218
} else {
218
219
STATE_IPV6_KEY
219
220
} ;
220
- let global_dict = self
221
+ let ip_dict = self
221
222
. store
222
- . get ( CFString :: new ( global_name ) )
223
+ . get ( key )
223
224
. and_then ( |v| v. downcast_into :: < CFDictionary > ( ) ) ?;
224
- let name = global_dict
225
- . find ( unsafe { kSCDynamicStorePropNetPrimaryInterface } . to_void ( ) )
226
- . map ( |s| unsafe { CFType :: wrap_under_get_rule ( * s) } )
227
- . and_then ( |s| s. downcast :: < CFString > ( ) )
228
- . map ( |s| s. to_string ( ) )
229
- . or_else ( || {
230
- log:: debug!( "Missing name for primary interface ({family})" ) ;
231
- None
232
- } ) ?;
233
-
234
- let router_key = if family == Family :: V4 {
235
- unsafe { kSCPropNetIPv4Router. to_void ( ) }
236
- } else {
237
- unsafe { kSCPropNetIPv6Router. to_void ( ) }
238
- } ;
239
-
240
- let router_ip = global_dict
241
- . find ( router_key)
242
- . map ( |s| unsafe { CFType :: wrap_under_get_rule ( * s) } )
243
- . and_then ( |s| s. downcast :: < CFString > ( ) )
244
- . and_then ( |ip| ip. to_string ( ) . parse ( ) . ok ( ) )
245
- . or_else ( || {
246
- log:: debug!( "Missing router IP for primary interface \" {name}\" " ) ;
247
- None
248
- } ) ?;
249
-
250
- let ip_key = if family == Family :: V4 {
251
- unsafe { kSCPropNetIPv4Addresses. to_void ( ) }
252
- } else {
253
- unsafe { kSCPropNetIPv6Addresses. to_void ( ) }
254
- } ;
255
-
256
- let first_ip = global_dict
257
- . find ( ip_key)
258
- . map ( |s| unsafe { CFType :: wrap_under_get_rule ( * s) } )
259
- . and_then ( |s| s. downcast :: < CFArray > ( ) )
260
- . and_then ( |ips| {
261
- ips. get ( 0 )
262
- . map ( |ip| unsafe { CFType :: wrap_under_get_rule ( * ip) } )
263
- } )
264
- . and_then ( |s| s. downcast :: < CFString > ( ) )
265
- . and_then ( |ip| ip. to_string ( ) . parse ( ) . ok ( ) )
266
- . or_else ( || {
267
- log:: debug!( "Missing IP for primary interface \" {name}\" " ) ;
268
- None
269
- } ) ?;
270
-
225
+ let name =
226
+ get_dict_elem_as_string ( & ip_dict, unsafe { kSCDynamicStorePropNetPrimaryInterface } )
227
+ . or_else ( || {
228
+ log:: debug!( "Missing name for primary interface ({family})" ) ;
229
+ None
230
+ } ) ?;
231
+ let router_ip = get_service_router_ip ( & ip_dict, family) . or_else ( || {
232
+ log:: debug!( "Missing router IP for primary interface ({name}, {family})" ) ;
233
+ None
234
+ } ) ?;
235
+ let first_ip = get_service_first_ip ( & ip_dict, family) . or_else ( || {
236
+ log:: debug!( "Missing IP for primary interface ({name}, {family})" ) ;
237
+ None
238
+ } ) ?;
271
239
Some ( NetworkServiceDetails {
272
240
name,
273
241
router_ip,
@@ -276,67 +244,33 @@ impl PrimaryInterfaceMonitor {
276
244
}
277
245
278
246
fn network_services ( & self , family : Family ) -> Vec < NetworkServiceDetails > {
279
- let router_key = if family == Family :: V4 {
280
- unsafe { kSCPropNetIPv4Router. to_void ( ) }
281
- } else {
282
- unsafe { kSCPropNetIPv6Router. to_void ( ) }
283
- } ;
284
-
285
247
SCNetworkSet :: new ( & self . prefs )
286
248
. service_order ( )
287
249
. iter ( )
288
250
. filter_map ( |service_id| {
289
251
let service_id_s = service_id. to_string ( ) ;
290
- let key = if family == Family :: V4 {
252
+ let service_key = if family == Family :: V4 {
291
253
format ! ( "State:/Network/Service/{service_id_s}/IPv4" )
292
254
} else {
293
255
format ! ( "State:/Network/Service/{service_id_s}/IPv6" )
294
256
} ;
295
-
296
257
let ip_dict = self
297
258
. store
298
- . get ( CFString :: new ( & key ) )
259
+ . get ( CFString :: new ( & service_key ) )
299
260
. and_then ( |v| v. downcast_into :: < CFDictionary > ( ) ) ?;
300
- let name = ip_dict
301
- . find ( unsafe { kSCPropInterfaceName } . to_void ( ) )
302
- . map ( |s| unsafe { CFType :: wrap_under_get_rule ( * s) } )
303
- . and_then ( |s| s. downcast :: < CFString > ( ) )
304
- . map ( |s| s. to_string ( ) )
261
+ let name = get_dict_elem_as_string ( & ip_dict, unsafe { kSCPropInterfaceName } )
305
262
. or_else ( || {
306
- log:: debug!( "Missing name for service {service_id_s } ({family})" ) ;
263
+ log:: debug!( "Missing name for service {service_key } ({family})" ) ;
307
264
None
308
265
} ) ?;
309
- let router_ip = ip_dict
310
- . find ( router_key)
311
- . map ( |s| unsafe { CFType :: wrap_under_get_rule ( * s) } )
312
- . and_then ( |s| s. downcast :: < CFString > ( ) )
313
- . and_then ( |ip| ip. to_string ( ) . parse ( ) . ok ( ) )
314
- . or_else ( || {
315
- log:: debug!( "Missing router IP for {service_id_s} ({name}, {family})" ) ;
316
- None
317
- } ) ?;
318
-
319
- let ip_key = if family == Family :: V4 {
320
- unsafe { kSCPropNetIPv4Addresses. to_void ( ) }
321
- } else {
322
- unsafe { kSCPropNetIPv6Addresses. to_void ( ) }
323
- } ;
324
-
325
- let first_ip = ip_dict
326
- . find ( ip_key)
327
- . map ( |s| unsafe { CFType :: wrap_under_get_rule ( * s) } )
328
- . and_then ( |s| s. downcast :: < CFArray > ( ) )
329
- . and_then ( |ips| {
330
- ips. get ( 0 )
331
- . map ( |ip| unsafe { CFType :: wrap_under_get_rule ( * ip) } )
332
- } )
333
- . and_then ( |s| s. downcast :: < CFString > ( ) )
334
- . and_then ( |ip| ip. to_string ( ) . parse ( ) . ok ( ) )
335
- . or_else ( || {
336
- log:: debug!( "Missing IP for primary interface \" {name}\" " ) ;
337
- None
338
- } ) ?;
339
-
266
+ let router_ip = get_service_router_ip ( & ip_dict, family) . or_else ( || {
267
+ log:: debug!( "Missing router IP for {service_key} ({name}, {family})" ) ;
268
+ None
269
+ } ) ?;
270
+ let first_ip = get_service_first_ip ( & ip_dict, family) . or_else ( || {
271
+ log:: debug!( "Missing IP for \" {service_key}\" ({name}, {family})" ) ;
272
+ None
273
+ } ) ?;
340
274
Some ( NetworkServiceDetails {
341
275
name,
342
276
router_ip,
@@ -406,3 +340,43 @@ fn is_routable_v6(addr: &Ipv6Addr) -> bool {
406
340
fn is_link_local_v6 ( addr : & Ipv6Addr ) -> bool {
407
341
( addr. segments ( ) [ 0 ] & 0xffc0 ) == 0xfe80
408
342
}
343
+
344
+ fn get_service_router_ip ( ip_dict : & CFDictionary , family : Family ) -> Option < IpAddr > {
345
+ let router_key = if family == Family :: V4 {
346
+ unsafe { kSCPropNetIPv4Router }
347
+ } else {
348
+ unsafe { kSCPropNetIPv6Router }
349
+ } ;
350
+ get_dict_elem_as_string ( ip_dict, router_key) . and_then ( |ip| ip. parse ( ) . ok ( ) )
351
+ }
352
+
353
+ fn get_service_first_ip ( ip_dict : & CFDictionary , family : Family ) -> Option < IpAddr > {
354
+ let ip_key = if family == Family :: V4 {
355
+ unsafe { kSCPropNetIPv4Addresses }
356
+ } else {
357
+ unsafe { kSCPropNetIPv6Addresses }
358
+ } ;
359
+ ip_dict
360
+ . find ( ip_key. to_void ( ) )
361
+ . map ( |s| unsafe { CFType :: wrap_under_get_rule ( * s) } )
362
+ . and_then ( |s| s. downcast :: < CFArray > ( ) )
363
+ . and_then ( |ips| {
364
+ ips. get ( 0 )
365
+ . map ( |ip| unsafe { CFType :: wrap_under_get_rule ( * ip) } )
366
+ } )
367
+ . and_then ( |s| s. downcast :: < CFString > ( ) )
368
+ . map ( |s| s. to_string ( ) )
369
+ . and_then ( |ip| ip. parse ( ) . ok ( ) )
370
+ }
371
+
372
+ fn get_dict_elem_as_string ( dict : & CFDictionary , key : CFStringRef ) -> Option < String > {
373
+ dict. find ( key. to_void ( ) )
374
+ . map ( |s| unsafe { CFType :: wrap_under_get_rule ( * s) } )
375
+ . and_then ( |s| s. downcast :: < CFArray > ( ) )
376
+ . and_then ( |ips| {
377
+ ips. get ( 0 )
378
+ . map ( |ip| unsafe { CFType :: wrap_under_get_rule ( * ip) } )
379
+ } )
380
+ . and_then ( |s| s. downcast :: < CFString > ( ) )
381
+ . map ( |s| s. to_string ( ) )
382
+ }
0 commit comments