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