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