• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #[cfg(any(target_os = "linux", target_os = "android"))]
2 use crate::*;
3 use libc::{c_char, sockaddr_storage};
4 #[allow(deprecated)]
5 use nix::sys::socket::InetAddr;
6 use nix::sys::socket::{
7     getsockname, sockaddr, sockaddr_in6, AddressFamily, UnixAddr,
8 };
9 use std::collections::hash_map::DefaultHasher;
10 use std::hash::{Hash, Hasher};
11 use std::mem::{self, MaybeUninit};
12 use std::net::{self, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6};
13 use std::os::unix::io::RawFd;
14 use std::path::Path;
15 use std::slice;
16 use std::str::FromStr;
17 
18 #[allow(deprecated)]
19 #[test]
test_inetv4_addr_to_sock_addr()20 pub fn test_inetv4_addr_to_sock_addr() {
21     let actual: net::SocketAddr = FromStr::from_str("127.0.0.1:3000").unwrap();
22     let addr = InetAddr::from_std(&actual);
23 
24     match addr {
25         InetAddr::V4(addr) => {
26             let ip: u32 = 0x7f00_0001;
27             let port: u16 = 3000;
28             let saddr = addr.sin_addr.s_addr;
29 
30             assert_eq!(saddr, ip.to_be());
31             assert_eq!(addr.sin_port, port.to_be());
32         }
33         _ => panic!("nope"),
34     }
35 
36     assert_eq!(addr.to_string(), "127.0.0.1:3000");
37 
38     let inet = addr.to_std();
39     assert_eq!(actual, inet);
40 }
41 
42 #[allow(deprecated)]
43 #[test]
test_inetv4_addr_roundtrip_sockaddr_storage_to_addr()44 pub fn test_inetv4_addr_roundtrip_sockaddr_storage_to_addr() {
45     use nix::sys::socket::{sockaddr_storage_to_addr, SockAddr};
46 
47     let actual: net::SocketAddr = FromStr::from_str("127.0.0.1:3000").unwrap();
48     let addr = InetAddr::from_std(&actual);
49     let sockaddr = SockAddr::new_inet(addr);
50 
51     let (storage, ffi_size) = {
52         let mut storage = MaybeUninit::<sockaddr_storage>::zeroed();
53         let storage_ptr = storage.as_mut_ptr().cast::<sockaddr>();
54         let (ffi_ptr, ffi_size) = sockaddr.as_ffi_pair();
55         assert_eq!(mem::size_of::<sockaddr>(), ffi_size as usize);
56         unsafe {
57             storage_ptr.copy_from_nonoverlapping(ffi_ptr as *const sockaddr, 1);
58             (storage.assume_init(), ffi_size)
59         }
60     };
61 
62     let from_storage =
63         sockaddr_storage_to_addr(&storage, ffi_size as usize).unwrap();
64     assert_eq!(from_storage, sockaddr);
65     let from_storage =
66         sockaddr_storage_to_addr(&storage, mem::size_of::<sockaddr_storage>())
67             .unwrap();
68     assert_eq!(from_storage, sockaddr);
69 }
70 
71 #[cfg(any(target_os = "linux"))]
72 #[cfg_attr(qemu, ignore)]
73 #[test]
test_timestamping()74 pub fn test_timestamping() {
75     use nix::sys::socket::{
76         recvmsg, sendmsg, setsockopt, socket, sockopt::Timestamping,
77         ControlMessageOwned, MsgFlags, SockFlag, SockType, SockaddrIn,
78         TimestampingFlag,
79     };
80     use std::io::{IoSlice, IoSliceMut};
81 
82     let sock_addr = SockaddrIn::from_str("127.0.0.1:6790").unwrap();
83 
84     let ssock = socket(
85         AddressFamily::Inet,
86         SockType::Datagram,
87         SockFlag::empty(),
88         None,
89     )
90     .expect("send socket failed");
91 
92     let rsock = socket(
93         AddressFamily::Inet,
94         SockType::Datagram,
95         SockFlag::empty(),
96         None,
97     )
98     .unwrap();
99     nix::sys::socket::bind(rsock, &sock_addr).unwrap();
100 
101     setsockopt(rsock, Timestamping, &TimestampingFlag::all()).unwrap();
102 
103     let sbuf = [0u8; 2048];
104     let mut rbuf = [0u8; 2048];
105     let flags = MsgFlags::empty();
106     let iov1 = [IoSlice::new(&sbuf)];
107     let mut iov2 = [IoSliceMut::new(&mut rbuf)];
108 
109     let mut cmsg = cmsg_space!(nix::sys::socket::Timestamps);
110     sendmsg(ssock, &iov1, &[], flags, Some(&sock_addr)).unwrap();
111     let recv = recvmsg::<()>(rsock, &mut iov2, Some(&mut cmsg), flags).unwrap();
112 
113     let mut ts = None;
114     for c in recv.cmsgs() {
115         if let ControlMessageOwned::ScmTimestampsns(timestamps) = c {
116             ts = Some(timestamps.system);
117         }
118     }
119     let ts = ts.expect("ScmTimestampns is present");
120     let sys_time =
121         ::nix::time::clock_gettime(::nix::time::ClockId::CLOCK_REALTIME)
122             .unwrap();
123     let diff = if ts > sys_time {
124         ts - sys_time
125     } else {
126         sys_time - ts
127     };
128     assert!(std::time::Duration::from(diff).as_secs() < 60);
129 }
130 
131 #[allow(deprecated)]
132 #[test]
test_inetv6_addr_roundtrip_sockaddr_storage_to_addr()133 pub fn test_inetv6_addr_roundtrip_sockaddr_storage_to_addr() {
134     use nix::sys::socket::{sockaddr_storage_to_addr, SockAddr};
135 
136     let port: u16 = 3000;
137     let flowinfo: u32 = 1;
138     let scope_id: u32 = 2;
139     let ip: Ipv6Addr = "fe80::1".parse().unwrap();
140 
141     let actual =
142         SocketAddr::V6(SocketAddrV6::new(ip, port, flowinfo, scope_id));
143     let addr = InetAddr::from_std(&actual);
144     let sockaddr = SockAddr::new_inet(addr);
145 
146     let (storage, ffi_size) = {
147         let mut storage = MaybeUninit::<sockaddr_storage>::zeroed();
148         let storage_ptr = storage.as_mut_ptr().cast::<sockaddr_in6>();
149         let (ffi_ptr, ffi_size) = sockaddr.as_ffi_pair();
150         assert_eq!(mem::size_of::<sockaddr_in6>(), ffi_size as usize);
151         unsafe {
152             storage_ptr.copy_from_nonoverlapping(
153                 (ffi_ptr as *const sockaddr).cast::<sockaddr_in6>(),
154                 1,
155             );
156             (storage.assume_init(), ffi_size)
157         }
158     };
159 
160     let from_storage =
161         sockaddr_storage_to_addr(&storage, ffi_size as usize).unwrap();
162     assert_eq!(from_storage, sockaddr);
163     let from_storage =
164         sockaddr_storage_to_addr(&storage, mem::size_of::<sockaddr_storage>())
165             .unwrap();
166     assert_eq!(from_storage, sockaddr);
167 }
168 
169 #[test]
test_path_to_sock_addr()170 pub fn test_path_to_sock_addr() {
171     let path = "/foo/bar";
172     let actual = Path::new(path);
173     let addr = UnixAddr::new(actual).unwrap();
174 
175     let expect: &[c_char] = unsafe {
176         slice::from_raw_parts(path.as_ptr() as *const c_char, path.len())
177     };
178     assert_eq!(unsafe { &(*addr.as_ptr()).sun_path[..8] }, expect);
179 
180     assert_eq!(addr.path(), Some(actual));
181 }
182 
calculate_hash<T: Hash>(t: &T) -> u64183 fn calculate_hash<T: Hash>(t: &T) -> u64 {
184     let mut s = DefaultHasher::new();
185     t.hash(&mut s);
186     s.finish()
187 }
188 
189 #[test]
test_addr_equality_path()190 pub fn test_addr_equality_path() {
191     let path = "/foo/bar";
192     let actual = Path::new(path);
193     let addr1 = UnixAddr::new(actual).unwrap();
194     let mut addr2 = addr1;
195 
196     unsafe { (*addr2.as_mut_ptr()).sun_path[10] = 127 };
197 
198     assert_eq!(addr1, addr2);
199     assert_eq!(calculate_hash(&addr1), calculate_hash(&addr2));
200 }
201 
202 #[cfg(any(target_os = "android", target_os = "linux"))]
203 #[test]
test_abstract_sun_path_too_long()204 pub fn test_abstract_sun_path_too_long() {
205     let name = String::from("nix\0abstract\0tesnix\0abstract\0tesnix\0abstract\0tesnix\0abstract\0tesnix\0abstract\0testttttnix\0abstract\0test\0make\0sure\0this\0is\0long\0enough");
206     let addr = UnixAddr::new_abstract(name.as_bytes());
207     addr.expect_err("assertion failed");
208 }
209 
210 #[cfg(any(target_os = "android", target_os = "linux"))]
211 #[test]
test_addr_equality_abstract()212 pub fn test_addr_equality_abstract() {
213     let name = String::from("nix\0abstract\0test");
214     let addr1 = UnixAddr::new_abstract(name.as_bytes()).unwrap();
215     let mut addr2 = addr1;
216 
217     assert_eq!(addr1, addr2);
218     assert_eq!(calculate_hash(&addr1), calculate_hash(&addr2));
219 
220     unsafe { (*addr2.as_mut_ptr()).sun_path[17] = 127 };
221     assert_ne!(addr1, addr2);
222     assert_ne!(calculate_hash(&addr1), calculate_hash(&addr2));
223 }
224 
225 // Test getting/setting abstract addresses (without unix socket creation)
226 #[cfg(any(target_os = "android", target_os = "linux"))]
227 #[test]
test_abstract_uds_addr()228 pub fn test_abstract_uds_addr() {
229     let empty = String::new();
230     let addr = UnixAddr::new_abstract(empty.as_bytes()).unwrap();
231     let sun_path: [u8; 0] = [];
232     assert_eq!(addr.as_abstract(), Some(&sun_path[..]));
233 
234     let name = String::from("nix\0abstract\0test");
235     let addr = UnixAddr::new_abstract(name.as_bytes()).unwrap();
236     let sun_path = [
237         110u8, 105, 120, 0, 97, 98, 115, 116, 114, 97, 99, 116, 0, 116, 101,
238         115, 116,
239     ];
240     assert_eq!(addr.as_abstract(), Some(&sun_path[..]));
241     assert_eq!(addr.path(), None);
242 
243     // Internally, name is null-prefixed (abstract namespace)
244     assert_eq!(unsafe { (*addr.as_ptr()).sun_path[0] }, 0);
245 }
246 
247 // Test getting an unnamed address (without unix socket creation)
248 #[cfg(any(target_os = "android", target_os = "linux"))]
249 #[test]
test_unnamed_uds_addr()250 pub fn test_unnamed_uds_addr() {
251     use crate::nix::sys::socket::SockaddrLike;
252 
253     let addr = UnixAddr::new_unnamed();
254 
255     assert!(addr.is_unnamed());
256     assert_eq!(addr.len(), 2);
257     assert!(addr.path().is_none());
258     assert_eq!(addr.path_len(), 0);
259 
260     assert!(addr.as_abstract().is_none());
261 }
262 
263 #[test]
test_getsockname()264 pub fn test_getsockname() {
265     use nix::sys::socket::bind;
266     use nix::sys::socket::{socket, AddressFamily, SockFlag, SockType};
267 
268     let tempdir = tempfile::tempdir().unwrap();
269     let sockname = tempdir.path().join("sock");
270     let sock = socket(
271         AddressFamily::Unix,
272         SockType::Stream,
273         SockFlag::empty(),
274         None,
275     )
276     .expect("socket failed");
277     let sockaddr = UnixAddr::new(&sockname).unwrap();
278     bind(sock, &sockaddr).expect("bind failed");
279     assert_eq!(sockaddr, getsockname(sock).expect("getsockname failed"));
280 }
281 
282 #[test]
test_socketpair()283 pub fn test_socketpair() {
284     use nix::sys::socket::{socketpair, AddressFamily, SockFlag, SockType};
285     use nix::unistd::{read, write};
286 
287     let (fd1, fd2) = socketpair(
288         AddressFamily::Unix,
289         SockType::Stream,
290         None,
291         SockFlag::empty(),
292     )
293     .unwrap();
294     write(fd1, b"hello").unwrap();
295     let mut buf = [0; 5];
296     read(fd2, &mut buf).unwrap();
297 
298     assert_eq!(&buf[..], b"hello");
299 }
300 
301 #[test]
test_std_conversions()302 pub fn test_std_conversions() {
303     use nix::sys::socket::*;
304 
305     let std_sa = SocketAddrV4::from_str("127.0.0.1:6789").unwrap();
306     let sock_addr = SockaddrIn::from(std_sa);
307     assert_eq!(std_sa, sock_addr.into());
308 
309     let std_sa = SocketAddrV6::from_str("[::1]:6000").unwrap();
310     let sock_addr: SockaddrIn6 = SockaddrIn6::from(std_sa);
311     assert_eq!(std_sa, sock_addr.into());
312 }
313 
314 mod recvfrom {
315     use super::*;
316     use nix::sys::socket::*;
317     use nix::{errno::Errno, Result};
318     use std::thread;
319 
320     const MSG: &[u8] = b"Hello, World!";
321 
sendrecv<Fs, Fr>( rsock: RawFd, ssock: RawFd, f_send: Fs, mut f_recv: Fr, ) -> Option<SockaddrStorage> where Fs: Fn(RawFd, &[u8], MsgFlags) -> Result<usize> + Send + 'static, Fr: FnMut(usize, Option<SockaddrStorage>),322     fn sendrecv<Fs, Fr>(
323         rsock: RawFd,
324         ssock: RawFd,
325         f_send: Fs,
326         mut f_recv: Fr,
327     ) -> Option<SockaddrStorage>
328     where
329         Fs: Fn(RawFd, &[u8], MsgFlags) -> Result<usize> + Send + 'static,
330         Fr: FnMut(usize, Option<SockaddrStorage>),
331     {
332         let mut buf: [u8; 13] = [0u8; 13];
333         let mut l = 0;
334         let mut from = None;
335 
336         let send_thread = thread::spawn(move || {
337             let mut l = 0;
338             while l < std::mem::size_of_val(MSG) {
339                 l += f_send(ssock, &MSG[l..], MsgFlags::empty()).unwrap();
340             }
341         });
342 
343         while l < std::mem::size_of_val(MSG) {
344             let (len, from_) = recvfrom(rsock, &mut buf[l..]).unwrap();
345             f_recv(len, from_);
346             from = from_;
347             l += len;
348         }
349         assert_eq!(&buf, MSG);
350         send_thread.join().unwrap();
351         from
352     }
353 
354     #[test]
stream()355     pub fn stream() {
356         let (fd2, fd1) = socketpair(
357             AddressFamily::Unix,
358             SockType::Stream,
359             None,
360             SockFlag::empty(),
361         )
362         .unwrap();
363         // Ignore from for stream sockets
364         let _ = sendrecv(fd1, fd2, send, |_, _| {});
365     }
366 
367     #[test]
udp()368     pub fn udp() {
369         let std_sa = SocketAddrV4::from_str("127.0.0.1:6789").unwrap();
370         let sock_addr = SockaddrIn::from(std_sa);
371         let rsock = socket(
372             AddressFamily::Inet,
373             SockType::Datagram,
374             SockFlag::empty(),
375             None,
376         )
377         .unwrap();
378         bind(rsock, &sock_addr).unwrap();
379         let ssock = socket(
380             AddressFamily::Inet,
381             SockType::Datagram,
382             SockFlag::empty(),
383             None,
384         )
385         .expect("send socket failed");
386         let from = sendrecv(
387             rsock,
388             ssock,
389             move |s, m, flags| sendto(s, m, &sock_addr, flags),
390             |_, _| {},
391         );
392         // UDP sockets should set the from address
393         assert_eq!(AddressFamily::Inet, from.unwrap().family().unwrap());
394     }
395 
396     #[cfg(target_os = "linux")]
397     mod udp_offload {
398         use super::*;
399         use nix::sys::socket::sockopt::{UdpGroSegment, UdpGsoSegment};
400         use std::io::IoSlice;
401 
402         #[test]
403         // Disable the test under emulation because it fails in Cirrus-CI.  Lack
404         // of QEMU support is suspected.
405         #[cfg_attr(qemu, ignore)]
gso()406         pub fn gso() {
407             require_kernel_version!(udp_offload::gso, ">= 4.18");
408 
409             // In this test, we send the data and provide a GSO segment size.
410             // Since we are sending the buffer of size 13, six UDP packets
411             // with size 2 and two UDP packet with size 1 will be sent.
412             let segment_size: u16 = 2;
413 
414             let sock_addr = SockaddrIn::new(127, 0, 0, 1, 6791);
415             let rsock = socket(
416                 AddressFamily::Inet,
417                 SockType::Datagram,
418                 SockFlag::empty(),
419                 None,
420             )
421             .unwrap();
422 
423             setsockopt(rsock, UdpGsoSegment, &(segment_size as _))
424                 .expect("setsockopt UDP_SEGMENT failed");
425 
426             bind(rsock, &sock_addr).unwrap();
427             let ssock = socket(
428                 AddressFamily::Inet,
429                 SockType::Datagram,
430                 SockFlag::empty(),
431                 None,
432             )
433             .expect("send socket failed");
434 
435             let mut num_packets_received: i32 = 0;
436 
437             sendrecv(
438                 rsock,
439                 ssock,
440                 move |s, m, flags| {
441                     let iov = [IoSlice::new(m)];
442                     let cmsg = ControlMessage::UdpGsoSegments(&segment_size);
443                     sendmsg(s, &iov, &[cmsg], flags, Some(&sock_addr))
444                 },
445                 {
446                     let num_packets_received_ref = &mut num_packets_received;
447 
448                     move |len, _| {
449                         // check that we receive UDP packets with payload size
450                         // less or equal to segment size
451                         assert!(len <= segment_size as usize);
452                         *num_packets_received_ref += 1;
453                     }
454                 },
455             );
456 
457             // Buffer size is 13, we will receive six packets of size 2,
458             // and one packet of size 1.
459             assert_eq!(7, num_packets_received);
460         }
461 
462         #[test]
463         // Disable the test on emulated platforms because it fails in Cirrus-CI.
464         // Lack of QEMU support is suspected.
465         #[cfg_attr(qemu, ignore)]
gro()466         pub fn gro() {
467             require_kernel_version!(udp_offload::gro, ">= 5.3");
468 
469             // It's hard to guarantee receiving GRO packets. Just checking
470             // that `setsockopt` doesn't fail with error
471 
472             let rsock = socket(
473                 AddressFamily::Inet,
474                 SockType::Datagram,
475                 SockFlag::empty(),
476                 None,
477             )
478             .unwrap();
479 
480             setsockopt(rsock, UdpGroSegment, &true)
481                 .expect("setsockopt UDP_GRO failed");
482         }
483     }
484 
485     #[cfg(any(
486         target_os = "linux",
487         target_os = "android",
488         target_os = "freebsd",
489         target_os = "netbsd",
490     ))]
491     #[test]
udp_sendmmsg()492     pub fn udp_sendmmsg() {
493         use std::io::IoSlice;
494 
495         let std_sa = SocketAddrV4::from_str("127.0.0.1:6793").unwrap();
496         let std_sa2 = SocketAddrV4::from_str("127.0.0.1:6794").unwrap();
497         let sock_addr = SockaddrIn::from(std_sa);
498         let sock_addr2 = SockaddrIn::from(std_sa2);
499 
500         let rsock = socket(
501             AddressFamily::Inet,
502             SockType::Datagram,
503             SockFlag::empty(),
504             None,
505         )
506         .unwrap();
507         bind(rsock, &sock_addr).unwrap();
508         let ssock = socket(
509             AddressFamily::Inet,
510             SockType::Datagram,
511             SockFlag::empty(),
512             None,
513         )
514         .expect("send socket failed");
515 
516         let from = sendrecv(
517             rsock,
518             ssock,
519             move |s, m, flags| {
520                 let batch_size = 15;
521                 let mut iovs = Vec::with_capacity(1 + batch_size);
522                 let mut addrs = Vec::with_capacity(1 + batch_size);
523                 let mut data = MultiHeaders::preallocate(1 + batch_size, None);
524                 let iov = IoSlice::new(m);
525                 // first chunk:
526                 iovs.push([iov]);
527                 addrs.push(Some(sock_addr));
528 
529                 for _ in 0..batch_size {
530                     iovs.push([iov]);
531                     addrs.push(Some(sock_addr2));
532                 }
533 
534                 let res = sendmmsg(s, &mut data, &iovs, addrs, [], flags)?;
535                 let mut sent_messages = 0;
536                 let mut sent_bytes = 0;
537                 for item in res {
538                     sent_messages += 1;
539                     sent_bytes += item.bytes;
540                 }
541                 //
542                 assert_eq!(sent_messages, iovs.len());
543                 assert_eq!(sent_bytes, sent_messages * m.len());
544                 Ok(sent_messages)
545             },
546             |_, _| {},
547         );
548         // UDP sockets should set the from address
549         assert_eq!(AddressFamily::Inet, from.unwrap().family().unwrap());
550     }
551 
552     #[cfg(any(
553         target_os = "linux",
554         target_os = "android",
555         target_os = "freebsd",
556         target_os = "netbsd",
557     ))]
558     #[test]
udp_recvmmsg()559     pub fn udp_recvmmsg() {
560         use nix::sys::socket::{recvmmsg, MsgFlags};
561         use std::io::IoSliceMut;
562 
563         const NUM_MESSAGES_SENT: usize = 2;
564         const DATA: [u8; 2] = [1, 2];
565 
566         let inet_addr = SocketAddrV4::from_str("127.0.0.1:6798").unwrap();
567         let sock_addr = SockaddrIn::from(inet_addr);
568 
569         let rsock = socket(
570             AddressFamily::Inet,
571             SockType::Datagram,
572             SockFlag::empty(),
573             None,
574         )
575         .unwrap();
576         bind(rsock, &sock_addr).unwrap();
577         let ssock = socket(
578             AddressFamily::Inet,
579             SockType::Datagram,
580             SockFlag::empty(),
581             None,
582         )
583         .expect("send socket failed");
584 
585         let send_thread = thread::spawn(move || {
586             for _ in 0..NUM_MESSAGES_SENT {
587                 sendto(ssock, &DATA[..], &sock_addr, MsgFlags::empty())
588                     .unwrap();
589             }
590         });
591 
592         let mut msgs = std::collections::LinkedList::new();
593 
594         // Buffers to receive exactly `NUM_MESSAGES_SENT` messages
595         let mut receive_buffers = [[0u8; 32]; NUM_MESSAGES_SENT];
596         msgs.extend(
597             receive_buffers
598                 .iter_mut()
599                 .map(|buf| [IoSliceMut::new(&mut buf[..])]),
600         );
601 
602         let mut data =
603             MultiHeaders::<SockaddrIn>::preallocate(msgs.len(), None);
604 
605         let res: Vec<RecvMsg<SockaddrIn>> =
606             recvmmsg(rsock, &mut data, msgs.iter(), MsgFlags::empty(), None)
607                 .expect("recvmmsg")
608                 .collect();
609         assert_eq!(res.len(), DATA.len());
610 
611         for RecvMsg { address, bytes, .. } in res.into_iter() {
612             assert_eq!(AddressFamily::Inet, address.unwrap().family().unwrap());
613             assert_eq!(DATA.len(), bytes);
614         }
615 
616         for buf in &receive_buffers {
617             assert_eq!(&buf[..DATA.len()], DATA);
618         }
619 
620         send_thread.join().unwrap();
621     }
622 
623     #[cfg(any(
624         target_os = "linux",
625         target_os = "android",
626         target_os = "freebsd",
627         target_os = "netbsd",
628     ))]
629     #[test]
udp_recvmmsg_dontwait_short_read()630     pub fn udp_recvmmsg_dontwait_short_read() {
631         use nix::sys::socket::{recvmmsg, MsgFlags};
632         use std::io::IoSliceMut;
633 
634         const NUM_MESSAGES_SENT: usize = 2;
635         const DATA: [u8; 4] = [1, 2, 3, 4];
636 
637         let inet_addr = SocketAddrV4::from_str("127.0.0.1:6799").unwrap();
638         let sock_addr = SockaddrIn::from(inet_addr);
639 
640         let rsock = socket(
641             AddressFamily::Inet,
642             SockType::Datagram,
643             SockFlag::empty(),
644             None,
645         )
646         .unwrap();
647         bind(rsock, &sock_addr).unwrap();
648         let ssock = socket(
649             AddressFamily::Inet,
650             SockType::Datagram,
651             SockFlag::empty(),
652             None,
653         )
654         .expect("send socket failed");
655 
656         let send_thread = thread::spawn(move || {
657             for _ in 0..NUM_MESSAGES_SENT {
658                 sendto(ssock, &DATA[..], &sock_addr, MsgFlags::empty())
659                     .unwrap();
660             }
661         });
662         // Ensure we've sent all the messages before continuing so `recvmmsg`
663         // will return right away
664         send_thread.join().unwrap();
665 
666         let mut msgs = std::collections::LinkedList::new();
667 
668         // Buffers to receive >`NUM_MESSAGES_SENT` messages to ensure `recvmmsg`
669         // will return when there are fewer than requested messages in the
670         // kernel buffers when using `MSG_DONTWAIT`.
671         let mut receive_buffers = [[0u8; 32]; NUM_MESSAGES_SENT + 2];
672         msgs.extend(
673             receive_buffers
674                 .iter_mut()
675                 .map(|buf| [IoSliceMut::new(&mut buf[..])]),
676         );
677 
678         let mut data = MultiHeaders::<SockaddrIn>::preallocate(
679             NUM_MESSAGES_SENT + 2,
680             None,
681         );
682 
683         let res: Vec<RecvMsg<SockaddrIn>> = recvmmsg(
684             rsock,
685             &mut data,
686             msgs.iter(),
687             MsgFlags::MSG_DONTWAIT,
688             None,
689         )
690         .expect("recvmmsg")
691         .collect();
692         assert_eq!(res.len(), NUM_MESSAGES_SENT);
693 
694         for RecvMsg { address, bytes, .. } in res.into_iter() {
695             assert_eq!(AddressFamily::Inet, address.unwrap().family().unwrap());
696             assert_eq!(DATA.len(), bytes);
697         }
698 
699         for buf in &receive_buffers[..NUM_MESSAGES_SENT] {
700             assert_eq!(&buf[..DATA.len()], DATA);
701         }
702     }
703 
704     #[test]
udp_inet6()705     pub fn udp_inet6() {
706         let addr = std::net::Ipv6Addr::from_str("::1").unwrap();
707         let rport = 6789;
708         let rstd_sa = SocketAddrV6::new(addr, rport, 0, 0);
709         let raddr = SockaddrIn6::from(rstd_sa);
710         let sport = 6790;
711         let sstd_sa = SocketAddrV6::new(addr, sport, 0, 0);
712         let saddr = SockaddrIn6::from(sstd_sa);
713         let rsock = socket(
714             AddressFamily::Inet6,
715             SockType::Datagram,
716             SockFlag::empty(),
717             None,
718         )
719         .expect("receive socket failed");
720         match bind(rsock, &raddr) {
721             Err(Errno::EADDRNOTAVAIL) => {
722                 println!("IPv6 not available, skipping test.");
723                 return;
724             }
725             Err(e) => panic!("bind: {}", e),
726             Ok(()) => (),
727         }
728         let ssock = socket(
729             AddressFamily::Inet6,
730             SockType::Datagram,
731             SockFlag::empty(),
732             None,
733         )
734         .expect("send socket failed");
735         bind(ssock, &saddr).unwrap();
736         let from = sendrecv(
737             rsock,
738             ssock,
739             move |s, m, flags| sendto(s, m, &raddr, flags),
740             |_, _| {},
741         );
742         assert_eq!(AddressFamily::Inet6, from.unwrap().family().unwrap());
743         let osent_addr = from.unwrap();
744         let sent_addr = osent_addr.as_sockaddr_in6().unwrap();
745         assert_eq!(sent_addr.ip(), addr);
746         assert_eq!(sent_addr.port(), sport);
747     }
748 }
749 
750 // Test error handling of our recvmsg wrapper
751 #[test]
test_recvmsg_ebadf()752 pub fn test_recvmsg_ebadf() {
753     use nix::errno::Errno;
754     use nix::sys::socket::{recvmsg, MsgFlags};
755     use std::io::IoSliceMut;
756 
757     let mut buf = [0u8; 5];
758     let mut iov = [IoSliceMut::new(&mut buf[..])];
759 
760     let fd = -1; // Bad file descriptor
761     let r = recvmsg::<()>(fd, &mut iov, None, MsgFlags::empty());
762 
763     assert_eq!(r.err().unwrap(), Errno::EBADF);
764 }
765 
766 // Disable the test on emulated platforms due to a bug in QEMU versions <
767 // 2.12.0.  https://bugs.launchpad.net/qemu/+bug/1701808
768 #[cfg_attr(qemu, ignore)]
769 #[test]
test_scm_rights()770 pub fn test_scm_rights() {
771     use nix::sys::socket::{
772         recvmsg, sendmsg, socketpair, AddressFamily, ControlMessage,
773         ControlMessageOwned, MsgFlags, SockFlag, SockType,
774     };
775     use nix::unistd::{close, pipe, read, write};
776     use std::io::{IoSlice, IoSliceMut};
777 
778     let (fd1, fd2) = socketpair(
779         AddressFamily::Unix,
780         SockType::Stream,
781         None,
782         SockFlag::empty(),
783     )
784     .unwrap();
785     let (r, w) = pipe().unwrap();
786     let mut received_r: Option<RawFd> = None;
787 
788     {
789         let iov = [IoSlice::new(b"hello")];
790         let fds = [r];
791         let cmsg = ControlMessage::ScmRights(&fds);
792         assert_eq!(
793             sendmsg::<()>(fd1, &iov, &[cmsg], MsgFlags::empty(), None).unwrap(),
794             5
795         );
796         close(r).unwrap();
797         close(fd1).unwrap();
798     }
799 
800     {
801         let mut buf = [0u8; 5];
802 
803         let mut iov = [IoSliceMut::new(&mut buf[..])];
804         let mut cmsgspace = cmsg_space!([RawFd; 1]);
805         let msg = recvmsg::<()>(
806             fd2,
807             &mut iov,
808             Some(&mut cmsgspace),
809             MsgFlags::empty(),
810         )
811         .unwrap();
812 
813         for cmsg in msg.cmsgs() {
814             if let ControlMessageOwned::ScmRights(fd) = cmsg {
815                 assert_eq!(received_r, None);
816                 assert_eq!(fd.len(), 1);
817                 received_r = Some(fd[0]);
818             } else {
819                 panic!("unexpected cmsg");
820             }
821         }
822         assert_eq!(msg.bytes, 5);
823         assert!(!msg
824             .flags
825             .intersects(MsgFlags::MSG_TRUNC | MsgFlags::MSG_CTRUNC));
826         close(fd2).unwrap();
827     }
828 
829     let received_r = received_r.expect("Did not receive passed fd");
830     // Ensure that the received file descriptor works
831     write(w, b"world").unwrap();
832     let mut buf = [0u8; 5];
833     read(received_r, &mut buf).unwrap();
834     assert_eq!(&buf[..], b"world");
835     close(received_r).unwrap();
836     close(w).unwrap();
837 }
838 
839 // Disable the test on emulated platforms due to not enabled support of AF_ALG in QEMU from rust cross
840 #[cfg(any(target_os = "linux", target_os = "android"))]
841 #[cfg_attr(qemu, ignore)]
842 #[test]
test_af_alg_cipher()843 pub fn test_af_alg_cipher() {
844     use nix::sys::socket::sockopt::AlgSetKey;
845     use nix::sys::socket::{
846         accept, bind, sendmsg, setsockopt, socket, AddressFamily, AlgAddr,
847         ControlMessage, MsgFlags, SockFlag, SockType,
848     };
849     use nix::unistd::read;
850     use std::io::IoSlice;
851 
852     skip_if_cirrus!("Fails for an unknown reason Cirrus CI.  Bug #1352");
853     // Travis's seccomp profile blocks AF_ALG
854     // https://docs.docker.com/engine/security/seccomp/
855     skip_if_seccomp!(test_af_alg_cipher);
856 
857     let alg_type = "skcipher";
858     let alg_name = "ctr-aes-aesni";
859     // 256-bits secret key
860     let key = vec![0u8; 32];
861     // 16-bytes IV
862     let iv_len = 16;
863     let iv = vec![1u8; iv_len];
864     // 256-bytes plain payload
865     let payload_len = 256;
866     let payload = vec![2u8; payload_len];
867 
868     let sock = socket(
869         AddressFamily::Alg,
870         SockType::SeqPacket,
871         SockFlag::empty(),
872         None,
873     )
874     .expect("socket failed");
875 
876     let sockaddr = AlgAddr::new(alg_type, alg_name);
877     bind(sock, &sockaddr).expect("bind failed");
878 
879     assert_eq!(sockaddr.alg_name().to_string_lossy(), alg_name);
880     assert_eq!(sockaddr.alg_type().to_string_lossy(), alg_type);
881 
882     setsockopt(sock, AlgSetKey::default(), &key).expect("setsockopt");
883     let session_socket = accept(sock).expect("accept failed");
884 
885     let msgs = [
886         ControlMessage::AlgSetOp(&libc::ALG_OP_ENCRYPT),
887         ControlMessage::AlgSetIv(iv.as_slice()),
888     ];
889     let iov = IoSlice::new(&payload);
890     sendmsg::<()>(session_socket, &[iov], &msgs, MsgFlags::empty(), None)
891         .expect("sendmsg encrypt");
892 
893     // allocate buffer for encrypted data
894     let mut encrypted = vec![0u8; payload_len];
895     let num_bytes = read(session_socket, &mut encrypted).expect("read encrypt");
896     assert_eq!(num_bytes, payload_len);
897 
898     let iov = IoSlice::new(&encrypted);
899 
900     let iv = vec![1u8; iv_len];
901 
902     let msgs = [
903         ControlMessage::AlgSetOp(&libc::ALG_OP_DECRYPT),
904         ControlMessage::AlgSetIv(iv.as_slice()),
905     ];
906     sendmsg::<()>(session_socket, &[iov], &msgs, MsgFlags::empty(), None)
907         .expect("sendmsg decrypt");
908 
909     // allocate buffer for decrypted data
910     let mut decrypted = vec![0u8; payload_len];
911     let num_bytes = read(session_socket, &mut decrypted).expect("read decrypt");
912 
913     assert_eq!(num_bytes, payload_len);
914     assert_eq!(decrypted, payload);
915 }
916 
917 // Disable the test on emulated platforms due to not enabled support of AF_ALG
918 // in QEMU from rust cross
919 #[cfg(any(target_os = "linux", target_os = "android"))]
920 #[cfg_attr(qemu, ignore)]
921 #[test]
test_af_alg_aead()922 pub fn test_af_alg_aead() {
923     use libc::{ALG_OP_DECRYPT, ALG_OP_ENCRYPT};
924     use nix::fcntl::{fcntl, FcntlArg, OFlag};
925     use nix::sys::socket::sockopt::{AlgSetAeadAuthSize, AlgSetKey};
926     use nix::sys::socket::{
927         accept, bind, sendmsg, setsockopt, socket, AddressFamily, AlgAddr,
928         ControlMessage, MsgFlags, SockFlag, SockType,
929     };
930     use nix::unistd::{close, read};
931     use std::io::IoSlice;
932 
933     skip_if_cirrus!("Fails for an unknown reason Cirrus CI.  Bug #1352");
934     // Travis's seccomp profile blocks AF_ALG
935     // https://docs.docker.com/engine/security/seccomp/
936     skip_if_seccomp!(test_af_alg_aead);
937 
938     let auth_size = 4usize;
939     let assoc_size = 16u32;
940 
941     let alg_type = "aead";
942     let alg_name = "gcm(aes)";
943     // 256-bits secret key
944     let key = vec![0u8; 32];
945     // 12-bytes IV
946     let iv_len = 12;
947     let iv = vec![1u8; iv_len];
948     // 256-bytes plain payload
949     let payload_len = 256;
950     let mut payload =
951         vec![2u8; payload_len + (assoc_size as usize) + auth_size];
952 
953     for i in 0..assoc_size {
954         payload[i as usize] = 10;
955     }
956 
957     let len = payload.len();
958 
959     for i in 0..auth_size {
960         payload[len - 1 - i] = 0;
961     }
962 
963     let sock = socket(
964         AddressFamily::Alg,
965         SockType::SeqPacket,
966         SockFlag::empty(),
967         None,
968     )
969     .expect("socket failed");
970 
971     let sockaddr = AlgAddr::new(alg_type, alg_name);
972     bind(sock, &sockaddr).expect("bind failed");
973 
974     setsockopt(sock, AlgSetAeadAuthSize, &auth_size)
975         .expect("setsockopt AlgSetAeadAuthSize");
976     setsockopt(sock, AlgSetKey::default(), &key).expect("setsockopt AlgSetKey");
977     let session_socket = accept(sock).expect("accept failed");
978 
979     let msgs = [
980         ControlMessage::AlgSetOp(&ALG_OP_ENCRYPT),
981         ControlMessage::AlgSetIv(iv.as_slice()),
982         ControlMessage::AlgSetAeadAssoclen(&assoc_size),
983     ];
984 
985     let iov = IoSlice::new(&payload);
986     sendmsg::<()>(session_socket, &[iov], &msgs, MsgFlags::empty(), None)
987         .expect("sendmsg encrypt");
988 
989     // allocate buffer for encrypted data
990     let mut encrypted =
991         vec![0u8; (assoc_size as usize) + payload_len + auth_size];
992     let num_bytes = read(session_socket, &mut encrypted).expect("read encrypt");
993     assert_eq!(num_bytes, payload_len + auth_size + (assoc_size as usize));
994     close(session_socket).expect("close");
995 
996     for i in 0..assoc_size {
997         encrypted[i as usize] = 10;
998     }
999 
1000     let iov = IoSlice::new(&encrypted);
1001 
1002     let iv = vec![1u8; iv_len];
1003 
1004     let session_socket = accept(sock).expect("accept failed");
1005 
1006     let msgs = [
1007         ControlMessage::AlgSetOp(&ALG_OP_DECRYPT),
1008         ControlMessage::AlgSetIv(iv.as_slice()),
1009         ControlMessage::AlgSetAeadAssoclen(&assoc_size),
1010     ];
1011     sendmsg::<()>(session_socket, &[iov], &msgs, MsgFlags::empty(), None)
1012         .expect("sendmsg decrypt");
1013 
1014     // allocate buffer for decrypted data
1015     let mut decrypted =
1016         vec![0u8; payload_len + (assoc_size as usize) + auth_size];
1017     // Starting with kernel 4.9, the interface changed slightly such that the
1018     // authentication tag memory is only needed in the output buffer for encryption
1019     // and in the input buffer for decryption.
1020     // Do not block on read, as we may have fewer bytes than buffer size
1021     fcntl(session_socket, FcntlArg::F_SETFL(OFlag::O_NONBLOCK))
1022         .expect("fcntl non_blocking");
1023     let num_bytes = read(session_socket, &mut decrypted).expect("read decrypt");
1024 
1025     assert!(num_bytes >= payload_len + (assoc_size as usize));
1026     assert_eq!(
1027         decrypted[(assoc_size as usize)..(payload_len + (assoc_size as usize))],
1028         payload[(assoc_size as usize)..payload_len + (assoc_size as usize)]
1029     );
1030 }
1031 
1032 // Verify `ControlMessage::Ipv4PacketInfo` for `sendmsg`.
1033 // This creates a (udp) socket bound to localhost, then sends a message to
1034 // itself but uses Ipv4PacketInfo to force the source address to be localhost.
1035 //
1036 // This would be a more interesting test if we could assume that the test host
1037 // has more than one IP address (since we could select a different address to
1038 // test from).
1039 #[cfg(any(target_os = "linux", target_os = "macos", target_os = "netbsd"))]
1040 #[test]
test_sendmsg_ipv4packetinfo()1041 pub fn test_sendmsg_ipv4packetinfo() {
1042     use cfg_if::cfg_if;
1043     use nix::sys::socket::{
1044         bind, sendmsg, socket, AddressFamily, ControlMessage, MsgFlags,
1045         SockFlag, SockType, SockaddrIn,
1046     };
1047     use std::io::IoSlice;
1048 
1049     let sock = socket(
1050         AddressFamily::Inet,
1051         SockType::Datagram,
1052         SockFlag::empty(),
1053         None,
1054     )
1055     .expect("socket failed");
1056 
1057     let sock_addr = SockaddrIn::new(127, 0, 0, 1, 4000);
1058 
1059     bind(sock, &sock_addr).expect("bind failed");
1060 
1061     let slice = [1u8, 2, 3, 4, 5, 6, 7, 8];
1062     let iov = [IoSlice::new(&slice)];
1063 
1064     cfg_if! {
1065         if #[cfg(target_os = "netbsd")] {
1066             let pi = libc::in_pktinfo {
1067                 ipi_ifindex: 0, /* Unspecified interface */
1068                 ipi_addr: libc::in_addr { s_addr: 0 },
1069             };
1070         } else {
1071             let pi = libc::in_pktinfo {
1072                 ipi_ifindex: 0, /* Unspecified interface */
1073                 ipi_addr: libc::in_addr { s_addr: 0 },
1074                 ipi_spec_dst: sock_addr.as_ref().sin_addr,
1075             };
1076         }
1077     }
1078 
1079     let cmsg = [ControlMessage::Ipv4PacketInfo(&pi)];
1080 
1081     sendmsg(sock, &iov, &cmsg, MsgFlags::empty(), Some(&sock_addr))
1082         .expect("sendmsg");
1083 }
1084 
1085 // Verify `ControlMessage::Ipv6PacketInfo` for `sendmsg`.
1086 // This creates a (udp) socket bound to ip6-localhost, then sends a message to
1087 // itself but uses Ipv6PacketInfo to force the source address to be
1088 // ip6-localhost.
1089 //
1090 // This would be a more interesting test if we could assume that the test host
1091 // has more than one IP address (since we could select a different address to
1092 // test from).
1093 #[cfg(any(
1094     target_os = "linux",
1095     target_os = "macos",
1096     target_os = "netbsd",
1097     target_os = "freebsd"
1098 ))]
1099 #[test]
test_sendmsg_ipv6packetinfo()1100 pub fn test_sendmsg_ipv6packetinfo() {
1101     use nix::errno::Errno;
1102     use nix::sys::socket::{
1103         bind, sendmsg, socket, AddressFamily, ControlMessage, MsgFlags,
1104         SockFlag, SockType, SockaddrIn6,
1105     };
1106     use std::io::IoSlice;
1107 
1108     let sock = socket(
1109         AddressFamily::Inet6,
1110         SockType::Datagram,
1111         SockFlag::empty(),
1112         None,
1113     )
1114     .expect("socket failed");
1115 
1116     let std_sa = SocketAddrV6::from_str("[::1]:6000").unwrap();
1117     let sock_addr: SockaddrIn6 = SockaddrIn6::from(std_sa);
1118 
1119     if let Err(Errno::EADDRNOTAVAIL) = bind(sock, &sock_addr) {
1120         println!("IPv6 not available, skipping test.");
1121         return;
1122     }
1123 
1124     let slice = [1u8, 2, 3, 4, 5, 6, 7, 8];
1125     let iov = [IoSlice::new(&slice)];
1126 
1127     let pi = libc::in6_pktinfo {
1128         ipi6_ifindex: 0, /* Unspecified interface */
1129         ipi6_addr: sock_addr.as_ref().sin6_addr,
1130     };
1131 
1132     let cmsg = [ControlMessage::Ipv6PacketInfo(&pi)];
1133 
1134     sendmsg::<SockaddrIn6>(
1135         sock,
1136         &iov,
1137         &cmsg,
1138         MsgFlags::empty(),
1139         Some(&sock_addr),
1140     )
1141     .expect("sendmsg");
1142 }
1143 
1144 // Verify that ControlMessage::Ipv4SendSrcAddr works for sendmsg. This
1145 // creates a UDP socket bound to all local interfaces (0.0.0.0). It then
1146 // sends message to itself at 127.0.0.1 while explicitly specifying
1147 // 127.0.0.1 as the source address through an Ipv4SendSrcAddr
1148 // (IP_SENDSRCADDR) control message.
1149 //
1150 // Note that binding to 0.0.0.0 is *required* on FreeBSD; sendmsg
1151 // returns EINVAL otherwise. (See FreeBSD's ip(4) man page.)
1152 #[cfg(any(
1153     target_os = "netbsd",
1154     target_os = "freebsd",
1155     target_os = "openbsd",
1156     target_os = "dragonfly",
1157 ))]
1158 #[test]
test_sendmsg_ipv4sendsrcaddr()1159 pub fn test_sendmsg_ipv4sendsrcaddr() {
1160     use nix::sys::socket::{
1161         bind, sendmsg, socket, AddressFamily, ControlMessage, MsgFlags,
1162         SockFlag, SockType, SockaddrIn,
1163     };
1164     use std::io::IoSlice;
1165 
1166     let sock = socket(
1167         AddressFamily::Inet,
1168         SockType::Datagram,
1169         SockFlag::empty(),
1170         None,
1171     )
1172     .expect("socket failed");
1173 
1174     let unspec_sock_addr = SockaddrIn::new(0, 0, 0, 0, 0);
1175     bind(sock, &unspec_sock_addr).expect("bind failed");
1176     let bound_sock_addr: SockaddrIn = getsockname(sock).unwrap();
1177     let localhost_sock_addr: SockaddrIn =
1178         SockaddrIn::new(127, 0, 0, 1, bound_sock_addr.port());
1179 
1180     let slice = [1u8, 2, 3, 4, 5, 6, 7, 8];
1181     let iov = [IoSlice::new(&slice)];
1182     let cmsg = [ControlMessage::Ipv4SendSrcAddr(
1183         &localhost_sock_addr.as_ref().sin_addr,
1184     )];
1185 
1186     sendmsg(
1187         sock,
1188         &iov,
1189         &cmsg,
1190         MsgFlags::empty(),
1191         Some(&localhost_sock_addr),
1192     )
1193     .expect("sendmsg");
1194 }
1195 
1196 /// Tests that passing multiple fds using a single `ControlMessage` works.
1197 // Disable the test on emulated platforms due to a bug in QEMU versions <
1198 // 2.12.0.  https://bugs.launchpad.net/qemu/+bug/1701808
1199 #[cfg_attr(qemu, ignore)]
1200 #[test]
test_scm_rights_single_cmsg_multiple_fds()1201 fn test_scm_rights_single_cmsg_multiple_fds() {
1202     use nix::sys::socket::{
1203         recvmsg, sendmsg, ControlMessage, ControlMessageOwned, MsgFlags,
1204     };
1205     use std::io::{IoSlice, IoSliceMut};
1206     use std::os::unix::io::{AsRawFd, RawFd};
1207     use std::os::unix::net::UnixDatagram;
1208     use std::thread;
1209 
1210     let (send, receive) = UnixDatagram::pair().unwrap();
1211     let thread = thread::spawn(move || {
1212         let mut buf = [0u8; 8];
1213         let mut iovec = [IoSliceMut::new(&mut buf)];
1214 
1215         let mut space = cmsg_space!([RawFd; 2]);
1216         let msg = recvmsg::<()>(
1217             receive.as_raw_fd(),
1218             &mut iovec,
1219             Some(&mut space),
1220             MsgFlags::empty(),
1221         )
1222         .unwrap();
1223         assert!(!msg
1224             .flags
1225             .intersects(MsgFlags::MSG_TRUNC | MsgFlags::MSG_CTRUNC));
1226 
1227         let mut cmsgs = msg.cmsgs();
1228         match cmsgs.next() {
1229             Some(ControlMessageOwned::ScmRights(fds)) => {
1230                 assert_eq!(
1231                     fds.len(),
1232                     2,
1233                     "unexpected fd count (expected 2 fds, got {})",
1234                     fds.len()
1235                 );
1236             }
1237             _ => panic!(),
1238         }
1239         assert!(cmsgs.next().is_none(), "unexpected control msg");
1240 
1241         assert_eq!(msg.bytes, 8);
1242         assert_eq!(*iovec[0], [1u8, 2, 3, 4, 5, 6, 7, 8]);
1243     });
1244 
1245     let slice = [1u8, 2, 3, 4, 5, 6, 7, 8];
1246     let iov = [IoSlice::new(&slice)];
1247     let fds = [libc::STDIN_FILENO, libc::STDOUT_FILENO]; // pass stdin and stdout
1248     let cmsg = [ControlMessage::ScmRights(&fds)];
1249     sendmsg::<()>(send.as_raw_fd(), &iov, &cmsg, MsgFlags::empty(), None)
1250         .unwrap();
1251     thread.join().unwrap();
1252 }
1253 
1254 // Verify `sendmsg` builds a valid `msghdr` when passing an empty
1255 // `cmsgs` argument.  This should result in a msghdr with a nullptr
1256 // msg_control field and a msg_controllen of 0 when calling into the
1257 // raw `sendmsg`.
1258 #[test]
test_sendmsg_empty_cmsgs()1259 pub fn test_sendmsg_empty_cmsgs() {
1260     use nix::sys::socket::{
1261         recvmsg, sendmsg, socketpair, AddressFamily, MsgFlags, SockFlag,
1262         SockType,
1263     };
1264     use nix::unistd::close;
1265     use std::io::{IoSlice, IoSliceMut};
1266 
1267     let (fd1, fd2) = socketpair(
1268         AddressFamily::Unix,
1269         SockType::Stream,
1270         None,
1271         SockFlag::empty(),
1272     )
1273     .unwrap();
1274 
1275     {
1276         let iov = [IoSlice::new(b"hello")];
1277         assert_eq!(
1278             sendmsg::<()>(fd1, &iov, &[], MsgFlags::empty(), None).unwrap(),
1279             5
1280         );
1281         close(fd1).unwrap();
1282     }
1283 
1284     {
1285         let mut buf = [0u8; 5];
1286         let mut iov = [IoSliceMut::new(&mut buf[..])];
1287 
1288         let mut cmsgspace = cmsg_space!([RawFd; 1]);
1289         let msg = recvmsg::<()>(
1290             fd2,
1291             &mut iov,
1292             Some(&mut cmsgspace),
1293             MsgFlags::empty(),
1294         )
1295         .unwrap();
1296 
1297         for _ in msg.cmsgs() {
1298             panic!("unexpected cmsg");
1299         }
1300         assert!(!msg
1301             .flags
1302             .intersects(MsgFlags::MSG_TRUNC | MsgFlags::MSG_CTRUNC));
1303         assert_eq!(msg.bytes, 5);
1304         close(fd2).unwrap();
1305     }
1306 }
1307 
1308 #[cfg(any(
1309     target_os = "android",
1310     target_os = "linux",
1311     target_os = "freebsd",
1312     target_os = "dragonfly",
1313 ))]
1314 #[test]
test_scm_credentials()1315 fn test_scm_credentials() {
1316     use nix::sys::socket::{
1317         recvmsg, sendmsg, socketpair, AddressFamily, ControlMessage,
1318         ControlMessageOwned, MsgFlags, SockFlag, SockType, UnixCredentials,
1319     };
1320     #[cfg(any(target_os = "android", target_os = "linux"))]
1321     use nix::sys::socket::{setsockopt, sockopt::PassCred};
1322     use nix::unistd::{close, getgid, getpid, getuid};
1323     use std::io::{IoSlice, IoSliceMut};
1324 
1325     let (send, recv) = socketpair(
1326         AddressFamily::Unix,
1327         SockType::Stream,
1328         None,
1329         SockFlag::empty(),
1330     )
1331     .unwrap();
1332     #[cfg(any(target_os = "android", target_os = "linux"))]
1333     setsockopt(recv, PassCred, &true).unwrap();
1334 
1335     {
1336         let iov = [IoSlice::new(b"hello")];
1337         #[cfg(any(target_os = "android", target_os = "linux"))]
1338         let cred = UnixCredentials::new();
1339         #[cfg(any(target_os = "android", target_os = "linux"))]
1340         let cmsg = ControlMessage::ScmCredentials(&cred);
1341         #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
1342         let cmsg = ControlMessage::ScmCreds;
1343         assert_eq!(
1344             sendmsg::<()>(send, &iov, &[cmsg], MsgFlags::empty(), None)
1345                 .unwrap(),
1346             5
1347         );
1348         close(send).unwrap();
1349     }
1350 
1351     {
1352         let mut buf = [0u8; 5];
1353         let mut iov = [IoSliceMut::new(&mut buf[..])];
1354 
1355         let mut cmsgspace = cmsg_space!(UnixCredentials);
1356         let msg = recvmsg::<()>(
1357             recv,
1358             &mut iov,
1359             Some(&mut cmsgspace),
1360             MsgFlags::empty(),
1361         )
1362         .unwrap();
1363         let mut received_cred = None;
1364 
1365         for cmsg in msg.cmsgs() {
1366             let cred = match cmsg {
1367                 #[cfg(any(target_os = "android", target_os = "linux"))]
1368                 ControlMessageOwned::ScmCredentials(cred) => cred,
1369                 #[cfg(any(target_os = "freebsd", target_os = "dragonfly"))]
1370                 ControlMessageOwned::ScmCreds(cred) => cred,
1371                 other => panic!("unexpected cmsg {:?}", other),
1372             };
1373             assert!(received_cred.is_none());
1374             assert_eq!(cred.pid(), getpid().as_raw());
1375             assert_eq!(cred.uid(), getuid().as_raw());
1376             assert_eq!(cred.gid(), getgid().as_raw());
1377             received_cred = Some(cred);
1378         }
1379         received_cred.expect("no creds received");
1380         assert_eq!(msg.bytes, 5);
1381         assert!(!msg
1382             .flags
1383             .intersects(MsgFlags::MSG_TRUNC | MsgFlags::MSG_CTRUNC));
1384         close(recv).unwrap();
1385     }
1386 }
1387 
1388 /// Ensure that we can send `SCM_CREDENTIALS` and `SCM_RIGHTS` with a single
1389 /// `sendmsg` call.
1390 #[cfg(any(target_os = "android", target_os = "linux"))]
1391 // qemu's handling of multiple cmsgs is bugged, ignore tests under emulation
1392 // see https://bugs.launchpad.net/qemu/+bug/1781280
1393 #[cfg_attr(qemu, ignore)]
1394 #[test]
test_scm_credentials_and_rights()1395 fn test_scm_credentials_and_rights() {
1396     let space = cmsg_space!(libc::ucred, RawFd);
1397     test_impl_scm_credentials_and_rights(space);
1398 }
1399 
1400 /// Ensure that passing a an oversized control message buffer to recvmsg
1401 /// still works.
1402 #[cfg(any(target_os = "android", target_os = "linux"))]
1403 // qemu's handling of multiple cmsgs is bugged, ignore tests under emulation
1404 // see https://bugs.launchpad.net/qemu/+bug/1781280
1405 #[cfg_attr(qemu, ignore)]
1406 #[test]
test_too_large_cmsgspace()1407 fn test_too_large_cmsgspace() {
1408     let space = vec![0u8; 1024];
1409     test_impl_scm_credentials_and_rights(space);
1410 }
1411 
1412 #[cfg(any(target_os = "android", target_os = "linux"))]
test_impl_scm_credentials_and_rights(mut space: Vec<u8>)1413 fn test_impl_scm_credentials_and_rights(mut space: Vec<u8>) {
1414     use libc::ucred;
1415     use nix::sys::socket::sockopt::PassCred;
1416     use nix::sys::socket::{
1417         recvmsg, sendmsg, setsockopt, socketpair, ControlMessage,
1418         ControlMessageOwned, MsgFlags, SockFlag, SockType,
1419     };
1420     use nix::unistd::{close, getgid, getpid, getuid, pipe, write};
1421     use std::io::{IoSlice, IoSliceMut};
1422 
1423     let (send, recv) = socketpair(
1424         AddressFamily::Unix,
1425         SockType::Stream,
1426         None,
1427         SockFlag::empty(),
1428     )
1429     .unwrap();
1430     setsockopt(recv, PassCred, &true).unwrap();
1431 
1432     let (r, w) = pipe().unwrap();
1433     let mut received_r: Option<RawFd> = None;
1434 
1435     {
1436         let iov = [IoSlice::new(b"hello")];
1437         let cred = ucred {
1438             pid: getpid().as_raw(),
1439             uid: getuid().as_raw(),
1440             gid: getgid().as_raw(),
1441         }
1442         .into();
1443         let fds = [r];
1444         let cmsgs = [
1445             ControlMessage::ScmCredentials(&cred),
1446             ControlMessage::ScmRights(&fds),
1447         ];
1448         assert_eq!(
1449             sendmsg::<()>(send, &iov, &cmsgs, MsgFlags::empty(), None).unwrap(),
1450             5
1451         );
1452         close(r).unwrap();
1453         close(send).unwrap();
1454     }
1455 
1456     {
1457         let mut buf = [0u8; 5];
1458         let mut iov = [IoSliceMut::new(&mut buf[..])];
1459         let msg =
1460             recvmsg::<()>(recv, &mut iov, Some(&mut space), MsgFlags::empty())
1461                 .unwrap();
1462         let mut received_cred = None;
1463 
1464         assert_eq!(msg.cmsgs().count(), 2, "expected 2 cmsgs");
1465 
1466         for cmsg in msg.cmsgs() {
1467             match cmsg {
1468                 ControlMessageOwned::ScmRights(fds) => {
1469                     assert_eq!(received_r, None, "already received fd");
1470                     assert_eq!(fds.len(), 1);
1471                     received_r = Some(fds[0]);
1472                 }
1473                 ControlMessageOwned::ScmCredentials(cred) => {
1474                     assert!(received_cred.is_none());
1475                     assert_eq!(cred.pid(), getpid().as_raw());
1476                     assert_eq!(cred.uid(), getuid().as_raw());
1477                     assert_eq!(cred.gid(), getgid().as_raw());
1478                     received_cred = Some(cred);
1479                 }
1480                 _ => panic!("unexpected cmsg"),
1481             }
1482         }
1483         received_cred.expect("no creds received");
1484         assert_eq!(msg.bytes, 5);
1485         assert!(!msg
1486             .flags
1487             .intersects(MsgFlags::MSG_TRUNC | MsgFlags::MSG_CTRUNC));
1488         close(recv).unwrap();
1489     }
1490 
1491     let received_r = received_r.expect("Did not receive passed fd");
1492     // Ensure that the received file descriptor works
1493     write(w, b"world").unwrap();
1494     let mut buf = [0u8; 5];
1495     read(received_r, &mut buf).unwrap();
1496     assert_eq!(&buf[..], b"world");
1497     close(received_r).unwrap();
1498     close(w).unwrap();
1499 }
1500 
1501 // Test creating and using named unix domain sockets
1502 #[test]
test_named_unixdomain()1503 pub fn test_named_unixdomain() {
1504     use nix::sys::socket::{accept, bind, connect, listen, socket, UnixAddr};
1505     use nix::sys::socket::{SockFlag, SockType};
1506     use nix::unistd::{close, read, write};
1507     use std::thread;
1508 
1509     let tempdir = tempfile::tempdir().unwrap();
1510     let sockname = tempdir.path().join("sock");
1511     let s1 = socket(
1512         AddressFamily::Unix,
1513         SockType::Stream,
1514         SockFlag::empty(),
1515         None,
1516     )
1517     .expect("socket failed");
1518     let sockaddr = UnixAddr::new(&sockname).unwrap();
1519     bind(s1, &sockaddr).expect("bind failed");
1520     listen(s1, 10).expect("listen failed");
1521 
1522     let thr = thread::spawn(move || {
1523         let s2 = socket(
1524             AddressFamily::Unix,
1525             SockType::Stream,
1526             SockFlag::empty(),
1527             None,
1528         )
1529         .expect("socket failed");
1530         connect(s2, &sockaddr).expect("connect failed");
1531         write(s2, b"hello").expect("write failed");
1532         close(s2).unwrap();
1533     });
1534 
1535     let s3 = accept(s1).expect("accept failed");
1536 
1537     let mut buf = [0; 5];
1538     read(s3, &mut buf).unwrap();
1539     close(s3).unwrap();
1540     close(s1).unwrap();
1541     thr.join().unwrap();
1542 
1543     assert_eq!(&buf[..], b"hello");
1544 }
1545 
1546 // Test using unnamed unix domain addresses
1547 #[cfg(any(target_os = "android", target_os = "linux"))]
1548 #[test]
test_unnamed_unixdomain()1549 pub fn test_unnamed_unixdomain() {
1550     use nix::sys::socket::{getsockname, socketpair};
1551     use nix::sys::socket::{SockFlag, SockType};
1552     use nix::unistd::close;
1553 
1554     let (fd_1, fd_2) = socketpair(
1555         AddressFamily::Unix,
1556         SockType::Stream,
1557         None,
1558         SockFlag::empty(),
1559     )
1560     .expect("socketpair failed");
1561 
1562     let addr_1: UnixAddr = getsockname(fd_1).expect("getsockname failed");
1563     assert!(addr_1.is_unnamed());
1564 
1565     close(fd_1).unwrap();
1566     close(fd_2).unwrap();
1567 }
1568 
1569 // Test creating and using unnamed unix domain addresses for autobinding sockets
1570 #[cfg(any(target_os = "android", target_os = "linux"))]
1571 #[test]
test_unnamed_unixdomain_autobind()1572 pub fn test_unnamed_unixdomain_autobind() {
1573     use nix::sys::socket::{bind, getsockname, socket};
1574     use nix::sys::socket::{SockFlag, SockType};
1575     use nix::unistd::close;
1576 
1577     let fd = socket(
1578         AddressFamily::Unix,
1579         SockType::Stream,
1580         SockFlag::empty(),
1581         None,
1582     )
1583     .expect("socket failed");
1584 
1585     // unix(7): "If a bind(2) call specifies addrlen as `sizeof(sa_family_t)`, or [...], then the
1586     // socket is autobound to an abstract address"
1587     bind(fd, &UnixAddr::new_unnamed()).expect("bind failed");
1588 
1589     let addr: UnixAddr = getsockname(fd).expect("getsockname failed");
1590     let addr = addr.as_abstract().unwrap();
1591 
1592     // changed from 8 to 5 bytes in Linux 2.3.15, and rust's minimum supported Linux version is 3.2
1593     // (as of 2022-11)
1594     assert_eq!(addr.len(), 5);
1595 
1596     close(fd).unwrap();
1597 }
1598 
1599 // Test creating and using named system control sockets
1600 #[cfg(any(target_os = "macos", target_os = "ios"))]
1601 #[test]
test_syscontrol()1602 pub fn test_syscontrol() {
1603     use nix::errno::Errno;
1604     use nix::sys::socket::{
1605         socket, SockFlag, SockProtocol, SockType, SysControlAddr,
1606     };
1607 
1608     let fd = socket(
1609         AddressFamily::System,
1610         SockType::Datagram,
1611         SockFlag::empty(),
1612         SockProtocol::KextControl,
1613     )
1614     .expect("socket failed");
1615     SysControlAddr::from_name(fd, "com.apple.net.utun_control", 0)
1616         .expect("resolving sys_control name failed");
1617     assert_eq!(
1618         SysControlAddr::from_name(fd, "foo.bar.lol", 0).err(),
1619         Some(Errno::ENOENT)
1620     );
1621 
1622     // requires root privileges
1623     // connect(fd, &sockaddr).expect("connect failed");
1624 }
1625 
1626 #[cfg(any(
1627     target_os = "android",
1628     target_os = "freebsd",
1629     target_os = "ios",
1630     target_os = "linux",
1631     target_os = "macos",
1632     target_os = "netbsd",
1633     target_os = "openbsd",
1634 ))]
loopback_address( family: AddressFamily, ) -> Option<nix::ifaddrs::InterfaceAddress>1635 fn loopback_address(
1636     family: AddressFamily,
1637 ) -> Option<nix::ifaddrs::InterfaceAddress> {
1638     use nix::ifaddrs::getifaddrs;
1639     use nix::net::if_::*;
1640     use nix::sys::socket::SockaddrLike;
1641     use std::io;
1642     use std::io::Write;
1643 
1644     let mut addrs = match getifaddrs() {
1645         Ok(iter) => iter,
1646         Err(e) => {
1647             let stdioerr = io::stderr();
1648             let mut handle = stdioerr.lock();
1649             writeln!(handle, "getifaddrs: {:?}", e).unwrap();
1650             return None;
1651         }
1652     };
1653     // return first address matching family
1654     addrs.find(|ifaddr| {
1655         ifaddr.flags.contains(InterfaceFlags::IFF_LOOPBACK)
1656             && ifaddr.address.as_ref().and_then(SockaddrLike::family)
1657                 == Some(family)
1658     })
1659 }
1660 
1661 #[cfg(any(
1662     target_os = "android",
1663     target_os = "ios",
1664     target_os = "linux",
1665     target_os = "macos",
1666     target_os = "netbsd",
1667 ))]
1668 // qemu doesn't seem to be emulating this correctly in these architectures
1669 #[cfg_attr(
1670     all(
1671         qemu,
1672         any(
1673             target_arch = "mips",
1674             target_arch = "mips64",
1675             target_arch = "powerpc64",
1676         )
1677     ),
1678     ignore
1679 )]
1680 #[test]
test_recv_ipv4pktinfo()1681 pub fn test_recv_ipv4pktinfo() {
1682     use nix::net::if_::*;
1683     use nix::sys::socket::sockopt::Ipv4PacketInfo;
1684     use nix::sys::socket::{bind, SockFlag, SockType, SockaddrIn};
1685     use nix::sys::socket::{getsockname, setsockopt, socket};
1686     use nix::sys::socket::{recvmsg, sendmsg, ControlMessageOwned, MsgFlags};
1687     use std::io::{IoSlice, IoSliceMut};
1688 
1689     let lo_ifaddr = loopback_address(AddressFamily::Inet);
1690     let (lo_name, lo) = match lo_ifaddr {
1691         Some(ifaddr) => (
1692             ifaddr.interface_name,
1693             ifaddr.address.expect("Expect IPv4 address on interface"),
1694         ),
1695         None => return,
1696     };
1697     let receive = socket(
1698         AddressFamily::Inet,
1699         SockType::Datagram,
1700         SockFlag::empty(),
1701         None,
1702     )
1703     .expect("receive socket failed");
1704     bind(receive, &lo).expect("bind failed");
1705     let sa: SockaddrIn = getsockname(receive).expect("getsockname failed");
1706     setsockopt(receive, Ipv4PacketInfo, &true).expect("setsockopt failed");
1707 
1708     {
1709         let slice = [1u8, 2, 3, 4, 5, 6, 7, 8];
1710         let iov = [IoSlice::new(&slice)];
1711 
1712         let send = socket(
1713             AddressFamily::Inet,
1714             SockType::Datagram,
1715             SockFlag::empty(),
1716             None,
1717         )
1718         .expect("send socket failed");
1719         sendmsg(send, &iov, &[], MsgFlags::empty(), Some(&sa))
1720             .expect("sendmsg failed");
1721     }
1722 
1723     {
1724         let mut buf = [0u8; 8];
1725         let mut iovec = [IoSliceMut::new(&mut buf)];
1726 
1727         let mut space = cmsg_space!(libc::in_pktinfo);
1728         let msg = recvmsg::<()>(
1729             receive,
1730             &mut iovec,
1731             Some(&mut space),
1732             MsgFlags::empty(),
1733         )
1734         .expect("recvmsg failed");
1735         assert!(!msg
1736             .flags
1737             .intersects(MsgFlags::MSG_TRUNC | MsgFlags::MSG_CTRUNC));
1738 
1739         let mut cmsgs = msg.cmsgs();
1740         if let Some(ControlMessageOwned::Ipv4PacketInfo(pktinfo)) = cmsgs.next()
1741         {
1742             let i = if_nametoindex(lo_name.as_bytes()).expect("if_nametoindex");
1743             assert_eq!(
1744                 pktinfo.ipi_ifindex as libc::c_uint, i,
1745                 "unexpected ifindex (expected {}, got {})",
1746                 i, pktinfo.ipi_ifindex
1747             );
1748         }
1749         assert!(cmsgs.next().is_none(), "unexpected additional control msg");
1750         assert_eq!(msg.bytes, 8);
1751         assert_eq!(*iovec[0], [1u8, 2, 3, 4, 5, 6, 7, 8]);
1752     }
1753 }
1754 
1755 #[cfg(any(
1756     target_os = "freebsd",
1757     target_os = "ios",
1758     target_os = "macos",
1759     target_os = "netbsd",
1760     target_os = "openbsd",
1761 ))]
1762 // qemu doesn't seem to be emulating this correctly in these architectures
1763 #[cfg_attr(
1764     all(
1765         qemu,
1766         any(
1767             target_arch = "mips",
1768             target_arch = "mips64",
1769             target_arch = "powerpc64",
1770         )
1771     ),
1772     ignore
1773 )]
1774 #[test]
test_recvif()1775 pub fn test_recvif() {
1776     use nix::net::if_::*;
1777     use nix::sys::socket::sockopt::{Ipv4RecvDstAddr, Ipv4RecvIf};
1778     use nix::sys::socket::{bind, SockFlag, SockType, SockaddrIn};
1779     use nix::sys::socket::{getsockname, setsockopt, socket};
1780     use nix::sys::socket::{recvmsg, sendmsg, ControlMessageOwned, MsgFlags};
1781     use std::io::{IoSlice, IoSliceMut};
1782 
1783     let lo_ifaddr = loopback_address(AddressFamily::Inet);
1784     let (lo_name, lo) = match lo_ifaddr {
1785         Some(ifaddr) => (
1786             ifaddr.interface_name,
1787             ifaddr.address.expect("Expect IPv4 address on interface"),
1788         ),
1789         None => return,
1790     };
1791     let receive = socket(
1792         AddressFamily::Inet,
1793         SockType::Datagram,
1794         SockFlag::empty(),
1795         None,
1796     )
1797     .expect("receive socket failed");
1798     bind(receive, &lo).expect("bind failed");
1799     let sa: SockaddrIn = getsockname(receive).expect("getsockname failed");
1800     setsockopt(receive, Ipv4RecvIf, &true)
1801         .expect("setsockopt IP_RECVIF failed");
1802     setsockopt(receive, Ipv4RecvDstAddr, &true)
1803         .expect("setsockopt IP_RECVDSTADDR failed");
1804 
1805     {
1806         let slice = [1u8, 2, 3, 4, 5, 6, 7, 8];
1807         let iov = [IoSlice::new(&slice)];
1808 
1809         let send = socket(
1810             AddressFamily::Inet,
1811             SockType::Datagram,
1812             SockFlag::empty(),
1813             None,
1814         )
1815         .expect("send socket failed");
1816         sendmsg(send, &iov, &[], MsgFlags::empty(), Some(&sa))
1817             .expect("sendmsg failed");
1818     }
1819 
1820     {
1821         let mut buf = [0u8; 8];
1822         let mut iovec = [IoSliceMut::new(&mut buf)];
1823         let mut space = cmsg_space!(libc::sockaddr_dl, libc::in_addr);
1824         let msg = recvmsg::<()>(
1825             receive,
1826             &mut iovec,
1827             Some(&mut space),
1828             MsgFlags::empty(),
1829         )
1830         .expect("recvmsg failed");
1831         assert!(!msg
1832             .flags
1833             .intersects(MsgFlags::MSG_TRUNC | MsgFlags::MSG_CTRUNC));
1834         assert_eq!(msg.cmsgs().count(), 2, "expected 2 cmsgs");
1835 
1836         let mut rx_recvif = false;
1837         let mut rx_recvdstaddr = false;
1838         for cmsg in msg.cmsgs() {
1839             match cmsg {
1840                 ControlMessageOwned::Ipv4RecvIf(dl) => {
1841                     rx_recvif = true;
1842                     let i = if_nametoindex(lo_name.as_bytes())
1843                         .expect("if_nametoindex");
1844                     assert_eq!(
1845                         dl.sdl_index as libc::c_uint, i,
1846                         "unexpected ifindex (expected {}, got {})",
1847                         i, dl.sdl_index
1848                     );
1849                 }
1850                 ControlMessageOwned::Ipv4RecvDstAddr(addr) => {
1851                     rx_recvdstaddr = true;
1852                     if let Some(sin) = lo.as_sockaddr_in() {
1853                         assert_eq!(sin.as_ref().sin_addr.s_addr,
1854                                    addr.s_addr,
1855                                    "unexpected destination address (expected {}, got {})",
1856                                    sin.as_ref().sin_addr.s_addr,
1857                                    addr.s_addr);
1858                     } else {
1859                         panic!("unexpected Sockaddr");
1860                     }
1861                 }
1862                 _ => panic!("unexpected additional control msg"),
1863             }
1864         }
1865         assert!(rx_recvif);
1866         assert!(rx_recvdstaddr);
1867         assert_eq!(msg.bytes, 8);
1868         assert_eq!(*iovec[0], [1u8, 2, 3, 4, 5, 6, 7, 8]);
1869     }
1870 }
1871 
1872 #[cfg(any(target_os = "android", target_os = "freebsd", target_os = "linux"))]
1873 #[cfg_attr(qemu, ignore)]
1874 #[test]
test_recvif_ipv4()1875 pub fn test_recvif_ipv4() {
1876     use nix::sys::socket::sockopt::Ipv4OrigDstAddr;
1877     use nix::sys::socket::{bind, SockFlag, SockType, SockaddrIn};
1878     use nix::sys::socket::{getsockname, setsockopt, socket};
1879     use nix::sys::socket::{recvmsg, sendmsg, ControlMessageOwned, MsgFlags};
1880     use std::io::{IoSlice, IoSliceMut};
1881 
1882     let lo_ifaddr = loopback_address(AddressFamily::Inet);
1883     let (_lo_name, lo) = match lo_ifaddr {
1884         Some(ifaddr) => (
1885             ifaddr.interface_name,
1886             ifaddr.address.expect("Expect IPv4 address on interface"),
1887         ),
1888         None => return,
1889     };
1890     let receive = socket(
1891         AddressFamily::Inet,
1892         SockType::Datagram,
1893         SockFlag::empty(),
1894         None,
1895     )
1896     .expect("receive socket failed");
1897     bind(receive, &lo).expect("bind failed");
1898     let sa: SockaddrIn = getsockname(receive).expect("getsockname failed");
1899     setsockopt(receive, Ipv4OrigDstAddr, &true)
1900         .expect("setsockopt IP_ORIGDSTADDR failed");
1901 
1902     {
1903         let slice = [1u8, 2, 3, 4, 5, 6, 7, 8];
1904         let iov = [IoSlice::new(&slice)];
1905 
1906         let send = socket(
1907             AddressFamily::Inet,
1908             SockType::Datagram,
1909             SockFlag::empty(),
1910             None,
1911         )
1912         .expect("send socket failed");
1913         sendmsg(send, &iov, &[], MsgFlags::empty(), Some(&sa))
1914             .expect("sendmsg failed");
1915     }
1916 
1917     {
1918         let mut buf = [0u8; 8];
1919         let mut iovec = [IoSliceMut::new(&mut buf)];
1920         let mut space = cmsg_space!(libc::sockaddr_in);
1921         let msg = recvmsg::<()>(
1922             receive,
1923             &mut iovec,
1924             Some(&mut space),
1925             MsgFlags::empty(),
1926         )
1927         .expect("recvmsg failed");
1928         assert!(!msg
1929             .flags
1930             .intersects(MsgFlags::MSG_TRUNC | MsgFlags::MSG_CTRUNC));
1931         assert_eq!(msg.cmsgs().count(), 1, "expected 1 cmsgs");
1932 
1933         let mut rx_recvorigdstaddr = false;
1934         for cmsg in msg.cmsgs() {
1935             match cmsg {
1936                 ControlMessageOwned::Ipv4OrigDstAddr(addr) => {
1937                     rx_recvorigdstaddr = true;
1938                     if let Some(sin) = lo.as_sockaddr_in() {
1939                         assert_eq!(sin.as_ref().sin_addr.s_addr,
1940                                    addr.sin_addr.s_addr,
1941                                    "unexpected destination address (expected {}, got {})",
1942                                    sin.as_ref().sin_addr.s_addr,
1943                                    addr.sin_addr.s_addr);
1944                     } else {
1945                         panic!("unexpected Sockaddr");
1946                     }
1947                 }
1948                 _ => panic!("unexpected additional control msg"),
1949             }
1950         }
1951         assert!(rx_recvorigdstaddr);
1952         assert_eq!(msg.bytes, 8);
1953         assert_eq!(*iovec[0], [1u8, 2, 3, 4, 5, 6, 7, 8]);
1954     }
1955 }
1956 
1957 #[cfg(any(target_os = "android", target_os = "freebsd", target_os = "linux"))]
1958 #[cfg_attr(qemu, ignore)]
1959 #[test]
test_recvif_ipv6()1960 pub fn test_recvif_ipv6() {
1961     use nix::sys::socket::sockopt::Ipv6OrigDstAddr;
1962     use nix::sys::socket::{bind, SockFlag, SockType, SockaddrIn6};
1963     use nix::sys::socket::{getsockname, setsockopt, socket};
1964     use nix::sys::socket::{recvmsg, sendmsg, ControlMessageOwned, MsgFlags};
1965     use std::io::{IoSlice, IoSliceMut};
1966 
1967     let lo_ifaddr = loopback_address(AddressFamily::Inet6);
1968     let (_lo_name, lo) = match lo_ifaddr {
1969         Some(ifaddr) => (
1970             ifaddr.interface_name,
1971             ifaddr.address.expect("Expect IPv6 address on interface"),
1972         ),
1973         None => return,
1974     };
1975     let receive = socket(
1976         AddressFamily::Inet6,
1977         SockType::Datagram,
1978         SockFlag::empty(),
1979         None,
1980     )
1981     .expect("receive socket failed");
1982     bind(receive, &lo).expect("bind failed");
1983     let sa: SockaddrIn6 = getsockname(receive).expect("getsockname failed");
1984     setsockopt(receive, Ipv6OrigDstAddr, &true)
1985         .expect("setsockopt IP_ORIGDSTADDR failed");
1986 
1987     {
1988         let slice = [1u8, 2, 3, 4, 5, 6, 7, 8];
1989         let iov = [IoSlice::new(&slice)];
1990 
1991         let send = socket(
1992             AddressFamily::Inet6,
1993             SockType::Datagram,
1994             SockFlag::empty(),
1995             None,
1996         )
1997         .expect("send socket failed");
1998         sendmsg(send, &iov, &[], MsgFlags::empty(), Some(&sa))
1999             .expect("sendmsg failed");
2000     }
2001 
2002     {
2003         let mut buf = [0u8; 8];
2004         let mut iovec = [IoSliceMut::new(&mut buf)];
2005         let mut space = cmsg_space!(libc::sockaddr_in6);
2006         let msg = recvmsg::<()>(
2007             receive,
2008             &mut iovec,
2009             Some(&mut space),
2010             MsgFlags::empty(),
2011         )
2012         .expect("recvmsg failed");
2013         assert!(!msg
2014             .flags
2015             .intersects(MsgFlags::MSG_TRUNC | MsgFlags::MSG_CTRUNC));
2016         assert_eq!(msg.cmsgs().count(), 1, "expected 1 cmsgs");
2017 
2018         let mut rx_recvorigdstaddr = false;
2019         for cmsg in msg.cmsgs() {
2020             match cmsg {
2021                 ControlMessageOwned::Ipv6OrigDstAddr(addr) => {
2022                     rx_recvorigdstaddr = true;
2023                     if let Some(sin) = lo.as_sockaddr_in6() {
2024                         assert_eq!(sin.as_ref().sin6_addr.s6_addr,
2025                                    addr.sin6_addr.s6_addr,
2026                                    "unexpected destination address (expected {:?}, got {:?})",
2027                                    sin.as_ref().sin6_addr.s6_addr,
2028                                    addr.sin6_addr.s6_addr);
2029                     } else {
2030                         panic!("unexpected Sockaddr");
2031                     }
2032                 }
2033                 _ => panic!("unexpected additional control msg"),
2034             }
2035         }
2036         assert!(rx_recvorigdstaddr);
2037         assert_eq!(msg.bytes, 8);
2038         assert_eq!(*iovec[0], [1u8, 2, 3, 4, 5, 6, 7, 8]);
2039     }
2040 }
2041 
2042 #[cfg(any(
2043     target_os = "android",
2044     target_os = "freebsd",
2045     target_os = "ios",
2046     target_os = "linux",
2047     target_os = "macos",
2048     target_os = "netbsd",
2049     target_os = "openbsd",
2050 ))]
2051 // qemu doesn't seem to be emulating this correctly in these architectures
2052 #[cfg_attr(
2053     all(
2054         qemu,
2055         any(
2056             target_arch = "mips",
2057             target_arch = "mips64",
2058             target_arch = "powerpc64",
2059         )
2060     ),
2061     ignore
2062 )]
2063 #[test]
test_recv_ipv6pktinfo()2064 pub fn test_recv_ipv6pktinfo() {
2065     use nix::net::if_::*;
2066     use nix::sys::socket::sockopt::Ipv6RecvPacketInfo;
2067     use nix::sys::socket::{bind, SockFlag, SockType, SockaddrIn6};
2068     use nix::sys::socket::{getsockname, setsockopt, socket};
2069     use nix::sys::socket::{recvmsg, sendmsg, ControlMessageOwned, MsgFlags};
2070     use std::io::{IoSlice, IoSliceMut};
2071 
2072     let lo_ifaddr = loopback_address(AddressFamily::Inet6);
2073     let (lo_name, lo) = match lo_ifaddr {
2074         Some(ifaddr) => (
2075             ifaddr.interface_name,
2076             ifaddr.address.expect("Expect IPv6 address on interface"),
2077         ),
2078         None => return,
2079     };
2080     let receive = socket(
2081         AddressFamily::Inet6,
2082         SockType::Datagram,
2083         SockFlag::empty(),
2084         None,
2085     )
2086     .expect("receive socket failed");
2087     bind(receive, &lo).expect("bind failed");
2088     let sa: SockaddrIn6 = getsockname(receive).expect("getsockname failed");
2089     setsockopt(receive, Ipv6RecvPacketInfo, &true).expect("setsockopt failed");
2090 
2091     {
2092         let slice = [1u8, 2, 3, 4, 5, 6, 7, 8];
2093         let iov = [IoSlice::new(&slice)];
2094 
2095         let send = socket(
2096             AddressFamily::Inet6,
2097             SockType::Datagram,
2098             SockFlag::empty(),
2099             None,
2100         )
2101         .expect("send socket failed");
2102         sendmsg(send, &iov, &[], MsgFlags::empty(), Some(&sa))
2103             .expect("sendmsg failed");
2104     }
2105 
2106     {
2107         let mut buf = [0u8; 8];
2108         let mut iovec = [IoSliceMut::new(&mut buf)];
2109 
2110         let mut space = cmsg_space!(libc::in6_pktinfo);
2111         let msg = recvmsg::<()>(
2112             receive,
2113             &mut iovec,
2114             Some(&mut space),
2115             MsgFlags::empty(),
2116         )
2117         .expect("recvmsg failed");
2118         assert!(!msg
2119             .flags
2120             .intersects(MsgFlags::MSG_TRUNC | MsgFlags::MSG_CTRUNC));
2121 
2122         let mut cmsgs = msg.cmsgs();
2123         if let Some(ControlMessageOwned::Ipv6PacketInfo(pktinfo)) = cmsgs.next()
2124         {
2125             let i = if_nametoindex(lo_name.as_bytes()).expect("if_nametoindex");
2126             assert_eq!(
2127                 pktinfo.ipi6_ifindex as libc::c_uint, i,
2128                 "unexpected ifindex (expected {}, got {})",
2129                 i, pktinfo.ipi6_ifindex
2130             );
2131         }
2132         assert!(cmsgs.next().is_none(), "unexpected additional control msg");
2133         assert_eq!(msg.bytes, 8);
2134         assert_eq!(*iovec[0], [1u8, 2, 3, 4, 5, 6, 7, 8]);
2135     }
2136 }
2137 
2138 #[cfg(any(target_os = "android", target_os = "linux"))]
2139 #[cfg_attr(graviton, ignore = "Not supported by the CI environment")]
2140 #[test]
test_vsock()2141 pub fn test_vsock() {
2142     use nix::errno::Errno;
2143     use nix::sys::socket::{
2144         bind, connect, listen, socket, AddressFamily, SockFlag, SockType,
2145         VsockAddr,
2146     };
2147     use nix::unistd::close;
2148     use std::thread;
2149 
2150     let port: u32 = 3000;
2151 
2152     let s1 = socket(
2153         AddressFamily::Vsock,
2154         SockType::Stream,
2155         SockFlag::empty(),
2156         None,
2157     )
2158     .expect("socket failed");
2159 
2160     // VMADDR_CID_HYPERVISOR is reserved, so we expect an EADDRNOTAVAIL error.
2161     let sockaddr_hv = VsockAddr::new(libc::VMADDR_CID_HYPERVISOR, port);
2162     assert_eq!(bind(s1, &sockaddr_hv).err(), Some(Errno::EADDRNOTAVAIL));
2163 
2164     let sockaddr_any = VsockAddr::new(libc::VMADDR_CID_ANY, port);
2165     assert_eq!(bind(s1, &sockaddr_any), Ok(()));
2166     listen(s1, 10).expect("listen failed");
2167 
2168     let thr = thread::spawn(move || {
2169         let cid: u32 = libc::VMADDR_CID_HOST;
2170 
2171         let s2 = socket(
2172             AddressFamily::Vsock,
2173             SockType::Stream,
2174             SockFlag::empty(),
2175             None,
2176         )
2177         .expect("socket failed");
2178 
2179         let sockaddr_host = VsockAddr::new(cid, port);
2180 
2181         // The current implementation does not support loopback devices, so,
2182         // for now, we expect a failure on the connect.
2183         assert_ne!(connect(s2, &sockaddr_host), Ok(()));
2184 
2185         close(s2).unwrap();
2186     });
2187 
2188     close(s1).unwrap();
2189     thr.join().unwrap();
2190 }
2191 
2192 // Disable the test on emulated platforms because it fails in Cirrus-CI.  Lack
2193 // of QEMU support is suspected.
2194 #[cfg_attr(qemu, ignore)]
2195 #[cfg(all(target_os = "linux"))]
2196 #[test]
test_recvmsg_timestampns()2197 fn test_recvmsg_timestampns() {
2198     use nix::sys::socket::*;
2199     use nix::sys::time::*;
2200     use std::io::{IoSlice, IoSliceMut};
2201     use std::time::*;
2202 
2203     // Set up
2204     let message = "Ohayō!".as_bytes();
2205     let in_socket = socket(
2206         AddressFamily::Inet,
2207         SockType::Datagram,
2208         SockFlag::empty(),
2209         None,
2210     )
2211     .unwrap();
2212     setsockopt(in_socket, sockopt::ReceiveTimestampns, &true).unwrap();
2213     let localhost = SockaddrIn::new(127, 0, 0, 1, 0);
2214     bind(in_socket, &localhost).unwrap();
2215     let address: SockaddrIn = getsockname(in_socket).unwrap();
2216     // Get initial time
2217     let time0 = SystemTime::now();
2218     // Send the message
2219     let iov = [IoSlice::new(message)];
2220     let flags = MsgFlags::empty();
2221     let l = sendmsg(in_socket, &iov, &[], flags, Some(&address)).unwrap();
2222     assert_eq!(message.len(), l);
2223     // Receive the message
2224     let mut buffer = vec![0u8; message.len()];
2225     let mut cmsgspace = nix::cmsg_space!(TimeSpec);
2226 
2227     let mut iov = [IoSliceMut::new(&mut buffer)];
2228     let r = recvmsg::<()>(in_socket, &mut iov, Some(&mut cmsgspace), flags)
2229         .unwrap();
2230     let rtime = match r.cmsgs().next() {
2231         Some(ControlMessageOwned::ScmTimestampns(rtime)) => rtime,
2232         Some(_) => panic!("Unexpected control message"),
2233         None => panic!("No control message"),
2234     };
2235     // Check the final time
2236     let time1 = SystemTime::now();
2237     // the packet's received timestamp should lie in-between the two system
2238     // times, unless the system clock was adjusted in the meantime.
2239     let rduration =
2240         Duration::new(rtime.tv_sec() as u64, rtime.tv_nsec() as u32);
2241     assert!(time0.duration_since(UNIX_EPOCH).unwrap() <= rduration);
2242     assert!(rduration <= time1.duration_since(UNIX_EPOCH).unwrap());
2243     // Close socket
2244     nix::unistd::close(in_socket).unwrap();
2245 }
2246 
2247 // Disable the test on emulated platforms because it fails in Cirrus-CI.  Lack
2248 // of QEMU support is suspected.
2249 #[cfg_attr(qemu, ignore)]
2250 #[cfg(all(target_os = "linux"))]
2251 #[test]
test_recvmmsg_timestampns()2252 fn test_recvmmsg_timestampns() {
2253     use nix::sys::socket::*;
2254     use nix::sys::time::*;
2255     use std::io::{IoSlice, IoSliceMut};
2256     use std::time::*;
2257 
2258     // Set up
2259     let message = "Ohayō!".as_bytes();
2260     let in_socket = socket(
2261         AddressFamily::Inet,
2262         SockType::Datagram,
2263         SockFlag::empty(),
2264         None,
2265     )
2266     .unwrap();
2267     setsockopt(in_socket, sockopt::ReceiveTimestampns, &true).unwrap();
2268     let localhost = SockaddrIn::from_str("127.0.0.1:0").unwrap();
2269     bind(in_socket, &localhost).unwrap();
2270     let address: SockaddrIn = getsockname(in_socket).unwrap();
2271     // Get initial time
2272     let time0 = SystemTime::now();
2273     // Send the message
2274     let iov = [IoSlice::new(message)];
2275     let flags = MsgFlags::empty();
2276     let l = sendmsg(in_socket, &iov, &[], flags, Some(&address)).unwrap();
2277     assert_eq!(message.len(), l);
2278     // Receive the message
2279     let mut buffer = vec![0u8; message.len()];
2280     let cmsgspace = nix::cmsg_space!(TimeSpec);
2281     let iov = vec![[IoSliceMut::new(&mut buffer)]];
2282     let mut data = MultiHeaders::preallocate(1, Some(cmsgspace));
2283     let r: Vec<RecvMsg<()>> =
2284         recvmmsg(in_socket, &mut data, iov.iter(), flags, None)
2285             .unwrap()
2286             .collect();
2287     let rtime = match r[0].cmsgs().next() {
2288         Some(ControlMessageOwned::ScmTimestampns(rtime)) => rtime,
2289         Some(_) => panic!("Unexpected control message"),
2290         None => panic!("No control message"),
2291     };
2292     // Check the final time
2293     let time1 = SystemTime::now();
2294     // the packet's received timestamp should lie in-between the two system
2295     // times, unless the system clock was adjusted in the meantime.
2296     let rduration =
2297         Duration::new(rtime.tv_sec() as u64, rtime.tv_nsec() as u32);
2298     assert!(time0.duration_since(UNIX_EPOCH).unwrap() <= rduration);
2299     assert!(rduration <= time1.duration_since(UNIX_EPOCH).unwrap());
2300     // Close socket
2301     nix::unistd::close(in_socket).unwrap();
2302 }
2303 
2304 // Disable the test on emulated platforms because it fails in Cirrus-CI.  Lack
2305 // of QEMU support is suspected.
2306 #[cfg_attr(qemu, ignore)]
2307 #[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
2308 #[test]
test_recvmsg_rxq_ovfl()2309 fn test_recvmsg_rxq_ovfl() {
2310     use nix::sys::socket::sockopt::{RcvBuf, RxqOvfl};
2311     use nix::sys::socket::*;
2312     use nix::Error;
2313     use std::io::{IoSlice, IoSliceMut};
2314 
2315     let message = [0u8; 2048];
2316     let bufsize = message.len() * 2;
2317 
2318     let in_socket = socket(
2319         AddressFamily::Inet,
2320         SockType::Datagram,
2321         SockFlag::empty(),
2322         None,
2323     )
2324     .unwrap();
2325     let out_socket = socket(
2326         AddressFamily::Inet,
2327         SockType::Datagram,
2328         SockFlag::empty(),
2329         None,
2330     )
2331     .unwrap();
2332 
2333     let localhost = SockaddrIn::from_str("127.0.0.1:0").unwrap();
2334     bind(in_socket, &localhost).unwrap();
2335 
2336     let address: SockaddrIn = getsockname(in_socket).unwrap();
2337     connect(out_socket, &address).unwrap();
2338 
2339     // Set SO_RXQ_OVFL flag.
2340     setsockopt(in_socket, RxqOvfl, &1).unwrap();
2341 
2342     // Set the receiver buffer size to hold only 2 messages.
2343     setsockopt(in_socket, RcvBuf, &bufsize).unwrap();
2344 
2345     let mut drop_counter = 0;
2346 
2347     for _ in 0..2 {
2348         let iov = [IoSlice::new(&message)];
2349         let flags = MsgFlags::empty();
2350 
2351         // Send the 3 messages (the receiver buffer can only hold 2 messages)
2352         // to create an overflow.
2353         for _ in 0..3 {
2354             let l =
2355                 sendmsg(out_socket, &iov, &[], flags, Some(&address)).unwrap();
2356             assert_eq!(message.len(), l);
2357         }
2358 
2359         // Receive the message and check the drop counter if any.
2360         loop {
2361             let mut buffer = vec![0u8; message.len()];
2362             let mut cmsgspace = nix::cmsg_space!(u32);
2363 
2364             let mut iov = [IoSliceMut::new(&mut buffer)];
2365 
2366             match recvmsg::<()>(
2367                 in_socket,
2368                 &mut iov,
2369                 Some(&mut cmsgspace),
2370                 MsgFlags::MSG_DONTWAIT,
2371             ) {
2372                 Ok(r) => {
2373                     drop_counter = match r.cmsgs().next() {
2374                         Some(ControlMessageOwned::RxqOvfl(drop_counter)) => {
2375                             drop_counter
2376                         }
2377                         Some(_) => panic!("Unexpected control message"),
2378                         None => 0,
2379                     };
2380                 }
2381                 Err(Error::EAGAIN) => {
2382                     break;
2383                 }
2384                 _ => {
2385                     panic!("unknown recvmsg() error");
2386                 }
2387             }
2388         }
2389     }
2390 
2391     // One packet lost.
2392     assert_eq!(drop_counter, 1);
2393 
2394     // Close sockets
2395     nix::unistd::close(in_socket).unwrap();
2396     nix::unistd::close(out_socket).unwrap();
2397 }
2398 
2399 #[cfg(any(target_os = "linux", target_os = "android",))]
2400 mod linux_errqueue {
2401     use super::FromStr;
2402     use nix::sys::socket::*;
2403 
2404     // Send a UDP datagram to a bogus destination address and observe an ICMP error (v4).
2405     //
2406     // Disable the test on QEMU because QEMU emulation of IP_RECVERR is broken (as documented on PR
2407     // #1514).
2408     #[cfg_attr(qemu, ignore)]
2409     #[test]
test_recverr_v4()2410     fn test_recverr_v4() {
2411         #[repr(u8)]
2412         enum IcmpTypes {
2413             DestUnreach = 3, // ICMP_DEST_UNREACH
2414         }
2415         #[repr(u8)]
2416         enum IcmpUnreachCodes {
2417             PortUnreach = 3, // ICMP_PORT_UNREACH
2418         }
2419 
2420         test_recverr_impl::<sockaddr_in, _, _>(
2421             "127.0.0.1:6800",
2422             AddressFamily::Inet,
2423             sockopt::Ipv4RecvErr,
2424             libc::SO_EE_ORIGIN_ICMP,
2425             IcmpTypes::DestUnreach as u8,
2426             IcmpUnreachCodes::PortUnreach as u8,
2427             // Closure handles protocol-specific testing and returns generic sock_extended_err for
2428             // protocol-independent test impl.
2429             |cmsg| {
2430                 if let ControlMessageOwned::Ipv4RecvErr(ext_err, err_addr) =
2431                     cmsg
2432                 {
2433                     if let Some(origin) = err_addr {
2434                         // Validate that our network error originated from 127.0.0.1:0.
2435                         assert_eq!(origin.sin_family, AddressFamily::Inet as _);
2436                         assert_eq!(
2437                             origin.sin_addr.s_addr,
2438                             u32::from_be(0x7f000001)
2439                         );
2440                         assert_eq!(origin.sin_port, 0);
2441                     } else {
2442                         panic!("Expected some error origin");
2443                     }
2444                     *ext_err
2445                 } else {
2446                     panic!("Unexpected control message {:?}", cmsg);
2447                 }
2448             },
2449         )
2450     }
2451 
2452     // Essentially the same test as v4.
2453     //
2454     // Disable the test on QEMU because QEMU emulation of IPV6_RECVERR is broken (as documented on
2455     // PR #1514).
2456     #[cfg_attr(qemu, ignore)]
2457     #[test]
test_recverr_v6()2458     fn test_recverr_v6() {
2459         #[repr(u8)]
2460         enum IcmpV6Types {
2461             DestUnreach = 1, // ICMPV6_DEST_UNREACH
2462         }
2463         #[repr(u8)]
2464         enum IcmpV6UnreachCodes {
2465             PortUnreach = 4, // ICMPV6_PORT_UNREACH
2466         }
2467 
2468         test_recverr_impl::<sockaddr_in6, _, _>(
2469             "[::1]:6801",
2470             AddressFamily::Inet6,
2471             sockopt::Ipv6RecvErr,
2472             libc::SO_EE_ORIGIN_ICMP6,
2473             IcmpV6Types::DestUnreach as u8,
2474             IcmpV6UnreachCodes::PortUnreach as u8,
2475             // Closure handles protocol-specific testing and returns generic sock_extended_err for
2476             // protocol-independent test impl.
2477             |cmsg| {
2478                 if let ControlMessageOwned::Ipv6RecvErr(ext_err, err_addr) =
2479                     cmsg
2480                 {
2481                     if let Some(origin) = err_addr {
2482                         // Validate that our network error originated from localhost:0.
2483                         assert_eq!(
2484                             origin.sin6_family,
2485                             AddressFamily::Inet6 as _
2486                         );
2487                         assert_eq!(
2488                             origin.sin6_addr.s6_addr,
2489                             std::net::Ipv6Addr::LOCALHOST.octets()
2490                         );
2491                         assert_eq!(origin.sin6_port, 0);
2492                     } else {
2493                         panic!("Expected some error origin");
2494                     }
2495                     *ext_err
2496                 } else {
2497                     panic!("Unexpected control message {:?}", cmsg);
2498                 }
2499             },
2500         )
2501     }
2502 
test_recverr_impl<SA, OPT, TESTF>( sa: &str, af: AddressFamily, opt: OPT, ee_origin: u8, ee_type: u8, ee_code: u8, testf: TESTF, ) where OPT: SetSockOpt<Val = bool>, TESTF: FnOnce(&ControlMessageOwned) -> libc::sock_extended_err,2503     fn test_recverr_impl<SA, OPT, TESTF>(
2504         sa: &str,
2505         af: AddressFamily,
2506         opt: OPT,
2507         ee_origin: u8,
2508         ee_type: u8,
2509         ee_code: u8,
2510         testf: TESTF,
2511     ) where
2512         OPT: SetSockOpt<Val = bool>,
2513         TESTF: FnOnce(&ControlMessageOwned) -> libc::sock_extended_err,
2514     {
2515         use nix::errno::Errno;
2516         use std::io::IoSliceMut;
2517 
2518         const MESSAGE_CONTENTS: &str = "ABCDEF";
2519         let std_sa = std::net::SocketAddr::from_str(sa).unwrap();
2520         let sock_addr = SockaddrStorage::from(std_sa);
2521         let sock = socket(af, SockType::Datagram, SockFlag::SOCK_CLOEXEC, None)
2522             .unwrap();
2523         setsockopt(sock, opt, &true).unwrap();
2524         if let Err(e) = sendto(
2525             sock,
2526             MESSAGE_CONTENTS.as_bytes(),
2527             &sock_addr,
2528             MsgFlags::empty(),
2529         ) {
2530             assert_eq!(e, Errno::EADDRNOTAVAIL);
2531             println!("{:?} not available, skipping test.", af);
2532             return;
2533         }
2534 
2535         let mut buf = [0u8; 8];
2536         let mut iovec = [IoSliceMut::new(&mut buf)];
2537         let mut cspace = cmsg_space!(libc::sock_extended_err, SA);
2538 
2539         let msg = recvmsg(
2540             sock,
2541             &mut iovec,
2542             Some(&mut cspace),
2543             MsgFlags::MSG_ERRQUEUE,
2544         )
2545         .unwrap();
2546         // The sent message / destination associated with the error is returned:
2547         assert_eq!(msg.bytes, MESSAGE_CONTENTS.as_bytes().len());
2548         // recvmsg(2): "The original destination address of the datagram that caused the error is
2549         // supplied via msg_name;" however, this is not literally true.  E.g., an earlier version
2550         // of this test used 0.0.0.0 (::0) as the destination address, which was mutated into
2551         // 127.0.0.1 (::1).
2552         assert_eq!(msg.address, Some(sock_addr));
2553 
2554         // Check for expected control message.
2555         let ext_err = match msg.cmsgs().next() {
2556             Some(cmsg) => testf(&cmsg),
2557             None => panic!("No control message"),
2558         };
2559 
2560         assert_eq!(ext_err.ee_errno, libc::ECONNREFUSED as u32);
2561         assert_eq!(ext_err.ee_origin, ee_origin);
2562         // ip(7): ee_type and ee_code are set from the type and code fields of the ICMP (ICMPv6)
2563         // header.
2564         assert_eq!(ext_err.ee_type, ee_type);
2565         assert_eq!(ext_err.ee_code, ee_code);
2566         // ip(7): ee_info contains the discovered MTU for EMSGSIZE errors.
2567         assert_eq!(ext_err.ee_info, 0);
2568 
2569         let bytes = msg.bytes;
2570         assert_eq!(&buf[..bytes], MESSAGE_CONTENTS.as_bytes());
2571     }
2572 }
2573 
2574 // Disable the test on emulated platforms because it fails in Cirrus-CI.  Lack
2575 // of QEMU support is suspected.
2576 #[cfg_attr(qemu, ignore)]
2577 #[cfg(target_os = "linux")]
2578 #[test]
test_txtime()2579 pub fn test_txtime() {
2580     use nix::sys::socket::{
2581         bind, recvmsg, sendmsg, setsockopt, socket, sockopt, ControlMessage,
2582         MsgFlags, SockFlag, SockType, SockaddrIn,
2583     };
2584     use nix::sys::time::TimeValLike;
2585     use nix::time::{clock_gettime, ClockId};
2586 
2587     require_kernel_version!(test_txtime, ">= 5.8");
2588 
2589     let sock_addr = SockaddrIn::from_str("127.0.0.1:6802").unwrap();
2590 
2591     let ssock = socket(
2592         AddressFamily::Inet,
2593         SockType::Datagram,
2594         SockFlag::empty(),
2595         None,
2596     )
2597     .expect("send socket failed");
2598 
2599     let txtime_cfg = libc::sock_txtime {
2600         clockid: libc::CLOCK_MONOTONIC,
2601         flags: 0,
2602     };
2603     setsockopt(ssock, sockopt::TxTime, &txtime_cfg).unwrap();
2604 
2605     let rsock = socket(
2606         AddressFamily::Inet,
2607         SockType::Datagram,
2608         SockFlag::empty(),
2609         None,
2610     )
2611     .unwrap();
2612     bind(rsock, &sock_addr).unwrap();
2613 
2614     let sbuf = [0u8; 2048];
2615     let iov1 = [std::io::IoSlice::new(&sbuf)];
2616 
2617     let now = clock_gettime(ClockId::CLOCK_MONOTONIC).unwrap();
2618     let delay = std::time::Duration::from_secs(1).into();
2619     let txtime = (now + delay).num_nanoseconds() as u64;
2620 
2621     let cmsg = ControlMessage::TxTime(&txtime);
2622     sendmsg(ssock, &iov1, &[cmsg], MsgFlags::empty(), Some(&sock_addr))
2623         .unwrap();
2624 
2625     let mut rbuf = [0u8; 2048];
2626     let mut iov2 = [std::io::IoSliceMut::new(&mut rbuf)];
2627     recvmsg::<()>(rsock, &mut iov2, None, MsgFlags::empty()).unwrap();
2628 }
2629