From e1ffbb710bda86a7df486e0bb0bd1062bc4c3e92 Mon Sep 17 00:00:00 2001 From: Bananymous Date: Sat, 3 Feb 2024 01:24:55 +0200 Subject: [PATCH] Kernel/LibC: Implement basic ioctl for network addresses --- kernel/include/kernel/FS/Inode.h | 4 ++ .../kernel/Networking/NetworkInterface.h | 9 +++ .../include/kernel/Networking/NetworkSocket.h | 2 + kernel/include/kernel/Process.h | 2 + kernel/kernel/FS/Inode.cpp | 6 ++ kernel/kernel/Networking/NetworkSocket.cpp | 63 +++++++++++++++++++ kernel/kernel/Process.cpp | 7 +++ kernel/kernel/Syscall.cpp | 3 + libc/CMakeLists.txt | 1 + libc/include/net/if.h | 18 ++++++ libc/include/stropts.h | 4 +- libc/include/sys/syscall.h | 1 + libc/stropts.cpp | 14 +++++ 13 files changed, 132 insertions(+), 2 deletions(-) create mode 100644 libc/stropts.cpp diff --git a/kernel/include/kernel/FS/Inode.h b/kernel/include/kernel/FS/Inode.h index e21f742d..e7be1c33 100644 --- a/kernel/include/kernel/FS/Inode.h +++ b/kernel/include/kernel/FS/Inode.h @@ -112,6 +112,8 @@ namespace Kernel BAN::ErrorOr chown(uid_t, gid_t); bool has_data() const; + BAN::ErrorOr ioctl(int request, void* arg); + protected: virtual void on_close_impl() {} @@ -138,6 +140,8 @@ namespace Kernel virtual BAN::ErrorOr 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 ioctl_impl(int request, void* arg) { return BAN::Error::from_errno(ENOTSUP); } + protected: mutable RecursivePrioritySpinLock m_lock; diff --git a/kernel/include/kernel/Networking/NetworkInterface.h b/kernel/include/kernel/Networking/NetworkInterface.h index 5224fd6f..83efcf28 100644 --- a/kernel/include/kernel/Networking/NetworkInterface.h +++ b/kernel/include/kernel/Networking/NetworkInterface.h @@ -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 }; }; } diff --git a/kernel/include/kernel/Networking/NetworkSocket.h b/kernel/include/kernel/Networking/NetworkSocket.h index 05fcd3dc..587d4a46 100644 --- a/kernel/include/kernel/Networking/NetworkSocket.h +++ b/kernel/include/kernel/Networking/NetworkSocket.h @@ -35,6 +35,8 @@ namespace Kernel virtual BAN::ErrorOr sendto_impl(const sys_sendto_t*) override; virtual BAN::ErrorOr recvfrom_impl(sys_recvfrom_t*) override; + virtual BAN::ErrorOr ioctl_impl(int request, void* arg) override; + protected: NetworkInterface* m_interface = nullptr; uint16_t m_port = PORT_NONE; diff --git a/kernel/include/kernel/Process.h b/kernel/include/kernel/Process.h index e7437a2d..70eb7946 100644 --- a/kernel/include/kernel/Process.h +++ b/kernel/include/kernel/Process.h @@ -117,6 +117,8 @@ namespace Kernel BAN::ErrorOr sys_sendto(const sys_sendto_t*); BAN::ErrorOr sys_recvfrom(sys_recvfrom_t*); + BAN::ErrorOr sys_ioctl(int fildes, int request, void* arg); + BAN::ErrorOr sys_pipe(int fildes[2]); BAN::ErrorOr sys_dup(int fildes); BAN::ErrorOr sys_dup2(int fildes, int fildes2); diff --git a/kernel/kernel/FS/Inode.cpp b/kernel/kernel/FS/Inode.cpp index 589f3eaa..c3cbaea6 100644 --- a/kernel/kernel/FS/Inode.cpp +++ b/kernel/kernel/FS/Inode.cpp @@ -183,4 +183,10 @@ namespace Kernel return has_data_impl(); } + BAN::ErrorOr Inode::ioctl(int request, void* arg) + { + LockGuard _(m_lock); + return ioctl_impl(request, arg); + } + } diff --git a/kernel/kernel/Networking/NetworkSocket.cpp b/kernel/kernel/Networking/NetworkSocket.cpp index 1a6bb664..b37b612d 100644 --- a/kernel/kernel/Networking/NetworkSocket.cpp +++ b/kernel/kernel/Networking/NetworkSocket.cpp @@ -2,6 +2,8 @@ #include #include +#include + namespace Kernel { @@ -123,4 +125,65 @@ namespace Kernel return TRY(read_packet(BAN::ByteSpan { reinterpret_cast(arguments->buffer), arguments->length }, sender_addr)); } + BAN::ErrorOr 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(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(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(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); + } + } + } diff --git a/kernel/kernel/Process.cpp b/kernel/kernel/Process.cpp index 82b328a2..6ba65d9e 100644 --- a/kernel/kernel/Process.cpp +++ b/kernel/kernel/Process.cpp @@ -952,6 +952,13 @@ namespace Kernel return TRY(inode->recvfrom(arguments)); } + BAN::ErrorOr 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 Process::sys_pipe(int fildes[2]) { LockGuard _(m_lock); diff --git a/kernel/kernel/Syscall.cpp b/kernel/kernel/Syscall.cpp index c2f59cef..fba41523 100644 --- a/kernel/kernel/Syscall.cpp +++ b/kernel/kernel/Syscall.cpp @@ -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; diff --git a/libc/CMakeLists.txt b/libc/CMakeLists.txt index 0d3fc235..ae5461bb 100644 --- a/libc/CMakeLists.txt +++ b/libc/CMakeLists.txt @@ -17,6 +17,7 @@ set(LIBC_SOURCES stdlib.cpp string.cpp strings.cpp + stropts.cpp sys/banan-os.cpp sys/mman.cpp sys/socket.cpp diff --git a/libc/include/net/if.h b/libc/include/net/if.h index 8a2664f4..89600f46 100644 --- a/libc/include/net/if.h +++ b/libc/include/net/if.h @@ -5,6 +5,8 @@ #include +#include + #define IF_NAMESIZE 16 __BEGIN_DECLS @@ -15,6 +17,22 @@ struct if_nameindex char* if_name; /* Null-terminated name of the interface. */ }; +struct ifreq +{ + union { + struct sockaddr ifru_addr; + struct sockaddr ifru_netmask; + struct sockaddr ifru_hwaddr; + unsigned char __min_storage[sizeof(sockaddr) + 6]; + } ifr_ifru; +}; + +#define SIOCGIFADDR 1 /* Get interface address */ +#define SIOCSIFADDR 2 /* Set interface address */ +#define SIOCGIFNETMASK 3 /* Get network mask */ +#define SIOCSIFNETMASK 4 /* Set network mask */ +#define SIOCGIFHWADDR 5 /* Get hardware address */ + void if_freenameindex(struct if_nameindex* ptr); char* if_indextoname(unsigned ifindex, char* ifname); struct if_nameindex* if_nameindex(void); diff --git a/libc/include/stropts.h b/libc/include/stropts.h index 4e2a810f..08ece53a 100644 --- a/libc/include/stropts.h +++ b/libc/include/stropts.h @@ -11,8 +11,8 @@ __BEGIN_DECLS #define __need_gid_t #include -typedef uint32_t t_uscalar_t; -typedef int32_t t_scalar_t; +typedef __UINT32_TYPE__ t_uscalar_t; +typedef __INT32_TYPE__ t_scalar_t; struct bandinfo { diff --git a/libc/include/sys/syscall.h b/libc/include/sys/syscall.h index 4fb51cf5..10a7e26a 100644 --- a/libc/include/sys/syscall.h +++ b/libc/include/sys/syscall.h @@ -67,6 +67,7 @@ __BEGIN_DECLS #define SYS_BIND 66 #define SYS_SENDTO 67 #define SYS_RECVFROM 68 +#define SYS_IOCTL 69 __END_DECLS diff --git a/libc/stropts.cpp b/libc/stropts.cpp new file mode 100644 index 00000000..4c14c421 --- /dev/null +++ b/libc/stropts.cpp @@ -0,0 +1,14 @@ +#include +#include +#include +#include + +int ioctl(int fildes, int request, ...) +{ + va_list args; + va_start(args, request); + void* extra = va_arg(args, void*); + va_end(args); + + return syscall(SYS_IOCTL, fildes, request, extra); +}