Add IP options to UDP socket
This commit is contained in:
parent
e796c41546
commit
1375346214
|
|
@ -12,6 +12,7 @@ use crate::{
|
|||
fs::utils::Inode,
|
||||
match_sock_option_mut,
|
||||
net::socket::{
|
||||
ip::options::{IpOptionSet, SetIpLevelOption},
|
||||
new_pseudo_inode,
|
||||
options::{Error as SocketError, SocketOption},
|
||||
private::SocketPrivate,
|
||||
|
|
@ -44,13 +45,15 @@ pub struct DatagramSocket {
|
|||
#[derive(Debug, Clone)]
|
||||
struct OptionSet {
|
||||
socket: SocketOptionSet,
|
||||
ip: IpOptionSet,
|
||||
// TODO: UDP option set
|
||||
}
|
||||
|
||||
impl OptionSet {
|
||||
fn new() -> Self {
|
||||
let socket = SocketOptionSet::new_udp();
|
||||
OptionSet { socket }
|
||||
let ip = IpOptionSet::new_udp();
|
||||
OptionSet { socket, ip }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -228,33 +231,47 @@ impl Socket for DatagramSocket {
|
|||
});
|
||||
|
||||
let inner = self.inner.read();
|
||||
self.options.read().socket.get_option(option, &*inner)
|
||||
let options = self.options.read();
|
||||
|
||||
// Deal with socket-level options
|
||||
match options.socket.get_option(option, &*inner) {
|
||||
Err(err) if err.error() == Errno::ENOPROTOOPT => (),
|
||||
res => return res,
|
||||
}
|
||||
|
||||
// Deal with IP-level options
|
||||
options.ip.get_option(option)
|
||||
}
|
||||
|
||||
fn set_option(&self, option: &dyn SocketOption) -> Result<()> {
|
||||
let inner = self.inner.read();
|
||||
let mut options = self.options.write();
|
||||
|
||||
match options.socket.set_option(option, &*inner) {
|
||||
Err(e) => Err(e),
|
||||
Ok(need_iface_poll) => {
|
||||
let iface_to_poll = need_iface_poll
|
||||
.then(|| match &*inner {
|
||||
Inner::Unbound(_) => None,
|
||||
Inner::Bound(bound_datagram) => Some(bound_datagram.iface().clone()),
|
||||
})
|
||||
.flatten();
|
||||
|
||||
drop(inner);
|
||||
drop(options);
|
||||
|
||||
if let Some(iface) = iface_to_poll {
|
||||
iface.poll();
|
||||
}
|
||||
|
||||
Ok(())
|
||||
// Deal with socket-level options
|
||||
let need_iface_poll = match options.socket.set_option(option, &*inner) {
|
||||
Err(err) if err.error() == Errno::ENOPROTOOPT => {
|
||||
// Deal with IP-level options
|
||||
options.ip.set_option(option, &*inner)?
|
||||
}
|
||||
Err(err) => return Err(err),
|
||||
Ok(need_iface_poll) => need_iface_poll,
|
||||
};
|
||||
|
||||
let iface_to_poll = need_iface_poll
|
||||
.then(|| match &*inner {
|
||||
Inner::Unbound(_) => None,
|
||||
Inner::Bound(bound_datagram) => Some(bound_datagram.iface().clone()),
|
||||
})
|
||||
.flatten();
|
||||
|
||||
drop(inner);
|
||||
drop(options);
|
||||
|
||||
if let Some(iface) = iface_to_poll {
|
||||
iface.poll();
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn pseudo_inode(&self) -> &Arc<dyn Inode> {
|
||||
|
|
@ -277,3 +294,12 @@ impl SetSocketLevelOption for Inner<UnboundDatagram, BoundDatagram> {
|
|||
bound.bound_port().set_can_reuse(reuse_addr);
|
||||
}
|
||||
}
|
||||
|
||||
impl SetIpLevelOption for Inner<UnboundDatagram, BoundDatagram> {
|
||||
fn set_hdrincl(&self, _hdrincl: bool) -> Result<()> {
|
||||
return_errno_with_message!(
|
||||
Errno::ENOPROTOOPT,
|
||||
"IP_HDRINCL cannot be set on UDP sockets"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,6 +31,14 @@ impl IpOptionSet {
|
|||
}
|
||||
}
|
||||
|
||||
pub(super) const fn new_udp() -> Self {
|
||||
Self {
|
||||
tos: 0,
|
||||
ttl: IpTtl(None),
|
||||
hdrincl: false,
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn get_option(&self, option: &mut dyn SocketOption) -> Result<()> {
|
||||
match_sock_option_mut!(option, {
|
||||
ip_tos: Tos => {
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ int sk_unbound;
|
|||
int sk_listen;
|
||||
int sk_connected;
|
||||
int sk_accepted;
|
||||
int sk_udp;
|
||||
|
||||
struct sockaddr_in listen_addr;
|
||||
#define LISTEN_PORT htons(0x1242)
|
||||
|
|
@ -35,6 +36,8 @@ FN_SETUP(general)
|
|||
sizeof(listen_addr)));
|
||||
|
||||
sk_accepted = CHECK(accept(sk_listen, NULL, NULL));
|
||||
|
||||
sk_udp = CHECK(socket(AF_INET, SOCK_DGRAM, 0));
|
||||
}
|
||||
END_SETUP()
|
||||
|
||||
|
|
@ -287,13 +290,18 @@ FN_TEST(ip_tos)
|
|||
// 1. Check default value
|
||||
TEST_RES(getsockopt(sk_unbound, IPPROTO_IP, IP_TOS, &tos, &tos_len),
|
||||
tos == 0 && tos_len == 4);
|
||||
TEST_RES(getsockopt(sk_udp, IPPROTO_IP, IP_TOS, &tos, &tos_len),
|
||||
tos == 0 && tos_len == 4);
|
||||
|
||||
// 2. Set and get value
|
||||
tos = 0x10;
|
||||
CHECK(setsockopt(sk_unbound, IPPROTO_IP, IP_TOS, &tos, tos_len));
|
||||
CHECK(setsockopt(sk_udp, IPPROTO_IP, IP_TOS, &tos, tos_len));
|
||||
tos = 0;
|
||||
TEST_RES(getsockopt(sk_unbound, IPPROTO_IP, IP_TOS, &tos, &tos_len),
|
||||
tos == 0x10 && tos_len == 4);
|
||||
TEST_RES(getsockopt(sk_udp, IPPROTO_IP, IP_TOS, &tos, &tos_len),
|
||||
tos == 0x10 && tos_len == 4);
|
||||
|
||||
tos = 0x123;
|
||||
CHECK(setsockopt(sk_unbound, IPPROTO_IP, IP_TOS, &tos, tos_len));
|
||||
|
|
@ -317,6 +325,8 @@ FN_TEST(ip_ttl)
|
|||
// 1. Check default value
|
||||
TEST_RES(getsockopt(sk_unbound, IPPROTO_IP, IP_TTL, &ttl, &ttl_len),
|
||||
ttl == 64 && ttl_len == 4);
|
||||
TEST_RES(getsockopt(sk_udp, IPPROTO_IP, IP_TTL, &ttl, &ttl_len),
|
||||
ttl == 64 && ttl_len == 4);
|
||||
|
||||
// 2. Set and get value
|
||||
ttl = 0x0;
|
||||
|
|
@ -329,10 +339,13 @@ FN_TEST(ip_ttl)
|
|||
|
||||
ttl = 0x10;
|
||||
CHECK(setsockopt(sk_unbound, IPPROTO_IP, IP_TTL, &ttl, ttl_len));
|
||||
CHECK(setsockopt(sk_udp, IPPROTO_IP, IP_TTL, &ttl, ttl_len));
|
||||
|
||||
ttl = 0;
|
||||
TEST_RES(getsockopt(sk_unbound, IPPROTO_IP, IP_TTL, &ttl, &ttl_len),
|
||||
ttl == 0x10 && ttl_len == 4);
|
||||
TEST_RES(getsockopt(sk_udp, IPPROTO_IP, IP_TTL, &ttl, &ttl_len),
|
||||
ttl == 0x10 && ttl_len == 4);
|
||||
|
||||
ttl = -1;
|
||||
CHECK(setsockopt(sk_unbound, IPPROTO_IP, IP_TTL, &ttl, ttl_len));
|
||||
|
|
@ -352,11 +365,17 @@ FN_TEST(ip_hdrincl)
|
|||
TEST_RES(getsockopt(sk_unbound, IPPROTO_IP, IP_HDRINCL, &hdrincl,
|
||||
&hdrincl_len),
|
||||
hdrincl == 0 && hdrincl_len == 4);
|
||||
TEST_RES(getsockopt(sk_udp, IPPROTO_IP, IP_HDRINCL, &hdrincl,
|
||||
&hdrincl_len),
|
||||
hdrincl == 0 && hdrincl_len == 4);
|
||||
|
||||
// 2. Set value
|
||||
// 2. Set and get value
|
||||
hdrincl = 0x10;
|
||||
TEST_ERRNO(setsockopt(sk_unbound, IPPROTO_IP, IP_HDRINCL, &hdrincl,
|
||||
hdrincl_len),
|
||||
ENOPROTOOPT);
|
||||
TEST_ERRNO(setsockopt(sk_udp, IPPROTO_IP, IP_HDRINCL, &hdrincl,
|
||||
hdrincl_len),
|
||||
ENOPROTOOPT);
|
||||
}
|
||||
END_TEST()
|
||||
|
|
|
|||
Loading…
Reference in New Issue