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