From cad55a4da50c17411a824800bb0ac56ab8e77c5f Mon Sep 17 00:00:00 2001 From: Bananymous Date: Mon, 17 Jun 2024 20:54:45 +0300 Subject: [PATCH] Kernel/LibC: Implement getsockname for ipv4 sockets --- kernel/include/kernel/FS/Inode.h | 4 +++- kernel/include/kernel/Networking/IPv4Layer.h | 1 + .../include/kernel/Networking/NetworkLayer.h | 1 + .../include/kernel/Networking/NetworkSocket.h | 1 + kernel/include/kernel/Process.h | 2 ++ kernel/kernel/FS/Inode.cpp | 8 +++++++ kernel/kernel/Networking/IPv4Layer.cpp | 22 +++++++++++++++++++ kernel/kernel/Networking/NetworkSocket.cpp | 6 +++++ kernel/kernel/Process.cpp | 14 ++++++++++++ libc/include/sys/syscall.h | 1 + libc/sys/socket.cpp | 5 +++++ 11 files changed, 64 insertions(+), 1 deletion(-) diff --git a/kernel/include/kernel/FS/Inode.h b/kernel/include/kernel/FS/Inode.h index dca85c55..94a48e99 100644 --- a/kernel/include/kernel/FS/Inode.h +++ b/kernel/include/kernel/FS/Inode.h @@ -105,6 +105,7 @@ namespace Kernel BAN::ErrorOr listen(int backlog); BAN::ErrorOr sendto(BAN::ConstByteSpan message, const sockaddr* address, socklen_t address_len); BAN::ErrorOr recvfrom(BAN::ByteSpan buffer, sockaddr* address, socklen_t* address_len); + BAN::ErrorOr getsockname(sockaddr* address, socklen_t* address_len); // General API BAN::ErrorOr read(off_t, BAN::ByteSpan buffer); @@ -139,7 +140,8 @@ namespace Kernel virtual BAN::ErrorOr listen_impl(int) { return BAN::Error::from_errno(ENOTSUP); } virtual BAN::ErrorOr bind_impl(const sockaddr*, socklen_t) { return BAN::Error::from_errno(ENOTSUP); } virtual BAN::ErrorOr sendto_impl(BAN::ConstByteSpan, const sockaddr*, socklen_t) { return BAN::Error::from_errno(ENOTSUP); } - virtual BAN::ErrorOr recvfrom_impl(BAN::ByteSpan, sockaddr*, socklen_t*) { return BAN::Error::from_errno(ENOTSUP); } + virtual BAN::ErrorOr recvfrom_impl(BAN::ByteSpan, sockaddr*, socklen_t*) { return BAN::Error::from_errno(ENOTSUP); } + virtual BAN::ErrorOr getsockname_impl(sockaddr*, socklen_t*) { return BAN::Error::from_errno(ENOTSUP); } // General API virtual BAN::ErrorOr read_impl(off_t, BAN::ByteSpan) { return BAN::Error::from_errno(ENOTSUP); } diff --git a/kernel/include/kernel/Networking/IPv4Layer.h b/kernel/include/kernel/Networking/IPv4Layer.h index 83aa4b1a..0167529a 100644 --- a/kernel/include/kernel/Networking/IPv4Layer.h +++ b/kernel/include/kernel/Networking/IPv4Layer.h @@ -47,6 +47,7 @@ namespace Kernel virtual void unbind_socket(BAN::RefPtr, uint16_t port) override; virtual BAN::ErrorOr bind_socket_to_unused(BAN::RefPtr, const sockaddr* send_address, socklen_t send_address_len) override; virtual BAN::ErrorOr bind_socket_to_address(BAN::RefPtr, const sockaddr* address, socklen_t address_len) override; + virtual BAN::ErrorOr get_socket_address(BAN::RefPtr, sockaddr* address, socklen_t* address_len) override; virtual BAN::ErrorOr sendto(NetworkSocket&, BAN::ConstByteSpan, const sockaddr*, socklen_t) override; diff --git a/kernel/include/kernel/Networking/NetworkLayer.h b/kernel/include/kernel/Networking/NetworkLayer.h index af9ca050..dce85345 100644 --- a/kernel/include/kernel/Networking/NetworkLayer.h +++ b/kernel/include/kernel/Networking/NetworkLayer.h @@ -25,6 +25,7 @@ namespace Kernel virtual void unbind_socket(BAN::RefPtr, uint16_t port) = 0; virtual BAN::ErrorOr bind_socket_to_unused(BAN::RefPtr, const sockaddr* send_address, socklen_t send_address_len) = 0; virtual BAN::ErrorOr bind_socket_to_address(BAN::RefPtr, const sockaddr* address, socklen_t address_len) = 0; + virtual BAN::ErrorOr get_socket_address(BAN::RefPtr, sockaddr* address, socklen_t* address_len) = 0; virtual BAN::ErrorOr sendto(NetworkSocket&, BAN::ConstByteSpan, const sockaddr*, socklen_t) = 0; diff --git a/kernel/include/kernel/Networking/NetworkSocket.h b/kernel/include/kernel/Networking/NetworkSocket.h index 04986fa7..72c28281 100644 --- a/kernel/include/kernel/Networking/NetworkSocket.h +++ b/kernel/include/kernel/Networking/NetworkSocket.h @@ -42,6 +42,7 @@ namespace Kernel NetworkSocket(NetworkLayer&, ino_t, const TmpInodeInfo&); virtual BAN::ErrorOr ioctl_impl(int request, void* arg) override; + virtual BAN::ErrorOr getsockname_impl(sockaddr*, socklen_t*) override; protected: NetworkLayer& m_network_layer; diff --git a/kernel/include/kernel/Process.h b/kernel/include/kernel/Process.h index 9a09082b..8f7756c7 100644 --- a/kernel/include/kernel/Process.h +++ b/kernel/include/kernel/Process.h @@ -119,6 +119,8 @@ namespace Kernel BAN::ErrorOr sys_chown(const char*, uid_t, gid_t); 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_accept(int socket, sockaddr* address, socklen_t* address_len); BAN::ErrorOr sys_bind(int socket, const sockaddr* address, socklen_t address_len); BAN::ErrorOr sys_connect(int socket, const sockaddr* address, socklen_t address_len); diff --git a/kernel/kernel/FS/Inode.cpp b/kernel/kernel/FS/Inode.cpp index 8dfcce20..2b6ef111 100644 --- a/kernel/kernel/FS/Inode.cpp +++ b/kernel/kernel/FS/Inode.cpp @@ -164,6 +164,14 @@ namespace Kernel return recvfrom_impl(buffer, address, address_len); }; + BAN::ErrorOr Inode::getsockname(sockaddr* address, socklen_t* address_len) + { + LockGuard _(m_mutex); + if (!mode().ifsock()) + return BAN::Error::from_errno(ENOTSOCK); + return getsockname_impl(address, address_len); + } + BAN::ErrorOr Inode::read(off_t offset, BAN::ByteSpan buffer) { LockGuard _(m_mutex); diff --git a/kernel/kernel/Networking/IPv4Layer.cpp b/kernel/kernel/Networking/IPv4Layer.cpp index 055ad25a..9ef3d629 100644 --- a/kernel/kernel/Networking/IPv4Layer.cpp +++ b/kernel/kernel/Networking/IPv4Layer.cpp @@ -139,6 +139,28 @@ namespace Kernel return {}; } + BAN::ErrorOr IPv4Layer::get_socket_address(BAN::RefPtr socket, sockaddr* address, socklen_t* address_len) + { + if (*address_len < (socklen_t)sizeof(sockaddr_in)) + return BAN::Error::from_errno(ENOBUFS); + + sockaddr_in* in_addr = reinterpret_cast(address); + + SpinLockGuard _(m_bound_socket_lock); + for (auto& [bound_port, bound_socket] : m_bound_sockets) + { + if (socket != bound_socket.lock()) + continue; + // FIXME: sockets should have bound address + in_addr->sin_family = AF_INET; + in_addr->sin_port = bound_port; + in_addr->sin_addr.s_addr = INADDR_ANY; + return {}; + } + + return {}; + } + BAN::ErrorOr IPv4Layer::sendto(NetworkSocket& socket, BAN::ConstByteSpan buffer, const sockaddr* address, socklen_t address_len) { if (address->sa_family != AF_INET) diff --git a/kernel/kernel/Networking/NetworkSocket.cpp b/kernel/kernel/Networking/NetworkSocket.cpp index c88627c8..1743e920 100644 --- a/kernel/kernel/Networking/NetworkSocket.cpp +++ b/kernel/kernel/Networking/NetworkSocket.cpp @@ -100,4 +100,10 @@ namespace Kernel } } + BAN::ErrorOr NetworkSocket::getsockname_impl(sockaddr* address, socklen_t* address_len) + { + TRY(m_network_layer.get_socket_address(this, address, address_len)); + return {}; + } + } diff --git a/kernel/kernel/Process.cpp b/kernel/kernel/Process.cpp index 3dfd5b10..922975e1 100644 --- a/kernel/kernel/Process.cpp +++ b/kernel/kernel/Process.cpp @@ -911,6 +911,20 @@ namespace Kernel return TRY(m_open_file_descriptors.socket(domain, type, protocol)); } + BAN::ErrorOr Process::sys_getsockname(int socket, sockaddr* address, socklen_t* address_len) + { + LockGuard _(m_process_lock); + TRY(validate_pointer_access(address_len, sizeof(address_len))); + TRY(validate_pointer_access(address, *address_len)); + + auto inode = TRY(m_open_file_descriptors.inode_of(socket)); + if (!inode->mode().ifsock()) + return BAN::Error::from_errno(ENOTSOCK); + + TRY(inode->getsockname(address, address_len)); + return 0; + } + 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 a720c1a8..9d44a0d1 100644 --- a/libc/include/sys/syscall.h +++ b/libc/include/sys/syscall.h @@ -78,6 +78,7 @@ __BEGIN_DECLS O(SYS_SMO_DELETE, smo_delete) \ O(SYS_SMO_MAP, smo_map) \ O(SYS_ISATTY, isatty) \ + O(SYS_GETSOCKNAME, getsockname) \ enum Syscall { diff --git a/libc/sys/socket.cpp b/libc/sys/socket.cpp index e9580ce4..b1663f89 100644 --- a/libc/sys/socket.cpp +++ b/libc/sys/socket.cpp @@ -62,3 +62,8 @@ int socket(int domain, int type, int protocol) { return syscall(SYS_SOCKET, domain, type, protocol); } + +int getsockname(int socket, struct sockaddr* __restrict address, socklen_t* __restrict address_len) +{ + return syscall(SYS_GETSOCKNAME, socket, address, address_len); +}