diff --git a/kernel/include/net/ethernet_layer.hpp b/kernel/include/net/ethernet_layer.hpp index 52490aa0..9d43b39b 100644 --- a/kernel/include/net/ethernet_layer.hpp +++ b/kernel/include/net/ethernet_layer.hpp @@ -9,6 +9,7 @@ #define NET_ETHERNET_LAYER_H #include +#include #include "net/network.hpp" #include "net/ethernet_packet.hpp" @@ -35,8 +36,8 @@ void mac64_to_mac6(uint64_t input, char* mac); void decode(network::interface_descriptor& interface, packet& packet); -packet prepare_packet(network::interface_descriptor& interface, size_t size, size_t destination, ether_type type); -packet prepare_packet(char* buffer, network::interface_descriptor& interface, size_t size, size_t destination, ether_type type); +std::expected prepare_packet(network::interface_descriptor& interface, size_t size, size_t destination, ether_type type); +std::expected prepare_packet(char* buffer, network::interface_descriptor& interface, size_t size, size_t destination, ether_type type); void finalize_packet(network::interface_descriptor& interface, packet& p); } // end of ethernet namespace diff --git a/kernel/include/net/icmp_layer.hpp b/kernel/include/net/icmp_layer.hpp index 64d88e67..5e1f2466 100644 --- a/kernel/include/net/icmp_layer.hpp +++ b/kernel/include/net/icmp_layer.hpp @@ -9,6 +9,7 @@ #define NET_ICMP_LAYER_H #include +#include #include "tlib/net_constants.hpp" @@ -23,8 +24,8 @@ static_assert(sizeof(echo_request_header) == sizeof(header::rest), "Invalid size void decode(network::interface_descriptor& interface, network::ethernet::packet& packet); -network::ethernet::packet prepare_packet(network::interface_descriptor& interface, network::ip::address target_ip, size_t payload_size, type t, size_t code); -network::ethernet::packet prepare_packet(char* buffer, network::interface_descriptor& interface, network::ip::address target_ip, size_t payload_size, type t, size_t code); +std::expected prepare_packet(network::interface_descriptor& interface, network::ip::address target_ip, size_t payload_size, type t, size_t code); +std::expected prepare_packet(char* buffer, network::interface_descriptor& interface, network::ip::address target_ip, size_t payload_size, type t, size_t code); void finalize_packet(network::interface_descriptor& interface, network::ethernet::packet& p); void ping(network::interface_descriptor& interface, network::ip::address addr); diff --git a/kernel/include/net/ip_layer.hpp b/kernel/include/net/ip_layer.hpp index 88293dcf..d83da009 100644 --- a/kernel/include/net/ip_layer.hpp +++ b/kernel/include/net/ip_layer.hpp @@ -9,6 +9,7 @@ #define NET_IP_LAYER_H #include +#include #include "net/network.hpp" #include "tlib/net_constants.hpp" @@ -37,8 +38,8 @@ static_assert(sizeof(header) == 20, "The size of an IPv4 header must be 20 bytes void decode(network::interface_descriptor& interface, network::ethernet::packet& packet); -network::ethernet::packet prepare_packet(network::interface_descriptor& interface, size_t size, address& destination, size_t protocol); -network::ethernet::packet prepare_packet(char* buffer, network::interface_descriptor& interface, size_t size, address& destination, size_t protocol); +std::expected prepare_packet(network::interface_descriptor& interface, size_t size, address& destination, size_t protocol); +std::expected prepare_packet(char* buffer, network::interface_descriptor& interface, size_t size, address& destination, size_t protocol); void finalize_packet(network::interface_descriptor& interface, network::ethernet::packet& p); } // end of ip namespace diff --git a/kernel/src/net/arp_cache.cpp b/kernel/src/net/arp_cache.cpp index 00bc1ca4..40a43bd6 100644 --- a/kernel/src/net/arp_cache.cpp +++ b/kernel/src/net/arp_cache.cpp @@ -28,25 +28,32 @@ struct cache_entry { std::vector cache; -void arp_request(network::interface_descriptor& interface, network::ip::address ip){ +bool arp_request(network::interface_descriptor& interface, network::ip::address ip){ // Ask the ethernet layer to craft a packet auto packet = network::ethernet::prepare_packet(interface, sizeof(network::arp::header), 0xFFFFFFFFFFFF, network::ethernet::ether_type::ARP); - auto* arp_request_header = reinterpret_cast(packet.payload + packet.index); + if(packet){ + auto* arp_request_header = reinterpret_cast(packet->payload + packet->index); - arp_request_header->hw_type = switch_endian_16(0x1); // ethernet - arp_request_header->protocol_type = switch_endian_16(0x800); // IPV4 - arp_request_header->hw_len = 0x6; // MAC Address - arp_request_header->protocol_len = 0x4; // IP Address - arp_request_header->operation = switch_endian_16(0x1); //ARP Request + arp_request_header->hw_type = switch_endian_16(0x1); // ethernet + arp_request_header->protocol_type = switch_endian_16(0x800); // IPV4 + arp_request_header->hw_len = 0x6; // MAC Address + arp_request_header->protocol_len = 0x4; // IP Address + arp_request_header->operation = switch_endian_16(0x1); //ARP Request - network::arp::mac64_to_mac3(interface.mac_address, arp_request_header->source_hw_addr); - network::arp::mac64_to_mac3(0x0, arp_request_header->target_hw_addr); + network::arp::mac64_to_mac3(interface.mac_address, arp_request_header->source_hw_addr); + network::arp::mac64_to_mac3(0x0, arp_request_header->target_hw_addr); - network::arp::ip_to_ip2(interface.ip_address, arp_request_header->source_protocol_addr); - network::arp::ip_to_ip2(ip, arp_request_header->target_protocol_addr); + network::arp::ip_to_ip2(interface.ip_address, arp_request_header->source_protocol_addr); + network::arp::ip_to_ip2(ip, arp_request_header->target_protocol_addr); - network::ethernet::finalize_packet(interface, packet); + network::ethernet::finalize_packet(interface, *packet); + + return true; + } else { + //TODO Don't loose the error + return false; + } } } //end of anonymous namespace @@ -130,6 +137,7 @@ uint64_t network::arp::get_mac_force(network::interface_descriptor& interface, n logging::logf(logging::log_level::TRACE, "arp: IP %u.%u.%u.%u not cached, generate ARP Request\n", ip(0), ip(1), ip(2), ip(3)); + // TODO Handle error here arp_request(interface, ip); while(!is_ip_cached(ip)){ @@ -157,6 +165,7 @@ std::expected network::arp::get_mac_force(network::interface_descripto logging::logf(logging::log_level::TRACE, "arp: IP %u.%u.%u.%u not cached, generate ARP Request\n", ip(0), ip(1), ip(2), ip(3)); + // TODO Handle error here arp_request(interface, ip); auto start = timer::milliseconds(); diff --git a/kernel/src/net/arp_layer.cpp b/kernel/src/net/arp_layer.cpp index 9b7cef74..d867f8a0 100644 --- a/kernel/src/net/arp_layer.cpp +++ b/kernel/src/net/arp_layer.cpp @@ -8,6 +8,8 @@ #include #include +#include "tlib/errors.hpp" + #include "net/arp_layer.hpp" #include "net/arp_cache.hpp" #include "net/ip_layer.hpp" @@ -118,22 +120,27 @@ void network::arp::decode(network::interface_descriptor& interface, network::eth // Ask the ethernet layer to craft a packet auto packet = network::ethernet::prepare_packet(interface, sizeof(header), source_hw, ethernet::ether_type::ARP); - auto* arp_reply_header = reinterpret_cast(packet.payload + packet.index); + if(packet){ + auto* arp_reply_header = reinterpret_cast(packet->payload + packet->index); - arp_reply_header->hw_type = switch_endian_16(0x1); // ethernet - arp_reply_header->protocol_type = switch_endian_16(0x800); // IPV4 - arp_reply_header->hw_len = 0x6; // MAC Address - arp_reply_header->protocol_len = 0x4; // IP Address - arp_reply_header->operation = switch_endian_16(0x2); //ARP Reply + arp_reply_header->hw_type = switch_endian_16(0x1); // ethernet + arp_reply_header->protocol_type = switch_endian_16(0x800); // IPV4 + arp_reply_header->hw_len = 0x6; // MAC Address + arp_reply_header->protocol_len = 0x4; // IP Address + arp_reply_header->operation = switch_endian_16(0x2); //ARP Reply - mac64_to_mac3(interface.mac_address, arp_reply_header->source_hw_addr); + mac64_to_mac3(interface.mac_address, arp_reply_header->source_hw_addr); - std::copy_n(arp_header->source_hw_addr, 3, arp_reply_header->target_hw_addr); + std::copy_n(arp_header->source_hw_addr, 3, arp_reply_header->target_hw_addr); - 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); + 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); + network::ethernet::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())); + + } } } else if(operation == 0x2){ logging::logf(logging::log_level::TRACE, "arp: Handle Reply\n"); diff --git a/kernel/src/net/ethernet_layer.cpp b/kernel/src/net/ethernet_layer.cpp index 41a21b8c..8660664f 100644 --- a/kernel/src/net/ethernet_layer.cpp +++ b/kernel/src/net/ethernet_layer.cpp @@ -120,7 +120,7 @@ void network::ethernet::decode(network::interface_descriptor& interface, packet& logging::logf(logging::log_level::TRACE, "ethernet: Finished decoding packet\n"); } -network::ethernet::packet network::ethernet::prepare_packet(network::interface_descriptor& interface, size_t size, size_t destination, ether_type type){ +std::expected network::ethernet::prepare_packet(network::interface_descriptor& interface, size_t size, size_t destination, ether_type type){ auto total_size = size + sizeof(header); network::ethernet::packet p(new char[total_size], total_size); @@ -130,7 +130,7 @@ network::ethernet::packet network::ethernet::prepare_packet(network::interface_d return p; } -network::ethernet::packet network::ethernet::prepare_packet(char* buffer, network::interface_descriptor& interface, size_t size, size_t destination, ether_type type){ +std::expected network::ethernet::prepare_packet(char* buffer, network::interface_descriptor& interface, size_t size, size_t destination, ether_type type){ auto total_size = size + sizeof(header); network::ethernet::packet p(buffer, total_size); diff --git a/kernel/src/net/icmp_layer.cpp b/kernel/src/net/icmp_layer.cpp index 68f906ba..6f5213e3 100644 --- a/kernel/src/net/icmp_layer.cpp +++ b/kernel/src/net/icmp_layer.cpp @@ -96,20 +96,24 @@ void network::icmp::decode(network::interface_descriptor& /*interface*/, network } } -network::ethernet::packet network::icmp::prepare_packet(network::interface_descriptor& interface, network::ip::address target_ip, size_t payload_size, type t, size_t code){ +std::expected network::icmp::prepare_packet(network::interface_descriptor& interface, network::ip::address target_ip, size_t payload_size, type t, size_t code){ // Ask the IP layer to craft a packet auto packet = network::ip::prepare_packet(interface, sizeof(header) + payload_size, target_ip, 0x01); - ::prepare_packet(packet, t, code); + if(packet){ + ::prepare_packet(*packet, t, code); + } return packet; } -network::ethernet::packet network::icmp::prepare_packet(char* buffer, network::interface_descriptor& interface, network::ip::address target_ip, size_t payload_size, type t, size_t code){ +std::expected network::icmp::prepare_packet(char* buffer, network::interface_descriptor& interface, network::ip::address target_ip, size_t payload_size, type t, size_t code){ // Ask the IP layer to craft a packet auto packet = network::ip::prepare_packet(buffer, interface, sizeof(header) + payload_size, target_ip, 0x01); - ::prepare_packet(packet, t, code); + if(packet){ + ::prepare_packet(*packet, t, code); + } return packet; } @@ -137,13 +141,15 @@ void network::icmp::ping(network::interface_descriptor& interface, network::ip:: // Ask the ICMP layer to craft a packet auto packet = network::icmp::prepare_packet(interface, target_ip, 0, type::ECHO_REQUEST, 0); - // Set the Command header + if(packet){ + // Set the Command header - auto* command_header = reinterpret_cast(packet.payload + packet.index); + auto* command_header = reinterpret_cast(packet->payload + packet->index); - command_header->identifier = 0x666; - command_header->sequence = echo_sequence++; + command_header->identifier = 0x666; + command_header->sequence = echo_sequence++; - // Send the packet back to ICMP - network::icmp::finalize_packet(interface, packet); + // Send the packet back to ICMP + network::icmp::finalize_packet(interface, *packet); + } } diff --git a/kernel/src/net/ip_layer.cpp b/kernel/src/net/ip_layer.cpp index fa1cd1fb..fcf5d8dc 100644 --- a/kernel/src/net/ip_layer.cpp +++ b/kernel/src/net/ip_layer.cpp @@ -110,24 +110,28 @@ void network::ip::decode(network::interface_descriptor& interface, network::ethe } } -network::ethernet::packet network::ip::prepare_packet(network::interface_descriptor& interface, size_t size, address& target_ip, size_t protocol){ +std::expected network::ip::prepare_packet(network::interface_descriptor& interface, size_t size, address& target_ip, size_t protocol){ auto target_mac = network::arp::get_mac_force(interface, target_ip); // Ask the ethernet layer to craft a packet auto packet = network::ethernet::prepare_packet(interface, size + sizeof(header), target_mac, ethernet::ether_type::IPV4); - ::prepare_packet(packet, interface, size, target_ip, protocol); + if(packet){ + ::prepare_packet(*packet, interface, size, target_ip, protocol); + } return packet; } -network::ethernet::packet network::ip::prepare_packet(char* buffer, network::interface_descriptor& interface, size_t size, address& target_ip, size_t protocol){ +std::expected network::ip::prepare_packet(char* buffer, network::interface_descriptor& interface, size_t size, address& target_ip, size_t protocol){ auto target_mac = network::arp::get_mac_force(interface, target_ip); // Ask the ethernet layer to craft a packet auto packet = network::ethernet::prepare_packet(buffer, interface, size + sizeof(header), target_mac, ethernet::ether_type::IPV4); - ::prepare_packet(packet, interface, size, target_ip, protocol); + if(packet){ + ::prepare_packet(*packet, interface, size, target_ip, protocol); + } return packet; } diff --git a/kernel/src/net/network.cpp b/kernel/src/net/network.cpp index 10e331c8..c26b7d5f 100644 --- a/kernel/src/net/network.cpp +++ b/kernel/src/net/network.cpp @@ -187,9 +187,14 @@ std::tuple network::prepare_packet(size_t socket_fd, void* desc, case network::socket_protocol::ICMP: auto descriptor = static_cast(desc); auto packet = network::icmp::prepare_packet(buffer, interface, descriptor->target_ip, descriptor->payload_size, descriptor->type, descriptor->code); - auto fd = socket.register_packet(packet); - return {fd, packet.index}; + if(packet){ + auto fd = socket.register_packet(*packet); + + return {fd, packet->index}; + } else { + return {-packet.error(), 0}; + } } return {-std::ERROR_SOCKET_UNIMPLEMENTED, 0};