@@ -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 ) ,
@@ -517,7 +514,7 @@ impl fmt::Display for Ipv6Addr {
517
514
}
518
515
519
516
/// A wrapper around `sockaddr_un`.
520
- #[ derive( Clone , Copy , Debug ) ]
517
+ #[ derive( Clone , Copy ) ]
521
518
pub struct UnixAddr {
522
519
// INVARIANT: sun & path_len are valid as defined by docs for from_raw_parts
523
520
sun : libc:: sockaddr_un ,
@@ -680,6 +677,17 @@ fn fmt_abstract(abs: &[u8], f: &mut fmt::Formatter) -> fmt::Result {
680
677
Ok ( ( ) )
681
678
}
682
679
680
+ impl fmt:: Debug for UnixAddr {
681
+ fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
682
+ match self . kind ( ) {
683
+ UnixAddrKind :: Pathname ( path) => path. fmt ( f) ,
684
+ UnixAddrKind :: Unnamed => f. pad ( "<unbound UNIX socket>" ) ,
685
+ #[ cfg( any( target_os = "android" , target_os = "linux" ) ) ]
686
+ UnixAddrKind :: Abstract ( name) => fmt_abstract ( name, f) ,
687
+ }
688
+ }
689
+ }
690
+
683
691
impl fmt:: Display for UnixAddr {
684
692
fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
685
693
match self . kind ( ) {
@@ -792,58 +800,86 @@ impl SockAddr {
792
800
format ! ( "{}" , self )
793
801
}
794
802
795
- /// Creates a `SockAddr` struct from libc's sockaddr.
803
+ /// Return the appropriate `SockAddr` type from a ` sockaddr` of a certain size .
796
804
///
797
- /// Supports only the following address families: Unix, Inet (v4 & v6), Netlink and System.
798
- /// Returns None for unsupported families.
805
+ /// In C this would usually be done by casting. The `len` argument
806
+ /// should be the number of bytes in the `sockaddr` that are actually
807
+ /// allocated and valid. It must be at least as large as all the useful parts
808
+ /// of the structure. Note that in the case of a `sockaddr_un`, `len` need not
809
+ /// include the terminating null.
799
810
///
800
811
/// # Safety
801
- ///
802
- /// unsafe because it takes a raw pointer as argument. The caller must
803
- /// ensure that the pointer is valid.
804
- #[ cfg( not( target_os = "fuchsia" ) ) ]
805
- pub unsafe fn from_raw_sockaddr ( addr : * const libc:: sockaddr ) -> Option < SockAddr > {
806
- if addr. is_null ( ) {
807
- None
808
- } else {
809
- match AddressFamily :: from_i32 ( i32:: from ( ( * addr) . sa_family ) ) {
810
- Some ( AddressFamily :: Unix ) => None ,
811
- Some ( AddressFamily :: Inet ) => Some ( SockAddr :: Inet (
812
- InetAddr :: V4 ( * ( addr as * const libc:: sockaddr_in ) ) ) ) ,
813
- Some ( AddressFamily :: Inet6 ) => Some ( SockAddr :: Inet (
814
- InetAddr :: V6 ( * ( addr as * const libc:: sockaddr_in6 ) ) ) ) ,
815
- #[ cfg( any( target_os = "android" , target_os = "linux" ) ) ]
816
- Some ( AddressFamily :: Netlink ) => Some ( SockAddr :: Netlink (
817
- NetlinkAddr ( * ( addr as * const libc:: sockaddr_nl ) ) ) ) ,
818
- #[ cfg( any( target_os = "ios" , target_os = "macos" ) ) ]
819
- Some ( AddressFamily :: System ) => Some ( SockAddr :: SysControl (
820
- SysControlAddr ( * ( addr as * const libc:: sockaddr_ctl ) ) ) ) ,
821
- #[ cfg( any( target_os = "android" , target_os = "linux" ) ) ]
822
- Some ( AddressFamily :: Packet ) => Some ( SockAddr :: Link (
823
- LinkAddr ( * ( addr as * const libc:: sockaddr_ll ) ) ) ) ,
824
- #[ cfg( any( target_os = "dragonfly" ,
825
- target_os = "freebsd" ,
826
- target_os = "ios" ,
827
- target_os = "macos" ,
828
- target_os = "netbsd" ,
829
- target_os = "illumos" ,
830
- target_os = "openbsd" ) ) ]
831
- Some ( AddressFamily :: Link ) => {
832
- let ether_addr = LinkAddr ( * ( addr as * const libc:: sockaddr_dl ) ) ;
833
- if ether_addr. is_empty ( ) {
834
- None
835
- } else {
836
- Some ( SockAddr :: Link ( ether_addr) )
837
- }
838
- } ,
839
- #[ cfg( any( target_os = "android" , target_os = "linux" ) ) ]
840
- Some ( AddressFamily :: Vsock ) => Some ( SockAddr :: Vsock (
841
- VsockAddr ( * ( addr as * const libc:: sockaddr_vm ) ) ) ) ,
842
- // Other address families are currently not supported and simply yield a None
843
- // entry instead of a proper conversion to a `SockAddr`.
844
- Some ( _) | None => None ,
812
+ /// `addr` must be a valid, non-null pointer, and `len` should describe the
813
+ /// number of bytes within `*addr` that are initialized and represent data.
814
+ pub unsafe fn from_raw_sockaddr ( addr : * const libc:: sockaddr , len : usize ) -> Result < SockAddr > {
815
+ let af = ( * addr) . sa_family ;
816
+ if len < mem:: size_of_val ( & af) {
817
+ return Err ( Errno :: ENOTCONN ) ;
818
+ }
819
+
820
+ let af = AddressFamily :: from_i32 ( af. into ( ) ) . ok_or ( Errno :: EAFNOSUPPORT ) ?;
821
+ match af {
822
+ AddressFamily :: Inet => {
823
+ use libc:: sockaddr_in;
824
+ assert ! ( len as usize >= mem:: size_of:: <sockaddr_in>( ) ) ;
825
+ let sin = * ( addr as * const sockaddr_in ) ;
826
+ Ok ( SockAddr :: Inet ( InetAddr :: V4 ( sin) ) )
827
+ }
828
+ AddressFamily :: Inet6 => {
829
+ use libc:: sockaddr_in6;
830
+ assert ! ( len as usize >= mem:: size_of:: <sockaddr_in6>( ) ) ;
831
+ let sin6 = * ( addr as * const sockaddr_in6 ) ;
832
+ Ok ( SockAddr :: Inet ( InetAddr :: V6 ( sin6) ) )
833
+ }
834
+ AddressFamily :: Unix => {
835
+ use libc:: sockaddr_un;
836
+ let pathlen = len - offset_of ! ( sockaddr_un, sun_path) ;
837
+ let sun = * ( addr as * const sockaddr_un ) ;
838
+ Ok ( SockAddr :: Unix ( UnixAddr :: from_raw_parts ( sun, pathlen) ) )
839
+ }
840
+ #[ cfg( any( target_os = "android" , target_os = "linux" ) ) ]
841
+ AddressFamily :: Packet => {
842
+ // Don't assert anything about the size.
843
+ // Apparently the Linux kernel can return smaller sizes when
844
+ // the value in the last element of sockaddr_ll (`sll_addr`) is
845
+ // smaller than the declared size of that field
846
+ let sll = * ( addr as * const libc:: sockaddr_ll ) ;
847
+ Ok ( SockAddr :: Link ( LinkAddr ( sll) ) )
848
+ }
849
+ #[ cfg( any( target_os = "android" , target_os = "linux" ) ) ]
850
+ AddressFamily :: Netlink => {
851
+ let snl = * ( addr as * const libc:: sockaddr_nl ) ;
852
+ Ok ( SockAddr :: Netlink ( NetlinkAddr ( snl) ) )
853
+ }
854
+ #[ cfg( any( target_os = "android" , target_os = "linux" ) ) ]
855
+ AddressFamily :: Alg => {
856
+ let salg = * ( addr as * const libc:: sockaddr_alg ) ;
857
+ Ok ( SockAddr :: Alg ( AlgAddr ( salg) ) )
858
+ }
859
+ #[ cfg( any( target_os = "android" , target_os = "linux" ) ) ]
860
+ AddressFamily :: Vsock => {
861
+ let svm = * ( addr as * const libc:: sockaddr_vm ) ;
862
+ Ok ( SockAddr :: Vsock ( VsockAddr ( svm) ) )
863
+ }
864
+ #[ cfg( any( target_os = "dragonfly" ,
865
+ target_os = "freebsd" ,
866
+ target_os = "ios" ,
867
+ target_os = "macos" ,
868
+ target_os = "netbsd" ,
869
+ target_os = "illumos" ,
870
+ target_os = "openbsd" ) ) ]
871
+ AddressFamily :: Link => {
872
+ let ether_addr = LinkAddr ( * ( addr as * const libc:: sockaddr_dl ) ) ;
873
+ Ok ( SockAddr :: Link ( ether_addr) )
874
+ }
875
+ #[ cfg( any( target_os = "ios" , target_os = "macos" ) ) ]
876
+ AddressFamily :: System => {
877
+ let sctl = SysControlAddr ( * ( addr as * const libc:: sockaddr_ctl ) ) ;
878
+ Ok ( SockAddr :: SysControl ( sctl) )
845
879
}
880
+ _ => Err ( Errno :: EAFNOSUPPORT ) ,
846
881
}
882
+
847
883
}
848
884
849
885
/// Conversion from nix's SockAddr type to the underlying libc sockaddr type.
@@ -1381,8 +1417,12 @@ mod tests {
1381
1417
fn test_macos_loopback_datalink_addr ( ) {
1382
1418
let bytes = [ 20i8 , 18 , 1 , 0 , 24 , 3 , 0 , 0 , 108 , 111 , 48 , 0 , 0 , 0 , 0 , 0 ] ;
1383
1419
let sa = bytes. as_ptr ( ) as * const libc:: sockaddr ;
1384
- let _sock_addr = unsafe { SockAddr :: from_raw_sockaddr ( sa) } ;
1385
- assert ! ( _sock_addr. is_none( ) ) ;
1420
+ let sock_addr = unsafe { SockAddr :: from_raw_sockaddr ( sa, bytes. len ( ) ) . unwrap ( ) } ;
1421
+ if let SockAddr :: Link ( link_addr) = sock_addr {
1422
+ assert ! ( link_addr. is_empty( ) )
1423
+ } else {
1424
+ panic ! ( "bad family" )
1425
+ }
1386
1426
}
1387
1427
1388
1428
#[ cfg( any( target_os = "dragonfly" ,
@@ -1396,11 +1436,7 @@ mod tests {
1396
1436
let bytes = [ 20i8 , 18 , 7 , 0 , 6 , 3 , 6 , 0 , 101 , 110 , 48 , 24 , 101 , -112 , -35 , 76 , -80 ] ;
1397
1437
let ptr = bytes. as_ptr ( ) ;
1398
1438
let sa = ptr as * const libc:: sockaddr ;
1399
- let _sock_addr = unsafe { SockAddr :: from_raw_sockaddr ( sa) } ;
1400
-
1401
- assert ! ( _sock_addr. is_some( ) ) ;
1402
-
1403
- let sock_addr = _sock_addr. unwrap ( ) ;
1439
+ let sock_addr = unsafe { SockAddr :: from_raw_sockaddr ( sa, bytes. len ( ) ) . unwrap ( ) } ;
1404
1440
1405
1441
assert_eq ! ( sock_addr. family( ) , AddressFamily :: Link ) ;
1406
1442
@@ -1418,11 +1454,7 @@ mod tests {
1418
1454
let bytes = [ 25u8 , 0 , 0 , 0 , 6 , 0 , 6 , 0 , 24 , 101 , 144 , 221 , 76 , 176 ] ;
1419
1455
let ptr = bytes. as_ptr ( ) ;
1420
1456
let sa = ptr as * const libc:: sockaddr ;
1421
- let _sock_addr = unsafe { SockAddr :: from_raw_sockaddr ( sa) } ;
1422
-
1423
- assert ! ( _sock_addr. is_some( ) ) ;
1424
-
1425
- let sock_addr = _sock_addr. unwrap ( ) ;
1457
+ let sock_addr = unsafe { SockAddr :: from_raw_sockaddr ( sa, bytes. len ( ) ) . unwrap ( ) } ;
1426
1458
1427
1459
assert_eq ! ( sock_addr. family( ) , AddressFamily :: Link ) ;
1428
1460
0 commit comments