@@ -11,7 +11,6 @@ use sys::time::TimeVal;
11
11
use sys:: uio:: IoVec ;
12
12
13
13
mod addr;
14
- mod ffi;
15
14
pub mod sockopt;
16
15
17
16
/*
@@ -33,6 +32,8 @@ pub use self::addr::{
33
32
pub use :: sys:: socket:: addr:: netlink:: NetlinkAddr ;
34
33
35
34
pub use libc:: {
35
+ cmsghdr,
36
+ msghdr,
36
37
sa_family_t,
37
38
sockaddr,
38
39
sockaddr_in,
@@ -295,19 +296,30 @@ unsafe fn copy_bytes<'a, 'b, T: ?Sized>(src: &T, dst: &'a mut &'b mut [u8]) {
295
296
mem:: swap ( dst, & mut remainder) ;
296
297
}
297
298
299
+ // Darwin and DragonFly BSD always aligns struct cmsghdr as if it were a 32-bit OS
300
+ #[ cfg( any( target_os = "dragonfly" , target_os = "ios" , target_os = "macos" ) ) ]
301
+ type align_of_cmsg_data = u32 ;
298
302
299
- use self :: ffi:: { cmsghdr, msghdr, type_of_cmsg_data, type_of_msg_iovlen, type_of_cmsg_len} ;
303
+ #[ cfg( not( target_os = "macos" ) ) ]
304
+ type align_of_cmsg_data = size_t ;
300
305
301
306
/// A structure used to make room in a cmsghdr passed to recvmsg. The
302
307
/// size and alignment match that of a cmsghdr followed by a T, but the
303
308
/// fields are not accessible, as the actual types will change on a call
304
309
/// to recvmsg.
305
310
///
306
311
/// To make room for multiple messages, nest the type parameter with
307
- /// tuples, e.g.
308
- /// `let cmsg: CmsgSpace<([RawFd; 3], CmsgSpace<[RawFd; 2]>)> = CmsgSpace::new();`
312
+ /// tuples:
313
+ ///
314
+ /// ```
315
+ /// use std::os::unix::io::RawFd;
316
+ /// use nix::sys::socket::CmsgSpace;
317
+ /// let cmsg: CmsgSpace<([RawFd; 3], CmsgSpace<[RawFd; 2]>)> = CmsgSpace::new();
318
+ /// ```
319
+ #[ repr( C ) ]
309
320
pub struct CmsgSpace < T > {
310
321
_hdr : cmsghdr ,
322
+ _pad : [ align_of_cmsg_data ; 0 ] ,
311
323
_data : T ,
312
324
}
313
325
@@ -377,24 +389,25 @@ impl<'a> Iterator for CmsgIterator<'a> {
377
389
if aligned_cmsg_len > self . buf . len ( ) {
378
390
return None ;
379
391
}
392
+ let cmsg_data = & self . buf [ cmsg_align ( sizeof_cmsghdr) ..cmsg_len] ;
380
393
self . buf = & self . buf [ aligned_cmsg_len..] ;
381
394
self . next += 1 ;
382
395
383
396
match ( cmsg. cmsg_level , cmsg. cmsg_type ) {
384
397
( libc:: SOL_SOCKET , libc:: SCM_RIGHTS ) => unsafe {
385
398
Some ( ControlMessage :: ScmRights (
386
- slice:: from_raw_parts (
387
- & cmsg . cmsg_data as * const _ as * const _ , 1 ) ) )
399
+ slice:: from_raw_parts ( cmsg_data . as_ptr ( ) as * const _ ,
400
+ cmsg_data . len ( ) / mem :: size_of :: < RawFd > ( ) ) ) )
388
401
} ,
389
402
( libc:: SOL_SOCKET , libc:: SCM_TIMESTAMP ) => unsafe {
390
403
Some ( ControlMessage :: ScmTimestamp (
391
- & * ( & cmsg . cmsg_data as * const _ as * const _ ) ) )
404
+ & * ( cmsg_data. as_ptr ( ) as * const _ ) ) )
392
405
} ,
393
406
( _, _) => unsafe {
394
407
Some ( ControlMessage :: Unknown ( UnknownCmsg (
395
408
& cmsg,
396
409
slice:: from_raw_parts (
397
- & cmsg . cmsg_data as * const _ as * const _ ,
410
+ cmsg_data. as_ptr ( ) as * const _ ,
398
411
len) ) ) )
399
412
}
400
413
}
@@ -487,8 +500,13 @@ pub enum ControlMessage<'a> {
487
500
#[ doc( hidden) ]
488
501
pub struct UnknownCmsg < ' a > ( & ' a cmsghdr , & ' a [ u8 ] ) ;
489
502
503
+ // Round `len` up to meet the platform's required alignment for
504
+ // `cmsghdr`s and trailing `cmsghdr` data. This should match the
505
+ // behaviour of CMSG_ALIGN from the Linux headers and do the correct
506
+ // thing on other platforms that don't usually provide CMSG_ALIGN.
507
+ #[ inline]
490
508
fn cmsg_align ( len : usize ) -> usize {
491
- let align_bytes = mem:: size_of :: < type_of_cmsg_data > ( ) - 1 ;
509
+ let align_bytes = mem:: size_of :: < align_of_cmsg_data > ( ) - 1 ;
492
510
( len + align_bytes) & !align_bytes
493
511
}
494
512
@@ -513,17 +531,16 @@ impl<'a> ControlMessage<'a> {
513
531
}
514
532
}
515
533
516
- // Unsafe: start and end of buffer must be size_t-aligned (that is,
517
- // cmsg_align'd). Updates the provided slice; panics if the buffer
518
- // is too small.
534
+ // Unsafe: start and end of buffer must be cmsg_align'd. Updates
535
+ // the provided slice; panics if the buffer is too small.
519
536
unsafe fn encode_into < ' b > ( & self , buf : & mut & ' b mut [ u8 ] ) {
520
537
match * self {
521
538
ControlMessage :: ScmRights ( fds) => {
522
539
let cmsg = cmsghdr {
523
- cmsg_len : self . len ( ) as type_of_cmsg_len ,
524
- cmsg_level : libc:: SOL_SOCKET ,
525
- cmsg_type : libc:: SCM_RIGHTS ,
526
- cmsg_data : [ ] ,
540
+ cmsg_len : self . len ( ) as _ ,
541
+ cmsg_level : libc:: SOL_SOCKET ,
542
+ cmsg_type : libc:: SCM_RIGHTS ,
543
+ ..mem :: uninitialized ( )
527
544
} ;
528
545
copy_bytes ( & cmsg, buf) ;
529
546
@@ -539,10 +556,10 @@ impl<'a> ControlMessage<'a> {
539
556
} ,
540
557
ControlMessage :: ScmTimestamp ( t) => {
541
558
let cmsg = cmsghdr {
542
- cmsg_len : self . len ( ) as type_of_cmsg_len ,
559
+ cmsg_len : self . len ( ) as _ ,
543
560
cmsg_level : libc:: SOL_SOCKET ,
544
561
cmsg_type : libc:: SCM_TIMESTAMP ,
545
- cmsg_data : [ ] ,
562
+ ..mem :: uninitialized ( )
546
563
} ;
547
564
copy_bytes ( & cmsg, buf) ;
548
565
@@ -603,15 +620,16 @@ pub fn sendmsg<'a>(fd: RawFd, iov: &[IoVec<&'a [u8]>], cmsgs: &[ControlMessage<'
603
620
} ;
604
621
605
622
let mhdr = msghdr {
606
- msg_name : name as * const c_void ,
623
+ msg_name : name as * mut _ ,
607
624
msg_namelen : namelen,
608
- msg_iov : iov. as_ptr ( ) ,
609
- msg_iovlen : iov. len ( ) as type_of_msg_iovlen ,
610
- msg_control : cmsg_ptr,
611
- msg_controllen : capacity as type_of_cmsg_len ,
625
+ msg_iov : iov. as_ptr ( ) as * mut _ ,
626
+ msg_iovlen : iov. len ( ) as _ ,
627
+ msg_control : cmsg_ptr as * mut _ ,
628
+ msg_controllen : capacity as _ ,
612
629
msg_flags : 0 ,
630
+ ..unsafe { mem:: uninitialized ( ) }
613
631
} ;
614
- let ret = unsafe { ffi :: sendmsg ( fd, & mhdr, flags. bits ( ) ) } ;
632
+ let ret = unsafe { libc :: sendmsg ( fd, & mhdr, flags. bits ( ) ) } ;
615
633
616
634
Errno :: result ( ret) . map ( |r| r as usize )
617
635
}
@@ -626,15 +644,16 @@ pub fn recvmsg<'a, T>(fd: RawFd, iov: &[IoVec<&mut [u8]>], cmsg_buffer: Option<&
626
644
None => ( 0 as * mut _ , 0 ) ,
627
645
} ;
628
646
let mut mhdr = msghdr {
629
- msg_name : & mut address as * const _ as * const c_void ,
647
+ msg_name : & mut address as * mut _ as * mut _ ,
630
648
msg_namelen : mem:: size_of :: < sockaddr_storage > ( ) as socklen_t ,
631
- msg_iov : iov. as_ptr ( ) as * const IoVec < & [ u8 ] > , // safe cast to add const-ness
632
- msg_iovlen : iov. len ( ) as type_of_msg_iovlen ,
633
- msg_control : msg_control as * const c_void ,
634
- msg_controllen : msg_controllen as type_of_cmsg_len ,
649
+ msg_iov : iov. as_ptr ( ) as * mut _ ,
650
+ msg_iovlen : iov. len ( ) as _ ,
651
+ msg_control : msg_control as * mut _ ,
652
+ msg_controllen : msg_controllen as _ ,
635
653
msg_flags : 0 ,
654
+ ..unsafe { mem:: uninitialized ( ) }
636
655
} ;
637
- let ret = unsafe { ffi :: recvmsg ( fd, & mut mhdr, flags. bits ( ) ) } ;
656
+ let ret = unsafe { libc :: recvmsg ( fd, & mut mhdr, flags. bits ( ) ) } ;
638
657
639
658
Ok ( unsafe { RecvMsg {
640
659
bytes : try!( Errno :: result ( ret) ) as usize ,
@@ -851,7 +870,7 @@ pub fn connect(fd: RawFd, addr: &SockAddr) -> Result<()> {
851
870
/// [Further reading](http://pubs.opengroup.org/onlinepubs/9699919799/functions/recv.html)
852
871
pub fn recv ( sockfd : RawFd , buf : & mut [ u8 ] , flags : MsgFlags ) -> Result < usize > {
853
872
unsafe {
854
- let ret = ffi :: recv (
873
+ let ret = libc :: recv (
855
874
sockfd,
856
875
buf. as_ptr ( ) as * mut c_void ,
857
876
buf. len ( ) as size_t ,
@@ -870,7 +889,7 @@ pub fn recvfrom(sockfd: RawFd, buf: &mut [u8]) -> Result<(usize, SockAddr)> {
870
889
let addr: sockaddr_storage = mem:: zeroed ( ) ;
871
890
let mut len = mem:: size_of :: < sockaddr_storage > ( ) as socklen_t ;
872
891
873
- let ret = try!( Errno :: result ( ffi :: recvfrom (
892
+ let ret = try!( Errno :: result ( libc :: recvfrom (
874
893
sockfd,
875
894
buf. as_ptr ( ) as * mut c_void ,
876
895
buf. len ( ) as size_t ,
0 commit comments