1use std::io::{Cursor, ErrorKind, Read, Write};
2use std::net::Ipv4Addr;
3use std::sync::{Arc, Weak};
4
5use atomic_refcell::AtomicRefCell;
6use linux_api::errno::Errno;
7use linux_api::ioctls::IoctlRequest;
8use linux_api::netlink::{ifaddrmsg, ifinfomsg, nlmsghdr};
9use linux_api::rtnetlink::{RTM_GETADDR, RTM_GETLINK, RTMGRP_IPV4_IFADDR, RTMGRP_IPV6_IFADDR};
10use linux_api::socket::Shutdown;
11use neli::consts::nl::{NlmF, Nlmsg};
12use neli::consts::rtnl::{Arphrd, Ifa, IfaF, Iff, Ifla, RtAddrFamily, RtScope, Rtm};
13use neli::nl::{NlPayload, Nlmsghdr, NlmsghdrBuilder};
14use neli::rtnl::{Ifaddrmsg, IfaddrmsgBuilder, Ifinfomsg, IfinfomsgBuilder, RtattrBuilder};
15use neli::types::{Buffer, RtBuffer};
16use neli::{FromBytes, ToBytes};
17use nix::sys::socket::{MsgFlags, NetlinkAddr};
18use shadow_shim_helper_rs::syscall_types::ForeignPtr;
19
20use crate::core::worker::Worker;
21use crate::cshadow as c;
22use crate::host::descriptor::listener::{StateEventSource, StateListenHandle, StateListenerFilter};
23use crate::host::descriptor::shared_buf::{
24 BufferHandle, BufferSignals, BufferState, ReaderHandle, SharedBuf,
25};
26use crate::host::descriptor::socket::{RecvmsgArgs, RecvmsgReturn, SendmsgArgs, Socket};
27use crate::host::descriptor::{
28 File, FileMode, FileSignals, FileState, FileStatus, OpenFile, SyscallResult,
29};
30use crate::host::memory_manager::MemoryManager;
31use crate::host::network::namespace::NetworkNamespace;
32use crate::host::syscall::io::{IoVec, IoVecReader, IoVecWriter};
33use crate::host::syscall::types::SyscallError;
34use crate::utility::HostTreePointer;
35use crate::utility::callback_queue::CallbackQueue;
36use crate::utility::sockaddr::SockaddrStorage;
37
38const NETLINK_SOCKET_DEFAULT_BUFFER_SIZE: u64 = 212_992;
40
41pub struct NetlinkSocket {
42 common: NetlinkSocketCommon,
44 protocol_state: ProtocolState,
46}
47
48impl NetlinkSocket {
49 pub fn new(
50 status: FileStatus,
51 _socket_type: NetlinkSocketType,
52 _family: NetlinkFamily,
53 ) -> Arc<AtomicRefCell<Self>> {
54 Arc::new_cyclic(|weak| {
55 let buffer = SharedBuf::new(usize::MAX);
57 let buffer = Arc::new(AtomicRefCell::new(buffer));
58
59 let default_ip = Worker::with_active_host(|host| host.default_ip()).unwrap();
61 let interfaces = vec![
63 Interface {
64 address: Ipv4Addr::LOCALHOST,
65 label: String::from("lo"),
66 prefix_len: 8,
67 if_type: Arphrd::Loopback,
68 mtu: c::CONFIG_MTU,
69 scope: RtScope::Host,
70 index: 1,
71 },
72 Interface {
73 address: default_ip,
74 label: String::from("eth0"),
75 prefix_len: 24,
76 if_type: Arphrd::Ether,
77 mtu: c::CONFIG_MTU,
78 scope: RtScope::Universe,
79 index: 2,
80 },
81 ];
82
83 let mut common = NetlinkSocketCommon {
84 buffer,
85 send_limit: NETLINK_SOCKET_DEFAULT_BUFFER_SIZE,
86 sent_len: 0,
87 event_source: StateEventSource::new(),
88 state: FileState::ACTIVE,
89 status,
90 has_open_file: false,
91 interfaces,
92 };
93 let protocol_state = ProtocolState::new(&mut common, weak);
94 let mut socket = Self {
95 common,
96 protocol_state,
97 };
98 CallbackQueue::queue_and_run_with_legacy(|cb_queue| {
99 socket.refresh_file_state(FileSignals::empty(), cb_queue)
100 });
101
102 AtomicRefCell::new(socket)
103 })
104 }
105
106 pub fn status(&self) -> FileStatus {
107 self.common.status
108 }
109
110 pub fn set_status(&mut self, status: FileStatus) {
111 self.common.status = status;
112 }
113
114 pub fn mode(&self) -> FileMode {
115 FileMode::READ | FileMode::WRITE
116 }
117
118 pub fn has_open_file(&self) -> bool {
119 self.common.has_open_file
120 }
121
122 pub fn supports_sa_restart(&self) -> bool {
123 self.common.supports_sa_restart()
124 }
125
126 pub fn set_has_open_file(&mut self, val: bool) {
127 self.common.has_open_file = val;
128 }
129
130 pub fn getsockname(&self) -> Result<Option<nix::sys::socket::NetlinkAddr>, Errno> {
131 self.protocol_state.bound_address()
132 }
133
134 pub fn getpeername(&self) -> Result<Option<nix::sys::socket::NetlinkAddr>, Errno> {
135 warn_once_then_debug!(
136 "getpeername() syscall not yet supported for netlink sockets; Returning ENOSYS"
137 );
138 Err(Errno::ENOSYS)
139 }
140
141 pub fn address_family(&self) -> linux_api::socket::AddressFamily {
142 linux_api::socket::AddressFamily::AF_NETLINK
143 }
144
145 pub fn close(&mut self, cb_queue: &mut CallbackQueue) -> Result<(), SyscallError> {
146 self.protocol_state.close(&mut self.common, cb_queue)
147 }
148
149 fn refresh_file_state(&mut self, signals: FileSignals, cb_queue: &mut CallbackQueue) {
150 self.protocol_state
151 .refresh_file_state(&mut self.common, signals, cb_queue)
152 }
153
154 pub fn shutdown(
155 &mut self,
156 _how: Shutdown,
157 _cb_queue: &mut CallbackQueue,
158 ) -> Result<(), SyscallError> {
159 warn_once_then_debug!(
160 "shutdown() syscall not yet supported for netlink sockets; Returning ENOSYS"
161 );
162 Err(Errno::ENOSYS.into())
163 }
164
165 pub fn getsockopt(
166 &mut self,
167 _level: libc::c_int,
168 _optname: libc::c_int,
169 _optval_ptr: ForeignPtr<()>,
170 _optlen: libc::socklen_t,
171 _memory_manager: &mut MemoryManager,
172 _cb_queue: &mut CallbackQueue,
173 ) -> Result<libc::socklen_t, SyscallError> {
174 warn_once_then_debug!(
175 "getsockopt() syscall not yet supported for netlink sockets; Returning ENOSYS"
176 );
177 Err(Errno::ENOSYS.into())
178 }
179
180 pub fn setsockopt(
181 &mut self,
182 level: libc::c_int,
183 optname: libc::c_int,
184 optval_ptr: ForeignPtr<()>,
185 optlen: libc::socklen_t,
186 memory_manager: &MemoryManager,
187 ) -> Result<(), SyscallError> {
188 match (level, optname) {
189 (libc::SOL_SOCKET, libc::SO_SNDBUF) => {
190 type OptType = libc::c_int;
191
192 if usize::try_from(optlen).unwrap() < std::mem::size_of::<OptType>() {
193 return Err(Errno::EINVAL.into());
194 }
195
196 let optval_ptr = optval_ptr.cast::<OptType>();
197 let val: u64 = memory_manager
198 .read(optval_ptr)?
199 .try_into()
200 .or(Err(Errno::EINVAL))?;
201
202 let val = val * 2;
204 let val = std::cmp::max(val, self.common.sent_len);
206 let val = std::cmp::max(val, 4096);
208 let val = std::cmp::min(val, 268435456); self.common.send_limit = val;
211 }
212 (libc::SOL_SOCKET, libc::SO_RCVBUF) => {
213 }
217 _ => {
218 warn_once_then_debug!(
219 "setsockopt called with unsupported level {level} and opt {optname}"
220 );
221 return Err(Errno::ENOPROTOOPT.into());
222 }
223 }
224
225 Ok(())
226 }
227
228 pub fn bind(
229 socket: &Arc<AtomicRefCell<Self>>,
230 addr: Option<&SockaddrStorage>,
231 _net_ns: &NetworkNamespace,
232 rng: impl rand::Rng,
233 ) -> Result<(), SyscallError> {
234 let socket_ref = &mut *socket.borrow_mut();
235 socket_ref
236 .protocol_state
237 .bind(&mut socket_ref.common, socket, addr, rng)
238 }
239
240 pub fn readv(
241 &mut self,
242 _iovs: &[IoVec],
243 _offset: Option<libc::off_t>,
244 _flags: libc::c_int,
245 _mem: &mut MemoryManager,
246 _cb_queue: &mut CallbackQueue,
247 ) -> Result<libc::ssize_t, SyscallError> {
248 panic!("Called NetlinkSocket::readv() on a netlink socket.");
252 }
253
254 pub fn writev(
255 &mut self,
256 _iovs: &[IoVec],
257 _offset: Option<libc::off_t>,
258 _flags: libc::c_int,
259 _mem: &mut MemoryManager,
260 _cb_queue: &mut CallbackQueue,
261 ) -> Result<libc::ssize_t, SyscallError> {
262 panic!("Called NetlinkSocket::writev() on a netlink socket");
266 }
267
268 pub fn sendmsg(
269 socket: &Arc<AtomicRefCell<Self>>,
270 args: SendmsgArgs,
271 mem: &mut MemoryManager,
272 _net_ns: &NetworkNamespace,
273 _rng: impl rand::Rng,
274 cb_queue: &mut CallbackQueue,
275 ) -> Result<libc::ssize_t, SyscallError> {
276 let socket_ref = &mut *socket.borrow_mut();
277 socket_ref
278 .protocol_state
279 .sendmsg(&mut socket_ref.common, socket, args, mem, cb_queue)
280 }
281
282 pub fn recvmsg(
283 socket: &Arc<AtomicRefCell<Self>>,
284 args: RecvmsgArgs,
285 mem: &mut MemoryManager,
286 cb_queue: &mut CallbackQueue,
287 ) -> Result<RecvmsgReturn, SyscallError> {
288 let socket_ref = &mut *socket.borrow_mut();
289 socket_ref
290 .protocol_state
291 .recvmsg(&mut socket_ref.common, socket, args, mem, cb_queue)
292 }
293
294 pub fn listen(
295 _socket: &Arc<AtomicRefCell<Self>>,
296 _backlog: i32,
297 _net_ns: &NetworkNamespace,
298 _rng: impl rand::Rng,
299 _cb_queue: &mut CallbackQueue,
300 ) -> Result<(), Errno> {
301 warn_once_then_debug!("We do not yet handle listen request on netlink sockets");
302 Err(Errno::EINVAL)
303 }
304
305 pub fn connect(
306 _socket: &Arc<AtomicRefCell<Self>>,
307 _addr: &SockaddrStorage,
308 _net_ns: &NetworkNamespace,
309 _rng: impl rand::Rng,
310 _cb_queue: &mut CallbackQueue,
311 ) -> Result<(), SyscallError> {
312 warn_once_then_debug!("We do not yet handle connect request on netlink sockets");
313 Err(Errno::EINVAL.into())
314 }
315
316 pub fn accept(
317 &mut self,
318 _net_ns: &NetworkNamespace,
319 _rng: impl rand::Rng,
320 _cb_queue: &mut CallbackQueue,
321 ) -> Result<OpenFile, SyscallError> {
322 warn_once_then_debug!("We do not yet handle accept request on netlink sockets");
323 Err(Errno::EINVAL.into())
324 }
325
326 pub fn ioctl(
327 &mut self,
328 request: IoctlRequest,
329 _arg_ptr: ForeignPtr<()>,
330 _memory_manager: &mut MemoryManager,
331 ) -> SyscallResult {
332 warn_once_then_debug!("We do not yet handle ioctl request {request:?} on netlink sockets");
333 Err(Errno::EINVAL.into())
334 }
335
336 pub fn stat(&self) -> Result<linux_api::stat::stat, SyscallError> {
337 warn_once_then_debug!("We do not yet handle stat calls on netlink sockets");
338 Err(Errno::EINVAL.into())
339 }
340
341 pub fn lseek(
342 &mut self,
343 _off: linux_api::posix_types::kernel_off_t,
344 _whence: linux_api::unistd::LSeekWhence,
345 ) -> Result<linux_api::posix_types::kernel_off_t, SyscallError> {
346 warn_once_then_debug!("We do not yet handle lseek calls on netlink sockets");
347 Err(Errno::EBADF.into())
348 }
349
350 pub fn add_listener(
351 &mut self,
352 monitoring_state: FileState,
353 monitoring_signals: FileSignals,
354 filter: StateListenerFilter,
355 notify_fn: impl Fn(FileState, FileState, FileSignals, &mut CallbackQueue)
356 + Send
357 + Sync
358 + 'static,
359 ) -> StateListenHandle {
360 self.common.event_source.add_listener(
361 monitoring_state,
362 monitoring_signals,
363 filter,
364 notify_fn,
365 )
366 }
367
368 pub fn add_legacy_listener(&mut self, ptr: HostTreePointer<c::StatusListener>) {
369 self.common.event_source.add_legacy_listener(ptr);
370 }
371
372 pub fn remove_legacy_listener(&mut self, ptr: *mut c::StatusListener) {
373 self.common.event_source.remove_legacy_listener(ptr);
374 }
375
376 pub fn state(&self) -> FileState {
377 self.common.state
378 }
379}
380
381struct InitialState {
382 bound_addr: Option<NetlinkAddr>,
383 reader_handle: ReaderHandle,
384 _buffer_handle: BufferHandle,
386}
387struct ClosedState {}
388enum ProtocolState {
392 Initial(Option<InitialState>),
393 Closed(Option<ClosedState>),
394}
395
396macro_rules! state_upcast {
398 ($type:ty, $parent:ident::$variant:ident) => {
399 impl From<$type> for $parent {
400 fn from(x: $type) -> Self {
401 Self::$variant(Some(x))
402 }
403 }
404 };
405}
406
407state_upcast!(InitialState, ProtocolState::Initial);
409state_upcast!(ClosedState, ProtocolState::Closed);
410
411impl ProtocolState {
412 fn new(common: &mut NetlinkSocketCommon, socket: &Weak<AtomicRefCell<NetlinkSocket>>) -> Self {
413 let mut cb_queue = CallbackQueue::new();
415
416 let reader_handle = common.buffer.borrow_mut().add_reader(&mut cb_queue);
418
419 let weak = Weak::clone(socket);
420 let buffer_handle = common.buffer.borrow_mut().add_listener(
421 BufferState::READABLE,
422 BufferSignals::BUFFER_GREW,
423 move |_, signals, cb_queue| {
424 if let Some(socket) = weak.upgrade() {
425 let signals = if signals.contains(BufferSignals::BUFFER_GREW) {
426 FileSignals::READ_BUFFER_GREW
427 } else {
428 FileSignals::empty()
429 };
430
431 socket.borrow_mut().refresh_file_state(signals, cb_queue);
432 }
433 },
434 );
435
436 ProtocolState::Initial(Some(InitialState {
437 bound_addr: None,
438 reader_handle,
439 _buffer_handle: buffer_handle,
440 }))
441 }
442
443 fn bound_address(&self) -> Result<Option<NetlinkAddr>, Errno> {
444 match self {
445 Self::Initial(x) => x.as_ref().unwrap().bound_address(),
446 Self::Closed(x) => x.as_ref().unwrap().bound_address(),
447 }
448 }
449
450 fn refresh_file_state(
451 &self,
452 common: &mut NetlinkSocketCommon,
453 signals: FileSignals,
454 cb_queue: &mut CallbackQueue,
455 ) {
456 match self {
457 Self::Initial(x) => x
458 .as_ref()
459 .unwrap()
460 .refresh_file_state(common, signals, cb_queue),
461 Self::Closed(x) => x
462 .as_ref()
463 .unwrap()
464 .refresh_file_state(common, signals, cb_queue),
465 }
466 }
467
468 fn close(
469 &mut self,
470 common: &mut NetlinkSocketCommon,
471 cb_queue: &mut CallbackQueue,
472 ) -> Result<(), SyscallError> {
473 let (new_state, rv) = match self {
474 Self::Initial(x) => x.take().unwrap().close(common, cb_queue),
475 Self::Closed(x) => x.take().unwrap().close(common, cb_queue),
476 };
477
478 *self = new_state;
479 rv
480 }
481
482 fn bind(
483 &mut self,
484 common: &mut NetlinkSocketCommon,
485 socket: &Arc<AtomicRefCell<NetlinkSocket>>,
486 addr: Option<&SockaddrStorage>,
487 rng: impl rand::Rng,
488 ) -> Result<(), SyscallError> {
489 match self {
490 Self::Initial(x) => x.as_mut().unwrap().bind(common, socket, addr, rng),
491 Self::Closed(x) => x.as_mut().unwrap().bind(common, socket, addr, rng),
492 }
493 }
494
495 fn sendmsg(
496 &mut self,
497 common: &mut NetlinkSocketCommon,
498 socket: &Arc<AtomicRefCell<NetlinkSocket>>,
499 args: SendmsgArgs,
500 mem: &mut MemoryManager,
501 cb_queue: &mut CallbackQueue,
502 ) -> Result<libc::ssize_t, SyscallError> {
503 match self {
504 Self::Initial(x) => x
505 .as_mut()
506 .unwrap()
507 .sendmsg(common, socket, args, mem, cb_queue),
508 Self::Closed(x) => x
509 .as_mut()
510 .unwrap()
511 .sendmsg(common, socket, args, mem, cb_queue),
512 }
513 }
514
515 fn recvmsg(
516 &mut self,
517 common: &mut NetlinkSocketCommon,
518 socket: &Arc<AtomicRefCell<NetlinkSocket>>,
519 args: RecvmsgArgs,
520 mem: &mut MemoryManager,
521 cb_queue: &mut CallbackQueue,
522 ) -> Result<RecvmsgReturn, SyscallError> {
523 match self {
524 Self::Initial(x) => x
525 .as_mut()
526 .unwrap()
527 .recvmsg(common, socket, args, mem, cb_queue),
528 Self::Closed(x) => x
529 .as_mut()
530 .unwrap()
531 .recvmsg(common, socket, args, mem, cb_queue),
532 }
533 }
534}
535
536impl InitialState {
537 fn bound_address(&self) -> Result<Option<NetlinkAddr>, Errno> {
538 Ok(self.bound_addr)
539 }
540
541 fn refresh_file_state(
542 &self,
543 common: &mut NetlinkSocketCommon,
544 signals: FileSignals,
545 cb_queue: &mut CallbackQueue,
546 ) {
547 let mut new_state = FileState::ACTIVE;
548
549 {
550 let buffer = common.buffer.borrow();
551
552 new_state.set(FileState::READABLE, buffer.has_data());
553 new_state.set(FileState::WRITABLE, common.sent_len < common.send_limit);
554 }
555
556 common.update_state(
557 FileState::all(),
558 new_state,
559 signals,
560 cb_queue,
561 );
562 }
563
564 fn close(
565 self,
566 common: &mut NetlinkSocketCommon,
567 cb_queue: &mut CallbackQueue,
568 ) -> (ProtocolState, Result<(), SyscallError>) {
569 common
571 .buffer
572 .borrow_mut()
573 .remove_reader(self.reader_handle, cb_queue);
574
575 let new_state = ClosedState {};
576 new_state.refresh_file_state(common, FileSignals::empty(), cb_queue);
577 (new_state.into(), Ok(()))
578 }
579
580 fn bind(
581 &mut self,
582 _common: &mut NetlinkSocketCommon,
583 _socket: &Arc<AtomicRefCell<NetlinkSocket>>,
584 addr: Option<&SockaddrStorage>,
585 _rng: impl rand::Rng,
586 ) -> Result<(), SyscallError> {
587 if self.bound_addr.is_some() {
589 return Err(Errno::EINVAL.into());
590 }
591 if addr.is_none() {
593 return Err(Errno::EFAULT.into());
594 }
595
596 let Some(addr) = addr.and_then(|x| x.as_netlink()) else {
598 log::warn!("Attempted to bind netlink socket to non-netlink address {addr:?}");
599 return Err(Errno::EINVAL.into());
600 };
601
602 self.bound_addr = Some(*addr);
606
607 if (addr.groups() & !(RTMGRP_IPV4_IFADDR | RTMGRP_IPV6_IFADDR)) != 0 {
610 log::warn!(
611 "Attempted to bind netlink socket to an address with unsupported groups {}",
612 addr.groups()
613 );
614 return Err(Errno::EINVAL.into());
615 }
616
617 Ok(())
618 }
619
620 fn sendmsg(
621 &mut self,
622 common: &mut NetlinkSocketCommon,
623 socket: &Arc<AtomicRefCell<NetlinkSocket>>,
624 args: SendmsgArgs,
625 mem: &mut MemoryManager,
626 cb_queue: &mut CallbackQueue,
627 ) -> Result<libc::ssize_t, SyscallError> {
628 if !args.control_ptr.ptr().is_null() {
629 log::debug!("Netlink sockets don't yet support control data for sendmsg()");
630 return Err(Errno::EINVAL.into());
631 }
632
633 if let Some(addr) = args.addr {
635 let Some(addr) = addr.as_netlink() else {
637 log::warn!("Attempted to send to non-netlink address {:?}", args.addr);
638 return Err(Errno::EINVAL.into());
639 };
640 if addr.pid() != 0 {
642 log::warn!("Attempted to send to non-kernel netlink address {addr:?}");
643 return Err(Errno::EINVAL.into());
644 }
645 if addr.groups() != 0 {
647 log::warn!("Attempted to send to netlink groups {addr:?}");
648 return Err(Errno::EINVAL.into());
649 }
650 }
651
652 let rv = common.sendmsg(socket, args.iovs, args.flags, mem, cb_queue)?;
653
654 self.refresh_file_state(common, FileSignals::empty(), cb_queue);
655
656 Ok(rv.try_into().unwrap())
657 }
658
659 fn recvmsg(
660 &mut self,
661 common: &mut NetlinkSocketCommon,
662 socket: &Arc<AtomicRefCell<NetlinkSocket>>,
663 args: RecvmsgArgs,
664 mem: &mut MemoryManager,
665 cb_queue: &mut CallbackQueue,
666 ) -> Result<RecvmsgReturn, SyscallError> {
667 if !args.control_ptr.ptr().is_null() {
668 log::debug!("Netlink sockets don't yet support control data for recvmsg()");
669 return Err(Errno::EINVAL.into());
670 }
671 let Some(flags) = MsgFlags::from_bits(args.flags) else {
672 warn_once_then_debug!("Unrecognized recv flags: {:#b}", args.flags);
673 return Err(Errno::EINVAL.into());
674 };
675
676 let mut packet_buffer = Vec::new();
677 let (_rv, _num_removed_from_buf) =
678 common.recvmsg(socket, &mut packet_buffer, flags, mem, cb_queue)?;
679 self.refresh_file_state(common, FileSignals::empty(), cb_queue);
680
681 let mut writer = IoVecWriter::new(args.iovs, mem);
682
683 let src_addr = SockaddrStorage::from_netlink(&NetlinkAddr::new(0, 0));
685
686 if packet_buffer.len() < std::mem::size_of::<nlmsghdr>() {
687 log::warn!("The processed packet is too short");
688 return Err(Errno::EINVAL.into());
689 }
690
691 let buffer = {
692 let nlmsg_type = &packet_buffer[memoffset::span_of!(nlmsghdr, nlmsg_type)];
693 let nlmsg_type = u16::from_ne_bytes(nlmsg_type.try_into().unwrap());
694
695 match nlmsg_type {
696 RTM_GETLINK => {
697 let nlmsghdr_len = std::mem::size_of::<nlmsghdr>();
698 let ifinfomsg_len = std::mem::size_of::<ifinfomsg>();
699 let header_len = nlmsghdr_len + ifinfomsg_len;
700
701 if (nlmsghdr_len..header_len).contains(&packet_buffer.len()) {
707 log::debug!(
708 "Padding the RTM_GETLINK with zeroes to meet the minimum length"
709 );
710 packet_buffer.resize(header_len, 0);
711 packet_buffer[memoffset::span_of!(nlmsghdr, nlmsg_len)]
712 .copy_from_slice(&(header_len as u32).to_ne_bytes()[..]);
713 }
714 self.handle_ifinfomsg(common, &packet_buffer[..])
715 }
716 RTM_GETADDR => {
717 let nlmsghdr_len = std::mem::size_of::<nlmsghdr>();
718 let ifaddrmsg_len = std::mem::size_of::<ifaddrmsg>();
719 let header_len = nlmsghdr_len + ifaddrmsg_len;
720
721 if (nlmsghdr_len..header_len).contains(&packet_buffer.len()) {
727 log::debug!(
728 "Padding the RTM_GETADDR with zeroes to meet the minimum length"
729 );
730 packet_buffer.resize(header_len, 0);
731 packet_buffer[memoffset::span_of!(nlmsghdr, nlmsg_len)]
732 .copy_from_slice(&(header_len as u32).to_ne_bytes()[..]);
733 }
734 self.handle_ifaddrmsg(common, &packet_buffer[..])
735 }
736 _ => {
737 warn_once_then_debug!(
738 "Found unsupported nlmsg_type: {nlmsg_type} (only RTM_GETLINK
739 and RTM_GETADDR are supported)"
740 );
741 self.handle_error(&packet_buffer[..])
742 }
743 }
744 };
745
746 let mut total_copied = 0;
748 let mut buf = buffer.as_slice();
749 while !buf.is_empty() {
750 match writer.write(buf) {
751 Ok(0) => break,
752 Ok(n) => {
753 buf = &buf[n..];
754 total_copied += n;
755 }
756 Err(ref e) if e.kind() == ErrorKind::Interrupted => continue,
757 Err(e) => return Err(e.into()),
758 }
759 }
760
761 let return_val = if flags.contains(MsgFlags::MSG_TRUNC) {
762 buffer.len()
763 } else {
764 total_copied
765 };
766
767 Ok(RecvmsgReturn {
768 return_val: return_val.try_into().unwrap(),
769 addr: Some(src_addr),
770 msg_flags: 0,
771 control_len: 0,
772 })
773 }
774
775 fn handle_error(&self, bytes: &[u8]) -> Vec<u8> {
776 let nlmsg_seq = match bytes.get(memoffset::span_of!(nlmsghdr, nlmsg_seq)) {
778 Some(x) => u32::from_ne_bytes(x.try_into().unwrap()),
779 None => 0,
780 };
781
782 let msg = NlmsghdrBuilder::default()
784 .nl_type(Nlmsg::Error)
785 .nl_flags(NlmF::empty())
786 .nl_seq(nlmsg_seq)
787 .nl_payload(NlPayload::<Nlmsg, ()>::Empty)
788 .build()
789 .expect("NlmsghdrBuilder missing a required field");
790
791 let mut buffer = Cursor::new(Vec::new());
792 msg.to_bytes(&mut buffer).unwrap();
793 buffer.into_inner()
794 }
795
796 fn handle_ifaddrmsg(&self, common: &mut NetlinkSocketCommon, bytes: &[u8]) -> Vec<u8> {
797 let Ok(nlmsg) = Nlmsghdr::<Rtm, Ifaddrmsg>::from_bytes(&mut Cursor::new(bytes)) else {
798 log::warn!("Failed to deserialize the message");
799 return self.handle_error(bytes);
800 };
801
802 let Some(ifaddrmsg) = nlmsg.get_payload() else {
803 log::warn!("Failed to find the payload");
804 return self.handle_error(bytes);
805 };
806
807 if *ifaddrmsg.ifa_family() != RtAddrFamily::Unspecified
809 && *ifaddrmsg.ifa_family() != RtAddrFamily::Inet
810 {
811 log::warn!("Unsupported ifa_family (only AF_UNSPEC and AF_INET are supported)");
812 return self.handle_error(bytes);
813 }
814
815 if *ifaddrmsg.ifa_prefixlen() != 0
817 || !ifaddrmsg.ifa_flags().is_empty()
818 || *ifaddrmsg.ifa_index() != 0
819 || *ifaddrmsg.ifa_scope() != RtScope::Universe
820 {
821 log::warn!(
822 "Unsupported ifa_prefixlen, ifa_flags, ifa_scope, or ifa_index (they have to be 0)",
823 );
824 return self.handle_error(bytes);
825 }
826
827 let mut buffer = Cursor::new(Vec::new());
828 for interface in &common.interfaces {
830 let address = interface.address.octets();
831 let broadcast = Ipv4Addr::from(
832 0xffff_ffff_u32
833 .checked_shr(u32::from(interface.prefix_len))
834 .unwrap_or(0)
835 | u32::from(interface.address),
836 )
837 .octets();
838 let mut label = Vec::from(interface.label.as_bytes());
839 label.push(0); let attrs = [
843 RtattrBuilder::default()
847 .rta_type(Ifa::Address)
848 .rta_payload(Buffer::from(&address[..]))
849 .build()
850 .unwrap(),
851 RtattrBuilder::default()
852 .rta_type(Ifa::Local)
853 .rta_payload(Buffer::from(&address[..]))
854 .build()
855 .unwrap(),
856 RtattrBuilder::default()
857 .rta_type(Ifa::Broadcast)
858 .rta_payload(Buffer::from(&broadcast[..]))
859 .build()
860 .unwrap(),
861 RtattrBuilder::default()
862 .rta_type(Ifa::Label)
863 .rta_payload(Buffer::from(label))
864 .build()
865 .unwrap(),
866 ];
867 let ifaddrmsg = IfaddrmsgBuilder::default()
868 .ifa_family(RtAddrFamily::Inet)
869 .ifa_prefixlen(interface.prefix_len)
870 .ifa_flags(IfaF::PERMANENT)
872 .ifa_scope(interface.scope)
873 .ifa_index(interface.index)
874 .rtattrs(RtBuffer::from_iter(attrs))
875 .build()
876 .expect("IfaddrmsgBuilder missing a required field");
877 let nlmsg = NlmsghdrBuilder::default()
878 .nl_type(Rtm::Newaddr)
879 .nl_flags(NlmF::MULTI)
881 .nl_seq(*nlmsg.nl_seq())
883 .nl_payload(NlPayload::Payload(ifaddrmsg))
884 .build()
885 .expect("NlmsghdrBuilder missing a required field");
886 nlmsg.to_bytes(&mut buffer).unwrap();
887 }
888 let done_msg = NlmsghdrBuilder::default()
890 .nl_type(Nlmsg::Done)
891 .nl_flags(NlmF::MULTI)
892 .nl_seq(*nlmsg.nl_seq())
894 .nl_payload(NlPayload::Payload(0u32))
900 .build()
901 .expect("NlmsghdrBuilder missing a required field");
902 done_msg.to_bytes(&mut buffer).unwrap();
903
904 buffer.into_inner()
905 }
906
907 fn handle_ifinfomsg(&self, common: &mut NetlinkSocketCommon, bytes: &[u8]) -> Vec<u8> {
908 let Ok(nlmsg) = Nlmsghdr::<Rtm, Ifinfomsg>::from_bytes(&mut Cursor::new(bytes)) else {
909 log::warn!("Failed to deserialize the message");
910 return self.handle_error(bytes);
911 };
912
913 let Some(ifinfomsg) = nlmsg.get_payload() else {
914 log::warn!("Failed to find the payload");
915 return self.handle_error(bytes);
916 };
917
918 if *ifinfomsg.ifi_family() != RtAddrFamily::Unspecified
920 && *ifinfomsg.ifi_family() != RtAddrFamily::Inet
921 {
922 warn_once_then_debug!(
923 "Unsupported ifi_family (only AF_UNSPEC and AF_INET are supported)"
924 );
925 return self.handle_error(bytes);
926 }
927
928 if *ifinfomsg.ifi_type() != 0.into()
930 || *ifinfomsg.ifi_index() != 0
931 || !ifinfomsg.ifi_flags().is_empty()
932 {
933 warn_once_then_debug!(
934 "Unsupported ifi_type, ifi_index, or ifi_flags (they have to be 0)"
935 );
936 return self.handle_error(bytes);
937 }
938
939 let mut buffer = Cursor::new(Vec::new());
943 for interface in &common.interfaces {
945 let mut label = Vec::from(interface.label.as_bytes());
946 label.push(0); let attrs = [
950 RtattrBuilder::default()
951 .rta_type(Ifla::Ifname)
952 .rta_payload(Buffer::from(label))
953 .build()
954 .unwrap(),
955 RtattrBuilder::default()
959 .rta_type(Ifla::Txqlen)
960 .rta_payload(Buffer::from(&u32::to_le_bytes(1000)[..]))
961 .build()
962 .unwrap(),
963 RtattrBuilder::default()
964 .rta_type(Ifla::Mtu)
965 .rta_payload(Buffer::from(&u32::to_le_bytes(interface.mtu)[..]))
966 .build()
967 .unwrap(),
968 ];
970 let flags = if interface.if_type == Arphrd::Loopback {
971 Iff::UP | Iff::LOOPBACK | Iff::RUNNING
972 } else {
973 Iff::UP | Iff::BROADCAST | Iff::RUNNING | Iff::MULTICAST
975 };
976 let interface_index = interface
977 .index
978 .try_into()
979 .expect("interface index too large");
980
981 let ifinfomsg = IfinfomsgBuilder::default()
982 .ifi_family(RtAddrFamily::Inet)
983 .ifi_type(interface.if_type)
984 .ifi_index(interface_index)
985 .ifi_flags(flags)
986 .ifi_change(Iff::from_bits_retain(0xffffffff))
988 .rtattrs(RtBuffer::from_iter(attrs))
989 .build()
990 .expect("IfinfomsgBuilder missing a required field");
991 let nlmsg = NlmsghdrBuilder::default()
992 .nl_type(Rtm::Newlink)
993 .nl_flags(NlmF::MULTI)
995 .nl_seq(*nlmsg.nl_seq())
997 .nl_payload(NlPayload::Payload(ifinfomsg))
998 .build()
999 .expect("NlmsghdrBuilder missing a required field");
1000 nlmsg.to_bytes(&mut buffer).unwrap();
1001 }
1002 let done_msg = NlmsghdrBuilder::default()
1004 .nl_type(Nlmsg::Done)
1005 .nl_flags(NlmF::MULTI)
1006 .nl_seq(*nlmsg.nl_seq())
1008 .nl_payload(NlPayload::Payload(0u32))
1014 .build()
1015 .expect("NlmsghdrBuilder missing a required field");
1016 done_msg.to_bytes(&mut buffer).unwrap();
1017
1018 buffer.into_inner()
1019 }
1020}
1021
1022impl ClosedState {
1023 fn bound_address(&self) -> Result<Option<NetlinkAddr>, Errno> {
1024 Ok(None)
1025 }
1026
1027 fn refresh_file_state(
1028 &self,
1029 common: &mut NetlinkSocketCommon,
1030 signals: FileSignals,
1031 cb_queue: &mut CallbackQueue,
1032 ) {
1033 common.update_state(
1034 FileState::all(),
1035 FileState::CLOSED,
1036 signals,
1037 cb_queue,
1038 );
1039 }
1040
1041 fn close(
1042 self,
1043 _common: &mut NetlinkSocketCommon,
1044 _cb_queue: &mut CallbackQueue,
1045 ) -> (ProtocolState, Result<(), SyscallError>) {
1046 panic!("Trying to close an already closed socket");
1048 }
1049
1050 fn bind(
1051 &mut self,
1052 _common: &mut NetlinkSocketCommon,
1053 _socket: &Arc<AtomicRefCell<NetlinkSocket>>,
1054 _addr: Option<&SockaddrStorage>,
1055 _rng: impl rand::Rng,
1056 ) -> Result<(), SyscallError> {
1057 log::warn!("bind() while in state {}", std::any::type_name::<Self>());
1059 Err(Errno::EOPNOTSUPP.into())
1060 }
1061
1062 fn sendmsg(
1063 &mut self,
1064 _common: &mut NetlinkSocketCommon,
1065 _socket: &Arc<AtomicRefCell<NetlinkSocket>>,
1066 _args: SendmsgArgs,
1067 _mem: &mut MemoryManager,
1068 _cb_queue: &mut CallbackQueue,
1069 ) -> Result<libc::ssize_t, SyscallError> {
1070 log::warn!("sendmsg() while in state {}", std::any::type_name::<Self>());
1072 Err(Errno::EOPNOTSUPP.into())
1073 }
1074
1075 fn recvmsg(
1076 &mut self,
1077 _common: &mut NetlinkSocketCommon,
1078 _socket: &Arc<AtomicRefCell<NetlinkSocket>>,
1079 _args: RecvmsgArgs,
1080 _mem: &mut MemoryManager,
1081 _cb_queue: &mut CallbackQueue,
1082 ) -> Result<RecvmsgReturn, SyscallError> {
1083 log::warn!("recvmsg() while in state {}", std::any::type_name::<Self>());
1085 Err(Errno::EOPNOTSUPP.into())
1086 }
1087}
1088
1089struct Interface {
1091 address: Ipv4Addr,
1092 label: String,
1093 prefix_len: u8,
1094 if_type: Arphrd,
1095 mtu: u32,
1096 scope: RtScope,
1097 index: libc::c_uint,
1098}
1099
1100struct NetlinkSocketCommon {
1102 buffer: Arc<AtomicRefCell<SharedBuf>>,
1103 send_limit: u64,
1105 sent_len: u64,
1107 event_source: StateEventSource,
1108 state: FileState,
1109 status: FileStatus,
1110 has_open_file: bool,
1113 interfaces: Vec<Interface>,
1115}
1116
1117impl NetlinkSocketCommon {
1118 pub fn supports_sa_restart(&self) -> bool {
1119 true
1120 }
1121
1122 pub fn sendmsg(
1123 &mut self,
1124 socket: &Arc<AtomicRefCell<NetlinkSocket>>,
1125 iovs: &[IoVec],
1126 flags: libc::c_int,
1127 mem: &mut MemoryManager,
1128 cb_queue: &mut CallbackQueue,
1129 ) -> Result<usize, SyscallError> {
1130 let supported_flags = MsgFlags::MSG_DONTWAIT | MsgFlags::MSG_NOSIGNAL | MsgFlags::MSG_TRUNC;
1133
1134 let Some(mut flags) = MsgFlags::from_bits(flags) else {
1137 warn_once_then_debug!("Unrecognized send flags: {:#b}", flags);
1138 return Err(Errno::EINVAL.into());
1139 };
1140 if flags.intersects(!supported_flags) {
1141 warn_once_then_debug!("Unsupported send flags: {:?}", flags);
1142 return Err(Errno::EINVAL.into());
1143 }
1144
1145 if self.status.contains(FileStatus::NONBLOCK) {
1146 flags.insert(MsgFlags::MSG_DONTWAIT);
1147 }
1148
1149 let result = (|| {
1151 let len = iovs.iter().map(|x| x.len).sum::<libc::size_t>();
1152
1153 let space_available = self
1156 .send_limit
1157 .saturating_sub(self.sent_len)
1158 .try_into()
1159 .unwrap();
1160
1161 if space_available == 0 {
1162 return Err(Errno::EAGAIN);
1163 }
1164
1165 if len > space_available {
1166 if len <= self.send_limit.try_into().unwrap() {
1167 return Err(Errno::EAGAIN);
1169 } else {
1170 return Err(Errno::EMSGSIZE);
1172 }
1173 }
1174
1175 let reader = IoVecReader::new(iovs, mem);
1176 let reader = reader.take(len.try_into().unwrap());
1177
1178 self.buffer
1181 .borrow_mut()
1182 .write_packet(reader, len, cb_queue)
1183 .map_err(|e| Errno::try_from(e).unwrap())?;
1184
1185 self.sent_len += u64::try_from(len).unwrap();
1187 Ok(len)
1188 })();
1189
1190 if result.as_ref().err() == Some(&Errno::EWOULDBLOCK)
1192 && !flags.contains(MsgFlags::MSG_DONTWAIT)
1193 {
1194 return Err(SyscallError::new_blocked_on_file(
1195 File::Socket(Socket::Netlink(socket.clone())),
1196 FileState::WRITABLE,
1197 self.supports_sa_restart(),
1198 ));
1199 }
1200
1201 Ok(result?)
1202 }
1203
1204 pub fn recvmsg<W: Write>(
1205 &mut self,
1206 socket: &Arc<AtomicRefCell<NetlinkSocket>>,
1207 dst: W,
1208 mut flags: MsgFlags,
1209 _mem: &mut MemoryManager,
1210 cb_queue: &mut CallbackQueue,
1211 ) -> Result<(usize, usize), SyscallError> {
1212 let supported_flags = MsgFlags::MSG_DONTWAIT | MsgFlags::MSG_PEEK | MsgFlags::MSG_TRUNC;
1213
1214 if flags.intersects(!supported_flags) {
1217 warn_once_then_debug!("Unsupported recv flags: {:?}", flags);
1218 return Err(Errno::EINVAL.into());
1219 }
1220
1221 if self.status.contains(FileStatus::NONBLOCK) {
1222 flags.insert(MsgFlags::MSG_DONTWAIT);
1223 }
1224
1225 let result = (|| {
1227 let mut buffer = self.buffer.borrow_mut();
1228
1229 if !buffer.has_data() {
1231 return Err(Errno::EWOULDBLOCK);
1232 }
1233
1234 let (num_copied, num_removed_from_buf) = if flags.contains(MsgFlags::MSG_PEEK) {
1235 buffer.peek(dst).map_err(|e| Errno::try_from(e).unwrap())?
1236 } else {
1237 buffer
1238 .read(dst, cb_queue)
1239 .map_err(|e| Errno::try_from(e).unwrap())?
1240 };
1241
1242 if flags.contains(MsgFlags::MSG_TRUNC) {
1243 Ok((num_removed_from_buf, num_removed_from_buf))
1245 } else {
1246 Ok((num_copied, num_removed_from_buf))
1247 }
1248 })();
1249
1250 if result.as_ref().err() == Some(&Errno::EWOULDBLOCK)
1252 && !flags.contains(MsgFlags::MSG_DONTWAIT)
1253 {
1254 return Err(SyscallError::new_blocked_on_file(
1255 File::Socket(Socket::Netlink(socket.clone())),
1256 FileState::READABLE,
1257 self.supports_sa_restart(),
1258 ));
1259 }
1260
1261 Ok(result?)
1262 }
1263
1264 fn update_state(
1265 &mut self,
1266 mask: FileState,
1267 state: FileState,
1268 signals: FileSignals,
1269 cb_queue: &mut CallbackQueue,
1270 ) {
1271 let old_state = self.state;
1272
1273 self.state.remove(mask);
1275 self.state.insert(state & mask);
1276
1277 self.handle_state_change(old_state, signals, cb_queue);
1278 }
1279
1280 fn handle_state_change(
1281 &mut self,
1282 old_state: FileState,
1283 signals: FileSignals,
1284 cb_queue: &mut CallbackQueue,
1285 ) {
1286 let states_changed = self.state ^ old_state;
1287
1288 if states_changed.is_empty() && signals.is_empty() {
1290 return;
1291 }
1292
1293 self.event_source
1294 .notify_listeners(self.state, states_changed, signals, cb_queue);
1295 }
1296}
1297
1298#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
1299pub enum NetlinkSocketType {
1300 Dgram,
1301 Raw,
1302}
1303
1304impl TryFrom<libc::c_int> for NetlinkSocketType {
1305 type Error = NetlinkSocketTypeConversionError;
1306 fn try_from(val: libc::c_int) -> Result<Self, Self::Error> {
1307 match val {
1308 libc::SOCK_DGRAM => Ok(Self::Dgram),
1309 libc::SOCK_RAW => Ok(Self::Raw),
1310 x => Err(NetlinkSocketTypeConversionError(x)),
1311 }
1312 }
1313}
1314
1315#[derive(Copy, Clone, Debug)]
1316pub struct NetlinkSocketTypeConversionError(libc::c_int);
1317
1318impl std::error::Error for NetlinkSocketTypeConversionError {}
1319
1320impl std::fmt::Display for NetlinkSocketTypeConversionError {
1321 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
1322 write!(
1323 f,
1324 "Invalid socket type {}; netlink sockets only support SOCK_DGRAM and SOCK_RAW",
1325 self.0
1326 )
1327 }
1328}
1329
1330#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
1331pub enum NetlinkFamily {
1332 Route,
1333}
1334
1335impl TryFrom<libc::c_int> for NetlinkFamily {
1336 type Error = NetlinkFamilyConversionError;
1337 fn try_from(val: libc::c_int) -> Result<Self, Self::Error> {
1338 match val {
1339 libc::NETLINK_ROUTE => Ok(Self::Route),
1340 x => Err(NetlinkFamilyConversionError(x)),
1341 }
1342 }
1343}
1344
1345#[derive(Copy, Clone, Debug)]
1346pub struct NetlinkFamilyConversionError(libc::c_int);
1347
1348impl std::error::Error for NetlinkFamilyConversionError {}
1349
1350impl std::fmt::Display for NetlinkFamilyConversionError {
1351 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
1352 write!(
1353 f,
1354 "Invalid netlink family {}; netlink families only support NETLINK_ROUTE",
1355 self.0
1356 )
1357 }
1358}