Serenity Operating System
1/*
2 * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
3 *
4 * SPDX-License-Identifier: BSD-2-Clause
5 */
6
7#include <Kernel/FileSystem/OpenFileDescription.h>
8#include <Kernel/Net/LocalSocket.h>
9#include <Kernel/Process.h>
10
11namespace Kernel {
12
13ErrorOr<FlatPtr> Process::sys$sendfd(int sockfd, int fd)
14{
15 VERIFY_NO_PROCESS_BIG_LOCK(this);
16 TRY(require_promise(Pledge::sendfd));
17 auto socket_description = TRY(open_file_description(sockfd));
18 if (!socket_description->is_socket())
19 return ENOTSOCK;
20 auto& socket = *socket_description->socket();
21 if (!socket.is_local())
22 return EAFNOSUPPORT;
23 if (!socket.is_connected())
24 return ENOTCONN;
25
26 auto passing_description = TRY(open_file_description(fd));
27 auto& local_socket = static_cast<LocalSocket&>(socket);
28 TRY(local_socket.sendfd(*socket_description, move(passing_description)));
29 return 0;
30}
31
32ErrorOr<FlatPtr> Process::sys$recvfd(int sockfd, int options)
33{
34 VERIFY_NO_PROCESS_BIG_LOCK(this);
35 TRY(require_promise(Pledge::recvfd));
36 auto socket_description = TRY(open_file_description(sockfd));
37 if (!socket_description->is_socket())
38 return ENOTSOCK;
39 auto& socket = *socket_description->socket();
40 if (!socket.is_local())
41 return EAFNOSUPPORT;
42
43 auto fd_allocation = TRY(m_fds.with_exclusive([](auto& fds) { return fds.allocate(); }));
44
45 auto& local_socket = static_cast<LocalSocket&>(socket);
46 auto received_description = TRY(local_socket.recvfd(*socket_description));
47
48 u32 fd_flags = 0;
49 if (options & O_CLOEXEC)
50 fd_flags |= FD_CLOEXEC;
51
52 m_fds.with_exclusive([&](auto& fds) { fds[fd_allocation.fd].set(move(received_description), fd_flags); });
53 return fd_allocation.fd;
54}
55
56}