diff --git a/changelog/2244.added.md b/changelog/2244.added.md new file mode 100644 index 0000000000..c5d9465c76 --- /dev/null +++ b/changelog/2244.added.md @@ -0,0 +1 @@ +Added `IpBindAddressNoPort` sockopt to support `IP_BIND_ADDRESS_NO_PORT` available on linux. diff --git a/src/sys/socket/sockopt.rs b/src/sys/socket/sockopt.rs index 5ebb885293..17d3f9b77f 100644 --- a/src/sys/socket/sockopt.rs +++ b/src/sys/socket/sockopt.rs @@ -412,6 +412,20 @@ sockopt_impl!( libc::IP_FREEBIND, bool ); +#[cfg(linux_android)] +#[cfg(feature = "net")] +sockopt_impl!( + #[cfg_attr(docsrs, doc(cfg(feature = "net")))] + /// If enabled, the kernel will not reserve an ephemeral port when binding + /// socket with a port number of 0. The port will later be automatically + /// chosen at connect time, in a way that allows sharing a source port as + /// long as the 4-tuple is unique. + IpBindAddressNoPort, + Both, + libc::IPPROTO_IP, + libc::IP_BIND_ADDRESS_NO_PORT, + bool +); sockopt_impl!( /// Specify the receiving timeout until reporting an error. ReceiveTimeout, diff --git a/test/sys/test_sockopt.rs b/test/sys/test_sockopt.rs index 6f9e3f0447..e4e4f493c6 100644 --- a/test/sys/test_sockopt.rs +++ b/test/sys/test_sockopt.rs @@ -549,3 +549,30 @@ fn test_ts_clock_monotonic() { SocketTimestamp::SO_TS_MONOTONIC ); } + +#[test] +#[cfg(linux_android)] +// Disable the test under emulation because it failsi with ENOPROTOOPT in CI +// on cross target. Lack of QEMU support is suspected. +#[cfg_attr(qemu, ignore)] +fn test_ip_bind_address_no_port() { + let fd = socket( + AddressFamily::Inet, + SockType::Stream, + SockFlag::empty(), + SockProtocol::Tcp, + ) + .unwrap(); + setsockopt(&fd, sockopt::IpBindAddressNoPort, &true).expect( + "setting IP_BIND_ADDRESS_NO_PORT on an inet stream socket should succeed", + ); + assert!(getsockopt(&fd, sockopt::IpBindAddressNoPort).expect( + "getting IP_BIND_ADDRESS_NO_PORT on an inet stream socket should succeed", + )); + setsockopt(&fd, sockopt::IpBindAddressNoPort, &false).expect( + "unsetting IP_BIND_ADDRESS_NO_PORT on an inet stream socket should succeed", + ); + assert!(!getsockopt(&fd, sockopt::IpBindAddressNoPort).expect( + "getting IP_BIND_ADDRESS_NO_PORT on an inet stream socket should succeed", + )); +}