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