99
1010//! Interface for the Linux socket-based MCTP support.
1111//!
12- //! This crate provides some minimal wrappers around standard [`libc`] socket
12+ //! This crate provides some minimal wrappers around standard socket
1313//! operations, using MCTP-specific addressing structures.
1414//!
1515//! [`MctpSocket`] provides support for blocking socket operations
4242use async_io:: Async ;
4343use core:: mem;
4444use std:: fmt;
45- use std:: io:: Error ;
46- use std:: os:: unix:: io:: { AsFd , AsRawFd , BorrowedFd , FromRawFd , OwnedFd , RawFd } ;
45+ use std:: io:: { Error , ErrorKind , IoSlice } ;
46+ use std:: os:: unix:: io:: { AsFd , BorrowedFd , OwnedFd , RawFd } ;
4747use std:: time:: Duration ;
4848
4949use mctp:: {
5050 Eid , MsgIC , MsgType , Result , Tag , TagValue , MCTP_ADDR_ANY , MCTP_TAG_OWNER ,
5151} ;
5252
53- /* until we have these in libc... */
54- const AF_MCTP : libc:: sa_family_t = 45 ;
53+ use rustix:: net:: AddressFamily ;
54+
55+ const AF_MCTP : AddressFamily = AddressFamily :: from_raw ( 45 ) ;
5556#[ repr( C ) ]
5657#[ allow( non_camel_case_types) ]
58+ #[ derive( Clone , Debug , Hash ) ]
5759struct sockaddr_mctp {
58- smctp_family : libc :: sa_family_t ,
60+ smctp_family : rustix :: net :: RawAddressFamily ,
5961 __smctp_pad0 : u16 ,
6062 smctp_network : u32 ,
6163 smctp_addr : u8 ,
@@ -75,7 +77,7 @@ impl MctpSockAddr {
7577 /// and tag value.
7678 pub fn new ( eid : u8 , net : u32 , typ : u8 , tag : u8 ) -> Self {
7779 MctpSockAddr ( sockaddr_mctp {
78- smctp_family : AF_MCTP ,
80+ smctp_family : AF_MCTP . as_raw ( ) ,
7981 __smctp_pad0 : 0 ,
8082 smctp_network : net,
8183 smctp_addr : eid,
@@ -84,23 +86,40 @@ impl MctpSockAddr {
8486 __smctp_pad1 : 0 ,
8587 } )
8688 }
89+ }
8790
88- fn zero ( ) -> Self {
89- Self :: new ( 0 , MCTP_NET_ANY , 0 , 0 )
90- }
91-
92- fn as_raw ( & self ) -> ( * const libc:: sockaddr , libc:: socklen_t ) {
93- (
94- & self . 0 as * const sockaddr_mctp as * const libc:: sockaddr ,
95- mem:: size_of :: < sockaddr_mctp > ( ) as libc:: socklen_t ,
91+ unsafe impl rustix:: net:: addr:: SocketAddrArg for MctpSockAddr {
92+ unsafe fn with_sockaddr < R > (
93+ & self ,
94+ f : impl FnOnce (
95+ * const rustix:: net:: addr:: SocketAddrOpaque ,
96+ rustix:: net:: addr:: SocketAddrLen ,
97+ ) -> R ,
98+ ) -> R {
99+ f (
100+ & self . 0 as * const sockaddr_mctp
101+ as * const rustix:: net:: addr:: SocketAddrOpaque ,
102+ mem:: size_of :: < sockaddr_mctp > ( ) as _ ,
96103 )
97104 }
105+ }
98106
99- fn as_raw_mut ( & mut self ) -> ( * mut libc:: sockaddr , libc:: socklen_t ) {
100- (
101- & mut self . 0 as * mut sockaddr_mctp as * mut libc:: sockaddr ,
102- mem:: size_of :: < sockaddr_mctp > ( ) as libc:: socklen_t ,
103- )
107+ impl TryFrom < rustix:: net:: SocketAddrAny > for MctpSockAddr {
108+ type Error = ( ) ;
109+ fn try_from (
110+ sock : rustix:: net:: SocketAddrAny ,
111+ ) -> core:: result:: Result < Self , Self :: Error > {
112+ if sock. address_family ( ) != AF_MCTP {
113+ return Err ( ( ) ) ;
114+ }
115+
116+ if sock. addr_len ( ) as usize != mem:: size_of :: < sockaddr_mctp > ( ) {
117+ return Err ( ( ) ) ;
118+ }
119+
120+ Ok ( Self (
121+ unsafe { & * ( sock. as_ptr ( ) as * const sockaddr_mctp ) } . clone ( ) ,
122+ ) )
104123 }
105124}
106125
@@ -134,31 +153,22 @@ fn tag_to_smctp(tag: &Tag) -> u8 {
134153 tag. tag ( ) . 0 | to_bit
135154}
136155
137- // helper for IO error construction
138- fn last_os_error ( ) -> mctp:: Error {
139- mctp:: Error :: Io ( Error :: last_os_error ( ) )
140- }
141-
142156/// MCTP socket object.
143157pub struct MctpSocket ( OwnedFd ) ;
144158
145159impl MctpSocket {
146160 /// Create a new MCTP socket. This can then be used for send/receive
147161 /// operations.
148162 pub fn new ( ) -> Result < Self > {
149- let rc = unsafe {
150- libc:: socket (
151- AF_MCTP . into ( ) ,
152- libc:: SOCK_DGRAM | libc:: SOCK_CLOEXEC ,
153- 0 ,
154- )
155- } ;
156- if rc < 0 {
157- return Err ( last_os_error ( ) ) ;
163+ match rustix:: net:: socket_with (
164+ AF_MCTP ,
165+ rustix:: net:: SocketType :: DGRAM ,
166+ rustix:: net:: SocketFlags :: CLOEXEC ,
167+ None ,
168+ ) {
169+ Ok ( fd) => Ok ( MctpSocket ( fd) ) ,
170+ Err ( e) => Err ( mctp:: Error :: Io ( e. into ( ) ) ) ,
158171 }
159- // safety: the fd is valid, and we have exclusive ownership
160- let fd = unsafe { OwnedFd :: from_raw_fd ( rc) } ;
161- Ok ( MctpSocket ( fd) )
162172 }
163173
164174 // Inner recvfrom, returning an io::Error on failure. This can be
@@ -168,34 +178,29 @@ impl MctpSocket {
168178 & self ,
169179 buf : & mut [ u8 ] ,
170180 ) -> std:: io:: Result < ( usize , MctpSockAddr ) > {
171- let mut addr = MctpSockAddr :: zero ( ) ;
172- let ( addr_ptr, mut addr_len) = addr. as_raw_mut ( ) ;
173- let buf_ptr = buf. as_mut_ptr ( ) as * mut libc:: c_void ;
174- let buf_len = buf. len ( ) as libc:: size_t ;
175- let fd = self . as_raw_fd ( ) ;
176-
177- let rc = unsafe {
178- libc:: recvfrom (
179- fd,
180- buf_ptr,
181- buf_len,
182- libc:: MSG_TRUNC ,
183- addr_ptr,
184- & mut addr_len,
185- )
186- } ;
187-
188- if rc < 0 {
189- Err ( Error :: last_os_error ( ) )
190- } else {
191- Ok ( ( rc as usize , addr) )
181+ match rustix:: net:: recvfrom (
182+ self . as_fd ( ) ,
183+ buf,
184+ rustix:: net:: RecvFlags :: TRUNC ,
185+ ) {
186+ Ok ( ( _out, len, addr) ) => {
187+ // OK unwrap, recv returns an address
188+ let addr = addr. unwrap ( ) ;
189+ // Shouldn't fail unless the kernel returns a bad address
190+ let addr = addr
191+ . try_into ( )
192+ . map_err ( |_| Error :: from ( ErrorKind :: Other ) ) ?;
193+ // OK unwrap, address.try_into().unwrap();
194+ Ok ( ( len, addr) )
195+ }
196+ Err ( e) => Err ( e. into ( ) ) ,
192197 }
193198 }
194199
195200 /// Blocking receive from a socket, into `buf`, returning a length
196201 /// and source address
197202 ///
198- /// Essentially a wrapper around [libc:: recvfrom] , using MCTP-specific
203+ /// Essentially a wrapper around ` recvfrom` , using MCTP-specific
199204 /// addressing.
200205 pub fn recvfrom ( & self , buf : & mut [ u8 ] ) -> Result < ( usize , MctpSockAddr ) > {
201206 let ( len, addr) = self . io_recvfrom ( buf) . map_err ( mctp:: Error :: Io ) ?;
@@ -210,44 +215,29 @@ impl MctpSocket {
210215 bufs : & [ & [ u8 ] ] ,
211216 addr : & MctpSockAddr ,
212217 ) -> std:: io:: Result < usize > {
213- let mut iov: Vec < libc:: iovec > = bufs
214- . iter ( )
215- . map ( |b| libc:: iovec {
216- iov_base : b. as_ptr ( ) as * mut libc:: c_void ,
217- iov_len : b. len ( ) as libc:: size_t ,
218- } )
219- . collect ( ) ;
220-
221- let ( addr_ptr, addr_len) = addr. as_raw ( ) ;
222-
223- let mut msg: libc:: msghdr = unsafe { mem:: zeroed ( ) } ;
224- msg. msg_name = addr_ptr as * mut libc:: c_void ;
225- msg. msg_namelen = addr_len;
226- msg. msg_iov = iov. as_mut_ptr ( ) ;
227- msg. msg_iovlen = iov. len ( ) as _ ;
228-
229- let fd = self . as_raw_fd ( ) ;
230- let rc = unsafe { libc:: sendmsg ( fd, & msg, 0 ) } ;
231-
232- if rc < 0 {
233- Err ( Error :: last_os_error ( ) )
234- } else {
235- Ok ( rc as usize )
236- }
218+ let iov: Vec < IoSlice > = bufs. iter ( ) . map ( |b| IoSlice :: new ( b) ) . collect ( ) ;
219+
220+ Ok ( rustix:: net:: sendmsg_addr (
221+ self . as_fd ( ) ,
222+ addr,
223+ & iov,
224+ & mut rustix:: net:: SendAncillaryBuffer :: default ( ) ,
225+ rustix:: net:: SendFlags :: empty ( ) ,
226+ ) ?)
237227 }
238228
239229 /// Blocking send to a socket, given a buffer and address, returning
240230 /// the number of bytes sent.
241231 ///
242- /// Essentially a wrapper around [libc:: sendto] .
232+ /// Essentially a wrapper around ` sendto` .
243233 pub fn sendto ( & self , buf : & [ u8 ] , addr : & MctpSockAddr ) -> Result < usize > {
244234 self . sendmsg ( & [ buf] , addr)
245235 }
246236
247237 /// Blocking send to a socket, given a slice of buffers and address, returning
248238 /// the number of bytes sent.
249239 ///
250- /// Essentially a wrapper around [libc:: sendmsg] .
240+ /// Essentially a wrapper around ` sendmsg` .
251241 pub fn sendmsg (
252242 & self ,
253243 bufs : & [ & [ u8 ] ] ,
@@ -258,89 +248,31 @@ impl MctpSocket {
258248
259249 /// Bind the socket to a local address.
260250 pub fn bind ( & self , addr : & MctpSockAddr ) -> Result < ( ) > {
261- let ( addr_ptr, addr_len) = addr. as_raw ( ) ;
262- let fd = self . as_raw_fd ( ) ;
263-
264- let rc = unsafe { libc:: bind ( fd, addr_ptr, addr_len) } ;
265-
266- if rc < 0 {
267- Err ( last_os_error ( ) )
268- } else {
269- Ok ( ( ) )
270- }
251+ rustix:: net:: bind ( self . as_fd ( ) , addr)
252+ . map_err ( |e| mctp:: Error :: Io ( e. into ( ) ) )
271253 }
272254
273255 /// Set the read timeout.
274256 ///
275257 /// A valid of `None` will have no timeout.
276258 pub fn set_read_timeout ( & self , dur : Option < Duration > ) -> Result < ( ) > {
277- // Avoid warnings about using time_t with musl. See comment in read_timeout().
278- #![ allow( deprecated) ]
279-
280- let dur = dur. unwrap_or ( Duration :: ZERO ) ;
281- let tv = libc:: timeval {
282- tv_sec : dur. as_secs ( ) as libc:: time_t ,
283- tv_usec : dur. subsec_micros ( ) as libc:: suseconds_t ,
284- } ;
285- let fd = self . as_raw_fd ( ) ;
286- let rc = unsafe {
287- libc:: setsockopt (
288- fd,
289- libc:: SOL_SOCKET ,
290- libc:: SO_RCVTIMEO ,
291- ( & tv as * const libc:: timeval ) as * const libc:: c_void ,
292- std:: mem:: size_of :: < libc:: timeval > ( ) as libc:: socklen_t ,
293- )
294- } ;
295-
296- if rc < 0 {
297- Err ( last_os_error ( ) )
298- } else {
299- Ok ( ( ) )
300- }
259+ rustix:: net:: sockopt:: set_socket_timeout (
260+ self . as_fd ( ) ,
261+ rustix:: net:: sockopt:: Timeout :: Recv ,
262+ dur,
263+ )
264+ . map_err ( |e| mctp:: Error :: Io ( e. into ( ) ) )
301265 }
302266
303267 /// Retrieves the read timeout
304268 ///
305269 /// A value of `None` indicates no timeout.
306270 pub fn read_timeout ( & self ) -> Result < Option < Duration > > {
307- // Avoid warnings about using time_t with musl. It is safe here since we are
308- // only using it directly with libc, that should be compiled with the
309- // same definitions as libc crate. https://github.com/rust-lang/libc/issues/1848
310- #![ allow( deprecated) ]
311-
312- let mut tv = std:: mem:: MaybeUninit :: < libc:: timeval > :: uninit ( ) ;
313- let mut tv_len =
314- std:: mem:: size_of :: < libc:: timeval > ( ) as libc:: socklen_t ;
315- let fd = self . as_raw_fd ( ) ;
316- let rc = unsafe {
317- libc:: getsockopt (
318- fd,
319- libc:: SOL_SOCKET ,
320- libc:: SO_RCVTIMEO ,
321- tv. as_mut_ptr ( ) as * mut libc:: c_void ,
322- & mut tv_len as * mut libc:: socklen_t ,
323- )
324- } ;
325-
326- if rc < 0 {
327- Err ( last_os_error ( ) )
328- } else {
329- let tv = unsafe { tv. assume_init ( ) } ;
330- if tv. tv_sec < 0 || tv. tv_usec < 0 {
331- // Negative timeout from socket
332- return Err ( mctp:: Error :: Other ) ;
333- }
334-
335- if tv. tv_sec == 0 && tv. tv_usec == 0 {
336- Ok ( None )
337- } else {
338- Ok ( Some (
339- Duration :: from_secs ( tv. tv_sec as u64 )
340- + Duration :: from_micros ( tv. tv_usec as u64 ) ,
341- ) )
342- }
343- }
271+ rustix:: net:: sockopt:: socket_timeout (
272+ self . as_fd ( ) ,
273+ rustix:: net:: sockopt:: Timeout :: Recv ,
274+ )
275+ . map_err ( |e| mctp:: Error :: Io ( e. into ( ) ) )
344276 }
345277}
346278
0 commit comments