Skip to main content

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