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