From f804e87f7deb8c4bd80603f77969459c97e8a8b2 Mon Sep 17 00:00:00 2001 From: Bananymous Date: Mon, 5 Feb 2024 17:38:57 +0200 Subject: [PATCH] Kernel: Implement basic gateway for network interfaces --- .../kernel/Networking/NetworkInterface.h | 4 ++++ kernel/kernel/Networking/ARPTable.cpp | 3 +++ kernel/kernel/Networking/NetworkSocket.cpp | 16 ++++++++++++++ libc/include/net/if.h | 5 ++++- userspace/dhcp-client/main.cpp | 21 +++++++++++++++++-- 5 files changed, 46 insertions(+), 3 deletions(-) diff --git a/kernel/include/kernel/Networking/NetworkInterface.h b/kernel/include/kernel/Networking/NetworkInterface.h index b23c3c1402..50ff40fdc3 100644 --- a/kernel/include/kernel/Networking/NetworkInterface.h +++ b/kernel/include/kernel/Networking/NetworkInterface.h @@ -46,6 +46,9 @@ namespace Kernel BAN::IPv4Address get_netmask() const { return m_netmask; } void set_netmask(BAN::IPv4Address new_netmask) { m_netmask = new_netmask; } + BAN::IPv4Address get_gateway() const { return m_gateway; } + void set_gateway(BAN::IPv4Address new_gateway) { m_gateway = new_gateway; } + virtual bool link_up() = 0; virtual int link_speed() = 0; @@ -65,6 +68,7 @@ namespace Kernel BAN::IPv4Address m_ipv4_address { 0 }; BAN::IPv4Address m_netmask { 0 }; + BAN::IPv4Address m_gateway { 0 }; }; } diff --git a/kernel/kernel/Networking/ARPTable.cpp b/kernel/kernel/Networking/ARPTable.cpp index b9f23842e7..ba98a5a3e3 100644 --- a/kernel/kernel/Networking/ARPTable.cpp +++ b/kernel/kernel/Networking/ARPTable.cpp @@ -45,6 +45,9 @@ namespace Kernel if (ipv4_address == s_broadcast_ipv4) return s_broadcast_mac; + if (interface.get_ipv4_address().mask(interface.get_netmask()) != ipv4_address.mask(interface.get_netmask())) + ipv4_address = interface.get_gateway(); + { LockGuard _(m_lock); if (m_arp_table.contains(ipv4_address)) diff --git a/kernel/kernel/Networking/NetworkSocket.cpp b/kernel/kernel/Networking/NetworkSocket.cpp index 5c5618bd7b..e0943e0f51 100644 --- a/kernel/kernel/Networking/NetworkSocket.cpp +++ b/kernel/kernel/Networking/NetworkSocket.cpp @@ -171,6 +171,22 @@ namespace Kernel dprintln("Netmask set to {}", m_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 = m_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); + m_interface->set_gateway(BAN::IPv4Address { ifru_gwaddr.sin_addr.s_addr }); + dprintln("Gateway set to {}", m_interface->get_gateway()); + return 0; + } case SIOCGIFHWADDR: { auto mac_address = m_interface->get_mac_address(); diff --git a/libc/include/net/if.h b/libc/include/net/if.h index 89600f4600..39de6da224 100644 --- a/libc/include/net/if.h +++ b/libc/include/net/if.h @@ -22,6 +22,7 @@ struct ifreq union { struct sockaddr ifru_addr; struct sockaddr ifru_netmask; + struct sockaddr ifru_gwaddr; struct sockaddr ifru_hwaddr; unsigned char __min_storage[sizeof(sockaddr) + 6]; } ifr_ifru; @@ -31,7 +32,9 @@ struct ifreq #define SIOCSIFADDR 2 /* Set interface address */ #define SIOCGIFNETMASK 3 /* Get network mask */ #define SIOCSIFNETMASK 4 /* Set network mask */ -#define SIOCGIFHWADDR 5 /* Get hardware address */ +#define SIOCGIFGWADDR 5 /* Get gateway address */ +#define SIOCSIFGWADDR 6 /* Set gateway address */ +#define SIOCGIFHWADDR 7 /* Get hardware address */ void if_freenameindex(struct if_nameindex* ptr); char* if_indextoname(unsigned ifindex, char* ifname); diff --git a/userspace/dhcp-client/main.cpp b/userspace/dhcp-client/main.cpp index 88a522029e..3e01cd90d9 100644 --- a/userspace/dhcp-client/main.cpp +++ b/userspace/dhcp-client/main.cpp @@ -73,7 +73,7 @@ BAN::MACAddress get_mac_address(int socket) return mac_address; } -void update_ipv4_info(int socket, BAN::IPv4Address address, BAN::IPv4Address subnet) +void update_ipv4_info(int socket, BAN::IPv4Address address, BAN::IPv4Address netmask, BAN::IPv4Address gateway) { { ifreq ifreq; @@ -98,6 +98,19 @@ void update_ipv4_info(int socket, BAN::IPv4Address address, BAN::IPv4Address sub exit(1); } } + + if (gateway.raw) + { + ifreq ifreq; + auto& ifru_gwaddr = *reinterpret_cast(&ifreq.ifr_ifru.ifru_gwaddr); + ifru_gwaddr.sin_family = AF_INET; + ifru_gwaddr.sin_addr.s_addr = gateway.raw; + if (ioctl(socket, SIOCSIFGWADDR, &ifreq) == -1) + { + perror("ioctl"); + exit(1); + } + } } void send_dhcp_packet(int socket, const DHCPPacket& dhcp_packet, BAN::IPv4Address server_ipv4) @@ -359,7 +372,11 @@ int main() return 1; } - update_ipv4_info(socket, dhcp_ack->address, dhcp_ack->subnet); + BAN::IPv4Address gateway { 0 }; + if (!dhcp_ack->routers.empty()) + gateway = dhcp_ack->routers.front(); + + update_ipv4_info(socket, dhcp_ack->address, dhcp_ack->subnet, gateway); close(socket);