package network import ( "fmt" "net" ) type SubnetOverlap struct { Interface string `json:"interface"` Subnet string `json:"subnet"` Label string `json:"label,omitempty"` } func parseIPNet(ipStr, maskStr string) (*net.IPNet, error) { ip := net.ParseIP(ipStr) if ip == nil { return nil, fmt.Errorf("invalid IP: %s", ipStr) } ip = ip.To4() if ip == nil { return nil, fmt.Errorf("invalid IPv4: %s", ipStr) } mask := ipMaskFromString(maskStr) if mask == nil { return nil, fmt.Errorf("invalid netmask: %s", maskStr) } return &net.IPNet{IP: ip.Mask(mask), Mask: mask}, nil } func ipMaskFromString(maskStr string) net.IPMask { m := net.ParseIP(maskStr) if m != nil { if m4 := m.To4(); m4 != nil { return net.IPMask(m4) } } return nil } func subnetsOverlap(a, b *net.IPNet) bool { return a.Contains(b.IP) || b.Contains(a.IP) } func CheckOverlap(newIP, newMask, excludeIface string, existing []SubnetOverlap) []SubnetOverlap { newNet, err := parseIPNet(newIP, newMask) if err != nil { return nil } var result []SubnetOverlap for _, s := range existing { if s.Interface == excludeIface { continue } parts, err := parseSubnetStr(s.Subnet) if err != nil { continue } existingNet, err := parseIPNet(parts[0], parts[1]) if err != nil { continue } if subnetsOverlap(newNet, existingNet) { result = append(result, s) } } return result } func ParseSubnet(ipStr, maskStr string) (string, error) { n, err := parseIPNet(ipStr, maskStr) if err != nil { return "", err } return n.String(), nil } func parseSubnetStr(s string) ([2]string, error) { for i := len(s) - 1; i >= 0; i-- { if s[i] == '/' { return [2]string{s[:i], s[i+1:]}, nil } } return [2]string{}, fmt.Errorf("invalid subnet format: %s", s) }