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