mirror of
https://github.com/tailscale/tailscale.git
synced 2024-11-29 04:55:31 +00:00
tailcfg: make SelfNodeV4MasqAddrForThisPeer a pointer
This makes `omitempty` actually work, and saves bytes in each map response. Updates tailscale/corp#8020 Signed-off-by: Maisem Ali <maisem@tailscale.com>
This commit is contained in:
parent
a5fd51ebdc
commit
64bbf1738e
@ -580,12 +580,12 @@ func natConfigFromWGConfig(wcfg *wgcfg.Config) *natV4Config {
|
|||||||
)
|
)
|
||||||
for i := range wcfg.Peers {
|
for i := range wcfg.Peers {
|
||||||
p := &wcfg.Peers[i]
|
p := &wcfg.Peers[i]
|
||||||
if !p.V4MasqAddr.IsValid() {
|
if p.V4MasqAddr == nil || !p.V4MasqAddr.IsValid() {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
rt.InsertOrReplace(p.PublicKey, p.AllowedIPs...)
|
rt.InsertOrReplace(p.PublicKey, p.AllowedIPs...)
|
||||||
mak.Set(&dstMasqAddrs, p.PublicKey, p.V4MasqAddr)
|
mak.Set(&dstMasqAddrs, p.PublicKey, *p.V4MasqAddr)
|
||||||
mak.Set(&listenAddrs, p.V4MasqAddr, struct{}{})
|
mak.Set(&listenAddrs, *p.V4MasqAddr, struct{}{})
|
||||||
}
|
}
|
||||||
if len(listenAddrs) == 0 || len(dstMasqAddrs) == 0 {
|
if len(listenAddrs) == 0 || len(dstMasqAddrs) == 0 {
|
||||||
return nil
|
return nil
|
||||||
|
@ -31,6 +31,7 @@
|
|||||||
"tailscale.com/types/key"
|
"tailscale.com/types/key"
|
||||||
"tailscale.com/types/logger"
|
"tailscale.com/types/logger"
|
||||||
"tailscale.com/types/netlogtype"
|
"tailscale.com/types/netlogtype"
|
||||||
|
"tailscale.com/types/ptr"
|
||||||
"tailscale.com/util/must"
|
"tailscale.com/util/must"
|
||||||
"tailscale.com/wgengine/filter"
|
"tailscale.com/wgengine/filter"
|
||||||
"tailscale.com/wgengine/wgcfg"
|
"tailscale.com/wgengine/wgcfg"
|
||||||
@ -602,7 +603,7 @@ func TestNATCfg(t *testing.T) {
|
|||||||
AllowedIPs: []netip.Prefix{
|
AllowedIPs: []netip.Prefix{
|
||||||
netip.PrefixFrom(ip, ip.BitLen()),
|
netip.PrefixFrom(ip, ip.BitLen()),
|
||||||
},
|
},
|
||||||
V4MasqAddr: eip,
|
V4MasqAddr: ptr.To(eip),
|
||||||
}
|
}
|
||||||
p.AllowedIPs = append(p.AllowedIPs, otherAllowedIPs...)
|
p.AllowedIPs = append(p.AllowedIPs, otherAllowedIPs...)
|
||||||
return p
|
return p
|
||||||
|
@ -289,7 +289,7 @@ type Node struct {
|
|||||||
// This only applies to traffic originating from the current node to the
|
// This only applies to traffic originating from the current node to the
|
||||||
// peer or any of its subnets. Traffic originating from subnet routes will
|
// peer or any of its subnets. Traffic originating from subnet routes will
|
||||||
// not be masqueraded (e.g. in case of --snat-subnet-routes).
|
// not be masqueraded (e.g. in case of --snat-subnet-routes).
|
||||||
SelfNodeV4MasqAddrForThisPeer netip.Addr `json:",omitempty"`
|
SelfNodeV4MasqAddrForThisPeer *netip.Addr `json:",omitempty"`
|
||||||
|
|
||||||
// IsWireGuardOnly indicates that this is a non-Tailscale WireGuard peer, it
|
// IsWireGuardOnly indicates that this is a non-Tailscale WireGuard peer, it
|
||||||
// is not expected to speak Disco or DERP, and it must have Endpoints in
|
// is not expected to speak Disco or DERP, and it must have Endpoints in
|
||||||
@ -1705,7 +1705,7 @@ func (n *Node) Equal(n2 *Node) bool {
|
|||||||
bytes.Equal(n.KeySignature, n2.KeySignature) &&
|
bytes.Equal(n.KeySignature, n2.KeySignature) &&
|
||||||
n.Machine == n2.Machine &&
|
n.Machine == n2.Machine &&
|
||||||
n.DiscoKey == n2.DiscoKey &&
|
n.DiscoKey == n2.DiscoKey &&
|
||||||
eqBoolPtr(n.Online, n2.Online) &&
|
eqPtr(n.Online, n2.Online) &&
|
||||||
eqCIDRs(n.Addresses, n2.Addresses) &&
|
eqCIDRs(n.Addresses, n2.Addresses) &&
|
||||||
eqCIDRs(n.AllowedIPs, n2.AllowedIPs) &&
|
eqCIDRs(n.AllowedIPs, n2.AllowedIPs) &&
|
||||||
eqCIDRs(n.PrimaryRoutes, n2.PrimaryRoutes) &&
|
eqCIDRs(n.PrimaryRoutes, n2.PrimaryRoutes) &&
|
||||||
@ -1722,11 +1722,11 @@ func (n *Node) Equal(n2 *Node) bool {
|
|||||||
n.ComputedNameWithHost == n2.ComputedNameWithHost &&
|
n.ComputedNameWithHost == n2.ComputedNameWithHost &&
|
||||||
eqStrings(n.Tags, n2.Tags) &&
|
eqStrings(n.Tags, n2.Tags) &&
|
||||||
n.Expired == n2.Expired &&
|
n.Expired == n2.Expired &&
|
||||||
n.SelfNodeV4MasqAddrForThisPeer == n2.SelfNodeV4MasqAddrForThisPeer &&
|
eqPtr(n.SelfNodeV4MasqAddrForThisPeer, n2.SelfNodeV4MasqAddrForThisPeer) &&
|
||||||
n.IsWireGuardOnly == n2.IsWireGuardOnly
|
n.IsWireGuardOnly == n2.IsWireGuardOnly
|
||||||
}
|
}
|
||||||
|
|
||||||
func eqBoolPtr(a, b *bool) bool {
|
func eqPtr[T comparable](a, b *T) bool {
|
||||||
if a == b { // covers nil
|
if a == b { // covers nil
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
@ -1734,7 +1734,6 @@ func eqBoolPtr(a, b *bool) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return *a == *b
|
return *a == *b
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func eqStrings(a, b []string) bool {
|
func eqStrings(a, b []string) bool {
|
||||||
|
@ -63,6 +63,10 @@ func (src *Node) Clone() *Node {
|
|||||||
*dst.Online = *src.Online
|
*dst.Online = *src.Online
|
||||||
}
|
}
|
||||||
dst.Capabilities = append(src.Capabilities[:0:0], src.Capabilities...)
|
dst.Capabilities = append(src.Capabilities[:0:0], src.Capabilities...)
|
||||||
|
if dst.SelfNodeV4MasqAddrForThisPeer != nil {
|
||||||
|
dst.SelfNodeV4MasqAddrForThisPeer = new(netip.Addr)
|
||||||
|
*dst.SelfNodeV4MasqAddrForThisPeer = *src.SelfNodeV4MasqAddrForThisPeer
|
||||||
|
}
|
||||||
return dst
|
return dst
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -98,7 +102,7 @@ func (src *Node) Clone() *Node {
|
|||||||
ComputedNameWithHost string
|
ComputedNameWithHost string
|
||||||
DataPlaneAuditLogID string
|
DataPlaneAuditLogID string
|
||||||
Expired bool
|
Expired bool
|
||||||
SelfNodeV4MasqAddrForThisPeer netip.Addr
|
SelfNodeV4MasqAddrForThisPeer *netip.Addr
|
||||||
IsWireGuardOnly bool
|
IsWireGuardOnly bool
|
||||||
}{})
|
}{})
|
||||||
|
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
. "tailscale.com/tailcfg"
|
. "tailscale.com/tailcfg"
|
||||||
"tailscale.com/tstest"
|
"tailscale.com/tstest"
|
||||||
"tailscale.com/types/key"
|
"tailscale.com/types/key"
|
||||||
|
"tailscale.com/types/ptr"
|
||||||
"tailscale.com/util/must"
|
"tailscale.com/util/must"
|
||||||
"tailscale.com/version"
|
"tailscale.com/version"
|
||||||
)
|
)
|
||||||
@ -537,12 +538,12 @@ func TestNodeEqual(t *testing.T) {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
&Node{},
|
&Node{},
|
||||||
&Node{SelfNodeV4MasqAddrForThisPeer: netip.MustParseAddr("100.64.0.1")},
|
&Node{SelfNodeV4MasqAddrForThisPeer: ptr.To(netip.MustParseAddr("100.64.0.1"))},
|
||||||
false,
|
false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
&Node{SelfNodeV4MasqAddrForThisPeer: netip.MustParseAddr("100.64.0.1")},
|
&Node{SelfNodeV4MasqAddrForThisPeer: ptr.To(netip.MustParseAddr("100.64.0.1"))},
|
||||||
&Node{SelfNodeV4MasqAddrForThisPeer: netip.MustParseAddr("100.64.0.1")},
|
&Node{SelfNodeV4MasqAddrForThisPeer: ptr.To(netip.MustParseAddr("100.64.0.1"))},
|
||||||
true,
|
true,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -176,9 +176,14 @@ func (v NodeView) ComputedName() string { return v.ж.ComputedName
|
|||||||
func (v NodeView) ComputedNameWithHost() string { return v.ж.ComputedNameWithHost }
|
func (v NodeView) ComputedNameWithHost() string { return v.ж.ComputedNameWithHost }
|
||||||
func (v NodeView) DataPlaneAuditLogID() string { return v.ж.DataPlaneAuditLogID }
|
func (v NodeView) DataPlaneAuditLogID() string { return v.ж.DataPlaneAuditLogID }
|
||||||
func (v NodeView) Expired() bool { return v.ж.Expired }
|
func (v NodeView) Expired() bool { return v.ж.Expired }
|
||||||
func (v NodeView) SelfNodeV4MasqAddrForThisPeer() netip.Addr {
|
func (v NodeView) SelfNodeV4MasqAddrForThisPeer() *netip.Addr {
|
||||||
return v.ж.SelfNodeV4MasqAddrForThisPeer
|
if v.ж.SelfNodeV4MasqAddrForThisPeer == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
x := *v.ж.SelfNodeV4MasqAddrForThisPeer
|
||||||
|
return &x
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v NodeView) IsWireGuardOnly() bool { return v.ж.IsWireGuardOnly }
|
func (v NodeView) IsWireGuardOnly() bool { return v.ж.IsWireGuardOnly }
|
||||||
func (v NodeView) Equal(v2 NodeView) bool { return v.ж.Equal(v2.ж) }
|
func (v NodeView) Equal(v2 NodeView) bool { return v.ж.Equal(v2.ж) }
|
||||||
|
|
||||||
@ -214,7 +219,7 @@ func (v NodeView) Equal(v2 NodeView) bool { return v.ж.Equal(v2.ж) }
|
|||||||
ComputedNameWithHost string
|
ComputedNameWithHost string
|
||||||
DataPlaneAuditLogID string
|
DataPlaneAuditLogID string
|
||||||
Expired bool
|
Expired bool
|
||||||
SelfNodeV4MasqAddrForThisPeer netip.Addr
|
SelfNodeV4MasqAddrForThisPeer *netip.Addr
|
||||||
IsWireGuardOnly bool
|
IsWireGuardOnly bool
|
||||||
}{})
|
}{})
|
||||||
|
|
||||||
|
@ -33,6 +33,7 @@
|
|||||||
"tailscale.com/tailcfg"
|
"tailscale.com/tailcfg"
|
||||||
"tailscale.com/types/key"
|
"tailscale.com/types/key"
|
||||||
"tailscale.com/types/logger"
|
"tailscale.com/types/logger"
|
||||||
|
"tailscale.com/types/ptr"
|
||||||
)
|
)
|
||||||
|
|
||||||
const msgLimit = 1 << 20 // encrypted message length limit
|
const msgLimit = 1 << 20 // encrypted message length limit
|
||||||
@ -843,7 +844,7 @@ func (s *Server) MapResponse(req *tailcfg.MapRequest) (res *tailcfg.MapResponse,
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if masqIP := nodeMasqs[p.Key]; masqIP.IsValid() {
|
if masqIP := nodeMasqs[p.Key]; masqIP.IsValid() {
|
||||||
p.SelfNodeV4MasqAddrForThisPeer = masqIP
|
p.SelfNodeV4MasqAddrForThisPeer = ptr.To(masqIP)
|
||||||
}
|
}
|
||||||
|
|
||||||
s.mu.Lock()
|
s.mu.Lock()
|
||||||
|
@ -575,8 +575,8 @@ func TestGetTypeHasher(t *testing.T) {
|
|||||||
{
|
{
|
||||||
name: "tailcfg.Node",
|
name: "tailcfg.Node",
|
||||||
val: &tailcfg.Node{},
|
val: &tailcfg.Node{},
|
||||||
out: "\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\tn\x88\xf1\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\tn\x88\xf1\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
|
out: "\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\tn\x88\xf1\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\tn\x88\xf1\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
|
||||||
out32: "\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\tn\x88\xf1\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\tn\x88\xf1\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
|
out32: "\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\tn\x88\xf1\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\tn\x88\xf1\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
|
@ -50,6 +50,7 @@
|
|||||||
"tailscale.com/types/netlogtype"
|
"tailscale.com/types/netlogtype"
|
||||||
"tailscale.com/types/netmap"
|
"tailscale.com/types/netmap"
|
||||||
"tailscale.com/types/nettype"
|
"tailscale.com/types/nettype"
|
||||||
|
"tailscale.com/types/ptr"
|
||||||
"tailscale.com/util/cibuild"
|
"tailscale.com/util/cibuild"
|
||||||
"tailscale.com/util/racebuild"
|
"tailscale.com/util/racebuild"
|
||||||
"tailscale.com/wgengine/filter"
|
"tailscale.com/wgengine/filter"
|
||||||
@ -2240,7 +2241,7 @@ func TestIsWireGuardOnlyPeerWithMasquerade(t *testing.T) {
|
|||||||
IsWireGuardOnly: true,
|
IsWireGuardOnly: true,
|
||||||
Addresses: []netip.Prefix{wgaip},
|
Addresses: []netip.Prefix{wgaip},
|
||||||
AllowedIPs: []netip.Prefix{wgaip},
|
AllowedIPs: []netip.Prefix{wgaip},
|
||||||
SelfNodeV4MasqAddrForThisPeer: masqip.Addr(),
|
SelfNodeV4MasqAddrForThisPeer: ptr.To(masqip.Addr()),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -37,7 +37,7 @@ type Peer struct {
|
|||||||
PublicKey key.NodePublic
|
PublicKey key.NodePublic
|
||||||
DiscoKey key.DiscoPublic // present only so we can handle restarts within wgengine, not passed to WireGuard
|
DiscoKey key.DiscoPublic // present only so we can handle restarts within wgengine, not passed to WireGuard
|
||||||
AllowedIPs []netip.Prefix
|
AllowedIPs []netip.Prefix
|
||||||
V4MasqAddr netip.Addr // if non-zero, masquerade IPv4 traffic to this peer using this address
|
V4MasqAddr *netip.Addr // if non-nil, masquerade IPv4 traffic to this peer using this address
|
||||||
PersistentKeepalive uint16
|
PersistentKeepalive uint16
|
||||||
// wireguard-go's endpoint for this peer. It should always equal Peer.PublicKey.
|
// wireguard-go's endpoint for this peer. It should always equal Peer.PublicKey.
|
||||||
// We represent it explicitly so that we can detect if they diverge and recover.
|
// We represent it explicitly so that we can detect if they diverge and recover.
|
||||||
|
@ -54,6 +54,10 @@ func (src *Peer) Clone() *Peer {
|
|||||||
dst := new(Peer)
|
dst := new(Peer)
|
||||||
*dst = *src
|
*dst = *src
|
||||||
dst.AllowedIPs = append(src.AllowedIPs[:0:0], src.AllowedIPs...)
|
dst.AllowedIPs = append(src.AllowedIPs[:0:0], src.AllowedIPs...)
|
||||||
|
if dst.V4MasqAddr != nil {
|
||||||
|
dst.V4MasqAddr = new(netip.Addr)
|
||||||
|
*dst.V4MasqAddr = *src.V4MasqAddr
|
||||||
|
}
|
||||||
return dst
|
return dst
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -62,7 +66,7 @@ func (src *Peer) Clone() *Peer {
|
|||||||
PublicKey key.NodePublic
|
PublicKey key.NodePublic
|
||||||
DiscoKey key.DiscoPublic
|
DiscoKey key.DiscoPublic
|
||||||
AllowedIPs []netip.Prefix
|
AllowedIPs []netip.Prefix
|
||||||
V4MasqAddr netip.Addr
|
V4MasqAddr *netip.Addr
|
||||||
PersistentKeepalive uint16
|
PersistentKeepalive uint16
|
||||||
WGEndpoint key.NodePublic
|
WGEndpoint key.NodePublic
|
||||||
}{})
|
}{})
|
||||||
|
Loading…
Reference in New Issue
Block a user