@@ -206,7 +206,7 @@ impl AddressFamily {
206
206
/// Create a new `AddressFamily` from an integer value retrieved from `libc`, usually from
207
207
/// the `sa_family` field of a `sockaddr`.
208
208
///
209
- /// Currently only supports these address families: Unix, Inet (v4 & v6), Netlink
209
+ /// Currently only supports these address families: Unix, Inet (v4 & v6), Netlink, Link
210
210
/// and System. Returns None for unsupported or unknown address families.
211
211
pub fn from_i32 ( family : i32 ) -> Option < AddressFamily > {
212
212
match family {
@@ -217,6 +217,15 @@ impl AddressFamily {
217
217
libc:: AF_NETLINK => Some ( AddressFamily :: Netlink ) ,
218
218
#[ cfg( any( target_os = "macos" , target_os = "macos" ) ) ]
219
219
libc:: AF_SYSTEM => Some ( AddressFamily :: System ) ,
220
+ #[ cfg( any( target_os = "android" , target_os = "linux" ) ) ]
221
+ libc:: AF_PACKET => Some ( AddressFamily :: Packet ) ,
222
+ #[ cfg( any( target_os = "dragonfly" ,
223
+ target_os = "freebsd" ,
224
+ target_os = "ios" ,
225
+ target_os = "macos" ,
226
+ target_os = "netbsd" ,
227
+ target_os = "openbsd" ) ) ]
228
+ libc:: AF_LINK => Some ( AddressFamily :: Link ) ,
220
229
_ => None
221
230
}
222
231
}
@@ -721,6 +730,8 @@ pub enum SockAddr {
721
730
Netlink ( NetlinkAddr ) ,
722
731
#[ cfg( any( target_os = "ios" , target_os = "macos" ) ) ]
723
732
SysControl ( SysControlAddr ) ,
733
+ /// Ethernet MAC address
734
+ Ether ( EtherAddr )
724
735
}
725
736
726
737
impl SockAddr {
@@ -751,6 +762,15 @@ impl SockAddr {
751
762
SockAddr :: Netlink ( ..) => AddressFamily :: Netlink ,
752
763
#[ cfg( any( target_os = "ios" , target_os = "macos" ) ) ]
753
764
SockAddr :: SysControl ( ..) => AddressFamily :: System ,
765
+ #[ cfg( any( target_os = "android" , target_os = "linux" ) ) ]
766
+ SockAddr :: Ether ( ..) => AddressFamily :: Packet ,
767
+ #[ cfg( any( target_os = "dragonfly" ,
768
+ target_os = "freebsd" ,
769
+ target_os = "ios" ,
770
+ target_os = "macos" ,
771
+ target_os = "netbsd" ,
772
+ target_os = "openbsd" ) ) ]
773
+ SockAddr :: Ether ( ..) => AddressFamily :: Link
754
774
}
755
775
}
756
776
@@ -778,6 +798,23 @@ impl SockAddr {
778
798
#[ cfg( any( target_os = "ios" , target_os = "macos" ) ) ]
779
799
Some ( AddressFamily :: System ) => Some ( SockAddr :: SysControl (
780
800
SysControlAddr ( * ( addr as * const sys_control:: sockaddr_ctl ) ) ) ) ,
801
+ #[ cfg( any( target_os = "android" , target_os = "linux" ) ) ]
802
+ Some ( AddressFamily :: Packet ) => match EtherAddr :: from_libc_sockaddr_ll (
803
+ addr as * const libc:: sockaddr_ll ) {
804
+ Some ( mac_addr) => Some ( SockAddr :: Ether ( mac_addr) ) ,
805
+ None => None
806
+ } ,
807
+ #[ cfg( any( target_os = "dragonfly" ,
808
+ target_os = "freebsd" ,
809
+ target_os = "ios" ,
810
+ target_os = "macos" ,
811
+ target_os = "netbsd" ,
812
+ target_os = "openbsd" ) ) ]
813
+ Some ( AddressFamily :: Link ) => match EtherAddr :: from_libc_sockaddr_dl (
814
+ addr as * const libc:: sockaddr_dl ) {
815
+ Some ( mac_addr) => Some ( SockAddr :: Ether ( mac_addr) ) ,
816
+ None => None
817
+ } ,
781
818
// Other address families are currently not supported and simply yield a None
782
819
// entry instead of a proper conversion to a `SockAddr`.
783
820
Some ( _) => None ,
@@ -795,6 +832,7 @@ impl SockAddr {
795
832
SockAddr :: Netlink ( NetlinkAddr ( ref sa) ) => ( mem:: transmute ( sa) , mem:: size_of :: < libc:: sockaddr_nl > ( ) as libc:: socklen_t ) ,
796
833
#[ cfg( any( target_os = "ios" , target_os = "macos" ) ) ]
797
834
SockAddr :: SysControl ( SysControlAddr ( ref sa) ) => ( mem:: transmute ( sa) , mem:: size_of :: < sys_control:: sockaddr_ctl > ( ) as libc:: socklen_t ) ,
835
+ SockAddr :: Ether ( _) => unimplemented ! ( )
798
836
}
799
837
}
800
838
}
@@ -812,6 +850,9 @@ impl PartialEq for SockAddr {
812
850
( SockAddr :: Netlink ( ref a) , SockAddr :: Netlink ( ref b) ) => {
813
851
a == b
814
852
}
853
+ ( SockAddr :: Ether ( ref a) , SockAddr :: Ether ( ref b) ) => {
854
+ a == b
855
+ }
815
856
_ => false ,
816
857
}
817
858
}
@@ -829,6 +870,7 @@ impl hash::Hash for SockAddr {
829
870
SockAddr :: Netlink ( ref a) => a. hash ( s) ,
830
871
#[ cfg( any( target_os = "ios" , target_os = "macos" ) ) ]
831
872
SockAddr :: SysControl ( ref a) => a. hash ( s) ,
873
+ SockAddr :: Ether ( ref ether_addr) => ether_addr. hash ( s)
832
874
}
833
875
}
834
876
}
@@ -848,6 +890,7 @@ impl fmt::Display for SockAddr {
848
890
SockAddr :: Netlink ( ref nl) => nl. fmt ( f) ,
849
891
#[ cfg( any( target_os = "ios" , target_os = "macos" ) ) ]
850
892
SockAddr :: SysControl ( ref sc) => sc. fmt ( f) ,
893
+ SockAddr :: Ether ( ref ether_addr) => ether_addr. fmt ( f)
851
894
}
852
895
}
853
896
}
@@ -1016,3 +1059,90 @@ pub mod sys_control {
1016
1059
}
1017
1060
}
1018
1061
}
1062
+
1063
+ #[ derive( Clone , Copy , Eq , Hash , PartialEq ) ]
1064
+ pub struct EtherAddr {
1065
+ pub a : u8 ,
1066
+ pub b : u8 ,
1067
+ pub c : u8 ,
1068
+ pub d : u8 ,
1069
+ pub e : u8 ,
1070
+ pub f : u8 ,
1071
+ }
1072
+
1073
+ impl EtherAddr {
1074
+ pub fn new ( a : u8 , b : u8 , c : u8 , d : u8 , e : u8 , f : u8 ) -> EtherAddr {
1075
+ EtherAddr {
1076
+ a : a,
1077
+ b : b,
1078
+ c : c,
1079
+ d : d,
1080
+ e : e,
1081
+ f : f,
1082
+ }
1083
+ }
1084
+
1085
+ #[ cfg( any( target_os = "android" , target_os = "linux" ) ) ]
1086
+ pub unsafe fn from_libc_sockaddr_ll ( sll : * const libc:: sockaddr_ll ) -> Option < EtherAddr > {
1087
+ let mac = EtherAddr :: new (
1088
+ ( * sll) . sll_addr [ 0 ] ,
1089
+ ( * sll) . sll_addr [ 1 ] ,
1090
+ ( * sll) . sll_addr [ 2 ] ,
1091
+ ( * sll) . sll_addr [ 3 ] ,
1092
+ ( * sll) . sll_addr [ 4 ] ,
1093
+ ( * sll) . sll_addr [ 5 ] ) ;
1094
+ Some ( mac)
1095
+ }
1096
+
1097
+ #[ cfg( any( target_os = "dragonfly" ,
1098
+ target_os = "freebsd" ,
1099
+ target_os = "ios" ,
1100
+ target_os = "macos" ,
1101
+ target_os = "netbsd" ,
1102
+ target_os = "openbsd" ) ) ]
1103
+ pub unsafe fn from_libc_sockaddr_dl ( sdl : * const libc:: sockaddr_dl ) -> Option < EtherAddr > {
1104
+ let nlen = ( * sdl) . sdl_nlen as usize ;
1105
+ let max_nlen: usize = if cfg ! ( target_os = "macos" ) || cfg ! ( target_os = "ios" ) {
1106
+ 12
1107
+ } else if cfg ! ( target_os = "freebsd" ) {
1108
+ 46
1109
+ } else if cfg ! ( target_os = "dragonfly" ) {
1110
+ 12
1111
+ } else if cfg ! ( target_os = "netbsd" ) {
1112
+ 12
1113
+ } else if cfg ! ( target_os = "openbsd" ) {
1114
+ 24
1115
+ } else {
1116
+ unreachable ! ( ) ;
1117
+ } ;
1118
+ if nlen + 5 >= max_nlen {
1119
+ return None ;
1120
+ }
1121
+ let mac = EtherAddr :: new (
1122
+ ( * sdl) . sdl_data [ nlen ] as u8 ,
1123
+ ( * sdl) . sdl_data [ nlen + 1 ] as u8 ,
1124
+ ( * sdl) . sdl_data [ nlen + 2 ] as u8 ,
1125
+ ( * sdl) . sdl_data [ nlen + 3 ] as u8 ,
1126
+ ( * sdl) . sdl_data [ nlen + 4 ] as u8 ,
1127
+ ( * sdl) . sdl_data [ nlen + 5 ] as u8 ) ;
1128
+ Some ( mac)
1129
+ }
1130
+ }
1131
+
1132
+ impl fmt:: Display for EtherAddr {
1133
+ fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
1134
+ write ! ( f, "{:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}" ,
1135
+ self . a,
1136
+ self . b,
1137
+ self . c,
1138
+ self . d,
1139
+ self . e,
1140
+ self . f)
1141
+ }
1142
+ }
1143
+
1144
+ impl fmt:: Debug for EtherAddr {
1145
+ fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
1146
+ fmt:: Display :: fmt ( self , f)
1147
+ }
1148
+ }
0 commit comments