@@ -1398,7 +1398,18 @@ impl SockaddrLike for SockaddrStorage {
1398
1398
let mut ss: libc:: sockaddr_storage = mem:: zeroed ( ) ;
1399
1399
let ssp = & mut ss as * mut libc:: sockaddr_storage as * mut u8 ;
1400
1400
ptr:: copy ( addr as * const u8 , ssp, len as usize ) ;
1401
- Some ( Self { ss} )
1401
+ #[ cfg( any(
1402
+ target_os = "android" ,
1403
+ target_os = "fuchsia" ,
1404
+ target_os = "illumos" ,
1405
+ target_os = "linux"
1406
+ ) ) ]
1407
+ if i32:: from ( ss. ss_family ) == libc:: AF_UNIX {
1408
+ // Safe because we UnixAddr is strictly smaller than
1409
+ // SockaddrStorage, and we just initialized the structure.
1410
+ ( * ( & mut ss as * mut libc:: sockaddr_storage as * mut UnixAddr ) ) . sun_len = len as u8 ;
1411
+ }
1412
+ Some ( Self { ss } )
1402
1413
}
1403
1414
} else {
1404
1415
// If length is not available and addr is of a fixed-length type,
@@ -1445,6 +1456,21 @@ impl SockaddrLike for SockaddrStorage {
1445
1456
}
1446
1457
}
1447
1458
}
1459
+
1460
+ #[ cfg( any(
1461
+ target_os = "android" ,
1462
+ target_os = "fuchsia" ,
1463
+ target_os = "illumos" ,
1464
+ target_os = "linux"
1465
+ ) ) ]
1466
+ fn len ( & self ) -> libc:: socklen_t {
1467
+ match self . as_unix_addr ( ) {
1468
+ // The UnixAddr type knows its own length
1469
+ Some ( ua) => ua. len ( ) ,
1470
+ // For all else, we're just a boring SockaddrStorage
1471
+ None => mem:: size_of_val ( self ) as libc:: socklen_t
1472
+ }
1473
+ }
1448
1474
}
1449
1475
1450
1476
macro_rules! accessors {
@@ -1483,6 +1509,64 @@ macro_rules! accessors {
1483
1509
}
1484
1510
1485
1511
impl SockaddrStorage {
1512
+ /// Downcast to an immutable `[UnixAddr]` reference.
1513
+ pub fn as_unix_addr ( & self ) -> Option < & UnixAddr > {
1514
+ cfg_if ! {
1515
+ if #[ cfg( any( target_os = "android" ,
1516
+ target_os = "fuchsia" ,
1517
+ target_os = "illumos" ,
1518
+ target_os = "linux"
1519
+ ) ) ]
1520
+ {
1521
+ let p = unsafe { & self . ss as * const libc:: sockaddr_storage } ;
1522
+ // Safe because UnixAddr is strictly smaller than
1523
+ // sockaddr_storage, and we're fully initialized
1524
+ let len = unsafe {
1525
+ ( * ( p as * const UnixAddr ) ) . sun_len as usize
1526
+ } ;
1527
+ } else {
1528
+ let len = self . len( ) as usize ;
1529
+ }
1530
+ }
1531
+ // Sanity checks
1532
+ if self . family ( ) != Some ( AddressFamily :: Unix ) ||
1533
+ len < offset_of ! ( libc:: sockaddr_un, sun_path) ||
1534
+ len > mem:: size_of :: < libc:: sockaddr_un > ( ) {
1535
+ None
1536
+ } else {
1537
+ Some ( unsafe { & self . su } )
1538
+ }
1539
+ }
1540
+
1541
+ /// Downcast to a mutable `[UnixAddr]` reference.
1542
+ pub fn as_unix_addr_mut ( & mut self ) -> Option < & mut UnixAddr > {
1543
+ cfg_if ! {
1544
+ if #[ cfg( any( target_os = "android" ,
1545
+ target_os = "fuchsia" ,
1546
+ target_os = "illumos" ,
1547
+ target_os = "linux"
1548
+ ) ) ]
1549
+ {
1550
+ let p = unsafe { & self . ss as * const libc:: sockaddr_storage } ;
1551
+ // Safe because UnixAddr is strictly smaller than
1552
+ // sockaddr_storage, and we're fully initialized
1553
+ let len = unsafe {
1554
+ ( * ( p as * const UnixAddr ) ) . sun_len as usize
1555
+ } ;
1556
+ } else {
1557
+ let len = self . len( ) as usize ;
1558
+ }
1559
+ }
1560
+ // Sanity checks
1561
+ if self . family ( ) != Some ( AddressFamily :: Unix ) ||
1562
+ len < offset_of ! ( libc:: sockaddr_un, sun_path) ||
1563
+ len > mem:: size_of :: < libc:: sockaddr_un > ( ) {
1564
+ None
1565
+ } else {
1566
+ Some ( unsafe { & mut self . su } )
1567
+ }
1568
+ }
1569
+
1486
1570
#[ cfg( any( target_os = "android" , target_os = "linux" ) ) ]
1487
1571
accessors ! { as_alg_addr, as_alg_addr_mut, AlgAddr ,
1488
1572
AddressFamily :: Alg , libc:: sockaddr_alg, alg}
@@ -2789,6 +2873,44 @@ mod tests {
2789
2873
}
2790
2874
}
2791
2875
2876
+ mod sockaddr_storage {
2877
+ use super :: * ;
2878
+
2879
+ #[ test]
2880
+ fn from_sockaddr_un_named ( ) {
2881
+ let ua = UnixAddr :: new ( "/var/run/mysock" ) . unwrap ( ) ;
2882
+ let ptr = ua. as_ptr ( ) as * const libc:: sockaddr ;
2883
+ let ss = unsafe {
2884
+ SockaddrStorage :: from_raw ( ptr, Some ( ua. len ( ) ) )
2885
+ } . unwrap ( ) ;
2886
+ assert_eq ! ( ss. len( ) , ua. len( ) ) ;
2887
+ }
2888
+
2889
+ #[ cfg( any( target_os = "android" , target_os = "linux" ) ) ]
2890
+ #[ test]
2891
+ fn from_sockaddr_un_abstract_named ( ) {
2892
+ let name = String :: from ( "nix\0 abstract\0 test" ) ;
2893
+ let ua = UnixAddr :: new_abstract ( name. as_bytes ( ) ) . unwrap ( ) ;
2894
+ let ptr = ua. as_ptr ( ) as * const libc:: sockaddr ;
2895
+ let ss = unsafe {
2896
+ SockaddrStorage :: from_raw ( ptr, Some ( ua. len ( ) ) )
2897
+ } . unwrap ( ) ;
2898
+ assert_eq ! ( ss. len( ) , ua. len( ) ) ;
2899
+ }
2900
+
2901
+ #[ cfg( any( target_os = "android" , target_os = "linux" ) ) ]
2902
+ #[ test]
2903
+ fn from_sockaddr_un_abstract_unnamed ( ) {
2904
+ let empty = String :: new ( ) ;
2905
+ let ua = UnixAddr :: new_abstract ( empty. as_bytes ( ) ) . unwrap ( ) ;
2906
+ let ptr = ua. as_ptr ( ) as * const libc:: sockaddr ;
2907
+ let ss = unsafe {
2908
+ SockaddrStorage :: from_raw ( ptr, Some ( ua. len ( ) ) )
2909
+ } . unwrap ( ) ;
2910
+ assert_eq ! ( ss. len( ) , ua. len( ) ) ;
2911
+ }
2912
+ }
2913
+
2792
2914
mod unixaddr {
2793
2915
use super :: * ;
2794
2916
0 commit comments