Skip to content

Commit 4825e9a

Browse files
committed
Implement Netlink socket syscall
Parse the socket type and the netlink family from the socket syscall parameters. The only supported socket types are SOCK_RAW and SOCK_DGRAM and the only supported netlink family is NETLINK_ROUTE.
1 parent 6aebdd3 commit 4825e9a

3 files changed

Lines changed: 107 additions & 0 deletions

File tree

src/main/host/descriptor/socket/mod.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use std::sync::Arc;
33
use atomic_refcell::AtomicRefCell;
44
use inet::{InetSocket, InetSocketRef, InetSocketRefMut};
55
use linux_api::ioctls::IoctlRequest;
6+
use netlink::NetlinkSocket;
67
use nix::sys::socket::Shutdown;
78
use shadow_shim_helper_rs::syscall_types::ForeignPtr;
89
use unix::UnixSocket;
@@ -21,6 +22,7 @@ use crate::utility::HostTreePointer;
2122

2223
pub mod abstract_unix_ns;
2324
pub mod inet;
25+
pub mod netlink;
2426
pub mod unix;
2527

2628
bitflags::bitflags! {
@@ -37,41 +39,47 @@ bitflags::bitflags! {
3739
pub enum Socket {
3840
Unix(Arc<AtomicRefCell<UnixSocket>>),
3941
Inet(InetSocket),
42+
Netlink(Arc<AtomicRefCell<NetlinkSocket>>),
4043
}
4144

4245
impl Socket {
4346
pub fn borrow(&self) -> SocketRef {
4447
match self {
4548
Self::Unix(ref f) => SocketRef::Unix(f.borrow()),
4649
Self::Inet(ref f) => SocketRef::Inet(f.borrow()),
50+
Self::Netlink(_) => todo!(),
4751
}
4852
}
4953

5054
pub fn try_borrow(&self) -> Result<SocketRef, atomic_refcell::BorrowError> {
5155
Ok(match self {
5256
Self::Unix(ref f) => SocketRef::Unix(f.try_borrow()?),
5357
Self::Inet(ref f) => SocketRef::Inet(f.try_borrow()?),
58+
Self::Netlink(_) => todo!(),
5459
})
5560
}
5661

5762
pub fn borrow_mut(&self) -> SocketRefMut {
5863
match self {
5964
Self::Unix(ref f) => SocketRefMut::Unix(f.borrow_mut()),
6065
Self::Inet(ref f) => SocketRefMut::Inet(f.borrow_mut()),
66+
Self::Netlink(_) => todo!(),
6167
}
6268
}
6369

6470
pub fn try_borrow_mut(&self) -> Result<SocketRefMut, atomic_refcell::BorrowMutError> {
6571
Ok(match self {
6672
Self::Unix(ref f) => SocketRefMut::Unix(f.try_borrow_mut()?),
6773
Self::Inet(ref f) => SocketRefMut::Inet(f.try_borrow_mut()?),
74+
Self::Netlink(_) => todo!(),
6875
})
6976
}
7077

7178
pub fn canonical_handle(&self) -> usize {
7279
match self {
7380
Self::Unix(f) => Arc::as_ptr(f) as usize,
7481
Self::Inet(ref f) => f.canonical_handle(),
82+
Self::Netlink(_) => todo!(),
7583
}
7684
}
7785

@@ -84,6 +92,7 @@ impl Socket {
8492
match self {
8593
Self::Unix(socket) => UnixSocket::bind(socket, addr, net_ns, rng),
8694
Self::Inet(socket) => InetSocket::bind(socket, addr, net_ns, rng),
95+
Self::Netlink(_) => todo!(),
8796
}
8897
}
8998

@@ -97,6 +106,7 @@ impl Socket {
97106
match self {
98107
Self::Unix(socket) => UnixSocket::listen(socket, backlog, net_ns, rng, cb_queue),
99108
Self::Inet(socket) => InetSocket::listen(socket, backlog, net_ns, rng, cb_queue),
109+
Self::Netlink(_) => todo!(),
100110
}
101111
}
102112

@@ -110,6 +120,7 @@ impl Socket {
110120
match self {
111121
Self::Unix(socket) => UnixSocket::connect(socket, addr, net_ns, rng, cb_queue),
112122
Self::Inet(socket) => InetSocket::connect(socket, addr, net_ns, rng, cb_queue),
123+
Self::Netlink(_) => todo!(),
113124
}
114125
}
115126

@@ -128,6 +139,9 @@ impl Socket {
128139
Self::Inet(socket) => {
129140
InetSocket::sendmsg(socket, args, memory_manager, net_ns, rng, cb_queue)
130141
}
142+
Self::Netlink(_) => {
143+
todo!()
144+
}
131145
}
132146
}
133147

@@ -140,6 +154,7 @@ impl Socket {
140154
match self {
141155
Self::Unix(socket) => UnixSocket::recvmsg(socket, args, memory_manager, cb_queue),
142156
Self::Inet(socket) => InetSocket::recvmsg(socket, args, memory_manager, cb_queue),
157+
Self::Netlink(_) => todo!(),
143158
}
144159
}
145160
}
@@ -149,6 +164,7 @@ impl std::fmt::Debug for Socket {
149164
match self {
150165
Self::Unix(_) => write!(f, "Unix")?,
151166
Self::Inet(_) => write!(f, "Inet")?,
167+
Self::Netlink(_) => todo!(),
152168
}
153169

154170
if let Ok(file) = self.try_borrow() {
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
use std::sync::Arc;
2+
3+
use atomic_refcell::AtomicRefCell;
4+
5+
pub struct NetlinkSocket {}
6+
7+
impl NetlinkSocket {
8+
pub fn new() -> Arc<AtomicRefCell<Self>> {
9+
Arc::new_cyclic(|weak| AtomicRefCell::new(Self {}))
10+
}
11+
}
12+
13+
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
14+
pub enum NetlinkSocketType {
15+
Dgram,
16+
Raw,
17+
}
18+
19+
impl TryFrom<libc::c_int> for NetlinkSocketType {
20+
type Error = NetlinkSocketTypeConversionError;
21+
fn try_from(val: libc::c_int) -> Result<Self, Self::Error> {
22+
match val {
23+
libc::SOCK_DGRAM => Ok(Self::Dgram),
24+
libc::SOCK_RAW => Ok(Self::Raw),
25+
x => Err(NetlinkSocketTypeConversionError(x)),
26+
}
27+
}
28+
}
29+
30+
#[derive(Copy, Clone, Debug)]
31+
pub struct NetlinkSocketTypeConversionError(libc::c_int);
32+
33+
impl std::error::Error for NetlinkSocketTypeConversionError {}
34+
35+
impl std::fmt::Display for NetlinkSocketTypeConversionError {
36+
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
37+
write!(
38+
f,
39+
"Invalid socket type {}; netlink sockets only support SOCK_DGRAM and SOCK_RAW",
40+
self.0
41+
)
42+
}
43+
}
44+
45+
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
46+
pub enum NetlinkFamily {
47+
Route,
48+
}
49+
50+
impl TryFrom<libc::c_int> for NetlinkFamily {
51+
type Error = NetlinkFamilyConversionError;
52+
fn try_from(val: libc::c_int) -> Result<Self, Self::Error> {
53+
match val {
54+
libc::NETLINK_ROUTE => Ok(Self::Route),
55+
x => Err(NetlinkFamilyConversionError(x)),
56+
}
57+
}
58+
}
59+
60+
#[derive(Copy, Clone, Debug)]
61+
pub struct NetlinkFamilyConversionError(libc::c_int);
62+
63+
impl std::error::Error for NetlinkFamilyConversionError {}
64+
65+
impl std::fmt::Display for NetlinkFamilyConversionError {
66+
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
67+
write!(
68+
f,
69+
"Invalid netlink family {}; netlink families only support NETLINK_ROUTE",
70+
self.0
71+
)
72+
}
73+
}

src/main/host/syscall/handler/socket.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ use crate::host::descriptor::socket::inet::legacy_tcp::LegacyTcpSocket;
99
use crate::host::descriptor::socket::inet::tcp::TcpSocket;
1010
use crate::host::descriptor::socket::inet::udp::UdpSocket;
1111
use crate::host::descriptor::socket::inet::InetSocket;
12+
use crate::host::descriptor::socket::netlink::{NetlinkFamily, NetlinkSocket, NetlinkSocketType};
1213
use crate::host::descriptor::socket::unix::{UnixSocket, UnixSocketType};
1314
use crate::host::descriptor::socket::{RecvmsgArgs, RecvmsgReturn, SendmsgArgs, Socket};
1415
use crate::host::descriptor::{CompatFile, Descriptor, File, FileState, FileStatus, OpenFile};
@@ -100,6 +101,23 @@ impl SyscallHandler {
100101
}
101102
_ => return Err(Errno::ESOCKTNOSUPPORT.into()),
102103
},
104+
libc::AF_NETLINK => {
105+
let socket_type = match NetlinkSocketType::try_from(socket_type) {
106+
Ok(x) => x,
107+
Err(e) => {
108+
warn!("{}", e);
109+
return Err(Errno::EPROTONOSUPPORT.into());
110+
}
111+
};
112+
let family = match NetlinkFamily::try_from(protocol) {
113+
Ok(x) => x,
114+
Err(e) => {
115+
warn!("{}", e);
116+
return Err(Errno::EPROTONOSUPPORT.into());
117+
}
118+
};
119+
Socket::Netlink(NetlinkSocket::new())
120+
}
103121
_ => return Err(Errno::EAFNOSUPPORT.into()),
104122
};
105123

0 commit comments

Comments
 (0)