Kernel/LibC: Implement basic socket binding

This commit is contained in:
2024-02-02 01:31:58 +02:00
parent cf28ecd5a6
commit ab150b458a
13 changed files with 119 additions and 7 deletions

View File

@@ -68,11 +68,39 @@ namespace Kernel
BAN::ErrorOr<BAN::RefPtr<NetworkSocket>> NetworkManager::create_socket(SocketType type, mode_t mode, uid_t uid, gid_t gid)
{
ASSERT((mode & Inode::Mode::TYPE_MASK) == 0);
if (type != SocketType::DGRAM)
return BAN::Error::from_errno(EPROTOTYPE);
auto udp_socket = TRY(UDPSocket::create(mode, uid, gid));
auto udp_socket = TRY(UDPSocket::create(mode | Inode::Mode::IFSOCK, uid, gid));
return BAN::RefPtr<NetworkSocket>(udp_socket);
}
void NetworkManager::unbind_socket(uint16_t port, BAN::RefPtr<NetworkSocket> socket)
{
if (m_bound_sockets.contains(port))
{
ASSERT(m_bound_sockets[port].valid());
ASSERT(m_bound_sockets[port].lock() == socket);
m_bound_sockets.remove(port);
}
NetworkManager::get().remove_from_cache(socket);
}
BAN::ErrorOr<void> NetworkManager::bind_socket(uint16_t port, BAN::RefPtr<NetworkSocket> socket)
{
if (m_interfaces.empty())
return BAN::Error::from_errno(EADDRNOTAVAIL);
if (m_bound_sockets.contains(port))
return BAN::Error::from_errno(EADDRINUSE);
// FIXME: actually determine proper interface
auto interface = m_interfaces.front();
TRY(m_bound_sockets.insert(port, socket));
socket->bind_interface_and_port(interface.ptr(), port);
return {};
}
}

View File

@@ -13,11 +13,30 @@ namespace Kernel
)
{ }
void NetworkSocket::bind_interface(NetworkInterface* interface)
NetworkSocket::~NetworkSocket()
{
}
void NetworkSocket::on_close_impl()
{
if (m_interface)
NetworkManager::get().unbind_socket(m_port, this);
}
void NetworkSocket::bind_interface_and_port(NetworkInterface* interface, uint16_t port)
{
ASSERT(!m_interface);
ASSERT(interface);
m_interface = interface;
m_port = port;
}
BAN::ErrorOr<void> NetworkSocket::bind_impl(const sockaddr* address, socklen_t address_len)
{
if (address_len != sizeof(sockaddr_in))
return BAN::Error::from_errno(EINVAL);
auto* addr_in = reinterpret_cast<const sockaddr_in*>(address);
return NetworkManager::get().bind_socket(addr_in->sin_port, this);
}
}