prepare_packet can fail

This commit is contained in:
Baptiste Wicht 2016-09-08 11:06:47 +02:00
parent 1d4b202224
commit 175bda1ad2
9 changed files with 81 additions and 47 deletions

View File

@ -9,6 +9,7 @@
#define NET_ETHERNET_LAYER_H #define NET_ETHERNET_LAYER_H
#include <types.hpp> #include <types.hpp>
#include <expected.hpp>
#include "net/network.hpp" #include "net/network.hpp"
#include "net/ethernet_packet.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); void decode(network::interface_descriptor& interface, packet& packet);
packet prepare_packet(network::interface_descriptor& interface, size_t size, size_t destination, ether_type type); std::expected<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<packet> 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); void finalize_packet(network::interface_descriptor& interface, packet& p);
} // end of ethernet namespace } // end of ethernet namespace

View File

@ -9,6 +9,7 @@
#define NET_ICMP_LAYER_H #define NET_ICMP_LAYER_H
#include <types.hpp> #include <types.hpp>
#include <expected.hpp>
#include "tlib/net_constants.hpp" #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); 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); std::expected<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<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);
void finalize_packet(network::interface_descriptor& interface, network::ethernet::packet& p); void finalize_packet(network::interface_descriptor& interface, network::ethernet::packet& p);
void ping(network::interface_descriptor& interface, network::ip::address addr); void ping(network::interface_descriptor& interface, network::ip::address addr);

View File

@ -9,6 +9,7 @@
#define NET_IP_LAYER_H #define NET_IP_LAYER_H
#include <types.hpp> #include <types.hpp>
#include <expected.hpp>
#include "net/network.hpp" #include "net/network.hpp"
#include "tlib/net_constants.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); 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); std::expected<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<network::ethernet::packet> 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); void finalize_packet(network::interface_descriptor& interface, network::ethernet::packet& p);
} // end of ip namespace } // end of ip namespace

View File

@ -28,25 +28,32 @@ struct cache_entry {
std::vector<cache_entry> cache; std::vector<cache_entry> 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 // 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 packet = network::ethernet::prepare_packet(interface, sizeof(network::arp::header), 0xFFFFFFFFFFFF, network::ethernet::ether_type::ARP);
auto* arp_request_header = reinterpret_cast<network::arp::header*>(packet.payload + packet.index); if(packet){
auto* arp_request_header = reinterpret_cast<network::arp::header*>(packet->payload + packet->index);
arp_request_header->hw_type = switch_endian_16(0x1); // ethernet arp_request_header->hw_type = switch_endian_16(0x1); // ethernet
arp_request_header->protocol_type = switch_endian_16(0x800); // IPV4 arp_request_header->protocol_type = switch_endian_16(0x800); // IPV4
arp_request_header->hw_len = 0x6; // MAC Address arp_request_header->hw_len = 0x6; // MAC Address
arp_request_header->protocol_len = 0x4; // IP Address arp_request_header->protocol_len = 0x4; // IP Address
arp_request_header->operation = switch_endian_16(0x1); //ARP Request 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(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(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(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(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 } //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", 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)); ip(0), ip(1), ip(2), ip(3));
// TODO Handle error here
arp_request(interface, ip); arp_request(interface, ip);
while(!is_ip_cached(ip)){ while(!is_ip_cached(ip)){
@ -157,6 +165,7 @@ std::expected<uint64_t> 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", 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)); ip(0), ip(1), ip(2), ip(3));
// TODO Handle error here
arp_request(interface, ip); arp_request(interface, ip);
auto start = timer::milliseconds(); auto start = timer::milliseconds();

View File

@ -8,6 +8,8 @@
#include <vector.hpp> #include <vector.hpp>
#include <string.hpp> #include <string.hpp>
#include "tlib/errors.hpp"
#include "net/arp_layer.hpp" #include "net/arp_layer.hpp"
#include "net/arp_cache.hpp" #include "net/arp_cache.hpp"
#include "net/ip_layer.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 // Ask the ethernet layer to craft a packet
auto packet = network::ethernet::prepare_packet(interface, sizeof(header), source_hw, ethernet::ether_type::ARP); auto packet = network::ethernet::prepare_packet(interface, sizeof(header), source_hw, ethernet::ether_type::ARP);
auto* arp_reply_header = reinterpret_cast<header*>(packet.payload + packet.index); if(packet){
auto* arp_reply_header = reinterpret_cast<header*>(packet->payload + packet->index);
arp_reply_header->hw_type = switch_endian_16(0x1); // ethernet arp_reply_header->hw_type = switch_endian_16(0x1); // ethernet
arp_reply_header->protocol_type = switch_endian_16(0x800); // IPV4 arp_reply_header->protocol_type = switch_endian_16(0x800); // IPV4
arp_reply_header->hw_len = 0x6; // MAC Address arp_reply_header->hw_len = 0x6; // MAC Address
arp_reply_header->protocol_len = 0x4; // IP Address arp_reply_header->protocol_len = 0x4; // IP Address
arp_reply_header->operation = switch_endian_16(0x2); //ARP Reply 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->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->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){ } else if(operation == 0x2){
logging::logf(logging::log_level::TRACE, "arp: Handle Reply\n"); logging::logf(logging::log_level::TRACE, "arp: Handle Reply\n");

View File

@ -120,7 +120,7 @@ void network::ethernet::decode(network::interface_descriptor& interface, packet&
logging::logf(logging::log_level::TRACE, "ethernet: Finished decoding packet\n"); 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::packet> network::ethernet::prepare_packet(network::interface_descriptor& interface, size_t size, size_t destination, ether_type type){
auto total_size = size + sizeof(header); auto total_size = size + sizeof(header);
network::ethernet::packet p(new char[total_size], total_size); 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; 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::packet> 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); auto total_size = size + sizeof(header);
network::ethernet::packet p(buffer, total_size); network::ethernet::packet p(buffer, total_size);

View File

@ -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::ethernet::packet> 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 // Ask the IP layer to craft a packet
auto packet = network::ip::prepare_packet(interface, sizeof(header) + payload_size, target_ip, 0x01); 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; 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::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){
// Ask the IP layer to craft a packet // Ask the IP layer to craft a packet
auto packet = network::ip::prepare_packet(buffer, interface, sizeof(header) + payload_size, target_ip, 0x01); 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; return packet;
} }
@ -137,13 +141,15 @@ void network::icmp::ping(network::interface_descriptor& interface, network::ip::
// Ask the ICMP layer to craft a packet // Ask the ICMP layer to craft a packet
auto packet = network::icmp::prepare_packet(interface, target_ip, 0, type::ECHO_REQUEST, 0); 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<echo_request_header*>(packet.payload + packet.index); auto* command_header = reinterpret_cast<echo_request_header*>(packet->payload + packet->index);
command_header->identifier = 0x666; command_header->identifier = 0x666;
command_header->sequence = echo_sequence++; command_header->sequence = echo_sequence++;
// Send the packet back to ICMP // Send the packet back to ICMP
network::icmp::finalize_packet(interface, packet); network::icmp::finalize_packet(interface, *packet);
}
} }

View File

@ -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::ethernet::packet> 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); auto target_mac = network::arp::get_mac_force(interface, target_ip);
// Ask the ethernet layer to craft a packet // Ask the ethernet layer to craft a packet
auto packet = network::ethernet::prepare_packet(interface, size + sizeof(header), target_mac, ethernet::ether_type::IPV4); 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; 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::ethernet::packet> 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); auto target_mac = network::arp::get_mac_force(interface, target_ip);
// Ask the ethernet layer to craft a packet // 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); 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; return packet;
} }

View File

@ -187,9 +187,14 @@ std::tuple<size_t, size_t> network::prepare_packet(size_t socket_fd, void* desc,
case network::socket_protocol::ICMP: case network::socket_protocol::ICMP:
auto descriptor = static_cast<network::icmp::packet_descriptor*>(desc); auto descriptor = static_cast<network::icmp::packet_descriptor*>(desc);
auto packet = network::icmp::prepare_packet(buffer, interface, descriptor->target_ip, descriptor->payload_size, descriptor->type, descriptor->code); 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}; return {-std::ERROR_SOCKET_UNIMPLEMENTED, 0};