// SPDX-FileCopyrightText: 2026 Echolot contributors // SPDX-License-Identifier: GPL-3.0-or-later package dataplane import ( "net" "net/netip" "testing" ) // A multi-homed server must answer from the address the client has been talking to. Sending from // a sibling address is silently dropped by the client's NAT or stateful firewall, and the client // then reports downstream loss that never happened — a wrong measurement, which is worse than a // failed one. This was a real bug: fmr binds two IPv4 addresses, the granted train went out from // the one the session had never used, and every packet vanished in transit. func TestConnForPrefersTheAddressTheSessionUsed(t *testing.T) { // Two loopback-bound sockets stand in for the two service addresses. a := mustListen(t, "127.0.0.1:0") b := mustListen(t, "127.0.0.1:0") defer a.Close() defer b.Close() srv := &Server{} srv.conns = []*net.UDPConn{a, b} client := netip.MustParseAddrPort("198.51.100.7:41000") bLocal := b.LocalAddr().(*net.UDPAddr).AddrPort() if got := srv.connFor(client, bLocal); got != b { t.Fatalf("connFor picked the wrong socket: want the one the session used (%v)", bLocal) } // With no recorded local address (nothing received yet) any socket of the right family is // the best available answer — but it must still be one, not nil. if got := srv.connFor(client, netip.AddrPort{}); got == nil { t.Fatal("connFor returned nil when a family match exists") } } func TestConnForFallsBackByFamily(t *testing.T) { v4 := mustListen(t, "127.0.0.1:0") defer v4.Close() srv := &Server{} srv.conns = []*net.UDPConn{v4} // A recorded local address that no longer matches any bound socket (a reload changed the // binds) must not strand the session: fall back rather than return nil. stale := netip.MustParseAddrPort("203.0.113.1:8442") if got := srv.connFor(netip.MustParseAddrPort("198.51.100.7:41000"), stale); got != v4 { t.Fatal("connFor should fall back to a family match when the recorded socket is gone") } // No IPv6 socket is bound, so an IPv6 target has no answer — nil, not an IPv4 socket. if got := srv.connFor(netip.MustParseAddrPort("[2001:db8::1]:41000"), netip.AddrPort{}); got != nil { t.Fatal("connFor returned an IPv4 socket for an IPv6 target") } } func mustListen(t *testing.T, addr string) *net.UDPConn { t.Helper() ua, err := net.ResolveUDPAddr("udp", addr) if err != nil { t.Fatal(err) } c, err := net.ListenUDP("udp", ua) if err != nil { t.Fatal(err) } return c }