|
@@ -5,6 +5,7 @@ import (
|
|
|
"errors"
|
|
|
"fmt"
|
|
|
"maps"
|
|
|
+ "net"
|
|
|
"sort"
|
|
|
"sync"
|
|
|
"time"
|
|
@@ -950,8 +951,12 @@ func getUserAclRulesForNode(targetnode *models.Node,
|
|
|
if aclRule, ok := rules[acl.ID]; ok {
|
|
|
aclRule.IPList = append(aclRule.IPList, r.IPList...)
|
|
|
aclRule.IP6List = append(aclRule.IP6List, r.IP6List...)
|
|
|
+ aclRule.IPList = UniqueIPNetList(aclRule.IPList)
|
|
|
+ aclRule.IP6List = UniqueIPNetList(aclRule.IP6List)
|
|
|
rules[acl.ID] = aclRule
|
|
|
} else {
|
|
|
+ r.IPList = UniqueIPNetList(r.IPList)
|
|
|
+ r.IP6List = UniqueIPNetList(r.IP6List)
|
|
|
rules[acl.ID] = r
|
|
|
}
|
|
|
}
|
|
@@ -1115,9 +1120,52 @@ func GetAclRulesForNode(targetnode *models.Node) (rules map[string]models.AclRul
|
|
|
}
|
|
|
}
|
|
|
if len(aclRule.IPList) > 0 || len(aclRule.IP6List) > 0 {
|
|
|
+ aclRule.IPList = UniqueIPNetList(aclRule.IPList)
|
|
|
+ aclRule.IP6List = UniqueIPNetList(aclRule.IP6List)
|
|
|
rules[acl.ID] = aclRule
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
return rules
|
|
|
}
|
|
|
+
|
|
|
+// Compare two IPs and return true if ip1 < ip2
|
|
|
+func lessIP(ip1, ip2 net.IP) bool {
|
|
|
+ ip1 = ip1.To16() // Ensure IPv4 is converted to IPv6-mapped format
|
|
|
+ ip2 = ip2.To16()
|
|
|
+ return string(ip1) < string(ip2)
|
|
|
+}
|
|
|
+
|
|
|
+// Sort by IP first, then by prefix length
|
|
|
+func sortIPNets(ipNets []net.IPNet) {
|
|
|
+ sort.Slice(ipNets, func(i, j int) bool {
|
|
|
+ ip1, ip2 := ipNets[i].IP, ipNets[j].IP
|
|
|
+ mask1, _ := ipNets[i].Mask.Size()
|
|
|
+ mask2, _ := ipNets[j].Mask.Size()
|
|
|
+
|
|
|
+ // Compare IPs first
|
|
|
+ if ip1.Equal(ip2) {
|
|
|
+ return mask1 < mask2 // If same IP, sort by subnet mask size
|
|
|
+ }
|
|
|
+ return lessIP(ip1, ip2)
|
|
|
+ })
|
|
|
+}
|
|
|
+
|
|
|
+func UniqueIPNetList(ipnets []net.IPNet) []net.IPNet {
|
|
|
+ uniqueMap := make(map[string]net.IPNet)
|
|
|
+
|
|
|
+ for _, ipnet := range ipnets {
|
|
|
+ key := ipnet.String() // Uses CIDR notation as a unique key
|
|
|
+ if _, exists := uniqueMap[key]; !exists {
|
|
|
+ uniqueMap[key] = ipnet
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // Convert map back to slice
|
|
|
+ uniqueList := make([]net.IPNet, 0, len(uniqueMap))
|
|
|
+ for _, ipnet := range uniqueMap {
|
|
|
+ uniqueList = append(uniqueList, ipnet)
|
|
|
+ }
|
|
|
+ sortIPNets(uniqueList)
|
|
|
+ return uniqueList
|
|
|
+}
|