@@ -29,12 +29,41 @@ pub use self::datalink::LinkAddr;
29
29
#[ cfg( any( target_os = "android" , target_os = "linux" ) ) ]
30
30
pub use self :: vsock:: VsockAddr ;
31
31
32
- /// These constants specify the protocol family to be used
33
- /// in [`socket`](fn.socket.html) and [`socketpair`](fn.socketpair.html)
34
- #[ repr( i32 ) ]
35
- #[ non_exhaustive]
36
- #[ derive( Copy , Clone , PartialEq , Eq , Debug , Hash ) ]
37
- pub enum AddressFamily {
32
+ macro_rules! address_family_enum {
33
+ ( $( $( #[ doc = $doc: tt] ) * $( #[ cfg( $cfg: meta) ] ) * $Variant: ident = $constant: path) ,* $( , ) ?) => {
34
+ /// These constants specify the protocol family to be used
35
+ /// in [`socket`](fn.socket.html) and [`socketpair`](fn.socketpair.html)
36
+ #[ repr( i32 ) ]
37
+ #[ non_exhaustive]
38
+ #[ derive( Copy , Clone , PartialEq , Eq , Debug , Hash ) ]
39
+ pub enum AddressFamily {
40
+ $(
41
+ $( #[ doc = $doc] ) *
42
+ $( #[ cfg( $cfg) ] ) *
43
+ $Variant = $constant,
44
+ ) *
45
+ }
46
+
47
+ impl AddressFamily {
48
+ /// Create a new `AddressFamily` from an integer value retrieved from `libc`, usually from
49
+ /// the `sa_family` field of a `sockaddr`.
50
+ ///
51
+ /// Currently only supports these address families: Unix, Inet (v4 & v6), Netlink, Link/Packet
52
+ /// and System. Returns None for unsupported or unknown address families.
53
+ pub const fn from_i32( family: i32 ) -> Option <AddressFamily > {
54
+ match family {
55
+ $(
56
+ $( #[ cfg( $cfg) ] ) *
57
+ $constant => Some ( AddressFamily :: $Variant) ,
58
+ ) *
59
+ _ => None
60
+ }
61
+ }
62
+ }
63
+ } ;
64
+ }
65
+
66
+ address_family_enum ! {
38
67
/// Local communication (see [`unix(7)`](https://man7.org/linux/man-pages/man7/unix.7.html))
39
68
Unix = libc:: AF_UNIX ,
40
69
/// IPv4 Internet protocols (see [`ip(7)`](https://man7.org/linux/man-pages/man7/ip.7.html))
@@ -231,38 +260,6 @@ pub enum AddressFamily {
231
260
Unspec = libc:: AF_UNSPEC ,
232
261
}
233
262
234
- impl AddressFamily {
235
- /// Create a new `AddressFamily` from an integer value retrieved from `libc`, usually from
236
- /// the `sa_family` field of a `sockaddr`.
237
- ///
238
- /// Currently only supports these address families: Unix, Inet (v4 & v6), Netlink, Link/Packet
239
- /// and System. Returns None for unsupported or unknown address families.
240
- pub const fn from_i32 ( family : i32 ) -> Option < AddressFamily > {
241
- match family {
242
- libc:: AF_UNIX => Some ( AddressFamily :: Unix ) ,
243
- libc:: AF_INET => Some ( AddressFamily :: Inet ) ,
244
- libc:: AF_INET6 => Some ( AddressFamily :: Inet6 ) ,
245
- #[ cfg( any( target_os = "android" , target_os = "linux" ) ) ]
246
- libc:: AF_NETLINK => Some ( AddressFamily :: Netlink ) ,
247
- #[ cfg( any( target_os = "macos" , target_os = "macos" ) ) ]
248
- libc:: AF_SYSTEM => Some ( AddressFamily :: System ) ,
249
- #[ cfg( any( target_os = "android" , target_os = "linux" ) ) ]
250
- libc:: AF_PACKET => Some ( AddressFamily :: Packet ) ,
251
- #[ cfg( any( target_os = "dragonfly" ,
252
- target_os = "freebsd" ,
253
- target_os = "ios" ,
254
- target_os = "macos" ,
255
- target_os = "netbsd" ,
256
- target_os = "illumos" ,
257
- target_os = "openbsd" ) ) ]
258
- libc:: AF_LINK => Some ( AddressFamily :: Link ) ,
259
- #[ cfg( any( target_os = "android" , target_os = "linux" ) ) ]
260
- libc:: AF_VSOCK => Some ( AddressFamily :: Vsock ) ,
261
- _ => None
262
- }
263
- }
264
- }
265
-
266
263
#[ derive( Clone , Copy , Debug , Eq , Hash , PartialEq ) ]
267
264
pub enum InetAddr {
268
265
V4 ( libc:: sockaddr_in ) ,
@@ -515,7 +512,7 @@ impl fmt::Display for Ipv6Addr {
515
512
}
516
513
517
514
/// A wrapper around `sockaddr_un`.
518
- #[ derive( Clone , Copy , Debug ) ]
515
+ #[ derive( Clone , Copy ) ]
519
516
pub struct UnixAddr {
520
517
// INVARIANT: sun & path_len are valid as defined by docs for from_raw_parts
521
518
sun : libc:: sockaddr_un ,
@@ -678,6 +675,17 @@ fn fmt_abstract(abs: &[u8], f: &mut fmt::Formatter) -> fmt::Result {
678
675
Ok ( ( ) )
679
676
}
680
677
678
+ impl fmt:: Debug for UnixAddr {
679
+ fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
680
+ match self . kind ( ) {
681
+ UnixAddrKind :: Pathname ( path) => path. fmt ( f) ,
682
+ UnixAddrKind :: Unnamed => f. pad ( "<unbound UNIX socket>" ) ,
683
+ #[ cfg( any( target_os = "android" , target_os = "linux" ) ) ]
684
+ UnixAddrKind :: Abstract ( name) => fmt_abstract ( name, f) ,
685
+ }
686
+ }
687
+ }
688
+
681
689
impl fmt:: Display for UnixAddr {
682
690
fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
683
691
match self . kind ( ) {
@@ -790,58 +798,86 @@ impl SockAddr {
790
798
format ! ( "{}" , self )
791
799
}
792
800
793
- /// Creates a `SockAddr` struct from libc's sockaddr.
801
+ /// Return the appropriate `SockAddr` type from a ` sockaddr` of a certain size .
794
802
///
795
- /// Supports only the following address families: Unix, Inet (v4 & v6), Netlink and System.
796
- /// Returns None for unsupported families.
803
+ /// In C this would usually be done by casting. The `len` argument
804
+ /// should be the number of bytes in the `sockaddr` that are actually
805
+ /// allocated and valid. It must be at least as large as all the useful parts
806
+ /// of the structure. Note that in the case of a `sockaddr_un`, `len` need not
807
+ /// include the terminating null.
797
808
///
798
809
/// # Safety
799
- ///
800
- /// unsafe because it takes a raw pointer as argument. The caller must
801
- /// ensure that the pointer is valid.
802
- #[ cfg( not( target_os = "fuchsia" ) ) ]
803
- pub unsafe fn from_raw_sockaddr ( addr : * const libc:: sockaddr ) -> Option < SockAddr > {
804
- if addr. is_null ( ) {
805
- None
806
- } else {
807
- match AddressFamily :: from_i32 ( i32:: from ( ( * addr) . sa_family ) ) {
808
- Some ( AddressFamily :: Unix ) => None ,
809
- Some ( AddressFamily :: Inet ) => Some ( SockAddr :: Inet (
810
- InetAddr :: V4 ( * ( addr as * const libc:: sockaddr_in ) ) ) ) ,
811
- Some ( AddressFamily :: Inet6 ) => Some ( SockAddr :: Inet (
812
- InetAddr :: V6 ( * ( addr as * const libc:: sockaddr_in6 ) ) ) ) ,
813
- #[ cfg( any( target_os = "android" , target_os = "linux" ) ) ]
814
- Some ( AddressFamily :: Netlink ) => Some ( SockAddr :: Netlink (
815
- NetlinkAddr ( * ( addr as * const libc:: sockaddr_nl ) ) ) ) ,
816
- #[ cfg( any( target_os = "ios" , target_os = "macos" ) ) ]
817
- Some ( AddressFamily :: System ) => Some ( SockAddr :: SysControl (
818
- SysControlAddr ( * ( addr as * const libc:: sockaddr_ctl ) ) ) ) ,
819
- #[ cfg( any( target_os = "android" , target_os = "linux" ) ) ]
820
- Some ( AddressFamily :: Packet ) => Some ( SockAddr :: Link (
821
- LinkAddr ( * ( addr as * const libc:: sockaddr_ll ) ) ) ) ,
822
- #[ cfg( any( target_os = "dragonfly" ,
823
- target_os = "freebsd" ,
824
- target_os = "ios" ,
825
- target_os = "macos" ,
826
- target_os = "netbsd" ,
827
- target_os = "illumos" ,
828
- target_os = "openbsd" ) ) ]
829
- Some ( AddressFamily :: Link ) => {
830
- let ether_addr = LinkAddr ( * ( addr as * const libc:: sockaddr_dl ) ) ;
831
- if ether_addr. is_empty ( ) {
832
- None
833
- } else {
834
- Some ( SockAddr :: Link ( ether_addr) )
835
- }
836
- } ,
837
- #[ cfg( any( target_os = "android" , target_os = "linux" ) ) ]
838
- Some ( AddressFamily :: Vsock ) => Some ( SockAddr :: Vsock (
839
- VsockAddr ( * ( addr as * const libc:: sockaddr_vm ) ) ) ) ,
840
- // Other address families are currently not supported and simply yield a None
841
- // entry instead of a proper conversion to a `SockAddr`.
842
- Some ( _) | None => None ,
810
+ /// `addr` must be a valid, non-null pointer, and `len` should describe the
811
+ /// number of bytes within `*addr` that are initialized and represent data.
812
+ pub unsafe fn from_raw_sockaddr ( addr : * const libc:: sockaddr , len : usize ) -> Result < SockAddr > {
813
+ let af = ( * addr) . sa_family ;
814
+ if len < mem:: size_of_val ( & af) {
815
+ return Err ( Error :: from ( Errno :: ENOTCONN ) ) ;
816
+ }
817
+
818
+ let af = AddressFamily :: from_i32 ( af. into ( ) ) . ok_or ( Errno :: EAFNOSUPPORT ) ?;
819
+ match af {
820
+ AddressFamily :: Inet => {
821
+ use libc:: sockaddr_in;
822
+ assert ! ( len as usize >= mem:: size_of:: <sockaddr_in>( ) ) ;
823
+ let sin = * ( addr as * const sockaddr_in ) ;
824
+ Ok ( SockAddr :: Inet ( InetAddr :: V4 ( sin) ) )
825
+ }
826
+ AddressFamily :: Inet6 => {
827
+ use libc:: sockaddr_in6;
828
+ assert ! ( len as usize >= mem:: size_of:: <sockaddr_in6>( ) ) ;
829
+ let sin6 = * ( addr as * const sockaddr_in6 ) ;
830
+ Ok ( SockAddr :: Inet ( InetAddr :: V6 ( sin6) ) )
831
+ }
832
+ AddressFamily :: Unix => {
833
+ use libc:: sockaddr_un;
834
+ let pathlen = len - offset_of ! ( sockaddr_un, sun_path) ;
835
+ let sun = * ( addr as * const sockaddr_un ) ;
836
+ Ok ( SockAddr :: Unix ( UnixAddr :: from_raw_parts ( sun, pathlen) ) )
837
+ }
838
+ #[ cfg( any( target_os = "android" , target_os = "linux" ) ) ]
839
+ AddressFamily :: Packet => {
840
+ // Don't assert anything about the size.
841
+ // Apparently the Linux kernel can return smaller sizes when
842
+ // the value in the last element of sockaddr_ll (`sll_addr`) is
843
+ // smaller than the declared size of that field
844
+ let sll = * ( addr as * const libc:: sockaddr_ll ) ;
845
+ Ok ( SockAddr :: Link ( LinkAddr ( sll) ) )
846
+ }
847
+ #[ cfg( any( target_os = "android" , target_os = "linux" ) ) ]
848
+ AddressFamily :: Netlink => {
849
+ let snl = * ( addr as * const libc:: sockaddr_nl ) ;
850
+ Ok ( SockAddr :: Netlink ( NetlinkAddr ( snl) ) )
851
+ }
852
+ #[ cfg( any( target_os = "android" , target_os = "linux" ) ) ]
853
+ AddressFamily :: Alg => {
854
+ let salg = * ( addr as * const libc:: sockaddr_alg ) ;
855
+ Ok ( SockAddr :: Alg ( AlgAddr ( salg) ) )
856
+ }
857
+ #[ cfg( any( target_os = "android" , target_os = "linux" ) ) ]
858
+ AddressFamily :: Vsock => {
859
+ let svm = * ( addr as * const libc:: sockaddr_vm ) ;
860
+ Ok ( SockAddr :: Vsock ( VsockAddr ( svm) ) )
861
+ }
862
+ #[ cfg( any( target_os = "dragonfly" ,
863
+ target_os = "freebsd" ,
864
+ target_os = "ios" ,
865
+ target_os = "macos" ,
866
+ target_os = "netbsd" ,
867
+ target_os = "illumos" ,
868
+ target_os = "openbsd" ) ) ]
869
+ AddressFamily :: Link => {
870
+ let ether_addr = LinkAddr ( * ( addr as * const libc:: sockaddr_dl ) ) ;
871
+ Ok ( SockAddr :: Link ( ether_addr) )
872
+ }
873
+ #[ cfg( any( target_os = "ios" , target_os = "macos" ) ) ]
874
+ AddressFamily :: System => {
875
+ let sctl = SysControlAddr ( * ( addr as * const libc:: sockaddr_ctl ) ) ;
876
+ Ok ( SockAddr :: SysControl ( sctl) )
843
877
}
878
+ _ => Err ( Errno :: EAFNOSUPPORT ) ,
844
879
}
880
+
845
881
}
846
882
847
883
/// Conversion from nix's SockAddr type to the underlying libc sockaddr type.
@@ -1379,8 +1415,12 @@ mod tests {
1379
1415
fn test_macos_loopback_datalink_addr ( ) {
1380
1416
let bytes = [ 20i8 , 18 , 1 , 0 , 24 , 3 , 0 , 0 , 108 , 111 , 48 , 0 , 0 , 0 , 0 , 0 ] ;
1381
1417
let sa = bytes. as_ptr ( ) as * const libc:: sockaddr ;
1382
- let _sock_addr = unsafe { SockAddr :: from_raw_sockaddr ( sa) } ;
1383
- assert ! ( _sock_addr. is_none( ) ) ;
1418
+ let sock_addr = unsafe { SockAddr :: from_raw_sockaddr ( sa, bytes. len ( ) ) . unwrap ( ) } ;
1419
+ if let SockAddr :: Link ( link_addr) = sock_addr {
1420
+ assert ! ( link_addr. is_empty( ) )
1421
+ } else {
1422
+ panic ! ( "bad family" )
1423
+ }
1384
1424
}
1385
1425
1386
1426
#[ cfg( any( target_os = "dragonfly" ,
@@ -1394,11 +1434,7 @@ mod tests {
1394
1434
let bytes = [ 20i8 , 18 , 7 , 0 , 6 , 3 , 6 , 0 , 101 , 110 , 48 , 24 , 101 , -112 , -35 , 76 , -80 ] ;
1395
1435
let ptr = bytes. as_ptr ( ) ;
1396
1436
let sa = ptr as * const libc:: sockaddr ;
1397
- let _sock_addr = unsafe { SockAddr :: from_raw_sockaddr ( sa) } ;
1398
-
1399
- assert ! ( _sock_addr. is_some( ) ) ;
1400
-
1401
- let sock_addr = _sock_addr. unwrap ( ) ;
1437
+ let sock_addr = unsafe { SockAddr :: from_raw_sockaddr ( sa, bytes. len ( ) ) . unwrap ( ) } ;
1402
1438
1403
1439
assert_eq ! ( sock_addr. family( ) , AddressFamily :: Link ) ;
1404
1440
@@ -1416,11 +1452,7 @@ mod tests {
1416
1452
let bytes = [ 25u8 , 0 , 0 , 0 , 6 , 0 , 6 , 0 , 24 , 101 , 144 , 221 , 76 , 176 ] ;
1417
1453
let ptr = bytes. as_ptr ( ) ;
1418
1454
let sa = ptr as * const libc:: sockaddr ;
1419
- let _sock_addr = unsafe { SockAddr :: from_raw_sockaddr ( sa) } ;
1420
-
1421
- assert ! ( _sock_addr. is_some( ) ) ;
1422
-
1423
- let sock_addr = _sock_addr. unwrap ( ) ;
1455
+ let sock_addr = unsafe { SockAddr :: from_raw_sockaddr ( sa, bytes. len ( ) ) . unwrap ( ) } ;
1424
1456
1425
1457
assert_eq ! ( sock_addr. family( ) , AddressFamily :: Link ) ;
1426
1458
0 commit comments