mirror of
				https://github.com/RGBCube/serenity
				synced 2025-10-31 01:22:43 +00:00 
			
		
		
		
	Kernel: Don't try to send TCP packets larger than the MSS
Previously TCPSocket::send_tcp_packet() would try to send TCP packets which matched whatever size the userspace program specified. We'd try to break those packets up into smaller fragments, however a much better approach is to limit TCP packets to the maximum segment size and avoid fragmentation altogether.
This commit is contained in:
		
							parent
							
								
									dce97678ae
								
							
						
					
					
						commit
						c6299d1e5d
					
				
					 2 changed files with 10 additions and 4 deletions
				
			
		|  | @ -9,6 +9,7 @@ | |||
| #include <Kernel/Debug.h> | ||||
| #include <Kernel/Devices/RandomDevice.h> | ||||
| #include <Kernel/FileSystem/FileDescription.h> | ||||
| #include <Kernel/Net/EthernetFrameHeader.h> | ||||
| #include <Kernel/Net/IPv4.h> | ||||
| #include <Kernel/Net/NetworkAdapter.h> | ||||
| #include <Kernel/Net/Routing.h> | ||||
|  | @ -167,7 +168,12 @@ KResultOr<size_t> TCPSocket::protocol_receive(ReadonlyBytes raw_ipv4_packet, Use | |||
| 
 | ||||
| KResultOr<size_t> TCPSocket::protocol_send(const UserOrKernelBuffer& data, size_t data_length) | ||||
| { | ||||
|     int err = send_tcp_packet(TCPFlags::PUSH | TCPFlags::ACK, &data, data_length); | ||||
|     RoutingDecision routing_decision = route_to(peer_address(), local_address(), bound_interface()); | ||||
|     if (routing_decision.is_zero()) | ||||
|         return EHOSTUNREACH; | ||||
|     size_t mss = routing_decision.adapter->mtu() - sizeof(IPv4Packet) - sizeof(TCPPacket); | ||||
|     data_length = min(data_length, mss); | ||||
|     int err = send_tcp_packet(TCPFlags::PUSH | TCPFlags::ACK, &data, data_length, &routing_decision); | ||||
|     if (err < 0) | ||||
|         return KResult((ErrnoCode)-err); | ||||
|     return data_length; | ||||
|  | @ -180,7 +186,7 @@ KResult TCPSocket::send_ack(bool allow_duplicate) | |||
|     return send_tcp_packet(TCPFlags::ACK); | ||||
| } | ||||
| 
 | ||||
| KResult TCPSocket::send_tcp_packet(u16 flags, const UserOrKernelBuffer* payload, size_t payload_size) | ||||
| KResult TCPSocket::send_tcp_packet(u16 flags, const UserOrKernelBuffer* payload, size_t payload_size, RoutingDecision* user_routing_decision) | ||||
| { | ||||
|     const bool has_mss_option = flags == TCPFlags::SYN; | ||||
|     const size_t options_size = has_mss_option ? sizeof(TCPOptionMSS) : 0; | ||||
|  | @ -211,7 +217,7 @@ KResult TCPSocket::send_tcp_packet(u16 flags, const UserOrKernelBuffer* payload, | |||
|         m_sequence_number += payload_size; | ||||
|     } | ||||
| 
 | ||||
|     auto routing_decision = route_to(peer_address(), local_address(), bound_interface()); | ||||
|     RoutingDecision routing_decision = user_routing_decision ? *user_routing_decision : route_to(peer_address(), local_address(), bound_interface()); | ||||
|     if (routing_decision.is_zero()) | ||||
|         return EHOSTUNREACH; | ||||
| 
 | ||||
|  |  | |||
|  | @ -136,7 +136,7 @@ public: | |||
|     u32 duplicate_acks() const { return m_duplicate_acks; } | ||||
| 
 | ||||
|     KResult send_ack(bool allow_duplicate = false); | ||||
|     KResult send_tcp_packet(u16 flags, const UserOrKernelBuffer* = nullptr, size_t = 0); | ||||
|     KResult send_tcp_packet(u16 flags, const UserOrKernelBuffer* = nullptr, size_t = 0, RoutingDecision* = nullptr); | ||||
|     void receive_tcp_packet(const TCPPacket&, u16 size); | ||||
| 
 | ||||
|     bool should_delay_next_ack() const; | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Gunnar Beutner
						Gunnar Beutner