mirror of
https://github.com/kiddin9/op-packages.git
synced 2026-11-02 03:33:56 +08:00
This commit is contained in:
1 parent
c7bafc635d
commit
c71da84035
264 files changed
+8169
-3944
No files matched your search
@@ -16,7 +16,7 @@ IPKG_INSTROOT="${IPKG_INSTROOT:-}"
|
||||
export IPKG_INSTROOT
|
||||
|
||||
readonly PKG_NAME='safeshield'
|
||||
readonly PKG_VERSION='0.3.24-r1'
|
||||
readonly PKG_VERSION='0.3.25-r1'
|
||||
|
||||
if type extra_command >/dev/null 2>&1; then
|
||||
extra_command 'apply_local_rules' 'Apply local allow/block rules using the cached Hub artifact'
|
||||
@@ -232,7 +232,7 @@ service_triggers() {
|
||||
status_service() {
|
||||
local status stage valid_line_count
|
||||
local enabled refresh_interval_s refresh_on_boot require_wan boot_delay
|
||||
local license_key artifact_tier artifact_version license_plan device_profile
|
||||
local artifact_tier artifact_version entitlement_plan device_profile
|
||||
local artifact_source_count artifact_block_source_count artifact_allow_source_count
|
||||
local dnsmasq_version dnsmasq_min_version
|
||||
local statistics_enabled statistics_snapshot_interval_s statistics_retention_hours
|
||||
@@ -246,7 +246,6 @@ status_service() {
|
||||
refresh_on_boot="$(ss_config_get config refresh_on_boot 1)"
|
||||
require_wan="$(ss_config_get config require_wan 1)"
|
||||
boot_delay="$(ss_config_get config boot_start_delay_s 30)"
|
||||
license_key="$(ss_config_get config license_key '')"
|
||||
statistics_enabled="$(ss_config_get config statistics_enabled 1)"
|
||||
statistics_snapshot_interval_s="$(ss_config_get config statistics_snapshot_interval_s 60)"
|
||||
statistics_retention_hours="$(ss_config_get config statistics_retention_hours 168)"
|
||||
@@ -264,7 +263,7 @@ status_service() {
|
||||
artifact_source_count="$(json get artifact_source_count 2>/dev/null)"
|
||||
artifact_block_source_count="$(json get artifact_block_source_count 2>/dev/null)"
|
||||
artifact_allow_source_count="$(json get artifact_allow_source_count 2>/dev/null)"
|
||||
license_plan="$(json get license_plan 2>/dev/null)"
|
||||
entitlement_plan="$(json get entitlement_plan 2>/dev/null)"
|
||||
device_profile="$(json get device_profile 2>/dev/null)"
|
||||
dnsmasq_version="$(json get dnsmasq_version 2>/dev/null)"
|
||||
dnsmasq_min_version="$(json get dnsmasq_min_version 2>/dev/null)"
|
||||
@@ -278,7 +277,6 @@ status_service() {
|
||||
printf 'refresh_on_boot: %s\n' "$refresh_on_boot"
|
||||
printf 'require_wan: %s\n' "$require_wan"
|
||||
printf 'boot_start_delay_s: %s\n' "$boot_delay"
|
||||
printf 'license_key: %s\n' "$(ss_mask_secret "$license_key")"
|
||||
|
||||
if [ -f "${SS_BLOCKLIST_FILE}" ]; then
|
||||
printf '%s\n' 'blocklist: installed'
|
||||
@@ -296,7 +294,7 @@ status_service() {
|
||||
|
||||
printf 'status: %s\n' "$status"
|
||||
[ -n "$stage" ] && printf 'stage: %s\n' "$stage"
|
||||
[ -n "$license_plan" ] && printf 'license_plan: %s\n' "$license_plan"
|
||||
[ -n "$entitlement_plan" ] && printf 'entitlement_plan: %s\n' "$entitlement_plan"
|
||||
[ -n "$device_profile" ] && printf 'device_profile: %s\n' "$device_profile"
|
||||
[ -n "$artifact_tier" ] && printf 'artifact_tier: %s\n' "$artifact_tier"
|
||||
[ -n "$artifact_version" ] && printf 'artifact_version: %s\n' "$artifact_version"
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
#!/bin/sh
|
||||
set -e
|
||||
|
||||
# SafeShield authentication is device-scoped. Remove the retired raw license
|
||||
# key from preserved configurations so obsolete secrets do not remain on flash.
|
||||
if uci -q get safeshield.config.license_key >/dev/null 2>&1; then
|
||||
uci -q delete safeshield.config.license_key
|
||||
uci -q commit safeshield
|
||||
fi
|
||||
|
||||
exit 0
|
||||
@@ -177,6 +177,17 @@ ss_read_installed_version() {
|
||||
printf '%s' "$version"
|
||||
}
|
||||
|
||||
ss_device_credential_path() {
|
||||
printf '%s' "${SS_DEVICE_CREDENTIAL_FILE:-/etc/smartsafehub/device-credential.json}"
|
||||
}
|
||||
|
||||
ss_device_credential_token() {
|
||||
local path
|
||||
path="$(ss_device_credential_path)"
|
||||
[ -r "$path" ] || return 1
|
||||
ss_json_get_file "$path" '@.token'
|
||||
}
|
||||
|
||||
ss_write_resolve_payload() {
|
||||
local out="$1"
|
||||
local model vendor arch memory physical_fingerprint safeshield_version
|
||||
@@ -202,7 +213,6 @@ ss_write_resolve_payload() {
|
||||
|
||||
cat >"$out" <<__SAFESHIELD_JSON__
|
||||
{
|
||||
"license_key": $(ss_json_value "$ss_license_key"),
|
||||
"device": {
|
||||
"physical_fingerprint": $(ss_json_value "$physical_fingerprint"),
|
||||
"fingerprint_version": ${SS_FINGERPRINT_VERSION:-1},
|
||||
@@ -494,22 +504,25 @@ ss_resolve_artifact_sources() {
|
||||
}
|
||||
|
||||
ss_resolve_artifact() {
|
||||
local url response payload retries ok statistics_entitlement_rc
|
||||
local url response payload retries ok statistics_entitlement_rc device_credential
|
||||
|
||||
SS_RESOLVE_ERROR_CODE='api_resolve_failed'
|
||||
url='https://www.smartsafehub.com/api/v1/licenses/resolve'
|
||||
url='https://www.smartsafehub.com/api/v1/devices/sync'
|
||||
payload="$SS_API_PAYLOAD"
|
||||
response="$SS_API_RESPONSE"
|
||||
|
||||
ss_status_set artifact_download_url_present "0"
|
||||
|
||||
if [ -z "$ss_license_key" ]; then
|
||||
log_info "license_key is empty; resolving SafeShield artifact as unlicensed/free device"
|
||||
ss_status_set license_plan "free"
|
||||
ss_status_set license_status "unlicensed"
|
||||
fi
|
||||
|
||||
ss_write_resolve_payload "$payload" || return 1
|
||||
device_credential="$(ss_device_credential_token 2>/dev/null || true)"
|
||||
if [ -z "$device_credential" ]; then
|
||||
log_warn "SmartSafeHub device credential is not available yet; retrying on the next refresh"
|
||||
SS_RESOLVE_ERROR_CODE='device_registration_pending'
|
||||
ss_status_set device_registration_status 'pending'
|
||||
ss_status_set health_api_resolve "0"
|
||||
return 1
|
||||
fi
|
||||
ss_status_set device_registration_status 'registered'
|
||||
|
||||
retries=1
|
||||
ok=0
|
||||
@@ -517,7 +530,7 @@ ss_resolve_artifact() {
|
||||
ss_should_stop && return 130
|
||||
log_info "Resolving SafeShield artifact via Hub API (try ${retries}/${ss_download_retry})"
|
||||
|
||||
if ss_http_post_json "$url" "$payload" "$response" && [ -s "$response" ]; then
|
||||
if ss_http_post_json "$url" "$payload" "$response" "Device ${device_credential}" && [ -s "$response" ]; then
|
||||
ok=1
|
||||
break
|
||||
fi
|
||||
@@ -546,8 +559,8 @@ ss_resolve_artifact() {
|
||||
ss_resolved_artifact_version="$(ss_json_get_file "$response" '@.artifact.version')"
|
||||
ss_resolved_artifact_unique_domains="$(ss_json_get_file "$response" '@.artifact.unique_domains')"
|
||||
ss_resolved_artifact_rules="$(ss_json_get_file "$response" '@.artifact.rules')"
|
||||
ss_resolved_license_plan="$(ss_json_get_file "$response" '@.license.plan')"
|
||||
ss_resolved_license_status="$(ss_json_get_file "$response" '@.license.status')"
|
||||
ss_resolved_entitlement_plan="$(ss_json_get_file "$response" '@.entitlement.plan')"
|
||||
ss_resolved_entitlement_status="$(ss_json_get_file "$response" '@.entitlement.status')"
|
||||
ss_resolved_device_profile="$(ss_json_get_file "$response" '@.device.profile')"
|
||||
|
||||
if command -v ss_statistics_sync_upload_entitlement >/dev/null 2>&1; then
|
||||
@@ -555,7 +568,7 @@ ss_resolve_artifact() {
|
||||
ss_statistics_sync_upload_entitlement "$response" || statistics_entitlement_rc=$?
|
||||
case "$statistics_entitlement_rc" in
|
||||
0) ;;
|
||||
2) log_info "Cloud statistics upload is not enabled for the current license" ;;
|
||||
2) log_info "Cloud statistics upload is not enabled for the current plan" ;;
|
||||
*) log_warn "Hub API response did not include usable statistics upload credentials" ;;
|
||||
esac
|
||||
fi
|
||||
@@ -572,12 +585,12 @@ ss_resolve_artifact() {
|
||||
ss_status_set artifact_version "$ss_resolved_artifact_version"
|
||||
ss_status_set artifact_unique_domains "${ss_resolved_artifact_unique_domains:-0}"
|
||||
ss_status_set artifact_rules "${ss_resolved_artifact_rules:-0}"
|
||||
ss_status_set license_plan "${ss_resolved_license_plan:-free}"
|
||||
ss_status_set license_status "${ss_resolved_license_status:-unlicensed}"
|
||||
ss_status_set entitlement_plan "${ss_resolved_entitlement_plan:-free}"
|
||||
ss_status_set entitlement_status "${ss_resolved_entitlement_status:-unlicensed}"
|
||||
ss_status_set device_profile "$ss_resolved_device_profile"
|
||||
SS_RESOLVE_ERROR_CODE=''
|
||||
|
||||
log_ok "Resolved ${ss_resolved_artifact_tier:-unknown}/${ss_resolved_artifact_version:-unknown} artifact sources for plan ${ss_resolved_license_plan:-free}"
|
||||
log_ok "Resolved ${ss_resolved_artifact_tier:-unknown}/${ss_resolved_artifact_version:-unknown} artifact sources for plan ${ss_resolved_entitlement_plan:-free}"
|
||||
}
|
||||
|
||||
ss_verify_artifact_sha256() {
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
|
||||
ss_enabled="0"
|
||||
ss_verbosity="2"
|
||||
ss_license_key=""
|
||||
ss_device_vendor=""
|
||||
ss_device_model=""
|
||||
ss_device_arch=""
|
||||
@@ -105,7 +104,6 @@ ss_load_config() {
|
||||
|
||||
ss_enabled="$(ss_config_get config enabled 0)"
|
||||
ss_verbosity="$(ss_config_get config verbosity 2)"
|
||||
ss_license_key="$(ss_config_get config license_key '')"
|
||||
ss_device_vendor="$(ss_config_get config device_vendor '')"
|
||||
ss_device_model="$(ss_config_get config device_model '')"
|
||||
ss_device_arch="$(ss_config_get config device_arch '')"
|
||||
|
||||
@@ -358,20 +358,22 @@ ss_statistics_load_upload_credentials() {
|
||||
}
|
||||
|
||||
ss_statistics_refresh_upload_credentials() {
|
||||
local request response resolve_url retries rc=1
|
||||
local request response sync_url retries rc=1 device_credential
|
||||
|
||||
resolve_url='https://www.smartsafehub.com/api/v1/licenses/resolve'
|
||||
request="${SS_STATISTICS_DIR:-/tmp/safeshield/statistics}/upload-resolve-request.json"
|
||||
response="${SS_STATISTICS_DIR:-/tmp/safeshield/statistics}/upload-resolve-response.json"
|
||||
sync_url='https://www.smartsafehub.com/api/v1/devices/sync'
|
||||
request="${SS_STATISTICS_DIR:-/tmp/safeshield/statistics}/upload-sync-request.json"
|
||||
response="${SS_STATISTICS_DIR:-/tmp/safeshield/statistics}/upload-sync-response.json"
|
||||
|
||||
ss_load_config || return 1
|
||||
device_credential="$(ss_device_credential_token 2>/dev/null || true)"
|
||||
[ -n "$device_credential" ] || return 1
|
||||
mkdir -p "${request%/*}" || return 1
|
||||
ss_refresh_lock_open_wait "${ss_download_timeout:-10}" || return $?
|
||||
|
||||
if ! ss_write_resolve_payload "$request"; then
|
||||
printf '{}\n' >"$request" || {
|
||||
ss_refresh_lock_close
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
retries=1
|
||||
while [ "$retries" -le "${ss_download_retry:-3}" ]; do
|
||||
@@ -379,7 +381,7 @@ ss_statistics_refresh_upload_credentials() {
|
||||
rc=130
|
||||
break
|
||||
}
|
||||
if ss_http_post_json "$resolve_url" "$request" "$response" && [ -s "$response" ]; then
|
||||
if ss_http_post_json "$sync_url" "$request" "$response" "Device ${device_credential}" && [ -s "$response" ]; then
|
||||
rc=0
|
||||
ss_statistics_sync_upload_entitlement "$response" || rc=$?
|
||||
break
|
||||
|
||||
@@ -70,8 +70,8 @@ ss_status_reset_blocklist_fields() {
|
||||
}
|
||||
|
||||
ss_status_reset_artifact_fields() {
|
||||
ss_status_set license_plan ""
|
||||
ss_status_set license_status ""
|
||||
ss_status_set entitlement_plan ""
|
||||
ss_status_set entitlement_status ""
|
||||
ss_status_set physical_fingerprint ""
|
||||
ss_status_set fingerprint_version ""
|
||||
ss_status_set identity_provider ""
|
||||
|
||||
@@ -8,23 +8,6 @@ command_exists() {
|
||||
command -v "$1" >/dev/null 2>&1
|
||||
}
|
||||
|
||||
ss_mask_secret() {
|
||||
local value="$1"
|
||||
local len
|
||||
|
||||
[ -n "$value" ] || {
|
||||
printf '%s' ''
|
||||
return 0
|
||||
}
|
||||
|
||||
len="${#value}"
|
||||
if [ "$len" -le 8 ] 2>/dev/null; then
|
||||
printf '%s' '********'
|
||||
else
|
||||
printf '%s****%s' "${value%${value#????}}" "${value#${value%????}}"
|
||||
fi
|
||||
}
|
||||
|
||||
is_valid_integer() {
|
||||
case "$1" in
|
||||
'' | *[!0-9]*) return 1 ;;
|
||||
|
||||
@@ -375,7 +375,7 @@ upload_send_pending() {
|
||||
continue
|
||||
fi
|
||||
if [ "$refresh_rc" -eq 2 ]; then
|
||||
log_info 'Cloud statistics upload is no longer enabled for the current license'
|
||||
log_info 'Cloud statistics upload is no longer enabled for the current account entitlement'
|
||||
upload_pending_clear
|
||||
return 2
|
||||
fi
|
||||
@@ -433,14 +433,11 @@ main() {
|
||||
fi
|
||||
|
||||
wait_s="$SS_STATS_UPLOAD_INTERVAL_S"
|
||||
if [ -z "${ss_license_key:-}" ]; then
|
||||
ss_statistics_upload_denied || ss_statistics_disable_cloud_upload >/dev/null 2>&1 || true
|
||||
fi
|
||||
if ss_statistics_upload_denied; then
|
||||
upload_pending_clear
|
||||
if [ -n "${ss_license_key:-}" ] && ss_statistics_upload_denied_recheck_due "$SS_STATS_UPLOAD_DENIED_RECHECK_S"; then
|
||||
if ss_statistics_upload_denied_recheck_due "$SS_STATS_UPLOAD_DENIED_RECHECK_S"; then
|
||||
log_info 'Rechecking Hub statistics upload entitlement'
|
||||
# Stamp this attempt before network I/O so a failed resolve cannot
|
||||
# Stamp this attempt before network I/O so a failed device sync cannot
|
||||
# turn into a routine upload retry loop while entitlement is denied.
|
||||
ss_statistics_set_upload_entitlement denied >/dev/null 2>&1 || true
|
||||
entitlement_rc=0
|
||||
|
||||
@@ -18,9 +18,7 @@
|
||||
"set_enabled",
|
||||
"refresh",
|
||||
"rule_add",
|
||||
"rule_delete",
|
||||
"license_get",
|
||||
"license_update"
|
||||
"rule_delete"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,6 @@ let status = require('status');
|
||||
let config = require('config');
|
||||
let refresh = require('refresh');
|
||||
let rules = require('rules');
|
||||
let license = require('license');
|
||||
let statistics = require('statistics');
|
||||
|
||||
return {
|
||||
@@ -66,17 +65,7 @@ return {
|
||||
refresh: true
|
||||
},
|
||||
call: rules.delete
|
||||
},
|
||||
|
||||
license_get: {
|
||||
call: license.get
|
||||
},
|
||||
|
||||
license_update: {
|
||||
args: {
|
||||
license_key: ''
|
||||
},
|
||||
call: license.update
|
||||
}
|
||||
|
||||
}
|
||||
};
|
||||
@@ -12,7 +12,6 @@ let reload_uci = core.reload_uci;
|
||||
let cfg = core.cfg;
|
||||
let to_bool = core.to_bool;
|
||||
let to_int = core.to_int;
|
||||
let mask_secret = core.mask_secret;
|
||||
let api_error = core.api_error;
|
||||
let uci_commit_option = core.uci_commit_option;
|
||||
let bool_uci = core.bool_uci;
|
||||
@@ -46,10 +45,6 @@ function build_config() {
|
||||
version: CONFIG_SCHEMA_VERSION
|
||||
},
|
||||
values: values,
|
||||
license: {
|
||||
configured: !!cfg('license_key', ''),
|
||||
key_masked: mask_secret(cfg('license_key', ''))
|
||||
},
|
||||
device: {
|
||||
vendor: cfg('device_vendor', ''),
|
||||
model: cfg('device_model', ''),
|
||||
@@ -67,9 +62,6 @@ function validate_config_value(name, value) {
|
||||
return api_error('dedicated_method_required', 'Use set_enabled to change enabled state', name);
|
||||
}
|
||||
|
||||
if (name == 'license_key') {
|
||||
return api_error('dedicated_method_required', 'Use license_update to change the license key', name);
|
||||
}
|
||||
|
||||
return api_error('unknown_option', 'Unsupported SafeShield configuration option', name);
|
||||
}
|
||||
|
||||
@@ -149,20 +149,6 @@ function identity_cfg(name, def) {
|
||||
return (v == null) ? def : v;
|
||||
}
|
||||
|
||||
function mask_secret(v) {
|
||||
let s = sprintf('%s', v || '');
|
||||
let n = length(s);
|
||||
|
||||
if (n == 0) {
|
||||
return '';
|
||||
}
|
||||
|
||||
if (n <= 8) {
|
||||
return '********';
|
||||
}
|
||||
|
||||
return sprintf('%s...%s', substr(s, 0, 4), substr(s, n - 4));
|
||||
}
|
||||
|
||||
function api_error(code, message, field) {
|
||||
let error = {
|
||||
@@ -242,7 +228,6 @@ return {
|
||||
reload_uci: reload_uci,
|
||||
cfg: cfg,
|
||||
identity_cfg: identity_cfg,
|
||||
mask_secret: mask_secret,
|
||||
api_error: api_error,
|
||||
uci_commit_option: uci_commit_option,
|
||||
uci_delete_option: uci_delete_option,
|
||||
|
||||
@@ -1,90 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
let core = require('core');
|
||||
let runtime = require('runtime');
|
||||
|
||||
let reload_uci = core.reload_uci;
|
||||
let cfg = core.cfg;
|
||||
let trim = core.trim;
|
||||
let mask_secret = core.mask_secret;
|
||||
let api_error = core.api_error;
|
||||
let uci_commit_option = core.uci_commit_option;
|
||||
let uci_delete_option = core.uci_delete_option;
|
||||
let start_refresh_async = runtime.start_refresh_async;
|
||||
let reset_statistics_upload_state = runtime.reset_statistics_upload_state;
|
||||
|
||||
function license_get_call() {
|
||||
reload_uci();
|
||||
|
||||
let key = cfg('license_key', '');
|
||||
|
||||
return {
|
||||
ok: true,
|
||||
license: {
|
||||
configured: !!key,
|
||||
key: key
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function license_update_call(request) {
|
||||
reload_uci();
|
||||
|
||||
if (request.args.license_key == null) {
|
||||
return api_error('missing_argument', 'license_key is required; use an empty string to clear it', 'license_key');
|
||||
}
|
||||
|
||||
let key = trim(request.args.license_key);
|
||||
|
||||
if (length(key) > 512 || match(key, /[\r\n]/)) {
|
||||
return api_error('invalid_license_key', 'license_key must be at most 512 characters and contain no line breaks', 'license_key');
|
||||
}
|
||||
|
||||
let current = cfg('license_key', '');
|
||||
|
||||
if (current == key) {
|
||||
return {
|
||||
ok: true,
|
||||
changed: false,
|
||||
license: {
|
||||
configured: !!key,
|
||||
key_masked: mask_secret(key)
|
||||
},
|
||||
refresh: {
|
||||
requested: false,
|
||||
accepted: false,
|
||||
reason: 'unchanged'
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
let saved = key == ''
|
||||
? uci_delete_option('license_key')
|
||||
: uci_commit_option('license_key', key);
|
||||
|
||||
if (!saved) {
|
||||
return api_error('uci_commit_failed', 'Failed to update the SafeShield license key');
|
||||
}
|
||||
|
||||
reset_statistics_upload_state();
|
||||
let refresh = start_refresh_async();
|
||||
|
||||
return {
|
||||
ok: true,
|
||||
changed: true,
|
||||
license: {
|
||||
configured: !!key,
|
||||
key_masked: mask_secret(key)
|
||||
},
|
||||
refresh: {
|
||||
requested: true,
|
||||
accepted: refresh.accepted,
|
||||
reason: refresh.reason || ''
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
get: license_get_call,
|
||||
update: license_update_call
|
||||
};
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
let core = require('core');
|
||||
let fs = require('fs');
|
||||
let ubus = require('ubus').connect();
|
||||
|
||||
let PKG_NAME = core.PKG_NAME;
|
||||
let STATUS_FILE = core.STATUS_FILE;
|
||||
@@ -12,43 +11,72 @@ let to_bool = core.to_bool;
|
||||
let reload_uci = core.reload_uci;
|
||||
let cfg = core.cfg;
|
||||
|
||||
function service_running(name) {
|
||||
let r = ubus.call('service', 'list', { name: name });
|
||||
if (!r || !r[name] || !r[name].instances) {
|
||||
return false;
|
||||
// Do not call ubus synchronously from an rpcd handler. In particular,
|
||||
// service.list may require the same event loop currently serving the caller.
|
||||
// Use an independent ubus client with its built-in -t timeout (seconds).
|
||||
// BusyBox/OpenWrt installations do not necessarily provide coreutils timeout.
|
||||
// Only successful procd lookups are briefly reused. A failed lookup must not
|
||||
// poison subsequent requests or be mistaken for a stopped service.
|
||||
let service_cache = {};
|
||||
|
||||
function service_status(name, use_cache) {
|
||||
if (name != PKG_NAME && name != 'dnsmasq') {
|
||||
return { state: 'unknown', running: false, lookup_ok: false };
|
||||
}
|
||||
|
||||
for (let inst_name, inst in r[name].instances) {
|
||||
if (inst.running) {
|
||||
return true;
|
||||
let now = time();
|
||||
let cached = service_cache[name];
|
||||
if (use_cache && cached && cached.at == now) {
|
||||
return cached.value;
|
||||
}
|
||||
|
||||
let pipe = fs.popen(sprintf("ubus -t 2 call service list '{\"name\":\"%s\"}' 2>/dev/null", name), 'r');
|
||||
if (!pipe) {
|
||||
return { state: 'unknown', running: false, lookup_ok: false };
|
||||
}
|
||||
|
||||
let output = pipe.read('all');
|
||||
pipe.close();
|
||||
if (!output) {
|
||||
return { state: 'unknown', running: false, lookup_ok: false };
|
||||
}
|
||||
|
||||
let result = json(output);
|
||||
// procd returns an empty object when the named service is absent.
|
||||
// That is a valid stopped response, not a transport failure.
|
||||
if (type(result) != 'object') {
|
||||
return { state: 'unknown', running: false, lookup_ok: false };
|
||||
}
|
||||
|
||||
let instances = result[name] && result[name].instances;
|
||||
let running = false;
|
||||
if (type(instances) == 'object') {
|
||||
for (let instance_name, instance in instances) {
|
||||
if (instance && instance.running) {
|
||||
running = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
let value = { state: running ? 'running' : 'stopped', running: running, lookup_ok: true, instances: instances || {} };
|
||||
if (use_cache) {
|
||||
service_cache[name] = { at: now, value: value };
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
function service_running(name) {
|
||||
return service_status(name, false).running;
|
||||
}
|
||||
|
||||
function service_instance_running(name, instance_name) {
|
||||
let r = ubus.call('service', 'list', { name: name });
|
||||
if (!r || !r[name] || !r[name].instances || !r[name].instances[instance_name]) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return !!r[name].instances[instance_name].running;
|
||||
let state = service_status(name, false);
|
||||
return !!(state.instances && state.instances[instance_name] && state.instances[instance_name].running);
|
||||
}
|
||||
|
||||
function dnsmasq_running() {
|
||||
let r = ubus.call('service', 'list', { name: 'dnsmasq' });
|
||||
if (!r || !r.dnsmasq || !r.dnsmasq.instances) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (let inst_name, inst in r.dnsmasq.instances) {
|
||||
if (inst.running) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
return service_running('dnsmasq');
|
||||
}
|
||||
|
||||
function run_service_action(action, timeout_ms) {
|
||||
@@ -85,10 +113,11 @@ function start_refresh_async() {
|
||||
};
|
||||
}
|
||||
|
||||
if (!service_running(PKG_NAME)) {
|
||||
let service = service_status(PKG_NAME, false);
|
||||
if (!service.running) {
|
||||
return {
|
||||
accepted: false,
|
||||
reason: 'service_stopped'
|
||||
reason: service.lookup_ok ? 'service_stopped' : 'service_unavailable'
|
||||
};
|
||||
}
|
||||
|
||||
@@ -129,10 +158,11 @@ function start_local_apply_async() {
|
||||
};
|
||||
}
|
||||
|
||||
if (!service_running(PKG_NAME)) {
|
||||
let service = service_status(PKG_NAME, false);
|
||||
if (!service.running) {
|
||||
return {
|
||||
accepted: false,
|
||||
reason: 'service_stopped'
|
||||
reason: service.lookup_ok ? 'service_stopped' : 'service_unavailable'
|
||||
};
|
||||
}
|
||||
|
||||
@@ -155,6 +185,7 @@ function start_local_apply_async() {
|
||||
|
||||
return {
|
||||
service_running: service_running,
|
||||
service_status: service_status,
|
||||
service_instance_running: service_instance_running,
|
||||
dnsmasq_running: dnsmasq_running,
|
||||
run_service_action: run_service_action,
|
||||
|
||||
@@ -91,7 +91,8 @@ function build_statistics() {
|
||||
let snapshot_interval_s = to_int(cfg('statistics_snapshot_interval_s', '60'), 60);
|
||||
let data = read_json_file(STATISTICS_FILE, {});
|
||||
let totals = (type(data.totals) == 'object') ? data.totals : {};
|
||||
let collector_running = service_instance_running(PKG_NAME, 'statistics');
|
||||
let collector_service = runtime.service_status(PKG_NAME, true);
|
||||
let collector_running = !!(collector_service.instances && collector_service.instances.statistics && collector_service.instances.statistics.running);
|
||||
let effective_enabled = enabled && collector_running;
|
||||
let source = sanitize_source(data.source);
|
||||
if (!effective_enabled) {
|
||||
@@ -106,6 +107,8 @@ function build_statistics() {
|
||||
effective_enabled: effective_enabled,
|
||||
available: !!data.schema,
|
||||
collector_running: collector_running,
|
||||
collector_state: collector_service.lookup_ok ? (collector_running ? 'running' : 'stopped') : 'unknown',
|
||||
collector_lookup_ok: collector_service.lookup_ok,
|
||||
volatile: to_bool(data.volatile, true),
|
||||
storage: sprintf('%s', data.storage || 'tmpfs'),
|
||||
persistent: to_bool(data.persistent, false),
|
||||
|
||||
@@ -20,7 +20,6 @@ let file_size_kb = core.file_size_kb;
|
||||
let to_bool = core.to_bool;
|
||||
let to_optional_bool = core.to_optional_bool;
|
||||
let to_int = core.to_int;
|
||||
let mask_secret = core.mask_secret;
|
||||
let service_running = runtime.service_running;
|
||||
let dnsmasq_running = runtime.dnsmasq_running;
|
||||
|
||||
@@ -134,8 +133,6 @@ function build_status() {
|
||||
let refresh_interval_s = to_int(cfg('refresh_interval_s', '28800'), 28800);
|
||||
let boot_start_delay_s = to_int(cfg('boot_start_delay_s', '30'), 30);
|
||||
|
||||
let license_key = cfg('license_key', '');
|
||||
let license_configured = !!license_key;
|
||||
let apply_local_overrides = to_bool(cfg('apply_local_overrides', '1'), true);
|
||||
|
||||
let cfg_physical_fingerprint = identity_cfg('physical_fingerprint', '');
|
||||
@@ -186,8 +183,8 @@ function build_status() {
|
||||
let artifact_block_source_count = to_int(data.artifact_block_source_count || (artifact_download_url_present ? 1 : 0), 0);
|
||||
let artifact_allow_source_count = to_int(data.artifact_allow_source_count || 0, 0);
|
||||
|
||||
let license_plan = data.license_plan || '';
|
||||
let license_status = data.license_status || '';
|
||||
let entitlement_plan = data.entitlement_plan || '';
|
||||
let entitlement_status = data.entitlement_status || '';
|
||||
let physical_fingerprint = data.physical_fingerprint || cfg_physical_fingerprint || '';
|
||||
let fingerprint_version = to_int(data.fingerprint_version || cfg_fingerprint_version || 1, 1);
|
||||
let identity_provider = data.identity_provider || cfg_identity_provider || '';
|
||||
@@ -217,8 +214,10 @@ function build_status() {
|
||||
|
||||
let hub_source = build_api_source(data, enabled);
|
||||
let installed = blocklist_installed || file_exists(BLOCKLIST_FILE);
|
||||
let refreshd_running = service_running(PKG_NAME);
|
||||
let dns_running = dnsmasq_running();
|
||||
let refresh_service = runtime.service_status(PKG_NAME, true);
|
||||
let dns_service = runtime.service_status('dnsmasq', true);
|
||||
let refreshd_running = refresh_service.running;
|
||||
let dns_running = dns_service.running;
|
||||
|
||||
let generated_at = time();
|
||||
let next_refresh_in_s = 0;
|
||||
@@ -245,7 +244,11 @@ function build_status() {
|
||||
|
||||
runtime: {
|
||||
refreshd_running: refreshd_running,
|
||||
refreshd_state: refresh_service.state,
|
||||
refreshd_lookup_ok: refresh_service.lookup_ok,
|
||||
dnsmasq_running: dns_running,
|
||||
dnsmasq_state: dns_service.state,
|
||||
dnsmasq_lookup_ok: dns_service.lookup_ok,
|
||||
dnsmasq_version: dnsmasq_version,
|
||||
dnsmasq_min_version: dnsmasq_min_version,
|
||||
dns_runtime_ok: health_dns_runtime || dns_running,
|
||||
@@ -255,11 +258,9 @@ function build_status() {
|
||||
last_result: last_result,
|
||||
last_error_code: last_error_code
|
||||
},
|
||||
license: {
|
||||
configured: license_configured,
|
||||
key_masked: mask_secret(license_key),
|
||||
plan: license_plan,
|
||||
status: license_status
|
||||
entitlement: {
|
||||
plan: entitlement_plan,
|
||||
status: entitlement_status
|
||||
},
|
||||
|
||||
device: {
|
||||
|
||||
Reference in new issue
Block a user