🎨 Sync 2026-09-15 23:44:06

This commit is contained in:
github-actions[bot] committed 2026-09-15 23:44:06 +08:00
1 parent 1a3656348a
commit 75e213b656
19 files changed
+130 -152

No files matched your search

+2 -2
View File
@@ -6,11 +6,11 @@ include $(TOPDIR)/rules.mk
PKG_NAME:=cloudreve
PKG_VERSION:=4.18.0
PKG_RELEASE:=17
PKG_RELEASE:=18
PKG_SOURCE_PROTO:=git
PKG_SOURCE_URL:=https://github.com/cloudreve/Cloudreve.git
PKG_SOURCE_VERSION:=ade1866be54a3614bc643ab5f513e93a1e0dc82f
PKG_SOURCE_VERSION:=e03a104a7d42a1fa46c697f57b66e550189350ea
PKG_MIRROR_HASH:=skip
PKG_LICENSE:=GPL-3.0-only
+1 -1
View File
@@ -12,7 +12,7 @@ LUCI_DEPENDS:=+luci-base +logd +jsonfilter
LUCI_PKGARCH:=all
PKG_VERSION:=0.1.41
PKG_RELEASE:=15
PKG_RELEASE:=16
# Reproducible build: honor SOURCE_DATE_EPOCH from the build environment (set by docker-sdk.sh / CI).
ifdef SOURCE_DATE_EPOCH
@@ -9,7 +9,7 @@
*
* While paused, ingest grows up to fetchLinesMax. Live mode caps at rowLimit.
* On resume, merge (do not replace) so pause-accumulated rows survive the first
* live poll — see issue #43 pause→resume data loss.
* live poll.
*/
function ingestCap(paused, rowLimit, fetchLinesMax) {
@@ -12,13 +12,13 @@ return baseclass.extend({
APP_VERSION: '0.1.41',
ROW_LIMIT_OPTIONS: [25, 50, 100, 250, 500, 1000, 2000],
DEFAULT_ROW_LIMIT: 100,
/* Row pass/deny tint (#40): classic green/red default; accessible teal/orange */
/* Row pass/deny tint: classic green/red default; accessible teal/orange */
ROW_TINT_OPTIONS: ['off', 'classic', 'accessible'],
DEFAULT_ROW_TINT: 'classic',
FETCH_LINES_MAX: 2000 /* ubus poll / logd ring cap (~2000 lines ≈ typical ring) */,
/* DOM budget: ~250 new/updated rows painted per second on typical LuCI routers */
RENDER_CAP_PER_SEC: 250,
/* #306 Layer 2 — measured client RTT → poll cadence (seconds). */
/* Layer 2 — measured client RTT → poll cadence (seconds). */
POLL_CADENCE_FAST_S: 1,
POLL_CADENCE_MID_S: 2,
POLL_CADENCE_SLOW_S: 5,
@@ -24,7 +24,7 @@ const callFwlivePoll = rpc.declare({
object: 'fwlive',
method: 'poll',
params: ['addresses']
/* Full reply object kept so reply.error reaches fetchEntries (#233). */
/* Full reply object kept so reply.error reaches fetchEntries. */
});
const callFwliveRules = rpc.declare({
@@ -36,7 +36,7 @@ const callFwliveResolve = rpc.declare({
object: 'fwlive',
method: 'resolve',
params: ['addresses']
/* Full reply kept so disabled:"load" reaches the view (#306 Layer 2). */
/* Full reply kept so disabled:"load" reaches the view. */
});
const callFwliveLoggingStatus = rpc.declare({
@@ -98,11 +98,11 @@ return view.extend({
sessionSeen: null,
pauseBufferLoading: false,
paused: false,
/* One-shot: first live poll after unpause merges instead of replacing (#43). */
/* One-shot: first live poll after unpause merges instead of replacing. */
resumeMerge: false,
pollFn: null,
pollDataInFlight: false,
/* #306 Layer 2 — visibility / RTT cadence / shed surfacing. */
/* Layer 2 — visibility / RTT cadence / shed surfacing. */
pollEpoch: 0,
pollCadenceSec: 1,
rttStreakKind: null,
@@ -473,7 +473,7 @@ return view.extend({
const res = await callFwliveRules();
this.rulesMap = (res && res.rules) || {};
this.firewallBackend = (res && res.backend) || 'nft';
/* Bounds / mktemp failures are reply.error — same idea as poll (#245). */
/* Bounds / mktemp failures are reply.error — same idea as poll. */
this.lastRulesError = (res && res.error) || null;
if (this.lastRulesError) console.warn('fwlive rules map error:', this.lastRulesError);
} catch (e) {
@@ -829,7 +829,7 @@ return view.extend({
return typeof document !== 'undefined' && !!document.hidden;
},
/* Classify one RTT sample into hysteresis buckets (#306).
/* Classify one RTT sample into hysteresis buckets.
* error and >1.5s share the slow/degraded streak so mixed failures still trip N=3. */
rttKindFromMs(ms, errored) {
if (errored) return 'slow';
@@ -1099,7 +1099,7 @@ return view.extend({
const limit = this.rowLimit;
const suffix = this.statusSuffix();
/* While paused the buffer can grow past the display limit — count matches
* over the full buffer so "matching" is not capped at visibleRows (#83). */
* over the full buffer so "matching" is not capped at visibleRows. */
let shown = matchCount;
if (this.paused) {
const filters = this.readFilters();
@@ -1206,7 +1206,7 @@ return view.extend({
if (wasPaused && !this.paused) {
this.followLive = true;
/* Merge pause buffer with the first live poll — do not replace (#43). */
/* Merge pause buffer with the first live poll — do not replace. */
this.resumeMerge = true;
const epoch = this.pollEpoch;
this.fetchEntries()
@@ -1671,7 +1671,7 @@ return view.extend({
}
} finally {
/* Only the owning epoch clears — a stale hidden-era poll must not
* drop the catch-up guard after resume (Grok #331). Resume clears
* drop the catch-up guard after resume. Resume clears
* explicitly before starting the catch-up poll. */
if (epoch === this.pollEpoch) this.pollDataInFlight = false;
}
@@ -2,7 +2,7 @@
# SPDX-License-Identifier: Apache-2.0
# Copyright 2025-2026 Lucas Albers <lucas.b.albers@gmail.com>
#
# Layer 1 adaptive poll cap (#306). Sourced by rpcd/fwlive.
# Layer 1 adaptive poll cap. Sourced by rpcd/fwlive.
# Always on unless test/triage override (no UCI / no product config):
# FWLIVE_ADAPTIVE=0|false|off|no
# or sentinel ${FWLIVE_ADAPTIVE_OFF_FILE:-<state-dir>/fwlive-adaptive-off}
@@ -18,10 +18,10 @@
# flock, lock busy, or corrupt state. Lock-busy ⇒ unlocked last-writer-wins is
# acceptable (state stays one valid JSON line; ordering is not guaranteed).
# Failed ubus log.read must NOT call record() — a ~0 ms failure is not "cold"
# health and must not clear an existing hot/shed cap (#329 Hermes Q1).
# health and must not clear an existing hot/shed cap.
# Outside the measured duration interval: plan (pre), record/merge (post).
# messages_received is 0 in Layer 1 — do not ash-scan the filter JSON after
# end_cs (Grok #329 P1); accurate count belongs in the filter or a later layer.
# end_cs; accurate count belongs in the filter or a later layer.
FWLIVE_ADAPTIVE_STATE_FILE="${FWLIVE_ADAPTIVE_STATE_FILE:-/var/run/fwlive-state.json}"
# Optional overrides; when unset, lock/off paths are siblings of the current state.
@@ -238,7 +238,7 @@ fwlive_adaptive_with_lock() {
"$@"
return $?
fi
# Create lock at 0600 (logging.lock #167 — world-readable fd can take LOCK_EX).
# Create lock at 0600 (world-readable fd can take LOCK_EX).
if [ ! -e "$_lock" ]; then
if ! ( umask 077; : >"$_lock" ) 2>/dev/null; then
"$@"
@@ -424,7 +424,7 @@ fwlive_adaptive_merge_reply() {
}
# Count log[*] via "msg" keys — helper for tests / future filter-side count.
# NOT called on the poll hot path (Grok #329 P1): ash-scanning a 2000-entry
# NOT called on the poll hot path: ash-scanning a 2000-entry
# reply after end_cs is unmeasured overhead that cannot shed itself.
fwlive_adaptive_count_log() {
_json=$1
@@ -6,11 +6,11 @@
# Log messages are treated as data (jsonfilter + awk stdin); never interpolated
# into shell command strings. Usage: ubus call log read '...' | fwlive-log-filter.sh
#
# Perf (#219): one jsonfilter for @.log[*] plus one awk classify. Process
# Perf: one jsonfilter for @.log[*] plus one awk classify. Process
# count is constant per poll, not O(entries).
#
# Entry point (pipeline). The classifier sibling is sourced and must not set
# strict mode itself (#291 C3).
# strict mode itself.
set -eu
# shellcheck disable=SC3040
(set -o pipefail) 2>/dev/null && set -o pipefail
@@ -26,7 +26,7 @@ FILTER_DIR="$(cd "$(dirname "$0")" && pwd)"
. "$FILTER_DIR/fwlive-is-firewall-event.sh"
# The classifier is a package asset, not generated at request time. Fail
# closed if an incomplete install or a damaged package removed it (#321).
# closed if an incomplete install or a damaged package removed it.
if [ ! -r "$CLASSIFY_AWK" ]; then
printf '%s' '{"log":[],"error":"classifier_missing"}'
exit 1
@@ -35,8 +35,8 @@ fi
printf '%s' '{"log":['
# Prefer stdin over -s: Linux MAX_ARG_STRLEN is 128KiB; a raised logd ring
# (or paused FETCH_LINES_MAX poll) can exceed that and make jsonfilter fail
# while this script still printed {"log":[]} and exited 0 (#234).
# jsonfilter miss / empty @.log is not fatal; must still close JSON (#220).
# set -e + pipefail cannot apply to this pipeline (#291 C3).
# while this script still printed {"log":[]} and exited 0.
# jsonfilter miss / empty @.log is not fatal; must still close JSON.
# set -e + pipefail cannot apply to this pipeline.
jsonfilter -e '@.log[*]' 2>/dev/null | _fwlive_filter_json_entries || true
printf '%s' ']}'
@@ -7,13 +7,13 @@
# Sourced library (rpcd plugin, package prerm). Do not `set -euo pipefail`
# here: prerm is best-effort (`restore ... || logger`; exit 0) and callers
# expect soft failures. The rpcd entry point enables strict mode; critical
# paths use explicit `|| return 1` / `|| true` (#244, #291 C3).
# paths use explicit `|| return 1` / `|| true`.
NF_LOG_IPV4='/proc/sys/net/netfilter/nf_log/2'
NF_LOG_IPV6='/proc/sys/net/netfilter/nf_log/10'
# Serialize the WAN logging read->compute->set->commit window across
# concurrent ubus write-ACL callers (#151): each toggle re-reads the current
# concurrent ubus write-ACL callers: each toggle re-reads the current
# firewall.<zone>.log bit, computes a target, then uci set + uci commit. Two
# concurrent callers could otherwise interleave and last-commit-wins.
#
@@ -28,7 +28,7 @@ WAN_LOG_LOCK_FILE="${FWLIVE_WAN_LOG_LOCK_FILE:-/etc/fwlive/logging.lock}"
WAN_LOG_BASELINE_FILE="${FWLIVE_WAN_LOG_BASELINE_FILE:-/etc/fwlive/wan-log-baseline}"
# RFC 8259 string escape. Lives here so prerm can source this file
# standalone (#222). rpcd sources us and must not redefine this.
# standalone. rpcd sources us and must not redefine this.
json_escape() {
# Escape for JSON string content per RFC 8259 (including remaining C0 controls).
# Slurp stdin as one string. Default awk RS is newline — RS="" is
@@ -67,8 +67,8 @@ json_escape() {
}'
}
# Production lock dir must be owned by euid with no group/other write (#204).
# Avoid GNU/BusyBox `stat -c` — stock OpenWrt omits FEATURE_STAT_FORMAT (#232).
# Production lock dir must be owned by euid with no group/other write.
# Avoid GNU/BusyBox `stat -c` — stock OpenWrt omits FEATURE_STAT_FORMAT.
wan_log_lock_dir_safe() {
dir="$1"
[ -n "$dir" ] || return 1
@@ -86,10 +86,10 @@ wan_log_lock_dir_safe() {
# Acquire the exclusive logging lock on fd 9. Blocks until free; fails closed
# (return 1) only if the lock file cannot be opened or flock is unavailable.
# Create/tighten the lock to 0600 so unprivileged UIDs cannot take LOCK_EX on
# a world-readable fd (issue #167 / flock(2) allows exclusive locks on O_RDONLY).
# a world-readable fd (flock(2) allows exclusive locks on O_RDONLY).
acquire_wan_log_lock() {
# Fail closed on symlinks: chmod/chown/exec O_TRUNC follow the target as root
# (#204). Default lock lives under /etc/fwlive (root-only), not world-writable
# Default lock lives under /etc/fwlive (root-only), not world-writable
# /var/lock. Re-check after create/tighten (TOCTOU).
lock_dir="$(dirname "$WAN_LOG_LOCK_FILE")"
[ -L "$lock_dir" ] && return 1
@@ -107,7 +107,7 @@ acquire_wan_log_lock() {
# Probe in a subshell first: a failed `exec` redirection aborts a POSIX
# non-interactive shell outright, so `|| return 1` on the real exec would
# never run — and `2>/dev/null` on the same exec would permanently
# silence this process's stderr on the success path (#244).
# silence this process's stderr on the success path.
( exec 9>>"$WAN_LOG_LOCK_FILE" ) 2>/dev/null || return 1
exec 9>>"$WAN_LOG_LOCK_FILE"
flock 9 2>/dev/null || {
@@ -124,16 +124,16 @@ release_wan_log_lock() {
find_wan_zone_section() {
# Match anonymous (@zone[N]) and named (e.g. wan) sections whose name option
# is 'wan'. Prefer the first section whose type is zone (issue #168); skip
# is 'wan'. Prefer the first section whose type is zone; skip
# non-zone sections that happen to share name='wan'.
# uci missing / no wan zone is empty, not fatal. pipefail + set -e
# cannot apply to this pipeline (#291 C3).
# cannot apply to this pipeline.
_zones=$(uci -q show firewall 2>/dev/null \
| sed -n "s/^firewall\.\([^.]*\)\.name='wan'$/\1/p") || true
for zone in $_zones; do
[ -n "$zone" ] || continue
# uci -q get exits 1 on a missing section. Capture with || true so
# set -e cannot abort inside "$(…)" before || continue (#291 C3).
# set -e cannot abort inside "$(…)" before || continue.
_type=$(uci -q get "firewall.${zone}" 2>/dev/null || true)
[ "$_type" = "zone" ] || continue
printf '%s' "$zone"
@@ -143,7 +143,7 @@ find_wan_zone_section() {
}
firewall_changes_pending() {
# uci miss is "no pending changes". set -e cannot apply (#291 C3).
# uci miss is "no pending changes". set -e cannot apply.
pending="$(uci -q changes firewall 2>/dev/null || true)"
[ -n "$pending" ]
}
@@ -151,7 +151,7 @@ firewall_changes_pending() {
wan_zone_log_value() {
zone="$1"
[ -n "$zone" ] || return 1
# Unset option is a valid empty value; uci -q get exits 1 (#291 C3).
# Unset option is a valid empty value; uci -q get exits 1.
uci -q get "firewall.${zone}.log" 2>/dev/null || true
}
@@ -165,7 +165,7 @@ uci_canonical_firewall_section() {
| sed -n '1s/^firewall\.\([^=.]*\)=.*/\1/p'
}
# True when two firewall section ids refer to the same WAN zone (issue #239).
# True when two firewall section ids refer to the same WAN zone.
# Compare canonical cfg ids — do NOT treat every name=wan zone as identical
# (duplicate wan sections would under-match foreign .log deltas as ours).
wan_firewall_zone_same() {
@@ -196,7 +196,7 @@ wan_log_staged_line_section() {
esac
}
# Zone ids that may appear in `uci changes` for firewall.<id>.log (issue #239).
# Zone ids that may appear in `uci changes` for firewall.<id>.log.
wan_log_staged_zone_ids() {
_zone="$1"
_staged="$2"
@@ -296,7 +296,7 @@ maybe_snapshot_wan_log_baseline() {
restore_wan_log_baseline() {
path="$(wan_log_baseline_path)"
[ -f "$path" ] || return 0
# Empty file is a valid "option was unset" baseline (#291 C3).
# Empty file is a valid "option was unset" baseline.
baseline=$(cat "$path" 2>/dev/null || true)
zone=$(find_wan_zone_section)
if [ -z "$zone" ]; then
@@ -417,18 +417,18 @@ collect_logging_blockers() {
check_nf_log_ipv6 || logging_blockers_append 'nf_log_ipv6_missing'
# Report via LOGGING_BLOCKERS, not exit status: return 1 would abort
# build_logging_status_json under set -e (#291 C3).
# build_logging_status_json under set -e.
return 0
}
collect_logging_warnings() {
LOGGING_WARNINGS=''
# rpcd/fwlive run_with_timeout fail-closes to 127 without timeout (#229).
# rpcd/fwlive run_with_timeout fail-closes to 127 without timeout.
# Warnings are diagnostics only — do not gate the enable-logging CTA.
command -v timeout >/dev/null 2>&1 || logging_warnings_append 'timeout_missing'
# Report via LOGGING_WARNINGS, not exit status (#291 C3).
# Report via LOGGING_WARNINGS, not exit status.
return 0
}
@@ -444,9 +444,9 @@ json_null_or_string() {
build_logging_status_json() {
zone=$(find_wan_zone_section)
# Empty zone / unset log bit are valid; set -e cannot apply (#291 C3).
# Empty zone / unset log bit are valid; set -e cannot apply.
log_val=$(wan_zone_log_value "$zone") || log_val=
# Unset log_limit is a valid empty value; uci -q get exits 1 (#291 C3).
# Unset log_limit is a valid empty value; uci -q get exits 1.
limit_val=
if [ -n "$zone" ]; then
limit_val=$(uci -q get "firewall.${zone}.log_limit" 2>/dev/null || true)
@@ -491,7 +491,7 @@ restore_wan_zone_log() {
zone="$1"
previous="$2"
[ -n "$zone" ] || return 1
# Refuse to publish unrelated staged firewall deltas (issue #168).
# Refuse to publish unrelated staged firewall deltas.
if firewall_changes_pending; then
logger -t fwlive "WAN log rollback skipped: firewall changes pending" 2>/dev/null || true
return 1
@@ -508,7 +508,7 @@ restore_wan_zone_log() {
# closes the read->compute->set->commit window so a concurrent toggle cannot
# commit between our read and our write (no lost update / no stale overwrite).
#
# TOCTOU hardening (#191): UCI staging is global per config file, so a
# TOCTOU hardening: UCI staging is global per config file, so a
# non-cooperating writer (another admin's `uci set`, the LuCI firewall page)
# can stage a delta AFTER the toggle's early firewall_changes_pending check.
# Staging and committing therefore live INSIDE this function — the only path
@@ -544,7 +544,7 @@ commit_wan_log_change() {
zone_json="$2"
target="$3"
# Last-moment guard (#191): runs before OUR delta is staged, so a
# Last-moment guard: runs before OUR delta is staged, so a
# non-empty changes list here can only be a foreign writer's race.
if firewall_changes_pending; then
logger -t fwlive "WAN log toggle aborted at commit gate: firewall changes staged by another writer" 2>/dev/null || true
@@ -568,7 +568,7 @@ commit_wan_log_change() {
fi
fi
# Post-stage guard (#191): anything besides our log option is foreign.
# Post-stage guard: anything besides our log option is foreign.
# Undo our staging only (set previous / delete to match committed); leave
# foreign deltas untouched and abort without commit.
_staged=$(uci -q changes firewall 2>/dev/null || true)
@@ -589,8 +589,8 @@ commit_wan_log_change() {
# firewall_changes_pending from this package's own orphaned write —
# but ONLY when nothing foreign is staged: `uci revert firewall` is
# config-wide (uci has no option-level revert), and reverting would
# clobber a concurrent writer's uncommitted delta (CodeRabbit/luna
# fold, #191). With foreign staging present, leave it and warn.
# clobber a concurrent writer's uncommitted delta. With foreign
# staging present, leave it and warn.
_staged=$(uci -q changes firewall 2>/dev/null || true)
_total=$(printf '%s\n' "$_staged" | grep -c . 2>/dev/null || true)
_ours=$(wan_log_count_our_staged_lines "$zone" "$_staged")
@@ -603,7 +603,7 @@ commit_wan_log_change() {
return 1
fi
# Post-commit verification (#191): confirm the committed config really
# Post-commit verification: confirm the committed config really
# carries what we wrote (empty target = option must now be gone/empty).
# A mismatch means another writer overtook the commit: warn loudly but do
# NOT blind-revert (that would destroy unrelated committed data); the
@@ -619,7 +619,7 @@ commit_wan_log_change() {
# would block a concurrent toggle until the holder exits — BusyBox flock has
# no -w timeout).
#
# The ROLLBACK re-acquires the lock (luna fold 2026-08-10): read->compare->
# The ROLLBACK re-acquires the lock: read->compare->
# restore is only atomic when no other writer can commit between the read and
# the restore. All writers hold the same flock, so re-acquiring it makes the
# decision-and-restore a serialized unit. The lock is held only for the few
@@ -686,7 +686,7 @@ enable_wan_logging() {
# The log bit is re-read AFTER acquiring the lock so the target is computed
# from the latest committed value; a concurrent toggle cannot interleave.
# Staging + commit live inside commit_wan_log_change behind its last-moment
# firewall_changes_pending re-check (#191): a foreign writer racing between
# firewall_changes_pending re-check: a foreign writer racing between
# the early check above and the commit aborts the toggle instead of having
# its half-finished delta published with our log bit.
if ! acquire_wan_log_lock; then
@@ -740,7 +740,7 @@ disable_wan_logging() {
# The log bit is re-read AFTER acquiring the lock so the target is computed
# from the latest committed value; a concurrent toggle cannot interleave.
# Staging + commit live inside commit_wan_log_change behind its last-moment
# firewall_changes_pending re-check (#191): a foreign writer racing between
# firewall_changes_pending re-check: a foreign writer racing between
# the early check above and the commit aborts the toggle instead of having
# its half-finished delta published with our log bit.
if ! acquire_wan_log_lock; then
+29 -29
View File
@@ -23,7 +23,7 @@ ADAPTIVE_SH="$LIBEXEC_DIR/fwlive-adaptive-cap.sh"
RESOLVE_MAX=32
# Per-lookup nslookup timeout (integer seconds — BusyBox `timeout` truncates
# fractional values to 0 on OpenWrt 23.05/1.36, so 0.5 would silently
# degrade to no timeout; luna fold 2026-08-10). The wall-clock budget
# degrade to no timeout.. The wall-clock budget
# below is the real whole-call bound; this per-lookup cap only prevents a
# single hung resolver from dominating the budget. LAN/local-resolver
# lookups are single-digit ms, so 1s is ample. Passed as argv to
@@ -42,7 +42,7 @@ NFT_TIMEOUT=5
# CLI-only iptables fixture path for __rulesmap_iptables (no arbitrary paths).
RULESMAP_IPTABLES_FILE='/tmp/rulesmap'
# json_escape lives in fwlive-logging.sh so prerm can source that file alone (#222).
# json_escape lives in fwlive-logging.sh so prerm can source that file alone.
# shellcheck disable=SC1090,SC1091 # LOGGING_SH resolves to sibling ../fwlive-logging.sh
. "$LOGGING_SH"
# shellcheck disable=SC1090,SC1091
@@ -52,10 +52,10 @@ slug_key() {
echo "$1" | tr '[:upper:]' '[:lower:]' | tr ' _' '--'
}
# Cap rules JSON size so a huge ruleset cannot unbound an rpcd reply (#229).
# Cap rules JSON size so a huge ruleset cannot unbound an rpcd reply.
RULES_MAP_MAX_KEYS=512
RULES_MAP_MAX_BYTES=65536
# Same wall-clock bound as nft for iptables-save / ip6tables-save (#229).
# Same wall-clock bound as nft for iptables-save / ip6tables-save.
# Overridable for host tests (e.g. FWLIVE_IPTABLES_TIMEOUT=1).
IPTABLES_TIMEOUT="${FWLIVE_IPTABLES_TIMEOUT:-5}"
@@ -70,7 +70,7 @@ map_add() {
# ("foo" vs "foobar") and value false positives ("see foo").
# Quoting "$esc_key" makes the match literal (no glob escaping needed).
# Callers apply UCI, then labeled (!fw4:) prefixes, then unlabeled
# cosmetics so first-wins prefers authoritative names (#230).
# cosmetics so first-wins prefers authoritative names.
case "$OUT" in
*"\"$esc_key\":"*) return 0 ;;
esac
@@ -92,7 +92,7 @@ map_add() {
uci_rule_names() {
# uci missing / empty firewall config is "no names", not fatal.
# pipefail + set -e cannot apply to this pipeline (#291 C3).
# pipefail + set -e cannot apply to this pipeline.
uci -q show firewall 2>/dev/null | sed -n "s/^firewall\.@rule\[[0-9]*\]\.name='\(.*\)'$/\1/p" || true
}
@@ -142,7 +142,7 @@ run_with_timeout() {
if command -v timeout >/dev/null 2>&1; then
timeout "$secs" "$@" 2>/dev/null
else
# Fail closed (#229): never run unbounded when timeout is absent.
# Fail closed: never run unbounded when timeout is absent.
return 127
fi
}
@@ -170,7 +170,7 @@ map_uci_rule_names() {
# Line-wise (here-doc, not an unquoted for-loop) so a name with
# spaces stays one token. Names that fail is_uci_style_name are
# skipped: parseRuleHint() cannot match them, and fragments of
# "My Rule" must not shadow a real rule named Rule (#226).
# "My Rule" must not shadow a real rule named Rule.
# The while-read stays in the current shell (here-doc, not a
# pipeline) so map_add mutations reach OUT.
while IFS= read -r name || [ -n "$name" ]; do
@@ -187,7 +187,7 @@ EOF
}
# pass=labeled|unlabeled|all — labeled before unlabeled so !fw4: beats
# an earlier cosmetic for the same prefix under first-wins (#230).
# an earlier cosmetic for the same prefix under first-wins.
map_from_nft_stream() {
pass="${1:-all}"
while IFS= read -r line; do
@@ -255,7 +255,7 @@ _fwlive_tmp_dir_ok() {
# Fail closed unless the dump dir is a real directory with the sticky
# bit. Without sticky, another uid can unlink a just-created mktemp
# file and replace it with a symlink before we reopen with `>` as
# root (same class as #204). Optional $1 is for CLI tests; production
# root (same class as the WAN logging lock). Optional $1 is for CLI tests; production
# always uses /tmp.
dir="${1:-/tmp}"
[ -n "$dir" ] || return 1
@@ -288,7 +288,7 @@ build_rules_map() {
backend=$(detect_firewall_backend)
# UCI first, then labeled stream prefixes, then unlabeled cosmetics
# (#230). First-wins keeps UCI over nft and !fw4: over cosmetic.
# First-wins keeps UCI over nft and !fw4: over cosmetic.
map_uci_rule_names
case "$backend" in
@@ -435,16 +435,16 @@ fetch_firewall_logs() {
shed_flag=${2:-0}
# Adaptive plan prints: lines shed bucket
start_cs=$(fwlive_adaptive_clock_cs)
# Drop dead oneshot flag — only consumed on logd's stream branch (#306).
# Drop dead oneshot flag — only consumed on logd's stream branch.
if ! raw=$(ubus call log read "{\"lines\":$lines,\"stream\":false}" 2>/dev/null); then
# Do not record ~0 ms as cold: failure is not healthy fast processing
# and must not clear an existing hot/shed cap (#329 Hermes Q1).
# and must not clear an existing hot/shed cap.
out='{"log":[],"error":"log_read_failed"}'
fwlive_adaptive_merge_reply "$out" "$shed_flag" "$lines" 0 0
return 0
fi
# Do not swallow a filter failure into a silent empty table (#220).
# Do not swallow a filter failure into a silent empty table.
# If the filter exits non-zero but still printed JSON, keep it.
# Empty success is not valid poll JSON — the shipped filter always
# prints {"log":[...]}, but a stub/regression must not emit a blank body.
@@ -455,12 +455,12 @@ fetch_firewall_logs() {
fi
[ -n "$out" ] || out='{"log":[],"error":"filter_empty"}'
end_cs=$(fwlive_adaptive_clock_cs)
# Uptime wrap / skew: end < start — do not record as cold (Grok #329 P2).
# Uptime wrap / skew: end < start — do not record as cold.
if [ "$end_cs" -ge "$start_cs" ]; then
_dur=$(((end_cs - start_cs) * 10))
fwlive_adaptive_record "$_dur" "$lines"
fi
# Layer 1: messages_received stays 0 — no post-filter ash count (Grok #329 P1).
# Layer 1: messages_received stays 0 — no post-filter ash count.
_trunc=0
[ "$shed_flag" = 1 ] && _trunc=1
[ "$lines" -lt "$requested" ] && _trunc=1
@@ -502,7 +502,7 @@ resolve_hostname() {
[ -n "$ip" ] || return 1
is_resolvable_address "$ip" || return 1
command -v nslookup >/dev/null 2>&1 || return 1
# timeout/nslookup miss is "no PTR", not a plugin abort (#291 C3).
# timeout/nslookup miss is "no PTR", not a plugin abort.
out=$(run_with_timeout "$RESOLVE_TIMEOUT" nslookup "$ip") || return 1
[ -n "$out" ] || return 1
name=$(parse_nslookup_name "$out") || return 1
@@ -510,7 +510,7 @@ resolve_hostname() {
printf '%s' "$name"
}
# Strict IPv4/IPv6 validation before nslookup (issue #190): the old char-class
# Strict IPv4/IPv6 validation before nslookup: the old char-class
# check admitted hostname-shaped tokens of hex chars + dots/colons
# (e.g. "dead.beef.cafe.baad"), letting the resolver fall back to upstream DNS
# queries chosen by an authenticated session. Validate the real address
@@ -523,7 +523,7 @@ is_resolvable_address() {
# Reject anything outside the address alphabet BEFORE awk, so embedded
# newlines/whitespace (which awk would treat as record separators) can
# never let a valid first record mask trailing garbage that still reaches
# nslookup (#190, CodeRabbit/luna fold): nslookup only ever sees a single
# nslookup: nslookup only ever sees a single
# token. Note the check intentionally allows only hex/colon/dot.
case "$addr" in
*[!0-9a-fA-F:.]*) return 1 ;;
@@ -596,7 +596,7 @@ is_resolvable_address() {
}
resolve_addresses() {
# Missing resolver must not look like "no PTR" (#218). Check before
# Missing resolver must not look like "no PTR". Check before
# starting the budget clock or reading stdin.
if ! command -v nslookup >/dev/null 2>&1; then
command -v logger >/dev/null 2>&1 && logger -t fwlive "nslookup not found; resolve disabled"
@@ -604,14 +604,14 @@ resolve_addresses() {
return 0
fi
# Load shed: previous poll was hot (#306 Layer 1).
# Load shed: previous poll was hot.
if fwlive_adaptive_is_hot; then
printf '{"names":{},"disabled":"load"}'
return 0
fi
# Wall-clock budget clock starts at the TRUE function entry (luna
# folds 2026-08-10): the budget must bound the whole call — including
# Wall-clock budget clock starts at the TRUE function entry: the
# budget must bound the whole call — including
# read_rpc_input (stalled stdin must not escape the budget) and json
# parsing. `date +%s` can jump under NTP sync — accepted (worst case
# the budget over- or under-runs by the jump; worker starvation is
@@ -657,12 +657,12 @@ resolve_addresses() {
# never START a lookup past the budget.
now=$(date +%s)
[ $((now - start)) -ge "$RESOLVE_BUDGET" ] && break
# Missing/empty element: set -u cannot read bare $ip (#291 C3).
# Missing/empty element: set -u cannot read bare $ip.
if ! is_resolvable_address "${ip:-}"; then
continue
fi
# NXDOMAIN / timeout: resolve_hostname returns 1. set -e
# cannot apply to this assignment (#291 C3).
# cannot apply to this assignment.
name=$(resolve_hostname "$ip") || name=
if [ -n "$name" ]; then
map_add "$ip" "$name"
@@ -729,7 +729,7 @@ run_selftest() {
return 1
fi
# Issue #190: hostname-shaped tokens of hex chars + dots/colons passed the
# hostname-shaped tokens of hex chars + dots/colons passed the
# old char-class check and made the resolver fall back to upstream DNS. Each case
# below must REJECT (and would be ACCEPTED by the reverted char-class code).
if is_resolvable_address 'ab.cd.ef.01'; then
@@ -757,7 +757,7 @@ run_selftest() {
echo 'is_resolvable_address: expected accept IPv6-mapped ::ffff:192.0.2.1' >&2
return 1
fi
# Multi-line input must be rejected wholesale (CodeRabbit/luna fold): awk
# Multi-line input must be rejected wholesale: awk
# reads newline-separated records, so a valid first record must not mask
# trailing garbage that would still reach nslookup.
if is_resolvable_address "$(printf '192.0.2.1\nnot-an-address')"; then
@@ -849,7 +849,7 @@ Address: 127.0.0.1:53")
run_logging_selftest || return 1
# Strict-mode smoke (#291 C3): status JSON uses soft-fail helpers
# Strict-mode smoke: status JSON uses soft-fail helpers
# (uci miss, empty WAN zone). Must not abort under dash/ash set -e.
_status=$(build_logging_status_json) || {
echo "build_logging_status_json: aborted under set -e" >&2
@@ -950,7 +950,7 @@ case "${1:-}" in
build_rules_map
;;
poll)
# rpcd may omit argv $3 and pass JSON on stdin (#291 C3).
# rpcd may omit argv $3 and pass JSON on stdin.
poll_logs "${3:-}"
;;
resolve)
+1 -1
View File
@@ -8,7 +8,7 @@ include $(TOPDIR)/rules.mk
PKG_NAME:=luci-app-passwall
PKG_VERSION:=26.9.9
PKG_RELEASE:=274
PKG_RELEASE:=275
PKG_PO_VERSION:=$(PKG_VERSION)
PKG_CONFIG_DEPENDS:= \
@@ -20,7 +20,10 @@ for _, k in ipairs(com.order) do
if k ~= "chinadns-ng" then
o = s:option(Value, k:gsub("%-","_") .. "_file", translatef("%s App Path", v.name))
o.default = v.default_path or ("/usr/bin/" .. k)
o.rmempty = false
o.placeholder = o.default
function o:remove(section)
self:write(section, self.default)
end
end
end
@@ -408,16 +408,16 @@ load_acl() {
else
[ -n "${DIRECT_DNSMASQ_PORT}" ] && dns_redirect=${DIRECT_DNSMASQ_PORT}
fi
if [ -n "${dns_redirect}" ]; then
if ([ -n "$tcp_port" ] || [ -n "$udp_port" ]) && [ -n "$dns_redirect" ]; then
$ipt_m -A PSW $(comment "$remarks") -p udp ${_ipt_source} --dport 53 -j RETURN
[ "$_ipv4" != "1" ] && $ip6t_m -A PSW $(comment "$remarks") -p udp ${_ipt_source} --dport 53 -j RETURN 2>/dev/null
$ip6t_m -A PSW $(comment "$remarks") -p udp ${_ipt_source} --dport 53 -j RETURN 2>/dev/null
$ipt_m -A PSW $(comment "$remarks") -p tcp ${_ipt_source} --dport 53 -j RETURN
[ "$_ipv4" != "1" ] && $ip6t_m -A PSW $(comment "$remarks") -p tcp ${_ipt_source} --dport 53 -j RETURN 2>/dev/null
$ip6t_m -A PSW $(comment "$remarks") -p tcp ${_ipt_source} --dport 53 -j RETURN 2>/dev/null
$ipt_n -A PSW_DNS $(comment "$remarks") -p udp ${_ipt_source} --dport 53 -j REDIRECT --to-ports ${dns_redirect}
[ "$_ipv4" != "1" ] && $ip6t_n -A PSW_DNS $(comment "$remarks") -p udp ${_ipt_source} --dport 53 -j REDIRECT --to-ports ${dns_redirect} 2>/dev/null
$ip6t_n -A PSW_DNS $(comment "$remarks") -p udp ${_ipt_source} --dport 53 -j REDIRECT --to-ports ${dns_redirect} 2>/dev/null
$ipt_n -A PSW_DNS $(comment "$remarks") -p tcp ${_ipt_source} --dport 53 -j REDIRECT --to-ports ${dns_redirect}
[ "$_ipv4" != "1" ] && $ip6t_n -A PSW_DNS $(comment "$remarks") -p tcp ${_ipt_source} --dport 53 -j REDIRECT --to-ports ${dns_redirect} 2>/dev/null
[ -z "$(get_cache_var "ACL_${sid}_default")" ] && echolog " - ${msg}节点不同于全局配置,DNS 重定向到专用服务器[${dns_redirect}]。"
$ip6t_n -A PSW_DNS $(comment "$remarks") -p tcp ${_ipt_source} --dport 53 -j REDIRECT --to-ports ${dns_redirect} 2>/dev/null
[ -z "$(get_cache_var "ACL_${sid}_default")" ] && echolog " - ${msg}节点不同于全局配置,DNS 重定向到专用服务器[${dns_redirect}]"
fi
[ -n "$tcp_port" ] || [ -n "$udp_port" ] && {
@@ -597,7 +597,7 @@ load_acl() {
[ -n "${DIRECT_DNSMASQ_PORT}" ] && DNS_REDIRECT=${DIRECT_DNSMASQ_PORT}
fi
if [ -n "${DNS_REDIRECT}" ]; then
if ([ -n "${TCP_PROXY_MODE}" ] || [ -n "${UDP_PROXY_MODE}" ]) && [ -n "$DNS_REDIRECT" ]; then
$ipt_m -A PSW $(comment "默认") -p udp --dport 53 -j RETURN
$ip6t_m -A PSW $(comment "默认") -p udp --dport 53 -j RETURN 2>/dev/null
$ipt_m -A PSW $(comment "默认") -p tcp --dport 53 -j RETURN
@@ -606,6 +606,7 @@ load_acl() {
$ip6t_n -A PSW_DNS $(comment "默认") -p udp --dport 53 -j REDIRECT --to-ports ${DNS_REDIRECT} 2>/dev/null
$ipt_n -A PSW_DNS $(comment "默认") -p tcp --dport 53 -j REDIRECT --to-ports ${DNS_REDIRECT}
$ip6t_n -A PSW_DNS $(comment "默认") -p tcp --dport 53 -j REDIRECT --to-ports ${DNS_REDIRECT} 2>/dev/null
echolog " - ${msg}DNS 重定向到专用服务器[${DNS_REDIRECT}]"
fi
[ -n "${TCP_PROXY_MODE}" ] || [ -n "${UDP_PROXY_MODE}" ] && {
@@ -471,26 +471,13 @@ load_acl() {
fi
if ([ -n "$tcp_port" ] || [ -n "$udp_port" ]) && [ -n "$dns_redirect" ]; then
if [ "$PROXY_IPV6" = "1" ]; then
nft "add rule $NFTABLE_NAME PSW_MANGLE_V6 meta l4proto udp ${_ipt_source} udp dport 53 counter accept"
nft "add rule $NFTABLE_NAME PSW_MANGLE_V6 meta l4proto tcp ${_ipt_source} tcp dport 53 counter accept"
nft "add rule $NFTABLE_NAME PSW_DNS meta l4proto udp ${_ipt_source} udp dport 53 counter redirect to :$dns_redirect comment \"$remarks\""
nft "add rule $NFTABLE_NAME PSW_DNS meta l4proto tcp ${_ipt_source} tcp dport 53 counter redirect to :$dns_redirect comment \"$remarks\""
else
nft "add rule $NFTABLE_NAME PSW_MANGLE ip protocol udp ${_ipt_source} udp dport 53 counter accept"
nft "add rule $NFTABLE_NAME PSW_MANGLE ip protocol tcp ${_ipt_source} tcp dport 53 counter accept"
nft "add rule $NFTABLE_NAME PSW_DNS ip protocol udp ${_ipt_source} udp dport 53 counter redirect to :$dns_redirect comment \"$remarks\""
nft "add rule $NFTABLE_NAME PSW_DNS ip protocol tcp ${_ipt_source} tcp dport 53 counter redirect to :$dns_redirect comment \"$remarks\""
fi
[ -z "$(get_cache_var "ACL_${sid}_default")" ] && echolog " - ${msg}节点不同于全局配置,DNS 重定向到专用服务器[${dns_redirect}]。"
else
if [ "$PROXY_IPV6" = "1" ]; then
nft "add rule $NFTABLE_NAME PSW_DNS meta l4proto udp ${_ipt_source} udp dport 53 counter return comment \"$remarks\""
nft "add rule $NFTABLE_NAME PSW_DNS meta l4proto tcp ${_ipt_source} tcp dport 53 counter return comment \"$remarks\""
else
nft "add rule $NFTABLE_NAME PSW_DNS ip protocol udp ${_ipt_source} udp dport 53 counter return comment \"$remarks\""
nft "add rule $NFTABLE_NAME PSW_DNS ip protocol tcp ${_ipt_source} tcp dport 53 counter return comment \"$remarks\""
fi
nft "add rule $NFTABLE_NAME PSW_MANGLE ip protocol udp ${_ipt_source} udp dport 53 counter return comment \"$remarks\""
nft "add rule $NFTABLE_NAME PSW_MANGLE ip protocol tcp ${_ipt_source} tcp dport 53 counter return comment \"$remarks\""
nft "add rule $NFTABLE_NAME PSW_MANGLE_V6 meta l4proto udp ${_ipt_source} udp dport 53 counter return comment \"$remarks\""
nft "add rule $NFTABLE_NAME PSW_MANGLE_V6 meta l4proto tcp ${_ipt_source} tcp dport 53 counter return comment \"$remarks\""
nft "add rule $NFTABLE_NAME PSW_DNS meta l4proto udp ${_ipt_source} udp dport 53 counter redirect to :$dns_redirect comment \"$remarks\""
nft "add rule $NFTABLE_NAME PSW_DNS meta l4proto tcp ${_ipt_source} tcp dport 53 counter redirect to :$dns_redirect comment \"$remarks\""
[ -z "$(get_cache_var "ACL_${sid}_default")" ] && echolog " - ${msg}节点不同于全局配置,DNS 重定向到专用服务器[${dns_redirect}]"
fi
[ -n "$tcp_port" ] || [ -n "$udp_port" ] && {
@@ -670,25 +657,13 @@ load_acl() {
fi
if ([ -n "${TCP_PROXY_MODE}" ] || [ -n "${UDP_PROXY_MODE}" ]) && [ -n "$DNS_REDIRECT" ]; then
if [ "$PROXY_IPV6" = "1" ]; then
nft "add rule $NFTABLE_NAME PSW_MANGLE_V6 meta l4proto udp udp dport 53 counter accept"
nft "add rule $NFTABLE_NAME PSW_MANGLE_V6 meta l4proto tcp tcp dport 53 counter accept"
nft "add rule $NFTABLE_NAME PSW_DNS meta l4proto udp udp dport 53 counter redirect to :$DNS_REDIRECT comment \"默认\""
nft "add rule $NFTABLE_NAME PSW_DNS meta l4proto tcp tcp dport 53 counter redirect to :$DNS_REDIRECT comment \"默认\""
else
nft "add rule $NFTABLE_NAME PSW_MANGLE ip protocol udp udp dport 53 counter accept"
nft "add rule $NFTABLE_NAME PSW_MANGLE ip protocol tcp tcp dport 53 counter accept"
nft "add rule $NFTABLE_NAME PSW_DNS ip protocol udp udp dport 53 counter redirect to :$DNS_REDIRECT comment \"默认\""
nft "add rule $NFTABLE_NAME PSW_DNS ip protocol tcp tcp dport 53 counter redirect to :$DNS_REDIRECT comment \"默认\""
fi
else
if [ "$PROXY_IPV6" = "1" ]; then
nft "add rule $NFTABLE_NAME PSW_DNS meta l4proto udp udp dport 53 counter return comment \"默认\""
nft "add rule $NFTABLE_NAME PSW_DNS meta l4proto tcp tcp dport 53 counter return comment \"默认\""
else
nft "add rule $NFTABLE_NAME PSW_DNS ip protocol udp udp dport 53 counter return comment \"默认\""
nft "add rule $NFTABLE_NAME PSW_DNS ip protocol tcp tcp dport 53 counter return comment \"默认\""
fi
nft "add rule $NFTABLE_NAME PSW_MANGLE ip protocol udp udp dport 53 counter return comment \"默认\""
nft "add rule $NFTABLE_NAME PSW_MANGLE ip protocol tcp tcp dport 53 counter return comment \"默认\""
nft "add rule $NFTABLE_NAME PSW_MANGLE_V6 meta l4proto udp udp dport 53 counter return comment \"默认\""
nft "add rule $NFTABLE_NAME PSW_MANGLE_V6 meta l4proto tcp tcp dport 53 counter return comment \"默认\""
nft "add rule $NFTABLE_NAME PSW_DNS meta l4proto udp udp dport 53 counter redirect to :${DNS_REDIRECT} comment \"默认\""
nft "add rule $NFTABLE_NAME PSW_DNS meta l4proto tcp tcp dport 53 counter redirect to :${DNS_REDIRECT} comment \"默认\""
echolog " - ${msg}DNS 重定向到专用服务器[${DNS_REDIRECT}]"
fi
[ -n "${TCP_PROXY_MODE}" ] || [ -n "${UDP_PROXY_MODE}" ] && {
@@ -1333,15 +1308,8 @@ add_firewall_rule() {
if [ -n "$NODE" ] && ([ -n "${LOCALHOST_TCP_PROXY_MODE}" ] || [ -n "${LOCALHOST_UDP_PROXY_MODE}" ]); then
[ -n "$DNS_REDIRECT_PORT" ] && {
if [ "$PROXY_IPV6" == "1" ]; then
#nft "add rule $NFTABLE_NAME PSW_OUTPUT_MANGLE_V6 meta l4proto udp udp dport 53 counter accept"
#nft "add rule $NFTABLE_NAME PSW_OUTPUT_MANGLE_V6 meta l4proto tcp tcp dport 53 counter accept"
nft "add rule $NFTABLE_NAME nat_output oif lo meta l4proto udp udp dport 53 counter redirect to :$DNS_REDIRECT_PORT comment \"PSW_DNS\""
nft "add rule $NFTABLE_NAME nat_output oif lo meta l4proto tcp tcp dport 53 counter redirect to :$DNS_REDIRECT_PORT comment \"PSW_DNS\""
else
nft "add rule $NFTABLE_NAME nat_output oif lo ip protocol udp udp dport 53 counter redirect to :$DNS_REDIRECT_PORT comment \"PSW_DNS\""
nft "add rule $NFTABLE_NAME nat_output oif lo ip protocol tcp tcp dport 53 counter redirect to :$DNS_REDIRECT_PORT comment \"PSW_DNS\""
fi
nft "add rule $NFTABLE_NAME nat_output meta l4proto udp oif lo udp dport 53 counter redirect to :$DNS_REDIRECT_PORT comment \"PSW_DNS\""
nft "add rule $NFTABLE_NAME nat_output meta l4proto tcp oif lo tcp dport 53 counter redirect to :$DNS_REDIRECT_PORT comment \"PSW_DNS\""
}
fi
+1 -1
View File
@@ -7,7 +7,7 @@ include $(TOPDIR)/rules.mk
PKG_NAME:=luci-app-passwall2
PKG_VERSION:=26.9.12
PKG_RELEASE:=122
PKG_RELEASE:=123
PKG_PO_VERSION:=$(PKG_VERSION)
PKG_CONFIG_DEPENDS:= \
@@ -14,7 +14,10 @@ local k, v
for k, v in pairs(com) do
o = s:option(Value, k:gsub("%-","_") .. "_file", translatef("%s App Path", v.name))
o.default = v.default_path or ("/usr/bin/" .. k)
o.rmempty = false
o.placeholder = o.default
function o:remove(section)
self:write(section, self.default)
end
end
o = s:option(DummyValue, "tips", " ")
+1 -1
View File
@@ -4,7 +4,7 @@ LUCI_TITLE:=luci-app-ssr-plus
LUCI_PKGARCH:=all
PKG_NAME:=luci-app-ssr-plus
PKG_VERSION:=196
PKG_RELEASE:=72
PKG_RELEASE:=73
PKG_CONFIG_DEPENDS:= \
CONFIG_PACKAGE_$(PKG_NAME)_Iptables_Transparent_Proxy \
@@ -696,6 +696,12 @@ local function build_dns_section(dns_mode, user_dns)
if not result["default-nameserver"] then
result["default-nameserver"] = get_fastest_dns()
end
if not result["direct-nameserver"] then
result["direct-nameserver"] = get_fastest_dns()
end
if result["direct-nameserver-follow-policy"] == nil then
result["direct-nameserver-follow-policy"] = false
end
if result["respect-rules"] == nil then
result["respect-rules"] = true
end
@@ -740,6 +746,8 @@ local function build_dns_section(dns_mode, user_dns)
result["respect-rules"] = nil
result["fallback-filter"] = nil
result["nameserver-policy"] = nil
result["direct-nameserver"] = nil
result["direct-nameserver-follow-policy"] = nil
end
local upstreams = build_dns_upstreams()
+1 -1
View File
@@ -9,7 +9,7 @@ include $(TOPDIR)/rules.mk
LUCI_TITLE:=LuCI Status Pages
LUCI_DEPENDS:=+luci-base +luci-app-oui +libiwinfo +rpcd-mod-iwinfo +rpcd-mod-rrdns +ucode +ucode-mod-fs +ucode-mod-ubus +ucode-mod-socket
PKG_RELEASE:=10
PKG_RELEASE:=11
PKG_BUILD_DEPENDS:=iwinfo
PKG_LICENSE:=Apache-2.0
@@ -88,11 +88,6 @@ return baseclass.extend({
_('Architecture'), (cpuinfo.cpuinfo || boardinfo.system) + ' ' + cpubench.cpubench,
_('Target Platform'), (L.isObject(boardinfo.release) ? boardinfo.release.target : ''),
_('Firmware Version'), (L.isObject(boardinfo.release) ? boardinfo.release.description + ' / ' : '') + (luciversion || ''),
? '%s%s / '.format(
boardinfo.release.description || '',
boardinfo.release.revision ? boardinfo.release.revision : ''
)
: '') + (luciversion || ''),
_('Kernel Version'), boardinfo.kernel,
_('Local Time'), datestr,
_('Uptime'), systeminfo.uptime ? '%t'.format(systeminfo.uptime) : null,