starnix_core/vfs/socket/
socket.rs

1// Copyright 2021 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5use super::{
6    NetlinkFamily, QipcrtrSocket, SocketAddress, SocketDomain, SocketFile, SocketMessageFlags,
7    SocketProtocol, SocketShutdownFlags, SocketType, UnixSocket, VsockSocket, ZxioBackedSocket,
8    new_netlink_socket,
9};
10use crate::mm::MemoryAccessorExt;
11use crate::security;
12use crate::syscalls::time::TimeValPtr;
13use crate::task::{CurrentTask, EventHandler, WaitCanceler, Waiter};
14use crate::vfs::buffers::{AncillaryData, InputBuffer, MessageReadInfo, OutputBuffer};
15use crate::vfs::{DowncastedFile, FileHandle, FileObject, FsNodeHandle, default_ioctl};
16use starnix_logging::track_stub;
17use starnix_sync::{FileOpsCore, LockEqualOrBefore, Locked, Mutex, Unlocked};
18use starnix_syscalls::{SyscallArg, SyscallResult};
19use starnix_types::time::{duration_from_timeval, timeval_from_duration};
20use starnix_types::user_buffer::UserBuffer;
21use starnix_uapi::as_any::AsAny;
22use starnix_uapi::auth::CAP_NET_RAW;
23use starnix_uapi::errors::{ENOTTY, Errno};
24use starnix_uapi::user_address::MappingMultiArchUserRef;
25use starnix_uapi::vfs::FdEvents;
26use starnix_uapi::{
27    SO_DOMAIN, SO_PROTOCOL, SO_RCVTIMEO, SO_SNDTIMEO, SO_TYPE, SOL_SOCKET, errno, error, uapi,
28};
29use std::collections::VecDeque;
30use std::sync::Arc;
31use std::sync::atomic::Ordering;
32use zerocopy::FromBytes;
33
34pub const DEFAULT_LISTEN_BACKLOG: usize = 1024;
35
36pub trait SocketOps: Send + Sync + AsAny {
37    /// Returns the domain, type and protocol of the socket. This is only used for socket that are
38    /// build without previous knowledge of this information, and can be ignored if all sockets are
39    /// build with it.
40    fn get_socket_info(&self) -> Result<(SocketDomain, SocketType, SocketProtocol), Errno> {
41        // This should not be used by most socket type that are created with their domain, type and
42        // protocol.
43        error!(EINVAL)
44    }
45
46    /// Connect the `socket` to the listening `peer`. On success
47    /// a new socket is created and added to the accept queue.
48    fn connect(
49        &self,
50        locked: &mut Locked<FileOpsCore>,
51        socket: &SocketHandle,
52        current_task: &CurrentTask,
53        peer: SocketPeer,
54    ) -> Result<(), Errno>;
55
56    /// Start listening at the bound address for `connect` calls.
57    fn listen(
58        &self,
59        locked: &mut Locked<FileOpsCore>,
60        socket: &Socket,
61        backlog: i32,
62        credentials: uapi::ucred,
63    ) -> Result<(), Errno>;
64
65    /// Returns the eariest socket on the accept queue of this
66    /// listening socket. Returns EAGAIN if the queue is empty.
67    fn accept(
68        &self,
69        locked: &mut Locked<FileOpsCore>,
70        socket: &Socket,
71        current_task: &CurrentTask,
72    ) -> Result<SocketHandle, Errno>;
73
74    /// Binds this socket to a `socket_address`.
75    ///
76    /// Returns an error if the socket could not be bound.
77    fn bind(
78        &self,
79        locked: &mut Locked<FileOpsCore>,
80        socket: &Socket,
81        current_task: &CurrentTask,
82        socket_address: SocketAddress,
83    ) -> Result<(), Errno>;
84
85    /// Reads the specified number of bytes from the socket, if possible.
86    ///
87    /// # Parameters
88    /// - `task`: The task to which the user buffers belong (i.e., the task to which the read bytes
89    ///           are written.
90    /// - `data`: The buffers to write the read data into.
91    ///
92    /// Returns the number of bytes that were written to the user buffers, as well as any ancillary
93    /// data associated with the read messages.
94    fn read(
95        &self,
96        locked: &mut Locked<FileOpsCore>,
97        socket: &Socket,
98        current_task: &CurrentTask,
99        data: &mut dyn OutputBuffer,
100        flags: SocketMessageFlags,
101    ) -> Result<MessageReadInfo, Errno>;
102
103    /// Writes the data in the provided user buffers to this socket.
104    ///
105    /// # Parameters
106    /// - `task`: The task to which the user buffers belong, used to read the memory.
107    /// - `data`: The data to write to the socket.
108    /// - `ancillary_data`: Optional ancillary data (a.k.a., control message) to write.
109    ///
110    /// Advances the iterator to indicate how much was actually written.
111    fn write(
112        &self,
113        locked: &mut Locked<FileOpsCore>,
114        socket: &Socket,
115        current_task: &CurrentTask,
116        data: &mut dyn InputBuffer,
117        dest_address: &mut Option<SocketAddress>,
118        ancillary_data: &mut Vec<AncillaryData>,
119    ) -> Result<usize, Errno>;
120
121    /// Queues an asynchronous wait for the specified `events`
122    /// on the `waiter`. Note that no wait occurs until a
123    /// wait functions is called on the `waiter`.
124    ///
125    /// # Parameters
126    /// - `waiter`: The Waiter that can be waited on, for example by
127    ///             calling Waiter::wait_until.
128    /// - `events`: The events that will trigger the waiter to wake up.
129    /// - `handler`: A handler that will be called on wake-up.
130    /// Returns a WaitCanceler that can be used to cancel the wait.
131    fn wait_async(
132        &self,
133        locked: &mut Locked<FileOpsCore>,
134        socket: &Socket,
135        current_task: &CurrentTask,
136        waiter: &Waiter,
137        events: FdEvents,
138        handler: EventHandler,
139    ) -> WaitCanceler;
140
141    /// Return the events that are currently active on the `socket`.
142    fn query_events(
143        &self,
144        locked: &mut Locked<FileOpsCore>,
145        socket: &Socket,
146        current_task: &CurrentTask,
147    ) -> Result<FdEvents, Errno>;
148
149    /// Shuts down this socket according to how, preventing any future reads and/or writes.
150    ///
151    /// Used by the shutdown syscalls.
152    fn shutdown(
153        &self,
154        locked: &mut Locked<FileOpsCore>,
155        socket: &Socket,
156        how: SocketShutdownFlags,
157    ) -> Result<(), Errno>;
158
159    /// Close this socket.
160    ///
161    /// Called by SocketFile when the file descriptor that is holding this
162    /// socket is closed.
163    ///
164    /// Close differs from shutdown in two ways. First, close will call
165    /// mark_peer_closed_with_unread_data if this socket has unread data,
166    /// which changes how read() behaves on that socket. Second, close
167    /// transitions the internal state of this socket to Closed, which breaks
168    /// the reference cycle that exists in the connected state.
169    fn close(&self, locked: &mut Locked<FileOpsCore>, current_task: &CurrentTask, socket: &Socket);
170
171    /// Returns the name of this socket.
172    ///
173    /// The name is derived from the address and domain. A socket
174    /// will always have a name, even if it is not bound to an address.
175    fn getsockname(
176        &self,
177        locked: &mut Locked<FileOpsCore>,
178        socket: &Socket,
179    ) -> Result<SocketAddress, Errno>;
180
181    /// Returns the name of the peer of this socket, if such a peer exists.
182    ///
183    /// Returns an error if the socket is not connected.
184    fn getpeername(
185        &self,
186        locked: &mut Locked<FileOpsCore>,
187        socket: &Socket,
188    ) -> Result<SocketAddress, Errno>;
189
190    /// Sets socket-specific options.
191    fn setsockopt(
192        &self,
193        _locked: &mut Locked<FileOpsCore>,
194        _socket: &Socket,
195        _current_task: &CurrentTask,
196        _level: u32,
197        _optname: u32,
198        _optval: SockOptValue,
199    ) -> Result<(), Errno> {
200        error!(ENOPROTOOPT)
201    }
202
203    /// Retrieves socket-specific options.
204    fn getsockopt(
205        &self,
206        _locked: &mut Locked<FileOpsCore>,
207        _socket: &Socket,
208        _current_task: &CurrentTask,
209        _level: u32,
210        _optname: u32,
211        _optlen: u32,
212    ) -> Result<Vec<u8>, Errno> {
213        error!(ENOPROTOOPT)
214    }
215
216    /// Implements ioctl.
217    fn ioctl(
218        &self,
219        locked: &mut Locked<Unlocked>,
220        _socket: &Socket,
221        file: &FileObject,
222        current_task: &CurrentTask,
223        request: u32,
224        arg: SyscallArg,
225    ) -> Result<SyscallResult, Errno> {
226        default_ioctl(file, locked, current_task, request, arg)
227    }
228
229    /// Return a handle that allows access to this file descritor through the zxio protocols.
230    ///
231    /// If None is returned, the file will be proxied.
232    fn to_handle(
233        &self,
234        _socket: &Socket,
235        _current_task: &CurrentTask,
236    ) -> Result<Option<zx::NullableHandle>, Errno> {
237        Ok(None)
238    }
239}
240
241/// A `Socket` represents one endpoint of a bidirectional communication channel.
242pub struct Socket {
243    pub(super) ops: Box<dyn SocketOps>,
244
245    /// The domain of this socket.
246    pub domain: SocketDomain,
247
248    /// The type of this socket.
249    pub socket_type: SocketType,
250
251    /// The protocol of this socket.
252    pub protocol: SocketProtocol,
253
254    state: Mutex<SocketState>,
255
256    /// Security module state associated with this socket. Note that the socket's security label is
257    /// applied to the associated `fs_node`.
258    pub security: security::SocketState,
259}
260
261#[derive(Default)]
262struct SocketState {
263    /// The value of SO_RCVTIMEO.
264    receive_timeout: Option<zx::MonotonicDuration>,
265
266    /// The value for SO_SNDTIMEO.
267    send_timeout: Option<zx::MonotonicDuration>,
268
269    /// Reference to the [`crate::vfs::FsNode`] to which this `Socket` is attached.
270    /// `None` until the `Socket` is wrapped into a [`crate::vfs::FileObject`] (e.g. while it is
271    /// still held in a listen queue).
272    fs_node: Option<FsNodeHandle>,
273}
274
275pub type SocketHandle = Arc<Socket>;
276
277#[derive(Clone)]
278pub enum SocketPeer {
279    Handle(SocketHandle),
280    Address(SocketAddress),
281}
282
283// `resolve_protocol()` returns the protocol that should be used for a new
284// socket. `socket()` allows `protocol` parameter to be set 0, in which case the
285// protocol defaults to TCP or UDP depending on the specified `socket_type`.
286fn resolve_protocol(
287    domain: SocketDomain,
288    socket_type: SocketType,
289    protocol: SocketProtocol,
290) -> SocketProtocol {
291    if domain.is_inet() && protocol.as_raw() == 0 {
292        match socket_type {
293            SocketType::Stream => SocketProtocol::TCP,
294            SocketType::Datagram => SocketProtocol::UDP,
295            _ => protocol,
296        }
297    } else {
298        protocol
299    }
300}
301
302fn create_socket_ops(
303    locked: &mut Locked<FileOpsCore>,
304    current_task: &CurrentTask,
305    domain: SocketDomain,
306    socket_type: SocketType,
307    protocol: SocketProtocol,
308) -> Result<Box<dyn SocketOps>, Errno> {
309    match domain {
310        SocketDomain::Unix => Ok(Box::new(UnixSocket::new(socket_type))),
311        SocketDomain::Vsock => Ok(Box::new(VsockSocket::new(socket_type))),
312        SocketDomain::Inet | SocketDomain::Inet6 => {
313            // Follow Linux, and require CAP_NET_RAW to create raw sockets.
314            // See https://man7.org/linux/man-pages/man7/raw.7.html.
315            if socket_type == SocketType::Raw {
316                security::check_task_capable(current_task, CAP_NET_RAW)?;
317            }
318            Ok(Box::new(ZxioBackedSocket::new(
319                locked,
320                current_task,
321                domain,
322                socket_type,
323                protocol,
324            )?))
325        }
326        SocketDomain::Netlink => {
327            let netlink_family = NetlinkFamily::from_raw(protocol.as_raw());
328            new_netlink_socket(current_task.kernel(), socket_type, netlink_family)
329        }
330        SocketDomain::Packet => {
331            // Follow Linux, and require CAP_NET_RAW to create packet sockets.
332            // See https://man7.org/linux/man-pages/man7/packet.7.html.
333            security::check_task_capable(current_task, CAP_NET_RAW)?;
334            Ok(Box::new(ZxioBackedSocket::new(
335                locked,
336                current_task,
337                domain,
338                socket_type,
339                protocol,
340            )?))
341        }
342        SocketDomain::Key => {
343            track_stub!(
344                TODO("https://fxbug.dev/323365389"),
345                "Returning a UnixSocket instead of a KeySocket"
346            );
347            Ok(Box::new(UnixSocket::new(SocketType::Datagram)))
348        }
349        SocketDomain::Qipcrtr => Ok(Box::new(QipcrtrSocket::new(socket_type))),
350    }
351}
352
353#[derive(Debug)]
354pub enum SockOptValue {
355    Value(Vec<u8>),
356    User(UserBuffer),
357}
358
359impl From<Vec<u8>> for SockOptValue {
360    fn from(buffer: Vec<u8>) -> Self {
361        Self::Value(buffer)
362    }
363}
364
365impl From<UserBuffer> for SockOptValue {
366    fn from(buffer: UserBuffer) -> Self {
367        Self::User(buffer)
368    }
369}
370
371impl SockOptValue {
372    pub fn len(&self) -> usize {
373        match self {
374            Self::Value(buffer) => buffer.len(),
375            Self::User(user_buffer) => user_buffer.length,
376        }
377    }
378
379    pub fn read<T: FromBytes>(&self, current_task: &CurrentTask) -> Result<T, Errno> {
380        match self {
381            Self::Value(buffer) => {
382                T::read_from_prefix(&buffer).map_err(|_| errno!(EINVAL)).map(|(v, _)| v)
383            }
384            Self::User(user_buffer) => {
385                current_task.read_object::<T>(user_buffer.clone().try_into()?)
386            }
387        }
388    }
389
390    pub fn read_bytes(
391        &self,
392        current_task: &CurrentTask,
393        max_bytes: usize,
394    ) -> Result<Vec<u8>, Errno> {
395        match self {
396            Self::Value(buffer) => {
397                let bytes = std::cmp::min(max_bytes, buffer.len());
398                Ok(buffer[..bytes].to_owned())
399            }
400            Self::User(user_buffer) => {
401                let bytes = std::cmp::min(max_bytes, user_buffer.length);
402                current_task
403                    .read_buffer(&UserBuffer { address: user_buffer.address, length: bytes })
404            }
405        }
406    }
407
408    pub fn to_vec(self, current_task: &CurrentTask) -> Result<Vec<u8>, Errno> {
409        match self {
410            Self::Value(buffer) => Ok(buffer),
411            Self::User(user_buffer) => current_task.read_buffer(&user_buffer),
412        }
413    }
414}
415
416// Trait used to provide `read_from_sockopt_value` for `MappingMultiArchUserRef`.
417pub trait ReadFromSockOptValue {
418    type Result;
419    fn read_from_sockopt_value(
420        current_task: &CurrentTask,
421        buffer: &SockOptValue,
422    ) -> Result<Self::Result, Errno>;
423}
424
425impl<T, T64, T32> ReadFromSockOptValue for MappingMultiArchUserRef<T, T64, T32>
426where
427    T64: FromBytes + TryInto<T>,
428    T32: FromBytes + TryInto<T>,
429{
430    type Result = T;
431    fn read_from_sockopt_value(
432        current_task: &CurrentTask,
433        buffer: &SockOptValue,
434    ) -> Result<T, Errno> {
435        match buffer {
436            SockOptValue::Value(buffer) => {
437                Self::read_from_prefix(current_task, &buffer).map_err(|_| errno!(EINVAL))
438            }
439            SockOptValue::User(user_buffer) => {
440                let user_ref = Self::new_with_ref(current_task, user_buffer.clone())?;
441                current_task.read_multi_arch_object(user_ref)
442            }
443        }
444    }
445}
446
447impl Socket {
448    /// Creates a new unbound socket.
449    ///
450    /// # Parameters
451    /// - `domain`: The domain of the socket (e.g., `AF_UNIX`).
452    pub fn new<L>(
453        locked: &mut Locked<L>,
454        current_task: &CurrentTask,
455        domain: SocketDomain,
456        socket_type: SocketType,
457        protocol: SocketProtocol,
458        kernel_private: bool,
459    ) -> Result<SocketHandle, Errno>
460    where
461        L: LockEqualOrBefore<FileOpsCore>,
462    {
463        let protocol = resolve_protocol(domain, socket_type, protocol);
464        // Checking access in `Socket::new()` prevents creating socket handles when not allowed,
465        // while skipping the "create" permission check for accepted sockets created with
466        // `Socket::new_with_ops()` and `Socket::new_with_ops_and_info()`.
467        security::check_socket_create_access(
468            locked,
469            current_task,
470            domain,
471            socket_type,
472            protocol,
473            kernel_private,
474        )?;
475        let ops =
476            create_socket_ops(locked.cast_locked(), current_task, domain, socket_type, protocol)?;
477        Ok(Self::new_with_ops_and_info(ops, domain, socket_type, protocol))
478    }
479
480    pub fn new_with_ops(ops: Box<dyn SocketOps>) -> Result<SocketHandle, Errno> {
481        let (domain, socket_type, protocol) = ops.get_socket_info()?;
482        Ok(Self::new_with_ops_and_info(ops, domain, socket_type, protocol))
483    }
484
485    pub fn new_with_ops_and_info(
486        ops: Box<dyn SocketOps>,
487        domain: SocketDomain,
488        socket_type: SocketType,
489        protocol: SocketProtocol,
490    ) -> SocketHandle {
491        Arc::new(Socket {
492            ops,
493            domain,
494            socket_type,
495            protocol,
496            state: Mutex::default(),
497            security: security::SocketState::default(),
498        })
499    }
500
501    pub(super) fn set_fs_node(&self, node: &FsNodeHandle) {
502        let mut locked_state = self.state.lock();
503        assert!(locked_state.fs_node.is_none());
504        locked_state.fs_node = Some(node.clone());
505    }
506
507    /// Returns the Socket that this FileHandle refers to. If this file is not a socket file,
508    /// returns ENOTSOCK.
509    pub fn get_from_file(file: &FileHandle) -> Result<&SocketHandle, Errno> {
510        let socket_file = file.downcast_file::<SocketFile>().ok_or_else(|| errno!(ENOTSOCK))?;
511        Ok(&socket_file.socket)
512    }
513
514    pub fn downcast_socket<T>(&self) -> Option<&T>
515    where
516        T: 'static,
517    {
518        let ops = &*self.ops;
519        ops.as_any().downcast_ref::<T>()
520    }
521
522    pub fn getsockname<L>(&self, locked: &mut Locked<L>) -> Result<SocketAddress, Errno>
523    where
524        L: LockEqualOrBefore<FileOpsCore>,
525    {
526        self.ops.getsockname(locked.cast_locked::<FileOpsCore>(), self)
527    }
528
529    pub fn getpeername<L>(&self, locked: &mut Locked<L>) -> Result<SocketAddress, Errno>
530    where
531        L: LockEqualOrBefore<FileOpsCore>,
532    {
533        self.ops.getpeername(locked.cast_locked::<FileOpsCore>(), self)
534    }
535
536    pub fn setsockopt<L>(
537        &self,
538        locked: &mut Locked<L>,
539        current_task: &CurrentTask,
540        level: u32,
541        optname: u32,
542        optval: SockOptValue,
543    ) -> Result<(), Errno>
544    where
545        L: LockEqualOrBefore<FileOpsCore>,
546    {
547        let locked = locked.cast_locked::<FileOpsCore>();
548        let read_timeval = || {
549            let timeval = TimeValPtr::read_from_sockopt_value(current_task, &optval)?;
550            let duration = duration_from_timeval(timeval)?;
551            Ok(if duration == zx::MonotonicDuration::default() { None } else { Some(duration) })
552        };
553
554        security::check_socket_setsockopt_access(current_task, self, level, optname)?;
555        match (level, optname) {
556            (SOL_SOCKET, SO_RCVTIMEO) => self.state.lock().receive_timeout = read_timeval()?,
557            (SOL_SOCKET, SO_SNDTIMEO) => self.state.lock().send_timeout = read_timeval()?,
558            _ => self.ops.setsockopt(locked, self, current_task, level, optname, optval)?,
559        }
560        Ok(())
561    }
562
563    pub fn getsockopt<L>(
564        &self,
565        locked: &mut Locked<L>,
566        current_task: &CurrentTask,
567        level: u32,
568        optname: u32,
569        optlen: u32,
570    ) -> Result<Vec<u8>, Errno>
571    where
572        L: LockEqualOrBefore<FileOpsCore>,
573    {
574        let locked = locked.cast_locked::<FileOpsCore>();
575        security::check_socket_getsockopt_access(current_task, self, level, optname)?;
576        let value = match level {
577            SOL_SOCKET => match optname {
578                SO_TYPE => self.socket_type.as_raw().to_ne_bytes().to_vec(),
579                SO_DOMAIN => {
580                    let domain = self.domain.as_raw() as u32;
581                    domain.to_ne_bytes().to_vec()
582                }
583                SO_PROTOCOL => self.protocol.as_raw().to_ne_bytes().to_vec(),
584                SO_RCVTIMEO => {
585                    let duration = self.receive_timeout().unwrap_or_default();
586                    TimeValPtr::into_bytes(current_task, timeval_from_duration(duration))
587                        .map_err(|_| errno!(EINVAL))?
588                }
589                SO_SNDTIMEO => {
590                    let duration = self.send_timeout().unwrap_or_default();
591                    TimeValPtr::into_bytes(current_task, timeval_from_duration(duration))
592                        .map_err(|_| errno!(EINVAL))?
593                }
594                _ => self.ops.getsockopt(locked, self, current_task, level, optname, optlen)?,
595            },
596            _ => self.ops.getsockopt(locked, self, current_task, level, optname, optlen)?,
597        };
598        Ok(value)
599    }
600
601    pub fn receive_timeout(&self) -> Option<zx::MonotonicDuration> {
602        self.state.lock().receive_timeout
603    }
604
605    pub fn send_timeout(&self) -> Option<zx::MonotonicDuration> {
606        self.state.lock().send_timeout
607    }
608
609    pub fn ioctl(
610        &self,
611        locked: &mut Locked<Unlocked>,
612        file: &FileObject,
613        current_task: &CurrentTask,
614        request: u32,
615        arg: SyscallArg,
616    ) -> Result<SyscallResult, Errno> {
617        let res = super::netlink_ioctl::netlink_ioctl(locked, current_task, request, arg);
618        match &res {
619            Err(e) if e.code == ENOTTY => {}
620            _ => return res,
621        }
622        self.ops.ioctl(locked, self, file, current_task, request, arg)
623    }
624
625    pub fn bind<L>(
626        &self,
627        locked: &mut Locked<L>,
628        current_task: &CurrentTask,
629        socket_address: SocketAddress,
630    ) -> Result<(), Errno>
631    where
632        L: LockEqualOrBefore<FileOpsCore>,
633    {
634        self.ops.bind(locked.cast_locked::<FileOpsCore>(), self, current_task, socket_address)
635    }
636
637    pub fn listen<L>(
638        &self,
639        locked: &mut Locked<L>,
640        current_task: &CurrentTask,
641        backlog: i32,
642    ) -> Result<(), Errno>
643    where
644        L: LockEqualOrBefore<FileOpsCore>,
645    {
646        security::check_socket_listen_access(current_task, self, backlog)?;
647        let max_connections =
648            current_task.kernel().system_limits.socket.max_connections.load(Ordering::Relaxed);
649        let backlog = std::cmp::min(backlog, max_connections);
650        let credentials = current_task.current_ucred();
651        self.ops.listen(locked.cast_locked::<FileOpsCore>(), self, backlog, credentials)
652    }
653
654    pub fn accept<L>(
655        &self,
656        locked: &mut Locked<L>,
657        current_task: &CurrentTask,
658    ) -> Result<SocketHandle, Errno>
659    where
660        L: LockEqualOrBefore<FileOpsCore>,
661    {
662        self.ops.accept(locked.cast_locked::<FileOpsCore>(), self, current_task)
663    }
664
665    pub fn read<L>(
666        &self,
667        locked: &mut Locked<L>,
668        current_task: &CurrentTask,
669        data: &mut dyn OutputBuffer,
670        flags: SocketMessageFlags,
671    ) -> Result<MessageReadInfo, Errno>
672    where
673        L: LockEqualOrBefore<FileOpsCore>,
674    {
675        security::check_socket_recvmsg_access(current_task, self)?;
676        let locked = locked.cast_locked::<FileOpsCore>();
677        self.ops.read(locked, self, current_task, data, flags)
678    }
679
680    pub fn write<L>(
681        &self,
682        locked: &mut Locked<L>,
683        current_task: &CurrentTask,
684        data: &mut dyn InputBuffer,
685        dest_address: &mut Option<SocketAddress>,
686        ancillary_data: &mut Vec<AncillaryData>,
687    ) -> Result<usize, Errno>
688    where
689        L: LockEqualOrBefore<FileOpsCore>,
690    {
691        security::check_socket_sendmsg_access(current_task, self)?;
692        let locked = locked.cast_locked::<FileOpsCore>();
693        self.ops.write(locked, self, current_task, data, dest_address, ancillary_data)
694    }
695
696    pub fn wait_async<L>(
697        &self,
698        locked: &mut Locked<L>,
699        current_task: &CurrentTask,
700        waiter: &Waiter,
701        events: FdEvents,
702        handler: EventHandler,
703    ) -> WaitCanceler
704    where
705        L: LockEqualOrBefore<FileOpsCore>,
706    {
707        let locked = locked.cast_locked::<FileOpsCore>();
708        self.ops.wait_async(locked, self, current_task, waiter, events, handler)
709    }
710
711    pub fn query_events<L>(
712        &self,
713        locked: &mut Locked<L>,
714        current_task: &CurrentTask,
715    ) -> Result<FdEvents, Errno>
716    where
717        L: LockEqualOrBefore<FileOpsCore>,
718    {
719        self.ops.query_events(locked.cast_locked::<FileOpsCore>(), self, current_task)
720    }
721
722    pub fn shutdown<L>(
723        &self,
724        locked: &mut Locked<L>,
725        current_task: &CurrentTask,
726        how: SocketShutdownFlags,
727    ) -> Result<(), Errno>
728    where
729        L: LockEqualOrBefore<FileOpsCore>,
730    {
731        security::check_socket_shutdown_access(current_task, self, how)?;
732        self.ops.shutdown(locked.cast_locked::<FileOpsCore>(), self, how)
733    }
734
735    pub fn close<L>(&self, locked: &mut Locked<L>, current_task: &CurrentTask)
736    where
737        L: LockEqualOrBefore<FileOpsCore>,
738    {
739        self.ops.close(locked.cast_locked::<FileOpsCore>(), current_task, self)
740    }
741
742    pub fn to_handle(
743        &self,
744        _file: &FileObject,
745        current_task: &CurrentTask,
746    ) -> Result<Option<zx::NullableHandle>, Errno> {
747        self.ops.to_handle(self, current_task)
748    }
749
750    /// Returns the [`crate::vfs::FsNode`] unique to this `Socket`.
751    // TODO: https://fxbug.dev/414583985 - Create `FsNode` at `Socket` creation and make this
752    // infallible.
753    pub fn fs_node(&self) -> Option<FsNodeHandle> {
754        self.state.lock().fs_node.clone()
755    }
756}
757
758impl DowncastedFile<'_, SocketFile> {
759    pub fn connect<L>(
760        self,
761        locked: &mut Locked<L>,
762        current_task: &CurrentTask,
763        peer: SocketPeer,
764    ) -> Result<(), Errno>
765    where
766        L: LockEqualOrBefore<FileOpsCore>,
767    {
768        security::check_socket_connect_access(current_task, self, &peer)?;
769        self.socket.ops.connect(locked.cast_locked(), &self.socket, current_task, peer)
770    }
771}
772
773pub struct AcceptQueue {
774    pub sockets: VecDeque<SocketHandle>,
775    pub backlog: usize,
776}
777
778impl AcceptQueue {
779    pub fn new(backlog: usize) -> AcceptQueue {
780        AcceptQueue { sockets: VecDeque::with_capacity(backlog), backlog }
781    }
782
783    pub fn set_backlog(&mut self, backlog: usize) -> Result<(), Errno> {
784        if self.sockets.len() > backlog {
785            return error!(EINVAL);
786        }
787        self.backlog = backlog;
788        Ok(())
789    }
790}
791
792#[cfg(test)]
793mod tests {
794    use super::*;
795    use crate::testing::{map_memory, spawn_kernel_and_run};
796    use crate::vfs::{UnixControlData, VecInputBuffer, VecOutputBuffer};
797    use starnix_uapi::SO_PASSCRED;
798    use starnix_uapi::user_address::{UserAddress, UserRef};
799
800    #[fuchsia::test]
801    async fn test_dgram_socket() {
802        spawn_kernel_and_run(async |locked, current_task| {
803            let bind_address = SocketAddress::Unix(b"dgram_test".into());
804            let rec_dgram = Socket::new(
805                locked,
806                &current_task,
807                SocketDomain::Unix,
808                SocketType::Datagram,
809                SocketProtocol::default(),
810                /* kernel_private = */ false,
811            )
812            .expect("Failed to create socket.");
813            let passcred: u32 = 1;
814            let opt_size = std::mem::size_of::<u32>();
815            let user_address =
816                map_memory(locked, &current_task, UserAddress::default(), opt_size as u64);
817            let opt_ref = UserRef::<u32>::new(user_address);
818            current_task.write_object(opt_ref, &passcred).unwrap();
819            let opt_buf = UserBuffer { address: user_address, length: opt_size };
820            rec_dgram
821                .setsockopt(locked, &current_task, SOL_SOCKET, SO_PASSCRED, opt_buf.into())
822                .unwrap();
823
824            rec_dgram
825                .bind(locked, &current_task, bind_address)
826                .expect("failed to bind datagram socket");
827
828            let xfer_value: u64 = 1234567819;
829            let xfer_bytes = xfer_value.to_ne_bytes();
830
831            let send = Socket::new(
832                locked,
833                &current_task,
834                SocketDomain::Unix,
835                SocketType::Datagram,
836                SocketProtocol::default(),
837                /* kernel_private = */ false,
838            )
839            .expect("Failed to connect socket.");
840            send.ops
841                .connect(
842                    locked.cast_locked(),
843                    &send,
844                    &current_task,
845                    SocketPeer::Handle(rec_dgram.clone()),
846                )
847                .unwrap();
848            let mut source_iter = VecInputBuffer::new(&xfer_bytes);
849            send.write(locked, &current_task, &mut source_iter, &mut None, &mut vec![]).unwrap();
850            assert_eq!(source_iter.available(), 0);
851            // Previously, this would cause the test to fail,
852            // because rec_dgram was shut down.
853            send.close(locked, &current_task);
854
855            let mut rec_buffer = VecOutputBuffer::new(8);
856            let read_info = rec_dgram
857                .read(locked, &current_task, &mut rec_buffer, SocketMessageFlags::empty())
858                .unwrap();
859            assert_eq!(read_info.bytes_read, xfer_bytes.len());
860            assert_eq!(rec_buffer.data(), xfer_bytes);
861            assert_eq!(1, read_info.ancillary_data.len());
862            assert_eq!(
863                read_info.ancillary_data[0],
864                AncillaryData::Unix(UnixControlData::Credentials(uapi::ucred {
865                    pid: current_task.get_pid(),
866                    uid: 0,
867                    gid: 0
868                }))
869            );
870
871            rec_dgram.close(locked, &current_task);
872        })
873        .await;
874    }
875}