Skip to main content

shadow_rs/host/descriptor/socket/
unix.rs

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
33/// A unix socket. The `UnixSocket` is the public-facing API, which forwards API calls to the inner
34/// state object.
35pub struct UnixSocket {
36    /// Data and functionality that is general for all states.
37    common: UnixSocketCommon,
38    /// State-specific data and functionality.
39    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            // each socket tracks its own send limit, and we let the receiver have an unlimited recv
50            // buffer size
51            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            // may generate new events
67            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        // return the bound address if set, otherwise return an empty unix sockaddr
102        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        // return the peer address if set, otherwise return an empty unix sockaddr
111        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        // we could call UnixSocket::recvmsg() here, but for now we expect that there are no code
161        // paths that would call UnixSocket::readv() since the readv() syscall handler should have
162        // called UnixSocket::recvmsg() instead
163        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        // we could call UnixSocket::sendmsg() here, but for now we expect that there are no code
175        // paths that would call UnixSocket::writev() since the writev() syscall handler should have
176        // called UnixSocket::sendmsg() instead
177        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    // these handles are never accessed, but we store them because of their drop impls
384    _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    // this handle is never accessed, but we store it because of its drop impl
397    _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
407/// The current protocol state of the unix socket. An `Option` is required for each variant so that
408/// the inner state object can be removed, transformed into a new state, and then re-added as a
409/// different variant.
410enum 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
419/// Upcast from a type to an enum variant.
420macro_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
430// implement upcasting for all state types
431state_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                // this is a new socket and there are no listeners, so safe to use a temporary event queue
450                let mut cb_queue = CallbackQueue::new();
451
452                // dgram unix sockets are immediately able to receive data, so initialize the
453                // receive buffer
454
455                // increment the buffer's reader count
456                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                // make sure no events were generated since if there were events to run, they would
476                // probably not run correctly if the socket's Arc is not fully created yet (as in
477                // the case of `Arc::new_cyclic`)
478                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    /// Called on the listening socket when there is an incoming connection.
824    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
879/// Methods that a protocol state may wish to handle. Default implementations which return an error
880/// status are provided for many methods. Each type that implements this trait can override any of
881/// these default implementations.
882trait 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            /* mask= */ 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 already bound
1064        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        // it must have already been bound
1126        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        // refresh the socket's file state
1138        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        // look up the server socket
1155        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        // need to tell the server to queue a new child socket, and then link the current socket
1165        // with the new child socket
1166
1167        // inform the server socket of the incoming connection and get the server socket's new child
1168        // socket
1169        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                // block until the server has room for new connections, or is closed
1187                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        // our send buffer will be the peer's receive buffer
1198        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        // increment the buffer's writer count
1214        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        // increment the buffer's reader count
1233        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            // increment the buffer's writer count
1280            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        // increment the buffer's reader count
1300        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        // socket is readable if the queue is not empty
1345        new_state.set(FileState::READABLE, !self.queue.is_empty());
1346
1347        // socket allows connections if the queue is not full
1348        new_state.set(FileState::SOCKET_ALLOWING_CONNECT, !self.queue_is_full());
1349
1350        // Note: This can cause a thundering-herd condition where multiple blocked connect() calls
1351        // are all notified at the same time, even if there isn't enough space to allow all of them.
1352        // In practice this should be uncommon so we don't worry about it, and avoids requiring that
1353        // the server keep a list of all connecting clients.
1354
1355        common.update_state(
1356            /* mask= */ 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            // close all queued sockets
1370            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        // refresh the socket's file state
1389        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        // refresh the socket's file state
1415        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            // copy the parent's status
1437            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        // increment the buffer's writer count
1458        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        // increment the buffer's reader count
1477        let reader_handle = child_recv_buffer.borrow_mut().add_reader(cb_queue);
1478
1479        let new_child_state = ConnOrientedConnected {
1480            // use the parent's bind address
1481            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        // update the child socket's state
1491        child_socket.borrow_mut().protocol_state = new_child_state.into();
1492
1493        // defer refreshing the child socket's file-state until later
1494        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        // add the child socket to the accept queue
1504        self.queue.push_back(child_socket);
1505
1506        // refresh the server socket's file state
1507        self.refresh_file_state(common, FileSignals::empty(), cb_queue);
1508
1509        // return a reference to the enqueued child socket
1510        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            /* mask= */ 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        // inform the buffer that there is one fewer readers
1560        common
1561            .recv_buffer
1562            .borrow_mut()
1563            .remove_reader(self.reader_handle, cb_queue);
1564
1565        // inform the buffer that there is one fewer writers
1566        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            // defer informing the peer until we're done processing the current socket
1617            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            /* mask= */ 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        // why are we trying to close an already closed file? we probably want a bt here...
1694        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        // do nothing since we're already closed
1704    }
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            /* mask= */ 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        // inform the buffer that there is one fewer readers
1748        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            // defer informing the senders until we're done processing the current socket
1755            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 already bound
1776        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        // defer informing the sender until we're done processing the current socket
1842        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        // TODO: support AF_UNSPEC to disassociate
1887        let Some(addr) = addr.as_unix() else {
1888            return (self.into(), Err(Errno::EINVAL.into()));
1889        };
1890
1891        // find the socket bound at the address
1892        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            /* mask= */ 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        // why are we trying to close an already closed file? we probably want a bt here...
1961        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        // do nothing since we're already closed
1971    }
1972}
1973
1974/// Common data and functionality that is useful for all states.
1975struct UnixSocketCommon {
1976    recv_buffer: Arc<AtomicRefCell<SharedBuf>>,
1977    /// The max number of "in flight" bytes (sent but not yet read from the receiving socket).
1978    send_limit: u64,
1979    /// The number of "in flight" bytes.
1980    sent_len: u64,
1981    event_source: StateEventSource,
1982    state: FileState,
1983    status: FileStatus,
1984    socket_type: UnixSocketType,
1985    namespace: Arc<AtomicRefCell<AbstractUnixNamespace>>,
1986    // should only be used by `OpenFile` to make sure there is only ever one `OpenFile` instance for
1987    // this file
1988    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        // check that the CLOSED flag was set by the protocol state
1998        if !self.state.contains(FileState::CLOSED) {
1999            // set the flag here since we missed doing it before
2000            // do this before the below panic, otherwise rust gives us warnings
2001            self.update_state(
2002                /* mask= */ FileState::all(),
2003                FileState::CLOSED,
2004                FileSignals::empty(),
2005                cb_queue,
2006            );
2007
2008            // panic in debug builds since the backtrace will be helpful for debugging
2009            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        // get the unix address
2022        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        // bind the socket
2028        let bound_addr = if let Some(name) = addr.as_abstract() {
2029            // if given an abstract socket address
2030            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                // address is in use
2040                Err(_) => return Err(Errno::EADDRINUSE.into()),
2041            }
2042        } else if addr.is_unnamed() {
2043            // if given an "unnamed" address
2044            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        // returns either the send buffer, or None if we should look up the send buffer from the
2074        // socket address
2075        let peer = match (peer, addr) {
2076            // already connected but a destination address was given
2077            (Some(peer), Some(_addr)) => match self.socket_type {
2078                UnixSocketType::Stream => return Err(Errno::EISCONN.into()),
2079                // linux seems to ignore the destination address for connected seq packet sockets
2080                UnixSocketType::SeqPacket => Some(peer),
2081                UnixSocketType::Dgram => None,
2082            },
2083            // already connected and no destination address was given
2084            (Some(peer), None) => Some(peer),
2085            // not connected but a destination address was given
2086            (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            // not connected and no destination address given
2092            (None, None) => return Err(Errno::ENOTCONN.into()),
2093        };
2094
2095        // either use the existing send buffer, or look up the send buffer from the address
2096        let peer = match peer {
2097            Some(x) => Arc::clone(x),
2098            None => {
2099                // look up the socket from the address name
2100                let recv_socket =
2101                    lookup_address(&self.namespace.borrow(), self.socket_type, &addr.unwrap())?;
2102                // store an Arc of the recv buffer
2103                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        // MSG_NOSIGNAL is currently a no-op, since we haven't implemented the behavior
2120        // it's meant to disable.
2121        // TODO: Once we've implemented generating a SIGPIPE when the peer on a
2122        // stream-oriented socket has closed the connection, MSG_NOSIGNAL should
2123        // disable it.
2124        // Ignore the MSG_TRUNC flag since it doesn't do anything when sending.
2125        let supported_flags = MsgFlags::MSG_DONTWAIT | MsgFlags::MSG_NOSIGNAL | MsgFlags::MSG_TRUNC;
2126
2127        // if there's a flag we don't support, it's probably best to raise an error rather than do
2128        // the wrong thing
2129        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        // run in a closure so that an early return doesn't return from the syscall handler
2143        let result = (|| {
2144            let peer_ref = peer.borrow();
2145            let mut send_buffer = peer_ref.recv_buffer().borrow_mut();
2146
2147            // if the buffer has no readers, the destination socket is closed
2148            if send_buffer.num_readers() == 0 {
2149                return Err(match self.socket_type {
2150                    // connection-oriented socket
2151                    UnixSocketType::Stream | UnixSocketType::SeqPacket => Errno::EPIPE,
2152                    // connectionless socket
2153                    UnixSocketType::Dgram => Errno::ECONNREFUSED,
2154                });
2155            }
2156
2157            let len = iovs.iter().map(|x| x.len).sum::<libc::size_t>();
2158
2159            // we keep track of the send buffer size manually, since the unix socket buffers all have
2160            // usize::MAX length
2161            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                        // we can send this when the buffer has more space available
2178                        return Err(Errno::EAGAIN);
2179                    } else {
2180                        // we could never send this message
2181                        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            // if we successfully sent bytes, update the sent count
2208            self.sent_len += u64::try_from(num_copied).unwrap();
2209
2210            Ok(num_copied)
2211        })();
2212
2213        // if the syscall would block and we don't have the MSG_DONTWAIT flag
2214        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        // if there's a flag we don't support, it's probably best to raise an error rather than do
2238        // the wrong thing
2239        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        // run in a closure so that an early return doesn't return from the syscall handler
2253        let result = (|| {
2254            let mut recv_buffer = self.recv_buffer.borrow_mut();
2255
2256            // the read would block if all:
2257            //  1. the recv buffer has no data
2258            //  2. it's a connectionless socket OR the connection-oriented destination socket is not
2259            //     closed
2260            if !recv_buffer.has_data()
2261                && (self.socket_type == UnixSocketType::Dgram || recv_buffer.num_writers() > 0)
2262            {
2263                // return EWOULDBLOCK even if 'bytes' has length 0
2264                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                // we're a message-based socket and MSG_TRUNC is set, so return the total size of
2283                // the message, not the number of bytes we read
2284                Ok((num_removed_from_buf, num_removed_from_buf, msg_flags))
2285            } else {
2286                // We're a stream-based socket. Unlike TCP sockets, unix stream sockets ignore the
2287                // MSG_TRUNC flag.
2288                Ok((num_copied, num_removed_from_buf, msg_flags))
2289            }
2290        })();
2291
2292        // if the syscall would block and we don't have the MSG_DONTWAIT flag
2293        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        // remove the masked flags, then copy the masked flags
2326        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 nothing changed
2341        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 an abstract address
2356    if let Some(name) = addr.as_abstract() {
2357        // look up the socket from the address name
2358        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    // linux also makes this cast, so negative backlogs wrap around to large positive backlogs
2369    // https://elixir.free-electrons.com/linux/v5.11.22/source/net/unix/af_unix.c#L628
2370    let backlog = backlog as u32;
2371
2372    // the linux '__sys_listen()' applies the somaxconn max to all protocols, including unix sockets
2373    let queue_limit = std::cmp::min(backlog, c::SHADOW_SOMAXCONN);
2374
2375    // linux uses a limit of one greater than the provided backlog (ex: a backlog value of 0 allows
2376    // for one incoming connection at a time)
2377    queue_limit.saturating_add(1)
2378}
2379
2380// WARNING: don't add new enum variants without updating 'AbstractUnixNamespace::new()'
2381#[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}