1 use rand::{thread_rng, Rng};
2 use nix::sys::socket::{socket, sockopt, getsockopt, setsockopt, AddressFamily, SockType, SockFlag, SockProtocol};
3 
4 #[cfg(target_os = "linux")]
5 #[test]
is_so_mark_functional()6 fn is_so_mark_functional() {
7     use nix::sys::socket::sockopt;
8 
9     require_capability!(CAP_NET_ADMIN);
10 
11     let s = socket(AddressFamily::Inet, SockType::Stream, SockFlag::empty(), None).unwrap();
12     setsockopt(s, sockopt::Mark, &1337).unwrap();
13     let mark = getsockopt(s, sockopt::Mark).unwrap();
14     assert_eq!(mark, 1337);
15 }
16 
17 #[test]
test_so_buf()18 fn test_so_buf() {
19     let fd = socket(AddressFamily::Inet, SockType::Datagram, SockFlag::empty(), SockProtocol::Udp)
20              .unwrap();
21     let bufsize: usize = thread_rng().gen_range(4096, 131_072);
22     setsockopt(fd, sockopt::SndBuf, &bufsize).unwrap();
23     let actual = getsockopt(fd, sockopt::SndBuf).unwrap();
24     assert!(actual >= bufsize);
25     setsockopt(fd, sockopt::RcvBuf, &bufsize).unwrap();
26     let actual = getsockopt(fd, sockopt::RcvBuf).unwrap();
27     assert!(actual >= bufsize);
28 }
29 
30 // The CI doesn't supported getsockopt and setsockopt on emulated processors.
31 // It's beleived that a QEMU issue, the tests run ok on a fully emulated system.
32 // Current CI just run the binary with QEMU but the Kernel remains the same as the host.
33 // So the syscall doesn't work properly unless the kernel is also emulated.
34 #[test]
35 #[cfg(all(
36     any(target_arch = "x86", target_arch = "x86_64"),
37     any(target_os = "freebsd", target_os = "linux")
38 ))]
test_tcp_congestion()39 fn test_tcp_congestion() {
40     use std::ffi::OsString;
41 
42     let fd = socket(AddressFamily::Inet, SockType::Stream, SockFlag::empty(), None).unwrap();
43 
44     let val = getsockopt(fd, sockopt::TcpCongestion).unwrap();
45     setsockopt(fd, sockopt::TcpCongestion, &val).unwrap();
46 
47     setsockopt(fd, sockopt::TcpCongestion, &OsString::from("tcp_congestion_does_not_exist")).unwrap_err();
48 
49     assert_eq!(
50         getsockopt(fd, sockopt::TcpCongestion).unwrap(),
51         val
52     );
53 }
54 
55 #[test]
56 #[cfg(any(target_os = "android", target_os = "linux"))]
test_bindtodevice()57 fn test_bindtodevice() {
58     skip_if_not_root!("test_bindtodevice");
59 
60     let fd = socket(AddressFamily::Inet, SockType::Stream, SockFlag::empty(), None).unwrap();
61 
62     let val = getsockopt(fd, sockopt::BindToDevice).unwrap();
63     setsockopt(fd, sockopt::BindToDevice, &val).unwrap();
64 
65     assert_eq!(
66         getsockopt(fd, sockopt::BindToDevice).unwrap(),
67         val
68     );
69 }
70 
71 #[test]
test_so_tcp_keepalive()72 fn test_so_tcp_keepalive() {
73     let fd = socket(AddressFamily::Inet, SockType::Stream, SockFlag::empty(), SockProtocol::Tcp).unwrap();
74     setsockopt(fd, sockopt::KeepAlive, &true).unwrap();
75     assert_eq!(getsockopt(fd, sockopt::KeepAlive).unwrap(), true);
76 
77     #[cfg(any(target_os = "android",
78               target_os = "dragonfly",
79               target_os = "freebsd",
80               target_os = "linux",
81               target_os = "nacl"))] {
82         let x = getsockopt(fd, sockopt::TcpKeepIdle).unwrap();
83         setsockopt(fd, sockopt::TcpKeepIdle, &(x + 1)).unwrap();
84         assert_eq!(getsockopt(fd, sockopt::TcpKeepIdle).unwrap(), x + 1);
85 
86         let x = getsockopt(fd, sockopt::TcpKeepCount).unwrap();
87         setsockopt(fd, sockopt::TcpKeepCount, &(x + 1)).unwrap();
88         assert_eq!(getsockopt(fd, sockopt::TcpKeepCount).unwrap(), x + 1);
89 
90         let x = getsockopt(fd, sockopt::TcpKeepInterval).unwrap();
91         setsockopt(fd, sockopt::TcpKeepInterval, &(x + 1)).unwrap();
92         assert_eq!(getsockopt(fd, sockopt::TcpKeepInterval).unwrap(), x + 1);
93     }
94 }
95