2020-01-18 11:38:21 +03:00
/*
2021-03-12 13:59:41 +03:00
* Copyright ( c ) 2018 - 2021 , Andreas Kling < kling @ serenityos . org >
2020-01-18 11:38:21 +03:00
*
2021-04-22 11:24:48 +03:00
* SPDX - License - Identifier : BSD - 2 - Clause
2020-01-18 11:38:21 +03:00
*/
2021-01-25 18:07:10 +03:00
# include <Kernel/Debug.h>
2019-06-07 12:43:58 +03:00
# include <Kernel/Lock.h>
# include <Kernel/Net/ARP.h>
# include <Kernel/Net/EtherType.h>
2019-04-02 20:54:38 +03:00
# include <Kernel/Net/EthernetFrameHeader.h>
# include <Kernel/Net/ICMP.h>
# include <Kernel/Net/IPv4.h>
# include <Kernel/Net/IPv4Socket.h>
2019-06-07 12:43:58 +03:00
# include <Kernel/Net/LoopbackAdapter.h>
2020-04-09 14:31:05 +03:00
# include <Kernel/Net/NetworkTask.h>
2019-08-28 14:53:01 +03:00
# include <Kernel/Net/Routing.h>
2019-06-07 12:43:58 +03:00
# include <Kernel/Net/TCP.h>
2019-04-02 20:54:38 +03:00
# include <Kernel/Net/TCPSocket.h>
2019-06-07 12:43:58 +03:00
# include <Kernel/Net/UDP.h>
2019-04-02 20:54:38 +03:00
# include <Kernel/Net/UDPSocket.h>
2019-03-11 14:43:45 +03:00
# include <Kernel/Process.h>
2019-03-12 01:21:38 +03:00
2020-02-16 03:27:42 +03:00
namespace Kernel {
2019-08-09 11:42:01 +03:00
static void handle_arp ( const EthernetFrameHeader & , size_t frame_size ) ;
2021-02-28 04:48:45 +03:00
static void handle_ipv4 ( const EthernetFrameHeader & , size_t frame_size , const Time & packet_timestamp ) ;
static void handle_icmp ( const EthernetFrameHeader & , const IPv4Packet & , const Time & packet_timestamp ) ;
static void handle_udp ( const IPv4Packet & , const Time & packet_timestamp ) ;
static void handle_tcp ( const IPv4Packet & , const Time & packet_timestamp ) ;
2019-03-11 14:43:45 +03:00
2020-11-17 06:51:34 +03:00
[[noreturn]] static void NetworkTask_main ( void * ) ;
2020-04-09 14:31:05 +03:00
void NetworkTask : : spawn ( )
{
2020-09-27 17:53:35 +03:00
RefPtr < Thread > thread ;
2020-11-17 06:51:34 +03:00
Process : : create_kernel_process ( thread , " NetworkTask " , NetworkTask_main , nullptr ) ;
2020-04-09 14:31:05 +03:00
}
2020-11-17 06:51:34 +03:00
void NetworkTask_main ( void * )
2019-03-11 14:43:45 +03:00
{
2019-12-01 18:47:49 +03:00
WaitQueue packet_wait_queue ;
2019-08-28 14:53:01 +03:00
int pending_packets = 0 ;
2019-12-01 18:47:49 +03:00
NetworkAdapter : : for_each ( [ & ] ( auto & adapter ) {
2021-04-03 04:42:32 +03:00
dmesgln ( " NetworkTask: {} network adapter found: hw={} " , adapter . class_name ( ) , adapter . mac_address ( ) . to_string ( ) ) ;
2019-08-28 14:53:01 +03:00
if ( String ( adapter . class_name ( ) ) = = " LoopbackAdapter " ) {
adapter . set_ipv4_address ( { 127 , 0 , 0 , 1 } ) ;
adapter . set_ipv4_netmask ( { 255 , 0 , 0 , 0 } ) ;
adapter . set_ipv4_gateway ( { 0 , 0 , 0 , 0 } ) ;
}
2019-04-02 16:46:44 +03:00
2019-12-01 18:47:49 +03:00
adapter . on_receive = [ & ] ( ) {
2019-08-28 14:53:01 +03:00
pending_packets + + ;
2019-12-01 18:47:49 +03:00
packet_wait_queue . wake_all ( ) ;
2019-08-28 15:14:38 +03:00
} ;
2019-08-28 14:53:01 +03:00
} ) ;
2019-03-11 14:43:45 +03:00
2021-02-28 04:48:45 +03:00
auto dequeue_packet = [ & pending_packets ] ( u8 * buffer , size_t buffer_size , Time & packet_timestamp ) - > size_t {
2019-12-01 18:47:49 +03:00
if ( pending_packets = = 0 )
2019-12-14 13:07:37 +03:00
return 0 ;
size_t packet_size = 0 ;
NetworkAdapter : : for_each ( [ & ] ( auto & adapter ) {
if ( packet_size | | ! adapter . has_queued_packets ( ) )
2019-08-28 14:53:01 +03:00
return ;
2020-09-16 19:25:06 +03:00
packet_size = adapter . dequeue_packet ( buffer , buffer_size , packet_timestamp ) ;
2019-08-28 14:53:01 +03:00
pending_packets - - ;
2021-03-12 13:59:41 +03:00
dbgln_if ( NETWORK_TASK_DEBUG , " NetworkTask: Dequeued packet from {} ({} bytes) " , adapter . name ( ) , packet_size ) ;
2019-08-28 14:53:01 +03:00
} ) ;
2019-12-14 13:07:37 +03:00
return packet_size ;
2019-04-02 16:46:44 +03:00
} ;
AK: Rename KB, MB, GB to KiB, MiB, GiB
The SI prefixes "k", "M", "G" mean "10^3", "10^6", "10^9".
The IEC prefixes "Ki", "Mi", "Gi" mean "2^10", "2^20", "2^30".
Let's use the correct name, at least in code.
Only changes the name of the constants, no other behavior change.
2020-08-15 20:55:00 +03:00
size_t buffer_size = 64 * KiB ;
2020-09-06 00:52:14 +03:00
auto buffer_region = MM . allocate_kernel_region ( buffer_size , " Kernel Packet Buffer " , Region : : Access : : Read | Region : : Access : : Write ) ;
2019-12-28 02:07:56 +03:00
auto buffer = ( u8 * ) buffer_region - > vaddr ( ) . get ( ) ;
2021-02-28 04:48:45 +03:00
Time packet_timestamp ;
2019-12-28 02:07:56 +03:00
2019-03-11 14:43:45 +03:00
for ( ; ; ) {
2020-09-16 19:25:06 +03:00
size_t packet_size = dequeue_packet ( buffer , buffer_size , packet_timestamp ) ;
2019-12-14 13:07:37 +03:00
if ( ! packet_size ) {
2021-02-15 02:02:14 +03:00
packet_wait_queue . wait_forever ( " NetworkTask " ) ;
2019-03-11 14:43:45 +03:00
continue ;
}
2019-12-14 13:07:37 +03:00
if ( packet_size < sizeof ( EthernetFrameHeader ) ) {
2021-03-12 13:59:41 +03:00
dbgln ( " NetworkTask: Packet is too small to be an Ethernet packet! ({}) " , packet_size ) ;
2019-03-11 14:43:45 +03:00
continue ;
}
2019-12-28 02:07:56 +03:00
auto & eth = * ( const EthernetFrameHeader * ) buffer ;
2021-03-12 13:59:41 +03:00
dbgln_if ( ETHERNET_DEBUG , " NetworkTask: From {} to {}, ether_type={:#04x}, packet_size={} " , eth . source ( ) . to_string ( ) , eth . destination ( ) . to_string ( ) , eth . ether_type ( ) , packet_size ) ;
2019-08-06 16:40:38 +03:00
2019-03-12 01:21:38 +03:00
switch ( eth . ether_type ( ) ) {
case EtherType : : ARP :
2019-12-14 13:07:37 +03:00
handle_arp ( eth , packet_size ) ;
2019-03-12 01:21:38 +03:00
break ;
case EtherType : : IPv4 :
2020-09-16 19:25:06 +03:00
handle_ipv4 ( eth , packet_size , packet_timestamp ) ;
2019-03-12 01:21:38 +03:00
break ;
2019-08-28 03:53:12 +03:00
case EtherType : : IPv6 :
// ignore
break ;
default :
2021-03-12 13:59:41 +03:00
dbgln ( " NetworkTask: Unknown ethernet type {:#04x} " , eth . ether_type ( ) ) ;
2019-03-12 01:21:38 +03:00
}
2019-03-11 14:43:45 +03:00
}
}
2019-03-12 01:21:38 +03:00
2019-08-09 11:42:01 +03:00
void handle_arp ( const EthernetFrameHeader & eth , size_t frame_size )
2019-03-12 01:21:38 +03:00
{
2019-08-09 11:42:01 +03:00
constexpr size_t minimum_arp_frame_size = sizeof ( EthernetFrameHeader ) + sizeof ( ARPPacket ) ;
2019-03-12 01:21:38 +03:00
if ( frame_size < minimum_arp_frame_size ) {
2021-03-12 13:59:41 +03:00
dbgln ( " handle_arp: Frame too small ({}, need {}) " , frame_size , minimum_arp_frame_size ) ;
2019-03-12 01:21:38 +03:00
return ;
}
2019-03-12 02:56:33 +03:00
auto & packet = * static_cast < const ARPPacket * > ( eth . payload ( ) ) ;
2019-03-12 02:01:07 +03:00
if ( packet . hardware_type ( ) ! = 1 | | packet . hardware_address_length ( ) ! = sizeof ( MACAddress ) ) {
2020-12-25 19:05:05 +03:00
dbgln ( " handle_arp: Hardware type not ethernet ({:#04x}, len={}) " , packet . hardware_type ( ) , packet . hardware_address_length ( ) ) ;
2019-03-12 01:21:38 +03:00
return ;
}
2019-03-12 02:01:07 +03:00
if ( packet . protocol_type ( ) ! = EtherType : : IPv4 | | packet . protocol_address_length ( ) ! = sizeof ( IPv4Address ) ) {
2020-12-25 19:05:05 +03:00
dbgln ( " handle_arp: Protocol type not IPv4 ({:#04x}, len={}) " , packet . protocol_type ( ) , packet . protocol_address_length ( ) ) ;
2019-03-12 01:21:38 +03:00
return ;
}
2021-03-12 13:59:41 +03:00
dbgln_if ( ARP_DEBUG , " handle_arp: operation={:#04x}, sender={}/{}, target={}/{} " ,
2020-12-25 19:05:05 +03:00
packet . operation ( ) ,
packet . sender_hardware_address ( ) . to_string ( ) ,
packet . sender_protocol_address ( ) . to_string ( ) ,
packet . target_hardware_address ( ) . to_string ( ) ,
packet . target_protocol_address ( ) . to_string ( ) ) ;
2019-03-12 01:21:38 +03:00
2019-09-08 10:26:21 +03:00
if ( ! packet . sender_hardware_address ( ) . is_zero ( ) & & ! packet . sender_protocol_address ( ) . is_zero ( ) ) {
// Someone has this IPv4 address. I guess we can try to remember that.
// FIXME: Protect against ARP spamming.
// FIXME: Support static ARP table entries.
2020-11-30 02:05:27 +03:00
update_arp_table ( packet . sender_protocol_address ( ) , packet . sender_hardware_address ( ) ) ;
2019-09-08 10:26:21 +03:00
}
2019-03-12 03:30:49 +03:00
if ( packet . operation ( ) = = ARPOperation : : Request ) {
2019-03-12 01:21:38 +03:00
// Who has this IP address?
2019-08-09 05:34:32 +03:00
if ( auto adapter = NetworkAdapter : : from_ipv4_address ( packet . target_protocol_address ( ) ) ) {
2019-03-12 01:21:38 +03:00
// We do!
2021-03-12 13:59:41 +03:00
dbgln ( " handle_arp: Responding to ARP request for my IPv4 address ({}) " , adapter - > ipv4_address ( ) ) ;
2019-03-12 01:21:38 +03:00
ARPPacket response ;
2019-03-12 03:30:49 +03:00
response . set_operation ( ARPOperation : : Response ) ;
2019-03-12 02:01:07 +03:00
response . set_target_hardware_address ( packet . sender_hardware_address ( ) ) ;
response . set_target_protocol_address ( packet . sender_protocol_address ( ) ) ;
2019-03-12 15:30:36 +03:00
response . set_sender_hardware_address ( adapter - > mac_address ( ) ) ;
response . set_sender_protocol_address ( adapter - > ipv4_address ( ) ) ;
2019-03-12 01:21:38 +03:00
2019-03-12 15:30:36 +03:00
adapter - > send ( packet . sender_hardware_address ( ) , response ) ;
2019-03-12 01:21:38 +03:00
}
2019-03-12 02:56:33 +03:00
return ;
}
2019-03-12 01:21:38 +03:00
}
2021-02-28 04:48:45 +03:00
void handle_ipv4 ( const EthernetFrameHeader & eth , size_t frame_size , const Time & packet_timestamp )
2019-03-12 01:21:38 +03:00
{
2019-08-09 11:42:01 +03:00
constexpr size_t minimum_ipv4_frame_size = sizeof ( EthernetFrameHeader ) + sizeof ( IPv4Packet ) ;
2019-03-12 06:11:20 +03:00
if ( frame_size < minimum_ipv4_frame_size ) {
2021-03-12 13:59:41 +03:00
dbgln ( " handle_ipv4: Frame too small ({}, need {}) " , frame_size , minimum_ipv4_frame_size ) ;
2019-03-12 06:11:20 +03:00
return ;
}
auto & packet = * static_cast < const IPv4Packet * > ( eth . payload ( ) ) ;
2019-03-12 01:21:38 +03:00
2019-08-09 10:36:06 +03:00
if ( packet . length ( ) < sizeof ( IPv4Packet ) ) {
2021-03-12 13:59:41 +03:00
dbgln ( " handle_ipv4: IPv4 packet too short ({}, need {}) " , packet . length ( ) , sizeof ( IPv4Packet ) ) ;
2019-08-09 10:36:06 +03:00
return ;
}
size_t actual_ipv4_packet_length = frame_size - sizeof ( EthernetFrameHeader ) ;
if ( packet . length ( ) > actual_ipv4_packet_length ) {
2021-03-12 13:59:41 +03:00
dbgln ( " handle_ipv4: IPv4 packet claims to be longer than it is ({}, actually {}) " , packet . length ( ) , actual_ipv4_packet_length ) ;
2019-08-09 10:36:06 +03:00
return ;
}
2021-03-12 13:59:41 +03:00
dbgln_if ( IPV4_DEBUG , " handle_ipv4: source={}, destination={} " , packet . source ( ) , packet . destination ( ) ) ;
2019-03-12 06:11:20 +03:00
2019-03-12 14:43:30 +03:00
switch ( ( IPv4Protocol ) packet . protocol ( ) ) {
2019-03-12 06:11:20 +03:00
case IPv4Protocol : : ICMP :
2020-09-16 19:25:06 +03:00
return handle_icmp ( eth , packet , packet_timestamp ) ;
2019-03-13 16:22:27 +03:00
case IPv4Protocol : : UDP :
2020-09-16 19:25:06 +03:00
return handle_udp ( packet , packet_timestamp ) ;
2019-03-13 19:17:07 +03:00
case IPv4Protocol : : TCP :
2020-09-16 19:25:06 +03:00
return handle_tcp ( packet , packet_timestamp ) ;
2019-03-12 06:11:20 +03:00
default :
2021-03-12 13:59:41 +03:00
dbgln ( " handle_ipv4: Unhandled protocol {:#02x} " , packet . protocol ( ) ) ;
2019-03-12 06:11:20 +03:00
break ;
}
}
2021-02-28 04:48:45 +03:00
void handle_icmp ( const EthernetFrameHeader & eth , const IPv4Packet & ipv4_packet , const Time & packet_timestamp )
2019-03-12 06:11:20 +03:00
{
auto & icmp_header = * static_cast < const ICMPHeader * > ( ipv4_packet . payload ( ) ) ;
2021-03-12 13:59:41 +03:00
dbgln_if ( ICMP_DEBUG , " handle_icmp: source={}, destination={}, type={:#02x}, code={:#02x} " , ipv4_packet . source ( ) . to_string ( ) , ipv4_packet . destination ( ) . to_string ( ) , icmp_header . type ( ) , icmp_header . code ( ) ) ;
2019-03-12 14:43:30 +03:00
2019-03-12 19:27:07 +03:00
{
2021-02-12 16:49:34 +03:00
NonnullRefPtrVector < IPv4Socket > icmp_sockets ;
{
2021-04-25 01:27:32 +03:00
Locker locker ( IPv4Socket : : all_sockets ( ) . lock ( ) , Lock : : Mode : : Shared ) ;
2021-02-12 16:49:34 +03:00
for ( auto * socket : IPv4Socket : : all_sockets ( ) . resource ( ) ) {
if ( socket - > protocol ( ) ! = ( unsigned ) IPv4Protocol : : ICMP )
continue ;
icmp_sockets . append ( * socket ) ;
}
2019-03-12 19:27:07 +03:00
}
2021-02-12 16:49:34 +03:00
for ( auto & socket : icmp_sockets )
socket . did_receive ( ipv4_packet . source ( ) , 0 , KBuffer : : copy ( & ipv4_packet , sizeof ( IPv4Packet ) + ipv4_packet . payload_size ( ) ) , packet_timestamp ) ;
2019-03-12 19:27:07 +03:00
}
2019-08-09 05:34:32 +03:00
auto adapter = NetworkAdapter : : from_ipv4_address ( ipv4_packet . destination ( ) ) ;
2019-03-12 15:30:36 +03:00
if ( ! adapter )
2019-03-12 14:43:30 +03:00
return ;
if ( icmp_header . type ( ) = = ICMPType : : EchoRequest ) {
auto & request = reinterpret_cast < const ICMPEchoPacket & > ( icmp_header ) ;
2021-03-12 13:59:41 +03:00
dbgln ( " handle_icmp: EchoRequest from {}: id={}, seq={} " , ipv4_packet . source ( ) , ( u16 ) request . identifier , ( u16 ) request . sequence_number ) ;
2019-03-12 14:43:30 +03:00
size_t icmp_packet_size = ipv4_packet . payload_size ( ) ;
2020-10-20 18:53:11 +03:00
if ( icmp_packet_size < sizeof ( ICMPEchoPacket ) ) {
2021-03-12 13:59:41 +03:00
dbgln ( " handle_icmp: EchoRequest packet is too small, ignoring. " ) ;
2020-10-20 18:53:11 +03:00
return ;
}
2019-03-12 14:43:30 +03:00
auto buffer = ByteBuffer : : create_zeroed ( icmp_packet_size ) ;
2019-09-30 09:57:01 +03:00
auto & response = * ( ICMPEchoPacket * ) buffer . data ( ) ;
2019-03-12 14:43:30 +03:00
response . header . set_type ( ICMPType : : EchoReply ) ;
response . header . set_code ( 0 ) ;
response . identifier = request . identifier ;
response . sequence_number = request . sequence_number ;
if ( size_t icmp_payload_size = icmp_packet_size - sizeof ( ICMPEchoPacket ) )
memcpy ( response . payload ( ) , request . payload ( ) , icmp_payload_size ) ;
response . header . set_checksum ( internet_checksum ( & response , icmp_packet_size ) ) ;
2019-09-19 22:40:06 +03:00
// FIXME: What is the right TTL value here? Is 64 ok? Should we use the same TTL as the echo request?
2020-09-12 06:11:07 +03:00
auto response_buffer = UserOrKernelBuffer : : for_kernel_buffer ( ( u8 * ) & response ) ;
2021-01-31 14:13:16 +03:00
[[maybe_unused]] auto result = adapter - > send_ipv4 ( eth . source ( ) , ipv4_packet . source ( ) , IPv4Protocol : : ICMP , response_buffer , buffer . size ( ) , 64 ) ;
2019-03-12 06:11:20 +03:00
}
2019-03-12 01:21:38 +03:00
}
2019-03-13 16:22:27 +03:00
2021-02-28 04:48:45 +03:00
void handle_udp ( const IPv4Packet & ipv4_packet , const Time & packet_timestamp )
2019-03-13 16:22:27 +03:00
{
2019-08-09 11:42:01 +03:00
if ( ipv4_packet . payload_size ( ) < sizeof ( UDPPacket ) ) {
2021-03-12 13:59:41 +03:00
dbgln ( " handle_udp: Packet too small ({}, need {}) " , ipv4_packet . payload_size ( ) , sizeof ( UDPPacket ) ) ;
2019-08-09 11:42:01 +03:00
return ;
}
2019-03-13 16:22:27 +03:00
2019-08-09 05:34:32 +03:00
auto adapter = NetworkAdapter : : from_ipv4_address ( ipv4_packet . destination ( ) ) ;
2020-04-04 13:03:47 +03:00
if ( ! adapter & & ipv4_packet . destination ( ) ! = IPv4Address ( 255 , 255 , 255 , 255 ) ) {
2021-03-12 13:59:41 +03:00
dbgln ( " handle_udp: this packet is not for me, it's for {} " , ipv4_packet . destination ( ) ) ;
2019-03-13 16:22:27 +03:00
return ;
}
auto & udp_packet = * static_cast < const UDPPacket * > ( ipv4_packet . payload ( ) ) ;
2021-03-12 13:59:41 +03:00
dbgln_if ( UDP_DEBUG , " handle_udp: source={}:{}, destination={}:{}, length={} " ,
ipv4_packet . source ( ) , udp_packet . source_port ( ) ,
ipv4_packet . destination ( ) , udp_packet . destination_port ( ) ,
udp_packet . length ( ) ) ;
2019-03-13 16:22:27 +03:00
2019-03-14 14:43:18 +03:00
auto socket = UDPSocket : : from_port ( udp_packet . destination_port ( ) ) ;
2019-03-14 11:19:24 +03:00
if ( ! socket ) {
2021-03-12 13:59:41 +03:00
dbgln ( " handle_udp: No local UDP socket for {}:{} " , ipv4_packet . destination ( ) , udp_packet . destination_port ( ) ) ;
2019-03-14 11:19:24 +03:00
return ;
2019-03-13 16:22:27 +03:00
}
2019-03-13 18:23:22 +03:00
2021-02-23 22:42:32 +03:00
VERIFY ( socket - > type ( ) = = SOCK_DGRAM ) ;
VERIFY ( socket - > local_port ( ) = = udp_packet . destination_port ( ) ) ;
2020-09-16 19:25:06 +03:00
socket - > did_receive ( ipv4_packet . source ( ) , udp_packet . source_port ( ) , KBuffer : : copy ( & ipv4_packet , sizeof ( IPv4Packet ) + ipv4_packet . payload_size ( ) ) , packet_timestamp ) ;
2019-03-13 16:22:27 +03:00
}
2019-03-13 19:17:07 +03:00
2021-02-28 04:48:45 +03:00
void handle_tcp ( const IPv4Packet & ipv4_packet , const Time & packet_timestamp )
2019-03-13 19:17:07 +03:00
{
2019-08-09 11:42:01 +03:00
if ( ipv4_packet . payload_size ( ) < sizeof ( TCPPacket ) ) {
2021-03-12 13:59:41 +03:00
dbgln ( " handle_tcp: IPv4 payload is too small to be a TCP packet ({}, need {}) " , ipv4_packet . payload_size ( ) , sizeof ( TCPPacket ) ) ;
2019-03-13 19:17:07 +03:00
return ;
}
auto & tcp_packet = * static_cast < const TCPPacket * > ( ipv4_packet . payload ( ) ) ;
2019-08-09 11:42:01 +03:00
size_t minimum_tcp_header_size = 5 * sizeof ( u32 ) ;
size_t maximum_tcp_header_size = 15 * sizeof ( u32 ) ;
if ( tcp_packet . header_size ( ) < minimum_tcp_header_size | | tcp_packet . header_size ( ) > maximum_tcp_header_size ) {
2021-03-12 13:59:41 +03:00
dbgln ( " handle_tcp: TCP packet header has invalid size {} " , tcp_packet . header_size ( ) ) ;
2019-08-09 11:42:01 +03:00
}
if ( ipv4_packet . payload_size ( ) < tcp_packet . header_size ( ) ) {
2021-03-12 13:59:41 +03:00
dbgln ( " handle_tcp: IPv4 payload is smaller than TCP header claims ({}, supposedly {}) " , ipv4_packet . payload_size ( ) , tcp_packet . header_size ( ) ) ;
2019-08-09 11:42:01 +03:00
return ;
}
2019-03-14 03:42:29 +03:00
size_t payload_size = ipv4_packet . payload_size ( ) - tcp_packet . header_size ( ) ;
2021-03-12 13:59:41 +03:00
dbgln_if ( TCP_DEBUG , " handle_tcp: source={}:{}, destination={}:{}, seq_no={}, ack_no={}, flags={:#04x} ({}{}{}{}), window_size={}, payload_size={} " ,
2020-12-25 19:05:05 +03:00
ipv4_packet . source ( ) . to_string ( ) ,
tcp_packet . source_port ( ) ,
ipv4_packet . destination ( ) . to_string ( ) ,
tcp_packet . destination_port ( ) ,
tcp_packet . sequence_number ( ) ,
tcp_packet . ack_number ( ) ,
tcp_packet . flags ( ) ,
tcp_packet . has_syn ( ) ? " SYN " : " " ,
tcp_packet . has_ack ( ) ? " ACK " : " " ,
tcp_packet . has_fin ( ) ? " FIN " : " " ,
tcp_packet . has_rst ( ) ? " RST " : " " ,
tcp_packet . window_size ( ) ,
payload_size ) ;
2019-03-13 19:17:07 +03:00
2019-08-09 11:42:01 +03:00
auto adapter = NetworkAdapter : : from_ipv4_address ( ipv4_packet . destination ( ) ) ;
if ( ! adapter ) {
2021-03-12 13:59:41 +03:00
dbgln ( " handle_tcp: this packet is not for me, it's for {} " , ipv4_packet . destination ( ) ) ;
2019-08-09 11:42:01 +03:00
return ;
}
2019-08-06 16:40:38 +03:00
IPv4SocketTuple tuple ( ipv4_packet . destination ( ) , tcp_packet . destination_port ( ) , ipv4_packet . source ( ) , tcp_packet . source_port ( ) ) ;
2021-03-12 13:59:41 +03:00
dbgln_if ( TCP_DEBUG , " handle_tcp: looking for socket; tuple={} " , tuple . to_string ( ) ) ;
2019-08-09 05:35:56 +03:00
2019-08-06 16:40:38 +03:00
auto socket = TCPSocket : : from_tuple ( tuple ) ;
2019-03-14 11:19:24 +03:00
if ( ! socket ) {
2020-12-25 19:05:05 +03:00
dbgln ( " handle_tcp: No TCP socket for tuple {} " , tuple . to_string ( ) ) ;
dbgln ( " handle_tcp: source={}:{}, destination={}:{}, seq_no={}, ack_no={}, flags={:#04x} ({}{}{}{}), window_size={}, payload_size={} " ,
ipv4_packet . source ( ) . to_string ( ) , tcp_packet . source_port ( ) ,
ipv4_packet . destination ( ) . to_string ( ) ,
tcp_packet . destination_port ( ) ,
tcp_packet . sequence_number ( ) ,
tcp_packet . ack_number ( ) ,
tcp_packet . flags ( ) ,
tcp_packet . has_syn ( ) ? " SYN " : " " ,
tcp_packet . has_ack ( ) ? " ACK " : " " ,
tcp_packet . has_fin ( ) ? " FIN " : " " ,
tcp_packet . has_rst ( ) ? " RST " : " " ,
tcp_packet . window_size ( ) ,
payload_size ) ;
2019-03-14 11:19:24 +03:00
return ;
2019-03-13 19:17:07 +03:00
}
2021-04-25 01:27:32 +03:00
Locker locker ( socket - > lock ( ) ) ;
2020-10-21 21:51:02 +03:00
2021-02-23 22:42:32 +03:00
VERIFY ( socket - > type ( ) = = SOCK_STREAM ) ;
VERIFY ( socket - > local_port ( ) = = tcp_packet . destination_port ( ) ) ;
2019-03-14 01:14:30 +03:00
2021-03-12 13:59:41 +03:00
dbgln_if ( TCP_DEBUG , " handle_tcp: got socket {}; state={} " , socket - > tuple ( ) . to_string ( ) , TCPSocket : : to_string ( socket - > state ( ) ) ) ;
2019-08-09 05:35:56 +03:00
2019-09-08 10:38:08 +03:00
socket - > receive_tcp_packet ( tcp_packet , ipv4_packet . payload_size ( ) ) ;
2019-08-08 05:32:35 +03:00
2020-12-21 02:09:48 +03:00
[[maybe_unused]] int unused_rc { } ;
2019-08-06 16:40:38 +03:00
switch ( socket - > state ( ) ) {
case TCPSocket : : State : : Closed :
2021-03-12 13:59:41 +03:00
dbgln ( " handle_tcp: unexpected flags in Closed state " ) ;
2019-08-08 05:29:34 +03:00
// TODO: we may want to send an RST here, maybe as a configurable option
2019-03-14 17:23:32 +03:00
return ;
2019-08-06 16:40:38 +03:00
case TCPSocket : : State : : TimeWait :
2021-03-12 13:59:41 +03:00
dbgln ( " handle_tcp: unexpected flags in TimeWait state " ) ;
2020-12-21 02:09:48 +03:00
unused_rc = socket - > send_tcp_packet ( TCPFlags : : RST ) ;
2019-08-06 16:40:38 +03:00
socket - > set_state ( TCPSocket : : State : : Closed ) ;
return ;
case TCPSocket : : State : : Listen :
switch ( tcp_packet . flags ( ) ) {
2019-08-09 05:48:28 +03:00
case TCPFlags : : SYN : {
2021-03-12 13:59:41 +03:00
dbgln_if ( TCP_DEBUG , " handle_tcp: incoming connection " ) ;
2019-08-09 05:48:28 +03:00
auto & local_address = ipv4_packet . destination ( ) ;
auto & peer_address = ipv4_packet . source ( ) ;
auto client = socket - > create_client ( local_address , tcp_packet . destination_port ( ) , peer_address , tcp_packet . source_port ( ) ) ;
if ( ! client ) {
2021-03-12 13:59:41 +03:00
dmesgln ( " handle_tcp: couldn't create client socket " ) ;
2019-08-09 05:48:28 +03:00
return ;
}
2021-04-25 01:27:32 +03:00
Locker locker ( client - > lock ( ) ) ;
2021-03-12 13:59:41 +03:00
dbgln_if ( TCP_DEBUG , " handle_tcp: created new client socket with tuple {} " , client - > tuple ( ) . to_string ( ) ) ;
2019-08-09 05:48:28 +03:00
client - > set_sequence_number ( 1000 ) ;
client - > set_ack_number ( tcp_packet . sequence_number ( ) + payload_size + 1 ) ;
2020-12-21 02:09:48 +03:00
[[maybe_unused]] auto rc2 = client - > send_tcp_packet ( TCPFlags : : SYN | TCPFlags : : ACK ) ;
2019-08-09 05:48:28 +03:00
client - > set_state ( TCPSocket : : State : : SynReceived ) ;
2019-08-06 16:40:38 +03:00
return ;
2019-08-09 05:48:28 +03:00
}
2019-08-06 16:40:38 +03:00
default :
2021-03-12 13:59:41 +03:00
dbgln ( " handle_tcp: unexpected flags in Listen state " ) ;
2020-12-21 02:09:48 +03:00
// socket->send_tcp_packet(TCPFlags::RST);
2019-08-06 16:40:38 +03:00
return ;
}
case TCPSocket : : State : : SynSent :
switch ( tcp_packet . flags ( ) ) {
case TCPFlags : : SYN :
socket - > set_ack_number ( tcp_packet . sequence_number ( ) + payload_size + 1 ) ;
2020-12-21 02:09:48 +03:00
unused_rc = socket - > send_tcp_packet ( TCPFlags : : ACK ) ;
2019-08-06 16:40:38 +03:00
socket - > set_state ( TCPSocket : : State : : SynReceived ) ;
return ;
2019-08-10 06:18:18 +03:00
case TCPFlags : : ACK | TCPFlags : : SYN :
2019-08-06 16:40:38 +03:00
socket - > set_ack_number ( tcp_packet . sequence_number ( ) + payload_size + 1 ) ;
2020-12-21 02:09:48 +03:00
unused_rc = socket - > send_tcp_packet ( TCPFlags : : ACK ) ;
2019-08-06 16:40:38 +03:00
socket - > set_state ( TCPSocket : : State : : Established ) ;
2019-08-10 06:17:00 +03:00
socket - > set_setup_state ( Socket : : SetupState : : Completed ) ;
2019-08-06 16:40:38 +03:00
socket - > set_connected ( true ) ;
return ;
2019-08-10 06:18:18 +03:00
case TCPFlags : : ACK | TCPFlags : : FIN :
socket - > set_ack_number ( tcp_packet . sequence_number ( ) + payload_size + 1 ) ;
2020-12-21 02:09:48 +03:00
unused_rc = socket - > send_tcp_packet ( TCPFlags : : ACK ) ;
2019-08-10 06:18:18 +03:00
socket - > set_state ( TCPSocket : : State : : Closed ) ;
socket - > set_error ( TCPSocket : : Error : : FINDuringConnect ) ;
socket - > set_setup_state ( Socket : : SetupState : : Completed ) ;
return ;
case TCPFlags : : ACK | TCPFlags : : RST :
2019-09-08 10:02:40 +03:00
socket - > set_ack_number ( tcp_packet . sequence_number ( ) + payload_size ) ;
2020-12-21 02:09:48 +03:00
unused_rc = socket - > send_tcp_packet ( TCPFlags : : ACK ) ;
2019-08-10 06:18:18 +03:00
socket - > set_state ( TCPSocket : : State : : Closed ) ;
socket - > set_error ( TCPSocket : : Error : : RSTDuringConnect ) ;
socket - > set_setup_state ( Socket : : SetupState : : Completed ) ;
return ;
2019-08-06 16:40:38 +03:00
default :
2021-03-12 13:59:41 +03:00
dbgln ( " handle_tcp: unexpected flags in SynSent state " ) ;
2020-12-21 02:09:48 +03:00
unused_rc = socket - > send_tcp_packet ( TCPFlags : : RST ) ;
2019-08-06 16:40:38 +03:00
socket - > set_state ( TCPSocket : : State : : Closed ) ;
2019-08-10 06:18:18 +03:00
socket - > set_error ( TCPSocket : : Error : : UnexpectedFlagsDuringConnect ) ;
2019-08-10 06:17:00 +03:00
socket - > set_setup_state ( Socket : : SetupState : : Completed ) ;
2019-08-06 16:40:38 +03:00
return ;
}
case TCPSocket : : State : : SynReceived :
switch ( tcp_packet . flags ( ) ) {
case TCPFlags : : ACK :
2019-09-08 10:02:40 +03:00
socket - > set_ack_number ( tcp_packet . sequence_number ( ) + payload_size ) ;
2019-09-08 12:37:05 +03:00
switch ( socket - > direction ( ) ) {
case TCPSocket : : Direction : : Incoming :
if ( ! socket - > has_originator ( ) ) {
2021-03-12 13:59:41 +03:00
dbgln ( " handle_tcp: connection doesn't have an originating socket; maybe it went away? " ) ;
2020-12-21 02:09:48 +03:00
unused_rc = socket - > send_tcp_packet ( TCPFlags : : RST ) ;
2019-09-08 12:37:05 +03:00
socket - > set_state ( TCPSocket : : State : : Closed ) ;
return ;
}
socket - > set_state ( TCPSocket : : State : : Established ) ;
socket - > set_setup_state ( Socket : : SetupState : : Completed ) ;
socket - > release_to_originator ( ) ;
return ;
case TCPSocket : : Direction : : Outgoing :
socket - > set_state ( TCPSocket : : State : : Established ) ;
socket - > set_setup_state ( Socket : : SetupState : : Completed ) ;
2019-08-09 05:48:28 +03:00
socket - > set_connected ( true ) ;
2019-09-08 12:37:05 +03:00
return ;
default :
2021-03-12 13:59:41 +03:00
dbgln ( " handle_tcp: got ACK in SynReceived state but direction is invalid ({}) " , TCPSocket : : to_string ( socket - > direction ( ) ) ) ;
2020-12-21 02:09:48 +03:00
unused_rc = socket - > send_tcp_packet ( TCPFlags : : RST ) ;
2019-09-08 12:37:05 +03:00
socket - > set_state ( TCPSocket : : State : : Closed ) ;
return ;
}
2019-08-06 16:40:38 +03:00
return ;
default :
2021-03-12 13:59:41 +03:00
dbgln ( " handle_tcp: unexpected flags in SynReceived state " ) ;
2020-12-21 02:09:48 +03:00
unused_rc = socket - > send_tcp_packet ( TCPFlags : : RST ) ;
2019-08-06 16:40:38 +03:00
socket - > set_state ( TCPSocket : : State : : Closed ) ;
return ;
}
case TCPSocket : : State : : CloseWait :
switch ( tcp_packet . flags ( ) ) {
default :
2021-03-12 13:59:41 +03:00
dbgln ( " handle_tcp: unexpected flags in CloseWait state " ) ;
2020-12-21 02:09:48 +03:00
unused_rc = socket - > send_tcp_packet ( TCPFlags : : RST ) ;
2019-08-06 16:40:38 +03:00
socket - > set_state ( TCPSocket : : State : : Closed ) ;
return ;
}
case TCPSocket : : State : : LastAck :
switch ( tcp_packet . flags ( ) ) {
case TCPFlags : : ACK :
2019-09-08 10:02:40 +03:00
socket - > set_ack_number ( tcp_packet . sequence_number ( ) + payload_size ) ;
2019-08-06 16:40:38 +03:00
socket - > set_state ( TCPSocket : : State : : Closed ) ;
return ;
default :
2021-03-12 13:59:41 +03:00
dbgln ( " handle_tcp: unexpected flags in LastAck state " ) ;
2020-12-21 02:09:48 +03:00
unused_rc = socket - > send_tcp_packet ( TCPFlags : : RST ) ;
2019-08-06 16:40:38 +03:00
socket - > set_state ( TCPSocket : : State : : Closed ) ;
return ;
}
case TCPSocket : : State : : FinWait1 :
switch ( tcp_packet . flags ( ) ) {
case TCPFlags : : ACK :
2019-09-08 10:02:40 +03:00
socket - > set_ack_number ( tcp_packet . sequence_number ( ) + payload_size ) ;
2019-08-06 16:40:38 +03:00
socket - > set_state ( TCPSocket : : State : : FinWait2 ) ;
return ;
case TCPFlags : : FIN :
socket - > set_ack_number ( tcp_packet . sequence_number ( ) + payload_size + 1 ) ;
socket - > set_state ( TCPSocket : : State : : Closing ) ;
return ;
default :
2021-03-12 13:59:41 +03:00
dbgln ( " handle_tcp: unexpected flags in FinWait1 state " ) ;
2020-12-21 02:09:48 +03:00
unused_rc = socket - > send_tcp_packet ( TCPFlags : : RST ) ;
2019-08-06 16:40:38 +03:00
socket - > set_state ( TCPSocket : : State : : Closed ) ;
return ;
}
case TCPSocket : : State : : FinWait2 :
switch ( tcp_packet . flags ( ) ) {
case TCPFlags : : FIN :
socket - > set_ack_number ( tcp_packet . sequence_number ( ) + payload_size + 1 ) ;
socket - > set_state ( TCPSocket : : State : : TimeWait ) ;
return ;
2020-02-08 17:52:32 +03:00
case TCPFlags : : ACK | TCPFlags : : RST :
socket - > set_state ( TCPSocket : : State : : Closed ) ;
return ;
2019-08-06 16:40:38 +03:00
default :
2021-03-12 13:59:41 +03:00
dbgln ( " handle_tcp: unexpected flags in FinWait2 state " ) ;
2020-12-21 02:09:48 +03:00
unused_rc = socket - > send_tcp_packet ( TCPFlags : : RST ) ;
2019-08-06 16:40:38 +03:00
socket - > set_state ( TCPSocket : : State : : Closed ) ;
return ;
}
case TCPSocket : : State : : Closing :
switch ( tcp_packet . flags ( ) ) {
case TCPFlags : : ACK :
2019-09-08 10:02:40 +03:00
socket - > set_ack_number ( tcp_packet . sequence_number ( ) + payload_size ) ;
2019-08-06 16:40:38 +03:00
socket - > set_state ( TCPSocket : : State : : TimeWait ) ;
return ;
default :
2021-03-12 13:59:41 +03:00
dbgln ( " handle_tcp: unexpected flags in Closing state " ) ;
2020-12-21 02:09:48 +03:00
unused_rc = socket - > send_tcp_packet ( TCPFlags : : RST ) ;
2019-08-06 16:40:38 +03:00
socket - > set_state ( TCPSocket : : State : : Closed ) ;
return ;
}
case TCPSocket : : State : : Established :
if ( tcp_packet . has_fin ( ) ) {
if ( payload_size ! = 0 )
2020-09-16 19:25:06 +03:00
socket - > did_receive ( ipv4_packet . source ( ) , tcp_packet . source_port ( ) , KBuffer : : copy ( & ipv4_packet , sizeof ( IPv4Packet ) + ipv4_packet . payload_size ( ) ) , packet_timestamp ) ;
2019-08-06 16:40:38 +03:00
socket - > set_ack_number ( tcp_packet . sequence_number ( ) + payload_size + 1 ) ;
2020-12-21 02:09:48 +03:00
unused_rc = socket - > send_tcp_packet ( TCPFlags : : ACK ) ;
2020-02-08 17:52:32 +03:00
socket - > set_state ( TCPSocket : : State : : CloseWait ) ;
2019-08-06 16:40:38 +03:00
socket - > set_connected ( false ) ;
return ;
}
socket - > set_ack_number ( tcp_packet . sequence_number ( ) + payload_size ) ;
2019-03-14 17:23:32 +03:00
2021-03-12 13:59:41 +03:00
dbgln_if ( TCP_DEBUG , " Got packet with ack_no={}, seq_no={}, payload_size={}, acking it with new ack_no={}, seq_no={} " ,
tcp_packet . ack_number ( ) , tcp_packet . sequence_number ( ) , payload_size , socket - > ack_number ( ) , socket - > sequence_number ( ) ) ;
2019-03-14 02:20:44 +03:00
2020-02-08 16:09:02 +03:00
if ( payload_size ) {
2020-09-16 19:25:06 +03:00
if ( socket - > did_receive ( ipv4_packet . source ( ) , tcp_packet . source_port ( ) , KBuffer : : copy ( & ipv4_packet , sizeof ( IPv4Packet ) + ipv4_packet . payload_size ( ) ) , packet_timestamp ) )
2020-12-21 02:09:48 +03:00
unused_rc = socket - > send_tcp_packet ( TCPFlags : : ACK ) ;
2019-11-04 16:03:14 +03:00
}
2019-08-06 16:40:38 +03:00
}
2019-03-13 19:17:07 +03:00
}
2020-02-16 03:27:42 +03:00
}