@@ -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
}
@@ -720,6 +729,16 @@ pub enum SockAddr {
720
729
Netlink ( NetlinkAddr ) ,
721
730
#[ cfg( any( target_os = "ios" , target_os = "macos" ) ) ]
722
731
SysControl ( SysControlAddr ) ,
732
+ /// Ethernet MAC address
733
+ #[ cfg( any( target_os = "dragonfly" ,
734
+ target_os = "freebsd" ,
735
+ target_os = "ios" ,
736
+ target_os = "macos" ,
737
+ target_os = "netbsd" ,
738
+ target_os = "openbsd" ,
739
+ target_os = "android" ,
740
+ target_os = "linux" ) ) ]
741
+ Ether ( EtherAddr )
723
742
}
724
743
725
744
impl SockAddr {
@@ -750,6 +769,15 @@ impl SockAddr {
750
769
SockAddr :: Netlink ( ..) => AddressFamily :: Netlink ,
751
770
#[ cfg( any( target_os = "ios" , target_os = "macos" ) ) ]
752
771
SockAddr :: SysControl ( ..) => AddressFamily :: System ,
772
+ #[ cfg( any( target_os = "android" , target_os = "linux" ) ) ]
773
+ SockAddr :: Ether ( ..) => AddressFamily :: Packet ,
774
+ #[ cfg( any( target_os = "dragonfly" ,
775
+ target_os = "freebsd" ,
776
+ target_os = "ios" ,
777
+ target_os = "macos" ,
778
+ target_os = "netbsd" ,
779
+ target_os = "openbsd" ) ) ]
780
+ SockAddr :: Ether ( ..) => AddressFamily :: Link
753
781
}
754
782
}
755
783
@@ -777,6 +805,27 @@ impl SockAddr {
777
805
#[ cfg( any( target_os = "ios" , target_os = "macos" ) ) ]
778
806
Some ( AddressFamily :: System ) => Some ( SockAddr :: SysControl (
779
807
SysControlAddr ( * ( addr as * const sys_control:: sockaddr_ctl ) ) ) ) ,
808
+ #[ cfg( any( target_os = "android" , target_os = "linux" ) ) ]
809
+ Some ( AddressFamily :: Packet ) => {
810
+ let ether_addr = EtherAddr :: new ( * ( addr as * const libc:: sockaddr_ll ) ) ;
811
+ match ether_addr {
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
+ let ether_addr = EtherAddr :: new ( * ( addr as * const libc:: sockaddr_dl ) ) ;
824
+ match ether_addr {
825
+ Some ( ether_addr) => Some ( SockAddr :: Ether ( ether_addr) ) ,
826
+ None => None
827
+ }
828
+ } ,
780
829
// Other address families are currently not supported and simply yield a None
781
830
// entry instead of a proper conversion to a `SockAddr`.
782
831
Some ( _) => None ,
@@ -794,6 +843,15 @@ impl SockAddr {
794
843
SockAddr :: Netlink ( NetlinkAddr ( ref sa) ) => ( mem:: transmute ( sa) , mem:: size_of :: < libc:: sockaddr_nl > ( ) as libc:: socklen_t ) ,
795
844
#[ cfg( any( target_os = "ios" , target_os = "macos" ) ) ]
796
845
SockAddr :: SysControl ( SysControlAddr ( ref sa) ) => ( mem:: transmute ( sa) , mem:: size_of :: < sys_control:: sockaddr_ctl > ( ) as libc:: socklen_t ) ,
846
+ #[ cfg( any( target_os = "dragonfly" ,
847
+ target_os = "freebsd" ,
848
+ target_os = "ios" ,
849
+ target_os = "macos" ,
850
+ target_os = "netbsd" ,
851
+ target_os = "openbsd" ,
852
+ target_os = "linux" ,
853
+ target_os = "android" ) ) ]
854
+ SockAddr :: Ether ( _) => unimplemented ! ( )
797
855
}
798
856
}
799
857
}
@@ -811,6 +869,17 @@ impl PartialEq for SockAddr {
811
869
( SockAddr :: Netlink ( ref a) , SockAddr :: Netlink ( ref b) ) => {
812
870
a == b
813
871
}
872
+ #[ cfg( any( target_os = "dragonfly" ,
873
+ target_os = "freebsd" ,
874
+ target_os = "ios" ,
875
+ target_os = "macos" ,
876
+ target_os = "netbsd" ,
877
+ target_os = "openbsd" ,
878
+ target_os = "linux" ,
879
+ target_os = "android" ) ) ]
880
+ ( SockAddr :: Ether ( ref a) , SockAddr :: Ether ( ref b) ) => {
881
+ a == b
882
+ }
814
883
_ => false ,
815
884
}
816
885
}
@@ -828,6 +897,15 @@ impl hash::Hash for SockAddr {
828
897
SockAddr :: Netlink ( ref a) => a. hash ( s) ,
829
898
#[ cfg( any( target_os = "ios" , target_os = "macos" ) ) ]
830
899
SockAddr :: SysControl ( ref a) => a. hash ( s) ,
900
+ #[ cfg( any( target_os = "dragonfly" ,
901
+ target_os = "freebsd" ,
902
+ target_os = "ios" ,
903
+ target_os = "macos" ,
904
+ target_os = "netbsd" ,
905
+ target_os = "openbsd" ,
906
+ target_os = "linux" ,
907
+ target_os = "android" ) ) ]
908
+ SockAddr :: Ether ( ref ether_addr) => ether_addr. hash ( s)
831
909
}
832
910
}
833
911
}
@@ -847,6 +925,15 @@ impl fmt::Display for SockAddr {
847
925
SockAddr :: Netlink ( ref nl) => nl. fmt ( f) ,
848
926
#[ cfg( any( target_os = "ios" , target_os = "macos" ) ) ]
849
927
SockAddr :: SysControl ( ref sc) => sc. fmt ( f) ,
928
+ #[ cfg( any( target_os = "dragonfly" ,
929
+ target_os = "freebsd" ,
930
+ target_os = "ios" ,
931
+ target_os = "macos" ,
932
+ target_os = "netbsd" ,
933
+ target_os = "openbsd" ,
934
+ target_os = "linux" ,
935
+ target_os = "android" ) ) ]
936
+ SockAddr :: Ether ( ref ether_addr) => ether_addr. fmt ( f)
850
937
}
851
938
}
852
939
}
@@ -1014,4 +1101,227 @@ pub mod sys_control {
1014
1101
fmt:: Display :: fmt ( self , f)
1015
1102
}
1016
1103
}
1017
- }
1104
+ }
1105
+
1106
+
1107
+ #[ cfg( any( target_os = "android" , target_os = "linux" ) ) ]
1108
+ #[ derive( Clone , Copy ) ]
1109
+ pub struct EtherAddr ( pub libc:: sockaddr_ll ) ;
1110
+
1111
+ #[ cfg( any( target_os = "dragonfly" ,
1112
+ target_os = "freebsd" ,
1113
+ target_os = "ios" ,
1114
+ target_os = "macos" ,
1115
+ target_os = "netbsd" ,
1116
+ target_os = "openbsd" ) ) ]
1117
+ #[ derive( Clone , Copy ) ]
1118
+ pub struct EtherAddr ( pub libc:: sockaddr_dl ) ;
1119
+
1120
+
1121
+ #[ cfg( any( target_os = "android" , target_os = "linux" ) ) ]
1122
+ impl EtherAddr {
1123
+ pub fn new ( sll : libc:: sockaddr_ll ) -> Option < EtherAddr > {
1124
+ Some ( EtherAddr ( sll) )
1125
+ }
1126
+
1127
+ pub fn is_empty ( & self ) -> bool {
1128
+ false
1129
+ }
1130
+
1131
+ pub fn addr ( & self ) -> [ u8 ; 6 ] {
1132
+ [ self . 0 . sll_addr [ 0 ] ,
1133
+ self . 0 . sll_addr [ 1 ] ,
1134
+ self . 0 . sll_addr [ 2 ] ,
1135
+ self . 0 . sll_addr [ 3 ] ,
1136
+ self . 0 . sll_addr [ 4 ] ,
1137
+ self . 0 . sll_addr [ 5 ] ]
1138
+ }
1139
+ }
1140
+
1141
+ #[ cfg( any( target_os = "dragonfly" ,
1142
+ target_os = "freebsd" ,
1143
+ target_os = "ios" ,
1144
+ target_os = "macos" ,
1145
+ target_os = "netbsd" ,
1146
+ target_os = "openbsd" ) ) ]
1147
+ impl EtherAddr {
1148
+ pub fn new ( sdl : libc:: sockaddr_dl ) -> Option < EtherAddr > {
1149
+ let sdl_wrap = EtherAddr ( sdl) ;
1150
+ match sdl_wrap. is_empty ( ) {
1151
+ true => None ,
1152
+ false => Some ( sdl_wrap) ,
1153
+ }
1154
+ }
1155
+
1156
+ pub fn nlen ( & self ) -> usize {
1157
+ self . 0 . sdl_nlen as usize
1158
+ }
1159
+
1160
+ pub fn is_empty ( & self ) -> bool {
1161
+ self . nlen ( ) + 5 >= self . max_nlen ( )
1162
+ }
1163
+
1164
+ #[ cfg( any( target_os = "macos" ,
1165
+ target_os = "ios" ,
1166
+ target_os = "dragonfly" ,
1167
+ target_os = "netbsd" ) ) ]
1168
+ pub fn max_nlen ( & self ) -> usize { 12 }
1169
+
1170
+ #[ cfg( target_os = "openbsd" ) ]
1171
+ pub fn max_nlen ( & self ) -> usize { 24 }
1172
+
1173
+ #[ cfg( target_os = "freebsd" ) ]
1174
+ pub fn max_nlen ( & self ) -> usize { 46 }
1175
+
1176
+ pub fn addr ( & self ) -> [ u8 ; 6 ] {
1177
+ assert_eq ! ( self . is_empty( ) , false ) ;
1178
+ let nlen = self . nlen ( ) ;
1179
+
1180
+ [ self . 0 . sdl_data [ nlen ] as u8 ,
1181
+ self . 0 . sdl_data [ nlen + 1 ] as u8 ,
1182
+ self . 0 . sdl_data [ nlen + 2 ] as u8 ,
1183
+ self . 0 . sdl_data [ nlen + 3 ] as u8 ,
1184
+ self . 0 . sdl_data [ nlen + 4 ] as u8 ,
1185
+ self . 0 . sdl_data [ nlen + 5 ] as u8 ]
1186
+ }
1187
+
1188
+ }
1189
+
1190
+ #[ cfg( any( target_os = "dragonfly" ,
1191
+ target_os = "freebsd" ,
1192
+ target_os = "ios" ,
1193
+ target_os = "macos" ,
1194
+ target_os = "netbsd" ,
1195
+ target_os = "openbsd" ,
1196
+ target_os = "linux" ,
1197
+ target_os = "android" ) ) ]
1198
+ impl Eq for EtherAddr { }
1199
+
1200
+
1201
+ #[ cfg( any( target_os = "android" , target_os = "linux" ) ) ]
1202
+ impl PartialEq for EtherAddr {
1203
+ fn eq ( & self , other : & Self ) -> bool {
1204
+ let ( a, b) = ( self . 0 , other. 0 ) ;
1205
+ ( a. sll_family , a. sll_protocol , a. sll_ifindex , a. sll_hatype ,
1206
+ a. sll_pkttype , a. sll_halen , a. sll_addr ) ==
1207
+ ( b. sll_family , b. sll_protocol , b. sll_ifindex , b. sll_hatype ,
1208
+ b. sll_pkttype , b. sll_halen , b. sll_addr )
1209
+ }
1210
+ }
1211
+
1212
+ #[ cfg( any( target_os = "android" , target_os = "linux" ) ) ]
1213
+ impl hash:: Hash for EtherAddr {
1214
+ fn hash < H : hash:: Hasher > ( & self , s : & mut H ) {
1215
+ let a = self . 0 ;
1216
+ ( a. sll_family , a. sll_protocol , a. sll_ifindex , a. sll_hatype ,
1217
+ a. sll_pkttype , a. sll_halen , a. sll_addr ) . hash ( s) ;
1218
+ }
1219
+ }
1220
+
1221
+ #[ cfg( any( target_os = "dragonfly" ,
1222
+ target_os = "freebsd" ,
1223
+ target_os = "ios" ,
1224
+ target_os = "macos" ,
1225
+ target_os = "netbsd" ,
1226
+ target_os = "openbsd" ) ) ]
1227
+ impl PartialEq for EtherAddr {
1228
+ #[ cfg( any( target_os = "macos" ,
1229
+ target_os = "ios" ,
1230
+ target_os = "netbsd" ,
1231
+ target_os = "openbsd" ) ) ]
1232
+ fn eq ( & self , other : & Self ) -> bool {
1233
+ let ( a, b) = ( self . 0 , other. 0 ) ;
1234
+ ( a. sdl_len , a. sdl_family , a. sdl_index , a. sdl_type ,
1235
+ a. sdl_nlen , a. sdl_alen , a. sdl_slen , a. sdl_data ) ==
1236
+ ( b. sdl_len , b. sdl_family , b. sdl_index , b. sdl_type ,
1237
+ b. sdl_nlen , b. sdl_alen , b. sdl_slen , b. sdl_data )
1238
+ }
1239
+
1240
+ #[ cfg( target_os = "freebsd" ) ]
1241
+ fn eq ( & self , other : & Self ) -> bool {
1242
+ let ( a, b) = ( self . 0 , other. 0 ) ;
1243
+ ( a. sdl_len , a. sdl_family , a. sdl_index , a. sdl_type ,
1244
+ a. sdl_nlen , a. sdl_alen , a. sdl_slen ,
1245
+ & a. sdl_data [ 0 ..30 ] , & a. sdl_data [ 30 ..46 ] ) ==
1246
+ ( b. sdl_len , b. sdl_family , b. sdl_index , b. sdl_type ,
1247
+ b. sdl_nlen , b. sdl_alen , b. sdl_slen ,
1248
+ & b. sdl_data [ 0 ..30 ] , & b. sdl_data [ 30 ..46 ] )
1249
+ }
1250
+
1251
+ #[ cfg( target_os = "dragonfly" ) ]
1252
+ fn eq ( & self , other : & Self ) -> bool {
1253
+ let ( a, b) = ( self . 0 , other. 0 ) ;
1254
+ ( a. sdl_len , a. sdl_family , a. sdl_index , a. sdl_type , a. sdl_nlen ,
1255
+ a. sdl_alen , a. sdl_slen , a. sdl_data , a. sdl_rcf , a. sdl_route ) ==
1256
+ ( b. sdl_len , b. sdl_family , b. sdl_index , b. sdl_type , b. sdl_nlen ,
1257
+ b. sdl_alen , b. sdl_slen , b. sdl_data , b. sdl_rcf , b. sdl_route )
1258
+ }
1259
+ }
1260
+
1261
+ #[ cfg( any( target_os = "dragonfly" ,
1262
+ target_os = "freebsd" ,
1263
+ target_os = "ios" ,
1264
+ target_os = "macos" ,
1265
+ target_os = "netbsd" ,
1266
+ target_os = "openbsd" ) ) ]
1267
+ impl hash:: Hash for EtherAddr {
1268
+ #[ cfg( any( target_os = "macos" ,
1269
+ target_os = "ios" ,
1270
+ target_os = "netbsd" ,
1271
+ target_os = "openbsd" ) ) ]
1272
+ fn hash < H : hash:: Hasher > ( & self , s : & mut H ) {
1273
+ let a = self . 0 ;
1274
+ ( a. sdl_len , a. sdl_family , a. sdl_index , a. sdl_type ,
1275
+ a. sdl_nlen , a. sdl_alen , a. sdl_slen , a. sdl_data ) . hash ( s) ;
1276
+ }
1277
+
1278
+ #[ cfg( target_os = "freebsd" ) ]
1279
+ fn hash < H : hash:: Hasher > ( & self , s : & mut H ) {
1280
+ let a = self . 0 ;
1281
+ ( a. sdl_len , a. sdl_family , a. sdl_index , a. sdl_type ,
1282
+ a. sdl_nlen , a. sdl_alen , a. sdl_slen ,
1283
+ & a. sdl_data [ 0 ..30 ] , & a. sdl_data [ 30 ..46 ] ) . hash ( s) ;
1284
+ }
1285
+
1286
+ #[ cfg( target_os = "dragonfly" ) ]
1287
+ fn hash < H : hash:: Hasher > ( & self , s : & mut H ) {
1288
+ let a = self . 0 ;
1289
+ ( a. sdl_len , a. sdl_family , a. sdl_index , a. sdl_type , a. sdl_nlen ,
1290
+ a. sdl_alen , a. sdl_slen , a. sdl_data , a. sdl_rcf , a. sdl_route ) . hash ( s) ;
1291
+ }
1292
+ }
1293
+
1294
+ #[ cfg( any( target_os = "dragonfly" ,
1295
+ target_os = "freebsd" ,
1296
+ target_os = "ios" ,
1297
+ target_os = "macos" ,
1298
+ target_os = "netbsd" ,
1299
+ target_os = "openbsd" ,
1300
+ target_os = "linux" ,
1301
+ target_os = "android" ) ) ]
1302
+ impl fmt:: Display for EtherAddr {
1303
+ fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
1304
+ let addr = self . addr ( ) ;
1305
+ write ! ( f, "{:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}" ,
1306
+ addr[ 0 ] ,
1307
+ addr[ 1 ] ,
1308
+ addr[ 2 ] ,
1309
+ addr[ 3 ] ,
1310
+ addr[ 4 ] ,
1311
+ addr[ 5 ] )
1312
+ }
1313
+ }
1314
+
1315
+ #[ cfg( any( target_os = "dragonfly" ,
1316
+ target_os = "freebsd" ,
1317
+ target_os = "ios" ,
1318
+ target_os = "macos" ,
1319
+ target_os = "netbsd" ,
1320
+ target_os = "openbsd" ,
1321
+ target_os = "linux" ,
1322
+ target_os = "android" ) ) ]
1323
+ impl fmt:: Debug for EtherAddr {
1324
+ fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
1325
+ fmt:: Display :: fmt ( self , f)
1326
+ }
1327
+ }
0 commit comments