Skip to content

AP_Networking: accept UDP client replies from a different source port - #34227

Open
timtuxworth wants to merge 1 commit into
ArduPilot:masterfrom
timtuxworth:pr-net-udp-port
Open

AP_Networking: accept UDP client replies from a different source port#34227
timtuxworth wants to merge 1 commit into
ArduPilot:masterfrom
timtuxworth:pr-net-udp-port

Conversation

@timtuxworth

Copy link
Copy Markdown
Contributor

Summary

Fix AP_Networking UDP client sockets silently dropping replies from devices that reply on a different source port than the one they were queried on.

Classification & Testing (check all that apply and add your own)

  • Checked by a human programmer
  • Non-functional change
  • No-binary change
  • Infrastructure change (e.g. unit tests, helper scripts)
  • Automated test(s) verify changes (e.g. unit test, autotest)
  • Tested manually, description below (e.g. SITL)
  • Tested on hardware
  • Logs attached
  • Logs available on request

Regression-tested against the existing TestLogDownloadMAVProxyNetwork autotest (covers unicast/multicast/broadcast UDP client, UDP server, and TCP client/server) and the full AP_Mount network autotest suite (MountSkyDroidNetwork, MountTopotekNetwork) — no regressions. The root cause was confirmed manually by hand-crafting the real device's wire protocol against an unconnected socket, and the fix was validated on real hardware: a Cube-based flight controller connected to a Topotek KHP415 gimbal over NET_Pn as a network mount.

Description

NET_Pn set to UDP_CLIENT calls connect() on its socket, which makes the kernel filter incoming packets by source IP and port. That's fine for a device that replies from the same socket it was queried on, but some devices reply from a different, fixed source port instead — every reply is silently dropped before ArduPilot's own code ever sees it, even though the NET_Pn configuration is otherwise correct and matches the documented setup exactly. This was found via a real Topotek KHP415 gimbal connected as a network mount, which consistently reported "Mount: not healthy" for this reason.

This PR skips connect() for unicast UDP_CLIENT destinations and uses sendto()/an unconnected recv() instead, checking only the source IP (not the port) before accepting a reply. Broadcast and multicast destinations are left on the original connect()-based path unchanged, since connect() also performs multicast-group-join setup (IP_ADD_MEMBERSHIP) for them that's unrelated to this fix, and neither is a point-to-point relationship that could hit this failure mode in the first place.

This class of bug is structurally invisible to SITL, since simulated network devices always reply from the same bound socket they were queried on — port symmetry is guaranteed by construction there.

This PR was developed with AI assistance (Claude).

NET_Pn set to UDP_CLIENT connect()'d its socket to the configured
destination, which makes the kernel filter incoming packets to match
that exact source address *and port*. That's fine for the common case
of a device that replies from the same socket it was queried on, but
some devices (confirmed against a real Topotek KHP415 gimbal) reply
from a different, fixed source port instead - every reply was silently
dropped before ArduPilot's own code ever saw it, regardless of NET_Pn
config being otherwise correct.

For a unicast destination, stop calling connect() and use sendto()/an
unconnected recv() instead, checking the source IP ourselves (but not
the port) before accepting a packet. Broadcast and multicast
destinations keep the original connect()-based path unchanged, since
connect() also does necessary setup for them (joining the multicast
group via IP_ADD_MEMBERSHIP) unrelated to this fix, and neither is a
point-to-point relationship that could hit this problem in the first
place.

Verified against the real KHP415 (which replies from a fixed but
different port than it's queried on) by hand-crafting its wire
protocol and sending it from an unconnected socket. Regression-tested
against the existing TestLogDownloadMAVProxyNetwork suite (unicast/
multicast/broadcast UDP client, UDP server, TCP client/server) and the
full AP_Mount network autotest suite - no regressions.
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