diff --git a/kernel/include/kernel/Process.h b/kernel/include/kernel/Process.h index 8f7756c7..058c2861 100644 --- a/kernel/include/kernel/Process.h +++ b/kernel/include/kernel/Process.h @@ -120,6 +120,8 @@ namespace Kernel BAN::ErrorOr sys_socket(int domain, int type, int protocol); BAN::ErrorOr sys_getsockname(int socket, sockaddr* address, socklen_t* address_len); + BAN::ErrorOr sys_getsockopt(int socket, int level, int option_name, void* option_value, socklen_t* option_len); + BAN::ErrorOr sys_setsockopt(int socket, int level, int option_name, const void* option_value, socklen_t option_len); BAN::ErrorOr sys_accept(int socket, sockaddr* address, socklen_t* address_len); BAN::ErrorOr sys_bind(int socket, const sockaddr* address, socklen_t address_len); diff --git a/kernel/kernel/Process.cpp b/kernel/kernel/Process.cpp index 922975e1..6c090284 100644 --- a/kernel/kernel/Process.cpp +++ b/kernel/kernel/Process.cpp @@ -925,6 +925,42 @@ namespace Kernel return 0; } + BAN::ErrorOr Process::sys_getsockopt(int socket, int level, int option_name, void* option_value, socklen_t* option_len) + { + LockGuard _(m_process_lock); + TRY(validate_pointer_access(option_len, sizeof(option_len))); + TRY(validate_pointer_access(option_value, *option_len)); + + auto inode = TRY(m_open_file_descriptors.inode_of(socket)); + if (!inode->mode().ifsock()) + return BAN::Error::from_errno(ENOTSOCK); + + // Because all networking is synchronous, there can not be errors to report + if (level == SOL_SOCKET && option_name == SO_ERROR) + { + if (*option_len) + *reinterpret_cast(option_value) = 0; + *option_len = BAN::Math::min(*option_len, sizeof(int)); + return 0; + } + + dprintln("SYS_GETSOCKOPT {}, {}, {}, {}, {}", socket, level, option_name, option_value, option_len); + return BAN::Error::from_errno(ENOTSUP); + } + + BAN::ErrorOr Process::sys_setsockopt(int socket, int level, int option_name, const void* option_value, socklen_t option_len) + { + LockGuard _(m_process_lock); + TRY(validate_pointer_access(option_value, option_len)); + + auto inode = TRY(m_open_file_descriptors.inode_of(socket)); + if (!inode->mode().ifsock()) + return BAN::Error::from_errno(ENOTSOCK); + + dprintln("SYS_GETSOCKOPT {}, {}, {}, {}, {}", socket, level, option_name, option_value, option_len); + return BAN::Error::from_errno(ENOTSUP); + } + BAN::ErrorOr Process::sys_accept(int socket, sockaddr* address, socklen_t* address_len) { if (address && !address_len) diff --git a/libc/include/sys/syscall.h b/libc/include/sys/syscall.h index 9d44a0d1..276c22c0 100644 --- a/libc/include/sys/syscall.h +++ b/libc/include/sys/syscall.h @@ -79,6 +79,8 @@ __BEGIN_DECLS O(SYS_SMO_MAP, smo_map) \ O(SYS_ISATTY, isatty) \ O(SYS_GETSOCKNAME, getsockname) \ + O(SYS_GETSOCKOPT, getsockopt) \ + O(SYS_SETSOCKOPT, setsockopt) \ enum Syscall { diff --git a/libc/sys/socket.cpp b/libc/sys/socket.cpp index b1663f89..2cc5abd4 100644 --- a/libc/sys/socket.cpp +++ b/libc/sys/socket.cpp @@ -67,3 +67,13 @@ int getsockname(int socket, struct sockaddr* __restrict address, socklen_t* __re { return syscall(SYS_GETSOCKNAME, socket, address, address_len); } + +int getsockopt(int socket, int level, int option_name, void* __restrict option_value, socklen_t* __restrict option_len) +{ + return syscall(SYS_GETSOCKOPT, socket, level, option_name, option_value, option_len); +} + +int setsockopt(int socket, int level, int option_name, const void* option_value, socklen_t option_len) +{ + return syscall(SYS_SETSOCKOPT, socket, level, option_name, option_value, option_len); +}