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