From b9f9b9163a419b1efd8375638ddb1d1574ebced3 Mon Sep 17 00:00:00 2001 From: Baptiste Wicht Date: Tue, 13 Sep 2016 20:57:18 +0200 Subject: [PATCH] Prepare TCP support --- kernel/include/net/tcp_layer.hpp | 42 +++++++++++++++ kernel/src/net/ip_layer.cpp | 3 +- kernel/src/net/tcp_layer.cpp | 89 ++++++++++++++++++++++++++++++++ 3 files changed, 133 insertions(+), 1 deletion(-) create mode 100644 kernel/include/net/tcp_layer.hpp create mode 100644 kernel/src/net/tcp_layer.cpp diff --git a/kernel/include/net/tcp_layer.hpp b/kernel/include/net/tcp_layer.hpp new file mode 100644 index 00000000..1283d48a --- /dev/null +++ b/kernel/include/net/tcp_layer.hpp @@ -0,0 +1,42 @@ +//======================================================================= +// Copyright Baptiste Wicht 2013-2016. +// Distributed under the terms of the MIT License. +// (See accompanying file LICENSE or copy at +// http://www.opensource.org/licenses/MIT) +//======================================================================= + +#ifndef NET_TCP_LAYER_H +#define NET_TCP_LAYER_H + +#include + +#include "net/ethernet_layer.hpp" +#include "net/ip_layer.hpp" +#include "net/network.hpp" + +namespace network { + +namespace tcp { + +struct header { + uint16_t source_port; + uint16_t target_port; + uint32_t sequence_number; + uint32_t ack_number; + uint16_t flags; + uint16_t window_size; + uint16_t checksum; + uint16_t urgent_pointer; +} __attribute__((packed)); + +void decode(network::interface_descriptor& interface, network::ethernet::packet& packet); + +std::expected prepare_packet(network::interface_descriptor& interface, network::ip::address target_ip, size_t source, size_t target, size_t payload_size); +std::expected prepare_packet(char* buffer, network::interface_descriptor& interface, network::ip::address target_ip, size_t source, size_t target, size_t payload_size); +void finalize_packet(network::interface_descriptor& interface, network::ethernet::packet& p); + +} // end of tcp namespace + +} // end of network namespace + +#endif diff --git a/kernel/src/net/ip_layer.cpp b/kernel/src/net/ip_layer.cpp index f305645e..af5a0dc0 100644 --- a/kernel/src/net/ip_layer.cpp +++ b/kernel/src/net/ip_layer.cpp @@ -12,6 +12,7 @@ #include "net/ethernet_layer.hpp" #include "net/icmp_layer.hpp" #include "net/udp_layer.hpp" +#include "net/tcp_layer.hpp" #include "net/arp_cache.hpp" #include "logging.hpp" @@ -143,7 +144,7 @@ void network::ip::decode(network::interface_descriptor& interface, network::ethe if(protocol == 0x01){ network::icmp::decode(interface, packet); } else if(protocol == 0x06){ - logging::logf(logging::log_level::ERROR, "ip: TCP packet detected (unsupported)\n"); + network::tcp::decode(interface, packet); } else if(protocol == 0x11){ network::udp::decode(interface, packet); } else { diff --git a/kernel/src/net/tcp_layer.cpp b/kernel/src/net/tcp_layer.cpp new file mode 100644 index 00000000..d7d79720 --- /dev/null +++ b/kernel/src/net/tcp_layer.cpp @@ -0,0 +1,89 @@ +//======================================================================= +// Copyright Baptiste Wicht 2013-2016. +// Distributed under the terms of the MIT License. +// (See accompanying file LICENSE or copy at +// http://www.opensource.org/licenses/MIT) +//======================================================================= + +#include "net/tcp_layer.hpp" +#include "net/dns_layer.hpp" + +#include "kernel_utils.hpp" + +namespace { + +void compute_checksum(network::ethernet::packet& packet){ + auto* ip_header = reinterpret_cast(packet.payload + packet.tag(1)); + auto* tcp_header = reinterpret_cast(packet.payload + packet.index); + + tcp_header->checksum = 0; + + //TODO +} + +void prepare_packet(network::ethernet::packet& packet, size_t source, size_t target, size_t payload_size){ + packet.tag(2, packet.index); + + // Set the TCP header + + auto* tcp_header = reinterpret_cast(packet.payload + packet.index); + + tcp_header->source_port = switch_endian_16(source); + tcp_header->target_port = switch_endian_16(target); + + //TODO + + packet.index += sizeof(network::tcp::header); +} + +} //end of anonymous namespace + +void network::tcp::decode(network::interface_descriptor& interface, network::ethernet::packet& packet){ + packet.tag(2, packet.index); + + auto* tcp_header = reinterpret_cast(packet.payload + packet.index); + + logging::logf(logging::log_level::TRACE, "tcp: Start TCP packet handling\n"); + + auto source_port = switch_endian_16(tcp_header->source_port); + auto target_port = switch_endian_16(tcp_header->target_port); + + logging::logf(logging::log_level::TRACE, "tcp: Source Port %h \n", source_port); + logging::logf(logging::log_level::TRACE, "tcp: Target Port %h \n", target_port); + + packet.index += sizeof(header); + + //TODO +} + +std::expected network::tcp::prepare_packet(network::interface_descriptor& interface, network::ip::address target_ip, size_t source, size_t target, size_t payload_size){ + // Ask the IP layer to craft a packet + auto packet = network::ip::prepare_packet(interface, sizeof(header) + payload_size, target_ip, 0x11); + + if(packet){ + ::prepare_packet(*packet, source, target, payload_size); + } + + return packet; +} + +std::expected network::tcp::prepare_packet(char* buffer, network::interface_descriptor& interface, network::ip::address target_ip, size_t source, size_t target, size_t payload_size){ + // Ask the IP layer to craft a packet + auto packet = network::ip::prepare_packet(buffer, interface, sizeof(header) + payload_size, target_ip, 0x11); + + if(packet){ + ::prepare_packet(*packet, source, target, payload_size); + } + + return packet; +} + +void network::tcp::finalize_packet(network::interface_descriptor& interface, network::ethernet::packet& p){ + p.index -= sizeof(header); + + // Compute the checksum + compute_checksum(p); + + // Give the packet to the IP layer for finalization + network::ip::finalize_packet(interface, p); +}