Start extracting layers

This commit is contained in:
Baptiste Wicht 2016-09-26 22:04:39 +02:00
parent 1a68b5f360
commit 9e98cd3411
No known key found for this signature in database
GPG Key ID: C5566B6C7F884532
9 changed files with 214 additions and 131 deletions

View File

@ -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);

View File

@ -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<packet> 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<packet> 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<packet> 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<packet> 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<void> 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<void> 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

View File

@ -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<network::ethernet::packet> 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<network::ethernet::packet> 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<network::ethernet::packet> 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<void> 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<network::ethernet::packet> 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<void> finalize_packet(network::interface_descriptor& interface, network::ethernet::packet& p);
private:
network::ip::layer* parent;
};
} // end of icmp namespace

View File

@ -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<network::ethernet::packet> 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<network::ethernet::packet> 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<network::ethernet::packet> 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<void> 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<network::ethernet::packet> 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<void> 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

View File

@ -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<header*>(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<header*>(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()));

View File

@ -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<header*>(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::packet> network::ethernet::kernel_prepare_packet(network::interface_descriptor& interface, const packet_descriptor& descriptor){
std::expected<network::ethernet::packet> 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::packet> network::ethernet::kernel_prepare_packe
return p;
}
std::expected<network::ethernet::packet> network::ethernet::user_prepare_packet(char* buffer, network::interface_descriptor& interface, const packet_descriptor* descriptor){
std::expected<network::ethernet::packet> 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::packet> network::ethernet::user_prepare_packet(
return p;
}
std::expected<void> network::ethernet::finalize_packet(network::interface_descriptor& interface, packet& p){
std::expected<void> 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

View File

@ -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<echo_request_header*>(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::ethernet::packet> network::icmp::kernel_prepare_packet(network::interface_descriptor& interface, const packet_descriptor& descriptor){
std::expected<network::ethernet::packet> 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::ethernet::packet> network::icmp::kernel_prepare_packet(ne
return packet;
}
std::expected<network::ethernet::packet> network::icmp::user_prepare_packet(char* buffer, network::socket& /*socket*/, const packet_descriptor* descriptor){
std::expected<network::ethernet::packet> 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::ethernet::packet> network::icmp::user_prepare_packet(char
return packet;
}
std::expected<void> network::icmp::finalize_packet(network::interface_descriptor& interface, network::ethernet::packet& packet){
std::expected<void> 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<header*>(packet.payload + packet.index);
@ -148,5 +148,5 @@ std::expected<void> 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);
}

View File

@ -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<header*>(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::ethernet::packet> network::ip::kernel_prepare_packet(network::interface_descriptor& interface, const packet_descriptor& descriptor){
std::expected<network::ethernet::packet> 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::ethernet::packet> 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::ethernet::packet> network::ip::kernel_prepare_packet(netw
return packet;
}
std::expected<network::ethernet::packet> network::ip::user_prepare_packet(char* buffer, network::interface_descriptor& interface, const packet_descriptor* descriptor){
std::expected<network::ethernet::packet> 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::ethernet::packet> 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::ethernet::packet> network::ip::user_prepare_packet(char*
return packet;
}
std::expected<void> network::ip::finalize_packet(network::interface_descriptor& interface, network::ethernet::packet& p){
std::expected<void> 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);
}

View File

@ -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<network::interface_descriptor> 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<network::interface_descriptor*>(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<size_t, size_t> network::prepare_packet(socket_fd_t socket_fd, void*
switch (socket.protocol) {
case network::socket_protocol::ICMP: {
auto descriptor = static_cast<network::icmp::packet_descriptor*>(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<void> 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));