mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 22:57:44 +00:00
Kernel+LibC: Turn errno codes into a strongly typed enum
..and allow implicit creation of KResult and KResultOr from ErrnoCode. This means that kernel functions that return those types can finally do "return EINVAL;" and it will just work. There's a handful of functions that still deal with signed integers that should be converted to return KResults.
This commit is contained in:
parent
e279b45aed
commit
19d3f8cab7
48 changed files with 591 additions and 506 deletions
|
@ -61,7 +61,7 @@ KResultOr<NonnullRefPtr<Socket>> IPv4Socket::create(int type, int protocol)
|
|||
return UDPSocket::create(protocol);
|
||||
if (type == SOCK_RAW)
|
||||
return adopt(*new IPv4Socket(type, protocol));
|
||||
return KResult(-EINVAL);
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
IPv4Socket::IPv4Socket(int type, int protocol)
|
||||
|
@ -102,20 +102,20 @@ KResult IPv4Socket::bind(Userspace<const sockaddr*> user_address, socklen_t addr
|
|||
{
|
||||
ASSERT(setup_state() == SetupState::Unstarted);
|
||||
if (address_size != sizeof(sockaddr_in))
|
||||
return KResult(-EINVAL);
|
||||
return EINVAL;
|
||||
|
||||
sockaddr_in address;
|
||||
if (!copy_from_user(&address, user_address, sizeof(sockaddr_in)))
|
||||
return KResult(-EFAULT);
|
||||
return EFAULT;
|
||||
|
||||
if (address.sin_family != AF_INET)
|
||||
return KResult(-EINVAL);
|
||||
return EINVAL;
|
||||
|
||||
auto requested_local_port = ntohs(address.sin_port);
|
||||
if (!Process::current()->is_superuser()) {
|
||||
if (requested_local_port < 1024) {
|
||||
dbgln("UID {} attempted to bind {} to port {}", Process::current()->uid(), class_name(), requested_local_port);
|
||||
return KResult(-EACCES);
|
||||
return EACCES;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -134,7 +134,7 @@ KResult IPv4Socket::listen(size_t backlog)
|
|||
LOCKER(lock());
|
||||
int rc = allocate_local_port_if_needed();
|
||||
if (rc < 0)
|
||||
return KResult(-EADDRINUSE);
|
||||
return EADDRINUSE;
|
||||
|
||||
set_backlog(backlog);
|
||||
m_role = Role::Listener;
|
||||
|
@ -150,19 +150,19 @@ KResult IPv4Socket::listen(size_t backlog)
|
|||
KResult IPv4Socket::connect(FileDescription& description, Userspace<const sockaddr*> address, socklen_t address_size, ShouldBlock should_block)
|
||||
{
|
||||
if (address_size != sizeof(sockaddr_in))
|
||||
return KResult(-EINVAL);
|
||||
return EINVAL;
|
||||
u16 sa_family_copy;
|
||||
auto* user_address = reinterpret_cast<const sockaddr*>(address.unsafe_userspace_ptr());
|
||||
if (!copy_from_user(&sa_family_copy, &user_address->sa_family, sizeof(u16)))
|
||||
return KResult(-EFAULT);
|
||||
return EFAULT;
|
||||
if (sa_family_copy != AF_INET)
|
||||
return KResult(-EINVAL);
|
||||
return EINVAL;
|
||||
if (m_role == Role::Connected)
|
||||
return KResult(-EISCONN);
|
||||
return EISCONN;
|
||||
|
||||
sockaddr_in safe_address;
|
||||
if (!copy_from_user(&safe_address, (const sockaddr_in*)user_address, sizeof(sockaddr_in)))
|
||||
return KResult(-EFAULT);
|
||||
return EFAULT;
|
||||
|
||||
m_peer_address = IPv4Address((const u8*)&safe_address.sin_addr.s_addr);
|
||||
m_peer_port = ntohs(safe_address.sin_port);
|
||||
|
@ -200,16 +200,16 @@ KResultOr<size_t> IPv4Socket::sendto(FileDescription&, const UserOrKernelBuffer&
|
|||
LOCKER(lock());
|
||||
|
||||
if (addr && addr_length != sizeof(sockaddr_in))
|
||||
return KResult(-EINVAL);
|
||||
return EINVAL;
|
||||
|
||||
if (addr) {
|
||||
sockaddr_in ia;
|
||||
if (!copy_from_user(&ia, Userspace<const sockaddr_in*>(addr.ptr())))
|
||||
return KResult(-EFAULT);
|
||||
return EFAULT;
|
||||
|
||||
if (ia.sin_family != AF_INET) {
|
||||
klog() << "sendto: Bad address family: " << ia.sin_family << " is not AF_INET!";
|
||||
return KResult(-EAFNOSUPPORT);
|
||||
return EAFNOSUPPORT;
|
||||
}
|
||||
|
||||
m_peer_address = IPv4Address((const u8*)&ia.sin_addr.s_addr);
|
||||
|
@ -218,7 +218,7 @@ KResultOr<size_t> IPv4Socket::sendto(FileDescription&, const UserOrKernelBuffer&
|
|||
|
||||
auto routing_decision = route_to(m_peer_address, m_local_address, bound_interface());
|
||||
if (routing_decision.is_zero())
|
||||
return KResult(-EHOSTUNREACH);
|
||||
return EHOSTUNREACH;
|
||||
|
||||
if (m_local_address.to_u32() == 0)
|
||||
m_local_address = routing_decision.adapter->ipv4_address();
|
||||
|
@ -234,7 +234,7 @@ KResultOr<size_t> IPv4Socket::sendto(FileDescription&, const UserOrKernelBuffer&
|
|||
if (type() == SOCK_RAW) {
|
||||
int err = routing_decision.adapter->send_ipv4(routing_decision.next_hop, m_peer_address, (IPv4Protocol)protocol(), data, data_length, m_ttl);
|
||||
if (err < 0)
|
||||
return KResult(err);
|
||||
return KResult((ErrnoCode)-err);
|
||||
return data_length;
|
||||
}
|
||||
|
||||
|
@ -251,7 +251,7 @@ KResultOr<size_t> IPv4Socket::receive_byte_buffered(FileDescription& description
|
|||
if (protocol_is_disconnected())
|
||||
return 0;
|
||||
if (!description.is_blocking())
|
||||
return KResult(-EAGAIN);
|
||||
return EAGAIN;
|
||||
|
||||
locker.unlock();
|
||||
auto unblocked_flags = Thread::FileDescriptionBlocker::BlockFlags::None;
|
||||
|
@ -260,10 +260,10 @@ KResultOr<size_t> IPv4Socket::receive_byte_buffered(FileDescription& description
|
|||
|
||||
if (!((u32)unblocked_flags & (u32)Thread::FileDescriptionBlocker::BlockFlags::Read)) {
|
||||
if (res.was_interrupted())
|
||||
return KResult(-EINTR);
|
||||
return EINTR;
|
||||
|
||||
// Unblocked due to timeout.
|
||||
return KResult(-EAGAIN);
|
||||
return EAGAIN;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -287,7 +287,7 @@ KResultOr<size_t> IPv4Socket::receive_packet_buffered(FileDescription& descripti
|
|||
if (protocol_is_disconnected())
|
||||
return 0;
|
||||
if (!description.is_blocking())
|
||||
return KResult(-EAGAIN);
|
||||
return EAGAIN;
|
||||
}
|
||||
|
||||
if (!m_receive_queue.is_empty()) {
|
||||
|
@ -311,10 +311,10 @@ KResultOr<size_t> IPv4Socket::receive_packet_buffered(FileDescription& descripti
|
|||
|
||||
if (!((u32)unblocked_flags & (u32)Thread::FileDescriptionBlocker::BlockFlags::Read)) {
|
||||
if (res.was_interrupted())
|
||||
return KResult(-EINTR);
|
||||
return EINTR;
|
||||
|
||||
// Unblocked due to timeout.
|
||||
return KResult(-EAGAIN);
|
||||
return EAGAIN;
|
||||
}
|
||||
ASSERT(m_can_read);
|
||||
ASSERT(!m_receive_queue.is_empty());
|
||||
|
@ -339,18 +339,18 @@ KResultOr<size_t> IPv4Socket::receive_packet_buffered(FileDescription& descripti
|
|||
out_addr.sin_family = AF_INET;
|
||||
Userspace<sockaddr_in*> dest_addr = addr.ptr();
|
||||
if (!copy_to_user(dest_addr, &out_addr))
|
||||
return KResult(-EFAULT);
|
||||
return EFAULT;
|
||||
|
||||
socklen_t out_length = sizeof(sockaddr_in);
|
||||
ASSERT(addr_length);
|
||||
if (!copy_to_user(addr_length, &out_length))
|
||||
return KResult(-EFAULT);
|
||||
return EFAULT;
|
||||
}
|
||||
|
||||
if (type() == SOCK_RAW) {
|
||||
size_t bytes_written = min(packet.data.value().size(), buffer_length);
|
||||
if (!buffer.write(packet.data.value().data(), bytes_written))
|
||||
return KResult(-EFAULT);
|
||||
return EFAULT;
|
||||
return bytes_written;
|
||||
}
|
||||
|
||||
|
@ -362,9 +362,9 @@ KResultOr<size_t> IPv4Socket::recvfrom(FileDescription& description, UserOrKerne
|
|||
if (user_addr_length) {
|
||||
socklen_t addr_length;
|
||||
if (!copy_from_user(&addr_length, user_addr_length.unsafe_userspace_ptr()))
|
||||
return KResult(-EFAULT);
|
||||
return EFAULT;
|
||||
if (addr_length < sizeof(sockaddr_in))
|
||||
return KResult(-EINVAL);
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
#ifdef IPV4_SOCKET_DEBUG
|
||||
|
@ -464,17 +464,17 @@ KResult IPv4Socket::setsockopt(int level, int option, Userspace<const void*> use
|
|||
switch (option) {
|
||||
case IP_TTL: {
|
||||
if (user_value_size < sizeof(int))
|
||||
return KResult(-EINVAL);
|
||||
return EINVAL;
|
||||
int value;
|
||||
if (!copy_from_user(&value, static_ptr_cast<const int*>(user_value)))
|
||||
return KResult(-EFAULT);
|
||||
return EFAULT;
|
||||
if (value < 0 || value > 255)
|
||||
return KResult(-EINVAL);
|
||||
return EINVAL;
|
||||
m_ttl = value;
|
||||
return KSuccess;
|
||||
}
|
||||
default:
|
||||
return KResult(-ENOPROTOOPT);
|
||||
return ENOPROTOOPT;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -485,20 +485,20 @@ KResult IPv4Socket::getsockopt(FileDescription& description, int level, int opti
|
|||
|
||||
socklen_t size;
|
||||
if (!copy_from_user(&size, value_size.unsafe_userspace_ptr()))
|
||||
return KResult(-EFAULT);
|
||||
return EFAULT;
|
||||
|
||||
switch (option) {
|
||||
case IP_TTL:
|
||||
if (size < sizeof(int))
|
||||
return KResult(-EINVAL);
|
||||
return EINVAL;
|
||||
if (!copy_to_user(static_ptr_cast<int*>(value), (int*)&m_ttl))
|
||||
return KResult(-EFAULT);
|
||||
return EFAULT;
|
||||
size = sizeof(int);
|
||||
if (!copy_to_user(value_size, &size))
|
||||
return KResult(-EFAULT);
|
||||
return EFAULT;
|
||||
return KSuccess;
|
||||
default:
|
||||
return KResult(-ENOPROTOOPT);
|
||||
return ENOPROTOOPT;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -102,14 +102,14 @@ KResult LocalSocket::bind(Userspace<const sockaddr*> user_address, socklen_t add
|
|||
{
|
||||
ASSERT(setup_state() == SetupState::Unstarted);
|
||||
if (address_size != sizeof(sockaddr_un))
|
||||
return KResult(-EINVAL);
|
||||
return EINVAL;
|
||||
|
||||
sockaddr_un address;
|
||||
if (!copy_from_user(&address, user_address, sizeof(sockaddr_un)))
|
||||
return KResult(-EFAULT);
|
||||
return EFAULT;
|
||||
|
||||
if (address.sun_family != AF_LOCAL)
|
||||
return KResult(-EINVAL);
|
||||
return EINVAL;
|
||||
|
||||
auto path = String(address.sun_path, strnlen(address.sun_path, sizeof(address.sun_path)));
|
||||
|
||||
|
@ -122,7 +122,7 @@ KResult LocalSocket::bind(Userspace<const sockaddr*> user_address, socklen_t add
|
|||
auto result = VFS::the().open(path, O_CREAT | O_EXCL | O_NOFOLLOW_NOERROR, mode, Process::current()->current_directory(), owner);
|
||||
if (result.is_error()) {
|
||||
if (result.error() == -EEXIST)
|
||||
return KResult(-EADDRINUSE);
|
||||
return EADDRINUSE;
|
||||
return result.error();
|
||||
}
|
||||
|
||||
|
@ -130,7 +130,7 @@ KResult LocalSocket::bind(Userspace<const sockaddr*> user_address, socklen_t add
|
|||
|
||||
ASSERT(file->inode());
|
||||
if (!file->inode()->bind_socket(*this))
|
||||
return KResult(-EADDRINUSE);
|
||||
return EADDRINUSE;
|
||||
|
||||
m_file = move(file);
|
||||
|
||||
|
@ -143,20 +143,20 @@ KResult LocalSocket::connect(FileDescription& description, Userspace<const socka
|
|||
{
|
||||
ASSERT(!m_bound);
|
||||
if (address_size != sizeof(sockaddr_un))
|
||||
return KResult(-EINVAL);
|
||||
return EINVAL;
|
||||
u16 sa_family_copy;
|
||||
auto* user_address = reinterpret_cast<const sockaddr*>(address.unsafe_userspace_ptr());
|
||||
if (!copy_from_user(&sa_family_copy, &user_address->sa_family, sizeof(u16)))
|
||||
return KResult(-EFAULT);
|
||||
return EFAULT;
|
||||
if (sa_family_copy != AF_LOCAL)
|
||||
return KResult(-EINVAL);
|
||||
return EINVAL;
|
||||
if (is_connected())
|
||||
return KResult(-EISCONN);
|
||||
return EISCONN;
|
||||
|
||||
const auto& local_address = *reinterpret_cast<const sockaddr_un*>(user_address);
|
||||
char safe_address[sizeof(local_address.sun_path) + 1] = { 0 };
|
||||
if (!copy_from_user(&safe_address[0], &local_address.sun_path[0], sizeof(safe_address) - 1))
|
||||
return KResult(-EFAULT);
|
||||
return EFAULT;
|
||||
safe_address[sizeof(safe_address) - 1] = '\0';
|
||||
|
||||
#ifdef DEBUG_LOCAL_SOCKET
|
||||
|
@ -165,13 +165,13 @@ KResult LocalSocket::connect(FileDescription& description, Userspace<const socka
|
|||
|
||||
auto description_or_error = VFS::the().open(safe_address, O_RDWR, 0, Process::current()->current_directory());
|
||||
if (description_or_error.is_error())
|
||||
return KResult(-ECONNREFUSED);
|
||||
return ECONNREFUSED;
|
||||
|
||||
m_file = move(description_or_error.value());
|
||||
|
||||
ASSERT(m_file->inode());
|
||||
if (!m_file->inode()->socket())
|
||||
return KResult(-ECONNREFUSED);
|
||||
return ECONNREFUSED;
|
||||
|
||||
m_address.sun_family = sa_family_copy;
|
||||
memcpy(m_address.sun_path, safe_address, sizeof(m_address.sun_path));
|
||||
|
@ -194,7 +194,7 @@ KResult LocalSocket::connect(FileDescription& description, Userspace<const socka
|
|||
auto unblock_flags = Thread::FileDescriptionBlocker::BlockFlags::None;
|
||||
if (Thread::current()->block<Thread::ConnectBlocker>({}, description, unblock_flags).was_interrupted()) {
|
||||
set_connect_side_role(Role::None);
|
||||
return KResult(-EINTR);
|
||||
return EINTR;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_LOCAL_SOCKET
|
||||
|
@ -203,7 +203,7 @@ KResult LocalSocket::connect(FileDescription& description, Userspace<const socka
|
|||
|
||||
if (!((u32)unblock_flags & (u32)Thread::FileDescriptionBlocker::BlockFlags::Connect)) {
|
||||
set_connect_side_role(Role::None);
|
||||
return KResult(-ECONNREFUSED);
|
||||
return ECONNREFUSED;
|
||||
}
|
||||
set_connect_side_role(Role::Connected);
|
||||
return KSuccess;
|
||||
|
@ -213,7 +213,7 @@ KResult LocalSocket::listen(size_t backlog)
|
|||
{
|
||||
LOCKER(lock());
|
||||
if (type() != SOCK_STREAM)
|
||||
return KResult(-EOPNOTSUPP);
|
||||
return EOPNOTSUPP;
|
||||
set_backlog(backlog);
|
||||
auto previous_role = m_role;
|
||||
m_role = Role::Listener;
|
||||
|
@ -286,10 +286,10 @@ bool LocalSocket::can_write(const FileDescription& description, size_t) const
|
|||
KResultOr<size_t> LocalSocket::sendto(FileDescription& description, const UserOrKernelBuffer& data, size_t data_size, int, Userspace<const sockaddr*>, socklen_t)
|
||||
{
|
||||
if (!has_attached_peer(description))
|
||||
return KResult(-EPIPE);
|
||||
return EPIPE;
|
||||
auto* socket_buffer = send_buffer_for(description);
|
||||
if (!socket_buffer)
|
||||
return KResult(-EINVAL);
|
||||
return EINVAL;
|
||||
ssize_t nwritten = socket_buffer->write(data, data_size);
|
||||
if (nwritten > 0)
|
||||
Thread::current()->did_unix_socket_write(nwritten);
|
||||
|
@ -320,17 +320,17 @@ KResultOr<size_t> LocalSocket::recvfrom(FileDescription& description, UserOrKern
|
|||
{
|
||||
auto* socket_buffer = receive_buffer_for(description);
|
||||
if (!socket_buffer)
|
||||
return KResult(-EINVAL);
|
||||
return EINVAL;
|
||||
if (!description.is_blocking()) {
|
||||
if (socket_buffer->is_empty()) {
|
||||
if (!has_attached_peer(description))
|
||||
return 0;
|
||||
return KResult(-EAGAIN);
|
||||
return EAGAIN;
|
||||
}
|
||||
} else if (!can_read(description, 0)) {
|
||||
auto unblock_flags = Thread::FileDescriptionBlocker::BlockFlags::None;
|
||||
if (Thread::current()->block<Thread::ReadBlocker>({}, description, unblock_flags).was_interrupted())
|
||||
return KResult(-EINTR);
|
||||
return EINTR;
|
||||
}
|
||||
if (!has_attached_peer(description) && socket_buffer->is_empty())
|
||||
return 0;
|
||||
|
@ -380,31 +380,31 @@ KResult LocalSocket::getsockopt(FileDescription& description, int level, int opt
|
|||
|
||||
socklen_t size;
|
||||
if (!copy_from_user(&size, value_size.unsafe_userspace_ptr()))
|
||||
return KResult(-EFAULT);
|
||||
return EFAULT;
|
||||
|
||||
switch (option) {
|
||||
case SO_PEERCRED: {
|
||||
if (size < sizeof(ucred))
|
||||
return KResult(-EINVAL);
|
||||
return EINVAL;
|
||||
switch (role(description)) {
|
||||
case Role::Accepted:
|
||||
if (!copy_to_user(static_ptr_cast<ucred*>(value), &m_origin))
|
||||
return KResult(-EFAULT);
|
||||
return EFAULT;
|
||||
size = sizeof(ucred);
|
||||
if (!copy_to_user(value_size, &size))
|
||||
return KResult(-EFAULT);
|
||||
return EFAULT;
|
||||
return KSuccess;
|
||||
case Role::Connected:
|
||||
if (!copy_to_user(static_ptr_cast<ucred*>(value), &m_acceptor))
|
||||
return KResult(-EFAULT);
|
||||
return EFAULT;
|
||||
size = sizeof(ucred);
|
||||
if (!copy_to_user(value_size, &size))
|
||||
return KResult(-EFAULT);
|
||||
return EFAULT;
|
||||
return KSuccess;
|
||||
case Role::Connecting:
|
||||
return KResult(-ENOTCONN);
|
||||
return ENOTCONN;
|
||||
default:
|
||||
return KResult(-EINVAL);
|
||||
return EINVAL;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -429,7 +429,7 @@ KResult LocalSocket::chown(FileDescription&, uid_t uid, gid_t gid)
|
|||
|
||||
auto current_process = Process::current();
|
||||
if (!current_process->is_superuser() && (current_process->euid() != uid || !current_process->in_group(gid)))
|
||||
return KResult(-EPERM);
|
||||
return EPERM;
|
||||
|
||||
m_prebind_uid = uid;
|
||||
m_prebind_gid = gid;
|
||||
|
@ -461,11 +461,11 @@ KResult LocalSocket::sendfd(const FileDescription& socket_description, FileDescr
|
|||
LOCKER(lock());
|
||||
auto role = this->role(socket_description);
|
||||
if (role != Role::Connected && role != Role::Accepted)
|
||||
return KResult(-EINVAL);
|
||||
return EINVAL;
|
||||
auto& queue = sendfd_queue_for(socket_description);
|
||||
// FIXME: Figure out how we should limit this properly.
|
||||
if (queue.size() > 16)
|
||||
return KResult(-EBUSY);
|
||||
return EBUSY;
|
||||
queue.append(move(passing_description));
|
||||
return KSuccess;
|
||||
}
|
||||
|
@ -475,11 +475,11 @@ KResultOr<NonnullRefPtr<FileDescription>> LocalSocket::recvfd(const FileDescript
|
|||
LOCKER(lock());
|
||||
auto role = this->role(socket_description);
|
||||
if (role != Role::Connected && role != Role::Accepted)
|
||||
return KResult(-EINVAL);
|
||||
return EINVAL;
|
||||
auto& queue = recvfd_queue_for(socket_description);
|
||||
if (queue.is_empty()) {
|
||||
// FIXME: Figure out the perfect error code for this.
|
||||
return KResult(-EAGAIN);
|
||||
return EAGAIN;
|
||||
}
|
||||
return queue.take_first();
|
||||
}
|
||||
|
|
|
@ -46,7 +46,7 @@ KResultOr<NonnullRefPtr<Socket>> Socket::create(int domain, int type, int protoc
|
|||
case AF_INET:
|
||||
return IPv4Socket::create(type & SOCK_TYPE_MASK, protocol);
|
||||
default:
|
||||
return KResult(-EAFNOSUPPORT);
|
||||
return EAFNOSUPPORT;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -99,7 +99,7 @@ KResult Socket::queue_connection_from(NonnullRefPtr<Socket> peer)
|
|||
#endif
|
||||
LOCKER(m_lock);
|
||||
if (m_pending.size() >= m_backlog)
|
||||
return KResult(-ECONNREFUSED);
|
||||
return ECONNREFUSED;
|
||||
m_pending.append(peer);
|
||||
evaluate_block_conditions();
|
||||
return KSuccess;
|
||||
|
@ -111,26 +111,26 @@ KResult Socket::setsockopt(int level, int option, Userspace<const void*> user_va
|
|||
switch (option) {
|
||||
case SO_SNDTIMEO:
|
||||
if (user_value_size != sizeof(timeval))
|
||||
return KResult(-EINVAL);
|
||||
return EINVAL;
|
||||
if (!copy_from_user(&m_send_timeout, static_ptr_cast<const timeval*>(user_value)))
|
||||
return KResult(-EFAULT);
|
||||
return EFAULT;
|
||||
return KSuccess;
|
||||
case SO_RCVTIMEO:
|
||||
if (user_value_size != sizeof(timeval))
|
||||
return KResult(-EINVAL);
|
||||
return EINVAL;
|
||||
if (!copy_from_user(&m_receive_timeout, static_ptr_cast<const timeval*>(user_value)))
|
||||
return KResult(-EFAULT);
|
||||
return EFAULT;
|
||||
return KSuccess;
|
||||
case SO_BINDTODEVICE: {
|
||||
if (user_value_size != IFNAMSIZ)
|
||||
return KResult(-EINVAL);
|
||||
return EINVAL;
|
||||
auto user_string = static_ptr_cast<const char*>(user_value);
|
||||
auto ifname = copy_string_from_user(user_string, user_value_size);
|
||||
if (ifname.is_null())
|
||||
return KResult(-EFAULT);
|
||||
return EFAULT;
|
||||
auto device = NetworkAdapter::lookup_by_name(ifname);
|
||||
if (!device)
|
||||
return KResult(-ENODEV);
|
||||
return ENODEV;
|
||||
m_bound_interface = device;
|
||||
return KSuccess;
|
||||
}
|
||||
|
@ -139,18 +139,18 @@ KResult Socket::setsockopt(int level, int option, Userspace<const void*> user_va
|
|||
return KSuccess;
|
||||
case SO_TIMESTAMP:
|
||||
if (user_value_size != sizeof(int))
|
||||
return KResult(-EINVAL);
|
||||
return EINVAL;
|
||||
if (!copy_from_user(&m_timestamp, static_ptr_cast<const int*>(user_value)))
|
||||
return KResult(-EFAULT);
|
||||
return EFAULT;
|
||||
if (m_timestamp && (domain() != AF_INET || type() == SOCK_STREAM)) {
|
||||
// FIXME: Support SO_TIMESTAMP for more protocols?
|
||||
m_timestamp = 0;
|
||||
return KResult(-ENOTSUP);
|
||||
return ENOTSUP;
|
||||
}
|
||||
return KSuccess;
|
||||
default:
|
||||
dbgln("setsockopt({}) at SOL_SOCKET not implemented.", option);
|
||||
return KResult(-ENOPROTOOPT);
|
||||
return ENOPROTOOPT;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -158,76 +158,76 @@ KResult Socket::getsockopt(FileDescription&, int level, int option, Userspace<vo
|
|||
{
|
||||
socklen_t size;
|
||||
if (!copy_from_user(&size, value_size.unsafe_userspace_ptr()))
|
||||
return KResult(-EFAULT);
|
||||
return EFAULT;
|
||||
|
||||
// FIXME: Add TCP_NODELAY, IPPROTO_TCP and IPPROTO_IP (used in OpenSSH)
|
||||
if (level != SOL_SOCKET) {
|
||||
// Not sure if this is the correct error code, but it's only temporary until other levels are implemented.
|
||||
return KResult(-ENOPROTOOPT);
|
||||
return ENOPROTOOPT;
|
||||
}
|
||||
|
||||
switch (option) {
|
||||
case SO_SNDTIMEO:
|
||||
if (size < sizeof(timeval))
|
||||
return KResult(-EINVAL);
|
||||
return EINVAL;
|
||||
if (!copy_to_user(static_ptr_cast<timeval*>(value), &m_send_timeout))
|
||||
return KResult(-EFAULT);
|
||||
return EFAULT;
|
||||
size = sizeof(timeval);
|
||||
if (!copy_to_user(value_size, &size))
|
||||
return KResult(-EFAULT);
|
||||
return EFAULT;
|
||||
return KSuccess;
|
||||
case SO_RCVTIMEO:
|
||||
if (size < sizeof(timeval))
|
||||
return KResult(-EINVAL);
|
||||
return EINVAL;
|
||||
if (!copy_to_user(static_ptr_cast<timeval*>(value), &m_receive_timeout))
|
||||
return KResult(-EFAULT);
|
||||
return EFAULT;
|
||||
size = sizeof(timeval);
|
||||
if (!copy_to_user(value_size, &size))
|
||||
return KResult(-EFAULT);
|
||||
return EFAULT;
|
||||
return KSuccess;
|
||||
case SO_ERROR: {
|
||||
if (size < sizeof(int))
|
||||
return KResult(-EINVAL);
|
||||
return EINVAL;
|
||||
dbgln("getsockopt(SO_ERROR): FIXME!");
|
||||
int errno = 0;
|
||||
if (!copy_to_user(static_ptr_cast<int*>(value), &errno))
|
||||
return KResult(-EFAULT);
|
||||
return EFAULT;
|
||||
size = sizeof(int);
|
||||
if (!copy_to_user(value_size, &size))
|
||||
return KResult(-EFAULT);
|
||||
return EFAULT;
|
||||
return KSuccess;
|
||||
}
|
||||
case SO_BINDTODEVICE:
|
||||
if (size < IFNAMSIZ)
|
||||
return KResult(-EINVAL);
|
||||
return EINVAL;
|
||||
if (m_bound_interface) {
|
||||
const auto& name = m_bound_interface->name();
|
||||
auto length = name.length() + 1;
|
||||
if (!copy_to_user(static_ptr_cast<char*>(value), name.characters(), length))
|
||||
return KResult(-EFAULT);
|
||||
return EFAULT;
|
||||
size = length;
|
||||
if (!copy_to_user(value_size, &size))
|
||||
return KResult(-EFAULT);
|
||||
return EFAULT;
|
||||
return KSuccess;
|
||||
} else {
|
||||
size = 0;
|
||||
if (!copy_to_user(value_size, &size))
|
||||
return KResult(-EFAULT);
|
||||
return EFAULT;
|
||||
|
||||
return KResult(-EFAULT);
|
||||
return EFAULT;
|
||||
}
|
||||
case SO_TIMESTAMP:
|
||||
if (size < sizeof(int))
|
||||
return KResult(-EINVAL);
|
||||
return EINVAL;
|
||||
if (!copy_to_user(static_ptr_cast<int*>(value), &m_timestamp))
|
||||
return KResult(-EFAULT);
|
||||
return EFAULT;
|
||||
size = sizeof(int);
|
||||
if (!copy_to_user(value_size, &size))
|
||||
return KResult(-EFAULT);
|
||||
return EFAULT;
|
||||
return KSuccess;
|
||||
default:
|
||||
dbgln("setsockopt({}) at SOL_SOCKET not implemented.", option);
|
||||
return KResult(-ENOPROTOOPT);
|
||||
return ENOPROTOOPT;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -250,9 +250,9 @@ KResult Socket::shutdown(int how)
|
|||
{
|
||||
LOCKER(lock());
|
||||
if (type() == SOCK_STREAM && !is_connected())
|
||||
return KResult(-ENOTCONN);
|
||||
return ENOTCONN;
|
||||
if (m_role == Role::Listener)
|
||||
return KResult(-ENOTCONN);
|
||||
return ENOTCONN;
|
||||
if (!m_shut_down_for_writing && (how & SHUT_WR))
|
||||
shut_down_for_writing();
|
||||
if (!m_shut_down_for_reading && (how & SHUT_RD))
|
||||
|
|
|
@ -177,7 +177,7 @@ KResultOr<size_t> TCPSocket::protocol_receive(ReadonlyBytes raw_ipv4_packet, Use
|
|||
#endif
|
||||
ASSERT(buffer_size >= payload_size);
|
||||
if (!buffer.write(tcp_packet.payload(), payload_size))
|
||||
return KResult(-EFAULT);
|
||||
return EFAULT;
|
||||
return payload_size;
|
||||
}
|
||||
|
||||
|
@ -185,7 +185,7 @@ KResultOr<size_t> TCPSocket::protocol_send(const UserOrKernelBuffer& data, size_
|
|||
{
|
||||
int err = send_tcp_packet(TCPFlags::PUSH | TCPFlags::ACK, &data, data_length);
|
||||
if (err < 0)
|
||||
return KResult(err);
|
||||
return KResult((ErrnoCode)-err);
|
||||
return data_length;
|
||||
}
|
||||
|
||||
|
@ -354,7 +354,7 @@ KResult TCPSocket::protocol_bind()
|
|||
if (has_specific_local_address() && !m_adapter) {
|
||||
m_adapter = NetworkAdapter::from_ipv4_address(local_address());
|
||||
if (!m_adapter)
|
||||
return KResult(-EADDRNOTAVAIL);
|
||||
return EADDRNOTAVAIL;
|
||||
}
|
||||
|
||||
return KSuccess;
|
||||
|
@ -364,7 +364,7 @@ KResult TCPSocket::protocol_listen()
|
|||
{
|
||||
LOCKER(sockets_by_tuple().lock());
|
||||
if (sockets_by_tuple().resource().contains(tuple()))
|
||||
return KResult(-EADDRINUSE);
|
||||
return EADDRINUSE;
|
||||
sockets_by_tuple().resource().set(tuple(), this);
|
||||
set_direction(Direction::Passive);
|
||||
set_state(State::Listen);
|
||||
|
@ -378,7 +378,7 @@ KResult TCPSocket::protocol_connect(FileDescription& description, ShouldBlock sh
|
|||
|
||||
auto routing_decision = route_to(peer_address(), local_address());
|
||||
if (routing_decision.is_zero())
|
||||
return KResult(-EHOSTUNREACH);
|
||||
return EHOSTUNREACH;
|
||||
if (!has_specific_local_address())
|
||||
set_local_address(routing_decision.adapter->ipv4_address());
|
||||
|
||||
|
@ -390,7 +390,7 @@ KResult TCPSocket::protocol_connect(FileDescription& description, ShouldBlock sh
|
|||
set_setup_state(SetupState::InProgress);
|
||||
int err = send_tcp_packet(TCPFlags::SYN);
|
||||
if (err < 0)
|
||||
return KResult(err);
|
||||
return KResult((ErrnoCode)-err);
|
||||
m_state = State::SynSent;
|
||||
m_role = Role::Connecting;
|
||||
m_direction = Direction::Outgoing;
|
||||
|
@ -401,17 +401,17 @@ KResult TCPSocket::protocol_connect(FileDescription& description, ShouldBlock sh
|
|||
locker.unlock();
|
||||
auto unblock_flags = Thread::FileBlocker::BlockFlags::None;
|
||||
if (Thread::current()->block<Thread::ConnectBlocker>({}, description, unblock_flags).was_interrupted())
|
||||
return KResult(-EINTR);
|
||||
return EINTR;
|
||||
locker.lock();
|
||||
ASSERT(setup_state() == SetupState::Completed);
|
||||
if (has_error()) { // TODO: check unblock_flags
|
||||
m_role = Role::None;
|
||||
return KResult(-ECONNREFUSED);
|
||||
return ECONNREFUSED;
|
||||
}
|
||||
return KSuccess;
|
||||
}
|
||||
|
||||
return KResult(-EINPROGRESS);
|
||||
return EINPROGRESS;
|
||||
}
|
||||
|
||||
int TCPSocket::protocol_allocate_local_port()
|
||||
|
|
|
@ -86,7 +86,7 @@ KResultOr<size_t> UDPSocket::protocol_receive(ReadonlyBytes raw_ipv4_packet, Use
|
|||
ASSERT(udp_packet.length() >= sizeof(UDPPacket)); // FIXME: This should be rejected earlier.
|
||||
ASSERT(buffer_size >= (udp_packet.length() - sizeof(UDPPacket)));
|
||||
if (!buffer.write(udp_packet.payload(), udp_packet.length() - sizeof(UDPPacket)))
|
||||
return KResult(-EFAULT);
|
||||
return EFAULT;
|
||||
return udp_packet.length() - sizeof(UDPPacket);
|
||||
}
|
||||
|
||||
|
@ -94,7 +94,7 @@ KResultOr<size_t> UDPSocket::protocol_send(const UserOrKernelBuffer& data, size_
|
|||
{
|
||||
auto routing_decision = route_to(peer_address(), local_address(), bound_interface());
|
||||
if (routing_decision.is_zero())
|
||||
return KResult(-EHOSTUNREACH);
|
||||
return EHOSTUNREACH;
|
||||
const size_t buffer_size = sizeof(UDPPacket) + data_length;
|
||||
|
||||
alignas(UDPPacket) u8 buffer[buffer_size];
|
||||
|
@ -105,7 +105,7 @@ KResultOr<size_t> UDPSocket::protocol_send(const UserOrKernelBuffer& data, size_
|
|||
udp_packet.set_destination_port(peer_port());
|
||||
udp_packet.set_length(buffer_size);
|
||||
if (!data.read(udp_packet.payload(), data_length))
|
||||
return KResult(-EFAULT);
|
||||
return EFAULT;
|
||||
|
||||
routing_decision.adapter->send_ipv4(routing_decision.next_hop, peer_address(), IPv4Protocol::UDP, UserOrKernelBuffer::for_kernel_buffer(buffer), buffer_size, ttl());
|
||||
return data_length;
|
||||
|
@ -146,7 +146,7 @@ KResult UDPSocket::protocol_bind()
|
|||
{
|
||||
LOCKER(sockets_by_port().lock());
|
||||
if (sockets_by_port().resource().contains(local_port()))
|
||||
return KResult(-EADDRINUSE);
|
||||
return EADDRINUSE;
|
||||
sockets_by_port().resource().set(local_port(), this);
|
||||
return KSuccess;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue