tsnet,wgengine/netstack: add ListenPacket and tests

This adds a new ListenPacket function on tsnet.Server
which acts mostly like `net.ListenPacket`.

Unlike `Server.Listen`, this requires listening on a
specific IP and does not automatically listen on both
V4 and V6 addresses of the Server when the IP is unspecified.

To test this, it also adds UDP support to tsdial.Dialer.UserDial
and plumbs it through the localapi. Then an associated test
to make sure the UDP functionality works from both sides.

Updates #12182

Signed-off-by: Maisem Ali <maisem@tailscale.com>
This commit is contained in:
Maisem Ali
2024-05-18 14:37:37 -07:00
committed by Maisem Ali
parent bcb55fdeb6
commit 42cfbf427c
7 changed files with 236 additions and 35 deletions

View File

@@ -59,6 +59,10 @@ type Dialer struct {
// If nil, it's not used.
NetstackDialTCP func(context.Context, netip.AddrPort) (net.Conn, error)
// NetstackDialUDP dials the provided IPPort using netstack.
// If nil, it's not used.
NetstackDialUDP func(context.Context, netip.AddrPort) (net.Conn, error)
peerClientOnce sync.Once
peerClient *http.Client
@@ -403,9 +407,12 @@ func (d *Dialer) UserDial(ctx context.Context, network, addr string) (net.Conn,
return nil, err
}
if d.UseNetstackForIP != nil && d.UseNetstackForIP(ipp.Addr()) {
if d.NetstackDialTCP == nil {
if d.NetstackDialTCP == nil || d.NetstackDialUDP == nil {
return nil, errors.New("Dialer not initialized correctly")
}
if strings.HasPrefix(network, "udp") {
return d.NetstackDialUDP(ctx, ipp)
}
return d.NetstackDialTCP(ctx, ipp)
}