1use std::collections::{LinkedList, VecDeque};
2use std::io::Read;
3use std::ops::DerefMut;
4use std::sync::{Arc, Weak};
5
6use atomic_refcell::AtomicRefCell;
7use linux_api::errno::Errno;
8use linux_api::ioctls::IoctlRequest;
9use linux_api::socket::Shutdown;
10use nix::sys::socket::MsgFlags;
11use shadow_shim_helper_rs::syscall_types::ForeignPtr;
12
13use crate::cshadow as c;
14use crate::host::descriptor::listener::{StateEventSource, StateListenHandle, StateListenerFilter};
15use crate::host::descriptor::shared_buf::{
16 BufferHandle, BufferSignals, BufferState, ReaderHandle, SharedBuf, WriterHandle,
17};
18use crate::host::descriptor::socket::abstract_unix_ns::AbstractUnixNamespace;
19use crate::host::descriptor::socket::{RecvmsgArgs, RecvmsgReturn, SendmsgArgs, Socket};
20use crate::host::descriptor::{
21 File, FileMode, FileSignals, FileState, FileStatus, OpenFile, SyscallResult,
22};
23use crate::host::memory_manager::MemoryManager;
24use crate::host::network::namespace::NetworkNamespace;
25use crate::host::syscall::io::{IoVec, IoVecReader, IoVecWriter};
26use crate::host::syscall::types::SyscallError;
27use crate::utility::HostTreePointer;
28use crate::utility::callback_queue::CallbackQueue;
29use crate::utility::sockaddr::{SockaddrStorage, SockaddrUnix};
30
31const UNIX_SOCKET_DEFAULT_BUFFER_SIZE: u64 = 212_992;
32
33pub struct UnixSocket {
36 common: UnixSocketCommon,
38 protocol_state: ProtocolState,
40}
41
42impl UnixSocket {
43 pub fn new(
44 status: FileStatus,
45 socket_type: UnixSocketType,
46 namespace: &Arc<AtomicRefCell<AbstractUnixNamespace>>,
47 ) -> Arc<AtomicRefCell<Self>> {
48 Arc::new_cyclic(|weak| {
49 let recv_buffer = SharedBuf::new(usize::MAX);
52 let recv_buffer = Arc::new(AtomicRefCell::new(recv_buffer));
53
54 let mut common = UnixSocketCommon {
55 recv_buffer,
56 send_limit: UNIX_SOCKET_DEFAULT_BUFFER_SIZE,
57 sent_len: 0,
58 event_source: StateEventSource::new(),
59 state: FileState::ACTIVE,
60 status,
61 socket_type,
62 namespace: Arc::clone(namespace),
63 has_open_file: false,
64 };
65
66 let protocol_state = ProtocolState::new(socket_type, &mut common, weak);
68
69 AtomicRefCell::new(Self {
70 common,
71 protocol_state,
72 })
73 })
74 }
75
76 pub fn status(&self) -> FileStatus {
77 self.common.status
78 }
79
80 pub fn set_status(&mut self, status: FileStatus) {
81 self.common.status = status;
82 }
83
84 pub fn mode(&self) -> FileMode {
85 FileMode::READ | FileMode::WRITE
86 }
87
88 pub fn has_open_file(&self) -> bool {
89 self.common.has_open_file
90 }
91
92 pub fn supports_sa_restart(&self) -> bool {
93 self.common.supports_sa_restart()
94 }
95
96 pub fn set_has_open_file(&mut self, val: bool) {
97 self.common.has_open_file = val;
98 }
99
100 pub fn getsockname(&self) -> Result<Option<SockaddrUnix<libc::sockaddr_un>>, Errno> {
101 Ok(Some(
103 self.protocol_state
104 .bound_address()?
105 .unwrap_or_else(SockaddrUnix::new_unnamed),
106 ))
107 }
108
109 pub fn getpeername(&self) -> Result<Option<SockaddrUnix<libc::sockaddr_un>>, Errno> {
110 Ok(Some(
112 self.protocol_state
113 .peer_address()?
114 .unwrap_or_else(SockaddrUnix::new_unnamed),
115 ))
116 }
117
118 pub fn address_family(&self) -> linux_api::socket::AddressFamily {
119 linux_api::socket::AddressFamily::AF_UNIX
120 }
121
122 fn recv_buffer(&self) -> &Arc<AtomicRefCell<SharedBuf>> {
123 &self.common.recv_buffer
124 }
125
126 fn inform_bytes_read(&mut self, num: u64, cb_queue: &mut CallbackQueue) {
127 self.protocol_state
128 .inform_bytes_read(&mut self.common, num, cb_queue);
129 }
130
131 pub fn close(&mut self, cb_queue: &mut CallbackQueue) -> Result<(), SyscallError> {
132 self.protocol_state.close(&mut self.common, cb_queue)
133 }
134
135 fn refresh_file_state(&mut self, signals: FileSignals, cb_queue: &mut CallbackQueue) {
136 self.protocol_state
137 .refresh_file_state(&mut self.common, signals, cb_queue)
138 }
139
140 pub fn bind(
141 socket: &Arc<AtomicRefCell<Self>>,
142 addr: Option<&SockaddrStorage>,
143 _net_ns: &NetworkNamespace,
144 rng: impl rand::Rng,
145 ) -> Result<(), SyscallError> {
146 let socket_ref = &mut *socket.borrow_mut();
147 socket_ref
148 .protocol_state
149 .bind(&mut socket_ref.common, socket, addr, rng)
150 }
151
152 pub fn readv(
153 &mut self,
154 _iovs: &[IoVec],
155 _offset: Option<libc::off_t>,
156 _flags: libc::c_int,
157 _mem: &mut MemoryManager,
158 _cb_queue: &mut CallbackQueue,
159 ) -> Result<libc::ssize_t, SyscallError> {
160 panic!("Called UnixSocket::readv() on a unix socket.");
164 }
165
166 pub fn writev(
167 &mut self,
168 _iovs: &[IoVec],
169 _offset: Option<libc::off_t>,
170 _flags: libc::c_int,
171 _mem: &mut MemoryManager,
172 _cb_queue: &mut CallbackQueue,
173 ) -> Result<libc::ssize_t, SyscallError> {
174 panic!("Called UnixSocket::writev() on a unix socket");
178 }
179
180 pub fn sendmsg(
181 socket: &Arc<AtomicRefCell<Self>>,
182 args: SendmsgArgs,
183 mem: &mut MemoryManager,
184 _net_ns: &NetworkNamespace,
185 _rng: impl rand::Rng,
186 cb_queue: &mut CallbackQueue,
187 ) -> Result<libc::ssize_t, SyscallError> {
188 let socket_ref = &mut *socket.borrow_mut();
189 socket_ref
190 .protocol_state
191 .sendmsg(&mut socket_ref.common, socket, args, mem, cb_queue)
192 }
193
194 pub fn recvmsg(
195 socket: &Arc<AtomicRefCell<Self>>,
196 args: RecvmsgArgs,
197 mem: &mut MemoryManager,
198 cb_queue: &mut CallbackQueue,
199 ) -> Result<RecvmsgReturn, SyscallError> {
200 let socket_ref = &mut *socket.borrow_mut();
201 socket_ref
202 .protocol_state
203 .recvmsg(&mut socket_ref.common, socket, args, mem, cb_queue)
204 }
205
206 pub fn ioctl(
207 &mut self,
208 request: IoctlRequest,
209 arg_ptr: ForeignPtr<()>,
210 memory_manager: &mut MemoryManager,
211 ) -> SyscallResult {
212 self.protocol_state
213 .ioctl(&mut self.common, request, arg_ptr, memory_manager)
214 }
215
216 pub fn lseek(
217 &mut self,
218 _off: linux_api::posix_types::kernel_off_t,
219 _whence: linux_api::unistd::LSeekWhence,
220 ) -> Result<linux_api::posix_types::kernel_off_t, SyscallError> {
221 warn_once_then_debug!("We do not yet handle lseek calls on unix sockets");
222 Err(Errno::EBADF.into())
223 }
224
225 pub fn stat(&self) -> Result<linux_api::stat::stat, SyscallError> {
226 warn_once_then_debug!("We do not yet handle stat calls on unix sockets");
227 Err(Errno::EINVAL.into())
228 }
229
230 pub fn listen(
231 socket: &Arc<AtomicRefCell<Self>>,
232 backlog: i32,
233 _net_ns: &NetworkNamespace,
234 _rng: impl rand::Rng,
235 cb_queue: &mut CallbackQueue,
236 ) -> Result<(), Errno> {
237 let mut socket_ref = socket.borrow_mut();
238 let socket_ref = socket_ref.deref_mut();
239 socket_ref
240 .protocol_state
241 .listen(&mut socket_ref.common, backlog, cb_queue)
242 }
243
244 pub fn connect(
245 socket: &Arc<AtomicRefCell<Self>>,
246 addr: &SockaddrStorage,
247 _net_ns: &NetworkNamespace,
248 _rng: impl rand::Rng,
249 cb_queue: &mut CallbackQueue,
250 ) -> Result<(), SyscallError> {
251 let socket_ref = &mut *socket.borrow_mut();
252 socket_ref
253 .protocol_state
254 .connect(&mut socket_ref.common, socket, addr, cb_queue)
255 }
256
257 pub fn accept(
258 &mut self,
259 _net_ns: &NetworkNamespace,
260 _rng: impl rand::Rng,
261 cb_queue: &mut CallbackQueue,
262 ) -> Result<OpenFile, SyscallError> {
263 self.protocol_state.accept(&mut self.common, cb_queue)
264 }
265
266 pub fn shutdown(
267 &mut self,
268 _how: Shutdown,
269 _cb_queue: &mut CallbackQueue,
270 ) -> Result<(), SyscallError> {
271 log::warn!("shutdown() syscall not yet supported for unix sockets; Returning ENOSYS");
272 Err(Errno::ENOSYS.into())
273 }
274
275 pub fn getsockopt(
276 &mut self,
277 _level: libc::c_int,
278 _optname: libc::c_int,
279 _optval_ptr: ForeignPtr<()>,
280 _optlen: libc::socklen_t,
281 _memory_manager: &mut MemoryManager,
282 _cb_queue: &mut CallbackQueue,
283 ) -> Result<libc::socklen_t, SyscallError> {
284 log::warn!("getsockopt() syscall not yet supported for unix sockets; Returning ENOSYS");
285 Err(Errno::ENOSYS.into())
286 }
287
288 pub fn setsockopt(
289 &mut self,
290 _level: libc::c_int,
291 _optname: libc::c_int,
292 _optval_ptr: ForeignPtr<()>,
293 _optlen: libc::socklen_t,
294 _memory_manager: &MemoryManager,
295 ) -> Result<(), SyscallError> {
296 log::warn!("setsockopt() syscall not yet supported for unix sockets; Returning ENOSYS");
297 Err(Errno::ENOSYS.into())
298 }
299
300 pub fn pair(
301 status: FileStatus,
302 socket_type: UnixSocketType,
303 namespace: &Arc<AtomicRefCell<AbstractUnixNamespace>>,
304 cb_queue: &mut CallbackQueue,
305 ) -> (Arc<AtomicRefCell<Self>>, Arc<AtomicRefCell<Self>>) {
306 let socket_1 = UnixSocket::new(status, socket_type, namespace);
307 let socket_2 = UnixSocket::new(status, socket_type, namespace);
308
309 {
310 let socket_1_ref = &mut *socket_1.borrow_mut();
311 socket_1_ref
312 .protocol_state
313 .connect_unnamed(
314 &mut socket_1_ref.common,
315 &socket_1,
316 Arc::clone(&socket_2),
317 cb_queue,
318 )
319 .unwrap();
320 }
321
322 {
323 let socket_2_ref = &mut *socket_2.borrow_mut();
324 socket_2_ref
325 .protocol_state
326 .connect_unnamed(
327 &mut socket_2_ref.common,
328 &socket_2,
329 Arc::clone(&socket_1),
330 cb_queue,
331 )
332 .unwrap();
333 }
334
335 (socket_1, socket_2)
336 }
337
338 pub fn add_listener(
339 &mut self,
340 monitoring_state: FileState,
341 monitoring_signals: FileSignals,
342 filter: StateListenerFilter,
343 notify_fn: impl Fn(FileState, FileState, FileSignals, &mut CallbackQueue)
344 + Send
345 + Sync
346 + 'static,
347 ) -> StateListenHandle {
348 self.common.event_source.add_listener(
349 monitoring_state,
350 monitoring_signals,
351 filter,
352 notify_fn,
353 )
354 }
355
356 pub fn add_legacy_listener(&mut self, ptr: HostTreePointer<c::StatusListener>) {
357 self.common.event_source.add_legacy_listener(ptr);
358 }
359
360 pub fn remove_legacy_listener(&mut self, ptr: *mut c::StatusListener) {
361 self.common.event_source.remove_legacy_listener(ptr);
362 }
363
364 pub fn state(&self) -> FileState {
365 self.common.state
366 }
367}
368
369struct ConnOrientedInitial {
370 bound_addr: Option<SockaddrUnix<libc::sockaddr_un>>,
371}
372struct ConnOrientedListening {
373 bound_addr: SockaddrUnix<libc::sockaddr_un>,
374 queue: VecDeque<Arc<AtomicRefCell<UnixSocket>>>,
375 queue_limit: u32,
376}
377struct ConnOrientedConnected {
378 bound_addr: Option<SockaddrUnix<libc::sockaddr_un>>,
379 peer_addr: Option<SockaddrUnix<libc::sockaddr_un>>,
380 peer: Arc<AtomicRefCell<UnixSocket>>,
381 reader_handle: ReaderHandle,
382 writer_handle: WriterHandle,
383 _recv_buffer_handle: BufferHandle,
385 _send_buffer_handle: BufferHandle,
386}
387struct ConnOrientedClosed {}
388
389struct ConnLessInitial {
390 this_socket: Weak<AtomicRefCell<UnixSocket>>,
391 bound_addr: Option<SockaddrUnix<libc::sockaddr_un>>,
392 peer_addr: Option<SockaddrUnix<libc::sockaddr_un>>,
393 peer: Option<Arc<AtomicRefCell<UnixSocket>>>,
394 recv_data: LinkedList<ByteData>,
395 reader_handle: ReaderHandle,
396 _recv_buffer_handle: BufferHandle,
398}
399struct ConnLessClosed {}
400
401impl ConnOrientedListening {
402 fn queue_is_full(&self) -> bool {
403 self.queue.len() >= self.queue_limit.try_into().unwrap()
404 }
405}
406
407enum ProtocolState {
411 ConnOrientedInitial(Option<ConnOrientedInitial>),
412 ConnOrientedListening(Option<ConnOrientedListening>),
413 ConnOrientedConnected(Option<ConnOrientedConnected>),
414 ConnOrientedClosed(Option<ConnOrientedClosed>),
415 ConnLessInitial(Option<ConnLessInitial>),
416 ConnLessClosed(Option<ConnLessClosed>),
417}
418
419macro_rules! state_upcast {
421 ($type:ty, $parent:ident::$variant:ident) => {
422 impl From<$type> for $parent {
423 fn from(x: $type) -> Self {
424 Self::$variant(Some(x))
425 }
426 }
427 };
428}
429
430state_upcast!(ConnOrientedInitial, ProtocolState::ConnOrientedInitial);
432state_upcast!(ConnOrientedListening, ProtocolState::ConnOrientedListening);
433state_upcast!(ConnOrientedConnected, ProtocolState::ConnOrientedConnected);
434state_upcast!(ConnOrientedClosed, ProtocolState::ConnOrientedClosed);
435state_upcast!(ConnLessInitial, ProtocolState::ConnLessInitial);
436state_upcast!(ConnLessClosed, ProtocolState::ConnLessClosed);
437
438impl ProtocolState {
439 fn new(
440 socket_type: UnixSocketType,
441 common: &mut UnixSocketCommon,
442 socket: &Weak<AtomicRefCell<UnixSocket>>,
443 ) -> Self {
444 match socket_type {
445 UnixSocketType::Stream | UnixSocketType::SeqPacket => {
446 Self::ConnOrientedInitial(Some(ConnOrientedInitial { bound_addr: None }))
447 }
448 UnixSocketType::Dgram => {
449 let mut cb_queue = CallbackQueue::new();
451
452 let reader_handle = common.recv_buffer.borrow_mut().add_reader(&mut cb_queue);
457
458 let weak = Weak::clone(socket);
459 let recv_buffer_handle = common.recv_buffer.borrow_mut().add_listener(
460 BufferState::READABLE,
461 BufferSignals::BUFFER_GREW,
462 move |_, signals, cb_queue| {
463 if let Some(socket) = weak.upgrade() {
464 let signals = if signals.contains(BufferSignals::BUFFER_GREW) {
465 FileSignals::READ_BUFFER_GREW
466 } else {
467 FileSignals::empty()
468 };
469
470 socket.borrow_mut().refresh_file_state(signals, cb_queue);
471 }
472 },
473 );
474
475 assert!(cb_queue.is_empty());
479
480 Self::ConnLessInitial(Some(ConnLessInitial {
481 this_socket: Weak::clone(socket),
482 bound_addr: None,
483 peer_addr: None,
484 peer: None,
485 recv_data: LinkedList::new(),
486 reader_handle,
487 _recv_buffer_handle: recv_buffer_handle,
488 }))
489 }
490 }
491 }
492
493 fn peer_address(&self) -> Result<Option<SockaddrUnix<libc::sockaddr_un>>, Errno> {
494 match self {
495 Self::ConnOrientedInitial(x) => x.as_ref().unwrap().peer_address(),
496 Self::ConnOrientedListening(x) => x.as_ref().unwrap().peer_address(),
497 Self::ConnOrientedConnected(x) => x.as_ref().unwrap().peer_address(),
498 Self::ConnOrientedClosed(x) => x.as_ref().unwrap().peer_address(),
499 Self::ConnLessInitial(x) => x.as_ref().unwrap().peer_address(),
500 Self::ConnLessClosed(x) => x.as_ref().unwrap().peer_address(),
501 }
502 }
503
504 fn bound_address(&self) -> Result<Option<SockaddrUnix<libc::sockaddr_un>>, Errno> {
505 match self {
506 Self::ConnOrientedInitial(x) => x.as_ref().unwrap().bound_address(),
507 Self::ConnOrientedListening(x) => x.as_ref().unwrap().bound_address(),
508 Self::ConnOrientedConnected(x) => x.as_ref().unwrap().bound_address(),
509 Self::ConnOrientedClosed(x) => x.as_ref().unwrap().bound_address(),
510 Self::ConnLessInitial(x) => x.as_ref().unwrap().bound_address(),
511 Self::ConnLessClosed(x) => x.as_ref().unwrap().bound_address(),
512 }
513 }
514
515 fn refresh_file_state(
516 &self,
517 common: &mut UnixSocketCommon,
518 signals: FileSignals,
519 cb_queue: &mut CallbackQueue,
520 ) {
521 match self {
522 Self::ConnOrientedInitial(x) => x
523 .as_ref()
524 .unwrap()
525 .refresh_file_state(common, signals, cb_queue),
526 Self::ConnOrientedListening(x) => x
527 .as_ref()
528 .unwrap()
529 .refresh_file_state(common, signals, cb_queue),
530 Self::ConnOrientedConnected(x) => x
531 .as_ref()
532 .unwrap()
533 .refresh_file_state(common, signals, cb_queue),
534 Self::ConnOrientedClosed(x) => x
535 .as_ref()
536 .unwrap()
537 .refresh_file_state(common, signals, cb_queue),
538 Self::ConnLessInitial(x) => x
539 .as_ref()
540 .unwrap()
541 .refresh_file_state(common, signals, cb_queue),
542 Self::ConnLessClosed(x) => x
543 .as_ref()
544 .unwrap()
545 .refresh_file_state(common, signals, cb_queue),
546 }
547 }
548
549 fn close(
550 &mut self,
551 common: &mut UnixSocketCommon,
552 cb_queue: &mut CallbackQueue,
553 ) -> Result<(), SyscallError> {
554 let (new_state, rv) = match self {
555 Self::ConnOrientedInitial(x) => x.take().unwrap().close(common, cb_queue),
556 Self::ConnOrientedListening(x) => x.take().unwrap().close(common, cb_queue),
557 Self::ConnOrientedConnected(x) => x.take().unwrap().close(common, cb_queue),
558 Self::ConnOrientedClosed(x) => x.take().unwrap().close(common, cb_queue),
559 Self::ConnLessInitial(x) => x.take().unwrap().close(common, cb_queue),
560 Self::ConnLessClosed(x) => x.take().unwrap().close(common, cb_queue),
561 };
562
563 *self = new_state;
564 rv
565 }
566
567 fn bind(
568 &mut self,
569 common: &mut UnixSocketCommon,
570 socket: &Arc<AtomicRefCell<UnixSocket>>,
571 addr: Option<&SockaddrStorage>,
572 rng: impl rand::Rng,
573 ) -> Result<(), SyscallError> {
574 match self {
575 Self::ConnOrientedInitial(x) => x.as_mut().unwrap().bind(common, socket, addr, rng),
576 Self::ConnOrientedListening(x) => x.as_mut().unwrap().bind(common, socket, addr, rng),
577 Self::ConnOrientedConnected(x) => x.as_mut().unwrap().bind(common, socket, addr, rng),
578 Self::ConnOrientedClosed(x) => x.as_mut().unwrap().bind(common, socket, addr, rng),
579 Self::ConnLessInitial(x) => x.as_mut().unwrap().bind(common, socket, addr, rng),
580 Self::ConnLessClosed(x) => x.as_mut().unwrap().bind(common, socket, addr, rng),
581 }
582 }
583
584 fn sendmsg(
585 &mut self,
586 common: &mut UnixSocketCommon,
587 socket: &Arc<AtomicRefCell<UnixSocket>>,
588 args: SendmsgArgs,
589 mem: &mut MemoryManager,
590 cb_queue: &mut CallbackQueue,
591 ) -> Result<libc::ssize_t, SyscallError> {
592 match self {
593 Self::ConnOrientedInitial(x) => x
594 .as_mut()
595 .unwrap()
596 .sendmsg(common, socket, args, mem, cb_queue),
597 Self::ConnOrientedListening(x) => x
598 .as_mut()
599 .unwrap()
600 .sendmsg(common, socket, args, mem, cb_queue),
601 Self::ConnOrientedConnected(x) => x
602 .as_mut()
603 .unwrap()
604 .sendmsg(common, socket, args, mem, cb_queue),
605 Self::ConnOrientedClosed(x) => x
606 .as_mut()
607 .unwrap()
608 .sendmsg(common, socket, args, mem, cb_queue),
609 Self::ConnLessInitial(x) => x
610 .as_mut()
611 .unwrap()
612 .sendmsg(common, socket, args, mem, cb_queue),
613 Self::ConnLessClosed(x) => x
614 .as_mut()
615 .unwrap()
616 .sendmsg(common, socket, args, mem, cb_queue),
617 }
618 }
619
620 fn recvmsg(
621 &mut self,
622 common: &mut UnixSocketCommon,
623 socket: &Arc<AtomicRefCell<UnixSocket>>,
624 args: RecvmsgArgs,
625 mem: &mut MemoryManager,
626 cb_queue: &mut CallbackQueue,
627 ) -> Result<RecvmsgReturn, SyscallError> {
628 match self {
629 Self::ConnOrientedInitial(x) => x
630 .as_mut()
631 .unwrap()
632 .recvmsg(common, socket, args, mem, cb_queue),
633 Self::ConnOrientedListening(x) => x
634 .as_mut()
635 .unwrap()
636 .recvmsg(common, socket, args, mem, cb_queue),
637 Self::ConnOrientedConnected(x) => x
638 .as_mut()
639 .unwrap()
640 .recvmsg(common, socket, args, mem, cb_queue),
641 Self::ConnOrientedClosed(x) => x
642 .as_mut()
643 .unwrap()
644 .recvmsg(common, socket, args, mem, cb_queue),
645 Self::ConnLessInitial(x) => x
646 .as_mut()
647 .unwrap()
648 .recvmsg(common, socket, args, mem, cb_queue),
649 Self::ConnLessClosed(x) => x
650 .as_mut()
651 .unwrap()
652 .recvmsg(common, socket, args, mem, cb_queue),
653 }
654 }
655
656 fn inform_bytes_read(
657 &mut self,
658 common: &mut UnixSocketCommon,
659 num: u64,
660 cb_queue: &mut CallbackQueue,
661 ) {
662 match self {
663 Self::ConnOrientedInitial(x) => {
664 x.as_mut().unwrap().inform_bytes_read(common, num, cb_queue)
665 }
666 Self::ConnOrientedListening(x) => {
667 x.as_mut().unwrap().inform_bytes_read(common, num, cb_queue)
668 }
669 Self::ConnOrientedConnected(x) => {
670 x.as_mut().unwrap().inform_bytes_read(common, num, cb_queue)
671 }
672 Self::ConnOrientedClosed(x) => {
673 x.as_mut().unwrap().inform_bytes_read(common, num, cb_queue)
674 }
675 Self::ConnLessInitial(x) => {
676 x.as_mut().unwrap().inform_bytes_read(common, num, cb_queue)
677 }
678 Self::ConnLessClosed(x) => x.as_mut().unwrap().inform_bytes_read(common, num, cb_queue),
679 }
680 }
681
682 fn ioctl(
683 &mut self,
684 common: &mut UnixSocketCommon,
685 request: IoctlRequest,
686 arg_ptr: ForeignPtr<()>,
687 memory_manager: &mut MemoryManager,
688 ) -> SyscallResult {
689 match self {
690 Self::ConnOrientedInitial(x) => {
691 x.as_mut()
692 .unwrap()
693 .ioctl(common, request, arg_ptr, memory_manager)
694 }
695 Self::ConnOrientedListening(x) => {
696 x.as_mut()
697 .unwrap()
698 .ioctl(common, request, arg_ptr, memory_manager)
699 }
700 Self::ConnOrientedConnected(x) => {
701 x.as_mut()
702 .unwrap()
703 .ioctl(common, request, arg_ptr, memory_manager)
704 }
705 Self::ConnOrientedClosed(x) => {
706 x.as_mut()
707 .unwrap()
708 .ioctl(common, request, arg_ptr, memory_manager)
709 }
710 Self::ConnLessInitial(x) => {
711 x.as_mut()
712 .unwrap()
713 .ioctl(common, request, arg_ptr, memory_manager)
714 }
715 Self::ConnLessClosed(x) => {
716 x.as_mut()
717 .unwrap()
718 .ioctl(common, request, arg_ptr, memory_manager)
719 }
720 }
721 }
722
723 fn listen(
724 &mut self,
725 common: &mut UnixSocketCommon,
726 backlog: i32,
727 cb_queue: &mut CallbackQueue,
728 ) -> Result<(), Errno> {
729 let (new_state, rv) = match self {
730 Self::ConnOrientedInitial(x) => x.take().unwrap().listen(common, backlog, cb_queue),
731 Self::ConnOrientedListening(x) => x.take().unwrap().listen(common, backlog, cb_queue),
732 Self::ConnOrientedConnected(x) => x.take().unwrap().listen(common, backlog, cb_queue),
733 Self::ConnOrientedClosed(x) => x.take().unwrap().listen(common, backlog, cb_queue),
734 Self::ConnLessInitial(x) => x.take().unwrap().listen(common, backlog, cb_queue),
735 Self::ConnLessClosed(x) => x.take().unwrap().listen(common, backlog, cb_queue),
736 };
737
738 *self = new_state;
739 rv
740 }
741
742 fn connect(
743 &mut self,
744 common: &mut UnixSocketCommon,
745 socket: &Arc<AtomicRefCell<UnixSocket>>,
746 addr: &SockaddrStorage,
747 cb_queue: &mut CallbackQueue,
748 ) -> Result<(), SyscallError> {
749 let (new_state, rv) = match self {
750 Self::ConnOrientedInitial(x) => {
751 x.take().unwrap().connect(common, socket, addr, cb_queue)
752 }
753 Self::ConnOrientedListening(x) => {
754 x.take().unwrap().connect(common, socket, addr, cb_queue)
755 }
756 Self::ConnOrientedConnected(x) => {
757 x.take().unwrap().connect(common, socket, addr, cb_queue)
758 }
759 Self::ConnOrientedClosed(x) => {
760 x.take().unwrap().connect(common, socket, addr, cb_queue)
761 }
762 Self::ConnLessInitial(x) => x.take().unwrap().connect(common, socket, addr, cb_queue),
763 Self::ConnLessClosed(x) => x.take().unwrap().connect(common, socket, addr, cb_queue),
764 };
765
766 *self = new_state;
767 rv
768 }
769
770 fn connect_unnamed(
771 &mut self,
772 common: &mut UnixSocketCommon,
773 socket: &Arc<AtomicRefCell<UnixSocket>>,
774 peer: Arc<AtomicRefCell<UnixSocket>>,
775 cb_queue: &mut CallbackQueue,
776 ) -> Result<(), SyscallError> {
777 let (new_state, rv) = match self {
778 Self::ConnOrientedInitial(x) => x
779 .take()
780 .unwrap()
781 .connect_unnamed(common, socket, peer, cb_queue),
782 Self::ConnOrientedListening(x) => x
783 .take()
784 .unwrap()
785 .connect_unnamed(common, socket, peer, cb_queue),
786 Self::ConnOrientedConnected(x) => x
787 .take()
788 .unwrap()
789 .connect_unnamed(common, socket, peer, cb_queue),
790 Self::ConnOrientedClosed(x) => x
791 .take()
792 .unwrap()
793 .connect_unnamed(common, socket, peer, cb_queue),
794 Self::ConnLessInitial(x) => x
795 .take()
796 .unwrap()
797 .connect_unnamed(common, socket, peer, cb_queue),
798 Self::ConnLessClosed(x) => x
799 .take()
800 .unwrap()
801 .connect_unnamed(common, socket, peer, cb_queue),
802 };
803
804 *self = new_state;
805 rv
806 }
807
808 fn accept(
809 &mut self,
810 common: &mut UnixSocketCommon,
811 cb_queue: &mut CallbackQueue,
812 ) -> Result<OpenFile, SyscallError> {
813 match self {
814 Self::ConnOrientedInitial(x) => x.as_mut().unwrap().accept(common, cb_queue),
815 Self::ConnOrientedListening(x) => x.as_mut().unwrap().accept(common, cb_queue),
816 Self::ConnOrientedConnected(x) => x.as_mut().unwrap().accept(common, cb_queue),
817 Self::ConnOrientedClosed(x) => x.as_mut().unwrap().accept(common, cb_queue),
818 Self::ConnLessInitial(x) => x.as_mut().unwrap().accept(common, cb_queue),
819 Self::ConnLessClosed(x) => x.as_mut().unwrap().accept(common, cb_queue),
820 }
821 }
822
823 fn queue_incoming_conn(
825 &mut self,
826 common: &mut UnixSocketCommon,
827 from_address: Option<SockaddrUnix<libc::sockaddr_un>>,
828 peer: &Arc<AtomicRefCell<UnixSocket>>,
829 child_send_buffer: &Arc<AtomicRefCell<SharedBuf>>,
830 cb_queue: &mut CallbackQueue,
831 ) -> Result<&Arc<AtomicRefCell<UnixSocket>>, IncomingConnError> {
832 match self {
833 Self::ConnOrientedInitial(x) => x.as_mut().unwrap().queue_incoming_conn(
834 common,
835 from_address,
836 peer,
837 child_send_buffer,
838 cb_queue,
839 ),
840 Self::ConnOrientedListening(x) => x.as_mut().unwrap().queue_incoming_conn(
841 common,
842 from_address,
843 peer,
844 child_send_buffer,
845 cb_queue,
846 ),
847 Self::ConnOrientedConnected(x) => x.as_mut().unwrap().queue_incoming_conn(
848 common,
849 from_address,
850 peer,
851 child_send_buffer,
852 cb_queue,
853 ),
854 Self::ConnOrientedClosed(x) => x.as_mut().unwrap().queue_incoming_conn(
855 common,
856 from_address,
857 peer,
858 child_send_buffer,
859 cb_queue,
860 ),
861 Self::ConnLessInitial(x) => x.as_mut().unwrap().queue_incoming_conn(
862 common,
863 from_address,
864 peer,
865 child_send_buffer,
866 cb_queue,
867 ),
868 Self::ConnLessClosed(x) => x.as_mut().unwrap().queue_incoming_conn(
869 common,
870 from_address,
871 peer,
872 child_send_buffer,
873 cb_queue,
874 ),
875 }
876 }
877}
878
879trait Protocol
883where
884 Self: Sized + Into<ProtocolState>,
885{
886 fn peer_address(&self) -> Result<Option<SockaddrUnix<libc::sockaddr_un>>, Errno>;
887 fn bound_address(&self) -> Result<Option<SockaddrUnix<libc::sockaddr_un>>, Errno>;
888 fn refresh_file_state(
889 &self,
890 common: &mut UnixSocketCommon,
891 signals: FileSignals,
892 cb_queue: &mut CallbackQueue,
893 );
894
895 fn close(
896 self,
897 _common: &mut UnixSocketCommon,
898 _cb_queue: &mut CallbackQueue,
899 ) -> (ProtocolState, Result<(), SyscallError>) {
900 log::warn!("close() while in state {}", std::any::type_name::<Self>());
901 (self.into(), Err(Errno::EOPNOTSUPP.into()))
902 }
903
904 fn bind(
905 &mut self,
906 _common: &mut UnixSocketCommon,
907 _socket: &Arc<AtomicRefCell<UnixSocket>>,
908 _addr: Option<&SockaddrStorage>,
909 _rng: impl rand::Rng,
910 ) -> Result<(), SyscallError> {
911 log::warn!("bind() while in state {}", std::any::type_name::<Self>());
912 Err(Errno::EOPNOTSUPP.into())
913 }
914
915 fn sendmsg(
916 &mut self,
917 _common: &mut UnixSocketCommon,
918 _socket: &Arc<AtomicRefCell<UnixSocket>>,
919 _args: SendmsgArgs,
920 _mem: &mut MemoryManager,
921 _cb_queue: &mut CallbackQueue,
922 ) -> Result<libc::ssize_t, SyscallError> {
923 log::warn!("sendmsg() while in state {}", std::any::type_name::<Self>());
924 Err(Errno::EOPNOTSUPP.into())
925 }
926
927 fn recvmsg(
928 &mut self,
929 _common: &mut UnixSocketCommon,
930 _socket: &Arc<AtomicRefCell<UnixSocket>>,
931 _args: RecvmsgArgs,
932 _mem: &mut MemoryManager,
933 _cb_queue: &mut CallbackQueue,
934 ) -> Result<RecvmsgReturn, SyscallError> {
935 log::warn!("recvmsg() while in state {}", std::any::type_name::<Self>());
936 Err(Errno::EOPNOTSUPP.into())
937 }
938
939 fn inform_bytes_read(
940 &mut self,
941 _common: &mut UnixSocketCommon,
942 _num: u64,
943 _cb_queue: &mut CallbackQueue,
944 ) {
945 panic!(
946 "inform_bytes_read() while in state {}",
947 std::any::type_name::<Self>()
948 );
949 }
950
951 fn ioctl(
952 &mut self,
953 _common: &mut UnixSocketCommon,
954 _request: IoctlRequest,
955 _arg_ptr: ForeignPtr<()>,
956 _memory_manager: &mut MemoryManager,
957 ) -> SyscallResult {
958 log::warn!("ioctl() while in state {}", std::any::type_name::<Self>());
959 Err(Errno::EOPNOTSUPP.into())
960 }
961
962 fn listen(
963 self,
964 _common: &mut UnixSocketCommon,
965 _backlog: i32,
966 _cb_queue: &mut CallbackQueue,
967 ) -> (ProtocolState, Result<(), Errno>) {
968 log::warn!("listen() while in state {}", std::any::type_name::<Self>());
969 (self.into(), Err(Errno::EOPNOTSUPP))
970 }
971
972 fn connect(
973 self,
974 _common: &mut UnixSocketCommon,
975 _socket: &Arc<AtomicRefCell<UnixSocket>>,
976 _addr: &SockaddrStorage,
977 _cb_queue: &mut CallbackQueue,
978 ) -> (ProtocolState, Result<(), SyscallError>) {
979 log::warn!("connect() while in state {}", std::any::type_name::<Self>());
980 (self.into(), Err(Errno::EOPNOTSUPP.into()))
981 }
982
983 fn connect_unnamed(
984 self,
985 _common: &mut UnixSocketCommon,
986 _socket: &Arc<AtomicRefCell<UnixSocket>>,
987 _peer: Arc<AtomicRefCell<UnixSocket>>,
988 _cb_queue: &mut CallbackQueue,
989 ) -> (ProtocolState, Result<(), SyscallError>) {
990 log::warn!(
991 "connect_unnamed() while in state {}",
992 std::any::type_name::<Self>()
993 );
994 (self.into(), Err(Errno::EOPNOTSUPP.into()))
995 }
996
997 fn accept(
998 &mut self,
999 _common: &mut UnixSocketCommon,
1000 _cb_queue: &mut CallbackQueue,
1001 ) -> Result<OpenFile, SyscallError> {
1002 log::warn!("accept() while in state {}", std::any::type_name::<Self>());
1003 Err(Errno::EOPNOTSUPP.into())
1004 }
1005
1006 fn queue_incoming_conn(
1007 &mut self,
1008 _common: &mut UnixSocketCommon,
1009 _from_address: Option<SockaddrUnix<libc::sockaddr_un>>,
1010 _peer: &Arc<AtomicRefCell<UnixSocket>>,
1011 _child_send_buffer: &Arc<AtomicRefCell<SharedBuf>>,
1012 _cb_queue: &mut CallbackQueue,
1013 ) -> Result<&Arc<AtomicRefCell<UnixSocket>>, IncomingConnError> {
1014 log::warn!(
1015 "queue_incoming_conn() while in state {}",
1016 std::any::type_name::<Self>()
1017 );
1018 Err(IncomingConnError::NotSupported)
1019 }
1020}
1021
1022impl Protocol for ConnOrientedInitial {
1023 fn peer_address(&self) -> Result<Option<SockaddrUnix<libc::sockaddr_un>>, Errno> {
1024 Err(Errno::ENOTCONN)
1025 }
1026
1027 fn bound_address(&self) -> Result<Option<SockaddrUnix<libc::sockaddr_un>>, Errno> {
1028 Ok(self.bound_addr)
1029 }
1030
1031 fn refresh_file_state(
1032 &self,
1033 common: &mut UnixSocketCommon,
1034 signals: FileSignals,
1035 cb_queue: &mut CallbackQueue,
1036 ) {
1037 assert!(!signals.contains(FileSignals::READ_BUFFER_GREW));
1038 common.update_state(
1039 FileState::all(),
1040 FileState::ACTIVE,
1041 signals,
1042 cb_queue,
1043 );
1044 }
1045
1046 fn close(
1047 self,
1048 common: &mut UnixSocketCommon,
1049 cb_queue: &mut CallbackQueue,
1050 ) -> (ProtocolState, Result<(), SyscallError>) {
1051 let new_state = ConnOrientedClosed {};
1052 new_state.refresh_file_state(common, FileSignals::empty(), cb_queue);
1053 (new_state.into(), common.close(cb_queue))
1054 }
1055
1056 fn bind(
1057 &mut self,
1058 common: &mut UnixSocketCommon,
1059 socket: &Arc<AtomicRefCell<UnixSocket>>,
1060 addr: Option<&SockaddrStorage>,
1061 rng: impl rand::Rng,
1062 ) -> Result<(), SyscallError> {
1063 if self.bound_addr.is_some() {
1065 return Err(Errno::EINVAL.into());
1066 }
1067
1068 self.bound_addr = Some(common.bind(socket, addr, rng)?);
1069 Ok(())
1070 }
1071
1072 fn sendmsg(
1073 &mut self,
1074 common: &mut UnixSocketCommon,
1075 _socket: &Arc<AtomicRefCell<UnixSocket>>,
1076 args: SendmsgArgs,
1077 _mem: &mut MemoryManager,
1078 _cb_queue: &mut CallbackQueue,
1079 ) -> Result<libc::ssize_t, SyscallError> {
1080 match (common.socket_type, args.addr) {
1081 (UnixSocketType::Stream, Some(_)) => Err(Errno::EOPNOTSUPP.into()),
1082 (UnixSocketType::Stream, None) => Err(Errno::ENOTCONN.into()),
1083 (UnixSocketType::SeqPacket, _) => Err(Errno::ENOTCONN.into()),
1084 (UnixSocketType::Dgram, _) => panic!(
1085 "A dgram unix socket is in the connection-oriented {:?} state",
1086 std::any::type_name::<Self>()
1087 ),
1088 }
1089 }
1090
1091 fn recvmsg(
1092 &mut self,
1093 common: &mut UnixSocketCommon,
1094 _socket: &Arc<AtomicRefCell<UnixSocket>>,
1095 _args: RecvmsgArgs,
1096 _mem: &mut MemoryManager,
1097 _cb_queue: &mut CallbackQueue,
1098 ) -> Result<RecvmsgReturn, SyscallError> {
1099 match common.socket_type {
1100 UnixSocketType::Stream => Err(Errno::EINVAL.into()),
1101 UnixSocketType::SeqPacket => Err(Errno::ENOTCONN.into()),
1102 UnixSocketType::Dgram => panic!(
1103 "A dgram unix socket is in the connection-oriented {:?} state",
1104 std::any::type_name::<Self>()
1105 ),
1106 }
1107 }
1108
1109 fn ioctl(
1110 &mut self,
1111 common: &mut UnixSocketCommon,
1112 request: IoctlRequest,
1113 arg_ptr: ForeignPtr<()>,
1114 memory_manager: &mut MemoryManager,
1115 ) -> SyscallResult {
1116 common.ioctl(request, arg_ptr, memory_manager)
1117 }
1118
1119 fn listen(
1120 self,
1121 common: &mut UnixSocketCommon,
1122 backlog: i32,
1123 cb_queue: &mut CallbackQueue,
1124 ) -> (ProtocolState, Result<(), Errno>) {
1125 let bound_addr = match self.bound_addr {
1127 Some(x) => x,
1128 None => return (self.into(), Err(Errno::EINVAL)),
1129 };
1130
1131 let new_state = ConnOrientedListening {
1132 bound_addr,
1133 queue: VecDeque::new(),
1134 queue_limit: backlog_to_queue_size(backlog),
1135 };
1136
1137 new_state.refresh_file_state(common, FileSignals::empty(), cb_queue);
1139
1140 (new_state.into(), Ok(()))
1141 }
1142
1143 fn connect(
1144 self,
1145 common: &mut UnixSocketCommon,
1146 socket: &Arc<AtomicRefCell<UnixSocket>>,
1147 addr: &SockaddrStorage,
1148 cb_queue: &mut CallbackQueue,
1149 ) -> (ProtocolState, Result<(), SyscallError>) {
1150 let Some(addr) = addr.as_unix() else {
1151 return (self.into(), Err(Errno::EINVAL.into()));
1152 };
1153
1154 let server = match lookup_address(
1156 &common.namespace.borrow(),
1157 common.socket_type,
1158 &addr.as_ref(),
1159 ) {
1160 Ok(x) => x,
1161 Err(e) => return (self.into(), Err(e.into())),
1162 };
1163
1164 let server_mut = &mut *server.borrow_mut();
1170 let peer = match server_mut.protocol_state.queue_incoming_conn(
1171 &mut server_mut.common,
1172 self.bound_addr,
1173 socket,
1174 &common.recv_buffer,
1175 cb_queue,
1176 ) {
1177 Ok(peer) => peer,
1178 Err(IncomingConnError::NotSupported) => {
1179 return (self.into(), Err(Errno::ECONNREFUSED.into()));
1180 }
1181 Err(IncomingConnError::QueueFull) => {
1182 if common.status.contains(FileStatus::NONBLOCK) {
1183 return (self.into(), Err(Errno::EWOULDBLOCK.into()));
1184 }
1185
1186 let err = SyscallError::new_blocked_on_file(
1188 File::Socket(Socket::Unix(Arc::clone(&server))),
1189 FileState::SOCKET_ALLOWING_CONNECT | FileState::CLOSED,
1190 server_mut.supports_sa_restart(),
1191 );
1192
1193 return (self.into(), Err(err));
1194 }
1195 };
1196
1197 let send_buffer = Arc::clone(peer.borrow().recv_buffer());
1199
1200 let weak = Arc::downgrade(socket);
1201 let send_buffer_handle = send_buffer.borrow_mut().add_listener(
1202 BufferState::WRITABLE | BufferState::NO_READERS,
1203 BufferSignals::empty(),
1204 move |_, _, cb_queue| {
1205 if let Some(socket) = weak.upgrade() {
1206 socket
1207 .borrow_mut()
1208 .refresh_file_state(FileSignals::empty(), cb_queue);
1209 }
1210 },
1211 );
1212
1213 let writer_handle = send_buffer.borrow_mut().add_writer(cb_queue);
1215
1216 let weak = Arc::downgrade(socket);
1217 let recv_buffer_handle = common.recv_buffer.borrow_mut().add_listener(
1218 BufferState::READABLE | BufferState::NO_WRITERS,
1219 BufferSignals::BUFFER_GREW,
1220 move |_, signals, cb_queue| {
1221 if let Some(socket) = weak.upgrade() {
1222 let signals = if signals.contains(BufferSignals::BUFFER_GREW) {
1223 FileSignals::READ_BUFFER_GREW
1224 } else {
1225 FileSignals::empty()
1226 };
1227 socket.borrow_mut().refresh_file_state(signals, cb_queue);
1228 }
1229 },
1230 );
1231
1232 let reader_handle = common.recv_buffer.borrow_mut().add_reader(cb_queue);
1234
1235 let new_state = ConnOrientedConnected {
1236 bound_addr: self.bound_addr,
1237 peer_addr: Some(addr.into_owned()),
1238 peer: Arc::clone(peer),
1239 reader_handle,
1240 writer_handle,
1241 _recv_buffer_handle: recv_buffer_handle,
1242 _send_buffer_handle: send_buffer_handle,
1243 };
1244
1245 new_state.refresh_file_state(common, FileSignals::empty(), cb_queue);
1246
1247 (new_state.into(), Ok(()))
1248 }
1249
1250 fn connect_unnamed(
1251 self,
1252 common: &mut UnixSocketCommon,
1253 socket: &Arc<AtomicRefCell<UnixSocket>>,
1254 peer: Arc<AtomicRefCell<UnixSocket>>,
1255 cb_queue: &mut CallbackQueue,
1256 ) -> (ProtocolState, Result<(), SyscallError>) {
1257 assert!(self.bound_addr.is_none());
1258
1259 let send_buffer_handle;
1260 let writer_handle;
1261
1262 {
1263 let peer_ref = peer.borrow();
1264 let send_buffer = peer_ref.recv_buffer();
1265
1266 let weak = Arc::downgrade(socket);
1267 send_buffer_handle = send_buffer.borrow_mut().add_listener(
1268 BufferState::WRITABLE | BufferState::NO_READERS,
1269 BufferSignals::empty(),
1270 move |_, _, cb_queue| {
1271 if let Some(socket) = weak.upgrade() {
1272 socket
1273 .borrow_mut()
1274 .refresh_file_state(FileSignals::empty(), cb_queue);
1275 }
1276 },
1277 );
1278
1279 writer_handle = send_buffer.borrow_mut().add_writer(cb_queue);
1281 }
1282
1283 let weak = Arc::downgrade(socket);
1284 let recv_buffer_handle = common.recv_buffer.borrow_mut().add_listener(
1285 BufferState::READABLE | BufferState::NO_WRITERS,
1286 BufferSignals::BUFFER_GREW,
1287 move |_, signals, cb_queue| {
1288 if let Some(socket) = weak.upgrade() {
1289 let signals = if signals.contains(BufferSignals::BUFFER_GREW) {
1290 FileSignals::READ_BUFFER_GREW
1291 } else {
1292 FileSignals::empty()
1293 };
1294 socket.borrow_mut().refresh_file_state(signals, cb_queue);
1295 }
1296 },
1297 );
1298
1299 let reader_handle = common.recv_buffer.borrow_mut().add_reader(cb_queue);
1301
1302 let new_state = ConnOrientedConnected {
1303 bound_addr: None,
1304 peer_addr: None,
1305 peer,
1306 reader_handle,
1307 writer_handle,
1308 _recv_buffer_handle: recv_buffer_handle,
1309 _send_buffer_handle: send_buffer_handle,
1310 };
1311
1312 new_state.refresh_file_state(common, FileSignals::empty(), cb_queue);
1313
1314 (new_state.into(), Ok(()))
1315 }
1316
1317 fn accept(
1318 &mut self,
1319 _common: &mut UnixSocketCommon,
1320 _cb_queue: &mut CallbackQueue,
1321 ) -> Result<OpenFile, SyscallError> {
1322 log::warn!("accept() while in state {}", std::any::type_name::<Self>());
1323 Err(Errno::EINVAL.into())
1324 }
1325}
1326
1327impl Protocol for ConnOrientedListening {
1328 fn peer_address(&self) -> Result<Option<SockaddrUnix<libc::sockaddr_un>>, Errno> {
1329 Err(Errno::ENOTCONN)
1330 }
1331
1332 fn bound_address(&self) -> Result<Option<SockaddrUnix<libc::sockaddr_un>>, Errno> {
1333 Ok(Some(self.bound_addr))
1334 }
1335
1336 fn refresh_file_state(
1337 &self,
1338 common: &mut UnixSocketCommon,
1339 signals: FileSignals,
1340 cb_queue: &mut CallbackQueue,
1341 ) {
1342 let mut new_state = FileState::ACTIVE;
1343
1344 new_state.set(FileState::READABLE, !self.queue.is_empty());
1346
1347 new_state.set(FileState::SOCKET_ALLOWING_CONNECT, !self.queue_is_full());
1349
1350 common.update_state(
1356 FileState::all(),
1357 new_state,
1358 signals,
1359 cb_queue,
1360 );
1361 }
1362
1363 fn close(
1364 self,
1365 common: &mut UnixSocketCommon,
1366 cb_queue: &mut CallbackQueue,
1367 ) -> (ProtocolState, Result<(), SyscallError>) {
1368 for sock in self.queue {
1369 if let Err(e) = sock.borrow_mut().close(cb_queue) {
1371 log::warn!("Unexpected error while closing queued unix socket: {e:?}");
1372 }
1373 }
1374
1375 let new_state = ConnOrientedClosed {};
1376 new_state.refresh_file_state(common, FileSignals::empty(), cb_queue);
1377 (new_state.into(), common.close(cb_queue))
1378 }
1379
1380 fn listen(
1381 mut self,
1382 common: &mut UnixSocketCommon,
1383 backlog: i32,
1384 cb_queue: &mut CallbackQueue,
1385 ) -> (ProtocolState, Result<(), Errno>) {
1386 self.queue_limit = backlog_to_queue_size(backlog);
1387
1388 self.refresh_file_state(common, FileSignals::empty(), cb_queue);
1390
1391 (self.into(), Ok(()))
1392 }
1393
1394 fn connect(
1395 self,
1396 _common: &mut UnixSocketCommon,
1397 _socket: &Arc<AtomicRefCell<UnixSocket>>,
1398 _addr: &SockaddrStorage,
1399 _cb_queue: &mut CallbackQueue,
1400 ) -> (ProtocolState, Result<(), SyscallError>) {
1401 (self.into(), Err(Errno::EINVAL.into()))
1402 }
1403
1404 fn accept(
1405 &mut self,
1406 common: &mut UnixSocketCommon,
1407 cb_queue: &mut CallbackQueue,
1408 ) -> Result<OpenFile, SyscallError> {
1409 let child_socket = match self.queue.pop_front() {
1410 Some(x) => x,
1411 None => return Err(Errno::EWOULDBLOCK.into()),
1412 };
1413
1414 self.refresh_file_state(common, FileSignals::empty(), cb_queue);
1416
1417 Ok(OpenFile::new(File::Socket(Socket::Unix(child_socket))))
1418 }
1419
1420 fn queue_incoming_conn(
1421 &mut self,
1422 common: &mut UnixSocketCommon,
1423 from_address: Option<SockaddrUnix<libc::sockaddr_un>>,
1424 peer: &Arc<AtomicRefCell<UnixSocket>>,
1425 child_send_buffer: &Arc<AtomicRefCell<SharedBuf>>,
1426 cb_queue: &mut CallbackQueue,
1427 ) -> Result<&Arc<AtomicRefCell<UnixSocket>>, IncomingConnError> {
1428 if self.queue.len() >= self.queue_limit.try_into().unwrap() {
1429 assert!(!common.state.contains(FileState::SOCKET_ALLOWING_CONNECT));
1430 return Err(IncomingConnError::QueueFull);
1431 }
1432
1433 assert!(common.state.contains(FileState::SOCKET_ALLOWING_CONNECT));
1434
1435 let child_socket = UnixSocket::new(
1436 common.status,
1438 common.socket_type,
1439 &common.namespace,
1440 );
1441
1442 let child_recv_buffer = Arc::clone(&child_socket.borrow_mut().common.recv_buffer);
1443
1444 let weak = Arc::downgrade(&child_socket);
1445 let send_buffer_handle = child_send_buffer.borrow_mut().add_listener(
1446 BufferState::WRITABLE | BufferState::NO_READERS,
1447 BufferSignals::empty(),
1448 move |_, _, cb_queue| {
1449 if let Some(socket) = weak.upgrade() {
1450 socket
1451 .borrow_mut()
1452 .refresh_file_state(FileSignals::empty(), cb_queue);
1453 }
1454 },
1455 );
1456
1457 let writer_handle = child_send_buffer.borrow_mut().add_writer(cb_queue);
1459
1460 let weak = Arc::downgrade(&child_socket);
1461 let recv_buffer_handle = child_recv_buffer.borrow_mut().add_listener(
1462 BufferState::READABLE | BufferState::NO_WRITERS,
1463 BufferSignals::BUFFER_GREW,
1464 move |_, signals, cb_queue| {
1465 if let Some(socket) = weak.upgrade() {
1466 let signals = if signals.contains(BufferSignals::BUFFER_GREW) {
1467 FileSignals::READ_BUFFER_GREW
1468 } else {
1469 FileSignals::empty()
1470 };
1471 socket.borrow_mut().refresh_file_state(signals, cb_queue);
1472 }
1473 },
1474 );
1475
1476 let reader_handle = child_recv_buffer.borrow_mut().add_reader(cb_queue);
1478
1479 let new_child_state = ConnOrientedConnected {
1480 bound_addr: Some(self.bound_addr),
1482 peer_addr: from_address,
1483 peer: Arc::clone(peer),
1484 reader_handle,
1485 writer_handle,
1486 _recv_buffer_handle: recv_buffer_handle,
1487 _send_buffer_handle: send_buffer_handle,
1488 };
1489
1490 child_socket.borrow_mut().protocol_state = new_child_state.into();
1492
1493 let weak = Arc::downgrade(&child_socket);
1495 cb_queue.add(move |cb_queue| {
1496 if let Some(child_socket) = weak.upgrade() {
1497 child_socket
1498 .borrow_mut()
1499 .refresh_file_state(FileSignals::empty(), cb_queue);
1500 }
1501 });
1502
1503 self.queue.push_back(child_socket);
1505
1506 self.refresh_file_state(common, FileSignals::empty(), cb_queue);
1508
1509 Ok(self.queue.back().unwrap())
1511 }
1512}
1513
1514impl Protocol for ConnOrientedConnected {
1515 fn peer_address(&self) -> Result<Option<SockaddrUnix<libc::sockaddr_un>>, Errno> {
1516 Ok(self.peer_addr)
1517 }
1518
1519 fn bound_address(&self) -> Result<Option<SockaddrUnix<libc::sockaddr_un>>, Errno> {
1520 Ok(self.bound_addr)
1521 }
1522
1523 fn refresh_file_state(
1524 &self,
1525 common: &mut UnixSocketCommon,
1526 signals: FileSignals,
1527 cb_queue: &mut CallbackQueue,
1528 ) {
1529 let mut new_state = FileState::ACTIVE;
1530
1531 {
1532 let recv_buffer = common.recv_buffer.borrow();
1533 let peer = self.peer.borrow();
1534 let send_buffer = peer.recv_buffer().borrow();
1535
1536 new_state.set(
1537 FileState::READABLE,
1538 recv_buffer.has_data() || recv_buffer.num_writers() == 0,
1539 );
1540 new_state.set(
1541 FileState::WRITABLE,
1542 common.sent_len < common.send_limit || send_buffer.num_readers() == 0,
1543 );
1544 }
1545
1546 common.update_state(
1547 FileState::all(),
1548 new_state,
1549 signals,
1550 cb_queue,
1551 );
1552 }
1553
1554 fn close(
1555 self,
1556 common: &mut UnixSocketCommon,
1557 cb_queue: &mut CallbackQueue,
1558 ) -> (ProtocolState, Result<(), SyscallError>) {
1559 common
1561 .recv_buffer
1562 .borrow_mut()
1563 .remove_reader(self.reader_handle, cb_queue);
1564
1565 self.peer
1567 .borrow()
1568 .recv_buffer()
1569 .borrow_mut()
1570 .remove_writer(self.writer_handle, cb_queue);
1571
1572 let new_state = ConnOrientedClosed {};
1573 new_state.refresh_file_state(common, FileSignals::empty(), cb_queue);
1574 (new_state.into(), common.close(cb_queue))
1575 }
1576
1577 fn sendmsg(
1578 &mut self,
1579 common: &mut UnixSocketCommon,
1580 socket: &Arc<AtomicRefCell<UnixSocket>>,
1581 args: SendmsgArgs,
1582 mem: &mut MemoryManager,
1583 cb_queue: &mut CallbackQueue,
1584 ) -> Result<libc::ssize_t, SyscallError> {
1585 if !args.control_ptr.ptr().is_null() {
1586 log::debug!("Unix sockets don't yet support control data for sendmsg()");
1587 return Err(Errno::EINVAL.into());
1588 }
1589
1590 let recv_socket = common.resolve_destination(Some(&self.peer), args.addr)?;
1591 let rv = common.sendmsg(socket, args.iovs, args.flags, &recv_socket, mem, cb_queue)?;
1592
1593 self.refresh_file_state(common, FileSignals::empty(), cb_queue);
1594
1595 Ok(rv.try_into().unwrap())
1596 }
1597
1598 fn recvmsg(
1599 &mut self,
1600 common: &mut UnixSocketCommon,
1601 socket: &Arc<AtomicRefCell<UnixSocket>>,
1602 args: RecvmsgArgs,
1603 mem: &mut MemoryManager,
1604 cb_queue: &mut CallbackQueue,
1605 ) -> Result<RecvmsgReturn, SyscallError> {
1606 if !args.control_ptr.ptr().is_null() {
1607 log::debug!("Unix sockets don't yet support control data for recvmsg()");
1608 return Err(Errno::EINVAL.into());
1609 }
1610
1611 let (rv, num_removed_from_buf, msg_flags) =
1612 common.recvmsg(socket, args.iovs, args.flags, mem, cb_queue)?;
1613 let num_removed_from_buf = u64::try_from(num_removed_from_buf).unwrap();
1614
1615 if num_removed_from_buf > 0 {
1616 let peer = Arc::clone(&self.peer);
1618 cb_queue.add(move |cb_queue| {
1619 peer.borrow_mut()
1620 .inform_bytes_read(num_removed_from_buf, cb_queue);
1621 });
1622 }
1623
1624 self.refresh_file_state(common, FileSignals::empty(), cb_queue);
1625
1626 Ok(RecvmsgReturn {
1627 return_val: rv.try_into().unwrap(),
1628 addr: self.peer_addr.map(Into::into),
1629 msg_flags,
1630 control_len: 0,
1631 })
1632 }
1633
1634 fn inform_bytes_read(
1635 &mut self,
1636 common: &mut UnixSocketCommon,
1637 num: u64,
1638 cb_queue: &mut CallbackQueue,
1639 ) {
1640 common.sent_len = common.sent_len.checked_sub(num).unwrap();
1641 self.refresh_file_state(common, FileSignals::empty(), cb_queue);
1642 }
1643
1644 fn ioctl(
1645 &mut self,
1646 common: &mut UnixSocketCommon,
1647 request: IoctlRequest,
1648 arg_ptr: ForeignPtr<()>,
1649 memory_manager: &mut MemoryManager,
1650 ) -> SyscallResult {
1651 common.ioctl(request, arg_ptr, memory_manager)
1652 }
1653
1654 fn accept(
1655 &mut self,
1656 _common: &mut UnixSocketCommon,
1657 _cb_queue: &mut CallbackQueue,
1658 ) -> Result<OpenFile, SyscallError> {
1659 log::warn!("accept() while in state {}", std::any::type_name::<Self>());
1660 Err(Errno::EINVAL.into())
1661 }
1662}
1663
1664impl Protocol for ConnOrientedClosed {
1665 fn peer_address(&self) -> Result<Option<SockaddrUnix<libc::sockaddr_un>>, Errno> {
1666 Err(Errno::ENOTCONN)
1667 }
1668
1669 fn bound_address(&self) -> Result<Option<SockaddrUnix<libc::sockaddr_un>>, Errno> {
1670 Err(Errno::EBADFD)
1671 }
1672
1673 fn refresh_file_state(
1674 &self,
1675 common: &mut UnixSocketCommon,
1676 signals: FileSignals,
1677 cb_queue: &mut CallbackQueue,
1678 ) {
1679 assert!(!signals.contains(FileSignals::READ_BUFFER_GREW));
1680 common.update_state(
1681 FileState::all(),
1682 FileState::CLOSED,
1683 signals,
1684 cb_queue,
1685 );
1686 }
1687
1688 fn close(
1689 self,
1690 _common: &mut UnixSocketCommon,
1691 _cb_queue: &mut CallbackQueue,
1692 ) -> (ProtocolState, Result<(), SyscallError>) {
1693 panic!("Trying to close an already closed socket");
1695 }
1696
1697 fn inform_bytes_read(
1698 &mut self,
1699 _common: &mut UnixSocketCommon,
1700 _num: u64,
1701 _cb_queue: &mut CallbackQueue,
1702 ) {
1703 }
1705}
1706
1707impl Protocol for ConnLessInitial {
1708 fn peer_address(&self) -> Result<Option<SockaddrUnix<libc::sockaddr_un>>, Errno> {
1709 match self.peer {
1710 Some(_) => Ok(self.peer_addr),
1711 None => Err(Errno::ENOTCONN),
1712 }
1713 }
1714
1715 fn bound_address(&self) -> Result<Option<SockaddrUnix<libc::sockaddr_un>>, Errno> {
1716 Ok(self.bound_addr)
1717 }
1718
1719 fn refresh_file_state(
1720 &self,
1721 common: &mut UnixSocketCommon,
1722 signals: FileSignals,
1723 cb_queue: &mut CallbackQueue,
1724 ) {
1725 let mut new_state = FileState::ACTIVE;
1726
1727 {
1728 let recv_buffer = common.recv_buffer.borrow();
1729
1730 new_state.set(FileState::READABLE, recv_buffer.has_data());
1731 new_state.set(FileState::WRITABLE, common.sent_len < common.send_limit);
1732 }
1733
1734 common.update_state(
1735 FileState::all(),
1736 new_state,
1737 signals,
1738 cb_queue,
1739 );
1740 }
1741
1742 fn close(
1743 self,
1744 common: &mut UnixSocketCommon,
1745 cb_queue: &mut CallbackQueue,
1746 ) -> (ProtocolState, Result<(), SyscallError>) {
1747 common
1749 .recv_buffer
1750 .borrow_mut()
1751 .remove_reader(self.reader_handle, cb_queue);
1752
1753 for byte_data in self.recv_data.into_iter() {
1754 cb_queue.add(move |cb_queue| {
1756 byte_data
1757 .from_socket
1758 .borrow_mut()
1759 .inform_bytes_read(byte_data.num_bytes, cb_queue);
1760 });
1761 }
1762
1763 let new_state = ConnLessClosed {};
1764 new_state.refresh_file_state(common, FileSignals::empty(), cb_queue);
1765 (new_state.into(), common.close(cb_queue))
1766 }
1767
1768 fn bind(
1769 &mut self,
1770 common: &mut UnixSocketCommon,
1771 socket: &Arc<AtomicRefCell<UnixSocket>>,
1772 addr: Option<&SockaddrStorage>,
1773 rng: impl rand::Rng,
1774 ) -> Result<(), SyscallError> {
1775 if self.bound_addr.is_some() {
1777 return Err(Errno::EINVAL.into());
1778 }
1779
1780 self.bound_addr = Some(common.bind(socket, addr, rng)?);
1781 Ok(())
1782 }
1783
1784 fn sendmsg(
1785 &mut self,
1786 common: &mut UnixSocketCommon,
1787 socket: &Arc<AtomicRefCell<UnixSocket>>,
1788 args: SendmsgArgs,
1789 mem: &mut MemoryManager,
1790 cb_queue: &mut CallbackQueue,
1791 ) -> Result<libc::ssize_t, SyscallError> {
1792 if !args.control_ptr.ptr().is_null() {
1793 log::debug!("Unix sockets don't yet support control data for sendmsg()");
1794 return Err(Errno::EINVAL.into());
1795 }
1796
1797 let recv_socket = common.resolve_destination(self.peer.as_ref(), args.addr)?;
1798 let rv = common.sendmsg(socket, args.iovs, args.flags, &recv_socket, mem, cb_queue)?;
1799
1800 let byte_data = ByteData {
1801 from_socket: self.this_socket.upgrade().unwrap(),
1802 from_addr: self.bound_addr,
1803 num_bytes: rv.try_into().unwrap(),
1804 };
1805
1806 match &mut recv_socket.borrow_mut().protocol_state {
1807 ProtocolState::ConnLessInitial(state) => {
1808 state.as_mut().unwrap().recv_data.push_back(byte_data);
1809 }
1810 _ => panic!(
1811 "Sending bytes to a socket in state {}",
1812 std::any::type_name::<Self>()
1813 ),
1814 }
1815
1816 self.refresh_file_state(common, FileSignals::empty(), cb_queue);
1817
1818 Ok(rv.try_into().unwrap())
1819 }
1820
1821 fn recvmsg(
1822 &mut self,
1823 common: &mut UnixSocketCommon,
1824 socket: &Arc<AtomicRefCell<UnixSocket>>,
1825 args: RecvmsgArgs,
1826 mem: &mut MemoryManager,
1827 cb_queue: &mut CallbackQueue,
1828 ) -> Result<RecvmsgReturn, SyscallError> {
1829 if !args.control_ptr.ptr().is_null() {
1830 log::debug!("Unix sockets don't yet support control data for recvmsg()");
1831 return Err(Errno::EINVAL.into());
1832 }
1833
1834 let (rv, num_removed_from_buf, msg_flags) =
1835 common.recvmsg(socket, args.iovs, args.flags, mem, cb_queue)?;
1836 let num_removed_from_buf = u64::try_from(num_removed_from_buf).unwrap();
1837
1838 let byte_data = self.recv_data.pop_front().unwrap();
1839 assert!(num_removed_from_buf == byte_data.num_bytes);
1840
1841 cb_queue.add(move |cb_queue| {
1843 byte_data
1844 .from_socket
1845 .borrow_mut()
1846 .inform_bytes_read(byte_data.num_bytes, cb_queue);
1847 });
1848
1849 self.refresh_file_state(common, FileSignals::empty(), cb_queue);
1850
1851 Ok(RecvmsgReturn {
1852 return_val: rv.try_into().unwrap(),
1853 addr: byte_data.from_addr.map(Into::into),
1854 msg_flags,
1855 control_len: 0,
1856 })
1857 }
1858
1859 fn inform_bytes_read(
1860 &mut self,
1861 common: &mut UnixSocketCommon,
1862 num: u64,
1863 cb_queue: &mut CallbackQueue,
1864 ) {
1865 common.sent_len = common.sent_len.checked_sub(num).unwrap();
1866 self.refresh_file_state(common, FileSignals::empty(), cb_queue);
1867 }
1868
1869 fn ioctl(
1870 &mut self,
1871 common: &mut UnixSocketCommon,
1872 request: IoctlRequest,
1873 arg_ptr: ForeignPtr<()>,
1874 memory_manager: &mut MemoryManager,
1875 ) -> SyscallResult {
1876 common.ioctl(request, arg_ptr, memory_manager)
1877 }
1878
1879 fn connect(
1880 self,
1881 common: &mut UnixSocketCommon,
1882 _socket: &Arc<AtomicRefCell<UnixSocket>>,
1883 addr: &SockaddrStorage,
1884 cb_queue: &mut CallbackQueue,
1885 ) -> (ProtocolState, Result<(), SyscallError>) {
1886 let Some(addr) = addr.as_unix() else {
1888 return (self.into(), Err(Errno::EINVAL.into()));
1889 };
1890
1891 let peer = match lookup_address(&common.namespace.borrow(), common.socket_type, &addr) {
1893 Ok(x) => x,
1894 Err(e) => return (self.into(), Err(e.into())),
1895 };
1896
1897 let new_state = Self {
1898 peer_addr: Some(addr.into_owned()),
1899 peer: Some(peer),
1900 ..self
1901 };
1902
1903 new_state.refresh_file_state(common, FileSignals::empty(), cb_queue);
1904
1905 (new_state.into(), Ok(()))
1906 }
1907
1908 fn connect_unnamed(
1909 self,
1910 common: &mut UnixSocketCommon,
1911 _socket: &Arc<AtomicRefCell<UnixSocket>>,
1912 peer: Arc<AtomicRefCell<UnixSocket>>,
1913 cb_queue: &mut CallbackQueue,
1914 ) -> (ProtocolState, Result<(), SyscallError>) {
1915 assert!(self.peer_addr.is_none());
1916 assert!(self.bound_addr.is_none());
1917
1918 let new_state = Self {
1919 bound_addr: None,
1920 peer_addr: None,
1921 peer: Some(peer),
1922 ..self
1923 };
1924
1925 new_state.refresh_file_state(common, FileSignals::empty(), cb_queue);
1926
1927 (new_state.into(), Ok(()))
1928 }
1929}
1930
1931impl Protocol for ConnLessClosed {
1932 fn peer_address(&self) -> Result<Option<SockaddrUnix<libc::sockaddr_un>>, Errno> {
1933 Ok(None)
1934 }
1935
1936 fn bound_address(&self) -> Result<Option<SockaddrUnix<libc::sockaddr_un>>, Errno> {
1937 Ok(None)
1938 }
1939
1940 fn refresh_file_state(
1941 &self,
1942 common: &mut UnixSocketCommon,
1943 signals: FileSignals,
1944 cb_queue: &mut CallbackQueue,
1945 ) {
1946 assert!(!signals.contains(FileSignals::READ_BUFFER_GREW));
1947 common.update_state(
1948 FileState::all(),
1949 FileState::CLOSED,
1950 signals,
1951 cb_queue,
1952 );
1953 }
1954
1955 fn close(
1956 self,
1957 _common: &mut UnixSocketCommon,
1958 _cb_queue: &mut CallbackQueue,
1959 ) -> (ProtocolState, Result<(), SyscallError>) {
1960 panic!("Trying to close an already closed socket");
1962 }
1963
1964 fn inform_bytes_read(
1965 &mut self,
1966 _common: &mut UnixSocketCommon,
1967 _num: u64,
1968 _cb_queue: &mut CallbackQueue,
1969 ) {
1970 }
1972}
1973
1974struct UnixSocketCommon {
1976 recv_buffer: Arc<AtomicRefCell<SharedBuf>>,
1977 send_limit: u64,
1979 sent_len: u64,
1981 event_source: StateEventSource,
1982 state: FileState,
1983 status: FileStatus,
1984 socket_type: UnixSocketType,
1985 namespace: Arc<AtomicRefCell<AbstractUnixNamespace>>,
1986 has_open_file: bool,
1989}
1990
1991impl UnixSocketCommon {
1992 pub fn supports_sa_restart(&self) -> bool {
1993 true
1994 }
1995
1996 pub fn close(&mut self, cb_queue: &mut CallbackQueue) -> Result<(), SyscallError> {
1997 if !self.state.contains(FileState::CLOSED) {
1999 self.update_state(
2002 FileState::all(),
2003 FileState::CLOSED,
2004 FileSignals::empty(),
2005 cb_queue,
2006 );
2007
2008 warn_and_debug_panic!("When closing a unix socket, the CLOSED flag was not set");
2010 }
2011
2012 Ok(())
2013 }
2014
2015 pub fn bind(
2016 &mut self,
2017 socket: &Arc<AtomicRefCell<UnixSocket>>,
2018 addr: Option<&SockaddrStorage>,
2019 rng: impl rand::Rng,
2020 ) -> Result<SockaddrUnix<libc::sockaddr_un>, SyscallError> {
2021 let Some(addr) = addr.and_then(|x| x.as_unix()) else {
2023 log::warn!("Attempted to bind unix socket to non-unix address {addr:?}");
2024 return Err(Errno::EINVAL.into());
2025 };
2026
2027 let bound_addr = if let Some(name) = addr.as_abstract() {
2029 let namespace = Arc::clone(&self.namespace);
2031 match AbstractUnixNamespace::bind(
2032 &namespace,
2033 self.socket_type,
2034 name.to_vec(),
2035 socket,
2036 &mut self.event_source,
2037 ) {
2038 Ok(()) => addr.into_owned(),
2039 Err(_) => return Err(Errno::EADDRINUSE.into()),
2041 }
2042 } else if addr.is_unnamed() {
2043 let namespace = Arc::clone(&self.namespace);
2045 match AbstractUnixNamespace::autobind(
2046 &namespace,
2047 self.socket_type,
2048 socket,
2049 &mut self.event_source,
2050 rng,
2051 ) {
2052 Ok(ref name) => SockaddrUnix::new_abstract(name).unwrap(),
2053 Err(_) => return Err(Errno::EADDRINUSE.into()),
2054 }
2055 } else {
2056 log::warn!("Only abstract names are currently supported for unix sockets");
2057 return Err(Errno::ENOTSUP.into());
2058 };
2059
2060 Ok(bound_addr)
2061 }
2062
2063 pub fn resolve_destination(
2064 &self,
2065 peer: Option<&Arc<AtomicRefCell<UnixSocket>>>,
2066 addr: Option<SockaddrStorage>,
2067 ) -> Result<Arc<AtomicRefCell<UnixSocket>>, SyscallError> {
2068 let addr = match addr {
2069 Some(ref addr) => Some(addr.as_unix().ok_or(Errno::EINVAL)?),
2070 None => None,
2071 };
2072
2073 let peer = match (peer, addr) {
2076 (Some(peer), Some(_addr)) => match self.socket_type {
2078 UnixSocketType::Stream => return Err(Errno::EISCONN.into()),
2079 UnixSocketType::SeqPacket => Some(peer),
2081 UnixSocketType::Dgram => None,
2082 },
2083 (Some(peer), None) => Some(peer),
2085 (None, Some(_addr)) => match self.socket_type {
2087 UnixSocketType::Stream => return Err(Errno::EOPNOTSUPP.into()),
2088 UnixSocketType::SeqPacket => return Err(Errno::ENOTCONN.into()),
2089 UnixSocketType::Dgram => None,
2090 },
2091 (None, None) => return Err(Errno::ENOTCONN.into()),
2093 };
2094
2095 let peer = match peer {
2097 Some(x) => Arc::clone(x),
2098 None => {
2099 let recv_socket =
2101 lookup_address(&self.namespace.borrow(), self.socket_type, &addr.unwrap())?;
2102 Arc::clone(&recv_socket)
2104 }
2105 };
2106
2107 Ok(peer)
2108 }
2109
2110 pub fn sendmsg(
2111 &mut self,
2112 socket: &Arc<AtomicRefCell<UnixSocket>>,
2113 iovs: &[IoVec],
2114 flags: libc::c_int,
2115 peer: &Arc<AtomicRefCell<UnixSocket>>,
2116 mem: &mut MemoryManager,
2117 cb_queue: &mut CallbackQueue,
2118 ) -> Result<usize, SyscallError> {
2119 let supported_flags = MsgFlags::MSG_DONTWAIT | MsgFlags::MSG_NOSIGNAL | MsgFlags::MSG_TRUNC;
2126
2127 let Some(mut flags) = MsgFlags::from_bits(flags) else {
2130 log::warn!("Unrecognized send flags: {flags:#b}");
2131 return Err(Errno::EINVAL.into());
2132 };
2133 if flags.intersects(!supported_flags) {
2134 log::warn!("Unsupported send flags: {flags:?}");
2135 return Err(Errno::EINVAL.into());
2136 }
2137
2138 if self.status.contains(FileStatus::NONBLOCK) {
2139 flags.insert(MsgFlags::MSG_DONTWAIT);
2140 }
2141
2142 let result = (|| {
2144 let peer_ref = peer.borrow();
2145 let mut send_buffer = peer_ref.recv_buffer().borrow_mut();
2146
2147 if send_buffer.num_readers() == 0 {
2149 return Err(match self.socket_type {
2150 UnixSocketType::Stream | UnixSocketType::SeqPacket => Errno::EPIPE,
2152 UnixSocketType::Dgram => Errno::ECONNREFUSED,
2154 });
2155 }
2156
2157 let len = iovs.iter().map(|x| x.len).sum::<libc::size_t>();
2158
2159 let space_available = self
2162 .send_limit
2163 .saturating_sub(self.sent_len)
2164 .try_into()
2165 .unwrap();
2166
2167 if space_available == 0 {
2168 return Err(Errno::EAGAIN);
2169 }
2170
2171 let len = match self.socket_type {
2172 UnixSocketType::Stream => std::cmp::min(len, space_available),
2173 UnixSocketType::Dgram | UnixSocketType::SeqPacket => {
2174 if len <= space_available {
2175 len
2176 } else if len <= self.send_limit.try_into().unwrap() {
2177 return Err(Errno::EAGAIN);
2179 } else {
2180 return Err(Errno::EMSGSIZE);
2182 }
2183 }
2184 };
2185
2186 let reader = IoVecReader::new(iovs, mem);
2187 let reader = reader.take(len.try_into().unwrap());
2188
2189 let num_copied = match self.socket_type {
2190 UnixSocketType::Stream => {
2191 if len == 0 {
2192 0
2193 } else {
2194 send_buffer
2195 .write_stream(reader, len, cb_queue)
2196 .map_err(|e| Errno::try_from(e).unwrap())?
2197 }
2198 }
2199 UnixSocketType::Dgram | UnixSocketType::SeqPacket => {
2200 send_buffer
2201 .write_packet(reader, len, cb_queue)
2202 .map_err(|e| Errno::try_from(e).unwrap())?;
2203 len
2204 }
2205 };
2206
2207 self.sent_len += u64::try_from(num_copied).unwrap();
2209
2210 Ok(num_copied)
2211 })();
2212
2213 if result.as_ref().err() == Some(&Errno::EWOULDBLOCK)
2215 && !flags.contains(MsgFlags::MSG_DONTWAIT)
2216 {
2217 return Err(SyscallError::new_blocked_on_file(
2218 File::Socket(Socket::Unix(socket.clone())),
2219 FileState::WRITABLE,
2220 self.supports_sa_restart(),
2221 ));
2222 }
2223
2224 Ok(result?)
2225 }
2226
2227 pub fn recvmsg(
2228 &mut self,
2229 socket: &Arc<AtomicRefCell<UnixSocket>>,
2230 iovs: &[IoVec],
2231 flags: libc::c_int,
2232 mem: &mut MemoryManager,
2233 cb_queue: &mut CallbackQueue,
2234 ) -> Result<(usize, usize, libc::c_int), SyscallError> {
2235 let supported_flags = MsgFlags::MSG_DONTWAIT | MsgFlags::MSG_TRUNC;
2236
2237 let Some(mut flags) = MsgFlags::from_bits(flags) else {
2240 log::warn!("Unrecognized recv flags: {flags:#b}");
2241 return Err(Errno::EINVAL.into());
2242 };
2243 if flags.intersects(!supported_flags) {
2244 log::warn!("Unsupported recv flags: {flags:?}");
2245 return Err(Errno::EINVAL.into());
2246 }
2247
2248 if self.status.contains(FileStatus::NONBLOCK) {
2249 flags.insert(MsgFlags::MSG_DONTWAIT);
2250 }
2251
2252 let result = (|| {
2254 let mut recv_buffer = self.recv_buffer.borrow_mut();
2255
2256 if !recv_buffer.has_data()
2261 && (self.socket_type == UnixSocketType::Dgram || recv_buffer.num_writers() > 0)
2262 {
2263 return Err(Errno::EWOULDBLOCK);
2265 }
2266
2267 let writer = IoVecWriter::new(iovs, mem);
2268
2269 let (num_copied, num_removed_from_buf) = recv_buffer
2270 .read(writer, cb_queue)
2271 .map_err(|e| Errno::try_from(e).unwrap())?;
2272
2273 let mut msg_flags = 0;
2274
2275 if flags.contains(MsgFlags::MSG_TRUNC)
2276 && [UnixSocketType::Dgram, UnixSocketType::SeqPacket].contains(&self.socket_type)
2277 {
2278 if num_copied < num_removed_from_buf {
2279 msg_flags |= libc::MSG_TRUNC;
2280 }
2281
2282 Ok((num_removed_from_buf, num_removed_from_buf, msg_flags))
2285 } else {
2286 Ok((num_copied, num_removed_from_buf, msg_flags))
2289 }
2290 })();
2291
2292 if result.as_ref().err() == Some(&Errno::EWOULDBLOCK)
2294 && !flags.contains(MsgFlags::MSG_DONTWAIT)
2295 {
2296 return Err(SyscallError::new_blocked_on_file(
2297 File::Socket(Socket::Unix(socket.clone())),
2298 FileState::READABLE,
2299 self.supports_sa_restart(),
2300 ));
2301 }
2302
2303 Ok(result?)
2304 }
2305
2306 pub fn ioctl(
2307 &mut self,
2308 request: IoctlRequest,
2309 _arg_ptr: ForeignPtr<()>,
2310 _memory_manager: &mut MemoryManager,
2311 ) -> SyscallResult {
2312 log::warn!("We do not yet handle ioctl request {request:?} on unix sockets");
2313 Err(Errno::EINVAL.into())
2314 }
2315
2316 fn update_state(
2317 &mut self,
2318 mask: FileState,
2319 state: FileState,
2320 signals: FileSignals,
2321 cb_queue: &mut CallbackQueue,
2322 ) {
2323 let old_state = self.state;
2324
2325 self.state.remove(mask);
2327 self.state.insert(state & mask);
2328
2329 self.handle_state_change(old_state, signals, cb_queue);
2330 }
2331
2332 fn handle_state_change(
2333 &mut self,
2334 old_state: FileState,
2335 signals: FileSignals,
2336 cb_queue: &mut CallbackQueue,
2337 ) {
2338 let states_changed = self.state ^ old_state;
2339
2340 if states_changed.is_empty() && signals.is_empty() {
2342 return;
2343 }
2344
2345 self.event_source
2346 .notify_listeners(self.state, states_changed, signals, cb_queue);
2347 }
2348}
2349
2350fn lookup_address(
2351 namespace: &AbstractUnixNamespace,
2352 socket_type: UnixSocketType,
2353 addr: &SockaddrUnix<&libc::sockaddr_un>,
2354) -> Result<Arc<AtomicRefCell<UnixSocket>>, linux_api::errno::Errno> {
2355 if let Some(name) = addr.as_abstract() {
2357 namespace
2359 .lookup(socket_type, name)
2360 .ok_or(linux_api::errno::Errno::ECONNREFUSED)
2361 } else {
2362 warn_once_then_debug!("Unix sockets with pathname addresses are not yet supported");
2363 Err(linux_api::errno::Errno::ENOENT)
2364 }
2365}
2366
2367fn backlog_to_queue_size(backlog: i32) -> u32 {
2368 let backlog = backlog as u32;
2371
2372 let queue_limit = std::cmp::min(backlog, c::SHADOW_SOMAXCONN);
2374
2375 queue_limit.saturating_add(1)
2378}
2379
2380#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
2382pub enum UnixSocketType {
2383 Stream,
2384 Dgram,
2385 SeqPacket,
2386}
2387
2388impl TryFrom<libc::c_int> for UnixSocketType {
2389 type Error = UnixSocketTypeConversionError;
2390 fn try_from(val: libc::c_int) -> Result<Self, Self::Error> {
2391 match val {
2392 libc::SOCK_STREAM => Ok(Self::Stream),
2393 libc::SOCK_DGRAM => Ok(Self::Dgram),
2394 libc::SOCK_SEQPACKET => Ok(Self::SeqPacket),
2395 x => Err(UnixSocketTypeConversionError(x)),
2396 }
2397 }
2398}
2399
2400#[derive(Copy, Clone, Debug)]
2401pub struct UnixSocketTypeConversionError(libc::c_int);
2402
2403impl std::error::Error for UnixSocketTypeConversionError {}
2404
2405impl std::fmt::Display for UnixSocketTypeConversionError {
2406 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
2407 write!(
2408 f,
2409 "Invalid socket type {}; unix sockets only support SOCK_STREAM, SOCK_DGRAM, and SOCK_SEQPACKET",
2410 self.0
2411 )
2412 }
2413}
2414
2415#[derive(Copy, Clone, Debug)]
2416enum IncomingConnError {
2417 QueueFull,
2418 NotSupported,
2419}
2420
2421struct ByteData {
2422 from_socket: Arc<AtomicRefCell<UnixSocket>>,
2423 from_addr: Option<SockaddrUnix<libc::sockaddr_un>>,
2424 num_bytes: u64,
2425}