@@ -1537,6 +1537,17 @@ impl SockaddrLike for SockaddrStorage {
1537
1537
let mut ss: libc:: sockaddr_storage = mem:: zeroed ( ) ;
1538
1538
let ssp = & mut ss as * mut libc:: sockaddr_storage as * mut u8 ;
1539
1539
ptr:: copy ( addr as * const u8 , ssp, len as usize ) ;
1540
+ #[ cfg( any(
1541
+ target_os = "android" ,
1542
+ target_os = "fuchsia" ,
1543
+ target_os = "illumos" ,
1544
+ target_os = "linux"
1545
+ ) ) ]
1546
+ if i32:: from ( ss. ss_family ) == libc:: AF_UNIX {
1547
+ // Safe because we UnixAddr is strictly smaller than
1548
+ // SockaddrStorage, and we just initialized the structure.
1549
+ ( * ( & mut ss as * mut libc:: sockaddr_storage as * mut UnixAddr ) ) . sun_len = len as u8 ;
1550
+ }
1540
1551
Some ( Self { ss } )
1541
1552
}
1542
1553
} else {
@@ -1598,6 +1609,21 @@ impl SockaddrLike for SockaddrStorage {
1598
1609
}
1599
1610
}
1600
1611
}
1612
+
1613
+ #[ cfg( any(
1614
+ target_os = "android" ,
1615
+ target_os = "fuchsia" ,
1616
+ target_os = "illumos" ,
1617
+ target_os = "linux"
1618
+ ) ) ]
1619
+ fn len ( & self ) -> libc:: socklen_t {
1620
+ match self . as_unix_addr ( ) {
1621
+ // The UnixAddr type knows its own length
1622
+ Some ( ua) => ua. len ( ) ,
1623
+ // For all else, we're just a boring SockaddrStorage
1624
+ None => mem:: size_of_val ( self ) as libc:: socklen_t
1625
+ }
1626
+ }
1601
1627
}
1602
1628
1603
1629
macro_rules! accessors {
@@ -1635,6 +1661,68 @@ macro_rules! accessors {
1635
1661
}
1636
1662
1637
1663
impl SockaddrStorage {
1664
+ /// Downcast to an immutable `[UnixAddr]` reference.
1665
+ pub fn as_unix_addr ( & self ) -> Option < & UnixAddr > {
1666
+ cfg_if ! {
1667
+ if #[ cfg( any( target_os = "android" ,
1668
+ target_os = "fuchsia" ,
1669
+ target_os = "illumos" ,
1670
+ target_os = "linux"
1671
+ ) ) ]
1672
+ {
1673
+ let p = unsafe { & self . ss as * const libc:: sockaddr_storage } ;
1674
+ // Safe because UnixAddr is strictly smaller than
1675
+ // sockaddr_storage, and we're fully initialized
1676
+ let len = unsafe {
1677
+ ( * ( p as * const UnixAddr ) ) . sun_len as usize
1678
+ } ;
1679
+ } else {
1680
+ let len = self . len( ) as usize ;
1681
+ }
1682
+ }
1683
+ // Sanity checks
1684
+ if self . family ( ) != Some ( AddressFamily :: Unix ) {
1685
+ return None ;
1686
+ } else if len < offset_of ! ( libc:: sockaddr_un, sun_path) {
1687
+ return None ;
1688
+ } else if len > mem:: size_of :: < libc:: sockaddr_un > ( ) {
1689
+ return None ;
1690
+ } else {
1691
+ Some ( unsafe { & self . su } )
1692
+ }
1693
+ }
1694
+
1695
+ /// Downcast to a mutable `[UnixAddr]` reference.
1696
+ pub fn as_unix_addr_mut ( & mut self ) -> Option < & mut UnixAddr > {
1697
+ cfg_if ! {
1698
+ if #[ cfg( any( target_os = "android" ,
1699
+ target_os = "fuchsia" ,
1700
+ target_os = "illumos" ,
1701
+ target_os = "linux"
1702
+ ) ) ]
1703
+ {
1704
+ let p = unsafe { & self . ss as * const libc:: sockaddr_storage } ;
1705
+ // Safe because UnixAddr is strictly smaller than
1706
+ // sockaddr_storage, and we're fully initialized
1707
+ let len = unsafe {
1708
+ ( * ( p as * const UnixAddr ) ) . sun_len as usize
1709
+ } ;
1710
+ } else {
1711
+ let len = self . len( ) as usize ;
1712
+ }
1713
+ }
1714
+ // Sanity checks
1715
+ if self . family ( ) != Some ( AddressFamily :: Unix ) {
1716
+ return None ;
1717
+ } else if len < offset_of ! ( libc:: sockaddr_un, sun_path) {
1718
+ return None ;
1719
+ } else if len > mem:: size_of :: < libc:: sockaddr_un > ( ) {
1720
+ return None ;
1721
+ } else {
1722
+ Some ( unsafe { & mut self . su } )
1723
+ }
1724
+ }
1725
+
1638
1726
#[ cfg( any( target_os = "android" , target_os = "linux" ) ) ]
1639
1727
accessors ! { as_alg_addr, as_alg_addr_mut, AlgAddr ,
1640
1728
AddressFamily :: Alg , libc:: sockaddr_alg, alg}
@@ -3064,6 +3152,44 @@ mod tests {
3064
3152
}
3065
3153
}
3066
3154
3155
+ mod sockaddr_storage {
3156
+ use super :: * ;
3157
+
3158
+ #[ test]
3159
+ fn from_sockaddr_un_named ( ) {
3160
+ let ua = UnixAddr :: new ( "/var/run/mysock" ) . unwrap ( ) ;
3161
+ let ptr = ua. as_ptr ( ) as * const libc:: sockaddr ;
3162
+ let ss = unsafe {
3163
+ SockaddrStorage :: from_raw ( ptr, Some ( ua. len ( ) ) )
3164
+ } . unwrap ( ) ;
3165
+ assert_eq ! ( ss. len( ) , ua. len( ) ) ;
3166
+ }
3167
+
3168
+ #[ cfg( any( target_os = "android" , target_os = "linux" ) ) ]
3169
+ #[ test]
3170
+ fn from_sockaddr_un_abstract_named ( ) {
3171
+ let name = String :: from ( "nix\0 abstract\0 test" ) ;
3172
+ let ua = UnixAddr :: new_abstract ( name. as_bytes ( ) ) . unwrap ( ) ;
3173
+ let ptr = ua. as_ptr ( ) as * const libc:: sockaddr ;
3174
+ let ss = unsafe {
3175
+ SockaddrStorage :: from_raw ( ptr, Some ( ua. len ( ) ) )
3176
+ } . unwrap ( ) ;
3177
+ assert_eq ! ( ss. len( ) , ua. len( ) ) ;
3178
+ }
3179
+
3180
+ #[ cfg( any( target_os = "android" , target_os = "linux" ) ) ]
3181
+ #[ test]
3182
+ fn from_sockaddr_un_abstract_unnamed ( ) {
3183
+ let empty = String :: new ( ) ;
3184
+ let ua = UnixAddr :: new_abstract ( empty. as_bytes ( ) ) . unwrap ( ) ;
3185
+ let ptr = ua. as_ptr ( ) as * const libc:: sockaddr ;
3186
+ let ss = unsafe {
3187
+ SockaddrStorage :: from_raw ( ptr, Some ( ua. len ( ) ) )
3188
+ } . unwrap ( ) ;
3189
+ assert_eq ! ( ss. len( ) , ua. len( ) ) ;
3190
+ }
3191
+ }
3192
+
3067
3193
mod unixaddr {
3068
3194
use super :: * ;
3069
3195
0 commit comments