@@ -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 ,
@@ -660,6 +657,20 @@ impl UnixAddr {
660
657
}
661
658
}
662
659
660
+ impl fmt:: Debug for UnixAddr {
661
+ fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
662
+ match self . kind ( ) {
663
+ UnixAddrKind :: Pathname ( path) => path. fmt ( f) ,
664
+ UnixAddrKind :: Unnamed => f. pad ( "<unbound UNIX socket>" ) ,
665
+ #[ cfg( any( target_os = "android" , target_os = "linux" ) ) ]
666
+ UnixAddrKind :: Abstract ( name) => {
667
+ write ! ( f, "@{:?}" , String :: from_utf8_lossy( name) )
668
+ }
669
+ }
670
+ }
671
+
672
+ }
673
+
663
674
impl fmt:: Display for UnixAddr {
664
675
fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
665
676
match self . kind ( ) {
@@ -774,58 +785,86 @@ impl SockAddr {
774
785
format ! ( "{}" , self )
775
786
}
776
787
777
- /// Creates a `SockAddr` struct from libc's sockaddr.
788
+ /// Return the appropriate `SockAddr` type from a ` sockaddr` of a certain size .
778
789
///
779
- /// Supports only the following address families: Unix, Inet (v4 & v6), Netlink and System.
780
- /// Returns None for unsupported families.
790
+ /// In C this would usually be done by casting. The `len` argument
791
+ /// should be the number of bytes in the `sockaddr` that are actually
792
+ /// allocated and valid. It must be at least as large as all the useful parts
793
+ /// of the structure. Note that in the case of a `sockaddr_un`, `len` should
794
+ /// include the terminating null.
781
795
///
782
796
/// # Safety
783
- ///
784
- /// unsafe because it takes a raw pointer as argument. The caller must
785
- /// ensure that the pointer is valid.
786
- #[ cfg( not( target_os = "fuchsia" ) ) ]
787
- pub unsafe fn from_raw_sockaddr ( addr : * const libc:: sockaddr ) -> Option < SockAddr > {
788
- if addr. is_null ( ) {
789
- None
790
- } else {
791
- match AddressFamily :: from_i32 ( i32:: from ( ( * addr) . sa_family ) ) {
792
- Some ( AddressFamily :: Unix ) => None ,
793
- Some ( AddressFamily :: Inet ) => Some ( SockAddr :: Inet (
794
- InetAddr :: V4 ( * ( addr as * const libc:: sockaddr_in ) ) ) ) ,
795
- Some ( AddressFamily :: Inet6 ) => Some ( SockAddr :: Inet (
796
- InetAddr :: V6 ( * ( addr as * const libc:: sockaddr_in6 ) ) ) ) ,
797
- #[ cfg( any( target_os = "android" , target_os = "linux" ) ) ]
798
- Some ( AddressFamily :: Netlink ) => Some ( SockAddr :: Netlink (
799
- NetlinkAddr ( * ( addr as * const libc:: sockaddr_nl ) ) ) ) ,
800
- #[ cfg( any( target_os = "ios" , target_os = "macos" ) ) ]
801
- Some ( AddressFamily :: System ) => Some ( SockAddr :: SysControl (
802
- SysControlAddr ( * ( addr as * const libc:: sockaddr_ctl ) ) ) ) ,
803
- #[ cfg( any( target_os = "android" , target_os = "linux" ) ) ]
804
- Some ( AddressFamily :: Packet ) => Some ( SockAddr :: Link (
805
- LinkAddr ( * ( addr as * const libc:: sockaddr_ll ) ) ) ) ,
806
- #[ cfg( any( target_os = "dragonfly" ,
807
- target_os = "freebsd" ,
808
- target_os = "ios" ,
809
- target_os = "macos" ,
810
- target_os = "netbsd" ,
811
- target_os = "illumos" ,
812
- target_os = "openbsd" ) ) ]
813
- Some ( AddressFamily :: Link ) => {
814
- let ether_addr = LinkAddr ( * ( addr as * const libc:: sockaddr_dl ) ) ;
815
- if ether_addr. is_empty ( ) {
816
- None
817
- } else {
818
- Some ( SockAddr :: Link ( ether_addr) )
819
- }
820
- } ,
821
- #[ cfg( any( target_os = "android" , target_os = "linux" ) ) ]
822
- Some ( AddressFamily :: Vsock ) => Some ( SockAddr :: Vsock (
823
- VsockAddr ( * ( addr as * const libc:: sockaddr_vm ) ) ) ) ,
824
- // Other address families are currently not supported and simply yield a None
825
- // entry instead of a proper conversion to a `SockAddr`.
826
- Some ( _) | None => None ,
797
+ /// `addr` must be a valid, non-null pointer, and `len` should describe the
798
+ /// number of bytes within `*addr` that are initialized and represent data.
799
+ pub unsafe fn from_raw_sockaddr ( addr : * const libc:: sockaddr , len : usize ) -> Result < SockAddr > {
800
+ let af = ( * addr) . sa_family ;
801
+ if len < mem:: size_of_val ( & af) {
802
+ return Err ( Error :: from ( Errno :: ENOTCONN ) ) ;
803
+ }
804
+
805
+ let af = AddressFamily :: from_i32 ( af. into ( ) ) . ok_or ( Errno :: EAFNOSUPPORT ) ?;
806
+ match af {
807
+ AddressFamily :: Inet => {
808
+ use libc:: sockaddr_in;
809
+ assert ! ( len as usize >= mem:: size_of:: <sockaddr_in>( ) ) ;
810
+ let sin = * ( addr as * const sockaddr_in ) ;
811
+ Ok ( SockAddr :: Inet ( InetAddr :: V4 ( sin) ) )
812
+ }
813
+ AddressFamily :: Inet6 => {
814
+ use libc:: sockaddr_in6;
815
+ assert ! ( len as usize >= mem:: size_of:: <sockaddr_in6>( ) ) ;
816
+ let sin6 = * ( addr as * const sockaddr_in6 ) ;
817
+ Ok ( SockAddr :: Inet ( InetAddr :: V6 ( sin6) ) )
827
818
}
819
+ AddressFamily :: Unix => {
820
+ use libc:: sockaddr_un;
821
+ let pathlen = len - offset_of ! ( sockaddr_un, sun_path) ;
822
+ let sun = * ( addr as * const sockaddr_un ) ;
823
+ Ok ( SockAddr :: Unix ( UnixAddr :: from_raw_parts ( sun, pathlen) ) )
824
+ }
825
+ #[ cfg( any( target_os = "android" , target_os = "linux" ) ) ]
826
+ AddressFamily :: Packet => {
827
+ // Don't assert anything about the size.
828
+ // Apparently the Linux kernel can return smaller sizes when
829
+ // the value in the last element of sockaddr_ll (`sll_addr`) is
830
+ // smaller than the declared size of that field
831
+ let sll = * ( addr as * const libc:: sockaddr_ll ) ;
832
+ Ok ( SockAddr :: Link ( LinkAddr ( sll) ) )
833
+ }
834
+ #[ cfg( any( target_os = "android" , target_os = "linux" ) ) ]
835
+ AddressFamily :: Netlink => {
836
+ let snl = * ( addr as * const libc:: sockaddr_nl ) ;
837
+ Ok ( SockAddr :: Netlink ( NetlinkAddr ( snl) ) )
838
+ }
839
+ #[ cfg( any( target_os = "android" , target_os = "linux" ) ) ]
840
+ AddressFamily :: Alg => {
841
+ let salg = * ( addr as * const libc:: sockaddr_alg ) ;
842
+ Ok ( SockAddr :: Alg ( AlgAddr ( salg) ) )
843
+ }
844
+ #[ cfg( any( target_os = "android" , target_os = "linux" ) ) ]
845
+ AddressFamily :: Vsock => {
846
+ let svm = * ( addr as * const libc:: sockaddr_vm ) ;
847
+ Ok ( SockAddr :: Vsock ( VsockAddr ( svm) ) )
848
+ }
849
+ #[ cfg( any( target_os = "dragonfly" ,
850
+ target_os = "freebsd" ,
851
+ target_os = "ios" ,
852
+ target_os = "macos" ,
853
+ target_os = "netbsd" ,
854
+ target_os = "illumos" ,
855
+ target_os = "openbsd" ) ) ]
856
+ AddressFamily :: Link => {
857
+ let ether_addr = LinkAddr ( * ( addr as * const libc:: sockaddr_dl ) ) ;
858
+ Ok ( SockAddr :: Link ( ether_addr) )
859
+ }
860
+ #[ cfg( any( target_os = "ios" , target_os = "macos" ) ) ]
861
+ AddressFamily :: System => {
862
+ let sctl = SysControlAddr ( * ( addr as * const libc:: sockaddr_ctl ) ) ;
863
+ Ok ( SockAddr :: SysControl ( sctl) )
864
+ }
865
+ _ => Err ( Errno :: EAFNOSUPPORT ) ,
828
866
}
867
+
829
868
}
830
869
831
870
/// Conversion from nix's SockAddr type to the underlying libc sockaddr type.
@@ -1363,8 +1402,12 @@ mod tests {
1363
1402
fn test_macos_loopback_datalink_addr ( ) {
1364
1403
let bytes = [ 20i8 , 18 , 1 , 0 , 24 , 3 , 0 , 0 , 108 , 111 , 48 , 0 , 0 , 0 , 0 , 0 ] ;
1365
1404
let sa = bytes. as_ptr ( ) as * const libc:: sockaddr ;
1366
- let _sock_addr = unsafe { SockAddr :: from_raw_sockaddr ( sa) } ;
1367
- assert ! ( _sock_addr. is_none( ) ) ;
1405
+ let sock_addr = unsafe { SockAddr :: from_raw_sockaddr ( sa, bytes. len ( ) ) . unwrap ( ) } ;
1406
+ if let SockAddr :: Link ( link_addr) = sock_addr {
1407
+ assert ! ( link_addr. is_empty( ) )
1408
+ } else {
1409
+ panic ! ( "bad family" )
1410
+ }
1368
1411
}
1369
1412
1370
1413
#[ cfg( any( target_os = "dragonfly" ,
@@ -1378,11 +1421,7 @@ mod tests {
1378
1421
let bytes = [ 20i8 , 18 , 7 , 0 , 6 , 3 , 6 , 0 , 101 , 110 , 48 , 24 , 101 , -112 , -35 , 76 , -80 ] ;
1379
1422
let ptr = bytes. as_ptr ( ) ;
1380
1423
let sa = ptr as * const libc:: sockaddr ;
1381
- let _sock_addr = unsafe { SockAddr :: from_raw_sockaddr ( sa) } ;
1382
-
1383
- assert ! ( _sock_addr. is_some( ) ) ;
1384
-
1385
- let sock_addr = _sock_addr. unwrap ( ) ;
1424
+ let sock_addr = unsafe { SockAddr :: from_raw_sockaddr ( sa, bytes. len ( ) ) . unwrap ( ) } ;
1386
1425
1387
1426
assert_eq ! ( sock_addr. family( ) , AddressFamily :: Link ) ;
1388
1427
@@ -1400,11 +1439,7 @@ mod tests {
1400
1439
let bytes = [ 25u8 , 0 , 0 , 0 , 6 , 0 , 6 , 0 , 24 , 101 , 144 , 221 , 76 , 176 ] ;
1401
1440
let ptr = bytes. as_ptr ( ) ;
1402
1441
let sa = ptr as * const libc:: sockaddr ;
1403
- let _sock_addr = unsafe { SockAddr :: from_raw_sockaddr ( sa) } ;
1404
-
1405
- assert ! ( _sock_addr. is_some( ) ) ;
1406
-
1407
- let sock_addr = _sock_addr. unwrap ( ) ;
1442
+ let sock_addr = unsafe { SockAddr :: from_raw_sockaddr ( sa, bytes. len ( ) ) . unwrap ( ) } ;
1408
1443
1409
1444
assert_eq ! ( sock_addr. family( ) , AddressFamily :: Link ) ;
1410
1445
0 commit comments