diff --git a/client.go b/client.go index ff6a985..4b32a83 100644 --- a/client.go +++ b/client.go @@ -351,13 +351,18 @@ func (c *Client) authenticate(ctx context.Context, conn *quic.Conn, retoken []by return nil, fmt.Errorf("authentication failed: %w", resp.Error) } + publicAddr, err := resp.Public.AsNetip() + if err != nil { + return nil, fmt.Errorf("authentication convert public address failed: %w", err) + } + c.addrs.Update(func(t advertiseAddrs) advertiseAddrs { - c.logger.Debug("updating nat stun", "addr", resp.Public.AsNetip()) - t.STUN = []netip.AddrPort{resp.Public.AsNetip()} + c.logger.Debug("updating nat stun", "addr", publicAddr) + t.STUN = []netip.AddrPort{publicAddr} return t }) - c.logger.Info("authenticated to server", "addr", c.controlAddr, "direct", resp.Public.AsNetip()) + c.logger.Info("authenticated to server", "addr", c.controlAddr, "direct", publicAddr) return &session{conn, resp.ReconnectToken}, nil } diff --git a/peer.go b/peer.go index 8a5844d..f3b9585 100644 --- a/peer.go +++ b/peer.go @@ -441,7 +441,11 @@ func (p *peer) status() (StatusPeer, error) { ID: peer.Id, Metadata: peer.Metadata, DirectAddrs: iterc.MapSlice(peer.Peer.Directs, func(addr *pbmodel.AddrPort) string { - return addr.AsNetip().String() + naddr, err := addr.AsNetip() + if err != nil { + return fmt.Sprintf("invalid address: %v", err) + } + return naddr.String() }), } } diff --git a/peer_remote.go b/peer_remote.go index 41741e8..7122edb 100644 --- a/peer_remote.go +++ b/peer_remote.go @@ -90,7 +90,11 @@ func (p *remotePeer) runErr(ctx context.Context) error { addrs := map[netip.AddrPort]struct{}{} for _, addr := range remote.Peer.Directs { - addrs[addr.AsNetip()] = struct{}{} + if a, err := addr.AsNetip(); err != nil { + p.logger.Warn("skipping invalid direct address", "err", err) + } else { + addrs[a] = struct{}{} + } } if p.outgoing == nil { remoteServerConf, err := newServerTLSConfig(remote.Peer.ServerCertificate) diff --git a/proto/pbmodel/addr.go b/proto/pbmodel/addr.go index 5d50539..4059ea2 100644 --- a/proto/pbmodel/addr.go +++ b/proto/pbmodel/addr.go @@ -1,6 +1,7 @@ package pbmodel import ( + "fmt" "net" "net/netip" @@ -16,11 +17,23 @@ func AddrFromNetip(addr netip.Addr) *Addr { return &Addr{V4: v4[:]} } -func (a *Addr) AsNetip() netip.Addr { +func (a *Addr) AsNetip() (netip.Addr, error) { + if a == nil { + return netip.Addr{}, fmt.Errorf("parse addr: nil") + } if len(a.V6) > 0 { - return netip.AddrFrom16([16]byte(a.V6)) + if len(a.V6) != 16 { + return netip.Addr{}, fmt.Errorf("parse addr: v6 length is %d, want 16", len(a.V6)) + } + return netip.AddrFrom16([16]byte(a.V6)), nil + } + if len(a.V4) == 0 { + return netip.Addr{}, fmt.Errorf("parse addr: v4 and v6 both empty") } - return netip.AddrFrom4([4]byte(a.V4)) + if len(a.V4) != 4 { + return netip.Addr{}, fmt.Errorf("parse addr: v4 length is %d, want 4", len(a.V4)) + } + return netip.AddrFrom4([4]byte(a.V4)), nil } func AddrPortFromNet(addr net.Addr) (*AddrPort, error) { @@ -38,16 +51,30 @@ func AddrPortFromNetip(addr netip.AddrPort) *AddrPort { } } -func (a *AddrPort) AsNetip() netip.AddrPort { - return netip.AddrPortFrom(a.Addr.AsNetip(), uint16(a.Port)) +func (a *AddrPort) AsNetip() (netip.AddrPort, error) { + if a == nil { + return netip.AddrPort{}, fmt.Errorf("parse addrport: nil") + } + if a.Addr == nil { + return netip.AddrPort{}, fmt.Errorf("parse addrport: missing addr") + } + addr, err := a.Addr.AsNetip() + if err != nil { + return netip.AddrPort{}, err + } + return netip.AddrPortFrom(addr, uint16(a.Port)), nil } -func AsNetips(pb []*AddrPort) []netip.AddrPort { +func AsNetips(pb []*AddrPort) ([]netip.AddrPort, error) { + var err error s := make([]netip.AddrPort, len(pb)) for i, pbi := range pb { - s[i] = pbi.AsNetip() + s[i], err = pbi.AsNetip() + if err != nil { + return nil, err + } } - return s + return s, nil } func AsAddrPorts(addrs []netip.AddrPort) []*AddrPort {