udp: send should return the error on the last send packet

checked against the output of the test sortix/os-test/udp/connect-send-error-send
* icmp: add more error codes

Change-Id: I7b1695d37cf5eae8cd09132047404b990f8791dd
Reviewed-on: https://review.haiku-os.org/c/haiku/+/9394
Reviewed-by: waddlesplash <[email protected]>
Tested-by: Commit checker robot <[email protected]>
This commit is contained in:
Jérôme Duval
2025-06-26 05:43:59 +00:00
parent f8e01ad15c
commit 74be257edf
4 changed files with 125 additions and 18 deletions
+11
View File
@@ -31,6 +31,17 @@ enum net_error {
B_NET_ERROR_UNREACH_PROTOCOL,
B_NET_ERROR_UNREACH_PORT,
B_NET_ERROR_MESSAGE_SIZE,
B_NET_ERROR_UNREACH_SOURCE_FAIL,
B_NET_ERROR_UNREACH_NET_UNKNOWN,
B_NET_ERROR_UNREACH_HOST_UNKNOWN,
B_NET_ERROR_UNREACH_ISOLATED,
B_NET_ERROR_UNREACH_NET_PROHIBITED,
B_NET_ERROR_UNREACH_HOST_PROHIBITED,
B_NET_ERROR_UNREACH_NET_TOS,
B_NET_ERROR_UNREACH_HOST_TOS,
B_NET_ERROR_UNREACH_FILTER_PROHIBITED,
B_NET_ERROR_UNREACH_HOST_PRECEDENCE,
B_NET_ERROR_UNREACH_PRECEDENCE_CUTOFF,
B_NET_ERROR_TRANSIT_TIME_EXCEEDED,
B_NET_ERROR_REASSEMBLY_TIME_EXCEEDED,
B_NET_ERROR_PARAMETER_PROBLEM,
@@ -148,16 +148,38 @@ icmp_to_net_error(uint8 type, uint8 code)
switch (type) {
case ICMP_TYPE_UNREACH:
switch (code) {
case ICMP_CODE_FRAGMENTATION_NEEDED:
return B_NET_ERROR_MESSAGE_SIZE;
case ICMP_CODE_NET_UNREACH:
case ICMP_CODE_UNREACH_NET:
return B_NET_ERROR_UNREACH_NET;
case ICMP_CODE_HOST_UNREACH:
case ICMP_CODE_UNREACH_HOST:
return B_NET_ERROR_UNREACH_HOST;
case ICMP_CODE_PROTOCOL_UNREACH:
case ICMP_CODE_UNREACH_PROTOCOL:
return B_NET_ERROR_UNREACH_PROTOCOL;
case ICMP_CODE_PORT_UNREACH:
case ICMP_CODE_UNREACH_PORT:
return B_NET_ERROR_UNREACH_PORT;
case ICMP_CODE_UNREACH_FRAGMENTATION_NEEDED:
return B_NET_ERROR_MESSAGE_SIZE;
case ICMP_CODE_UNREACH_SOURCE_ROUTE_FAIL:
return B_NET_ERROR_UNREACH_SOURCE_FAIL;
case ICMP_CODE_UNREACH_NET_UNKNOWN:
return B_NET_ERROR_UNREACH_NET_UNKNOWN;
case ICMP_CODE_UNREACH_HOST_UNKNOWN:
return B_NET_ERROR_UNREACH_HOST_UNKNOWN;
case ICMP_CODE_UNREACH_ISOLATED:
return B_NET_ERROR_UNREACH_ISOLATED;
case ICMP_CODE_UNREACH_NET_PROHIBITED:
return B_NET_ERROR_UNREACH_NET_PROHIBITED;
case ICMP_CODE_UNREACH_HOST_PROHIBITED:
return B_NET_ERROR_UNREACH_HOST_PROHIBITED;
case ICMP_CODE_UNREACH_NET_TOS:
return B_NET_ERROR_UNREACH_NET_TOS;
case ICMP_CODE_UNREACH_HOST_TOS:
return B_NET_ERROR_UNREACH_HOST_TOS;
case ICMP_CODE_UNREACH_FILTER_PROHIBITED:
return B_NET_ERROR_UNREACH_FILTER_PROHIBITED;
case ICMP_CODE_UNREACH_HOST_PRECEDENCE:
return B_NET_ERROR_UNREACH_HOST_PRECEDENCE;
case ICMP_CODE_UNREACH_PRECEDENCE_CUTOFF:
return B_NET_ERROR_UNREACH_PRECEDENCE_CUTOFF;
}
break;
@@ -200,23 +222,67 @@ net_error_to_icmp(net_error error, uint8& type, uint8& code)
// unreach
case B_NET_ERROR_UNREACH_NET:
type = ICMP_TYPE_UNREACH;
code = ICMP_CODE_NET_UNREACH;
code = ICMP_CODE_UNREACH_NET;
break;
case B_NET_ERROR_UNREACH_HOST:
type = ICMP_TYPE_UNREACH;
code = ICMP_CODE_HOST_UNREACH;
code = ICMP_CODE_UNREACH_HOST;
break;
case B_NET_ERROR_UNREACH_PROTOCOL:
type = ICMP_TYPE_UNREACH;
code = ICMP_CODE_PROTOCOL_UNREACH;
code = ICMP_CODE_UNREACH_PROTOCOL;
break;
case B_NET_ERROR_UNREACH_PORT:
type = ICMP_TYPE_UNREACH;
code = ICMP_CODE_PORT_UNREACH;
code = ICMP_CODE_UNREACH_PORT;
break;
case B_NET_ERROR_MESSAGE_SIZE:
type = ICMP_TYPE_UNREACH;
code = ICMP_CODE_FRAGMENTATION_NEEDED;
code = ICMP_CODE_UNREACH_FRAGMENTATION_NEEDED;
break;
case B_NET_ERROR_UNREACH_SOURCE_FAIL:
type = ICMP_TYPE_UNREACH;
code = ICMP_CODE_UNREACH_SOURCE_ROUTE_FAIL;
break;
case B_NET_ERROR_UNREACH_NET_UNKNOWN:
type = ICMP_TYPE_UNREACH;
code = ICMP_CODE_UNREACH_NET_UNKNOWN;
break;
case B_NET_ERROR_UNREACH_HOST_UNKNOWN:
type = ICMP_TYPE_UNREACH;
code = ICMP_CODE_UNREACH_HOST_UNKNOWN;
break;
case B_NET_ERROR_UNREACH_ISOLATED:
type = ICMP_TYPE_UNREACH;
code = ICMP_CODE_UNREACH_ISOLATED;
break;
case B_NET_ERROR_UNREACH_NET_PROHIBITED:
type = ICMP_TYPE_UNREACH;
code = ICMP_CODE_UNREACH_NET_PROHIBITED;
break;
case B_NET_ERROR_UNREACH_HOST_PROHIBITED:
type = ICMP_TYPE_UNREACH;
code = ICMP_CODE_UNREACH_HOST_PROHIBITED;
break;
case B_NET_ERROR_UNREACH_NET_TOS:
type = ICMP_TYPE_UNREACH;
code = ICMP_CODE_UNREACH_NET_TOS;
break;
case B_NET_ERROR_UNREACH_HOST_TOS:
type = ICMP_TYPE_UNREACH;
code = ICMP_CODE_UNREACH_HOST_TOS;
break;
case B_NET_ERROR_UNREACH_FILTER_PROHIBITED:
type = ICMP_TYPE_UNREACH;
code = ICMP_CODE_UNREACH_FILTER_PROHIBITED;
break;
case B_NET_ERROR_UNREACH_HOST_PRECEDENCE:
type = ICMP_TYPE_UNREACH;
code = ICMP_CODE_UNREACH_HOST_PRECEDENCE;
break;
case B_NET_ERROR_UNREACH_PRECEDENCE_CUTOFF:
type = ICMP_TYPE_UNREACH;
code = ICMP_CODE_UNREACH_PRECEDENCE_CUTOFF;
break;
// time exceeded
@@ -36,12 +36,23 @@
#define ICMP_CODE_PARAMETER_MISSING 1
// ICMP_TYPE_UNREACH codes
#define ICMP_CODE_NET_UNREACH 0
#define ICMP_CODE_HOST_UNREACH 1
#define ICMP_CODE_PROTOCOL_UNREACH 2
#define ICMP_CODE_PORT_UNREACH 3
#define ICMP_CODE_FRAGMENTATION_NEEDED 4
#define ICMP_CODE_SOURCE_ROUTE_FAIL 5
#define ICMP_CODE_UNREACH_NET 0
#define ICMP_CODE_UNREACH_HOST 1
#define ICMP_CODE_UNREACH_PROTOCOL 2
#define ICMP_CODE_UNREACH_PORT 3
#define ICMP_CODE_UNREACH_FRAGMENTATION_NEEDED 4
#define ICMP_CODE_UNREACH_SOURCE_ROUTE_FAIL 5
#define ICMP_CODE_UNREACH_NET_UNKNOWN 6
#define ICMP_CODE_UNREACH_HOST_UNKNOWN 7
#define ICMP_CODE_UNREACH_ISOLATED 8
#define ICMP_CODE_UNREACH_NET_PROHIBITED 9
#define ICMP_CODE_UNREACH_HOST_PROHIBITED 10
#define ICMP_CODE_UNREACH_NET_TOS 11
#define ICMP_CODE_UNREACH_HOST_TOS 12
#define ICMP_CODE_UNREACH_FILTER_PROHIBITED 13
#define ICMP_CODE_UNREACH_HOST_PRECEDENCE 14
#define ICMP_CODE_UNREACH_PRECEDENCE_CUTOFF 15
// ICMP_TYPE_REDIRECT codes
#define ICMP_CODE_REDIRECT_NET 0
@@ -769,7 +769,7 @@ UdpEndpointManager::ReceiveData(net_buffer *buffer)
status_t
UdpEndpointManager::ReceiveError(status_t error, net_buffer* buffer)
{
TRACE_EPM("ReceiveError(code %" B_PRId32 " %p [%" B_PRIu32 " bytes])",
TRACE_EPM("ReceiveError(code %" B_PRIx32 " %p [%" B_PRIu32 " bytes])",
error, buffer, buffer->size);
// We only really need the port information
@@ -1056,6 +1056,10 @@ UdpEndpoint::SendRoutedData(net_buffer *buffer, net_route *route)
return EMSGSIZE;
if ((fFlags & FLAG_NO_SEND) != 0)
return EPIPE;
status_t status = fSocket->error;
fSocket->error = 0;
if (status != B_OK)
return status;
buffer->protocol = IPPROTO_UDP;
@@ -1091,6 +1095,10 @@ UdpEndpoint::SendData(net_buffer *buffer)
if ((fFlags & FLAG_NO_SEND) != 0)
return EPIPE;
status_t status = fSocket->error;
fSocket->error = 0;
if (status != B_OK)
return status;
return gDatalinkModule->send_data(this, NULL, buffer);
}
@@ -1371,11 +1379,22 @@ udp_error_received(net_error error, net_buffer* buffer)
notifyError = ENETUNREACH;
break;
case B_NET_ERROR_UNREACH_HOST:
case B_NET_ERROR_UNREACH_SOURCE_FAIL:
case B_NET_ERROR_UNREACH_NET_UNKNOWN:
case B_NET_ERROR_UNREACH_HOST_UNKNOWN:
case B_NET_ERROR_UNREACH_ISOLATED:
case B_NET_ERROR_UNREACH_NET_TOS:
case B_NET_ERROR_UNREACH_HOST_TOS:
case B_NET_ERROR_UNREACH_HOST_PRECEDENCE:
case B_NET_ERROR_UNREACH_PRECEDENCE_CUTOFF:
case B_NET_ERROR_TRANSIT_TIME_EXCEEDED:
notifyError = EHOSTUNREACH;
break;
case B_NET_ERROR_UNREACH_PROTOCOL:
case B_NET_ERROR_UNREACH_PORT:
case B_NET_ERROR_UNREACH_NET_PROHIBITED:
case B_NET_ERROR_UNREACH_HOST_PROHIBITED:
case B_NET_ERROR_UNREACH_FILTER_PROHIBITED:
notifyError = ECONNREFUSED;
break;
case B_NET_ERROR_MESSAGE_SIZE: