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