mirror of
https://github.com/RGBCube/serenity
synced 2025-05-31 13:28:11 +00:00
Kernel+LibC: Implement the socketpair() syscall
This commit is contained in:
parent
c841012f56
commit
aa792062cb
11 changed files with 100 additions and 91 deletions
|
@ -20,6 +20,18 @@ namespace Kernel {
|
|||
REQUIRE_PROMISE(unix); \
|
||||
} while (0)
|
||||
|
||||
void Process::setup_socket_fd(int fd, NonnullRefPtr<FileDescription> description, int type)
|
||||
{
|
||||
description->set_readable(true);
|
||||
description->set_writable(true);
|
||||
unsigned flags = 0;
|
||||
if (type & SOCK_CLOEXEC)
|
||||
flags |= FD_CLOEXEC;
|
||||
if (type & SOCK_NONBLOCK)
|
||||
description->set_blocking(false);
|
||||
m_fds[fd].set(*description, flags);
|
||||
}
|
||||
|
||||
KResultOr<int> Process::sys$socket(int domain, int type, int protocol)
|
||||
{
|
||||
REQUIRE_PROMISE_FOR_SOCKET_DOMAIN(domain);
|
||||
|
@ -35,14 +47,7 @@ KResultOr<int> Process::sys$socket(int domain, int type, int protocol)
|
|||
auto description_result = FileDescription::create(*result.value());
|
||||
if (description_result.is_error())
|
||||
return description_result.error();
|
||||
description_result.value()->set_readable(true);
|
||||
description_result.value()->set_writable(true);
|
||||
unsigned flags = 0;
|
||||
if (type & SOCK_CLOEXEC)
|
||||
flags |= FD_CLOEXEC;
|
||||
if (type & SOCK_NONBLOCK)
|
||||
description_result.value()->set_blocking(false);
|
||||
m_fds[fd].set(description_result.release_value(), flags);
|
||||
setup_socket_fd(fd, description_result.value(), type);
|
||||
return fd;
|
||||
}
|
||||
|
||||
|
@ -362,4 +367,41 @@ KResultOr<int> Process::sys$setsockopt(Userspace<const Syscall::SC_setsockopt_pa
|
|||
return socket.setsockopt(params.level, params.option, user_value, params.value_size);
|
||||
}
|
||||
|
||||
KResultOr<int> Process::sys$socketpair(Userspace<const Syscall::SC_socketpair_params*> user_params)
|
||||
{
|
||||
Syscall::SC_socketpair_params params;
|
||||
if (!copy_from_user(¶ms, user_params))
|
||||
return EFAULT;
|
||||
|
||||
if (params.domain != AF_LOCAL)
|
||||
return EINVAL;
|
||||
|
||||
if (params.protocol != 0 && params.protocol != PF_LOCAL)
|
||||
return EINVAL;
|
||||
|
||||
auto result = LocalSocket::create_connected_pair(params.type & SOCK_TYPE_MASK);
|
||||
if (result.is_error())
|
||||
return result.error();
|
||||
auto pair = result.value();
|
||||
|
||||
int fds[2];
|
||||
fds[0] = alloc_fd();
|
||||
if (fds[0] < 0)
|
||||
return ENFILE;
|
||||
setup_socket_fd(fds[0], pair.description1, params.type);
|
||||
|
||||
fds[1] = alloc_fd();
|
||||
if (fds[1] < 0) {
|
||||
// FIXME: This leaks fds[0]
|
||||
return ENFILE;
|
||||
}
|
||||
setup_socket_fd(fds[1], pair.description2, params.type);
|
||||
|
||||
if (!copy_to_user(params.sv, fds, sizeof(fds))) {
|
||||
// FIXME: This leaks both file descriptors
|
||||
return EFAULT;
|
||||
}
|
||||
|
||||
return KSuccess;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue