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