From d266d2ca88ed575c4f4425b19f6425c16be98b96 Mon Sep 17 00:00:00 2001 From: Bananymous Date: Sat, 23 May 2026 13:02:43 +0300 Subject: [PATCH] Kernel: Allow network interface ioctls on interfaces previously it was only on the sockets --- .../kernel/Networking/NetworkInterface.h | 3 + kernel/kernel/Networking/NetworkInterface.cpp | 95 ++++++++++++++++++- kernel/kernel/Networking/NetworkSocket.cpp | 69 +------------- 3 files changed, 100 insertions(+), 67 deletions(-) diff --git a/kernel/include/kernel/Networking/NetworkInterface.h b/kernel/include/kernel/Networking/NetworkInterface.h index 94cae3eb..1157ad86 100644 --- a/kernel/include/kernel/Networking/NetworkInterface.h +++ b/kernel/include/kernel/Networking/NetworkInterface.h @@ -65,6 +65,9 @@ namespace Kernel } virtual BAN::ErrorOr send_bytes(BAN::MACAddress destination, EtherType protocol, BAN::Span payload) = 0; + private: + BAN::ErrorOr ioctl_impl(int, void*) override; + private: const Type m_type; char m_name[10]; diff --git a/kernel/kernel/Networking/NetworkInterface.cpp b/kernel/kernel/Networking/NetworkInterface.cpp index fe2b8b72..b21c1f61 100644 --- a/kernel/kernel/Networking/NetworkInterface.cpp +++ b/kernel/kernel/Networking/NetworkInterface.cpp @@ -3,6 +3,8 @@ #include #include +#include +#include #include #include @@ -25,7 +27,7 @@ namespace Kernel } NetworkInterface::NetworkInterface(Type type) - : CharacterDevice(0400, 0, 0) + : CharacterDevice(0664, 0, 0) , m_type(type) { m_rdev = get_rdev(type); @@ -43,4 +45,95 @@ namespace Kernel } } + BAN::ErrorOr NetworkInterface::ioctl_impl(int request, void* arg) + { + if (arg == nullptr) + { + dprintln("No argument provided"); + return BAN::Error::from_errno(EINVAL); + } + + auto* ifreq = reinterpret_cast(arg); + + switch (request) + { + case SIOCGIFADDR: + { + auto& ifru_addr = *reinterpret_cast(&ifreq->ifr_ifru.ifru_addr); + ifru_addr.sin_family = AF_INET; + ifru_addr.sin_addr.s_addr = get_ipv4_address().raw; + return 0; + } + case SIOCSIFADDR: + { + auto& ifru_addr = *reinterpret_cast(&ifreq->ifr_ifru.ifru_addr); + if (ifru_addr.sin_family != AF_INET) + return BAN::Error::from_errno(EADDRNOTAVAIL); + set_ipv4_address(BAN::IPv4Address { ifru_addr.sin_addr.s_addr }); + dprintln("IPv4 address set to {}", get_ipv4_address()); + return 0; + } + case SIOCGIFNETMASK: + { + auto& ifru_netmask = *reinterpret_cast(&ifreq->ifr_ifru.ifru_netmask); + ifru_netmask.sin_family = AF_INET; + ifru_netmask.sin_addr.s_addr = get_netmask().raw; + return 0; + } + case SIOCSIFNETMASK: + { + auto& ifru_netmask = *reinterpret_cast(&ifreq->ifr_ifru.ifru_netmask); + if (ifru_netmask.sin_family != AF_INET) + return BAN::Error::from_errno(EADDRNOTAVAIL); + set_netmask(BAN::IPv4Address { ifru_netmask.sin_addr.s_addr }); + dprintln("Netmask set to {}", get_netmask()); + return 0; + } + case SIOCGIFGWADDR: + { + auto& ifru_gwaddr = *reinterpret_cast(&ifreq->ifr_ifru.ifru_gwaddr); + ifru_gwaddr.sin_family = AF_INET; + ifru_gwaddr.sin_addr.s_addr = get_gateway().raw; + return 0; + } + case SIOCSIFGWADDR: + { + auto& ifru_gwaddr = *reinterpret_cast(&ifreq->ifr_ifru.ifru_gwaddr); + if (ifru_gwaddr.sin_family != AF_INET) + return BAN::Error::from_errno(EADDRNOTAVAIL); + set_gateway(BAN::IPv4Address { ifru_gwaddr.sin_addr.s_addr }); + dprintln("Gateway set to {}", get_gateway()); + return 0; + } + case SIOCGIFHWADDR: + { + auto mac_address = get_mac_address(); + ifreq->ifr_ifru.ifru_hwaddr.sa_family = AF_INET; + memcpy(ifreq->ifr_ifru.ifru_hwaddr.sa_data, &mac_address, sizeof(mac_address)); + return 0; + } + case SIOCGIFNAME: + { + auto& ifrn_name = ifreq->ifr_ifrn.ifrn_name; + ASSERT(name().size() < sizeof(ifrn_name)); + memcpy(ifrn_name, name().data(), name().size()); + ifrn_name[name().size()] = '\0'; + return 0; + } + case SIOCGIFFLAGS: + { + int flags = 0; + if (link_up()) + flags |= IFF_UP | IFF_RUNNING; + if (m_type == Type::Loopback) + flags |= IFF_LOOPBACK; + ifreq->ifr_ifru.ifru_flags = flags; + return 0; + } + } + + return CharacterDevice::ioctl_impl(request, arg); + } + + } diff --git a/kernel/kernel/Networking/NetworkSocket.cpp b/kernel/kernel/Networking/NetworkSocket.cpp index b689eeaa..91847b54 100644 --- a/kernel/kernel/Networking/NetworkSocket.cpp +++ b/kernel/kernel/Networking/NetworkSocket.cpp @@ -110,83 +110,20 @@ namespace Kernel BAN::ErrorOr NetworkSocket::ioctl_impl(int request, void* arg) { - if (!arg) - { - dprintln("No argument provided"); - return BAN::Error::from_errno(EINVAL); - } - - auto interface = TRY(this->interface(nullptr, 0)); - auto* ifreq = reinterpret_cast(arg); - switch (request) { case SIOCGIFADDR: - { - auto& ifru_addr = *reinterpret_cast(&ifreq->ifr_ifru.ifru_addr); - ifru_addr.sin_family = AF_INET; - ifru_addr.sin_addr.s_addr = interface->get_ipv4_address().raw; - return 0; - } case SIOCSIFADDR: - { - auto& ifru_addr = *reinterpret_cast(&ifreq->ifr_ifru.ifru_addr); - if (ifru_addr.sin_family != AF_INET) - return BAN::Error::from_errno(EADDRNOTAVAIL); - interface->set_ipv4_address(BAN::IPv4Address { ifru_addr.sin_addr.s_addr }); - dprintln("IPv4 address set to {}", interface->get_ipv4_address()); - return 0; - } case SIOCGIFNETMASK: - { - auto& ifru_netmask = *reinterpret_cast(&ifreq->ifr_ifru.ifru_netmask); - ifru_netmask.sin_family = AF_INET; - ifru_netmask.sin_addr.s_addr = interface->get_netmask().raw; - return 0; - } case SIOCSIFNETMASK: - { - auto& ifru_netmask = *reinterpret_cast(&ifreq->ifr_ifru.ifru_netmask); - if (ifru_netmask.sin_family != AF_INET) - return BAN::Error::from_errno(EADDRNOTAVAIL); - interface->set_netmask(BAN::IPv4Address { ifru_netmask.sin_addr.s_addr }); - dprintln("Netmask set to {}", interface->get_netmask()); - return 0; - } case SIOCGIFGWADDR: - { - auto& ifru_gwaddr = *reinterpret_cast(&ifreq->ifr_ifru.ifru_gwaddr); - ifru_gwaddr.sin_family = AF_INET; - ifru_gwaddr.sin_addr.s_addr = interface->get_gateway().raw; - return 0; - } case SIOCSIFGWADDR: - { - auto& ifru_gwaddr = *reinterpret_cast(&ifreq->ifr_ifru.ifru_gwaddr); - if (ifru_gwaddr.sin_family != AF_INET) - return BAN::Error::from_errno(EADDRNOTAVAIL); - interface->set_gateway(BAN::IPv4Address { ifru_gwaddr.sin_addr.s_addr }); - dprintln("Gateway set to {}", interface->get_gateway()); - return 0; - } case SIOCGIFHWADDR: - { - auto mac_address = interface->get_mac_address(); - ifreq->ifr_ifru.ifru_hwaddr.sa_family = AF_INET; - memcpy(ifreq->ifr_ifru.ifru_hwaddr.sa_data, &mac_address, sizeof(mac_address)); - return 0; - } case SIOCGIFNAME: - { - auto& ifrn_name = ifreq->ifr_ifrn.ifrn_name; - ASSERT(interface->name().size() < sizeof(ifrn_name)); - memcpy(ifrn_name, interface->name().data(), interface->name().size()); - ifrn_name[interface->name().size()] = '\0'; - return 0; - } - default: - return BAN::Error::from_errno(EINVAL); + return TRY(interface(nullptr, 0))->ioctl(request, arg); } + + return Socket::ioctl_impl(request, arg); } BAN::ErrorOr NetworkSocket::getsockname_impl(sockaddr* address, socklen_t* address_len)