2023-07-27 16:37:10 +02:00
|
|
|
#include "net/Socket.h"
|
2023-08-12 21:38:25 +02:00
|
|
|
#include "Pledge.h"
|
2023-07-27 16:37:10 +02:00
|
|
|
#include "memory/MemoryManager.h"
|
|
|
|
#include "net/UnixSocket.h"
|
|
|
|
#include "sys/Syscall.h"
|
|
|
|
#include "thread/Scheduler.h"
|
|
|
|
#include <bits/open-flags.h>
|
|
|
|
|
|
|
|
Result<u64> sys_socket(Registers*, SyscallArgs args)
|
|
|
|
{
|
|
|
|
int domain = (int)args[0];
|
|
|
|
int type = (int)args[1];
|
|
|
|
// protocol is not used for now.
|
|
|
|
|
|
|
|
if (type != SOCK_STREAM) return err(EPROTOTYPE);
|
|
|
|
if (domain != AF_UNIX) return err(EAFNOSUPPORT);
|
|
|
|
|
|
|
|
auto* current = Scheduler::current();
|
2023-08-12 21:38:25 +02:00
|
|
|
TRY(check_pledge(current, Promise::p_unix));
|
|
|
|
|
|
|
|
auto socket = TRY(make_shared<UnixSocket>());
|
2023-07-27 16:37:10 +02:00
|
|
|
|
|
|
|
int fd = TRY(current->allocate_fd(0));
|
|
|
|
|
2023-07-27 19:21:23 +02:00
|
|
|
current->fd_table[fd] = FileDescriptor { TRY(make_shared<OpenFileDescription>(socket, O_RDWR)), 0 };
|
2023-07-27 16:37:10 +02:00
|
|
|
|
|
|
|
return fd;
|
|
|
|
}
|
|
|
|
|
|
|
|
Result<u64> sys_bind(Registers*, SyscallArgs args)
|
|
|
|
{
|
|
|
|
int sockfd = (int)args[0];
|
|
|
|
struct sockaddr* addr = (struct sockaddr*)args[1];
|
|
|
|
socklen_t addrlen = (socklen_t)args[2];
|
|
|
|
|
|
|
|
struct sockaddr_storage storage;
|
|
|
|
if ((usize)addrlen > sizeof(storage)) return err(EINVAL);
|
|
|
|
if (!MemoryManager::copy_from_user(addr, &storage, addrlen)) return err(EFAULT);
|
|
|
|
|
|
|
|
auto* current = Scheduler::current();
|
2023-08-12 21:38:25 +02:00
|
|
|
TRY(check_pledge(current, Promise::p_unix));
|
2023-07-27 16:37:10 +02:00
|
|
|
|
2023-07-27 19:21:23 +02:00
|
|
|
auto inode = TRY(current->resolve_fd(sockfd))->inode();
|
2023-07-27 16:37:10 +02:00
|
|
|
|
|
|
|
if (inode->type() != VFS::InodeType::Socket) return err(ENOTSOCK);
|
|
|
|
|
|
|
|
auto socket = (SharedPtr<Socket>)inode;
|
|
|
|
|
2023-08-01 17:20:28 +02:00
|
|
|
TRY(socket->bind((struct sockaddr*)&storage, addrlen));
|
2023-07-27 16:37:10 +02:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
2023-07-28 17:30:20 +02:00
|
|
|
|
|
|
|
Result<u64> sys_connect(Registers* regs, SyscallArgs args)
|
|
|
|
{
|
|
|
|
int sockfd = (int)args[0];
|
|
|
|
struct sockaddr* addr = (struct sockaddr*)args[1];
|
|
|
|
socklen_t addrlen = (socklen_t)args[2];
|
|
|
|
|
|
|
|
struct sockaddr_storage storage;
|
|
|
|
if ((usize)addrlen > sizeof(storage)) return err(EINVAL);
|
|
|
|
if (!MemoryManager::copy_from_user(addr, &storage, addrlen)) return err(EFAULT);
|
|
|
|
|
|
|
|
auto* current = Scheduler::current();
|
2023-08-12 21:38:25 +02:00
|
|
|
TRY(check_pledge(current, Promise::p_unix));
|
2023-07-28 17:30:20 +02:00
|
|
|
|
|
|
|
auto description = TRY(current->resolve_fd(sockfd))->description;
|
|
|
|
|
|
|
|
if (description->inode->type() != VFS::InodeType::Socket) return err(ENOTSOCK);
|
|
|
|
|
|
|
|
auto socket = (SharedPtr<Socket>)description->inode;
|
|
|
|
|
|
|
|
TRY(socket->connect(regs, description->flags, (struct sockaddr*)&storage, addrlen));
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
Result<u64> sys_listen(Registers*, SyscallArgs args)
|
|
|
|
{
|
|
|
|
int sockfd = (int)args[0];
|
|
|
|
int backlog = (int)args[1];
|
|
|
|
|
|
|
|
auto* current = Scheduler::current();
|
2023-08-12 21:38:25 +02:00
|
|
|
TRY(check_pledge(current, Promise::p_unix));
|
2023-07-28 17:30:20 +02:00
|
|
|
|
|
|
|
auto inode = TRY(current->resolve_fd(sockfd))->inode();
|
|
|
|
|
|
|
|
if (inode->type() != VFS::InodeType::Socket) return err(ENOTSOCK);
|
|
|
|
|
|
|
|
auto socket = (SharedPtr<Socket>)inode;
|
|
|
|
|
|
|
|
TRY(socket->listen(backlog));
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
Result<u64> sys_accept(Registers* regs, SyscallArgs args)
|
|
|
|
{
|
|
|
|
int sockfd = (int)args[0];
|
|
|
|
struct sockaddr* addr = (struct sockaddr*)args[1];
|
|
|
|
socklen_t* addrlen = (socklen_t*)args[2];
|
|
|
|
|
|
|
|
if (addr && !addrlen) return err(EINVAL);
|
|
|
|
|
|
|
|
socklen_t len;
|
|
|
|
if (addr)
|
|
|
|
{
|
|
|
|
if (!MemoryManager::copy_from_user_typed(addrlen, &len)) return err(EFAULT);
|
|
|
|
}
|
|
|
|
|
|
|
|
auto* current = Scheduler::current();
|
2023-08-12 21:38:25 +02:00
|
|
|
TRY(check_pledge(current, Promise::p_unix));
|
2023-07-28 17:30:20 +02:00
|
|
|
|
|
|
|
auto description = TRY(current->resolve_fd(sockfd))->description;
|
|
|
|
|
|
|
|
if (description->inode->type() != VFS::InodeType::Socket) return err(ENOTSOCK);
|
|
|
|
|
|
|
|
auto socket = (SharedPtr<Socket>)description->inode;
|
|
|
|
|
|
|
|
struct sockaddr* client;
|
|
|
|
socklen_t client_len;
|
|
|
|
auto new_description = TRY(socket->accept(regs, description->flags, &client, &client_len));
|
|
|
|
|
|
|
|
int fd = TRY(current->allocate_fd(0));
|
|
|
|
current->fd_table[fd] = FileDescriptor { new_description, 0 };
|
|
|
|
|
|
|
|
if (client_len < len) len = client_len;
|
|
|
|
if (addr)
|
|
|
|
{
|
|
|
|
MemoryManager::copy_to_user(addr, client, len);
|
|
|
|
MemoryManager::copy_to_user_typed(addrlen, &client_len);
|
|
|
|
}
|
|
|
|
|
|
|
|
return fd;
|
|
|
|
}
|