From 12b93567f7dadec522e6b5f61e22a2dc7b52d714 Mon Sep 17 00:00:00 2001 From: Bananymous Date: Tue, 27 May 2025 07:07:30 +0300 Subject: [PATCH] Kernel/LibC: Implement `getpeername` --- kernel/include/kernel/FS/Inode.h | 2 ++ .../kernel/Networking/NetworkManager.h | 1 + .../include/kernel/Networking/NetworkSocket.h | 1 + kernel/include/kernel/Networking/TCPSocket.h | 1 + kernel/include/kernel/Networking/UDPSocket.h | 1 + .../include/kernel/Networking/UNIX/Socket.h | 1 + kernel/include/kernel/Process.h | 1 + kernel/kernel/FS/Inode.cpp | 8 +++++ kernel/kernel/Networking/TCPSocket.cpp | 11 +++++++ kernel/kernel/Networking/UNIX/Socket.cpp | 29 +++++++++++++++++++ kernel/kernel/Process.cpp | 14 +++++++++ .../libraries/LibC/include/sys/syscall.h | 1 + userspace/libraries/LibC/sys/socket.cpp | 10 +++---- 13 files changed, 76 insertions(+), 5 deletions(-) diff --git a/kernel/include/kernel/FS/Inode.h b/kernel/include/kernel/FS/Inode.h index 580eabac9f..9941873abe 100644 --- a/kernel/include/kernel/FS/Inode.h +++ b/kernel/include/kernel/FS/Inode.h @@ -111,6 +111,7 @@ namespace Kernel 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); + BAN::ErrorOr getpeername(sockaddr* address, socklen_t* address_len); // General API BAN::ErrorOr read(off_t, BAN::ByteSpan buffer); @@ -153,6 +154,7 @@ namespace Kernel 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 getsockname_impl(sockaddr*, socklen_t*) { return BAN::Error::from_errno(ENOTSUP); } + virtual BAN::ErrorOr getpeername_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/NetworkManager.h b/kernel/include/kernel/Networking/NetworkManager.h index aa0f1d10c0..779f8adaaf 100644 --- a/kernel/include/kernel/Networking/NetworkManager.h +++ b/kernel/include/kernel/Networking/NetworkManager.h @@ -25,6 +25,7 @@ namespace Kernel BAN::Vector>& interfaces() { return m_interfaces; } BAN::ErrorOr> create_socket(Socket::Domain, Socket::Type, mode_t, uid_t, gid_t); + BAN::ErrorOr connect_sockets(Socket::Domain, BAN::RefPtr, BAN::RefPtr); void on_receive(NetworkInterface&, BAN::ConstByteSpan); diff --git a/kernel/include/kernel/Networking/NetworkSocket.h b/kernel/include/kernel/Networking/NetworkSocket.h index e01a5ab129..66175a53e1 100644 --- a/kernel/include/kernel/Networking/NetworkSocket.h +++ b/kernel/include/kernel/Networking/NetworkSocket.h @@ -42,6 +42,7 @@ namespace Kernel virtual BAN::ErrorOr ioctl_impl(int request, void* arg) override; virtual BAN::ErrorOr getsockname_impl(sockaddr*, socklen_t*) override; + virtual BAN::ErrorOr getpeername_impl(sockaddr*, socklen_t*) override = 0; protected: NetworkLayer& m_network_layer; diff --git a/kernel/include/kernel/Networking/TCPSocket.h b/kernel/include/kernel/Networking/TCPSocket.h index 2c49171cd0..b36e1f8876 100644 --- a/kernel/include/kernel/Networking/TCPSocket.h +++ b/kernel/include/kernel/Networking/TCPSocket.h @@ -61,6 +61,7 @@ namespace Kernel virtual BAN::ErrorOr bind_impl(const sockaddr*, socklen_t) override; virtual BAN::ErrorOr sendto_impl(BAN::ConstByteSpan, const sockaddr*, socklen_t) override; virtual BAN::ErrorOr recvfrom_impl(BAN::ByteSpan, sockaddr*, socklen_t*) override; + virtual BAN::ErrorOr getpeername_impl(sockaddr*, socklen_t*) override; virtual void receive_packet(BAN::ConstByteSpan, const sockaddr* sender, socklen_t sender_len) override; diff --git a/kernel/include/kernel/Networking/UDPSocket.h b/kernel/include/kernel/Networking/UDPSocket.h index 995e6e8460..4ded8d987b 100644 --- a/kernel/include/kernel/Networking/UDPSocket.h +++ b/kernel/include/kernel/Networking/UDPSocket.h @@ -36,6 +36,7 @@ namespace Kernel virtual BAN::ErrorOr bind_impl(const sockaddr* address, socklen_t address_len) override; virtual BAN::ErrorOr sendto_impl(BAN::ConstByteSpan message, const sockaddr* address, socklen_t address_len) override; virtual BAN::ErrorOr recvfrom_impl(BAN::ByteSpan buffer, sockaddr* address, socklen_t* address_len) override; + virtual BAN::ErrorOr getpeername_impl(sockaddr*, socklen_t*) override { return BAN::Error::from_errno(ENOTCONN); } virtual bool can_read_impl() const override { return !m_packets.empty(); } virtual bool can_write_impl() const override { return true; } diff --git a/kernel/include/kernel/Networking/UNIX/Socket.h b/kernel/include/kernel/Networking/UNIX/Socket.h index 92dfff409f..eff296200a 100644 --- a/kernel/include/kernel/Networking/UNIX/Socket.h +++ b/kernel/include/kernel/Networking/UNIX/Socket.h @@ -25,6 +25,7 @@ namespace Kernel virtual BAN::ErrorOr bind_impl(const sockaddr*, socklen_t) override; virtual BAN::ErrorOr sendto_impl(BAN::ConstByteSpan, const sockaddr*, socklen_t) override; virtual BAN::ErrorOr recvfrom_impl(BAN::ByteSpan, sockaddr*, socklen_t*) override; + virtual BAN::ErrorOr getpeername_impl(sockaddr*, socklen_t*) override; virtual bool can_read_impl() const override; virtual bool can_write_impl() const override; diff --git a/kernel/include/kernel/Process.h b/kernel/include/kernel/Process.h index 2144045289..9e1007445f 100644 --- a/kernel/include/kernel/Process.h +++ b/kernel/include/kernel/Process.h @@ -119,6 +119,7 @@ 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_getpeername(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); diff --git a/kernel/kernel/FS/Inode.cpp b/kernel/kernel/FS/Inode.cpp index ca3af167b9..aeddd8a5d7 100644 --- a/kernel/kernel/FS/Inode.cpp +++ b/kernel/kernel/FS/Inode.cpp @@ -186,6 +186,14 @@ namespace Kernel return getsockname_impl(address, address_len); } + BAN::ErrorOr Inode::getpeername(sockaddr* address, socklen_t* address_len) + { + LockGuard _(m_mutex); + if (!mode().ifsock()) + return BAN::Error::from_errno(ENOTSOCK); + return getpeername_impl(address, address_len); + } + BAN::ErrorOr Inode::read(off_t offset, BAN::ByteSpan buffer) { LockGuard _(m_mutex); diff --git a/kernel/kernel/Networking/TCPSocket.cpp b/kernel/kernel/Networking/TCPSocket.cpp index 27174027ec..0ca588c1a6 100644 --- a/kernel/kernel/Networking/TCPSocket.cpp +++ b/kernel/kernel/Networking/TCPSocket.cpp @@ -256,6 +256,17 @@ namespace Kernel return to_send; } + BAN::ErrorOr TCPSocket::getpeername_impl(sockaddr* address, socklen_t* address_len) + { + if (!m_has_connected && m_state != State::Established) + return BAN::Error::from_errno(ENOTCONN); + ASSERT(m_connection_info.has_value()); + const size_t to_copy = BAN::Math::min(m_connection_info->address_len, *address_len); + memcpy(address, &m_connection_info->address, to_copy); + *address_len = to_copy; + return {}; + } + bool TCPSocket::can_read_impl() const { if (m_has_connected && !m_has_sent_zero && m_state != State::Established && m_state != State::Listen) diff --git a/kernel/kernel/Networking/UNIX/Socket.cpp b/kernel/kernel/Networking/UNIX/Socket.cpp index eab89a1bfe..84dc06dcb3 100644 --- a/kernel/kernel/Networking/UNIX/Socket.cpp +++ b/kernel/kernel/Networking/UNIX/Socket.cpp @@ -412,4 +412,33 @@ namespace Kernel return nread; } + BAN::ErrorOr UnixDomainSocket::getpeername_impl(sockaddr* address, socklen_t* address_len) + { + if (!m_info.has()) + return BAN::Error::from_errno(ENOTCONN); + auto connection = m_info.get().connection.lock(); + if (!connection) + return BAN::Error::from_errno(ENOTCONN); + + sockaddr_un sa_un; + sa_un.sun_family = AF_UNIX; + sa_un.sun_path[0] = 0; + + { + SpinLockGuard _(s_bound_socket_lock); + for (auto& [path, socket] : s_bound_sockets) + { + if (socket.lock() != connection) + continue; + strcpy(sa_un.sun_path, path.data()); + break; + } + } + + const size_t to_copy = BAN::Math::min(sizeof(sockaddr_un), *address_len); + memcpy(address, &sa_un, to_copy); + *address_len = to_copy; + return {}; + } + } diff --git a/kernel/kernel/Process.cpp b/kernel/kernel/Process.cpp index b823c5436e..97d5effc94 100644 --- a/kernel/kernel/Process.cpp +++ b/kernel/kernel/Process.cpp @@ -1284,6 +1284,20 @@ namespace Kernel return 0; } + BAN::ErrorOr Process::sys_getpeername(int socket, sockaddr* address, socklen_t* address_len) + { + LockGuard _(m_process_lock); + TRY(validate_pointer_access(address_len, sizeof(address_len), true)); + TRY(validate_pointer_access(address, *address_len, true)); + + auto inode = TRY(m_open_file_descriptors.inode_of(socket)); + if (!inode->mode().ifsock()) + return BAN::Error::from_errno(ENOTSOCK); + + TRY(inode->getpeername(address, address_len)); + 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); diff --git a/userspace/libraries/LibC/include/sys/syscall.h b/userspace/libraries/LibC/include/sys/syscall.h index 27fa9a8296..0e7cb42e56 100644 --- a/userspace/libraries/LibC/include/sys/syscall.h +++ b/userspace/libraries/LibC/include/sys/syscall.h @@ -78,6 +78,7 @@ __BEGIN_DECLS O(SYS_SMO_MAP, smo_map) \ O(SYS_ISATTY, isatty) \ O(SYS_GETSOCKNAME, getsockname) \ + O(SYS_GETPEERNAME, getpeername) \ O(SYS_GETSOCKOPT, getsockopt) \ O(SYS_SETSOCKOPT, setsockopt) \ O(SYS_REALPATH, realpath) \ diff --git a/userspace/libraries/LibC/sys/socket.cpp b/userspace/libraries/LibC/sys/socket.cpp index 4e62e0d407..93435cc35b 100644 --- a/userspace/libraries/LibC/sys/socket.cpp +++ b/userspace/libraries/LibC/sys/socket.cpp @@ -73,6 +73,11 @@ int getsockname(int socket, struct sockaddr* __restrict address, socklen_t* __re return syscall(SYS_GETSOCKNAME, socket, address, address_len); } +int getpeername(int socket, struct sockaddr* __restrict address, socklen_t* __restrict address_len) +{ + return syscall(SYS_GETPEERNAME, 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); @@ -87,11 +92,6 @@ int setsockopt(int socket, int level, int option_name, const void* option_value, #include -int getpeername(int, struct sockaddr* __restrict, socklen_t* __restrict) -{ - ASSERT_NOT_REACHED(); -} - int shutdown(int, int) { ASSERT_NOT_REACHED();