@@ -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/Packet
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,16 @@ 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
+ #[ cfg( any( target_os = "dragonfly" ,
735
+ target_os = "freebsd" ,
736
+ target_os = "ios" ,
737
+ target_os = "macos" ,
738
+ target_os = "netbsd" ,
739
+ target_os = "openbsd" ,
740
+ target_os = "android" ,
741
+ target_os = "linux" ) ) ]
742
+ Ether ( EtherAddr )
724
743
}
725
744
726
745
impl SockAddr {
@@ -751,6 +770,15 @@ impl SockAddr {
751
770
SockAddr :: Netlink ( ..) => AddressFamily :: Netlink ,
752
771
#[ cfg( any( target_os = "ios" , target_os = "macos" ) ) ]
753
772
SockAddr :: SysControl ( ..) => AddressFamily :: System ,
773
+ #[ cfg( any( target_os = "android" , target_os = "linux" ) ) ]
774
+ SockAddr :: Ether ( ..) => AddressFamily :: Packet ,
775
+ #[ cfg( any( target_os = "dragonfly" ,
776
+ target_os = "freebsd" ,
777
+ target_os = "ios" ,
778
+ target_os = "macos" ,
779
+ target_os = "netbsd" ,
780
+ target_os = "openbsd" ) ) ]
781
+ SockAddr :: Ether ( ..) => AddressFamily :: Link
754
782
}
755
783
}
756
784
@@ -778,6 +806,25 @@ impl SockAddr {
778
806
#[ cfg( any( target_os = "ios" , target_os = "macos" ) ) ]
779
807
Some ( AddressFamily :: System ) => Some ( SockAddr :: SysControl (
780
808
SysControlAddr ( * ( addr as * const sys_control:: sockaddr_ctl ) ) ) ) ,
809
+ #[ cfg( any( target_os = "android" , target_os = "linux" ) ) ]
810
+ Some ( AddressFamily :: Packet ) => {
811
+ match EtherAddr :: new_checked ( * ( addr as * const libc:: sockaddr_ll ) ) {
812
+ Some ( ether_addr) => Some ( SockAddr :: Ether ( ether_addr) ) ,
813
+ None => None
814
+ }
815
+ } ,
816
+ #[ cfg( any( target_os = "dragonfly" ,
817
+ target_os = "freebsd" ,
818
+ target_os = "ios" ,
819
+ target_os = "macos" ,
820
+ target_os = "netbsd" ,
821
+ target_os = "openbsd" ) ) ]
822
+ Some ( AddressFamily :: Link ) => {
823
+ match EtherAddr :: new_checked ( * ( addr as * const libc:: sockaddr_dl ) ) {
824
+ Some ( ether_addr) => Some ( SockAddr :: Ether ( ether_addr) ) ,
825
+ None => None
826
+ }
827
+ } ,
781
828
// Other address families are currently not supported and simply yield a None
782
829
// entry instead of a proper conversion to a `SockAddr`.
783
830
Some ( _) => None ,
@@ -795,6 +842,7 @@ impl SockAddr {
795
842
SockAddr :: Netlink ( NetlinkAddr ( ref sa) ) => ( mem:: transmute ( sa) , mem:: size_of :: < libc:: sockaddr_nl > ( ) as libc:: socklen_t ) ,
796
843
#[ cfg( any( target_os = "ios" , target_os = "macos" ) ) ]
797
844
SockAddr :: SysControl ( SysControlAddr ( ref sa) ) => ( mem:: transmute ( sa) , mem:: size_of :: < sys_control:: sockaddr_ctl > ( ) as libc:: socklen_t ) ,
845
+ SockAddr :: Ether ( _) => unimplemented ! ( )
798
846
}
799
847
}
800
848
}
@@ -812,6 +860,9 @@ impl PartialEq for SockAddr {
812
860
( SockAddr :: Netlink ( ref a) , SockAddr :: Netlink ( ref b) ) => {
813
861
a == b
814
862
}
863
+ ( SockAddr :: Ether ( ref a) , SockAddr :: Ether ( ref b) ) => {
864
+ a == b
865
+ }
815
866
_ => false ,
816
867
}
817
868
}
@@ -829,6 +880,7 @@ impl hash::Hash for SockAddr {
829
880
SockAddr :: Netlink ( ref a) => a. hash ( s) ,
830
881
#[ cfg( any( target_os = "ios" , target_os = "macos" ) ) ]
831
882
SockAddr :: SysControl ( ref a) => a. hash ( s) ,
883
+ SockAddr :: Ether ( ref ether_addr) => ether_addr. hash ( s)
832
884
}
833
885
}
834
886
}
@@ -848,6 +900,7 @@ impl fmt::Display for SockAddr {
848
900
SockAddr :: Netlink ( ref nl) => nl. fmt ( f) ,
849
901
#[ cfg( any( target_os = "ios" , target_os = "macos" ) ) ]
850
902
SockAddr :: SysControl ( ref sc) => sc. fmt ( f) ,
903
+ SockAddr :: Ether ( ref ether_addr) => ether_addr. fmt ( f)
851
904
}
852
905
}
853
906
}
@@ -1016,3 +1069,199 @@ pub mod sys_control {
1016
1069
}
1017
1070
}
1018
1071
}
1072
+
1073
+ #[ cfg( any( target_os = "android" , target_os = "linux" ) ) ]
1074
+ #[ derive( Clone , Copy ) ]
1075
+ pub struct EtherAddr ( libc:: sockaddr_ll ) ;
1076
+
1077
+ #[ cfg( any( target_os = "dragonfly" ,
1078
+ target_os = "freebsd" ,
1079
+ target_os = "ios" ,
1080
+ target_os = "macos" ,
1081
+ target_os = "netbsd" ,
1082
+ target_os = "openbsd" ) ) ]
1083
+ #[ derive( Clone , Copy ) ]
1084
+ pub struct EtherAddr ( libc:: sockaddr_dl ) ;
1085
+
1086
+ impl EtherAddr {
1087
+ #[ cfg( any( target_os = "android" , target_os = "linux" ) ) ]
1088
+ pub fn new_checked ( sll : libc:: sockaddr_ll ) -> Option < EtherAddr > {
1089
+ Some ( EtherAddr ( sll) )
1090
+ }
1091
+
1092
+ #[ cfg( any( target_os = "dragonfly" ,
1093
+ target_os = "freebsd" ,
1094
+ target_os = "ios" ,
1095
+ target_os = "macos" ,
1096
+ target_os = "netbsd" ,
1097
+ target_os = "openbsd" ) ) ]
1098
+ pub fn new_checked ( sdl : libc:: sockaddr_dl ) -> Option < EtherAddr > {
1099
+ let ether_addr = EtherAddr ( sdl) ;
1100
+ if ether_addr. is_empty ( ) {
1101
+ None
1102
+ } else {
1103
+ Some ( ether_addr)
1104
+ }
1105
+ }
1106
+
1107
+ #[ cfg( any( target_os = "dragonfly" ,
1108
+ target_os = "freebsd" ,
1109
+ target_os = "ios" ,
1110
+ target_os = "macos" ,
1111
+ target_os = "netbsd" ,
1112
+ target_os = "openbsd" ) ) ]
1113
+ pub fn is_empty ( & self ) -> bool {
1114
+ self . nlen ( ) + 5 >= self . max_nlen ( )
1115
+ }
1116
+
1117
+ #[ cfg( any( target_os = "dragonfly" ,
1118
+ target_os = "freebsd" ,
1119
+ target_os = "ios" ,
1120
+ target_os = "macos" ,
1121
+ target_os = "netbsd" ,
1122
+ target_os = "openbsd" ) ) ]
1123
+ pub fn nlen ( & self ) -> usize {
1124
+ self . 0 . sdl_nlen as usize
1125
+ }
1126
+
1127
+ #[ cfg( any( target_os = "macos" ,
1128
+ target_os = "ios" ,
1129
+ target_os = "dragonfly" ,
1130
+ target_os = "netbsd" ) ) ]
1131
+ pub fn max_nlen ( & self ) -> usize { 12 }
1132
+
1133
+ #[ cfg( target_os = "openbsd" ) ]
1134
+ pub fn max_nlen ( & self ) -> usize { 24 }
1135
+
1136
+ #[ cfg( target_os = "freebsd" ) ]
1137
+ pub fn max_nlen ( & self ) -> usize { 46 }
1138
+
1139
+ #[ cfg( any( target_os = "android" , target_os = "linux" ) ) ]
1140
+ pub fn addr ( & self ) -> [ u8 ; 6 ] {
1141
+ [
1142
+ self . 0 . sll_addr [ 0 ] ,
1143
+ self . 0 . sll_addr [ 1 ] ,
1144
+ self . 0 . sll_addr [ 2 ] ,
1145
+ self . 0 . sll_addr [ 3 ] ,
1146
+ self . 0 . sll_addr [ 4 ] ,
1147
+ self . 0 . sll_addr [ 5 ]
1148
+ ]
1149
+ }
1150
+
1151
+ #[ cfg( any( target_os = "dragonfly" ,
1152
+ target_os = "freebsd" ,
1153
+ target_os = "ios" ,
1154
+ target_os = "macos" ,
1155
+ target_os = "netbsd" ,
1156
+ target_os = "openbsd" ) ) ]
1157
+ pub fn addr ( & self ) -> [ u8 ; 6 ] {
1158
+ assert_eq ! ( self . is_empty( ) , false ) ;
1159
+ let nlen = self . nlen ( ) ;
1160
+ [
1161
+ self . 0 . sdl_data [ nlen ] as u8 ,
1162
+ self . 0 . sdl_data [ nlen + 1 ] as u8 ,
1163
+ self . 0 . sdl_data [ nlen + 2 ] as u8 ,
1164
+ self . 0 . sdl_data [ nlen + 3 ] as u8 ,
1165
+ self . 0 . sdl_data [ nlen + 4 ] as u8 ,
1166
+ self . 0 . sdl_data [ nlen + 5 ] as u8
1167
+ ]
1168
+ }
1169
+ }
1170
+
1171
+ impl Eq for EtherAddr { }
1172
+
1173
+ impl PartialEq for EtherAddr {
1174
+ #[ cfg( any( target_os = "android" , target_os = "linux" ) ) ]
1175
+ fn eq ( & self , other : & Self ) -> bool {
1176
+ let ( a, b) = ( self . 0 , other. 0 ) ;
1177
+ ( a. sll_family , a. sll_protocol , a. sll_ifindex , a. sll_hatype ,
1178
+ a. sll_pkttype , a. sll_halen , a. sll_addr ) ==
1179
+ ( b. sll_family , b. sll_protocol , b. sll_ifindex , b. sll_hatype ,
1180
+ b. sll_pkttype , b. sll_halen , b. sll_addr )
1181
+ }
1182
+
1183
+ #[ cfg( any( target_os = "macos" ,
1184
+ target_os = "ios" ,
1185
+ target_os = "netbsd" ,
1186
+ target_os = "openbsd" ) ) ]
1187
+ fn eq ( & self , other : & Self ) -> bool {
1188
+ let ( a, b) = ( self . 0 , other. 0 ) ;
1189
+ ( a. sdl_len , a. sdl_family , a. sdl_index , a. sdl_type ,
1190
+ a. sdl_nlen , a. sdl_alen , a. sdl_slen , a. sdl_data ) ==
1191
+ ( b. sdl_len , b. sdl_family , b. sdl_index , b. sdl_type ,
1192
+ b. sdl_nlen , b. sdl_alen , b. sdl_slen , b. sdl_data )
1193
+ }
1194
+
1195
+ #[ cfg( target_os = "freebsd" ) ]
1196
+ fn eq ( & self , other : & Self ) -> bool {
1197
+ let ( a, b) = ( self . 0 , other. 0 ) ;
1198
+ ( a. sdl_len , a. sdl_family , a. sdl_index , a. sdl_type ,
1199
+ a. sdl_nlen , a. sdl_alen , a. sdl_slen ,
1200
+ & a. sdl_data [ 0 ..30 ] , & a. sdl_data [ 30 ..46 ] ) ==
1201
+ ( b. sdl_len , b. sdl_family , b. sdl_index , b. sdl_type ,
1202
+ b. sdl_nlen , b. sdl_alen , b. sdl_slen ,
1203
+ & b. sdl_data [ 0 ..30 ] , & b. sdl_data [ 30 ..46 ] )
1204
+ }
1205
+
1206
+ #[ cfg( target_os = "dragonfly" ) ]
1207
+ fn eq ( & self , other : & Self ) -> bool {
1208
+ let ( a, b) = ( self . 0 , other. 0 ) ;
1209
+ ( a. sdl_len , a. sdl_family , a. sdl_index , a. sdl_type , a. sdl_nlen ,
1210
+ a. sdl_alen , a. sdl_slen , a. sdl_data , a. sdl_rcf , a. sdl_route ) ==
1211
+ ( b. sdl_len , b. sdl_family , b. sdl_index , b. sdl_type , b. sdl_nlen ,
1212
+ b. sdl_alen , b. sdl_slen , b. sdl_data , b. sdl_rcf , b. sdl_route )
1213
+ }
1214
+ }
1215
+
1216
+ impl hash:: Hash for EtherAddr {
1217
+ #[ cfg( any( target_os = "android" , target_os = "linux" ) ) ]
1218
+ fn hash < H : hash:: Hasher > ( & self , s : & mut H ) {
1219
+ let a = self . 0 ;
1220
+ ( a. sll_family , a. sll_protocol , a. sll_ifindex , a. sll_hatype ,
1221
+ a. sll_pkttype , a. sll_halen , a. sll_addr ) . hash ( s) ;
1222
+ }
1223
+
1224
+ #[ cfg( any( target_os = "macos" ,
1225
+ target_os = "ios" ,
1226
+ target_os = "netbsd" ,
1227
+ target_os = "openbsd" ) ) ]
1228
+ fn hash < H : hash:: Hasher > ( & self , s : & mut H ) {
1229
+ let a = self . 0 ;
1230
+ ( a. sdl_len , a. sdl_family , a. sdl_index , a. sdl_type ,
1231
+ a. sdl_nlen , a. sdl_alen , a. sdl_slen , a. sdl_data ) . hash ( s) ;
1232
+ }
1233
+
1234
+ #[ cfg( target_os = "freebsd" ) ]
1235
+ fn hash < H : hash:: Hasher > ( & self , s : & mut H ) {
1236
+ let a = self . 0 ;
1237
+ ( a. sdl_len , a. sdl_family , a. sdl_index , a. sdl_type ,
1238
+ a. sdl_nlen , a. sdl_alen , a. sdl_slen ,
1239
+ & a. sdl_data [ 0 ..30 ] , & a. sdl_data [ 30 ..46 ] ) . hash ( s) ;
1240
+ }
1241
+
1242
+ #[ cfg( target_os = "dragonfly" ) ]
1243
+ fn hash < H : hash:: Hasher > ( & self , s : & mut H ) {
1244
+ let a = self . 0 ;
1245
+ ( a. sdl_len , a. sdl_family , a. sdl_index , a. sdl_type , a. sdl_nlen ,
1246
+ a. sdl_alen , a. sdl_slen , a. sdl_data , a. sdl_rcf , a. sdl_route ) . hash ( s) ;
1247
+ }
1248
+ }
1249
+
1250
+ impl fmt:: Display for EtherAddr {
1251
+ fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
1252
+ let elems = self . addr ( ) ;
1253
+ write ! ( f, "{:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}" ,
1254
+ elems[ 0 ] ,
1255
+ elems[ 1 ] ,
1256
+ elems[ 2 ] ,
1257
+ elems[ 3 ] ,
1258
+ elems[ 4 ] ,
1259
+ elems[ 5 ] )
1260
+ }
1261
+ }
1262
+
1263
+ impl fmt:: Debug for EtherAddr {
1264
+ fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
1265
+ fmt:: Display :: fmt ( self , f)
1266
+ }
1267
+ }
0 commit comments