diff --git a/kernel/include/net/arp_layer.hpp b/kernel/include/net/arp_layer.hpp index c5cb2c13..c375503c 100644 --- a/kernel/include/net/arp_layer.hpp +++ b/kernel/include/net/arp_layer.hpp @@ -36,8 +36,24 @@ network::ip::address ip2_to_ip(uint16_t* source_ip); void mac64_to_mac3(uint64_t source_mac, uint16_t* mac); void ip_to_ip2(network::ip::address source_ip, uint16_t* ip); -void decode(network::interface_descriptor& interface, network::ethernet::packet& packet); +struct layer { + layer(network::ethernet::layer* parent); + /*! + * \brief Decode a network packet. + * + * This must only be called from the ethernet layer. + * + * \param interface The interface on which the packet was received + * \param packet The packet to decode + */ + void decode(network::interface_descriptor& interface, network::ethernet::packet& packet); + +private: + network::ethernet::layer* parent; +}; + +//TODO Move void wait_for_reply(); void wait_for_reply(size_t ms); diff --git a/kernel/include/net/ethernet_layer.hpp b/kernel/include/net/ethernet_layer.hpp index 9e2bc43f..3b07d757 100644 --- a/kernel/include/net/ethernet_layer.hpp +++ b/kernel/include/net/ethernet_layer.hpp @@ -16,6 +16,14 @@ namespace network { +namespace arp { +struct layer; +} + +namespace ip { +struct layer; +} + namespace ethernet { static_assert(sizeof(address) == 6, "The size of a MAC address is 6 bytes"); @@ -24,40 +32,49 @@ static_assert(sizeof(header) == 14, "The size of the Ethernet header is 14 bytes uint64_t mac6_to_mac64(const char* mac); void mac64_to_mac6(uint64_t input, char* mac); -/*! - * \brief Decode a network packet. - * - * This must only be called from the network interface. - * - * \param interface The interface on which the packet was received - * \param packet The packet to decode - */ -void decode(network::interface_descriptor& interface, packet& packet); +struct layer { + /*! + * \brief Decode a network packet. + * + * This must only be called from the network interface. + * + * \param interface The interface on which the packet was received + * \param packet The packet to decode + */ + void decode(network::interface_descriptor& interface, packet& packet); -/*! - * \brief Prepare a packet for the kernel - * \param interface The interface on which to prepare the packet for - * \param descriptor The packet descriptor - * \return the prepared packet or an error - */ -std::expected kernel_prepare_packet(network::interface_descriptor& interface, const packet_descriptor& descriptor); + /*! + * \brief Prepare a packet for the kernel + * \param interface The interface on which to prepare the packet for + * \param descriptor The packet descriptor + * \return the prepared packet or an error + */ + std::expected kernel_prepare_packet(network::interface_descriptor& interface, const packet_descriptor& descriptor); -/*! - * \brief Prepare a packet for the user - * \param buffer The buffer to write the packet to - * \param interface The interface on which to prepare the packet for - * \param descriptor The packet descriptor - * \return the prepared packet or an error - */ -std::expected user_prepare_packet(char* buffer, network::interface_descriptor& interface, const packet_descriptor* descriptor); + /*! + * \brief Prepare a packet for the user + * \param buffer The buffer to write the packet to + * \param interface The interface on which to prepare the packet for + * \param descriptor The packet descriptor + * \return the prepared packet or an error + */ + std::expected user_prepare_packet(char* buffer, network::interface_descriptor& interface, const packet_descriptor* descriptor); -/*! - * \brief Finalize a prepared packet - * \param interface The interface on which to finalize the packet - * \param p The packet to finalize - * \return nothing or an error - */ -std::expected finalize_packet(network::interface_descriptor& interface, packet& p); + /*! + * \brief Finalize a prepared packet + * \param interface The interface on which to finalize the packet + * \param p The packet to finalize + * \return nothing or an error + */ + std::expected finalize_packet(network::interface_descriptor& interface, packet& p); + + void register_arp_layer(network::arp::layer* layer); + void register_ip_layer(network::ip::layer* layer); + +private: + network::arp::layer* arp_layer; + network::ip::layer* ip_layer; +}; } // end of ethernet namespace diff --git a/kernel/include/net/icmp_layer.hpp b/kernel/include/net/icmp_layer.hpp index 1efa28d3..e9dd349b 100644 --- a/kernel/include/net/icmp_layer.hpp +++ b/kernel/include/net/icmp_layer.hpp @@ -18,44 +18,55 @@ namespace network { +namespace ip { +struct layer; +} + namespace icmp { static_assert(sizeof(echo_request_header) == sizeof(header::rest), "Invalid size for echo request header"); -/*! - * \brief Decode a network packet. - * - * This must only be called from the ip layer. - * - * \param interface The interface on which the packet was received - * \param packet The packet to decode - */ -void decode(network::interface_descriptor& interface, network::ethernet::packet& packet); +struct layer { + layer(network::ip::layer* parent); -/*! - * \brief Prepare a packet for the kernel - * \param interface The interface on which to prepare the packet for - * \param descriptor The packet descriptor - * \return the prepared packet or an error - */ -std::expected kernel_prepare_packet(network::interface_descriptor& interface, const packet_descriptor& descriptor); + /*! + * \brief Decode a network packet. + * + * This must only be called from the ip layer. + * + * \param interface The interface on which the packet was received + * \param packet The packet to decode + */ + void decode(network::interface_descriptor& interface, network::ethernet::packet& packet); -/*! - * \brief Prepare a packet for the user - * \param buffer The buffer to write the packet to - * \param interface The interface on which to prepare the packet for - * \param descriptor The packet descriptor - * \return the prepared packet or an error - */ -std::expected user_prepare_packet(char* buffer, network::socket& sock, const packet_descriptor* descriptor); + /*! + * \brief Prepare a packet for the kernel + * \param interface The interface on which to prepare the packet for + * \param descriptor The packet descriptor + * \return the prepared packet or an error + */ + std::expected kernel_prepare_packet(network::interface_descriptor& interface, const packet_descriptor& descriptor); -/*! - * \brief Finalize a prepared packet - * \param interface The interface on which to finalize the packet - * \param p The packet to finalize - * \return nothing or an error - */ -std::expected finalize_packet(network::interface_descriptor& interface, network::ethernet::packet& p); + /*! + * \brief Prepare a packet for the user + * \param buffer The buffer to write the packet to + * \param interface The interface on which to prepare the packet for + * \param descriptor The packet descriptor + * \return the prepared packet or an error + */ + std::expected user_prepare_packet(char* buffer, network::socket& sock, const packet_descriptor* descriptor); + + /*! + * \brief Finalize a prepared packet + * \param interface The interface on which to finalize the packet + * \param p The packet to finalize + * \return nothing or an error + */ + std::expected finalize_packet(network::interface_descriptor& interface, network::ethernet::packet& p); + +private: + network::ip::layer* parent; +}; } // end of icmp namespace diff --git a/kernel/include/net/ip_layer.hpp b/kernel/include/net/ip_layer.hpp index 92e4b361..f815262c 100644 --- a/kernel/include/net/ip_layer.hpp +++ b/kernel/include/net/ip_layer.hpp @@ -16,6 +16,10 @@ namespace network { +namespace icmp { +struct layer; +} + namespace ip { address ip32_to_ip(uint32_t raw); @@ -26,40 +30,51 @@ bool same_network(address ip, address test); static_assert(sizeof(header) == 20, "The size of an IPv4 header must be 20 bytes"); -/*! - * \brief Decode a network packet. - * - * This must only be called from the ethernet layer. - * - * \param interface The interface on which the packet was received - * \param packet The packet to decode - */ -void decode(network::interface_descriptor& interface, network::ethernet::packet& packet); +struct layer { + layer(network::ethernet::layer* parent); -/*! - * \brief Prepare a packet for the kernel - * \param interface The interface on which to prepare the packet for - * \param descriptor The packet descriptor - * \return the prepared packet or an error - */ -std::expected kernel_prepare_packet(network::interface_descriptor& interface, const packet_descriptor& desc); + /*! + * \brief Decode a network packet. + * + * This must only be called from the ethernet layer. + * + * \param interface The interface on which the packet was received + * \param packet The packet to decode + */ + void decode(network::interface_descriptor& interface, network::ethernet::packet& packet); -/*! - * \brief Prepare a packet for the user - * \param buffer The buffer to write the packet to - * \param interface The interface on which to prepare the packet for - * \param descriptor The packet descriptor - * \return the prepared packet or an error - */ -std::expected user_prepare_packet(char* buffer, network::interface_descriptor& interface, const packet_descriptor* desc); + /*! + * \brief Prepare a packet for the kernel + * \param interface The interface on which to prepare the packet for + * \param descriptor The packet descriptor + * \return the prepared packet or an error + */ + std::expected kernel_prepare_packet(network::interface_descriptor& interface, const packet_descriptor& desc); -/*! - * \brief Finalize a prepared packet - * \param interface The interface on which to finalize the packet - * \param p The packet to finalize - * \return nothing or an error - */ -std::expected finalize_packet(network::interface_descriptor& interface, network::ethernet::packet& p); + /*! + * \brief Prepare a packet for the user + * \param buffer The buffer to write the packet to + * \param interface The interface on which to prepare the packet for + * \param descriptor The packet descriptor + * \return the prepared packet or an error + */ + std::expected user_prepare_packet(char* buffer, network::interface_descriptor& interface, const packet_descriptor* desc); + + /*! + * \brief Finalize a prepared packet + * \param interface The interface on which to finalize the packet + * \param p The packet to finalize + * \return nothing or an error + */ + std::expected finalize_packet(network::interface_descriptor& interface, network::ethernet::packet& p); + + void register_icmp_layer(network::icmp::layer* layer); + +private: + network::ethernet::layer* parent; + + network::icmp::layer* icmp_layer; +}; } // end of ip namespace diff --git a/kernel/src/net/arp_layer.cpp b/kernel/src/net/arp_layer.cpp index 703b097b..4fe111b4 100644 --- a/kernel/src/net/arp_layer.cpp +++ b/kernel/src/net/arp_layer.cpp @@ -60,7 +60,11 @@ void network::arp::ip_to_ip2(network::ip::address source_ip, uint16_t* ip){ } } -void network::arp::decode(network::interface_descriptor& interface, network::ethernet::packet& packet){ +network::arp::layer::layer(network::ethernet::layer* parent) : parent(parent) { + parent->register_arp_layer(this); +} + +void network::arp::layer::decode(network::interface_descriptor& interface, network::ethernet::packet& packet){ packet.tag(1, packet.index); header* arp_header = reinterpret_cast(packet.payload + packet.index); @@ -122,7 +126,7 @@ void network::arp::decode(network::interface_descriptor& interface, network::eth // Ask the ethernet layer to craft a packet network::ethernet::packet_descriptor desc{sizeof(header), source_hw, ethernet::ether_type::ARP}; - auto packet = network::ethernet::kernel_prepare_packet(interface, desc); + auto packet = parent->kernel_prepare_packet(interface, desc); if(packet){ auto* arp_reply_header = reinterpret_cast(packet->payload + packet->index); @@ -140,7 +144,7 @@ void network::arp::decode(network::interface_descriptor& interface, network::eth std::copy_n(arp_header->target_protocol_addr, 2, arp_reply_header->source_protocol_addr); std::copy_n(arp_header->source_protocol_addr, 2, arp_reply_header->target_protocol_addr); - network::ethernet::finalize_packet(interface, *packet); + parent->finalize_packet(interface, *packet); } else { logging::logf(logging::log_level::ERROR, "arp: Impossible to reply to ARP Request: %s\n", std::error_message(packet.error())); diff --git a/kernel/src/net/ethernet_layer.cpp b/kernel/src/net/ethernet_layer.cpp index 32c35cd5..226b0c6c 100644 --- a/kernel/src/net/ethernet_layer.cpp +++ b/kernel/src/net/ethernet_layer.cpp @@ -81,7 +81,7 @@ void network::ethernet::mac64_to_mac6(uint64_t source_mac, char* mac){ } } -void network::ethernet::decode(network::interface_descriptor& interface, packet& packet){ +void network::ethernet::layer::decode(network::interface_descriptor& interface, packet& packet){ logging::logf(logging::log_level::TRACE, "ethernet: Start decoding new packet\n"); header* ether_header = reinterpret_cast(packet.payload); @@ -102,19 +102,23 @@ void network::ethernet::decode(network::interface_descriptor& interface, packet& packet.type = decode_ether_type(ether_header); packet.index += sizeof(header); - switch(packet.type){ + switch (packet.type) { case ether_type::IPV4: - network::ip::decode(interface, packet); + ip_layer->decode(interface, packet); break; + + case ether_type::ARP: + arp_layer->decode(interface, packet); + break; + case ether_type::IPV6: logging::logf(logging::log_level::TRACE, "ethernet: IPV6 Packet (unsupported)\n"); break; - case ether_type::ARP: - network::arp::decode(interface, packet); - break; + case ether_type::UNKNOWN: logging::logf(logging::log_level::TRACE, "ethernet: Unhandled Packet Type: %u\n", uint64_t(switch_endian_16(ether_header->type))); break; + default: logging::logf(logging::log_level::ERROR, "ethernet: Unhandled Packet Type in switch: %u\n", uint64_t(switch_endian_16(ether_header->type))); break; @@ -123,7 +127,7 @@ void network::ethernet::decode(network::interface_descriptor& interface, packet& logging::logf(logging::log_level::TRACE, "ethernet: Finished decoding packet\n"); } -std::expected network::ethernet::kernel_prepare_packet(network::interface_descriptor& interface, const packet_descriptor& descriptor){ +std::expected network::ethernet::layer::kernel_prepare_packet(network::interface_descriptor& interface, const packet_descriptor& descriptor){ auto total_size = descriptor.size + sizeof(header); network::ethernet::packet p(new char[total_size], total_size); @@ -133,7 +137,7 @@ std::expected network::ethernet::kernel_prepare_packe return p; } -std::expected network::ethernet::user_prepare_packet(char* buffer, network::interface_descriptor& interface, const packet_descriptor* descriptor){ +std::expected network::ethernet::layer::user_prepare_packet(char* buffer, network::interface_descriptor& interface, const packet_descriptor* descriptor){ auto total_size = descriptor->size + sizeof(header); network::ethernet::packet p(buffer, total_size); @@ -144,7 +148,7 @@ std::expected network::ethernet::user_prepare_packet( return p; } -std::expected network::ethernet::finalize_packet(network::interface_descriptor& interface, packet& p){ +std::expected network::ethernet::layer::finalize_packet(network::interface_descriptor& interface, packet& p){ if(p.user){ // The packet will be handled by a kernel thread, needs to // be copied to kernel memory diff --git a/kernel/src/net/icmp_layer.cpp b/kernel/src/net/icmp_layer.cpp index f85f6309..b0f3feb3 100644 --- a/kernel/src/net/icmp_layer.cpp +++ b/kernel/src/net/icmp_layer.cpp @@ -54,7 +54,7 @@ void prepare_packet(network::ethernet::packet& packet, network::icmp::type t, si } // end of anonymous namespace -void network::icmp::decode(network::interface_descriptor& interface, network::ethernet::packet& packet){ +void network::icmp::layer::decode(network::interface_descriptor& interface, network::ethernet::packet& packet){ packet.tag(2, packet.index); logging::logf(logging::log_level::TRACE, "icmp: Start ICMP packet handling\n"); @@ -80,7 +80,7 @@ void network::icmp::decode(network::interface_descriptor& interface, network::et logging::logf(logging::log_level::TRACE, "icmp: Reply to Echo Request for own IP\n"); network::icmp::packet_descriptor desc{0, source_ip, type::ECHO_REPLY, 0x0}; - auto reply_packet = network::icmp::kernel_prepare_packet(interface, desc); + auto reply_packet = kernel_prepare_packet(interface, desc); if(reply_packet){ auto* command_header = reinterpret_cast(packet.payload + command_index); @@ -91,7 +91,7 @@ void network::icmp::decode(network::interface_descriptor& interface, network::et logging::logf(logging::log_level::ERROR, "icmp: Failed to reply: %s\n", std::error_message(reply_packet.error())); } - network::icmp::finalize_packet(interface, *reply_packet); + finalize_packet(interface, *reply_packet); } break; @@ -113,10 +113,10 @@ void network::icmp::decode(network::interface_descriptor& interface, network::et network::propagate_packet(packet, network::socket_protocol::ICMP); } -std::expected network::icmp::kernel_prepare_packet(network::interface_descriptor& interface, const packet_descriptor& descriptor){ +std::expected network::icmp::layer::kernel_prepare_packet(network::interface_descriptor& interface, const packet_descriptor& descriptor){ // Ask the IP layer to craft a packet network::ip::packet_descriptor desc{sizeof(header) + descriptor.payload_size, descriptor.target_ip, 0x01}; - auto packet = network::ip::kernel_prepare_packet(interface, desc); + auto packet = parent->kernel_prepare_packet(interface, desc); if(packet){ ::prepare_packet(*packet, descriptor.type, descriptor.code); @@ -125,12 +125,12 @@ std::expected network::icmp::kernel_prepare_packet(ne return packet; } -std::expected network::icmp::user_prepare_packet(char* buffer, network::socket& /*socket*/, const packet_descriptor* descriptor){ +std::expected network::icmp::layer::user_prepare_packet(char* buffer, network::socket& /*socket*/, const packet_descriptor* descriptor){ auto& interface = network::select_interface(descriptor->target_ip); // Ask the IP layer to craft a packet network::ip::packet_descriptor desc{sizeof(header) + descriptor->payload_size, descriptor->target_ip, 0x01}; - auto packet = network::ip::user_prepare_packet(buffer, interface, &desc); + auto packet = parent->user_prepare_packet(buffer, interface, &desc); if(packet){ ::prepare_packet(*packet, descriptor->type, descriptor->code); @@ -139,7 +139,7 @@ std::expected network::icmp::user_prepare_packet(char return packet; } -std::expected network::icmp::finalize_packet(network::interface_descriptor& interface, network::ethernet::packet& packet){ +std::expected network::icmp::layer::finalize_packet(network::interface_descriptor& interface, network::ethernet::packet& packet){ packet.index -= sizeof(header) - sizeof(uint32_t); auto* icmp_header = reinterpret_cast(packet.payload + packet.index); @@ -148,5 +148,5 @@ std::expected network::icmp::finalize_packet(network::interface_descriptor compute_checksum(icmp_header, 0); // Give the packet to the IP layer for finalization - return network::ip::finalize_packet(interface, packet); + return parent->finalize_packet(interface, packet); } diff --git a/kernel/src/net/ip_layer.cpp b/kernel/src/net/ip_layer.cpp index e9727f66..5b3667c5 100644 --- a/kernel/src/net/ip_layer.cpp +++ b/kernel/src/net/ip_layer.cpp @@ -119,7 +119,11 @@ bool network::ip::same_network(address ip, address test) { return ip(0) == test(0) && ip(1) == test(1) && ip(2) == test(2); } -void network::ip::decode(network::interface_descriptor& interface, network::ethernet::packet& packet){ +network::ip::layer::layer(network::ethernet::layer* parent) : parent(parent) { + parent->register_ip_layer(this); +} + +void network::ip::layer::decode(network::interface_descriptor& interface, network::ethernet::packet& packet){ packet.tag(1, packet.index); header* ip_header = reinterpret_cast(packet.payload + packet.index); @@ -154,7 +158,7 @@ void network::ip::decode(network::interface_descriptor& interface, network::ethe packet.index += header_length; if (protocol == 0x01) { - network::icmp::decode(interface, packet); + icmp_layer->decode(interface, packet); } else if (protocol == 0x06) { network::tcp::decode(interface, packet); } else if (protocol == 0x11) { @@ -164,7 +168,7 @@ void network::ip::decode(network::interface_descriptor& interface, network::ethe } } -std::expected network::ip::kernel_prepare_packet(network::interface_descriptor& interface, const packet_descriptor& descriptor){ +std::expected network::ip::layer::kernel_prepare_packet(network::interface_descriptor& interface, const packet_descriptor& descriptor){ auto target_mac = get_target_mac(interface, descriptor.destination); if(!target_mac){ @@ -173,7 +177,7 @@ std::expected network::ip::kernel_prepare_packet(netw // Ask the ethernet layer to craft a packet network::ethernet::packet_descriptor desc{descriptor.size + default_ip_header_len, *target_mac, ethernet::ether_type::IPV4}; - auto packet = network::ethernet::kernel_prepare_packet(interface, desc); + auto packet = parent->kernel_prepare_packet(interface, desc); if(packet){ ::prepare_packet(*packet, interface, descriptor.size, descriptor.destination, descriptor.protocol); @@ -182,7 +186,7 @@ std::expected network::ip::kernel_prepare_packet(netw return packet; } -std::expected network::ip::user_prepare_packet(char* buffer, network::interface_descriptor& interface, const packet_descriptor* descriptor){ +std::expected network::ip::layer::user_prepare_packet(char* buffer, network::interface_descriptor& interface, const packet_descriptor* descriptor){ auto target_mac = get_target_mac(interface, descriptor->destination); if(!target_mac){ @@ -191,7 +195,7 @@ std::expected network::ip::user_prepare_packet(char* // Ask the ethernet layer to craft a packet network::ethernet::packet_descriptor desc{descriptor->size + default_ip_header_len, *target_mac, ethernet::ether_type::IPV4}; - auto packet = network::ethernet::user_prepare_packet(buffer, interface, &desc); + auto packet = parent->user_prepare_packet(buffer, interface, &desc); if(packet){ ::prepare_packet(*packet, interface, descriptor->size, descriptor->destination, descriptor->protocol); @@ -200,7 +204,7 @@ std::expected network::ip::user_prepare_packet(char* return packet; } -std::expected network::ip::finalize_packet(network::interface_descriptor& interface, network::ethernet::packet& p){ +std::expected network::ip::layer::finalize_packet(network::interface_descriptor& interface, network::ethernet::packet& p){ // Send the packet to the ethernet layer - return network::ethernet::finalize_packet(interface, p); + return parent->finalize_packet(interface, p); } diff --git a/kernel/src/net/network.cpp b/kernel/src/net/network.cpp index c90aa6e8..e238c838 100644 --- a/kernel/src/net/network.cpp +++ b/kernel/src/net/network.cpp @@ -12,7 +12,12 @@ #include "net/network.hpp" #include "net/ethernet_layer.hpp" +#include "net/arp_layer.hpp" #include "net/dhcp_layer.hpp" +#include "net/icmp_layer.hpp" +#include "net/dns_layer.hpp" +#include "net/udp_layer.hpp" +#include "net/tcp_layer.hpp" #include "drivers/rtl8139.hpp" #include "drivers/pci.hpp" @@ -27,11 +32,6 @@ #include "tlib/errors.hpp" -#include "net/icmp_layer.hpp" -#include "net/dns_layer.hpp" -#include "net/udp_layer.hpp" -#include "net/tcp_layer.hpp" - /* * TODO: Network layers * @@ -51,6 +51,11 @@ std::vector interfaces; network::ip::address dns_address; +network::ethernet::layer* ethernet_layer; +network::arp::layer* arp_layer; +network::ip::layer* ip_layer; +network::icmp::layer* icmp_layer; + void rx_thread(void* data){ auto& interface = *reinterpret_cast(data); @@ -64,7 +69,7 @@ void rx_thread(void* data){ interface.rx_sem.wait(); auto packet = interface.rx_queue.pop(); - network::ethernet::decode(interface, packet); + ethernet_layer->decode(interface, packet); ++interface.rx_packets_counter; interface.rx_bytes_counter += packet.payload_size; @@ -274,6 +279,13 @@ void network::init(){ // Initialize the necessary network layers + ethernet_layer = new network::ethernet::layer(); + + arp_layer = new network::arp::layer(ethernet_layer); + ip_layer = new network::ip::layer(ethernet_layer); + + icmp_layer = new network::icmp::layer(ip_layer); + network::udp::init_layer(); network::tcp::init_layer(); } @@ -398,7 +410,7 @@ std::tuple network::prepare_packet(socket_fd_t socket_fd, void* switch (socket.protocol) { case network::socket_protocol::ICMP: { auto descriptor = static_cast(desc); - auto packet = network::icmp::user_prepare_packet(buffer, socket, descriptor); + auto packet = icmp_layer->user_prepare_packet(buffer, socket, descriptor); return return_from_packet(packet); } @@ -600,7 +612,7 @@ std::expected network::finalize_packet(socket_fd_t socket_fd, size_t packe switch(socket.protocol){ case network::socket_protocol::ICMP: - return check_and_return(network::icmp::finalize_packet(interface, packet)); + return check_and_return(icmp_layer->finalize_packet(interface, packet)); case network::socket_protocol::TCP: return check_and_return(network::tcp::finalize_packet(interface, socket, packet));