internal: only delete old ipv6 if it is non-link local

So the client is removed from table only when it's global ipv6 changed.
This commit is contained in:
Cuong Manh Le
2024-04-05 17:59:21 +07:00
committed by Cuong Manh Le
parent affef963c1
commit b002dff624
4 changed files with 27 additions and 15 deletions
+14 -10
View File
@@ -15,6 +15,7 @@ import (
"github.com/mdlayher/ndp" "github.com/mdlayher/ndp"
"github.com/Control-D-Inc/ctrld" "github.com/Control-D-Inc/ctrld"
ctrldnet "github.com/Control-D-Inc/ctrld/internal/net"
) )
// ndpDiscover provides client discovery functionality using NDP protocol. // ndpDiscover provides client discovery functionality using NDP protocol.
@@ -70,20 +71,23 @@ func (nd *ndpDiscover) List() []string {
} }
// saveInfo saves ip and mac info to mapping table. // saveInfo saves ip and mac info to mapping table.
// If force is true, old ip will be removed before saving. func (nd *ndpDiscover) saveInfo(ip, mac string) {
func (nd *ndpDiscover) saveInfo(ip, mac string, force bool) {
ip = normalizeIP(ip) ip = normalizeIP(ip)
// Store ip => map mapping, // Store ip => map mapping,
nd.mac.Store(ip, mac) nd.mac.Store(ip, mac)
if force { // Do not store mac => ip mapping if new ip is a link local unicast.
// If there is old ip => mac mapping, delete it. if ctrldnet.IsLinkLocalUnicastIPv6(ip) {
if old, ok := nd.ip.Load(mac); ok { return
oldIP := old.(string) }
// If there is old ip => mac mapping, delete it.
if old, existed := nd.ip.Load(mac); existed {
oldIP := old.(string)
if oldIP != ip {
nd.mac.Delete(oldIP) nd.mac.Delete(oldIP)
} }
} }
// Store mac => ip mapping. // Store mac => ip mapping.
nd.ip.Store(mac, ip) nd.ip.Store(mac, ip)
} }
@@ -138,7 +142,7 @@ func (nd *ndpDiscover) listenOnInterface(ctx context.Context, ifi *net.Interface
for _, opt := range am.Options { for _, opt := range am.Options {
if lla, ok := opt.(*ndp.LinkLayerAddress); ok { if lla, ok := opt.(*ndp.LinkLayerAddress); ok {
mac := lla.Addr.String() mac := lla.Addr.String()
nd.saveInfo(fromIP, mac, true) nd.saveInfo(fromIP, mac)
} }
} }
} }
@@ -153,7 +157,7 @@ func (nd *ndpDiscover) scanWindows(r io.Reader) {
continue continue
} }
if mac := parseMAC(fields[1]); mac != "" { if mac := parseMAC(fields[1]); mac != "" {
nd.saveInfo(fields[0], mac, true) nd.saveInfo(fields[0], mac)
} }
} }
} }
@@ -172,7 +176,7 @@ func (nd *ndpDiscover) scanUnix(r io.Reader) {
if idx := strings.IndexByte(ip, '%'); idx != -1 { if idx := strings.IndexByte(ip, '%'); idx != -1 {
ip = ip[:idx] ip = ip[:idx]
} }
nd.saveInfo(ip, mac, true) nd.saveInfo(ip, mac)
} }
} }
} }
+2 -2
View File
@@ -24,7 +24,7 @@ func (nd *ndpDiscover) scan() {
} }
ip := n.IP.String() ip := n.IP.String()
mac := n.HardwareAddr.String() mac := n.HardwareAddr.String()
nd.saveInfo(ip, mac, false) nd.saveInfo(ip, mac)
} }
} }
@@ -54,7 +54,7 @@ func (nd *ndpDiscover) subscribe(ctx context.Context) {
mac := nu.HardwareAddr.String() mac := nu.HardwareAddr.String()
switch nu.State { switch nu.State {
case netlink.NUD_REACHABLE: case netlink.NUD_REACHABLE:
nd.saveInfo(ip, mac, false) nd.saveInfo(ip, mac)
case netlink.NUD_FAILED: case netlink.NUD_FAILED:
ctrld.ProxyLogger.Load().Debug().Msgf("removing NDP neighbor with failed state: %s", ip) ctrld.ProxyLogger.Load().Debug().Msgf("removing NDP neighbor with failed state: %s", ip)
nd.mac.Delete(ip) nd.mac.Delete(ip)
+2 -3
View File
@@ -45,18 +45,17 @@ ff02::c 33-33-00-00-00-0c Permanent
nd.scanWindows(r) nd.scanWindows(r)
count := 0 count := 0
expectedCount := 5 expectedCount := 6
nd.mac.Range(func(key, value any) bool { nd.mac.Range(func(key, value any) bool {
count++ count++
return true return true
}) })
// There are 2 entries for 60-57-47-21-dd-00 in the table, but (*ndpDiscover).saveInfo
// only saves the last one, that's why the expected count number is 5.
if count != expectedCount { if count != expectedCount {
t.Errorf("unexpected count, want %d, got: %d", expectedCount, count) t.Errorf("unexpected count, want %d, got: %d", expectedCount, count)
} }
count = 0 count = 0
expectedCount = 4
nd.ip.Range(func(key, value any) bool { nd.ip.Range(func(key, value any) bool {
count++ count++
return true return true
+9
View File
@@ -115,6 +115,15 @@ func IsIPv6(ip string) bool {
return parsedIP != nil && parsedIP.To4() == nil && parsedIP.To16() != nil return parsedIP != nil && parsedIP.To4() == nil && parsedIP.To16() != nil
} }
// IsLinkLocalUnicastIPv6 checks if the provided IP is a link local unicast v6 address.
func IsLinkLocalUnicastIPv6(ip string) bool {
parsedIP := net.ParseIP(ip)
if parsedIP == nil || parsedIP.To4() != nil || parsedIP.To16() == nil {
return false
}
return parsedIP.To16().IsLinkLocalUnicast()
}
type parallelDialerResult struct { type parallelDialerResult struct {
conn net.Conn conn net.Conn
err error err error