From 2b6aa571d11dad03d5b0f02dd392f6cf10d4f70b Mon Sep 17 00:00:00 2001 From: Gunnar Beutner Date: Wed, 12 May 2021 14:36:09 +0200 Subject: [PATCH] Kernel: Outbound packets should use the source address from the socket Previously we'd use the adapter's address as the source address when sending packets. Instead we should use the socket's bound local address. --- Kernel/Net/IPv4Socket.cpp | 3 ++- Kernel/Net/NetworkAdapter.cpp | 10 +++++----- Kernel/Net/NetworkAdapter.h | 4 ++-- Kernel/Net/NetworkTask.cpp | 3 ++- Kernel/Net/TCPSocket.cpp | 6 +++--- Kernel/Net/UDPSocket.cpp | 3 ++- 6 files changed, 16 insertions(+), 13 deletions(-) diff --git a/Kernel/Net/IPv4Socket.cpp b/Kernel/Net/IPv4Socket.cpp index ad039cd4e7..610274c295 100644 --- a/Kernel/Net/IPv4Socket.cpp +++ b/Kernel/Net/IPv4Socket.cpp @@ -206,7 +206,8 @@ KResultOr IPv4Socket::sendto(FileDescription&, const UserOrKernelBuffer& dbgln_if(IPV4_SOCKET_DEBUG, "sendto: destination={}:{}", m_peer_address, m_peer_port); if (type() == SOCK_RAW) { - auto result = routing_decision.adapter->send_ipv4(routing_decision.next_hop, m_peer_address, (IPv4Protocol)protocol(), data, data_length, m_ttl); + auto result = routing_decision.adapter->send_ipv4(local_address(), routing_decision.next_hop, + m_peer_address, (IPv4Protocol)protocol(), data, data_length, m_ttl); if (result.is_error()) return result; return data_length; diff --git a/Kernel/Net/NetworkAdapter.cpp b/Kernel/Net/NetworkAdapter.cpp index d310912a55..4b5bc33f24 100644 --- a/Kernel/Net/NetworkAdapter.cpp +++ b/Kernel/Net/NetworkAdapter.cpp @@ -83,11 +83,11 @@ void NetworkAdapter::send(const MACAddress& destination, const ARPPacket& packet send_raw({ (const u8*)eth, size_in_bytes }); } -KResult NetworkAdapter::send_ipv4(const MACAddress& destination_mac, const IPv4Address& destination_ipv4, IPv4Protocol protocol, const UserOrKernelBuffer& payload, size_t payload_size, u8 ttl) +KResult NetworkAdapter::send_ipv4(const IPv4Address& source_ipv4, const MACAddress& destination_mac, const IPv4Address& destination_ipv4, IPv4Protocol protocol, const UserOrKernelBuffer& payload, size_t payload_size, u8 ttl) { size_t ipv4_packet_size = sizeof(IPv4Packet) + payload_size; if (ipv4_packet_size > mtu()) - return send_ipv4_fragmented(destination_mac, destination_ipv4, protocol, payload, payload_size, ttl); + return send_ipv4_fragmented(source_ipv4, destination_mac, destination_ipv4, protocol, payload, payload_size, ttl); size_t ethernet_frame_size = sizeof(EthernetFrameHeader) + sizeof(IPv4Packet) + payload_size; auto buffer = ByteBuffer::create_zeroed(ethernet_frame_size); @@ -98,7 +98,7 @@ KResult NetworkAdapter::send_ipv4(const MACAddress& destination_mac, const IPv4A auto& ipv4 = *(IPv4Packet*)eth.payload(); ipv4.set_version(4); ipv4.set_internet_header_length(5); - ipv4.set_source(ipv4_address()); + ipv4.set_source(source_ipv4); ipv4.set_destination(destination_ipv4); ipv4.set_protocol((u8)protocol); ipv4.set_length(sizeof(IPv4Packet) + payload_size); @@ -114,7 +114,7 @@ KResult NetworkAdapter::send_ipv4(const MACAddress& destination_mac, const IPv4A return KSuccess; } -KResult NetworkAdapter::send_ipv4_fragmented(const MACAddress& destination_mac, const IPv4Address& destination_ipv4, IPv4Protocol protocol, const UserOrKernelBuffer& payload, size_t payload_size, u8 ttl) +KResult NetworkAdapter::send_ipv4_fragmented(const IPv4Address& source_ipv4, const MACAddress& destination_mac, const IPv4Address& destination_ipv4, IPv4Protocol protocol, const UserOrKernelBuffer& payload, size_t payload_size, u8 ttl) { // packets must be split on the 64-bit boundary auto packet_boundary_size = (mtu() - sizeof(IPv4Packet) - sizeof(EthernetFrameHeader)) & 0xfffffff8; @@ -136,7 +136,7 @@ KResult NetworkAdapter::send_ipv4_fragmented(const MACAddress& destination_mac, auto& ipv4 = *(IPv4Packet*)eth.payload(); ipv4.set_version(4); ipv4.set_internet_header_length(5); - ipv4.set_source(ipv4_address()); + ipv4.set_source(source_ipv4); ipv4.set_destination(destination_ipv4); ipv4.set_protocol((u8)protocol); ipv4.set_length(sizeof(IPv4Packet) + packet_payload_size); diff --git a/Kernel/Net/NetworkAdapter.h b/Kernel/Net/NetworkAdapter.h index dc4de36723..6e6dcf32b0 100644 --- a/Kernel/Net/NetworkAdapter.h +++ b/Kernel/Net/NetworkAdapter.h @@ -45,8 +45,8 @@ public: void set_ipv4_gateway(const IPv4Address&); void send(const MACAddress&, const ARPPacket&); - KResult send_ipv4(const MACAddress&, const IPv4Address&, IPv4Protocol, const UserOrKernelBuffer& payload, size_t payload_size, u8 ttl); - KResult send_ipv4_fragmented(const MACAddress&, const IPv4Address&, IPv4Protocol, const UserOrKernelBuffer& payload, size_t payload_size, u8 ttl); + KResult send_ipv4(const IPv4Address& source_ipv4, const MACAddress&, const IPv4Address&, IPv4Protocol, const UserOrKernelBuffer& payload, size_t payload_size, u8 ttl); + KResult send_ipv4_fragmented(const IPv4Address& source_ipv4, const MACAddress&, const IPv4Address&, IPv4Protocol, const UserOrKernelBuffer& payload, size_t payload_size, u8 ttl); size_t dequeue_packet(u8* buffer, size_t buffer_size, Time& packet_timestamp); diff --git a/Kernel/Net/NetworkTask.cpp b/Kernel/Net/NetworkTask.cpp index f4c5e480b5..6618e7c889 100644 --- a/Kernel/Net/NetworkTask.cpp +++ b/Kernel/Net/NetworkTask.cpp @@ -256,7 +256,8 @@ void handle_icmp(const EthernetFrameHeader& eth, const IPv4Packet& ipv4_packet, response.header.set_checksum(internet_checksum(&response, icmp_packet_size)); // FIXME: What is the right TTL value here? Is 64 ok? Should we use the same TTL as the echo request? auto response_buffer = UserOrKernelBuffer::for_kernel_buffer((u8*)&response); - [[maybe_unused]] auto result = adapter->send_ipv4(eth.source(), ipv4_packet.source(), IPv4Protocol::ICMP, response_buffer, buffer.size(), 64); + [[maybe_unused]] auto result = adapter->send_ipv4(adapter->ipv4_address(), eth.source(), + ipv4_packet.source(), IPv4Protocol::ICMP, response_buffer, buffer.size(), 64); } } diff --git a/Kernel/Net/TCPSocket.cpp b/Kernel/Net/TCPSocket.cpp index c3176538c9..035e76d480 100644 --- a/Kernel/Net/TCPSocket.cpp +++ b/Kernel/Net/TCPSocket.cpp @@ -227,7 +227,7 @@ KResult TCPSocket::send_tcp_packet(u16 flags, const UserOrKernelBuffer* payload, auto packet_buffer = UserOrKernelBuffer::for_kernel_buffer(buffer.data()); auto result = routing_decision.adapter->send_ipv4( - routing_decision.next_hop, peer_address(), IPv4Protocol::TCP, + local_address(), routing_decision.next_hop, peer_address(), IPv4Protocol::TCP, packet_buffer, buffer_size, ttl()); if (result.is_error()) return result; @@ -265,8 +265,8 @@ void TCPSocket::send_outgoing_packets(RoutingDecision& routing_decision) auto packet_buffer = UserOrKernelBuffer::for_kernel_buffer(packet.buffer.data()); int err = routing_decision.adapter->send_ipv4( - routing_decision.next_hop, peer_address(), IPv4Protocol::TCP, - packet_buffer, packet.buffer.size(), ttl()); + local_address(), routing_decision.next_hop, peer_address(), + IPv4Protocol::TCP, packet_buffer, packet.buffer.size(), ttl()); if (err < 0) { auto& tcp_packet = *(const TCPPacket*)(packet.buffer.data()); dmesgln("Error ({}) sending TCP packet from {}:{} to {}:{} with ({}{}{}{}) seq_no={}, ack_no={}, tx_counter={}", diff --git a/Kernel/Net/UDPSocket.cpp b/Kernel/Net/UDPSocket.cpp index fb08f20180..ebe10199ea 100644 --- a/Kernel/Net/UDPSocket.cpp +++ b/Kernel/Net/UDPSocket.cpp @@ -84,7 +84,8 @@ KResultOr UDPSocket::protocol_send(const UserOrKernelBuffer& data, size_ if (!data.read(udp_packet.payload(), data_length)) return EFAULT; - auto result = routing_decision.adapter->send_ipv4(routing_decision.next_hop, peer_address(), IPv4Protocol::UDP, UserOrKernelBuffer::for_kernel_buffer(buffer.data()), buffer_size, ttl()); + auto result = routing_decision.adapter->send_ipv4(local_address(), routing_decision.next_hop, + peer_address(), IPv4Protocol::UDP, UserOrKernelBuffer::for_kernel_buffer(buffer.data()), buffer_size, ttl()); if (result.is_error()) return result; return data_length;