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