Skip to content

Refused a UDP reply from an IPv6 address that is no longer valid - #496

Merged
fdesbiens merged 1 commit into
devfrom
fix/udp-ipv6-reply-invalid-address
Oct 19, 2026
Merged

fdesbiens merged 1 commit into
devfrom
fix/udp-ipv6-reply-invalid-address

Conversation

@fdesbiens

Copy link
Copy Markdown
Contributor

Problem

A received IPv6 datagram carries the address it arrived on
(nx_packet_address.nx_packet_ipv6_address_ptr), and _nxd_udp_socket_send uses that address as
the source of a reply instead of looking one up. Once that address has been deleted
(nxd_ipv6_address_delete) or IPv6 disabled (nxd_ipv6_disable), the entry is cleared and no
longer attached to an interface. Sending the received packet back then:

  • reaches NX_ASSERT(if_ptr != NX_NULL) in _nx_ipv6_packet_send with nx_ip_protection held: the
    caller sleeps forever and the IP thread blocks on the mutex, so the IP instance is dead;
  • with NX_ENABLE_INTERFACE_CAPABILITY, dereferences the NULL interface in _nxd_udp_socket_send
    first.

It is the same mechanism as the TCP control path fixed in #490, reached through the UDP data path.

Measured on dev (9609e856)

Two IP instances on the RAM driver; a datagram received on 2001::4, the address deleted, the
received packet sent back with nxd_udp_socket_send:

v6_build, v6_only_build, v6_no_dad_build   test fails (rc 1): the reply does not return within its bound
v6_full_build                              segmentation fault at nxd_udp_socket_send.c:523 (NULL interface)
with this change, all four                 test passes

Change

_nxd_udp_socket_send returns NX_NO_INTERFACE_ADDRESS when the packet carries an IPv6 address
that is not valid, before anything uses it. That is the status the function's header already lists
("Socket interface not marked valid"), and the one nxd_udp_socket_source_send returns for an
address that is not valid. The packet stays with the caller. An address set again and still in
duplicate address detection is refused the same way; until now that datagram was dropped by the
header build and the send reported success.

Test

netx_udp_ipv6_reply_invalid_address_test replies with a received packet after the address is
deleted, after IPv6 is disabled, and after the address is deleted and set again. It checks each
refusal, that the refused packet goes out once the address is valid again, and that datagrams
cross both ways afterwards. The reply is sent from a helper thread with a bounded wait, so without
the change the test fails rather than hangs.

Swept over all 43 configurations of test/cmake/netxduo, five runs each: 145 pass (the 29 IPv6
configurations), 70 N/A (the 14 IPv4-only ones), 0 fail, 0 build failures.

A received IPv6 datagram carries the address it arrived on, and
_nxd_udp_socket_send uses that address as the source of a reply without
looking one up. Once the address has been deleted, or IPv6 disabled, the
entry is no longer attached to an interface. _nx_ipv6_packet_send then
fails its NX_ASSERT that the interface is not NULL, with the IP mutex
held: the caller sleeps forever and the IP thread waits for the mutex,
so the IP instance is dead. With NX_ENABLE_INTERFACE_CAPABILITY the send
dereferences the NULL interface first.

Measured on two IP instances on the RAM driver: a datagram received on
2001::4, the address deleted, the received packet sent back with
nxd_udp_socket_send. In v6_build and v6_only_build the caller is left in
TX_SLEEP and the IP thread suspended on the mutex; in v6_full_build the
process takes a segmentation fault.

The send now returns NX_NO_INTERFACE_ADDRESS when the packet carries an
address that is not valid, before anything else uses it. That is the
status the function's header already documents for this case, and the
one nxd_udp_socket_source_send and the TCP send path return for an
address that is not valid. The packet stays with the caller. An address
set again and still being checked for duplicates is refused the same
way, where until now the datagram was dropped and the send reported
success. The product file header is unchanged.

netx_udp_ipv6_reply_invalid_address_test replies with a received packet
after the address is deleted, after IPv6 is disabled, and after the
address is deleted and set again, and checks each refusal, that the
refused packet can be sent once the address is valid, and that
datagrams cross both ways afterwards. The reply is sent from a helper
thread with a bounded wait. Without the change the test fails within a
second, or with the segmentation fault; with it, it passes.

Assisted-by: Claude Code (Opus 5.5) <noreply@anthropic.com>
@fdesbiens
fdesbiens merged commit 3b3c8b3 into dev Oct 19, 2026
22 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant