From d31febdefa0a26237f78972a1844b939be197725 Mon Sep 17 00:00:00 2001 From: Augustin Cavalier Date: Thu, 26 Jun 2025 21:54:48 -0400 Subject: [PATCH] ICMP: Pass FRAGMENTATION_NEEDED and REDIRECT info up the stack. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Using the new net_error_data parameter to error_received. Move the "update routing table" TODO into the IPv4 module, since the ICMP module doesn't deal with the routing table at all, while the IPv4 module already does. Also add a missing endian swap in ICMP error_reply. Change-Id: I1135eaa442f515d656143c76ab130be19cdcbaf2 Reviewed-on: https://review.haiku-os.org/c/haiku/+/9400 Reviewed-by: waddlesplash Reviewed-by: Jérôme Duval Tested-by: Commit checker robot --- .../kernel/network/protocols/icmp/icmp.cpp | 35 ++++++++++++++----- .../kernel/network/protocols/ipv4/ipv4.cpp | 4 +++ 2 files changed, 30 insertions(+), 9 deletions(-) diff --git a/src/add-ons/kernel/network/protocols/icmp/icmp.cpp b/src/add-ons/kernel/network/protocols/icmp/icmp.cpp index 28647182e1..1f9cd5d3fe 100644 --- a/src/add-ons/kernel/network/protocols/icmp/icmp.cpp +++ b/src/add-ons/kernel/network/protocols/icmp/icmp.cpp @@ -544,23 +544,40 @@ icmp_receive_data(net_buffer* buffer) case ICMP_TYPE_SOURCE_QUENCH: case ICMP_TYPE_PARAMETER_PROBLEM: case ICMP_TYPE_TIME_EXCEEDED: + case ICMP_TYPE_REDIRECT: { net_domain* domain = get_domain(buffer); if (domain == NULL) break; + net_error error = icmp_to_net_error(header.type, header.code); + if (error == 0) + break; + + net_error_data dataStorage = {}; + net_error_data* data = NULL; + if (error == B_NET_ERROR_MESSAGE_SIZE) { + data = &dataStorage; + data->mtu = ntohs(header.path_mtu.next_mtu); + + // IPv4 minimum fragment size is 68 bytes, so if the "next MTU" is + // smaller than that, we can be sure it's invalid. + if (data->mtu < 68) + data = NULL; + } else if (error == B_NET_ERROR_REDIRECT_HOST) { + data = &dataStorage; + sockaddr_in& gateway = (sockaddr_in&)data->gateway; + gateway.sin_len = sizeof(sockaddr_in); + gateway.sin_family = AF_INET; + gateway.sin_addr.s_addr = header.redirect.gateway; + } + // Deliver the error to the domain protocol which will // propagate the error to the upper protocols - net_error error = icmp_to_net_error(header.type, header.code); - if (error != 0) { - bufferHeader.Remove(); - return domain->module->error_received(error, NULL, buffer); - } - break; + bufferHeader.Remove(); + return domain->module->error_received(error, data, buffer); } - case ICMP_TYPE_REDIRECT: - // TODO: Update the routing table case ICMP_TYPE_TIMESTAMP_REQUEST: case ICMP_TYPE_TIMESTAMP_REPLY: case ICMP_TYPE_INFO_REQUEST: @@ -662,7 +679,7 @@ icmp_error_reply(net_protocol* protocol, net_buffer* buffer, net_error error, icmpHeader->parameter_problem.pointer = errorData->error_offset; break; case B_NET_ERROR_MESSAGE_SIZE: - icmpHeader->path_mtu.next_mtu = errorData->mtu; + icmpHeader->path_mtu.next_mtu = htons(errorData->mtu); break; default: diff --git a/src/add-ons/kernel/network/protocols/ipv4/ipv4.cpp b/src/add-ons/kernel/network/protocols/ipv4/ipv4.cpp index c1520b8540..101b285a86 100644 --- a/src/add-ons/kernel/network/protocols/ipv4/ipv4.cpp +++ b/src/add-ons/kernel/network/protocols/ipv4/ipv4.cpp @@ -1920,6 +1920,10 @@ ipv4_error_received(net_error error, net_error_data* errorData, net_buffer* buff return B_ERROR; } + if (error == B_NET_ERROR_REDIRECT_HOST) { + // TODO: Update the routing table! + } + buffer->protocol = header.protocol; bufferHeader.Remove(headerLength);