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