@@ -7,6 +7,10 @@ use std::path::Path;
7
7
use std:: os:: unix:: ffi:: OsStrExt ;
8
8
#[ cfg( any( target_os = "linux" , target_os = "android" ) ) ]
9
9
use :: sys:: socket:: addr:: netlink:: NetlinkAddr ;
10
+ #[ cfg( any( target_os = "macos" , target_os = "ios" ) ) ]
11
+ use std:: os:: unix:: io:: RawFd ;
12
+ #[ cfg( any( target_os = "macos" , target_os = "ios" ) ) ]
13
+ use :: sys:: socket:: addr:: sys_control:: SysControlAddr ;
10
14
11
15
// TODO: uncomment out IpAddr functions: rust-lang/rfcs#988
12
16
@@ -26,6 +30,8 @@ pub enum AddressFamily {
26
30
Netlink = consts:: AF_NETLINK ,
27
31
#[ cfg( any( target_os = "linux" , target_os = "android" ) ) ]
28
32
Packet = consts:: AF_PACKET ,
33
+ #[ cfg( any( target_os = "macos" , target_os = "ios" ) ) ]
34
+ System = consts:: AF_SYSTEM ,
29
35
}
30
36
31
37
#[ derive( Copy ) ]
@@ -475,7 +481,9 @@ pub enum SockAddr {
475
481
Inet ( InetAddr ) ,
476
482
Unix ( UnixAddr ) ,
477
483
#[ cfg( any( target_os = "linux" , target_os = "android" ) ) ]
478
- Netlink ( NetlinkAddr )
484
+ Netlink ( NetlinkAddr ) ,
485
+ #[ cfg( any( target_os = "macos" , target_os = "ios" ) ) ]
486
+ SysControl ( SysControlAddr ) ,
479
487
}
480
488
481
489
impl SockAddr {
@@ -492,13 +500,20 @@ impl SockAddr {
492
500
SockAddr :: Netlink ( NetlinkAddr :: new ( pid, groups) )
493
501
}
494
502
503
+ #[ cfg( any( target_os = "macos" , target_os = "ios" ) ) ]
504
+ pub fn new_sys_control ( sockfd : RawFd , name : & str , unit : u32 ) -> Result < SockAddr > {
505
+ SysControlAddr :: from_name ( sockfd, name, unit) . map ( |a| SockAddr :: SysControl ( a) )
506
+ }
507
+
495
508
pub fn family ( & self ) -> AddressFamily {
496
509
match * self {
497
510
SockAddr :: Inet ( InetAddr :: V4 ( ..) ) => AddressFamily :: Inet ,
498
511
SockAddr :: Inet ( InetAddr :: V6 ( ..) ) => AddressFamily :: Inet6 ,
499
512
SockAddr :: Unix ( ..) => AddressFamily :: Unix ,
500
513
#[ cfg( any( target_os = "linux" , target_os = "android" ) ) ]
501
514
SockAddr :: Netlink ( ..) => AddressFamily :: Netlink ,
515
+ #[ cfg( any( target_os = "macos" , target_os = "ios" ) ) ]
516
+ SockAddr :: SysControl ( ..) => AddressFamily :: System ,
502
517
}
503
518
}
504
519
@@ -513,6 +528,8 @@ impl SockAddr {
513
528
SockAddr :: Unix ( UnixAddr ( ref addr, len) ) => ( mem:: transmute ( addr) , ( len + offset_of ! ( libc:: sockaddr_un, sun_path) ) as libc:: socklen_t ) ,
514
529
#[ cfg( any( target_os = "linux" , target_os = "android" ) ) ]
515
530
SockAddr :: Netlink ( NetlinkAddr ( ref sa) ) => ( mem:: transmute ( sa) , mem:: size_of :: < libc:: sockaddr_nl > ( ) as libc:: socklen_t ) ,
531
+ #[ cfg( any( target_os = "macos" , target_os = "ios" ) ) ]
532
+ SockAddr :: SysControl ( SysControlAddr ( ref sa) ) => ( mem:: transmute ( sa) , mem:: size_of :: < sys_control:: sockaddr_ctl > ( ) as libc:: socklen_t ) ,
516
533
}
517
534
}
518
535
}
@@ -545,6 +562,8 @@ impl hash::Hash for SockAddr {
545
562
SockAddr :: Unix ( ref a) => a. hash ( s) ,
546
563
#[ cfg( any( target_os = "linux" , target_os = "android" ) ) ]
547
564
SockAddr :: Netlink ( ref a) => a. hash ( s) ,
565
+ #[ cfg( any( target_os = "macos" , target_os = "ios" ) ) ]
566
+ SockAddr :: SysControl ( ref a) => a. hash ( s) ,
548
567
}
549
568
}
550
569
}
@@ -562,6 +581,8 @@ impl fmt::Display for SockAddr {
562
581
SockAddr :: Unix ( ref unix) => unix. fmt ( f) ,
563
582
#[ cfg( any( target_os = "linux" , target_os = "android" ) ) ]
564
583
SockAddr :: Netlink ( ref nl) => nl. fmt ( f) ,
584
+ #[ cfg( any( target_os = "macos" , target_os = "ios" ) ) ]
585
+ SockAddr :: SysControl ( ref sc) => sc. fmt ( f) ,
565
586
}
566
587
}
567
588
}
@@ -620,3 +641,102 @@ pub mod netlink {
620
641
}
621
642
}
622
643
}
644
+
645
+ #[ cfg( any( target_os = "macos" , target_os = "ios" ) ) ]
646
+ pub mod sys_control {
647
+ use :: sys:: socket:: consts;
648
+ use :: sys:: socket:: addr:: { AddressFamily } ;
649
+ use libc:: { c_uchar, uint16_t, uint32_t} ;
650
+ use std:: { fmt, mem} ;
651
+ use std:: hash:: { Hash , Hasher } ;
652
+ use std:: os:: unix:: io:: RawFd ;
653
+ use { Errno , Error , Result } ;
654
+
655
+ #[ repr( C ) ]
656
+ pub struct ctl_ioc_info {
657
+ pub ctl_id : uint32_t ,
658
+ pub ctl_name : [ c_uchar ; MAX_KCTL_NAME ] ,
659
+ }
660
+
661
+ const CTL_IOC_MAGIC : u8 = 'N' as u8 ;
662
+ const CTL_IOC_INFO : u8 = 3 ;
663
+ const MAX_KCTL_NAME : usize = 96 ;
664
+
665
+ ioctl ! ( readwrite ctl_info with CTL_IOC_MAGIC , CTL_IOC_INFO ; ctl_ioc_info) ;
666
+
667
+ #[ repr( C ) ]
668
+ #[ derive( Copy , Clone ) ]
669
+ pub struct sockaddr_ctl {
670
+ pub sc_len : c_uchar ,
671
+ pub sc_family : c_uchar ,
672
+ pub ss_sysaddr : uint16_t ,
673
+ pub sc_id : uint32_t ,
674
+ pub sc_unit : uint32_t ,
675
+ pub sc_reserved : [ uint32_t ; 5 ] ,
676
+ }
677
+
678
+ #[ derive( Copy , Clone ) ]
679
+ pub struct SysControlAddr ( pub sockaddr_ctl ) ;
680
+
681
+ // , PartialEq, Eq, Debug, Hash
682
+ impl PartialEq for SysControlAddr {
683
+ fn eq ( & self , other : & Self ) -> bool {
684
+ let ( inner, other) = ( self . 0 , other. 0 ) ;
685
+ ( inner. sc_id , inner. sc_unit ) ==
686
+ ( other. sc_id , other. sc_unit )
687
+ }
688
+ }
689
+
690
+ impl Eq for SysControlAddr { }
691
+
692
+ impl Hash for SysControlAddr {
693
+ fn hash < H : Hasher > ( & self , s : & mut H ) {
694
+ let inner = self . 0 ;
695
+ ( inner. sc_id , inner. sc_unit ) . hash ( s) ;
696
+ }
697
+ }
698
+
699
+
700
+ impl SysControlAddr {
701
+ pub fn new ( id : u32 , unit : u32 ) -> SysControlAddr {
702
+ let addr = sockaddr_ctl {
703
+ sc_len : mem:: size_of :: < sockaddr_ctl > ( ) as c_uchar ,
704
+ sc_family : AddressFamily :: System as c_uchar ,
705
+ ss_sysaddr : consts:: AF_SYS_CONTROL as uint16_t ,
706
+ sc_id : id,
707
+ sc_unit : unit,
708
+ sc_reserved : [ 0 ; 5 ]
709
+ } ;
710
+
711
+ SysControlAddr ( addr)
712
+ }
713
+
714
+ pub fn from_name ( sockfd : RawFd , name : & str , unit : u32 ) -> Result < SysControlAddr > {
715
+ if name. len ( ) > MAX_KCTL_NAME {
716
+ return Err ( Error :: Sys ( Errno :: ENAMETOOLONG ) ) ;
717
+ }
718
+
719
+ let mut ctl_name = [ 0 ; MAX_KCTL_NAME ] ;
720
+ ctl_name[ ..name. len ( ) ] . clone_from_slice ( name. as_bytes ( ) ) ;
721
+ let mut info = ctl_ioc_info { ctl_id : 0 , ctl_name : ctl_name } ;
722
+
723
+ unsafe { try!( ctl_info ( sockfd, & mut info) ) ; }
724
+
725
+ Ok ( SysControlAddr :: new ( info. ctl_id , unit) )
726
+ }
727
+
728
+ pub fn id ( & self ) -> u32 {
729
+ self . 0 . sc_id
730
+ }
731
+
732
+ pub fn unit ( & self ) -> u32 {
733
+ self . 0 . sc_unit
734
+ }
735
+ }
736
+
737
+ impl fmt:: Display for SysControlAddr {
738
+ fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
739
+ write ! ( f, "id: {} unit: {}" , self . id( ) , self . unit( ) )
740
+ }
741
+ }
742
+ }
0 commit comments