@@ -3,9 +3,11 @@ use std::net::{SocketAddr, SocketAddrV4, SocketAddrV6};
3
3
use std:: { fmt, ptr} ;
4
4
5
5
use crate :: sys:: {
6
- c_int , sa_family_t, sockaddr, sockaddr_in, sockaddr_in6, sockaddr_storage, socklen_t, AF_INET ,
6
+ sa_family_t, sockaddr, sockaddr_in, sockaddr_in6, sockaddr_storage, socklen_t, AF_INET ,
7
7
AF_INET6 ,
8
8
} ;
9
+ #[ cfg( windows) ]
10
+ use winapi:: shared:: ws2ipdef:: SOCKADDR_IN6_LH_u ;
9
11
10
12
/// The address of a socket.
11
13
///
@@ -24,7 +26,7 @@ impl SockAddr {
24
26
/// It is up to the user to ensure the `addr` pointer and `len` length are
25
27
/// correct.
26
28
pub unsafe fn from_raw_parts ( addr : * const sockaddr , len : socklen_t ) -> SockAddr {
27
- let mut storage = MaybeUninit :: < sockaddr_storage > :: uninit ( ) ;
29
+ let mut storage = MaybeUninit :: < sockaddr_storage > :: zeroed ( ) ;
28
30
ptr:: copy_nonoverlapping (
29
31
addr as * const _ as * const u8 ,
30
32
storage. as_mut_ptr ( ) as * mut u8 ,
@@ -33,7 +35,7 @@ impl SockAddr {
33
35
SockAddr {
34
36
// This is safe as we written the address to `storage` above.
35
37
storage : storage. assume_init ( ) ,
36
- len : len ,
38
+ len,
37
39
}
38
40
}
39
41
@@ -55,30 +57,50 @@ impl SockAddr {
55
57
/// Returns this address as a `SocketAddr` if it is in the `AF_INET` (IP v4)
56
58
/// or `AF_INET6` (IP v6) family, otherwise returns `None`.
57
59
pub fn as_std ( & self ) -> Option < SocketAddr > {
58
- self . as_inet ( )
59
- . map ( |a| a. into ( ) )
60
- . or_else ( || self . as_inet6 ( ) . map ( |a| a. into ( ) ) )
60
+ if self . storage . ss_family == AF_INET as sa_family_t {
61
+ // Safety: if the ss_family field is AF_INET then storage must be a sockaddr_in.
62
+ let addr = unsafe { & * ( & self . storage as * const _ as * const sockaddr_in ) } ;
63
+
64
+ let ip = crate :: sys:: from_in_addr ( addr. sin_addr ) ;
65
+ let port = u16:: from_be ( addr. sin_port ) ;
66
+ Some ( SocketAddr :: V4 ( SocketAddrV4 :: new ( ip, port) ) )
67
+ } else if self . storage . ss_family == AF_INET6 as sa_family_t {
68
+ // Safety: if the ss_family field is AF_INET6 then storage must be a sockaddr_in6.
69
+ let addr = unsafe { & * ( & self . storage as * const _ as * const sockaddr_in6 ) } ;
70
+
71
+ let ip = crate :: sys:: from_in6_addr ( addr. sin6_addr ) ;
72
+ let port = u16:: from_be ( addr. sin6_port ) ;
73
+ Some ( SocketAddr :: V6 ( SocketAddrV6 :: new (
74
+ ip,
75
+ port,
76
+ addr. sin6_flowinfo ,
77
+ #[ cfg( unix) ]
78
+ addr. sin6_scope_id ,
79
+ #[ cfg( windows) ]
80
+ unsafe {
81
+ * addr. u . sin6_scope_id ( )
82
+ } ,
83
+ ) ) )
84
+ } else {
85
+ None
86
+ }
61
87
}
62
88
63
89
/// Returns this address as a `SocketAddrV4` if it is in the `AF_INET`
64
90
/// family.
65
91
pub fn as_inet ( & self ) -> Option < SocketAddrV4 > {
66
- if self . storage . ss_family as c_int == AF_INET {
67
- let storage: * const sockaddr_storage = ( & self . storage ) as * const _ ;
68
- Some ( unsafe { * ( storage as * const sockaddr_in as * const _ ) } )
69
- } else {
70
- None
92
+ match self . as_std ( ) {
93
+ Some ( SocketAddr :: V4 ( addr) ) => Some ( addr) ,
94
+ _ => None ,
71
95
}
72
96
}
73
97
74
98
/// Returns this address as a `SocketAddrV6` if it is in the `AF_INET6`
75
99
/// family.
76
100
pub fn as_inet6 ( & self ) -> Option < SocketAddrV6 > {
77
- if self . storage . ss_family as c_int == AF_INET6 {
78
- let storage: * const sockaddr_storage = ( & self . storage ) as * const _ ;
79
- Some ( unsafe { * ( storage as * const sockaddr_in6 as * const _ ) } )
80
- } else {
81
- None
101
+ match self . as_std ( ) {
102
+ Some ( SocketAddr :: V6 ( addr) ) => Some ( addr) ,
103
+ _ => None ,
82
104
}
83
105
}
84
106
}
@@ -94,22 +116,67 @@ impl From<SocketAddr> for SockAddr {
94
116
95
117
impl From < SocketAddrV4 > for SockAddr {
96
118
fn from ( addr : SocketAddrV4 ) -> SockAddr {
97
- unsafe {
98
- SockAddr :: from_raw_parts (
99
- & addr as * const _ as * const _ ,
100
- mem:: size_of :: < SocketAddrV4 > ( ) as socklen_t ,
101
- )
119
+ let sockaddr_in = sockaddr_in {
120
+ sin_family : AF_INET as sa_family_t ,
121
+ sin_port : addr. port ( ) . to_be ( ) ,
122
+ sin_addr : crate :: sys:: to_in_addr ( & addr. ip ( ) ) ,
123
+ sin_zero : [ 0 ; 8 ] ,
124
+ #[ cfg( any(
125
+ target_os = "dragonfly" ,
126
+ target_os = "freebsd" ,
127
+ target_os = "ios" ,
128
+ target_os = "macos" ,
129
+ target_os = "netbsd" ,
130
+ target_os = "openbsd"
131
+ ) ) ]
132
+ sin_len : 0 ,
133
+ } ;
134
+ let mut storage = MaybeUninit :: < sockaddr_storage > :: zeroed ( ) ;
135
+ // Safety: A `sockaddr_in` is memory compatible with a `sockaddr_storage`
136
+ unsafe { ( storage. as_mut_ptr ( ) as * mut sockaddr_in ) . write ( sockaddr_in) } ;
137
+ SockAddr {
138
+ storage : unsafe { storage. assume_init ( ) } ,
139
+ len : mem:: size_of :: < sockaddr_in > ( ) as socklen_t ,
102
140
}
103
141
}
104
142
}
105
143
106
144
impl From < SocketAddrV6 > for SockAddr {
107
145
fn from ( addr : SocketAddrV6 ) -> SockAddr {
108
- unsafe {
109
- SockAddr :: from_raw_parts (
110
- & addr as * const _ as * const _ ,
111
- mem:: size_of :: < SocketAddrV6 > ( ) as socklen_t ,
112
- )
146
+ #[ cfg( windows) ]
147
+ let u = unsafe {
148
+ let mut u = mem:: zeroed :: < SOCKADDR_IN6_LH_u > ( ) ;
149
+ * u. sin6_scope_id_mut ( ) = addr. scope_id ( ) ;
150
+ u
151
+ } ;
152
+
153
+ let sockaddr_in6 = sockaddr_in6 {
154
+ sin6_family : AF_INET6 as sa_family_t ,
155
+ sin6_port : addr. port ( ) . to_be ( ) ,
156
+ sin6_addr : crate :: sys:: to_in6_addr ( addr. ip ( ) ) ,
157
+ sin6_flowinfo : addr. flowinfo ( ) ,
158
+ #[ cfg( unix) ]
159
+ sin6_scope_id : addr. scope_id ( ) ,
160
+ #[ cfg( windows) ]
161
+ u,
162
+ #[ cfg( any(
163
+ target_os = "dragonfly" ,
164
+ target_os = "freebsd" ,
165
+ target_os = "ios" ,
166
+ target_os = "macos" ,
167
+ target_os = "netbsd" ,
168
+ target_os = "openbsd"
169
+ ) ) ]
170
+ sin6_len : 0 ,
171
+ #[ cfg( any( target_os = "solaris" , target_os = "illumos" ) ) ]
172
+ __sin6_src_id : 0 ,
173
+ } ;
174
+ let mut storage = MaybeUninit :: < sockaddr_storage > :: zeroed ( ) ;
175
+ // Safety: A `sockaddr_in6` is memory compatible with a `sockaddr_storage`
176
+ unsafe { ( storage. as_mut_ptr ( ) as * mut sockaddr_in6 ) . write ( sockaddr_in6) } ;
177
+ SockAddr {
178
+ storage : unsafe { storage. assume_init ( ) } ,
179
+ len : mem:: size_of :: < sockaddr_in6 > ( ) as socklen_t ,
113
180
}
114
181
}
115
182
}
0 commit comments