Kernel/Net: Implement SIOCGIFINDEX and SIOCGIFNAME for sockets

These ioctls exist on Linux and can be used to implement libc functions
if_indextoname and if_nametoindex (without needing to parse any JSON).
This commit is contained in:
Arda Cinar 2023-01-14 00:05:18 +03:00 committed by Sam Atkins
parent 47c21cc349
commit 38dc54317c
Notes: sideshowbarker 2024-07-17 18:23:22 +09:00
3 changed files with 54 additions and 0 deletions

View file

@ -112,6 +112,8 @@ enum IOCtlNumber {
SIOCSIFADDR,
SIOCGIFADDR,
SIOCGIFHWADDR,
SIOCGIFNAME,
SIOCGIFINDEX,
SIOCGIFNETMASK,
SIOCSIFNETMASK,
SIOCGIFBRDADDR,
@ -174,6 +176,8 @@ enum IOCtlNumber {
#define SIOCGIFADDR SIOCGIFADDR
#define SIOCGIFHWADDR SIOCGIFHWADDR
#define SIOCGIFNETMASK SIOCGIFNETMASK
#define SIOCGIFNAME SIOCGIFNAME
#define SIOCGIFINDEX SIOCGIFINDEX
#define SIOCSIFNETMASK SIOCSIFNETMASK
#define SIOCGIFBRDADDR SIOCGIFBRDADDR
#define SIOCGIFMTU SIOCGIFMTU

View file

@ -6,6 +6,7 @@
#include <AK/Singleton.h>
#include <AK/StringBuilder.h>
#include <AK/StringView.h>
#include <Kernel/API/Ioctl.h>
#include <Kernel/API/POSIX/errno.h>
#include <Kernel/Debug.h>
@ -693,10 +694,55 @@ ErrorOr<void> IPv4Socket::ioctl(OpenFileDescription&, unsigned request, Userspac
ifreq ifr;
TRY(copy_from_user(&ifr, user_ifr));
if (request == SIOCGIFNAME) {
// NOTE: Network devices are 1-indexed since index 0 denotes an invalid device
if (ifr.ifr_index == 0)
return EINVAL;
size_t index = 1;
Optional<StringView> result {};
NetworkingManagement::the().for_each([&ifr, &index, &result](auto& adapter) {
if (index == ifr.ifr_index)
result = adapter.name();
++index;
});
if (result.has_value()) {
auto name = result.release_value();
auto succ = name.copy_characters_to_buffer(ifr.ifr_name, IFNAMSIZ);
if (!succ) {
return EFAULT;
}
return copy_to_user(user_ifr, &ifr);
}
return ENODEV;
}
char namebuf[IFNAMSIZ + 1];
memcpy(namebuf, ifr.ifr_name, IFNAMSIZ);
namebuf[sizeof(namebuf) - 1] = '\0';
if (request == SIOCGIFINDEX) {
StringView name { namebuf, strlen(namebuf) };
size_t index = 1;
Optional<size_t> result {};
NetworkingManagement::the().for_each([&name, &index, &result](auto& adapter) {
if (adapter.name() == name)
result = index;
++index;
});
if (result.has_value()) {
ifr.ifr_index = result.release_value();
return copy_to_user(user_ifr, &ifr);
}
return ENODEV;
}
auto adapter = NetworkingManagement::the().lookup_by_name({ namebuf, strlen(namebuf) });
if (!adapter)
return ENODEV;
@ -800,6 +846,8 @@ ErrorOr<void> IPv4Socket::ioctl(OpenFileDescription&, unsigned request, Userspac
case SIOCGIFMTU:
case SIOCGIFFLAGS:
case SIOCGIFCONF:
case SIOCGIFNAME:
case SIOCGIFINDEX:
return ioctl_interface();
case SIOCADDRT:

View file

@ -157,6 +157,8 @@ HANDLE(KEYBOARD_IOCTL_SET_CAPS_LOCK)
HANDLE(SIOCSIFADDR)
HANDLE(SIOCGIFADDR)
HANDLE(SIOCGIFHWADDR)
HANDLE(SIOCGIFNAME)
HANDLE(SIOCGIFINDEX)
HANDLE(SIOCGIFNETMASK)
HANDLE(SIOCSIFNETMASK)
HANDLE(SIOCGIFBRDADDR)