Kernel/LibC: Implement basic ioctl for network addresses

This commit is contained in:
2024-02-03 01:24:55 +02:00
parent c18f72ceb9
commit e1ffbb710b
13 changed files with 132 additions and 2 deletions

View File

@@ -112,6 +112,8 @@ namespace Kernel
BAN::ErrorOr<void> chown(uid_t, gid_t);
bool has_data() const;
BAN::ErrorOr<long> ioctl(int request, void* arg);
protected:
virtual void on_close_impl() {}
@@ -138,6 +140,8 @@ namespace Kernel
virtual BAN::ErrorOr<void> chown_impl(uid_t, gid_t) { return BAN::Error::from_errno(ENOTSUP); }
virtual bool has_data_impl() const { dwarnln("nonblock not supported"); return true; }
virtual BAN::ErrorOr<long> ioctl_impl(int request, void* arg) { return BAN::Error::from_errno(ENOTSUP); }
protected:
mutable RecursivePrioritySpinLock m_lock;

View File

@@ -11,6 +11,9 @@ namespace Kernel
class NetworkInterface : public CharacterDevice
{
BAN_NON_COPYABLE(NetworkInterface);
BAN_NON_MOVABLE(NetworkInterface);
public:
enum class Type
{
@@ -22,7 +25,12 @@ namespace Kernel
virtual ~NetworkInterface() {}
virtual BAN::MACAddress get_mac_address() const = 0;
BAN::IPv4Address get_ipv4_address() const { return m_ipv4_address; }
void set_ipv4_address(BAN::IPv4Address new_address) { m_ipv4_address = new_address; }
BAN::IPv4Address get_netmask() const { return m_netmask; }
void set_netmask(BAN::IPv4Address new_netmask) { m_netmask = new_netmask; }
virtual bool link_up() = 0;
virtual int link_speed() = 0;
@@ -42,6 +50,7 @@ namespace Kernel
char m_name[10];
BAN::IPv4Address m_ipv4_address { 0 };
BAN::IPv4Address m_netmask { 0 };
};
}

View File

@@ -35,6 +35,8 @@ namespace Kernel
virtual BAN::ErrorOr<ssize_t> sendto_impl(const sys_sendto_t*) override;
virtual BAN::ErrorOr<ssize_t> recvfrom_impl(sys_recvfrom_t*) override;
virtual BAN::ErrorOr<long> ioctl_impl(int request, void* arg) override;
protected:
NetworkInterface* m_interface = nullptr;
uint16_t m_port = PORT_NONE;

View File

@@ -117,6 +117,8 @@ namespace Kernel
BAN::ErrorOr<long> sys_sendto(const sys_sendto_t*);
BAN::ErrorOr<long> sys_recvfrom(sys_recvfrom_t*);
BAN::ErrorOr<long> sys_ioctl(int fildes, int request, void* arg);
BAN::ErrorOr<long> sys_pipe(int fildes[2]);
BAN::ErrorOr<long> sys_dup(int fildes);
BAN::ErrorOr<long> sys_dup2(int fildes, int fildes2);

View File

@@ -183,4 +183,10 @@ namespace Kernel
return has_data_impl();
}
BAN::ErrorOr<long> Inode::ioctl(int request, void* arg)
{
LockGuard _(m_lock);
return ioctl_impl(request, arg);
}
}

View File

@@ -2,6 +2,8 @@
#include <kernel/Networking/NetworkManager.h>
#include <kernel/Networking/NetworkSocket.h>
#include <net/if.h>
namespace Kernel
{
@@ -123,4 +125,65 @@ namespace Kernel
return TRY(read_packet(BAN::ByteSpan { reinterpret_cast<uint8_t*>(arguments->buffer), arguments->length }, sender_addr));
}
BAN::ErrorOr<long> NetworkSocket::ioctl_impl(int request, void* arg)
{
if (!arg)
{
dprintln("No argument provided");
return BAN::Error::from_errno(EINVAL);
}
if (m_interface == nullptr)
{
dprintln("No interface bound");
return BAN::Error::from_errno(EADDRNOTAVAIL);
}
auto* ifreq = reinterpret_cast<struct ifreq*>(arg);
switch (request)
{
case SIOCGIFADDR:
{
auto ipv4_address = m_interface->get_ipv4_address();
ifreq->ifr_ifru.ifru_addr.sa_family = AF_INET;
memcpy(ifreq->ifr_ifru.ifru_addr.sa_data, &ipv4_address, sizeof(ipv4_address));
return 0;
}
case SIOCSIFADDR:
{
if (ifreq->ifr_ifru.ifru_addr.sa_family != AF_INET)
return BAN::Error::from_errno(EADDRNOTAVAIL);
BAN::IPv4Address ipv4_address { *reinterpret_cast<uint32_t*>(ifreq->ifr_ifru.ifru_addr.sa_data) };
m_interface->set_ipv4_address(ipv4_address);
dprintln("IPv4 address set to {}", m_interface->get_ipv4_address());
return 0;
}
case SIOCGIFNETMASK:
{
auto netmask_address = m_interface->get_netmask();
ifreq->ifr_ifru.ifru_netmask.sa_family = AF_INET;
memcpy(ifreq->ifr_ifru.ifru_netmask.sa_data, &netmask_address, sizeof(netmask_address));
return 0;
}
case SIOCSIFNETMASK:
{
if (ifreq->ifr_ifru.ifru_netmask.sa_family != AF_INET)
return BAN::Error::from_errno(EADDRNOTAVAIL);
BAN::IPv4Address netmask { *reinterpret_cast<uint32_t*>(ifreq->ifr_ifru.ifru_netmask.sa_data) };
m_interface->set_netmask(netmask);
dprintln("Netmask set to {}", m_interface->get_netmask());
return 0;
}
case SIOCGIFHWADDR:
{
auto mac_address = m_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;
}
default:
return BAN::Error::from_errno(EINVAL);
}
}
}

View File

@@ -952,6 +952,13 @@ namespace Kernel
return TRY(inode->recvfrom(arguments));
}
BAN::ErrorOr<long> Process::sys_ioctl(int fildes, int request, void* arg)
{
LockGuard _(m_lock);
auto inode = TRY(m_open_file_descriptors.inode_of(fildes));
return TRY(inode->ioctl(request, arg));
}
BAN::ErrorOr<long> Process::sys_pipe(int fildes[2])
{
LockGuard _(m_lock);

View File

@@ -225,6 +225,9 @@ namespace Kernel
case SYS_RECVFROM:
ret = Process::current().sys_recvfrom((sys_recvfrom_t*)arg1);
break;
case SYS_IOCTL:
ret = Process::current().sys_ioctl((int)arg1, (int)arg2, (void*)arg3);
break;
default:
dwarnln("Unknown syscall {}", syscall);
break;