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