2020-01-18 11:38:21 +03:00
/*
* Copyright ( c ) 2018 - 2020 , Andreas Kling < kling @ serenityos . org >
* All rights reserved .
*
* Redistribution and use in source and binary forms , with or without
* modification , are permitted provided that the following conditions are met :
*
* 1. Redistributions of source code must retain the above copyright notice , this
* list of conditions and the following disclaimer .
*
* 2. Redistributions in binary form must reproduce the above copyright notice ,
* this list of conditions and the following disclaimer in the documentation
* and / or other materials provided with the distribution .
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS " AS IS "
* AND ANY EXPRESS OR IMPLIED WARRANTIES , INCLUDING , BUT NOT LIMITED TO , THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED . IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT , INDIRECT , INCIDENTAL , SPECIAL , EXEMPLARY , OR CONSEQUENTIAL
* DAMAGES ( INCLUDING , BUT NOT LIMITED TO , PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES ; LOSS OF USE , DATA , OR PROFITS ; OR BUSINESS INTERRUPTION ) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY , WHETHER IN CONTRACT , STRICT LIABILITY ,
* OR TORT ( INCLUDING NEGLIGENCE OR OTHERWISE ) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE , EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE .
*/
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
2019-08-28 14:53:01 +03:00
//#define NETWORK_TASK_DEBUG
2019-03-12 06:11:20 +03:00
//#define ETHERNET_DEBUG
2019-08-06 16:40:38 +03:00
//#define ETHERNET_VERY_DEBUG
2019-08-28 14:58:01 +03:00
//#define ARP_DEBUG
2019-08-04 11:04:06 +03:00
//#define IPV4_DEBUG
2019-03-13 16:22:27 +03:00
//#define ICMP_DEBUG
2019-08-04 11:04:06 +03:00
//#define UDP_DEBUG
//#define TCP_DEBUG
2019-03-12 06:11:20 +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 ) ;
2020-09-16 19:25:06 +03:00
static void handle_ipv4 ( const EthernetFrameHeader & , size_t frame_size , const timeval & packet_timestamp ) ;
static void handle_icmp ( const EthernetFrameHeader & , const IPv4Packet & , const timeval & packet_timestamp ) ;
static void handle_udp ( const IPv4Packet & , const timeval & packet_timestamp ) ;
static void handle_tcp ( const IPv4Packet & , const timeval & 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
u8 octet = 15 ;
int pending_packets = 0 ;
2019-12-01 18:47:49 +03:00
NetworkAdapter : : for_each ( [ & ] ( auto & adapter ) {
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 } ) ;
} else {
adapter . set_ipv4_address ( { 10 , 0 , 2 , octet + + } ) ;
adapter . set_ipv4_netmask ( { 255 , 255 , 255 , 0 } ) ;
adapter . set_ipv4_gateway ( { 10 , 0 , 2 , 2 } ) ;
}
2019-04-02 16:46:44 +03:00
2020-03-01 22:45:39 +03:00
klog ( ) < < " NetworkTask: " < < adapter . class_name ( ) < < " network adapter found: hw= " < < adapter . mac_address ( ) . to_string ( ) . characters ( ) < < " address= " < < adapter . ipv4_address ( ) . to_string ( ) . characters ( ) < < " netmask= " < < adapter . ipv4_netmask ( ) . to_string ( ) . characters ( ) < < " gateway= " < < adapter . ipv4_gateway ( ) . to_string ( ) . characters ( ) ;
2019-05-18 01:22:08 +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
2020-09-16 19:25:06 +03:00
auto dequeue_packet = [ & pending_packets ] ( u8 * buffer , size_t buffer_size , timeval & 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 - - ;
# ifdef NETWORK_TASK_DEBUG
2020-03-01 22:45:39 +03:00
klog ( ) < < " NetworkTask: Dequeued packet from " < < adapter . name ( ) . characters ( ) < < " ( " < < packet_size < < " bytes) " ;
2019-08-28 14:53:01 +03:00
# endif
} ) ;
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 ;
2019-12-28 02:07:56 +03:00
auto buffer_region = MM . allocate_kernel_region ( buffer_size , " Kernel Packet Buffer " , Region : : Access : : Read | Region : : Access : : Write , false , true ) ;
auto buffer = ( u8 * ) buffer_region - > vaddr ( ) . get ( ) ;
2020-09-16 19:25:06 +03:00
timeval packet_timestamp ;
2019-12-28 02:07:56 +03:00
2020-03-01 22:45:39 +03:00
klog ( ) < < " NetworkTask: Enter main loop. " ;
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 ) {
2020-12-08 07:29:41 +03:00
packet_wait_queue . wait_on ( nullptr , " NetworkTask " ) ;
2019-03-11 14:43:45 +03:00
continue ;
}
2019-12-14 13:07:37 +03:00
if ( packet_size < sizeof ( EthernetFrameHeader ) ) {
2020-03-01 22:45:39 +03:00
klog ( ) < < " 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 ;
2019-03-12 06:11:20 +03:00
# ifdef ETHERNET_DEBUG
2020-03-01 22:45:39 +03:00
klog ( ) < < " NetworkTask: From " < < eth . source ( ) . to_string ( ) . characters ( ) < < " to " < < eth . destination ( ) . to_string ( ) . characters ( ) < < " , ether_type= " < < String : : format ( " %w " , eth . ether_type ( ) ) < < " , packet_length= " < < packet_size ;
2019-03-12 06:11:20 +03:00
# endif
2019-03-12 01:21:38 +03:00
2019-08-06 16:40:38 +03:00
# ifdef ETHERNET_VERY_DEBUG
2019-12-14 13:07:37 +03:00
for ( size_t i = 0 ; i < packet_size ; i + + ) {
2020-12-25 18:45:35 +03:00
klog ( ) < < String : : format ( " %#02x " , buffer [ i ] ) ;
2019-08-06 16:40:38 +03:00
switch ( i % 16 ) {
case 7 :
2020-03-01 22:45:39 +03:00
klog ( ) < < " " ;
2019-08-06 16:40:38 +03:00
break ;
case 15 :
2020-03-01 22:45:39 +03:00
klog ( ) < < " " ;
2019-08-06 16:40:38 +03:00
break ;
default :
2020-03-01 22:45:39 +03:00
klog ( ) < < " " ;
2019-08-06 16:40:38 +03:00
break ;
}
}
2020-03-01 22:45:39 +03:00
klog ( ) < < " " ;
2019-08-06 16:40:38 +03:00
# endif
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 :
2020-03-01 22:45:39 +03:00
klog ( ) < < " NetworkTask: Unknown ethernet type 0x " < < String : : format ( " %x " , 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 ) {
2020-03-01 22:45:39 +03:00
klog ( ) < < " handle_arp: Frame too small ( " < < frame_size < < " , need " < < 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-03-01 22:45:39 +03:00
klog ( ) < < " handle_arp: Hardware type not ethernet ( " < < String : : format ( " %w " , packet . hardware_type ( ) ) < < " , len= " < < 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-03-01 22:45:39 +03:00
klog ( ) < < " handle_arp: Protocol type not IPv4 ( " < < String : : format ( " %w " , packet . hardware_type ( ) ) < < " , len= " < < packet . protocol_address_length ( ) < < " ) " ;
2019-03-12 01:21:38 +03:00
return ;
}
# ifdef ARP_DEBUG
2020-03-01 22:45:39 +03:00
klog ( ) < < " handle_arp: operation= " < < String : : format ( " %w " , packet . operation ( ) ) < < " , sender= " < < packet . sender_hardware_address ( ) . to_string ( ) . characters ( ) < < " / " < < packet . sender_protocol_address ( ) . to_string ( ) . characters ( ) < < " , target= " < < packet . target_hardware_address ( ) . to_string ( ) . characters ( ) < < " / " < < packet . target_protocol_address ( ) . to_string ( ) . characters ( ) ;
2019-03-12 01:21:38 +03:00
# endif
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!
2020-03-01 22:45:39 +03:00
klog ( ) < < " handle_arp: Responding to ARP request for my IPv4 address ( " < < adapter - > ipv4_address ( ) . to_string ( ) . characters ( ) < < " ) " ;
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
}
2020-09-16 19:25:06 +03:00
void handle_ipv4 ( const EthernetFrameHeader & eth , size_t frame_size , const timeval & 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 ) {
2020-03-01 22:45:39 +03:00
klog ( ) < < " handle_ipv4: Frame too small ( " < < frame_size < < " , need " < < 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 ) ) {
2020-03-01 22:45:39 +03:00
klog ( ) < < " handle_ipv4: IPv4 packet too short ( " < < packet . length ( ) < < " , need " < < 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 ) {
2020-03-01 22:45:39 +03:00
klog ( ) < < " handle_ipv4: IPv4 packet claims to be longer than it is ( " < < packet . length ( ) < < " , actually " < < actual_ipv4_packet_length < < " ) " ;
2019-08-09 10:36:06 +03:00
return ;
}
2019-03-12 06:11:20 +03:00
# ifdef IPV4_DEBUG
2020-03-01 22:45:39 +03:00
klog ( ) < < " handle_ipv4: source= " < < packet . source ( ) . to_string ( ) . characters ( ) < < " , target= " < < packet . destination ( ) . to_string ( ) . characters ( ) ;
2019-03-12 06:11:20 +03:00
# endif
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 :
2020-03-01 22:45:39 +03:00
klog ( ) < < " handle_ipv4: Unhandled protocol " < < packet . protocol ( ) ;
2019-03-12 06:11:20 +03:00
break ;
}
}
2020-09-16 19:25:06 +03:00
void handle_icmp ( const EthernetFrameHeader & eth , const IPv4Packet & ipv4_packet , const timeval & packet_timestamp )
2019-03-12 06:11:20 +03:00
{
auto & icmp_header = * static_cast < const ICMPHeader * > ( ipv4_packet . payload ( ) ) ;
2019-03-12 13:44:38 +03:00
# ifdef ICMP_DEBUG
2020-12-25 18:45:35 +03:00
dbgln ( " 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 13:44:38 +03:00
# endif
2019-03-12 14:43:30 +03:00
2019-03-12 19:27:07 +03:00
{
LOCKER ( IPv4Socket : : all_sockets ( ) . lock ( ) ) ;
2019-06-21 19:37:47 +03:00
for ( RefPtr < IPv4Socket > socket : IPv4Socket : : all_sockets ( ) . resource ( ) ) {
2019-03-12 19:27:07 +03:00
LOCKER ( socket - > lock ( ) ) ;
if ( socket - > protocol ( ) ! = ( unsigned ) IPv4Protocol : : ICMP )
continue ;
2020-09-16 19:25:06 +03:00
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 ) ;
2020-03-01 22:45:39 +03:00
klog ( ) < < " handle_icmp: EchoRequest from " < < ipv4_packet . source ( ) . to_string ( ) . characters ( ) < < " : id= " < < ( u16 ) request . identifier < < " , seq= " < < ( 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 ) ) {
klog ( ) < < " handle_icmp: EchoRequest packet is too small, ignoring. " ;
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 ) ;
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
2020-09-16 19:25:06 +03:00
void handle_udp ( const IPv4Packet & ipv4_packet , const timeval & 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 ) ) {
2020-03-01 22:45:39 +03:00
klog ( ) < < " handle_udp: Packet too small ( " < < ipv4_packet . payload_size ( ) < < " , need " < < 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 ) ) {
2020-03-01 22:45:39 +03:00
klog ( ) < < " handle_udp: this packet is not for me, it's for " < < ipv4_packet . destination ( ) . to_string ( ) . characters ( ) ;
2019-03-13 16:22:27 +03:00
return ;
}
auto & udp_packet = * static_cast < const UDPPacket * > ( ipv4_packet . payload ( ) ) ;
# ifdef UDP_DEBUG
2020-03-01 22:45:39 +03:00
klog ( ) < < " handle_udp: source= " < < ipv4_packet . source ( ) . to_string ( ) . characters ( ) < < " : " < < udp_packet . source_port ( ) < < " , destination= " < < ipv4_packet . destination ( ) . to_string ( ) . characters ( ) < < " : " < < udp_packet . destination_port ( ) < < " length= " < < udp_packet . length ( ) ;
2019-03-13 16:22:27 +03:00
# endif
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 ) {
2020-03-01 22:45:39 +03:00
klog ( ) < < " handle_udp: No UDP socket for port " < < 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
ASSERT ( socket - > type ( ) = = SOCK_DGRAM ) ;
2019-05-04 17:40:34 +03:00
ASSERT ( 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
2020-09-16 19:25:06 +03:00
void handle_tcp ( const IPv4Packet & ipv4_packet , const timeval & 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 ) ) {
2020-03-01 22:45:39 +03:00
klog ( ) < < " handle_tcp: IPv4 payload is too small to be a TCP packet ( " < < ipv4_packet . payload_size ( ) < < " , need " < < 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 ) {
2020-03-01 22:45:39 +03:00
klog ( ) < < " 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 ( ) ) {
2020-03-01 22:45:39 +03:00
klog ( ) < < " handle_tcp: IPv4 payload is smaller than TCP header claims ( " < < ipv4_packet . payload_size ( ) < < " , supposedly " < < 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 ( ) ;
2019-03-13 19:17:07 +03:00
# ifdef TCP_DEBUG
2020-03-01 22:45:39 +03:00
klog ( ) < < " handle_tcp: source= " < < ipv4_packet . source ( ) . to_string ( ) . characters ( ) < < " : " < < tcp_packet . source_port ( ) < < " , destination= " < < ipv4_packet . destination ( ) . to_string ( ) . characters ( ) < < " : " < < tcp_packet . destination_port ( ) < < " seq_no= " < < tcp_packet . sequence_number ( ) < < " , ack_no= " < < tcp_packet . ack_number ( ) < < " , flags= " < < String : : format ( " %w " , tcp_packet . flags ( ) ) < < " ( " < < ( tcp_packet . has_syn ( ) ? " SYN " : " " ) < < ( tcp_packet . has_ack ( ) ? " ACK " : " " ) < < ( tcp_packet . has_fin ( ) ? " FIN " : " " ) < < ( tcp_packet . has_rst ( ) ? " RST " : " " ) < < " ), window_size= " < < tcp_packet . window_size ( ) < < " , payload_size= " < < payload_size ;
2019-03-13 19:17:07 +03:00
# endif
2019-08-09 11:42:01 +03:00
auto adapter = NetworkAdapter : : from_ipv4_address ( ipv4_packet . destination ( ) ) ;
if ( ! adapter ) {
2020-03-01 22:45:39 +03:00
klog ( ) < < " handle_tcp: this packet is not for me, it's for " < < ipv4_packet . destination ( ) . to_string ( ) . characters ( ) ;
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 ( ) ) ;
2019-08-09 05:35:56 +03:00
# ifdef TCP_DEBUG
2020-03-01 22:45:39 +03:00
klog ( ) < < " handle_tcp: looking for socket; tuple= " < < tuple . to_string ( ) . characters ( ) ;
2019-08-09 05:35:56 +03:00
# endif
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-03-01 22:45:39 +03:00
klog ( ) < < " handle_tcp: No TCP socket for tuple " < < tuple . to_string ( ) . characters ( ) ;
klog ( ) < < " handle_tcp: source= " < < ipv4_packet . source ( ) . to_string ( ) . characters ( ) < < " : " < < tcp_packet . source_port ( ) < < " , destination= " < < ipv4_packet . destination ( ) . to_string ( ) . characters ( ) < < " : " < < tcp_packet . destination_port ( ) < < " seq_no= " < < tcp_packet . sequence_number ( ) < < " , ack_no= " < < tcp_packet . ack_number ( ) < < " , flags= " < < String : : format ( " %w " , tcp_packet . flags ( ) ) < < " ( " < < ( tcp_packet . has_syn ( ) ? " SYN " : " " ) < < ( tcp_packet . has_ack ( ) ? " ACK " : " " ) < < ( tcp_packet . has_fin ( ) ? " FIN " : " " ) < < ( tcp_packet . has_rst ( ) ? " RST " : " " ) < < " ), window_size= " < < tcp_packet . window_size ( ) < < " , payload_size= " < < payload_size ;
2019-03-14 11:19:24 +03:00
return ;
2019-03-13 19:17:07 +03:00
}
2020-10-21 21:51:02 +03:00
LOCKER ( socket - > lock ( ) ) ;
2019-03-13 19:17:07 +03:00
ASSERT ( socket - > type ( ) = = SOCK_STREAM ) ;
2019-05-04 17:40:34 +03:00
ASSERT ( socket - > local_port ( ) = = tcp_packet . destination_port ( ) ) ;
2019-03-14 01:14:30 +03:00
2019-08-09 05:35:56 +03:00
# ifdef TCP_DEBUG
2020-03-01 22:45:39 +03:00
klog ( ) < < " handle_tcp: got socket; state= " < < socket - > tuple ( ) . to_string ( ) . characters ( ) < < " " < < TCPSocket : : to_string ( socket - > state ( ) ) ;
2019-08-09 05:35:56 +03:00
# endif
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 :
2020-03-01 22:45:39 +03:00
klog ( ) < < " 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 :
2020-03-01 22:45:39 +03:00
klog ( ) < < " 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 : {
2019-09-08 12:13:50 +03:00
# ifdef TCP_DEBUG
2020-03-01 22:45:39 +03:00
klog ( ) < < " handle_tcp: incoming connection " ;
2019-09-08 12:13:50 +03:00
# endif
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 ) {
2020-03-01 22:45:39 +03:00
klog ( ) < < " handle_tcp: couldn't create client socket " ;
2019-08-09 05:48:28 +03:00
return ;
}
2020-10-21 21:51:02 +03:00
LOCKER ( client - > lock ( ) ) ;
2019-09-08 12:13:50 +03:00
# ifdef TCP_DEBUG
2020-03-01 22:45:39 +03:00
klog ( ) < < " handle_tcp: created new client socket with tuple " < < client - > tuple ( ) . to_string ( ) . characters ( ) ;
2019-09-08 12:13:50 +03:00
# endif
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 :
2020-03-01 22:45:39 +03:00
klog ( ) < < " 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 :
2020-03-01 22:45:39 +03:00
klog ( ) < < " 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 ( ) ) {
2020-03-01 22:45:39 +03:00
klog ( ) < < " 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 :
2020-03-01 22:45:39 +03:00
klog ( ) < < " 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 :
2020-03-01 22:45:39 +03:00
klog ( ) < < " 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 :
2020-03-01 22:45:39 +03:00
klog ( ) < < " 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 :
2020-03-01 22:45:39 +03:00
klog ( ) < < " 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 :
2020-03-01 22:45:39 +03:00
klog ( ) < < " 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 :
2020-03-01 22:45:39 +03:00
klog ( ) < < " 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 :
2020-03-01 22:45:39 +03:00
klog ( ) < < " 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
2019-08-04 11:04:06 +03:00
# ifdef TCP_DEBUG
2020-03-01 22:45:39 +03:00
klog ( ) < < " Got packet with ack_no= " < < tcp_packet . ack_number ( ) < < " , seq_no= " < < tcp_packet . sequence_number ( ) < < " , payload_size= " < < payload_size < < " , acking it with new ack_no= " < < socket - > ack_number ( ) < < " , seq_no= " < < socket - > sequence_number ( ) ;
2019-08-04 11:04:06 +03:00
# endif
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
}