• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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().unwrap() {
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().unwrap() {
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().unwrap() {
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().unwrap() {
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().unwrap();
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().unwrap().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().unwrap() {
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).unwrap();
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).unwrap();
1513 }
1514 
1515 #[cfg(linux_android)]
1516 #[test]
test_too_small_cmsgspace()1517 fn test_too_small_cmsgspace() {
1518     let space = vec![0u8; 4];
1519     assert_eq!(
1520         test_impl_scm_credentials_and_rights(space),
1521         Err(nix::errno::Errno::ENOBUFS)
1522     );
1523 }
1524 
1525 #[cfg(linux_android)]
test_impl_scm_credentials_and_rights( mut space: Vec<u8>, ) -> Result<(), nix::errno::Errno>1526 fn test_impl_scm_credentials_and_rights(
1527     mut space: Vec<u8>,
1528 ) -> Result<(), nix::errno::Errno> {
1529     use libc::ucred;
1530     use nix::sys::socket::sockopt::PassCred;
1531     use nix::sys::socket::{
1532         recvmsg, sendmsg, setsockopt, socketpair, ControlMessage,
1533         ControlMessageOwned, MsgFlags, SockFlag, SockType,
1534     };
1535     use nix::unistd::{close, getgid, getpid, getuid, pipe, write};
1536     use std::io::{IoSlice, IoSliceMut};
1537 
1538     let (send, recv) = socketpair(
1539         AddressFamily::Unix,
1540         SockType::Stream,
1541         None,
1542         SockFlag::empty(),
1543     )
1544     .unwrap();
1545     setsockopt(&recv, PassCred, &true).unwrap();
1546 
1547     let (r, w) = pipe().unwrap();
1548     let mut received_r: Option<RawFd> = None;
1549 
1550     {
1551         let iov = [IoSlice::new(b"hello")];
1552         let cred = ucred {
1553             pid: getpid().as_raw(),
1554             uid: getuid().as_raw(),
1555             gid: getgid().as_raw(),
1556         }
1557         .into();
1558         let fds = [r.as_raw_fd()];
1559         let cmsgs = [
1560             ControlMessage::ScmCredentials(&cred),
1561             ControlMessage::ScmRights(&fds),
1562         ];
1563         assert_eq!(
1564             sendmsg::<()>(
1565                 send.as_raw_fd(),
1566                 &iov,
1567                 &cmsgs,
1568                 MsgFlags::empty(),
1569                 None
1570             )
1571             .unwrap(),
1572             5
1573         );
1574     }
1575 
1576     {
1577         let mut buf = [0u8; 5];
1578         let mut iov = [IoSliceMut::new(&mut buf[..])];
1579         let msg = recvmsg::<()>(
1580             recv.as_raw_fd(),
1581             &mut iov,
1582             Some(&mut space),
1583             MsgFlags::empty(),
1584         )
1585         .unwrap();
1586         let mut received_cred = None;
1587 
1588         assert_eq!(msg.cmsgs()?.count(), 2, "expected 2 cmsgs");
1589 
1590         for cmsg in msg.cmsgs()? {
1591             match cmsg {
1592                 ControlMessageOwned::ScmRights(fds) => {
1593                     assert_eq!(received_r, None, "already received fd");
1594                     assert_eq!(fds.len(), 1);
1595                     received_r = Some(fds[0]);
1596                 }
1597                 ControlMessageOwned::ScmCredentials(cred) => {
1598                     assert!(received_cred.is_none());
1599                     assert_eq!(cred.pid(), getpid().as_raw());
1600                     assert_eq!(cred.uid(), getuid().as_raw());
1601                     assert_eq!(cred.gid(), getgid().as_raw());
1602                     received_cred = Some(cred);
1603                 }
1604                 _ => panic!("unexpected cmsg"),
1605             }
1606         }
1607         received_cred.expect("no creds received");
1608         assert_eq!(msg.bytes, 5);
1609         assert!(!msg
1610             .flags
1611             .intersects(MsgFlags::MSG_TRUNC | MsgFlags::MSG_CTRUNC));
1612     }
1613 
1614     let received_r = received_r.expect("Did not receive passed fd");
1615     // Ensure that the received file descriptor works
1616     write(&w, b"world").unwrap();
1617     let mut buf = [0u8; 5];
1618     read(received_r.as_raw_fd(), &mut buf).unwrap();
1619     assert_eq!(&buf[..], b"world");
1620     close(received_r).unwrap();
1621 
1622     Ok(())
1623 }
1624 
1625 // Test creating and using named unix domain sockets
1626 #[test]
test_named_unixdomain()1627 pub fn test_named_unixdomain() {
1628     use nix::sys::socket::{
1629         accept, bind, connect, listen, socket, Backlog, UnixAddr,
1630     };
1631     use nix::sys::socket::{SockFlag, SockType};
1632     use nix::unistd::{read, write};
1633     use std::thread;
1634 
1635     let tempdir = tempfile::tempdir().unwrap();
1636     let sockname = tempdir.path().join("sock");
1637     let s1 = socket(
1638         AddressFamily::Unix,
1639         SockType::Stream,
1640         SockFlag::empty(),
1641         None,
1642     )
1643     .expect("socket failed");
1644     let sockaddr = UnixAddr::new(&sockname).unwrap();
1645     bind(s1.as_raw_fd(), &sockaddr).expect("bind failed");
1646     listen(&s1, Backlog::new(10).unwrap()).expect("listen failed");
1647 
1648     let thr = thread::spawn(move || {
1649         let s2 = socket(
1650             AddressFamily::Unix,
1651             SockType::Stream,
1652             SockFlag::empty(),
1653             None,
1654         )
1655         .expect("socket failed");
1656         connect(s2.as_raw_fd(), &sockaddr).expect("connect failed");
1657         write(&s2, b"hello").expect("write failed");
1658     });
1659 
1660     let s3 = accept(s1.as_raw_fd()).expect("accept failed");
1661 
1662     let mut buf = [0; 5];
1663     read(s3.as_raw_fd(), &mut buf).unwrap();
1664     thr.join().unwrap();
1665 
1666     assert_eq!(&buf[..], b"hello");
1667 }
1668 
1669 #[test]
test_listen_wrongbacklog()1670 pub fn test_listen_wrongbacklog() {
1671     use nix::sys::socket::Backlog;
1672 
1673     assert!(Backlog::new(libc::SOMAXCONN + 1).is_err());
1674     assert!(Backlog::new(-2).is_err());
1675 }
1676 
1677 // Test using unnamed unix domain addresses
1678 #[cfg(linux_android)]
1679 #[test]
test_unnamed_unixdomain()1680 pub fn test_unnamed_unixdomain() {
1681     use nix::sys::socket::{getsockname, socketpair};
1682     use nix::sys::socket::{SockFlag, SockType};
1683 
1684     let (fd_1, _fd_2) = socketpair(
1685         AddressFamily::Unix,
1686         SockType::Stream,
1687         None,
1688         SockFlag::empty(),
1689     )
1690     .expect("socketpair failed");
1691 
1692     let addr_1: UnixAddr =
1693         getsockname(fd_1.as_raw_fd()).expect("getsockname failed");
1694     assert!(addr_1.is_unnamed());
1695 }
1696 
1697 // Test creating and using unnamed unix domain addresses for autobinding sockets
1698 #[cfg(linux_android)]
1699 #[test]
test_unnamed_unixdomain_autobind()1700 pub fn test_unnamed_unixdomain_autobind() {
1701     use nix::sys::socket::{bind, getsockname, socket};
1702     use nix::sys::socket::{SockFlag, SockType};
1703 
1704     let fd = socket(
1705         AddressFamily::Unix,
1706         SockType::Stream,
1707         SockFlag::empty(),
1708         None,
1709     )
1710     .expect("socket failed");
1711 
1712     // unix(7): "If a bind(2) call specifies addrlen as `sizeof(sa_family_t)`, or [...], then the
1713     // socket is autobound to an abstract address"
1714     bind(fd.as_raw_fd(), &UnixAddr::new_unnamed()).expect("bind failed");
1715 
1716     let addr: UnixAddr =
1717         getsockname(fd.as_raw_fd()).expect("getsockname failed");
1718     let addr = addr.as_abstract().unwrap();
1719 
1720     // changed from 8 to 5 bytes in Linux 2.3.15, and rust's minimum supported Linux version is 3.2
1721     // (as of 2022-11)
1722     assert_eq!(addr.len(), 5);
1723 }
1724 
1725 // Test creating and using named system control sockets
1726 #[cfg(apple_targets)]
1727 #[test]
test_syscontrol()1728 pub fn test_syscontrol() {
1729     use nix::errno::Errno;
1730     use nix::sys::socket::{
1731         socket, SockFlag, SockProtocol, SockType, SysControlAddr,
1732     };
1733 
1734     let fd = socket(
1735         AddressFamily::System,
1736         SockType::Datagram,
1737         SockFlag::empty(),
1738         SockProtocol::KextControl,
1739     )
1740     .expect("socket failed");
1741     SysControlAddr::from_name(fd.as_raw_fd(), "com.apple.net.utun_control", 0)
1742         .expect("resolving sys_control name failed");
1743     assert_eq!(
1744         SysControlAddr::from_name(fd.as_raw_fd(), "foo.bar.lol", 0).err(),
1745         Some(Errno::ENOENT)
1746     );
1747 
1748     // requires root privileges
1749     // connect(fd.as_raw_fd(), &sockaddr).expect("connect failed");
1750 }
1751 
1752 #[cfg(any(bsd, linux_android))]
loopback_address( family: AddressFamily, ) -> Option<nix::ifaddrs::InterfaceAddress>1753 fn loopback_address(
1754     family: AddressFamily,
1755 ) -> Option<nix::ifaddrs::InterfaceAddress> {
1756     use nix::ifaddrs::getifaddrs;
1757     use nix::net::if_::*;
1758     use nix::sys::socket::SockaddrLike;
1759     use std::io;
1760     use std::io::Write;
1761 
1762     let mut addrs = match getifaddrs() {
1763         Ok(iter) => iter,
1764         Err(e) => {
1765             let stdioerr = io::stderr();
1766             let mut handle = stdioerr.lock();
1767             writeln!(handle, "getifaddrs: {e:?}").unwrap();
1768             return None;
1769         }
1770     };
1771     // return first address matching family
1772     addrs.find(|ifaddr| {
1773         ifaddr.flags.contains(InterfaceFlags::IFF_LOOPBACK)
1774             && ifaddr.address.as_ref().and_then(SockaddrLike::family)
1775                 == Some(family)
1776     })
1777 }
1778 
1779 #[cfg(any(linux_android, apple_targets, target_os = "netbsd"))]
1780 // qemu doesn't seem to be emulating this correctly in these architectures
1781 #[cfg_attr(
1782     all(
1783         qemu,
1784         any(
1785             target_arch = "mips",
1786             target_arch = "mips32r6",
1787             target_arch = "mips64",
1788             target_arch = "mips64r6",
1789             target_arch = "powerpc64",
1790         )
1791     ),
1792     ignore
1793 )]
1794 #[test]
test_recv_ipv4pktinfo()1795 pub fn test_recv_ipv4pktinfo() {
1796     use nix::net::if_::*;
1797     use nix::sys::socket::sockopt::Ipv4PacketInfo;
1798     use nix::sys::socket::{bind, SockFlag, SockType, SockaddrIn};
1799     use nix::sys::socket::{getsockname, setsockopt, socket};
1800     use nix::sys::socket::{recvmsg, sendmsg, ControlMessageOwned, MsgFlags};
1801     use std::io::{IoSlice, IoSliceMut};
1802 
1803     let lo_ifaddr = loopback_address(AddressFamily::Inet);
1804     let (lo_name, lo) = match lo_ifaddr {
1805         Some(ifaddr) => (
1806             ifaddr.interface_name,
1807             ifaddr.address.expect("Expect IPv4 address on interface"),
1808         ),
1809         None => return,
1810     };
1811     let receive = socket(
1812         AddressFamily::Inet,
1813         SockType::Datagram,
1814         SockFlag::empty(),
1815         None,
1816     )
1817     .expect("receive socket failed");
1818     bind(receive.as_raw_fd(), &lo).expect("bind failed");
1819     let sa: SockaddrIn =
1820         getsockname(receive.as_raw_fd()).expect("getsockname failed");
1821     setsockopt(&receive, Ipv4PacketInfo, &true).expect("setsockopt failed");
1822 
1823     {
1824         let slice = [1u8, 2, 3, 4, 5, 6, 7, 8];
1825         let iov = [IoSlice::new(&slice)];
1826 
1827         let send = socket(
1828             AddressFamily::Inet,
1829             SockType::Datagram,
1830             SockFlag::empty(),
1831             None,
1832         )
1833         .expect("send socket failed");
1834         sendmsg(send.as_raw_fd(), &iov, &[], MsgFlags::empty(), Some(&sa))
1835             .expect("sendmsg failed");
1836     }
1837 
1838     {
1839         let mut buf = [0u8; 8];
1840         let mut iovec = [IoSliceMut::new(&mut buf)];
1841 
1842         let mut space = cmsg_space!(libc::in_pktinfo);
1843         let msg = recvmsg::<()>(
1844             receive.as_raw_fd(),
1845             &mut iovec,
1846             Some(&mut space),
1847             MsgFlags::empty(),
1848         )
1849         .expect("recvmsg failed");
1850         assert!(!msg
1851             .flags
1852             .intersects(MsgFlags::MSG_TRUNC | MsgFlags::MSG_CTRUNC));
1853 
1854         let mut cmsgs = msg.cmsgs().unwrap();
1855         if let Some(ControlMessageOwned::Ipv4PacketInfo(pktinfo)) = cmsgs.next()
1856         {
1857             let i = if_nametoindex(lo_name.as_bytes()).expect("if_nametoindex");
1858             assert_eq!(
1859                 pktinfo.ipi_ifindex as libc::c_uint, i,
1860                 "unexpected ifindex (expected {}, got {})",
1861                 i, pktinfo.ipi_ifindex
1862             );
1863         }
1864         assert!(cmsgs.next().is_none(), "unexpected additional control msg");
1865         assert_eq!(msg.bytes, 8);
1866         assert_eq!(*iovec[0], [1u8, 2, 3, 4, 5, 6, 7, 8]);
1867     }
1868 }
1869 
1870 #[cfg(bsd)]
1871 // qemu doesn't seem to be emulating this correctly in these architectures
1872 #[cfg_attr(
1873     all(
1874         qemu,
1875         any(
1876             target_arch = "mips",
1877             target_arch = "mips32r6",
1878             target_arch = "mips64",
1879             target_arch = "mips64r6",
1880             target_arch = "powerpc64",
1881         )
1882     ),
1883     ignore
1884 )]
1885 #[test]
test_recvif()1886 pub fn test_recvif() {
1887     use nix::net::if_::*;
1888     use nix::sys::socket::sockopt::{Ipv4RecvDstAddr, Ipv4RecvIf};
1889     use nix::sys::socket::{bind, SockFlag, SockType, SockaddrIn};
1890     use nix::sys::socket::{getsockname, setsockopt, socket};
1891     use nix::sys::socket::{recvmsg, sendmsg, ControlMessageOwned, MsgFlags};
1892     use std::io::{IoSlice, IoSliceMut};
1893 
1894     let lo_ifaddr = loopback_address(AddressFamily::Inet);
1895     let (lo_name, lo) = match lo_ifaddr {
1896         Some(ifaddr) => (
1897             ifaddr.interface_name,
1898             ifaddr.address.expect("Expect IPv4 address on interface"),
1899         ),
1900         None => return,
1901     };
1902     let receive = socket(
1903         AddressFamily::Inet,
1904         SockType::Datagram,
1905         SockFlag::empty(),
1906         None,
1907     )
1908     .expect("receive socket failed");
1909     bind(receive.as_raw_fd(), &lo).expect("bind failed");
1910     let sa: SockaddrIn =
1911         getsockname(receive.as_raw_fd()).expect("getsockname failed");
1912     setsockopt(&receive, Ipv4RecvIf, &true)
1913         .expect("setsockopt IP_RECVIF failed");
1914     setsockopt(&receive, Ipv4RecvDstAddr, &true)
1915         .expect("setsockopt IP_RECVDSTADDR failed");
1916 
1917     {
1918         let slice = [1u8, 2, 3, 4, 5, 6, 7, 8];
1919         let iov = [IoSlice::new(&slice)];
1920 
1921         let send = socket(
1922             AddressFamily::Inet,
1923             SockType::Datagram,
1924             SockFlag::empty(),
1925             None,
1926         )
1927         .expect("send socket failed");
1928         sendmsg(send.as_raw_fd(), &iov, &[], MsgFlags::empty(), Some(&sa))
1929             .expect("sendmsg failed");
1930     }
1931 
1932     {
1933         let mut buf = [0u8; 8];
1934         let mut iovec = [IoSliceMut::new(&mut buf)];
1935         let mut space = cmsg_space!(libc::sockaddr_dl, libc::in_addr);
1936         let msg = recvmsg::<()>(
1937             receive.as_raw_fd(),
1938             &mut iovec,
1939             Some(&mut space),
1940             MsgFlags::empty(),
1941         )
1942         .expect("recvmsg failed");
1943         assert!(!msg
1944             .flags
1945             .intersects(MsgFlags::MSG_TRUNC | MsgFlags::MSG_CTRUNC));
1946         assert_eq!(msg.cmsgs().unwrap().count(), 2, "expected 2 cmsgs");
1947 
1948         let mut rx_recvif = false;
1949         let mut rx_recvdstaddr = false;
1950         for cmsg in msg.cmsgs().unwrap() {
1951             match cmsg {
1952                 ControlMessageOwned::Ipv4RecvIf(dl) => {
1953                     rx_recvif = true;
1954                     let i = if_nametoindex(lo_name.as_bytes())
1955                         .expect("if_nametoindex");
1956                     assert_eq!(
1957                         dl.sdl_index as libc::c_uint, i,
1958                         "unexpected ifindex (expected {}, got {})",
1959                         i, dl.sdl_index
1960                     );
1961                 }
1962                 ControlMessageOwned::Ipv4RecvDstAddr(addr) => {
1963                     rx_recvdstaddr = true;
1964                     if let Some(sin) = lo.as_sockaddr_in() {
1965                         assert_eq!(sin.as_ref().sin_addr.s_addr,
1966                                    addr.s_addr,
1967                                    "unexpected destination address (expected {}, got {})",
1968                                    sin.as_ref().sin_addr.s_addr,
1969                                    addr.s_addr);
1970                     } else {
1971                         panic!("unexpected Sockaddr");
1972                     }
1973                 }
1974                 _ => panic!("unexpected additional control msg"),
1975             }
1976         }
1977         assert!(rx_recvif);
1978         assert!(rx_recvdstaddr);
1979         assert_eq!(msg.bytes, 8);
1980         assert_eq!(*iovec[0], [1u8, 2, 3, 4, 5, 6, 7, 8]);
1981     }
1982 }
1983 
1984 #[cfg(any(linux_android, target_os = "freebsd"))]
1985 #[cfg_attr(qemu, ignore)]
1986 #[test]
test_recvif_ipv4()1987 pub fn test_recvif_ipv4() {
1988     use nix::sys::socket::sockopt::Ipv4OrigDstAddr;
1989     use nix::sys::socket::{bind, SockFlag, SockType, SockaddrIn};
1990     use nix::sys::socket::{getsockname, setsockopt, socket};
1991     use nix::sys::socket::{recvmsg, sendmsg, ControlMessageOwned, MsgFlags};
1992     use std::io::{IoSlice, IoSliceMut};
1993 
1994     let lo_ifaddr = loopback_address(AddressFamily::Inet);
1995     let (_lo_name, lo) = match lo_ifaddr {
1996         Some(ifaddr) => (
1997             ifaddr.interface_name,
1998             ifaddr.address.expect("Expect IPv4 address on interface"),
1999         ),
2000         None => return,
2001     };
2002     let receive = socket(
2003         AddressFamily::Inet,
2004         SockType::Datagram,
2005         SockFlag::empty(),
2006         None,
2007     )
2008     .expect("receive socket failed");
2009     bind(receive.as_raw_fd(), &lo).expect("bind failed");
2010     let sa: SockaddrIn =
2011         getsockname(receive.as_raw_fd()).expect("getsockname failed");
2012     setsockopt(&receive, Ipv4OrigDstAddr, &true)
2013         .expect("setsockopt IP_ORIGDSTADDR failed");
2014 
2015     {
2016         let slice = [1u8, 2, 3, 4, 5, 6, 7, 8];
2017         let iov = [IoSlice::new(&slice)];
2018 
2019         let send = socket(
2020             AddressFamily::Inet,
2021             SockType::Datagram,
2022             SockFlag::empty(),
2023             None,
2024         )
2025         .expect("send socket failed");
2026         sendmsg(send.as_raw_fd(), &iov, &[], MsgFlags::empty(), Some(&sa))
2027             .expect("sendmsg failed");
2028     }
2029 
2030     {
2031         let mut buf = [0u8; 8];
2032         let mut iovec = [IoSliceMut::new(&mut buf)];
2033         let mut space = cmsg_space!(libc::sockaddr_in);
2034         let msg = recvmsg::<()>(
2035             receive.as_raw_fd(),
2036             &mut iovec,
2037             Some(&mut space),
2038             MsgFlags::empty(),
2039         )
2040         .expect("recvmsg failed");
2041         assert!(!msg
2042             .flags
2043             .intersects(MsgFlags::MSG_TRUNC | MsgFlags::MSG_CTRUNC));
2044         assert_eq!(msg.cmsgs().unwrap().count(), 1, "expected 1 cmsgs");
2045 
2046         let mut rx_recvorigdstaddr = false;
2047         for cmsg in msg.cmsgs().unwrap() {
2048             match cmsg {
2049                 ControlMessageOwned::Ipv4OrigDstAddr(addr) => {
2050                     rx_recvorigdstaddr = true;
2051                     if let Some(sin) = lo.as_sockaddr_in() {
2052                         assert_eq!(sin.as_ref().sin_addr.s_addr,
2053                                    addr.sin_addr.s_addr,
2054                                    "unexpected destination address (expected {}, got {})",
2055                                    sin.as_ref().sin_addr.s_addr,
2056                                    addr.sin_addr.s_addr);
2057                     } else {
2058                         panic!("unexpected Sockaddr");
2059                     }
2060                 }
2061                 _ => panic!("unexpected additional control msg"),
2062             }
2063         }
2064         assert!(rx_recvorigdstaddr);
2065         assert_eq!(msg.bytes, 8);
2066         assert_eq!(*iovec[0], [1u8, 2, 3, 4, 5, 6, 7, 8]);
2067     }
2068 }
2069 
2070 #[cfg(any(linux_android, target_os = "freebsd"))]
2071 #[cfg_attr(qemu, ignore)]
2072 #[test]
test_recvif_ipv6()2073 pub fn test_recvif_ipv6() {
2074     use nix::sys::socket::sockopt::Ipv6OrigDstAddr;
2075     use nix::sys::socket::{bind, SockFlag, SockType, SockaddrIn6};
2076     use nix::sys::socket::{getsockname, setsockopt, socket};
2077     use nix::sys::socket::{recvmsg, sendmsg, ControlMessageOwned, MsgFlags};
2078     use std::io::{IoSlice, IoSliceMut};
2079 
2080     let lo_ifaddr = loopback_address(AddressFamily::Inet6);
2081     let (_lo_name, lo) = match lo_ifaddr {
2082         Some(ifaddr) => (
2083             ifaddr.interface_name,
2084             ifaddr.address.expect("Expect IPv6 address on interface"),
2085         ),
2086         None => return,
2087     };
2088     let receive = socket(
2089         AddressFamily::Inet6,
2090         SockType::Datagram,
2091         SockFlag::empty(),
2092         None,
2093     )
2094     .expect("receive socket failed");
2095     bind(receive.as_raw_fd(), &lo).expect("bind failed");
2096     let sa: SockaddrIn6 =
2097         getsockname(receive.as_raw_fd()).expect("getsockname failed");
2098     setsockopt(&receive, Ipv6OrigDstAddr, &true)
2099         .expect("setsockopt IP_ORIGDSTADDR failed");
2100 
2101     {
2102         let slice = [1u8, 2, 3, 4, 5, 6, 7, 8];
2103         let iov = [IoSlice::new(&slice)];
2104 
2105         let send = socket(
2106             AddressFamily::Inet6,
2107             SockType::Datagram,
2108             SockFlag::empty(),
2109             None,
2110         )
2111         .expect("send socket failed");
2112         sendmsg(send.as_raw_fd(), &iov, &[], MsgFlags::empty(), Some(&sa))
2113             .expect("sendmsg failed");
2114     }
2115 
2116     {
2117         let mut buf = [0u8; 8];
2118         let mut iovec = [IoSliceMut::new(&mut buf)];
2119         let mut space = cmsg_space!(libc::sockaddr_in6);
2120         let msg = recvmsg::<()>(
2121             receive.as_raw_fd(),
2122             &mut iovec,
2123             Some(&mut space),
2124             MsgFlags::empty(),
2125         )
2126         .expect("recvmsg failed");
2127         assert!(!msg
2128             .flags
2129             .intersects(MsgFlags::MSG_TRUNC | MsgFlags::MSG_CTRUNC));
2130         assert_eq!(msg.cmsgs().unwrap().count(), 1, "expected 1 cmsgs");
2131 
2132         let mut rx_recvorigdstaddr = false;
2133         for cmsg in msg.cmsgs().unwrap() {
2134             match cmsg {
2135                 ControlMessageOwned::Ipv6OrigDstAddr(addr) => {
2136                     rx_recvorigdstaddr = true;
2137                     if let Some(sin) = lo.as_sockaddr_in6() {
2138                         assert_eq!(sin.as_ref().sin6_addr.s6_addr,
2139                                    addr.sin6_addr.s6_addr,
2140                                    "unexpected destination address (expected {:?}, got {:?})",
2141                                    sin.as_ref().sin6_addr.s6_addr,
2142                                    addr.sin6_addr.s6_addr);
2143                     } else {
2144                         panic!("unexpected Sockaddr");
2145                     }
2146                 }
2147                 _ => panic!("unexpected additional control msg"),
2148             }
2149         }
2150         assert!(rx_recvorigdstaddr);
2151         assert_eq!(msg.bytes, 8);
2152         assert_eq!(*iovec[0], [1u8, 2, 3, 4, 5, 6, 7, 8]);
2153     }
2154 }
2155 
2156 #[cfg(any(linux_android, target_os = "freebsd", apple_targets, netbsdlike))]
2157 // qemu doesn't seem to be emulating this correctly in these architectures
2158 #[cfg_attr(
2159     all(
2160         qemu,
2161         any(
2162             target_arch = "mips",
2163             target_arch = "mips32r6",
2164             target_arch = "mips64",
2165             target_arch = "mips64r6",
2166             target_arch = "powerpc64",
2167         )
2168     ),
2169     ignore
2170 )]
2171 #[test]
test_recv_ipv6pktinfo()2172 pub fn test_recv_ipv6pktinfo() {
2173     use nix::net::if_::*;
2174     use nix::sys::socket::sockopt::Ipv6RecvPacketInfo;
2175     use nix::sys::socket::{bind, SockFlag, SockType, SockaddrIn6};
2176     use nix::sys::socket::{getsockname, setsockopt, socket};
2177     use nix::sys::socket::{recvmsg, sendmsg, ControlMessageOwned, MsgFlags};
2178     use std::io::{IoSlice, IoSliceMut};
2179 
2180     let lo_ifaddr = loopback_address(AddressFamily::Inet6);
2181     let (lo_name, lo) = match lo_ifaddr {
2182         Some(ifaddr) => (
2183             ifaddr.interface_name,
2184             ifaddr.address.expect("Expect IPv6 address on interface"),
2185         ),
2186         None => return,
2187     };
2188     let receive = socket(
2189         AddressFamily::Inet6,
2190         SockType::Datagram,
2191         SockFlag::empty(),
2192         None,
2193     )
2194     .expect("receive socket failed");
2195     bind(receive.as_raw_fd(), &lo).expect("bind failed");
2196     let sa: SockaddrIn6 =
2197         getsockname(receive.as_raw_fd()).expect("getsockname failed");
2198     setsockopt(&receive, Ipv6RecvPacketInfo, &true).expect("setsockopt failed");
2199 
2200     {
2201         let slice = [1u8, 2, 3, 4, 5, 6, 7, 8];
2202         let iov = [IoSlice::new(&slice)];
2203 
2204         let send = socket(
2205             AddressFamily::Inet6,
2206             SockType::Datagram,
2207             SockFlag::empty(),
2208             None,
2209         )
2210         .expect("send socket failed");
2211         sendmsg(send.as_raw_fd(), &iov, &[], MsgFlags::empty(), Some(&sa))
2212             .expect("sendmsg failed");
2213     }
2214 
2215     {
2216         let mut buf = [0u8; 8];
2217         let mut iovec = [IoSliceMut::new(&mut buf)];
2218 
2219         let mut space = cmsg_space!(libc::in6_pktinfo);
2220         let msg = recvmsg::<()>(
2221             receive.as_raw_fd(),
2222             &mut iovec,
2223             Some(&mut space),
2224             MsgFlags::empty(),
2225         )
2226         .expect("recvmsg failed");
2227         assert!(!msg
2228             .flags
2229             .intersects(MsgFlags::MSG_TRUNC | MsgFlags::MSG_CTRUNC));
2230 
2231         let mut cmsgs = msg.cmsgs().unwrap();
2232         if let Some(ControlMessageOwned::Ipv6PacketInfo(pktinfo)) = cmsgs.next()
2233         {
2234             let i = if_nametoindex(lo_name.as_bytes()).expect("if_nametoindex");
2235             assert_eq!(
2236                 pktinfo.ipi6_ifindex as libc::c_uint, i,
2237                 "unexpected ifindex (expected {}, got {})",
2238                 i, pktinfo.ipi6_ifindex
2239             );
2240         }
2241         assert!(cmsgs.next().is_none(), "unexpected additional control msg");
2242         assert_eq!(msg.bytes, 8);
2243         assert_eq!(*iovec[0], [1u8, 2, 3, 4, 5, 6, 7, 8]);
2244     }
2245 }
2246 
2247 #[cfg(linux_android)]
2248 #[test]
test_vsock()2249 pub fn test_vsock() {
2250     use nix::sys::socket::SockaddrLike;
2251     use nix::sys::socket::{AddressFamily, VsockAddr};
2252     use std::mem;
2253 
2254     let port: u32 = 3000;
2255 
2256     let addr_local = VsockAddr::new(libc::VMADDR_CID_LOCAL, port);
2257     assert_eq!(addr_local.cid(), libc::VMADDR_CID_LOCAL);
2258     assert_eq!(addr_local.port(), port);
2259 
2260     let addr_any = VsockAddr::new(libc::VMADDR_CID_ANY, libc::VMADDR_PORT_ANY);
2261     assert_eq!(addr_any.cid(), libc::VMADDR_CID_ANY);
2262     assert_eq!(addr_any.port(), libc::VMADDR_PORT_ANY);
2263 
2264     assert_ne!(addr_local, addr_any);
2265     assert_ne!(calculate_hash(&addr_local), calculate_hash(&addr_any));
2266 
2267     let addr1 = VsockAddr::new(libc::VMADDR_CID_HOST, port);
2268     let addr2 = VsockAddr::new(libc::VMADDR_CID_HOST, port);
2269     assert_eq!(addr1, addr2);
2270     assert_eq!(calculate_hash(&addr1), calculate_hash(&addr2));
2271 
2272     let addr3 = unsafe {
2273         VsockAddr::from_raw(
2274             addr2.as_ref() as *const libc::sockaddr_vm as *const libc::sockaddr,
2275             Some(mem::size_of::<libc::sockaddr_vm>().try_into().unwrap()),
2276         )
2277     }
2278     .unwrap();
2279     assert_eq!(
2280         addr3.as_ref().svm_family,
2281         AddressFamily::Vsock as libc::sa_family_t
2282     );
2283     assert_eq!(addr3.as_ref().svm_cid, addr1.cid());
2284     assert_eq!(addr3.as_ref().svm_port, addr1.port());
2285 }
2286 
2287 #[cfg(apple_targets)]
2288 #[test]
test_vsock()2289 pub fn test_vsock() {
2290     use nix::sys::socket::SockaddrLike;
2291     use nix::sys::socket::{AddressFamily, VsockAddr};
2292     use std::mem;
2293 
2294     let port: u32 = 3000;
2295 
2296     // macOS doesn't have a VMADDR_CID_LOCAL, so test with host again
2297     let addr_host = VsockAddr::new(libc::VMADDR_CID_HOST, port);
2298     assert_eq!(addr_host.cid(), libc::VMADDR_CID_HOST);
2299     assert_eq!(addr_host.port(), port);
2300 
2301     let addr_any = VsockAddr::new(libc::VMADDR_CID_ANY, libc::VMADDR_PORT_ANY);
2302     assert_eq!(addr_any.cid(), libc::VMADDR_CID_ANY);
2303     assert_eq!(addr_any.port(), libc::VMADDR_PORT_ANY);
2304 
2305     assert_ne!(addr_host, addr_any);
2306     assert_ne!(calculate_hash(&addr_host), calculate_hash(&addr_any));
2307 
2308     let addr1 = VsockAddr::new(libc::VMADDR_CID_HOST, port);
2309     let addr2 = VsockAddr::new(libc::VMADDR_CID_HOST, port);
2310     assert_eq!(addr1, addr2);
2311     assert_eq!(calculate_hash(&addr1), calculate_hash(&addr2));
2312 
2313     let addr3 = unsafe {
2314         VsockAddr::from_raw(
2315             addr2.as_ref() as *const libc::sockaddr_vm as *const libc::sockaddr,
2316             Some(mem::size_of::<libc::sockaddr_vm>().try_into().unwrap()),
2317         )
2318     }
2319     .unwrap();
2320     assert_eq!(
2321         addr3.as_ref().svm_family,
2322         AddressFamily::Vsock as libc::sa_family_t
2323     );
2324     let cid = addr3.as_ref().svm_cid;
2325     let port = addr3.as_ref().svm_port;
2326     assert_eq!(cid, addr1.cid());
2327     assert_eq!(port, addr1.port());
2328 }
2329 
2330 // Disable the test on emulated platforms because it fails in Cirrus-CI.  Lack
2331 // of QEMU support is suspected.
2332 #[cfg_attr(qemu, ignore)]
2333 #[cfg(target_os = "linux")]
2334 #[test]
test_recvmsg_timestampns()2335 fn test_recvmsg_timestampns() {
2336     use nix::sys::socket::*;
2337     use nix::sys::time::*;
2338     use std::io::{IoSlice, IoSliceMut};
2339     use std::time::*;
2340 
2341     // Set up
2342     let message = "Ohayō!".as_bytes();
2343     let in_socket = socket(
2344         AddressFamily::Inet,
2345         SockType::Datagram,
2346         SockFlag::empty(),
2347         None,
2348     )
2349     .unwrap();
2350     setsockopt(&in_socket, sockopt::ReceiveTimestampns, &true).unwrap();
2351     let localhost = SockaddrIn::new(127, 0, 0, 1, 0);
2352     bind(in_socket.as_raw_fd(), &localhost).unwrap();
2353     let address: SockaddrIn = getsockname(in_socket.as_raw_fd()).unwrap();
2354     // Get initial time
2355     let time0 = SystemTime::now();
2356     // Send the message
2357     let iov = [IoSlice::new(message)];
2358     let flags = MsgFlags::empty();
2359     let l = sendmsg(in_socket.as_raw_fd(), &iov, &[], flags, Some(&address))
2360         .unwrap();
2361     assert_eq!(message.len(), l);
2362     // Receive the message
2363     let mut buffer = vec![0u8; message.len()];
2364     let mut cmsgspace = nix::cmsg_space!(TimeSpec);
2365 
2366     let mut iov = [IoSliceMut::new(&mut buffer)];
2367     let r = recvmsg::<()>(
2368         in_socket.as_raw_fd(),
2369         &mut iov,
2370         Some(&mut cmsgspace),
2371         flags,
2372     )
2373     .unwrap();
2374     let rtime = match r.cmsgs().unwrap().next() {
2375         Some(ControlMessageOwned::ScmTimestampns(rtime)) => rtime,
2376         Some(_) => panic!("Unexpected control message"),
2377         None => panic!("No control message"),
2378     };
2379     // Check the final time
2380     let time1 = SystemTime::now();
2381     // the packet's received timestamp should lie in-between the two system
2382     // times, unless the system clock was adjusted in the meantime.
2383     let rduration =
2384         Duration::new(rtime.tv_sec() as u64, rtime.tv_nsec() as u32);
2385     assert!(time0.duration_since(UNIX_EPOCH).unwrap() <= rduration);
2386     assert!(rduration <= time1.duration_since(UNIX_EPOCH).unwrap());
2387 }
2388 
2389 // Disable the test on emulated platforms because it fails in Cirrus-CI.  Lack
2390 // of QEMU support is suspected.
2391 #[cfg_attr(qemu, ignore)]
2392 #[cfg(target_os = "linux")]
2393 #[test]
test_recvmmsg_timestampns()2394 fn test_recvmmsg_timestampns() {
2395     use nix::sys::socket::*;
2396     use nix::sys::time::*;
2397     use std::io::{IoSlice, IoSliceMut};
2398     use std::time::*;
2399 
2400     // Set up
2401     let message = "Ohayō!".as_bytes();
2402     let in_socket = socket(
2403         AddressFamily::Inet,
2404         SockType::Datagram,
2405         SockFlag::empty(),
2406         None,
2407     )
2408     .unwrap();
2409     setsockopt(&in_socket, sockopt::ReceiveTimestampns, &true).unwrap();
2410     let localhost = SockaddrIn::from_str("127.0.0.1:0").unwrap();
2411     bind(in_socket.as_raw_fd(), &localhost).unwrap();
2412     let address: SockaddrIn = getsockname(in_socket.as_raw_fd()).unwrap();
2413     // Get initial time
2414     let time0 = SystemTime::now();
2415     // Send the message
2416     let iov = [IoSlice::new(message)];
2417     let flags = MsgFlags::empty();
2418     let l = sendmsg(in_socket.as_raw_fd(), &iov, &[], flags, Some(&address))
2419         .unwrap();
2420     assert_eq!(message.len(), l);
2421     // Receive the message
2422     let mut buffer = vec![0u8; message.len()];
2423     let cmsgspace = nix::cmsg_space!(TimeSpec);
2424     let mut iov = [[IoSliceMut::new(&mut buffer)]];
2425     let mut data = MultiHeaders::preallocate(1, Some(cmsgspace));
2426     let r: Vec<RecvMsg<()>> = recvmmsg(
2427         in_socket.as_raw_fd(),
2428         &mut data,
2429         iov.iter_mut(),
2430         flags,
2431         None,
2432     )
2433     .unwrap()
2434     .collect();
2435     let rtime = match r[0].cmsgs().unwrap().next() {
2436         Some(ControlMessageOwned::ScmTimestampns(rtime)) => rtime,
2437         Some(_) => panic!("Unexpected control message"),
2438         None => panic!("No control message"),
2439     };
2440     // Check the final time
2441     let time1 = SystemTime::now();
2442     // the packet's received timestamp should lie in-between the two system
2443     // times, unless the system clock was adjusted in the meantime.
2444     let rduration =
2445         Duration::new(rtime.tv_sec() as u64, rtime.tv_nsec() as u32);
2446     assert!(time0.duration_since(UNIX_EPOCH).unwrap() <= rduration);
2447     assert!(rduration <= time1.duration_since(UNIX_EPOCH).unwrap());
2448 }
2449 
2450 // Disable the test on emulated platforms because it fails in Cirrus-CI.  Lack
2451 // of QEMU support is suspected.
2452 #[cfg_attr(qemu, ignore)]
2453 #[cfg(any(linux_android, target_os = "fuchsia"))]
2454 #[test]
test_recvmsg_rxq_ovfl()2455 fn test_recvmsg_rxq_ovfl() {
2456     use nix::sys::socket::sockopt::{RcvBuf, RxqOvfl};
2457     use nix::sys::socket::*;
2458     use nix::Error;
2459     use std::io::{IoSlice, IoSliceMut};
2460 
2461     let message = [0u8; 2048];
2462     let bufsize = message.len() * 2;
2463 
2464     let in_socket = socket(
2465         AddressFamily::Inet,
2466         SockType::Datagram,
2467         SockFlag::empty(),
2468         None,
2469     )
2470     .unwrap();
2471     let out_socket = socket(
2472         AddressFamily::Inet,
2473         SockType::Datagram,
2474         SockFlag::empty(),
2475         None,
2476     )
2477     .unwrap();
2478 
2479     let localhost = SockaddrIn::from_str("127.0.0.1:0").unwrap();
2480     bind(in_socket.as_raw_fd(), &localhost).unwrap();
2481 
2482     let address: SockaddrIn = getsockname(in_socket.as_raw_fd()).unwrap();
2483     connect(out_socket.as_raw_fd(), &address).unwrap();
2484 
2485     // Set SO_RXQ_OVFL flag.
2486     setsockopt(&in_socket, RxqOvfl, &1).unwrap();
2487 
2488     // Set the receiver buffer size to hold only 2 messages.
2489     setsockopt(&in_socket, RcvBuf, &bufsize).unwrap();
2490 
2491     let mut drop_counter = 0;
2492 
2493     for _ in 0..2 {
2494         let iov = [IoSlice::new(&message)];
2495         let flags = MsgFlags::empty();
2496 
2497         // Send the 3 messages (the receiver buffer can only hold 2 messages)
2498         // to create an overflow.
2499         for _ in 0..3 {
2500             let l = sendmsg(
2501                 out_socket.as_raw_fd(),
2502                 &iov,
2503                 &[],
2504                 flags,
2505                 Some(&address),
2506             )
2507             .unwrap();
2508             assert_eq!(message.len(), l);
2509         }
2510 
2511         // Receive the message and check the drop counter if any.
2512         loop {
2513             let mut buffer = vec![0u8; message.len()];
2514             let mut cmsgspace = nix::cmsg_space!(u32);
2515 
2516             let mut iov = [IoSliceMut::new(&mut buffer)];
2517 
2518             match recvmsg::<()>(
2519                 in_socket.as_raw_fd(),
2520                 &mut iov,
2521                 Some(&mut cmsgspace),
2522                 MsgFlags::MSG_DONTWAIT,
2523             ) {
2524                 Ok(r) => {
2525                     drop_counter = match r.cmsgs().unwrap().next() {
2526                         Some(ControlMessageOwned::RxqOvfl(drop_counter)) => {
2527                             drop_counter
2528                         }
2529                         Some(_) => panic!("Unexpected control message"),
2530                         None => 0,
2531                     };
2532                 }
2533                 Err(Error::EAGAIN) => {
2534                     break;
2535                 }
2536                 _ => {
2537                     panic!("unknown recvmsg() error");
2538                 }
2539             }
2540         }
2541     }
2542 
2543     // One packet lost.
2544     assert_eq!(drop_counter, 1);
2545 }
2546 
2547 #[cfg(linux_android)]
2548 mod linux_errqueue {
2549     use super::FromStr;
2550     use nix::sys::socket::*;
2551     use std::os::unix::io::AsRawFd;
2552 
2553     // Send a UDP datagram to a bogus destination address and observe an ICMP error (v4).
2554     //
2555     // Disable the test on QEMU because QEMU emulation of IP_RECVERR is broken (as documented on PR
2556     // #1514).
2557     #[cfg_attr(qemu, ignore)]
2558     #[test]
test_recverr_v4()2559     fn test_recverr_v4() {
2560         #[repr(u8)]
2561         enum IcmpTypes {
2562             DestUnreach = 3, // ICMP_DEST_UNREACH
2563         }
2564         #[repr(u8)]
2565         enum IcmpUnreachCodes {
2566             PortUnreach = 3, // ICMP_PORT_UNREACH
2567         }
2568 
2569         test_recverr_impl::<sockaddr_in, _, _>(
2570             "127.0.0.1:6800",
2571             AddressFamily::Inet,
2572             sockopt::Ipv4RecvErr,
2573             libc::SO_EE_ORIGIN_ICMP,
2574             IcmpTypes::DestUnreach as u8,
2575             IcmpUnreachCodes::PortUnreach as u8,
2576             // Closure handles protocol-specific testing and returns generic sock_extended_err for
2577             // protocol-independent test impl.
2578             |cmsg| {
2579                 if let ControlMessageOwned::Ipv4RecvErr(ext_err, err_addr) =
2580                     cmsg
2581                 {
2582                     if let Some(origin) = err_addr {
2583                         // Validate that our network error originated from 127.0.0.1:0.
2584                         assert_eq!(origin.sin_family, AddressFamily::Inet as _);
2585                         assert_eq!(
2586                             origin.sin_addr.s_addr,
2587                             u32::from_be(0x7f000001)
2588                         );
2589                         assert_eq!(origin.sin_port, 0);
2590                     } else {
2591                         panic!("Expected some error origin");
2592                     }
2593                     *ext_err
2594                 } else {
2595                     panic!("Unexpected control message {cmsg:?}");
2596                 }
2597             },
2598         )
2599     }
2600 
2601     // Essentially the same test as v4.
2602     //
2603     // Disable the test on QEMU because QEMU emulation of IPV6_RECVERR is broken (as documented on
2604     // PR #1514).
2605     #[cfg_attr(qemu, ignore)]
2606     #[test]
test_recverr_v6()2607     fn test_recverr_v6() {
2608         #[repr(u8)]
2609         enum IcmpV6Types {
2610             DestUnreach = 1, // ICMPV6_DEST_UNREACH
2611         }
2612         #[repr(u8)]
2613         enum IcmpV6UnreachCodes {
2614             PortUnreach = 4, // ICMPV6_PORT_UNREACH
2615         }
2616 
2617         test_recverr_impl::<sockaddr_in6, _, _>(
2618             "[::1]:6801",
2619             AddressFamily::Inet6,
2620             sockopt::Ipv6RecvErr,
2621             libc::SO_EE_ORIGIN_ICMP6,
2622             IcmpV6Types::DestUnreach as u8,
2623             IcmpV6UnreachCodes::PortUnreach as u8,
2624             // Closure handles protocol-specific testing and returns generic sock_extended_err for
2625             // protocol-independent test impl.
2626             |cmsg| {
2627                 if let ControlMessageOwned::Ipv6RecvErr(ext_err, err_addr) =
2628                     cmsg
2629                 {
2630                     if let Some(origin) = err_addr {
2631                         // Validate that our network error originated from localhost:0.
2632                         assert_eq!(
2633                             origin.sin6_family,
2634                             AddressFamily::Inet6 as _
2635                         );
2636                         assert_eq!(
2637                             origin.sin6_addr.s6_addr,
2638                             std::net::Ipv6Addr::LOCALHOST.octets()
2639                         );
2640                         assert_eq!(origin.sin6_port, 0);
2641                     } else {
2642                         panic!("Expected some error origin");
2643                     }
2644                     *ext_err
2645                 } else {
2646                     panic!("Unexpected control message {cmsg:?}");
2647                 }
2648             },
2649         )
2650     }
2651 
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,2652     fn test_recverr_impl<SA, OPT, TESTF>(
2653         sa: &str,
2654         af: AddressFamily,
2655         opt: OPT,
2656         ee_origin: u8,
2657         ee_type: u8,
2658         ee_code: u8,
2659         testf: TESTF,
2660     ) where
2661         OPT: SetSockOpt<Val = bool>,
2662         TESTF: FnOnce(&ControlMessageOwned) -> libc::sock_extended_err,
2663     {
2664         use nix::errno::Errno;
2665         use std::io::IoSliceMut;
2666 
2667         const MESSAGE_CONTENTS: &str = "ABCDEF";
2668         let std_sa = std::net::SocketAddr::from_str(sa).unwrap();
2669         let sock_addr = SockaddrStorage::from(std_sa);
2670         let sock = socket(af, SockType::Datagram, SockFlag::SOCK_CLOEXEC, None)
2671             .unwrap();
2672         setsockopt(&sock, opt, &true).unwrap();
2673         if let Err(e) = sendto(
2674             sock.as_raw_fd(),
2675             MESSAGE_CONTENTS.as_bytes(),
2676             &sock_addr,
2677             MsgFlags::empty(),
2678         ) {
2679             assert_eq!(e, Errno::EADDRNOTAVAIL);
2680             println!("{af:?} not available, skipping test.");
2681             return;
2682         }
2683 
2684         let mut buf = [0u8; 8];
2685         let mut iovec = [IoSliceMut::new(&mut buf)];
2686         let mut cspace = cmsg_space!(libc::sock_extended_err, SA);
2687 
2688         let msg = recvmsg(
2689             sock.as_raw_fd(),
2690             &mut iovec,
2691             Some(&mut cspace),
2692             MsgFlags::MSG_ERRQUEUE,
2693         )
2694         .unwrap();
2695         // The sent message / destination associated with the error is returned:
2696         assert_eq!(msg.bytes, MESSAGE_CONTENTS.as_bytes().len());
2697         // recvmsg(2): "The original destination address of the datagram that caused the error is
2698         // supplied via msg_name;" however, this is not literally true.  E.g., an earlier version
2699         // of this test used 0.0.0.0 (::0) as the destination address, which was mutated into
2700         // 127.0.0.1 (::1).
2701         assert_eq!(msg.address, Some(sock_addr));
2702 
2703         // Check for expected control message.
2704         let ext_err = match msg.cmsgs().unwrap().next() {
2705             Some(cmsg) => testf(&cmsg),
2706             None => panic!("No control message"),
2707         };
2708 
2709         assert_eq!(ext_err.ee_errno, libc::ECONNREFUSED as u32);
2710         assert_eq!(ext_err.ee_origin, ee_origin);
2711         // ip(7): ee_type and ee_code are set from the type and code fields of the ICMP (ICMPv6)
2712         // header.
2713         assert_eq!(ext_err.ee_type, ee_type);
2714         assert_eq!(ext_err.ee_code, ee_code);
2715         // ip(7): ee_info contains the discovered MTU for EMSGSIZE errors.
2716         assert_eq!(ext_err.ee_info, 0);
2717 
2718         let bytes = msg.bytes;
2719         assert_eq!(&buf[..bytes], MESSAGE_CONTENTS.as_bytes());
2720     }
2721 }
2722 
2723 // Disable the test on emulated platforms because it fails in Cirrus-CI.  Lack
2724 // of QEMU support is suspected.
2725 #[cfg_attr(qemu, ignore)]
2726 #[cfg(target_os = "linux")]
2727 #[test]
test_txtime()2728 pub fn test_txtime() {
2729     use nix::sys::socket::{
2730         bind, recvmsg, sendmsg, setsockopt, socket, sockopt, ControlMessage,
2731         MsgFlags, SockFlag, SockType, SockaddrIn,
2732     };
2733     use nix::sys::time::TimeValLike;
2734     use nix::time::{clock_gettime, ClockId};
2735 
2736     require_kernel_version!(test_txtime, ">= 5.8");
2737 
2738     let sock_addr = SockaddrIn::from_str("127.0.0.1:6802").unwrap();
2739 
2740     let ssock = socket(
2741         AddressFamily::Inet,
2742         SockType::Datagram,
2743         SockFlag::empty(),
2744         None,
2745     )
2746     .expect("send socket failed");
2747 
2748     let txtime_cfg = libc::sock_txtime {
2749         clockid: libc::CLOCK_MONOTONIC,
2750         flags: 0,
2751     };
2752     setsockopt(&ssock, sockopt::TxTime, &txtime_cfg).unwrap();
2753 
2754     let rsock = socket(
2755         AddressFamily::Inet,
2756         SockType::Datagram,
2757         SockFlag::empty(),
2758         None,
2759     )
2760     .unwrap();
2761     bind(rsock.as_raw_fd(), &sock_addr).unwrap();
2762 
2763     let sbuf = [0u8; 2048];
2764     let iov1 = [std::io::IoSlice::new(&sbuf)];
2765 
2766     let now = clock_gettime(ClockId::CLOCK_MONOTONIC).unwrap();
2767     let delay = std::time::Duration::from_secs(1).into();
2768     let txtime = (now + delay).num_nanoseconds() as u64;
2769 
2770     let cmsg = ControlMessage::TxTime(&txtime);
2771     sendmsg(
2772         ssock.as_raw_fd(),
2773         &iov1,
2774         &[cmsg],
2775         MsgFlags::empty(),
2776         Some(&sock_addr),
2777     )
2778     .unwrap();
2779 
2780     let mut rbuf = [0u8; 2048];
2781     let mut iov2 = [std::io::IoSliceMut::new(&mut rbuf)];
2782     recvmsg::<()>(rsock.as_raw_fd(), &mut iov2, None, MsgFlags::empty())
2783         .unwrap();
2784 }
2785 
2786 // cfg needed for capability check.
2787 #[cfg(linux_android)]
2788 #[test]
test_icmp_protocol()2789 fn test_icmp_protocol() {
2790     use nix::sys::socket::{
2791         sendto, socket, AddressFamily, MsgFlags, SockFlag, SockProtocol,
2792         SockType, SockaddrIn,
2793     };
2794 
2795     require_capability!("test_icmp_protocol", CAP_NET_RAW);
2796 
2797     let owned_fd = socket(
2798         AddressFamily::Inet,
2799         SockType::Raw,
2800         SockFlag::empty(),
2801         SockProtocol::Icmp,
2802     )
2803     .unwrap();
2804 
2805     // Send a minimal ICMP packet with no payload.
2806     let packet = [
2807         0x08, // Type
2808         0x00, // Code
2809         0x84, 0x85, // Checksum
2810         0x73, 0x8a, // ID
2811         0x00, 0x00, // Sequence Number
2812     ];
2813 
2814     let dest_addr = SockaddrIn::new(127, 0, 0, 1, 0);
2815     sendto(owned_fd.as_raw_fd(), &packet, &dest_addr, MsgFlags::empty())
2816         .unwrap();
2817 }
2818 
2819 // test contains both recvmmsg and timestaping which is linux only
2820 // there are existing tests for recvmmsg only in tests/
2821 #[cfg_attr(qemu, ignore)]
2822 #[cfg(target_os = "linux")]
2823 #[test]
test_recvmm2() -> nix::Result<()>2824 fn test_recvmm2() -> nix::Result<()> {
2825     use nix::sys::{
2826         socket::{
2827             bind, recvmmsg, sendmsg, setsockopt, socket, sockopt::Timestamping,
2828             AddressFamily, ControlMessageOwned, MsgFlags, MultiHeaders,
2829             SockFlag, SockType, SockaddrIn, TimestampingFlag, Timestamps,
2830         },
2831         time::TimeSpec,
2832     };
2833     use std::io::{IoSlice, IoSliceMut};
2834     use std::os::unix::io::AsRawFd;
2835     use std::str::FromStr;
2836 
2837     let sock_addr = SockaddrIn::from_str("127.0.0.1:6790").unwrap();
2838 
2839     let ssock = socket(
2840         AddressFamily::Inet,
2841         SockType::Datagram,
2842         SockFlag::empty(),
2843         None,
2844     )?;
2845 
2846     let rsock = socket(
2847         AddressFamily::Inet,
2848         SockType::Datagram,
2849         SockFlag::SOCK_NONBLOCK,
2850         None,
2851     )?;
2852 
2853     bind(rsock.as_raw_fd(), &sock_addr)?;
2854 
2855     setsockopt(&rsock, Timestamping, &TimestampingFlag::all())?;
2856 
2857     let sbuf = (0..400).map(|i| i as u8).collect::<Vec<_>>();
2858 
2859     let mut recv_buf = vec![0; 1024];
2860 
2861     let mut recv_iovs = Vec::new();
2862     let mut pkt_iovs = Vec::new();
2863 
2864     for (ix, chunk) in recv_buf.chunks_mut(256).enumerate() {
2865         pkt_iovs.push(IoSliceMut::new(chunk));
2866         if ix % 2 == 1 {
2867             recv_iovs.push(pkt_iovs);
2868             pkt_iovs = Vec::new();
2869         }
2870     }
2871     drop(pkt_iovs);
2872 
2873     let flags = MsgFlags::empty();
2874     let iov1 = [IoSlice::new(&sbuf)];
2875 
2876     let cmsg = cmsg_space!(Timestamps);
2877     sendmsg(ssock.as_raw_fd(), &iov1, &[], flags, Some(&sock_addr)).unwrap();
2878 
2879     let mut data = MultiHeaders::<()>::preallocate(recv_iovs.len(), Some(cmsg));
2880 
2881     let t = TimeSpec::from_duration(std::time::Duration::from_secs(10));
2882 
2883     let recv = recvmmsg(
2884         rsock.as_raw_fd(),
2885         &mut data,
2886         recv_iovs.iter_mut(),
2887         flags,
2888         Some(t),
2889     )?;
2890 
2891     for rmsg in recv {
2892         #[cfg(not(any(qemu, target_arch = "aarch64")))]
2893         let mut saw_time = false;
2894         let mut recvd = 0;
2895         for cmsg in rmsg.cmsgs().unwrap() {
2896             if let ControlMessageOwned::ScmTimestampsns(timestamps) = cmsg {
2897                 let ts = timestamps.system;
2898 
2899                 let sys_time = nix::time::clock_gettime(
2900                     nix::time::ClockId::CLOCK_REALTIME,
2901                 )?;
2902                 let diff = if ts > sys_time {
2903                     ts - sys_time
2904                 } else {
2905                     sys_time - ts
2906                 };
2907                 assert!(std::time::Duration::from(diff).as_secs() < 60);
2908                 #[cfg(not(any(qemu, target_arch = "aarch64")))]
2909                 {
2910                     saw_time = true;
2911                 }
2912             }
2913         }
2914 
2915         #[cfg(not(any(qemu, target_arch = "aarch64")))]
2916         assert!(saw_time);
2917 
2918         for iov in rmsg.iovs() {
2919             recvd += iov.len();
2920         }
2921         assert_eq!(recvd, 400);
2922     }
2923 
2924     Ok(())
2925 }
2926 
2927 #[cfg(not(target_os = "redox"))]
2928 #[test]
can_use_cmsg_space()2929 fn can_use_cmsg_space() {
2930     let _ = cmsg_space!(u8);
2931 }
2932 
2933 #[cfg(not(any(linux_android, target_os = "redox", target_os = "haiku")))]
2934 #[test]
can_open_routing_socket()2935 fn can_open_routing_socket() {
2936     use nix::sys::socket::{socket, AddressFamily, SockFlag, SockType};
2937 
2938     let _ =
2939         socket(AddressFamily::Route, SockType::Raw, SockFlag::empty(), None)
2940             .expect("Failed to open routing socket");
2941 }
2942