mirror of
https://dev.iopsys.eu/feed/iopsys.git
synced 2025-12-10 07:44:50 +01:00
Compare commits
16 commits
5d91a8a154
...
a3dbf63810
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a3dbf63810 | ||
|
|
9101095a0a | ||
|
|
2bd4c0c236 | ||
|
|
61bda623ca | ||
|
|
e2eaf6221a | ||
|
|
82183e9e3b | ||
|
|
edfbcb1074 | ||
|
|
5af1df3493 | ||
|
|
3ec6c21456 | ||
|
|
9d251b5d9d | ||
|
|
a3e4a0f6e9 | ||
|
|
d5044df134 | ||
|
|
cef4d4efea | ||
|
|
1f093159d8 | ||
|
|
22e6d80384 | ||
|
|
c8b5878332 |
29 changed files with 970 additions and 263 deletions
|
|
@ -5,13 +5,13 @@
|
||||||
include $(TOPDIR)/rules.mk
|
include $(TOPDIR)/rules.mk
|
||||||
|
|
||||||
PKG_NAME:=bbfdm
|
PKG_NAME:=bbfdm
|
||||||
PKG_VERSION:=1.18.15
|
PKG_VERSION:=1.18.16
|
||||||
|
|
||||||
USE_LOCAL:=0
|
USE_LOCAL:=0
|
||||||
ifneq ($(USE_LOCAL),1)
|
ifneq ($(USE_LOCAL),1)
|
||||||
PKG_SOURCE_PROTO:=git
|
PKG_SOURCE_PROTO:=git
|
||||||
PKG_SOURCE_URL:=https://dev.iopsys.eu/bbf/bbfdm.git
|
PKG_SOURCE_URL:=https://dev.iopsys.eu/bbf/bbfdm.git
|
||||||
PKG_SOURCE_VERSION:=8f72146f0f42b76b43ef545136548dd2ca1b0388
|
PKG_SOURCE_VERSION:=72c3307651cb583121fa5b4abcaad957ddc264bd
|
||||||
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION)-$(PKG_SOURCE_VERSION).tar.gz
|
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION)-$(PKG_SOURCE_VERSION).tar.gz
|
||||||
PKG_MIRROR_HASH:=skip
|
PKG_MIRROR_HASH:=skip
|
||||||
endif
|
endif
|
||||||
|
|
|
||||||
|
|
@ -6,12 +6,12 @@
|
||||||
include $(TOPDIR)/rules.mk
|
include $(TOPDIR)/rules.mk
|
||||||
|
|
||||||
PKG_NAME:=ieee1905
|
PKG_NAME:=ieee1905
|
||||||
PKG_VERSION:=8.7.42
|
PKG_VERSION:=8.7.43
|
||||||
|
|
||||||
LOCAL_DEV=0
|
LOCAL_DEV=0
|
||||||
ifneq ($(LOCAL_DEV),1)
|
ifneq ($(LOCAL_DEV),1)
|
||||||
PKG_SOURCE_PROTO:=git
|
PKG_SOURCE_PROTO:=git
|
||||||
PKG_SOURCE_VERSION:=2e7d1377794b8d4f8aad252265110b09b129fdc8
|
PKG_SOURCE_VERSION:=48f1eb0ffceea5b6cd98846d7f774387f1e57401
|
||||||
PKG_SOURCE_URL:=https://dev.iopsys.eu/multi-ap/ieee1905.git
|
PKG_SOURCE_URL:=https://dev.iopsys.eu/multi-ap/ieee1905.git
|
||||||
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION)_$(PKG_SOURCE_VERSION).tar.xz
|
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION)_$(PKG_SOURCE_VERSION).tar.xz
|
||||||
PKG_MIRROR_HASH:=skip
|
PKG_MIRROR_HASH:=skip
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ PKG_NAME:=iopsys-analytics
|
||||||
PKG_RELEASE:=$(COMMITCOUNT)
|
PKG_RELEASE:=$(COMMITCOUNT)
|
||||||
PKG_LICENSE:=PROPRIETARY
|
PKG_LICENSE:=PROPRIETARY
|
||||||
PKG_SOURCE_PROTO:=git
|
PKG_SOURCE_PROTO:=git
|
||||||
PKG_SOURCE_VERSION:=25e32ac5a860aec6e53e3449565b71595073e014
|
PKG_SOURCE_VERSION:=7c2780b4c24e5a1078c060bf9d3a03365f71f06a
|
||||||
PKG_SOURCE_URL:=https://dev.iopsys.eu/iopsys/iopsys-analytics.git
|
PKG_SOURCE_URL:=https://dev.iopsys.eu/iopsys/iopsys-analytics.git
|
||||||
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION)_$(PKG_SOURCE_VERSION).tar.xz
|
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION)_$(PKG_SOURCE_VERSION).tar.xz
|
||||||
PKG_MIRROR_HASH:=skip
|
PKG_MIRROR_HASH:=skip
|
||||||
|
|
|
||||||
|
|
@ -6,9 +6,9 @@
|
||||||
include $(TOPDIR)/rules.mk
|
include $(TOPDIR)/rules.mk
|
||||||
|
|
||||||
PKG_NAME:=map-agent
|
PKG_NAME:=map-agent
|
||||||
PKG_VERSION:=6.5.0.7
|
PKG_VERSION:=6.5.0.8
|
||||||
PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION)
|
PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION)
|
||||||
PKG_SOURCE_VERSION:=189c1d101ed4be399ebca6cad2c95808f6a7ffde
|
PKG_SOURCE_VERSION:=725909127f3ba4be38ae6e8f13b70260062737a6
|
||||||
PKG_MAINTAINER:=Jakob Olsson <jakob.olsson@iopsys.eu>
|
PKG_MAINTAINER:=Jakob Olsson <jakob.olsson@iopsys.eu>
|
||||||
|
|
||||||
PKG_LICENSE:=BSD-3-Clause
|
PKG_LICENSE:=BSD-3-Clause
|
||||||
|
|
|
||||||
|
|
@ -6,9 +6,9 @@
|
||||||
include $(TOPDIR)/rules.mk
|
include $(TOPDIR)/rules.mk
|
||||||
|
|
||||||
PKG_NAME:=map-controller
|
PKG_NAME:=map-controller
|
||||||
PKG_VERSION:=6.4.4.13
|
PKG_VERSION:=6.4.4.14
|
||||||
PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION)
|
PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION)
|
||||||
PKG_SOURCE_VERSION:=bd0fb2b63830e19038d9495517c03fdc3900cdfa
|
PKG_SOURCE_VERSION:=abd127215616717506fb03c94ca629f22768ff4f
|
||||||
PKG_MAINTAINER:=Jakob Olsson <jakob.olsson@genexis.eu>
|
PKG_MAINTAINER:=Jakob Olsson <jakob.olsson@genexis.eu>
|
||||||
|
|
||||||
LOCAL_DEV=0
|
LOCAL_DEV=0
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,66 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
. /lib/functions.sh
|
||||||
|
|
||||||
|
cfg="mapcontroller"
|
||||||
|
config_load "$cfg"
|
||||||
|
|
||||||
|
used_ids=""
|
||||||
|
|
||||||
|
collect_used_ids() {
|
||||||
|
local section="$1"
|
||||||
|
local id
|
||||||
|
|
||||||
|
id=$(uci -q get ${cfg}.${section}.id)
|
||||||
|
if [ -n "$id" ] && printf "%s" "$id" | grep -qE '^[0-9]+$'; then
|
||||||
|
used_ids="$used_ids $id"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Find first available ID from 0 to INT32_MAX
|
||||||
|
find_first_available_id() {
|
||||||
|
local max_int=2147483647
|
||||||
|
local expected=0
|
||||||
|
local id
|
||||||
|
|
||||||
|
# Convert list to sorted unique list
|
||||||
|
sorted_ids=$(printf "%s\n" $used_ids | sort -n | uniq)
|
||||||
|
|
||||||
|
for id in $sorted_ids; do
|
||||||
|
if [ "$id" -eq "$expected" ]; then
|
||||||
|
expected=$((expected + 1))
|
||||||
|
elif [ "$id" -gt "$expected" ]; then
|
||||||
|
# Found a gap -> return the gap
|
||||||
|
echo "$expected"
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# If no gaps, next available is `expected`
|
||||||
|
if [ "$expected" -le "$max_int" ]; then
|
||||||
|
echo "$expected"
|
||||||
|
else
|
||||||
|
echo -1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Assign ID if missing
|
||||||
|
add_qos_rule_id() {
|
||||||
|
local section="$1"
|
||||||
|
local id
|
||||||
|
|
||||||
|
id=$(uci -q get ${cfg}.${section}.id)
|
||||||
|
if [ -z "$id" ]; then
|
||||||
|
new_id=$(find_first_available_id)
|
||||||
|
[ "$new_id" -ge 0 ] || return # No available ID
|
||||||
|
uci -q set ${cfg}.${section}.id="$new_id"
|
||||||
|
|
||||||
|
used_ids="$used_ids $new_id"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Step 1: Collect all existing IDs
|
||||||
|
config_foreach collect_used_ids qos_rule
|
||||||
|
|
||||||
|
# Step 2: Assign IDs to rules missing them
|
||||||
|
config_foreach add_qos_rule_id qos_rule
|
||||||
|
|
@ -14,5 +14,3 @@ for sec in $sections; do
|
||||||
|
|
||||||
uci rename $cfg.$s=$sec
|
uci rename $cfg.$s=$sec
|
||||||
done
|
done
|
||||||
|
|
||||||
uci commit $cfg
|
|
||||||
|
|
|
||||||
|
|
@ -5,13 +5,13 @@
|
||||||
include $(TOPDIR)/rules.mk
|
include $(TOPDIR)/rules.mk
|
||||||
|
|
||||||
PKG_NAME:=parental-control
|
PKG_NAME:=parental-control
|
||||||
PKG_VERSION:=1.4.4
|
PKG_VERSION:=1.4.6
|
||||||
|
|
||||||
LOCAL_DEV:=0
|
LOCAL_DEV:=0
|
||||||
ifneq ($(LOCAL_DEV),1)
|
ifneq ($(LOCAL_DEV),1)
|
||||||
PKG_SOURCE_PROTO:=git
|
PKG_SOURCE_PROTO:=git
|
||||||
PKG_SOURCE_URL:=https://dev.iopsys.eu/network/parental-control.git
|
PKG_SOURCE_URL:=https://dev.iopsys.eu/network/parental-control.git
|
||||||
PKG_SOURCE_VERSION:=d0eabdda9790d1df3cec30589c97214731108367
|
PKG_SOURCE_VERSION:=11777ff069888fc543c2501110313b654bbbfbc9
|
||||||
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION)-$(PKG_SOURCE_VERSION).tar.gz
|
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION)-$(PKG_SOURCE_VERSION).tar.gz
|
||||||
PKG_MIRROR_HASH:=skip
|
PKG_MIRROR_HASH:=skip
|
||||||
endif
|
endif
|
||||||
|
|
@ -27,7 +27,7 @@ define Package/parental-control
|
||||||
CATEGORY:=Utilities
|
CATEGORY:=Utilities
|
||||||
TITLE:=URL filter
|
TITLE:=URL filter
|
||||||
DEPENDS:=+libuci +libnetfilter-queue +libnfnetlink +iptables-mod-nfqueue +libpthread
|
DEPENDS:=+libuci +libnetfilter-queue +libnfnetlink +iptables-mod-nfqueue +libpthread
|
||||||
DEPENDS+=+libubox +ubus +conntrack +libcurl +cmph
|
DEPENDS+=+libubox +ubus +conntrack +libcurl +cmph +libjson-c
|
||||||
DEPENDS+=+libbbfdm-api +libbbfdm-ubus +dm-service
|
DEPENDS+=+libbbfdm-api +libbbfdm-ubus +dm-service
|
||||||
endef
|
endef
|
||||||
|
|
||||||
|
|
@ -87,11 +87,10 @@ define Package/parental-control/install
|
||||||
|
|
||||||
$(INSTALL_DATA) ./files/etc/uci-defaults/40-parental_control_update_bundle_path $(1)/etc/uci-defaults/
|
$(INSTALL_DATA) ./files/etc/uci-defaults/40-parental_control_update_bundle_path $(1)/etc/uci-defaults/
|
||||||
ifeq ($(CONFIG_PARENTAL_CONTROL_URLFILTERING),y)
|
ifeq ($(CONFIG_PARENTAL_CONTROL_URLFILTERING),y)
|
||||||
$(INSTALL_DATA) ./files/etc/uci-defaults/50-parental_control_add_bundles $(1)/etc/uci-defaults/
|
$(INSTALL_DATA) ./files/etc/parentalcontrol/url_bundles.json $(1)/etc/parentalcontrol/
|
||||||
$(CP) ./files/urlbundle_override.json $(1)/etc/parentalcontrol/
|
$(INSTALL_DATA) ./files/etc/parentalcontrol/urlbundle_override.json $(1)/etc/parentalcontrol/
|
||||||
else
|
else
|
||||||
$(BBFDM_INSTALL_MS_PLUGIN) -v ${VENDOR_PREFIX} ./files/urlbundle_override.json $(1) parentalcontrol
|
$(BBFDM_INSTALL_MS_PLUGIN) -v ${VENDOR_PREFIX} ./files/urlbundle_override.json $(1) parentalcontrol
|
||||||
$(INSTALL_DATA) ./files/etc/uci-defaults/50-parental_control_disable_urlfilter $(1)/etc/uci-defaults/
|
|
||||||
endif
|
endif
|
||||||
endef
|
endef
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
config globals 'globals'
|
config globals 'globals'
|
||||||
option enable '1'
|
option enable '1'
|
||||||
option loglevel '3'
|
option loglevel '3'
|
||||||
|
option urlfilter '0'
|
||||||
|
|
|
||||||
76
parental-control/files/etc/parentalcontrol/url_bundles.json
Normal file
76
parental-control/files/etc/parentalcontrol/url_bundles.json
Normal file
|
|
@ -0,0 +1,76 @@
|
||||||
|
{
|
||||||
|
"urlBundles": [
|
||||||
|
{
|
||||||
|
"url": "https://blocklistproject.github.io/Lists/alt-version/abuse-nl.txt",
|
||||||
|
"name": "Abuse"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://blocklistproject.github.io/Lists/alt-version/ads-nl.txt",
|
||||||
|
"name": "Ads"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://blocklistproject.github.io/Lists/alt-version/crypto-nl.txt",
|
||||||
|
"name": "Crypto"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://blocklistproject.github.io/Lists/alt-version/drugs-nl.txt",
|
||||||
|
"name": "Drugs"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://blocklistproject.github.io/Lists/alt-version/everything-nl.txt",
|
||||||
|
"name": "Everything else"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://blocklistproject.github.io/Lists/alt-version/facebook-nl.txt",
|
||||||
|
"name": "Facebook/Instagram"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://blocklistproject.github.io/Lists/alt-version/fraud-nl.txt",
|
||||||
|
"name": "Fraud"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://blocklistproject.github.io/Lists/alt-version/gambling-nl.txt",
|
||||||
|
"name": "Gambling"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://blocklistproject.github.io/Lists/alt-version/malware-nl.txt",
|
||||||
|
"name": "Malware"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://blocklistproject.github.io/Lists/alt-version/phishing-nl.txt",
|
||||||
|
"name": "Phishing"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://blocklistproject.github.io/Lists/alt-version/piracy-nl.txt",
|
||||||
|
"name": "Piracy"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://blocklistproject.github.io/Lists/alt-version/porn-nl.txt",
|
||||||
|
"name": "Porn"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://blocklistproject.github.io/Lists/alt-version/ransomware-nl.txt",
|
||||||
|
"name": "Ransomware"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://blocklistproject.github.io/Lists/alt-version/redirect-nl.txt",
|
||||||
|
"name": "Redirect"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://blocklistproject.github.io/Lists/alt-version/scam-nl.txt",
|
||||||
|
"name": "Scam"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://blocklistproject.github.io/Lists/alt-version/tiktok-nl.txt",
|
||||||
|
"name": "TikTok"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://blocklistproject.github.io/Lists/alt-version/torrent-nl.txt",
|
||||||
|
"name": "Torrent"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://blocklistproject.github.io/Lists/alt-version/tracking-nl.txt",
|
||||||
|
"name": "Tracking"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
@ -25,14 +25,6 @@ check_mounted_app_partition() {
|
||||||
|
|
||||||
if check_mounted_app_partition; then
|
if check_mounted_app_partition; then
|
||||||
uci -q set parentalcontrol.globals.bundle_path="${APPS_DIR}/parentalcontrol"
|
uci -q set parentalcontrol.globals.bundle_path="${APPS_DIR}/parentalcontrol"
|
||||||
|
|
||||||
# configure the urlfilter if not configured
|
|
||||||
urlfilter="$(uci -q get parentalcontrol.globals.urlfilter)"
|
|
||||||
if [ -z "${urlfilter}" ]; then
|
|
||||||
uci -q set parentalcontrol.globals.urlfilter='1'
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
uci -q set parentalcontrol.globals.urlfilter='0'
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
exit 0
|
exit 0
|
||||||
|
|
|
||||||
|
|
@ -1,43 +0,0 @@
|
||||||
#!/bin/sh
|
|
||||||
|
|
||||||
[ ! -f "/etc/config/parentalcontrol" ] && exit 0
|
|
||||||
|
|
||||||
COUNT=1
|
|
||||||
|
|
||||||
add_urlbundle()
|
|
||||||
{
|
|
||||||
local name url
|
|
||||||
|
|
||||||
url="${1}"; shift
|
|
||||||
name="$*"
|
|
||||||
|
|
||||||
uci -q set parentalcontrol.urlbundle_${COUNT}=urlbundle
|
|
||||||
uci -q set parentalcontrol.urlbundle_${COUNT}.name="${name}"
|
|
||||||
uci -q set parentalcontrol.urlbundle_${COUNT}.download_url="${url}"
|
|
||||||
|
|
||||||
COUNT="$((COUNT+1))"
|
|
||||||
}
|
|
||||||
|
|
||||||
urlfilter="$(uci -q get parentalcontrol.globals.urlfilter)"
|
|
||||||
if [ "${urlfilter}" -eq "1" ]; then
|
|
||||||
add_urlbundle "https://blocklistproject.github.io/Lists/alt-version/abuse-nl.txt" "Abuse"
|
|
||||||
add_urlbundle "https://blocklistproject.github.io/Lists/alt-version/ads-nl.txt" "Ads"
|
|
||||||
add_urlbundle "https://blocklistproject.github.io/Lists/alt-version/crypto-nl.txt" "Crypto"
|
|
||||||
add_urlbundle "https://blocklistproject.github.io/Lists/alt-version/drugs-nl.txt" "Drugs"
|
|
||||||
add_urlbundle 'https://blocklistproject.github.io/Lists/alt-version/everything-nl.txt' "Everything else"
|
|
||||||
add_urlbundle 'https://blocklistproject.github.io/Lists/alt-version/facebook-nl.txt' 'Facebook/Instagram'
|
|
||||||
add_urlbundle 'https://blocklistproject.github.io/Lists/alt-version/fraud-nl.txt' 'Fraud'
|
|
||||||
add_urlbundle 'https://blocklistproject.github.io/Lists/alt-version/gambling-nl.txt' 'Gambling'
|
|
||||||
add_urlbundle 'https://blocklistproject.github.io/Lists/alt-version/malware-nl.txt' 'Malware'
|
|
||||||
add_urlbundle 'https://blocklistproject.github.io/Lists/alt-version/phishing-nl.txt' 'Phishing'
|
|
||||||
add_urlbundle 'https://blocklistproject.github.io/Lists/alt-version/piracy-nl.txt' 'Piracy'
|
|
||||||
add_urlbundle 'https://blocklistproject.github.io/Lists/alt-version/porn-nl.txt' 'Porn'
|
|
||||||
add_urlbundle 'https://blocklistproject.github.io/Lists/alt-version/ransomware-nl.txt' 'Ransomware'
|
|
||||||
add_urlbundle 'https://blocklistproject.github.io/Lists/alt-version/redirect-nl.txt' 'Redirect'
|
|
||||||
add_urlbundle 'https://blocklistproject.github.io/Lists/alt-version/scam-nl.txt' 'Scam'
|
|
||||||
add_urlbundle 'https://blocklistproject.github.io/Lists/alt-version/tiktok-nl.txt' 'TikTok'
|
|
||||||
add_urlbundle 'https://blocklistproject.github.io/Lists/alt-version/torrent-nl.txt' 'Torrent'
|
|
||||||
add_urlbundle 'https://blocklistproject.github.io/Lists/alt-version/tracking-nl.txt' 'Tracking'
|
|
||||||
fi
|
|
||||||
|
|
||||||
exit 0
|
|
||||||
|
|
@ -1,14 +0,0 @@
|
||||||
#!/bin/sh
|
|
||||||
|
|
||||||
. /lib/functions.sh
|
|
||||||
|
|
||||||
[ ! -f "/etc/config/parentalcontrol" ] && exit 0
|
|
||||||
|
|
||||||
uci -q set parentalcontrol.globals.urlfilter='0'
|
|
||||||
|
|
||||||
_delete_urlbundle() {
|
|
||||||
uci_remove parentalcontrol "${1}"
|
|
||||||
}
|
|
||||||
|
|
||||||
config_load "parentalcontrol"
|
|
||||||
config_foreach _delete_urlbundle urlbundle
|
|
||||||
|
|
@ -1,10 +1,12 @@
|
||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
|
||||||
. /lib/functions.sh
|
. /lib/functions.sh
|
||||||
|
. /usr/share/libubox/jshn.sh
|
||||||
|
|
||||||
LOCKFILE="/tmp/sync_bundles.lock"
|
LOCKFILE="/tmp/sync_bundles.lock"
|
||||||
log_level="$(uci -q get parentalcontrol.globals.loglevel)"
|
log_level="$(uci -q get parentalcontrol.globals.loglevel)"
|
||||||
log_level="${log_level:-1}"
|
log_level="${log_level:-1}"
|
||||||
|
URLBUNDLE_JSON="/etc/parentalcontrol/url_bundles.json"
|
||||||
DEBUG=0
|
DEBUG=0
|
||||||
|
|
||||||
log_err() {
|
log_err() {
|
||||||
|
|
@ -85,6 +87,7 @@ update_bundle_file_from_url() {
|
||||||
local success=0
|
local success=0
|
||||||
while [ $attempt -le 3 ]; do
|
while [ $attempt -le 3 ]; do
|
||||||
if curl -s -o "$temp_file" "$download_url"; then
|
if curl -s -o "$temp_file" "$download_url"; then
|
||||||
|
log_info "Download successful for $download_url"
|
||||||
success=1
|
success=1
|
||||||
break
|
break
|
||||||
else
|
else
|
||||||
|
|
@ -218,24 +221,33 @@ cleanup_bundle_files() {
|
||||||
# Collect all download_url entries using config_foreach
|
# Collect all download_url entries using config_foreach
|
||||||
local urls=""
|
local urls=""
|
||||||
get_download_url() {
|
get_download_url() {
|
||||||
local section="$1"
|
local enable url
|
||||||
config_get url "$section" download_url
|
|
||||||
config_get_bool enable "$1" enable 1
|
json_select "${2}"
|
||||||
|
|
||||||
|
json_get_var url url
|
||||||
|
json_get_var enable enable
|
||||||
|
enable="${enable:-1}"
|
||||||
|
|
||||||
if [ "${enable}" -eq 0 ]; then
|
if [ "${enable}" -eq 0 ]; then
|
||||||
# bundle is disabled
|
log_info "get_download_url: Skipping bundle ${name} not enabled"
|
||||||
|
json_select ..
|
||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
url="${url#file://}"
|
url="${url#file://}"
|
||||||
url="${url#https://}"
|
url="${url#https://}"
|
||||||
url="${url#http://}"
|
url="${url#http://}"
|
||||||
|
|
||||||
url="${url##*/}" # Get everything after the last '/'
|
url="${url##*/}" # Get everything after the last '/'
|
||||||
urls="$urls $url"
|
urls="$urls $url"
|
||||||
|
json_select ..
|
||||||
}
|
}
|
||||||
|
|
||||||
config_load parentalcontrol
|
json_init
|
||||||
config_foreach get_download_url urlbundle
|
json_load_file "${URLBUNDLE_JSON}"
|
||||||
|
|
||||||
|
json_for_each_item get_download_url "urlBundles"
|
||||||
|
|
||||||
# Loop through all files in the directory
|
# Loop through all files in the directory
|
||||||
for file in "$dir"/*; do
|
for file in "$dir"/*; do
|
||||||
|
|
@ -294,30 +306,29 @@ handle_filter_for_bundles() {
|
||||||
fi
|
fi
|
||||||
|
|
||||||
check_bundle_exists() {
|
check_bundle_exists() {
|
||||||
local enable download_url name cfg
|
local enable url name
|
||||||
|
|
||||||
cfg="$1"
|
json_select "${2}"
|
||||||
config_get name "$cfg" name
|
|
||||||
config_get_bool enable "$cfg" enable 1
|
json_get_var name name
|
||||||
config_get download_url "$cfg" download_url
|
json_get_var url url
|
||||||
|
json_get_var enable enable
|
||||||
|
enable="${enable:-1}"
|
||||||
|
|
||||||
if [ "${enable}" -eq 0 ]; then
|
if [ "${enable}" -eq 0 ]; then
|
||||||
log_info "Skipping bundle ${name} not enabled"
|
log_info "check_bundle_exists: Skipping bundle ${name} not enabled"
|
||||||
|
json_select ..
|
||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
handle_download_url "$download_url" "$name"
|
handle_download_url "${url}" "${name}"
|
||||||
local exit_status=$?
|
json_select ..
|
||||||
if [ "$exit_status" -eq 1 ]; then
|
|
||||||
uci -q set "parentalcontrol.${cfg}.status"="Error"
|
|
||||||
else
|
|
||||||
uci -q set "parentalcontrol.${cfg}.status"=""
|
|
||||||
fi
|
|
||||||
|
|
||||||
uci commit parentalcontrol
|
|
||||||
}
|
}
|
||||||
|
|
||||||
config_foreach check_bundle_exists urlbundle
|
json_init
|
||||||
|
json_load_file "${URLBUNDLE_JSON}"
|
||||||
|
|
||||||
|
json_for_each_item check_bundle_exists "urlBundles"
|
||||||
}
|
}
|
||||||
|
|
||||||
# Open file descriptor 200 for locking
|
# Open file descriptor 200 for locking
|
||||||
|
|
|
||||||
|
|
@ -28,4 +28,15 @@ config SSHMNGR_SFTP
|
||||||
default y
|
default y
|
||||||
help
|
help
|
||||||
Enable this option to support the SFTP protocol.
|
Enable this option to support the SFTP protocol.
|
||||||
|
|
||||||
|
config SSHMNGR_SECURITY_MFA
|
||||||
|
bool "MFA using PAM and Google authenticator"
|
||||||
|
depends on SSHMNGR_BACKEND_OPENSSH_PAM
|
||||||
|
default n
|
||||||
|
help
|
||||||
|
Enable this option to use MFA with PAM based Google authenticator.
|
||||||
|
|
||||||
|
config SSHMNGR_VENDOR_PREFIX
|
||||||
|
string "Package specific datamodel Vendor Prefix for TR181 extensions"
|
||||||
|
default ""
|
||||||
endif
|
endif
|
||||||
|
|
|
||||||
|
|
@ -34,6 +34,7 @@ define Package/sshmngr
|
||||||
DEPENDS+=+SSHMNGR_BACKEND_OPENSSH_PAM:openssh-server-pam +SSHMNGR_BACKEND_OPENSSH_PAM:openssh-client-utils
|
DEPENDS+=+SSHMNGR_BACKEND_OPENSSH_PAM:openssh-server-pam +SSHMNGR_BACKEND_OPENSSH_PAM:openssh-client-utils
|
||||||
DEPENDS+=+SSHMNGR_BACKEND_DROPBEAR:dropbear
|
DEPENDS+=+SSHMNGR_BACKEND_DROPBEAR:dropbear
|
||||||
DEPENDS+=+SSHMNGR_SFTP:openssh-sftp-server
|
DEPENDS+=+SSHMNGR_SFTP:openssh-sftp-server
|
||||||
|
DEPENDS+=+SSHMNGR_SECURITY_MFA:google-authenticator-libpam
|
||||||
endef
|
endef
|
||||||
|
|
||||||
define Package/sshmngr/description
|
define Package/sshmngr/description
|
||||||
|
|
@ -44,6 +45,13 @@ define Package/$(PKG_NAME)/config
|
||||||
source "$(SOURCE)/Config.in"
|
source "$(SOURCE)/Config.in"
|
||||||
endef
|
endef
|
||||||
|
|
||||||
|
ifeq ($(CONFIG_SSHMNGR_VENDOR_PREFIX),"")
|
||||||
|
VENDOR_PREFIX = $(CONFIG_BBF_VENDOR_PREFIX)
|
||||||
|
else
|
||||||
|
VENDOR_PREFIX = $(CONFIG_SSHMNGR_VENDOR_PREFIX)
|
||||||
|
endif
|
||||||
|
|
||||||
|
|
||||||
ifeq ($(LOCAL_DEV),1)
|
ifeq ($(LOCAL_DEV),1)
|
||||||
define Build/Prepare
|
define Build/Prepare
|
||||||
$(CP) -rf ./sshmngr/* $(PKG_BUILD_DIR)/
|
$(CP) -rf ./sshmngr/* $(PKG_BUILD_DIR)/
|
||||||
|
|
@ -67,6 +75,16 @@ endif
|
||||||
$(BBFDM_REGISTER_SERVICES) ./bbfdm_service.json $(1) $(PKG_NAME)
|
$(BBFDM_REGISTER_SERVICES) ./bbfdm_service.json $(1) $(PKG_NAME)
|
||||||
$(BBFDM_INSTALL_MS_DM) $(PKG_BUILD_DIR)/src/libsshmngr.so $(1) $(PKG_NAME)
|
$(BBFDM_INSTALL_MS_DM) $(PKG_BUILD_DIR)/src/libsshmngr.so $(1) $(PKG_NAME)
|
||||||
|
|
||||||
|
ifeq ($(CONFIG_SSHMNGR_BACKEND_OPENSSH_PAM),y)
|
||||||
|
$(INSTALL_DIR) $(1)/etc/uci-defaults
|
||||||
|
$(INSTALL_DATA) ./files/openssh_backend/lib/sshmngr/pam_config.sh $(1)/lib/sshmngr/
|
||||||
|
$(INSTALL_BIN) ./files/openssh_backend/etc/uci-defaults/91-set-sshd-pam $(1)/etc/uci-defaults/
|
||||||
|
ifeq ($(CONFIG_SSHMNGR_SECURITY_MFA),y)
|
||||||
|
$(INSTALL_BIN) ./files/openssh_backend/etc/uci-defaults/92-set-ssh-mfa $(1)/etc/uci-defaults/
|
||||||
|
$(BBFDM_INSTALL_MS_PLUGIN) -v ${VENDOR_PREFIX} ./files/openssh_backend/ssh_mfa_override.json $(1) $(PKG_NAME)
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
ifeq ($(CONFIG_PACKAGE_fail2ban),y)
|
ifeq ($(CONFIG_PACKAGE_fail2ban),y)
|
||||||
$(INSTALL_DIR) $(1)/etc/fail2ban/jail.d
|
$(INSTALL_DIR) $(1)/etc/fail2ban/jail.d
|
||||||
$(INSTALL_DIR) $(1)/etc/fail2ban/filter.d/
|
$(INSTALL_DIR) $(1)/etc/fail2ban/filter.d/
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,8 @@
|
||||||
. /usr/share/libubox/jshn.sh
|
. /usr/share/libubox/jshn.sh
|
||||||
. /lib/sshmngr/backend.sh
|
. /lib/sshmngr/backend.sh
|
||||||
|
|
||||||
|
MFA_SECRET_FILE="/etc/security/mfa_secret"
|
||||||
|
|
||||||
add_server_name()
|
add_server_name()
|
||||||
{
|
{
|
||||||
local server_sec="${1}"
|
local server_sec="${1}"
|
||||||
|
|
@ -44,7 +46,7 @@ get_pid()
|
||||||
|
|
||||||
case "$1" in
|
case "$1" in
|
||||||
list)
|
list)
|
||||||
echo '{ "dump" : {"server_name":"string"}, "kill_session" : {"session_pid":"string","server_name":"string"}, "list_keys" : {}, "add_pubkey" : {"current_key":"string","new_key":"string"}, "remove_pubkey" : {"key":"string"} }'
|
echo '{ "dump" : {"server_name":"string"}, "kill_session" : {"session_pid":"string","server_name":"string"}, "list_keys" : {}, "add_pubkey" : {"current_key":"string","new_key":"string"}, "remove_pubkey" : {"key":"string"}, "get_mfa_key" : {}, "get_mfa_recovery" : {} }'
|
||||||
;;
|
;;
|
||||||
call)
|
call)
|
||||||
case "$2" in
|
case "$2" in
|
||||||
|
|
@ -221,6 +223,31 @@ case "$1" in
|
||||||
fi
|
fi
|
||||||
echo '{}'
|
echo '{}'
|
||||||
;;
|
;;
|
||||||
|
|
||||||
|
get_mfa_key)
|
||||||
|
mfa_key=""
|
||||||
|
if [ -f "${MFA_SECRET_FILE}" ]; then
|
||||||
|
mfa_key="$(head -n 1 "$MFA_SECRET_FILE" 2>/dev/null)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
json_init
|
||||||
|
json_add_string "mfa_key" "${mfa_key}"
|
||||||
|
json_dump
|
||||||
|
;;
|
||||||
|
|
||||||
|
get_mfa_recovery)
|
||||||
|
mfa_recovery_codes=""
|
||||||
|
|
||||||
|
if [ -f "${MFA_SECRET_FILE}" ]; then
|
||||||
|
mfa_recovery_codes="$(tail -n 3 "$MFA_SECRET_FILE" 2>/dev/null | tr '\n' ',')"
|
||||||
|
# remove trailing comma
|
||||||
|
mfa_recovery_codes="${mfa_recovery_codes%,}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
json_init
|
||||||
|
json_add_string "recovery_codes" "${mfa_recovery_codes}"
|
||||||
|
json_dump
|
||||||
|
;;
|
||||||
esac
|
esac
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,36 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
# create or over-write our desired file
|
||||||
|
# /etc/pam.d/sshd
|
||||||
|
cat << 'EOF' > /etc/pam.d/sshd
|
||||||
|
auth required pam_env.so
|
||||||
|
auth include sshd-auth
|
||||||
|
account required pam_nologin.so
|
||||||
|
account include sshd-account
|
||||||
|
session include common-session
|
||||||
|
session required pam_limits.so
|
||||||
|
password include sshd-password
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# /etc/pam.d/sshd-auth
|
||||||
|
cat << 'EOF' > /etc/pam.d/sshd-auth
|
||||||
|
auth [success=1 default=ignore] pam_unix.so nullok_secure
|
||||||
|
auth requisite pam_deny.so
|
||||||
|
auth required pam_permit.so
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# /etc/pam.d/sshd-password
|
||||||
|
cat << 'EOF' > /etc/pam.d/sshd-password
|
||||||
|
password [success=1 default=ignore] pam_unix.so sha512
|
||||||
|
password requisite pam_deny.so
|
||||||
|
password required pam_permit.so
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# /etc/pam.d/sshd-account
|
||||||
|
cat << 'EOF' > /etc/pam.d/sshd-account
|
||||||
|
account [success=1 new_authtok_reqd=done default=ignore] pam_unix.so
|
||||||
|
account requisite pam_deny.so
|
||||||
|
account required pam_permit.so
|
||||||
|
EOF
|
||||||
|
|
||||||
|
exit 0
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
if [ -f /etc/config/sshd ]; then
|
||||||
|
# make sure not to change already existing setting
|
||||||
|
if ! uci -q get sshd.@sshd[0].UseMFA 2>&1 > /dev/null; then
|
||||||
|
uci -q set sshd.@sshd[0].UseMFA=1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
exit 0
|
||||||
228
sshmngr/files/openssh_backend/lib/sshmngr/pam_config.sh
Executable file
228
sshmngr/files/openssh_backend/lib/sshmngr/pam_config.sh
Executable file
|
|
@ -0,0 +1,228 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
# List of required .so files
|
||||||
|
REQUIRED_MODULES="
|
||||||
|
/usr/lib/security/pam_faildelay.so
|
||||||
|
/usr/lib/security/pam_faillock.so
|
||||||
|
/usr/lib/security/pam_unix.so
|
||||||
|
/usr/lib/security/pam_deny.so
|
||||||
|
/usr/lib/security/pam_permit.so
|
||||||
|
/usr/lib/security/pam_passwdqc.so
|
||||||
|
"
|
||||||
|
|
||||||
|
MFA_APP="google-authenticator"
|
||||||
|
MFA_LIB="/usr/lib/security/pam_google_authenticator.so"
|
||||||
|
MFA_DIR="/etc/security"
|
||||||
|
MFA_SECRET_FILE="${MFA_DIR}/mfa_secret"
|
||||||
|
MFA_QR_FILE="${MFA_DIR}/mfa_qr"
|
||||||
|
|
||||||
|
log() {
|
||||||
|
echo "$*" | logger -t sshd.init -p info
|
||||||
|
}
|
||||||
|
|
||||||
|
log_err() {
|
||||||
|
echo "$*" | logger -t sshd.init -p err
|
||||||
|
}
|
||||||
|
|
||||||
|
check_required_modules() {
|
||||||
|
for mod in $REQUIRED_MODULES; do
|
||||||
|
if [ ! -f "$mod" ]; then
|
||||||
|
log_err "ERROR: Cannot setup security policy, missing PAM module: $mod"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
write_line() {
|
||||||
|
local filepath="$1"
|
||||||
|
local line="$2"
|
||||||
|
|
||||||
|
echo "$line" >> "$filepath"
|
||||||
|
}
|
||||||
|
|
||||||
|
compare_and_replace() {
|
||||||
|
local src dst
|
||||||
|
src="$1"
|
||||||
|
dst="$2"
|
||||||
|
|
||||||
|
if [ ! -f "$dst" ] || ! cmp -s "$src" "$dst"; then
|
||||||
|
cp "$src" "$dst"
|
||||||
|
log "Updated $dst"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
setup_mfa() {
|
||||||
|
mkdir -p "$MFA_DIR"
|
||||||
|
|
||||||
|
if [ -f "${MFA_SECRET_FILE}" ] && [ -f "${MFA_QR_FILE}" ]; then
|
||||||
|
log "Not updating MFA files, they already exist"
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
touch "$MFA_SECRET_FILE"
|
||||||
|
touch "$MFA_QR_FILE"
|
||||||
|
chmod 600 "$MFA_SECRET_FILE"
|
||||||
|
chmod 600 "$MFA_QR_FILE"
|
||||||
|
|
||||||
|
local cmd="$MFA_APP -f -s $MFA_SECRET_FILE -C -t -d -r 3 -R 30 -w 3 -Q UTF8 -e 3"
|
||||||
|
|
||||||
|
log "Running MFA app: $cmd"
|
||||||
|
# if the google-authenticator senses that the output is not going to a terminal
|
||||||
|
# then it does not print out the QR, so simple redirection does not work
|
||||||
|
# we have to run the command inside a pseudo-terminal using script command
|
||||||
|
# and then redirect that output to a file
|
||||||
|
cmd="script -q -c \"$cmd\" $MFA_QR_FILE > /dev/null"
|
||||||
|
eval "$cmd"
|
||||||
|
}
|
||||||
|
|
||||||
|
update_auth() {
|
||||||
|
# Write /etc/pam.d/sshd-auth
|
||||||
|
local tmp_file pam_file
|
||||||
|
tmp_file="/tmp/sshd-auth"
|
||||||
|
pam_file="/etc/pam.d/sshd-auth"
|
||||||
|
|
||||||
|
local auth_enabled="${1}"
|
||||||
|
local enabled="${2}"
|
||||||
|
local mfa_enabled="${3}"
|
||||||
|
|
||||||
|
local faildelay="$(uci -q get users.authentication_policy.fail_delay || echo 3)"
|
||||||
|
local faillock_lockout_time="$(uci -q get users.authentication_policy.faillock_lockout_time || echo 300)"
|
||||||
|
local faillock_attempts="$(uci -q get users.authentication_policy.faillock_attempts || echo 6)"
|
||||||
|
|
||||||
|
# Convert seconds to microseconds for pam_faildelay
|
||||||
|
local faildelay_usec=$((faildelay * 1000000))
|
||||||
|
|
||||||
|
rm -f "$tmp_file"
|
||||||
|
touch "$tmp_file"
|
||||||
|
|
||||||
|
if [ "${auth_enabled}" -eq 1 ] && [ "${enabled}" -eq 1 ]; then
|
||||||
|
write_line "$tmp_file" "auth optional pam_faildelay.so delay=$faildelay_usec"
|
||||||
|
write_line "$tmp_file" "auth required pam_faillock.so preauth deny=$faillock_attempts even_deny_root unlock_time=$faillock_lockout_time"
|
||||||
|
fi
|
||||||
|
|
||||||
|
write_line "$tmp_file" "auth [success=1 default=bad] pam_unix.so nullok_secure"
|
||||||
|
write_line "$tmp_file" "auth [default=die] pam_faillock.so authfail audit deny=$faillock_attempts even_deny_root unlock_time=$faillock_lockout_time"
|
||||||
|
|
||||||
|
if [ "$mfa_enabled" -eq 1 ]; then
|
||||||
|
write_line "$tmp_file" "auth [success=1 default=bad] pam_google_authenticator.so secret=$MFA_SECRET_FILE"
|
||||||
|
write_line "$tmp_file" "auth [default=die] pam_faillock.so authfail audit deny=$faillock_attempts even_deny_root unlock_time=$faillock_lockout_time"
|
||||||
|
fi
|
||||||
|
|
||||||
|
write_line "$tmp_file" "auth sufficient pam_faillock.so authsucc audit deny=$faillock_attempts even_deny_root unlock_time=$faillock_lockout_time"
|
||||||
|
|
||||||
|
write_line "$tmp_file" "auth requisite pam_deny.so"
|
||||||
|
|
||||||
|
compare_and_replace "$tmp_file" "$pam_file"
|
||||||
|
}
|
||||||
|
|
||||||
|
build_pam_passwdqc_line() {
|
||||||
|
local base="password requisite pam_passwdqc.so"
|
||||||
|
local k v line
|
||||||
|
|
||||||
|
for line in $(uci show users.passwdqc 2>/dev/null); do
|
||||||
|
case "$line" in
|
||||||
|
users.passwdqc=*) continue ;;
|
||||||
|
users.passwdqc.enabled=*) continue ;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
k="${line%%=*}"
|
||||||
|
k="${k#users.passwdqc.}"
|
||||||
|
v="${line#*=}"
|
||||||
|
v="${v%\'}"
|
||||||
|
v="${v#\'}"
|
||||||
|
base="$base $k=$v"
|
||||||
|
done
|
||||||
|
|
||||||
|
base="$base match=0"
|
||||||
|
|
||||||
|
echo "$base"
|
||||||
|
}
|
||||||
|
|
||||||
|
# NOTE:
|
||||||
|
# for some reason setting min 8 makes passwdqc accept minimum 12 letter password with this configuration
|
||||||
|
# if we set it to 12 then we need atleast 16 characters and so on
|
||||||
|
# passphrase = 0 means no space separated words
|
||||||
|
# passphrase = N means the number of words required for a passphrase or 0 to disable the support for user-chosen passphrases.
|
||||||
|
# rest can be figured out from passwdqc man page
|
||||||
|
update_password() {
|
||||||
|
local tmp_file pam_file enabled line
|
||||||
|
tmp_file="/tmp/sshd-password"
|
||||||
|
pam_file="/etc/pam.d/sshd-password"
|
||||||
|
|
||||||
|
local auth_enabled="${1}"
|
||||||
|
|
||||||
|
rm -f "$tmp_file"
|
||||||
|
touch "$tmp_file"
|
||||||
|
|
||||||
|
# Check if section exists
|
||||||
|
if uci -q get users.passwdqc >/dev/null 2>&1; then
|
||||||
|
# if enabled is not present it is assumed to be 0
|
||||||
|
enabled=$(uci -q get users.passwdqc.enabled || echo "0")
|
||||||
|
if [ "${auth_enabled}" -eq 1 ] && [ "${enabled}" -eq 1 ]; then
|
||||||
|
line="$(build_pam_passwdqc_line)"
|
||||||
|
write_line "$tmp_file" "$line"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
write_line "$tmp_file" "password [success=1 default=ignore] pam_unix.so sha512"
|
||||||
|
write_line "$tmp_file" ""
|
||||||
|
write_line "$tmp_file" "password requisite pam_deny.so"
|
||||||
|
write_line "$tmp_file" "password required pam_permit.so"
|
||||||
|
|
||||||
|
compare_and_replace "$tmp_file" "$pam_file"
|
||||||
|
}
|
||||||
|
|
||||||
|
update_account() {
|
||||||
|
# Write /etc/pam.d/sshd-account
|
||||||
|
local tmp_file pam_file
|
||||||
|
tmp_file="/tmp/sshd-account"
|
||||||
|
pam_file="/etc/pam.d/sshd-account"
|
||||||
|
|
||||||
|
local auth_enabled="${1}"
|
||||||
|
local enabled="${2}"
|
||||||
|
|
||||||
|
rm -f "$tmp_file"
|
||||||
|
touch "$tmp_file"
|
||||||
|
|
||||||
|
if [ "${auth_enabled}" -eq 1 ] && [ "${enabled}" -eq 1 ]; then
|
||||||
|
write_line "$tmp_file" "account required pam_faillock.so"
|
||||||
|
fi
|
||||||
|
|
||||||
|
write_line "$tmp_file" "account [success=1 new_authtok_reqd=done default=ignore] pam_unix.so"
|
||||||
|
write_line "$tmp_file" ""
|
||||||
|
write_line "$tmp_file" "account requisite pam_deny.so"
|
||||||
|
write_line "$tmp_file" "account required pam_permit.so"
|
||||||
|
|
||||||
|
compare_and_replace "$tmp_file" "$pam_file"
|
||||||
|
}
|
||||||
|
|
||||||
|
handle_security_policy() {
|
||||||
|
local auth_enabled enabled
|
||||||
|
local use_mfa mfa_enabled
|
||||||
|
|
||||||
|
# Read UCI values
|
||||||
|
auth_enabled="$(uci -q get users.users.auth_policy_enable || echo 0)"
|
||||||
|
enabled="$(uci -q get users.authentication_policy.enabled || echo 0)"
|
||||||
|
use_mfa="$(uci -q get sshd.@sshd[0].UseMFA || echo 0)"
|
||||||
|
|
||||||
|
# if any .so files are missing, then we cannot setup security
|
||||||
|
if ! check_required_modules; then
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Detect and enable MFA only if requested and module exists
|
||||||
|
if which "$MFA_APP" > /dev/null 2>&1 && [ "$use_mfa" = "1" ] && [ -f "$MFA_LIB" ]; then
|
||||||
|
mfa_enabled=1
|
||||||
|
setup_mfa
|
||||||
|
else
|
||||||
|
rm -rf "${MFA_QR_FILE}"
|
||||||
|
rm -rf "${MFA_SECRET_FILE}"
|
||||||
|
mfa_enabled=0
|
||||||
|
fi
|
||||||
|
|
||||||
|
update_auth "${auth_enabled}" "${enabled}" "${mfa_enabled}"
|
||||||
|
update_account "${auth_enabled}" "${enabled}"
|
||||||
|
update_password "${auth_enabled}"
|
||||||
|
}
|
||||||
68
sshmngr/files/openssh_backend/ssh_mfa_override.json
Normal file
68
sshmngr/files/openssh_backend/ssh_mfa_override.json
Normal file
|
|
@ -0,0 +1,68 @@
|
||||||
|
{
|
||||||
|
"json_plugin_version": 2,
|
||||||
|
"Device.SSH.Server.{i}.": {
|
||||||
|
"type": "object",
|
||||||
|
"protocols": [
|
||||||
|
"cwmp",
|
||||||
|
"usp"
|
||||||
|
],
|
||||||
|
"access": false,
|
||||||
|
"array": false,
|
||||||
|
"{BBF_VENDOR_PREFIX}UseMFA": {
|
||||||
|
"type": "boolean",
|
||||||
|
"read": true,
|
||||||
|
"write": true,
|
||||||
|
"protocols": [
|
||||||
|
"cwmp",
|
||||||
|
"usp"
|
||||||
|
],
|
||||||
|
"mapping": [
|
||||||
|
{
|
||||||
|
"data": "@Parent",
|
||||||
|
"type": "uci_sec",
|
||||||
|
"key": "UseMFA"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"{BBF_VENDOR_PREFIX}MFA_Key": {
|
||||||
|
"type": "string",
|
||||||
|
"read": true,
|
||||||
|
"write": false,
|
||||||
|
"protocols": [
|
||||||
|
"cwmp",
|
||||||
|
"usp"
|
||||||
|
],
|
||||||
|
"mapping": [
|
||||||
|
{
|
||||||
|
"type": "ubus",
|
||||||
|
"ubus": {
|
||||||
|
"object": "sshmngr",
|
||||||
|
"method": "get_mfa_key",
|
||||||
|
"args": {},
|
||||||
|
"key": "mfa_key"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"{BBF_VENDOR_PREFIX}MFA_Recovery_Codes": {
|
||||||
|
"type": "string",
|
||||||
|
"read": true,
|
||||||
|
"write": false,
|
||||||
|
"protocols": [
|
||||||
|
"cwmp",
|
||||||
|
"usp"
|
||||||
|
],
|
||||||
|
"mapping": [
|
||||||
|
{
|
||||||
|
"type": "ubus",
|
||||||
|
"ubus": {
|
||||||
|
"object": "sshmngr",
|
||||||
|
"method": "get_mfa_recovery",
|
||||||
|
"args": {},
|
||||||
|
"key": "recovery_codes"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -5,11 +5,11 @@
|
||||||
include $(TOPDIR)/rules.mk
|
include $(TOPDIR)/rules.mk
|
||||||
|
|
||||||
PKG_NAME:=sulu-base
|
PKG_NAME:=sulu-base
|
||||||
PKG_VERSION:=5.3.7
|
PKG_VERSION:=5.3.8
|
||||||
|
|
||||||
PKG_SOURCE_PROTO:=git
|
PKG_SOURCE_PROTO:=git
|
||||||
PKG_SOURCE_URL:=https://dev.iopsys.eu/websdk/sulu.git
|
PKG_SOURCE_URL:=https://dev.iopsys.eu/websdk/sulu.git
|
||||||
PKG_SOURCE_VERSION:=031da9aa475a8f91feb1f358d5c1fd64cef709bc
|
PKG_SOURCE_VERSION:=d539ffdea1640b7cdeb55765c5737d8d7b6ab630
|
||||||
PKG_MIRROR_HASH:=skip
|
PKG_MIRROR_HASH:=skip
|
||||||
|
|
||||||
SULU_MOD:=core
|
SULU_MOD:=core
|
||||||
|
|
|
||||||
|
|
@ -5,12 +5,12 @@
|
||||||
include $(TOPDIR)/rules.mk
|
include $(TOPDIR)/rules.mk
|
||||||
|
|
||||||
PKG_NAME:=sulu-builder
|
PKG_NAME:=sulu-builder
|
||||||
PKG_VERSION:=5.3.7
|
PKG_VERSION:=5.3.8
|
||||||
PKG_RELEASE:=1
|
PKG_RELEASE:=1
|
||||||
|
|
||||||
PKG_SOURCE_PROTO:=git
|
PKG_SOURCE_PROTO:=git
|
||||||
PKG_SOURCE_URL:=https://dev.iopsys.eu/websdk/sulu-builder.git
|
PKG_SOURCE_URL:=https://dev.iopsys.eu/websdk/sulu-builder.git
|
||||||
PKG_SOURCE_VERSION:=76d57b5a4654291ef089b54a195953add2b8aaff
|
PKG_SOURCE_VERSION:=fae099019a4dc74e529a909c110966c1cf10b4c7
|
||||||
PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_SOURCE_VERSION)
|
PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_SOURCE_VERSION)
|
||||||
PKG_SOURCE:=$(PKG_NAME)-$(PKG_SOURCE_VERSION).tar.gz
|
PKG_SOURCE:=$(PKG_NAME)-$(PKG_SOURCE_VERSION).tar.gz
|
||||||
PKG_BUILD_DIR:=$(BUILD_DIR)/sulu-$(PKG_VERSION)/sulu-builder-$(PKG_SOURCE_VERSION)
|
PKG_BUILD_DIR:=$(BUILD_DIR)/sulu-$(PKG_VERSION)/sulu-builder-$(PKG_SOURCE_VERSION)
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@
|
||||||
include $(TOPDIR)/rules.mk
|
include $(TOPDIR)/rules.mk
|
||||||
|
|
||||||
PKG_NAME:=sulu-theme-genexis
|
PKG_NAME:=sulu-theme-genexis
|
||||||
PKG_VERSION:=5.3.7
|
PKG_VERSION:=5.3.8
|
||||||
|
|
||||||
PKG_SOURCE_PROTO:=git
|
PKG_SOURCE_PROTO:=git
|
||||||
PKG_SOURCE_URL:=https://dev.iopsys.eu/gnx/sulu-theme-genexis
|
PKG_SOURCE_URL:=https://dev.iopsys.eu/gnx/sulu-theme-genexis
|
||||||
|
|
|
||||||
|
|
@ -5,13 +5,13 @@
|
||||||
include $(TOPDIR)/rules.mk
|
include $(TOPDIR)/rules.mk
|
||||||
|
|
||||||
PKG_NAME:=tr143
|
PKG_NAME:=tr143
|
||||||
PKG_VERSION:=1.1.12
|
PKG_VERSION:=1.1.13
|
||||||
|
|
||||||
LOCAL_DEV:=0
|
LOCAL_DEV:=0
|
||||||
ifneq ($(LOCAL_DEV),1)
|
ifneq ($(LOCAL_DEV),1)
|
||||||
PKG_SOURCE_PROTO:=git
|
PKG_SOURCE_PROTO:=git
|
||||||
PKG_SOURCE_URL:=https://dev.iopsys.eu/bbf/tr143d.git
|
PKG_SOURCE_URL:=https://dev.iopsys.eu/bbf/tr143d.git
|
||||||
PKG_SOURCE_VERSION:=c0149efd8e5cd5d908988148281b6caabeac615e
|
PKG_SOURCE_VERSION:=be8ee7b6c52817914f66875d36061f2f62b80af8
|
||||||
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION)-$(PKG_SOURCE_VERSION).tar.gz
|
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION)-$(PKG_SOURCE_VERSION).tar.gz
|
||||||
PKG_MIRROR_HASH:=skip
|
PKG_MIRROR_HASH:=skip
|
||||||
endif
|
endif
|
||||||
|
|
@ -41,14 +41,15 @@ define Package/tr143/install
|
||||||
|
|
||||||
ifeq ($(CONFIG_TARGET_SUBTARGET),"an7581")
|
ifeq ($(CONFIG_TARGET_SUBTARGET),"an7581")
|
||||||
$(BBFDM_INSTALL_SCRIPT) $(PKG_BUILD_DIR)/airoha/scripts/download $(1)
|
$(BBFDM_INSTALL_SCRIPT) $(PKG_BUILD_DIR)/airoha/scripts/download $(1)
|
||||||
|
$(BBFDM_INSTALL_SCRIPT) $(PKG_BUILD_DIR)/airoha/scripts/upload $(1)
|
||||||
$(INSTALL_DATA) ./files/an7581/etc/uci-defaults/* $(1)/etc/uci-defaults/
|
$(INSTALL_DATA) ./files/an7581/etc/uci-defaults/* $(1)/etc/uci-defaults/
|
||||||
else
|
else
|
||||||
$(BBFDM_INSTALL_SCRIPT) $(PKG_BUILD_DIR)/scripts/download $(1)
|
$(BBFDM_INSTALL_SCRIPT) $(PKG_BUILD_DIR)/scripts/download $(1)
|
||||||
|
$(BBFDM_INSTALL_SCRIPT) $(PKG_BUILD_DIR)/scripts/upload $(1)
|
||||||
$(INSTALL_DATA) ./files/other/etc/uci-defaults/* $(1)/etc/uci-defaults/
|
$(INSTALL_DATA) ./files/other/etc/uci-defaults/* $(1)/etc/uci-defaults/
|
||||||
endif
|
endif
|
||||||
|
|
||||||
$(BBFDM_INSTALL_SCRIPT) $(PKG_BUILD_DIR)/scripts/traceroute $(1)
|
$(BBFDM_INSTALL_SCRIPT) $(PKG_BUILD_DIR)/scripts/traceroute $(1)
|
||||||
$(BBFDM_INSTALL_SCRIPT) $(PKG_BUILD_DIR)/scripts/upload $(1)
|
|
||||||
$(BBFDM_INSTALL_SCRIPT) -d $(PKG_BUILD_DIR)/scripts/bbf_diag/ipping $(1)
|
$(BBFDM_INSTALL_SCRIPT) -d $(PKG_BUILD_DIR)/scripts/bbf_diag/ipping $(1)
|
||||||
$(BBFDM_INSTALL_SCRIPT) -d $(PKG_BUILD_DIR)/scripts/bbf_diag/serverselection $(1)
|
$(BBFDM_INSTALL_SCRIPT) -d $(PKG_BUILD_DIR)/scripts/bbf_diag/serverselection $(1)
|
||||||
$(BBFDM_INSTALL_SCRIPT) -d $(PKG_BUILD_DIR)/scripts/bbf_diag/udpecho $(1)
|
$(BBFDM_INSTALL_SCRIPT) -d $(PKG_BUILD_DIR)/scripts/bbf_diag/udpecho $(1)
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
|
||||||
set_tr143_download_defaults() {
|
set_tr143_diagnostic_defaults() {
|
||||||
if [ ! -f /etc/bbfdm/dmmap/dmmap_diagnostics ]; then
|
if [ ! -f /etc/bbfdm/dmmap/dmmap_diagnostics ]; then
|
||||||
touch /etc/bbfdm/dmmap/dmmap_diagnostics
|
touch /etc/bbfdm/dmmap/dmmap_diagnostics
|
||||||
fi
|
fi
|
||||||
|
|
@ -9,7 +9,11 @@ set_tr143_download_defaults() {
|
||||||
uci -q -c /etc/bbfdm/dmmap set dmmap_diagnostics.download.DefaultNumberOfConnections='4'
|
uci -q -c /etc/bbfdm/dmmap set dmmap_diagnostics.download.DefaultNumberOfConnections='4'
|
||||||
uci -q -c /etc/bbfdm/dmmap set dmmap_diagnostics.download.DownloadDiagnosticMaxConnections='8'
|
uci -q -c /etc/bbfdm/dmmap set dmmap_diagnostics.download.DownloadDiagnosticMaxConnections='8'
|
||||||
|
|
||||||
|
uci -q -c /etc/bbfdm/dmmap set dmmap_diagnostics.upload='upload'
|
||||||
|
uci -q -c /etc/bbfdm/dmmap set dmmap_diagnostics.upload.DefaultNumberOfConnections='1'
|
||||||
|
uci -q -c /etc/bbfdm/dmmap set dmmap_diagnostics.upload.UploadDiagnosticMaxConnections='8'
|
||||||
|
|
||||||
uci -q -c /etc/bbfdm/dmmap commit dmmap_diagnostics
|
uci -q -c /etc/bbfdm/dmmap commit dmmap_diagnostics
|
||||||
}
|
}
|
||||||
|
|
||||||
set_tr143_download_defaults
|
set_tr143_diagnostic_defaults
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
|
||||||
set_tr143_download_defaults() {
|
set_tr143_diagnostic_defaults() {
|
||||||
if [ ! -f /etc/bbfdm/dmmap/dmmap_diagnostics ]; then
|
if [ ! -f /etc/bbfdm/dmmap/dmmap_diagnostics ]; then
|
||||||
touch /etc/bbfdm/dmmap/dmmap_diagnostics
|
touch /etc/bbfdm/dmmap/dmmap_diagnostics
|
||||||
fi
|
fi
|
||||||
|
|
@ -9,7 +9,11 @@ set_tr143_download_defaults() {
|
||||||
uci -q -c /etc/bbfdm/dmmap set dmmap_diagnostics.download.DefaultNumberOfConnections='1'
|
uci -q -c /etc/bbfdm/dmmap set dmmap_diagnostics.download.DefaultNumberOfConnections='1'
|
||||||
uci -q -c /etc/bbfdm/dmmap set dmmap_diagnostics.download.DownloadDiagnosticMaxConnections='1'
|
uci -q -c /etc/bbfdm/dmmap set dmmap_diagnostics.download.DownloadDiagnosticMaxConnections='1'
|
||||||
|
|
||||||
|
uci -q -c /etc/bbfdm/dmmap set dmmap_diagnostics.upload='upload'
|
||||||
|
uci -q -c /etc/bbfdm/dmmap set dmmap_diagnostics.upload.DefaultNumberOfConnections='1'
|
||||||
|
uci -q -c /etc/bbfdm/dmmap set dmmap_diagnostics.upload.UploadDiagnosticMaxConnections='1'
|
||||||
|
|
||||||
uci -q -c /etc/bbfdm/dmmap commit dmmap_diagnostics
|
uci -q -c /etc/bbfdm/dmmap commit dmmap_diagnostics
|
||||||
}
|
}
|
||||||
|
|
||||||
set_tr143_download_defaults
|
set_tr143_diagnostic_defaults
|
||||||
|
|
|
||||||
|
|
@ -2,197 +2,411 @@
|
||||||
|
|
||||||
# Script: bbf_config_reload.sh
|
# Script: bbf_config_reload.sh
|
||||||
# Description:
|
# Description:
|
||||||
# This script reloads WiFi Configs based on input args.
|
# Reloads WiFi configurations based on provided arguments.
|
||||||
# Input args should be one of the below or both with space separate
|
#
|
||||||
# - "wireless"
|
|
||||||
# - "mapcontroller"
|
|
||||||
#
|
|
||||||
# Usage:
|
# Usage:
|
||||||
# sh bbf_config_reload.sh wireless mapcontroller
|
# sh bbf_config_reload.sh [wireless] [mapcontroller]
|
||||||
#
|
#
|
||||||
|
# Input arguments:
|
||||||
|
# wireless Reload only wireless configuration
|
||||||
|
# mapcontroller Reload only mapcontroller configuration
|
||||||
|
#
|
||||||
# Actions:
|
# Actions:
|
||||||
# - If both wireless and mapcontroller → Reload mapcontroller (SIGHUP)
|
# - If both "wireless" and "mapcontroller" are specified:
|
||||||
# - If only wireless → Commit wireless config via ubus
|
# → Reload mapcontroller (send SIGHUP)
|
||||||
# - If only mapcontroller → Reload mapcontroller (SIGHUP)
|
# - If only "wireless" is specified:
|
||||||
# - Otherwise → Do nothing
|
# → Commit wireless configuration via ubus
|
||||||
|
# - If only "mapcontroller" is specified:
|
||||||
|
# → Reload mapcontroller (send SIGHUP)
|
||||||
|
# - If no valid arguments are provided:
|
||||||
|
# → Do nothing
|
||||||
|
|
||||||
log() {
|
. /lib/functions.sh
|
||||||
echo "${@}"|logger -t bbf.config.wifi.reload -p info
|
|
||||||
|
# ------------------------------------------------------
|
||||||
|
# Global variables
|
||||||
|
# ------------------------------------------------------
|
||||||
|
MAPCONTROLLER=0
|
||||||
|
WIRELESS=0
|
||||||
|
MAX_RETRIES=15
|
||||||
|
AP_COUNT=0
|
||||||
|
|
||||||
|
# ------------------------------------------------------
|
||||||
|
# Info log
|
||||||
|
# ------------------------------------------------------
|
||||||
|
info() {
|
||||||
|
echo "${@}" | logger -t bbf.config.wifi.reload -p info
|
||||||
}
|
}
|
||||||
|
|
||||||
input="$@"
|
# ------------------------------------------------------
|
||||||
|
# Debug log
|
||||||
|
# ------------------------------------------------------
|
||||||
|
debug() {
|
||||||
|
echo "${@}"
|
||||||
|
}
|
||||||
|
|
||||||
# Validate input
|
# ------------------------------------------------------
|
||||||
if [ -z "$input" ]; then
|
# Parse AP from mapcontroller config
|
||||||
log "Error: No input provided"
|
# ------------------------------------------------------
|
||||||
exit 1
|
parse_mapcontroller_ap() {
|
||||||
fi
|
local section="$1"
|
||||||
|
|
||||||
# Normalize inputs (default to 0 if not set)
|
config_get type "$section" type
|
||||||
wireless=0
|
[ "$type" = "fronthaul" ] || return 0
|
||||||
mapcontroller=0
|
|
||||||
|
|
||||||
for arg in ${input}; do
|
config_get enabled "$section" enabled
|
||||||
if [ "${arg}" == "wireless" ]; then
|
[ "$enabled" != "0" ] || return 0
|
||||||
wireless=1
|
|
||||||
|
config_get ssid "$section" ssid
|
||||||
|
[ -n "$ssid" ] || return 0
|
||||||
|
|
||||||
|
config_get band "$section" band
|
||||||
|
[ -n "$band" ] || return 0
|
||||||
|
|
||||||
|
case "$band" in
|
||||||
|
2|5|6) ;;
|
||||||
|
*) return 0 ;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
config_get encryption "$section" encryption
|
||||||
|
config_get key "$section" key
|
||||||
|
|
||||||
|
eval "AP_SSID_${AP_COUNT}='${ssid}'"
|
||||||
|
eval "AP_BAND_${AP_COUNT}='${band}'"
|
||||||
|
eval "AP_ENCRYPTION_${AP_COUNT}='${encryption}'"
|
||||||
|
eval "AP_KEY_${AP_COUNT}='${key}'"
|
||||||
|
|
||||||
|
debug "parse_mapcontroller_ap: AP[$AP_COUNT] ssid=|$ssid| band=|$band| encryption=|$encryption| key=|$key|"
|
||||||
|
|
||||||
|
AP_COUNT=$((AP_COUNT + 1))
|
||||||
|
}
|
||||||
|
|
||||||
|
# ------------------------------------------------------
|
||||||
|
# Parse wireless APs (multi_ap, enabled, ssid, band, key, encryption)
|
||||||
|
# ------------------------------------------------------
|
||||||
|
parse_wireless_ap() {
|
||||||
|
log_prefix="parse_wireless_ap:"
|
||||||
|
local section="$1"
|
||||||
|
local matched_ifname=""
|
||||||
|
|
||||||
|
config_get disabled "$section" disabled
|
||||||
|
[ "$disabled" = "1" ] && return 0
|
||||||
|
|
||||||
|
config_get multi_ap "$section" multi_ap
|
||||||
|
case "$multi_ap" in
|
||||||
|
1|2) return 0 ;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
config_get ssid "$section" ssid
|
||||||
|
[ -n "$ssid" ] || return 0
|
||||||
|
|
||||||
|
config_get device "$section" device
|
||||||
|
[ -n "$device" ] || return 0
|
||||||
|
|
||||||
|
config_get band "$device" band
|
||||||
|
case "$band" in
|
||||||
|
2g) band="2" ;;
|
||||||
|
5g) band="5" ;;
|
||||||
|
6g) band="6" ;;
|
||||||
|
*) return 0 ;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
config_get radio_disabled "$device" disabled
|
||||||
|
[ "$radio_disabled" = "1" ] && return 0
|
||||||
|
|
||||||
|
config_get encryption "$section" encryption
|
||||||
|
config_get key "$section" key
|
||||||
|
|
||||||
|
eval "AP_SSID_${AP_COUNT}='${ssid}'"
|
||||||
|
eval "AP_BAND_${AP_COUNT}='${band}'"
|
||||||
|
eval "AP_KEY_${AP_COUNT}='${key}'"
|
||||||
|
eval "AP_ENCRYPTION_${AP_COUNT}='${encryption}'"
|
||||||
|
|
||||||
|
debug "$log_prefix AP[$AP_COUNT] iface=$section ssid=|$ssid| band=|$band| encryption=|$encryption| key=|$key|"
|
||||||
|
|
||||||
|
for try in $(seq 1 "$MAX_RETRIES"); do
|
||||||
|
config_get matched_ifname "$section" ifname
|
||||||
|
|
||||||
|
if [ -n "$matched_ifname" ]; then
|
||||||
|
debug "$log_prefix matched AP[$AP_COUNT] → ifname=$matched_ifname"
|
||||||
|
eval "AP_IFNAME_${AP_COUNT}='${matched_ifname}'"
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
|
||||||
|
debug "$log_prefix no ifname for AP[$AP_COUNT] ssid=$ssid (try $try/$MAX_RETRIES)"
|
||||||
|
sleep 1
|
||||||
|
config_load wireless
|
||||||
|
done
|
||||||
|
|
||||||
|
eval "tmp_ifname=\$AP_IFNAME_${AP_COUNT}"
|
||||||
|
if [ -z "$tmp_ifname" ]; then
|
||||||
|
info "$log_prefix FAIL: could not match AP[$AP_COUNT] ssid=$ssid after $MAX_RETRIES tries"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ "${arg}" == "mapcontroller" ]; then
|
AP_COUNT=$((AP_COUNT + 1))
|
||||||
mapcontroller=1
|
}
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
|
# ------------------------------------------------------
|
||||||
|
# Match AP from mapcontroller to wireless interface
|
||||||
|
# ------------------------------------------------------
|
||||||
|
match_ap_to_wireless_interface() {
|
||||||
|
local section="$1"
|
||||||
|
|
||||||
################################################################################
|
config_get disabled "$section" disabled
|
||||||
# wait_for_wifi_reload
|
[ "$disabled" = "1" ] && return 0
|
||||||
#
|
|
||||||
# Description:
|
|
||||||
# Currently, there is no direct way to determine when WiFi reload
|
|
||||||
# operations have fully completed. The ubus API does not provide any
|
|
||||||
# event or flag indicating that WiFi services have finished reloading.
|
|
||||||
#
|
|
||||||
# To work around this, we use a timing-based heuristic:
|
|
||||||
# - We repeatedly run `ubus call wifi status` every 1 second.
|
|
||||||
# - Each call is timed (using `date +%s` before and after).
|
|
||||||
# - Normally, this command returns almost instantly (<1s).
|
|
||||||
# - However, during a WiFi reload, the call may take longer
|
|
||||||
# (several seconds) while the subsystem is busy.
|
|
||||||
# - Once we detect that `ubus call wifi status` takes longer than
|
|
||||||
# 2 seconds to return, we assume the reload has been applied
|
|
||||||
# and completed successfully.
|
|
||||||
#
|
|
||||||
# Additional wait constraints:
|
|
||||||
# - Minimum wait: 5 seconds (to ensure reload started).
|
|
||||||
# - Maximum wait: 15 seconds (to prevent indefinite blocking).
|
|
||||||
# - If the threshold is not met within 15s, we log a timeout warning.
|
|
||||||
################################################################################
|
|
||||||
wait_for_wifi_reload() {
|
|
||||||
MAX_ITER=15
|
|
||||||
MIN_ITER=5
|
|
||||||
THRESH=2 # seconds
|
|
||||||
|
|
||||||
# Check if wifi ubus object exists
|
config_get multi_ap "$section" multi_ap
|
||||||
ubus -t 2 wait_for wifi >/dev/null 2>&1
|
[ "$multi_ap" = "2" ] || return 0
|
||||||
if [ "$?" -ne 0 ]; then
|
|
||||||
log "wifi ubus object not available, skipping wait logic"
|
config_get w_ssid "$section" ssid
|
||||||
|
[ "$w_ssid" = "$SSID" ] || return 0
|
||||||
|
|
||||||
|
config_get device "$section" device
|
||||||
|
[ -n "$device" ] || return 0
|
||||||
|
|
||||||
|
config_get ap_band "$device" band
|
||||||
|
case "$ap_band" in
|
||||||
|
2g) ap_band="2" ;;
|
||||||
|
5g) ap_band="5" ;;
|
||||||
|
6g) ap_band="6" ;;
|
||||||
|
*) return 0 ;;
|
||||||
|
esac
|
||||||
|
[ "$ap_band" = "$BAND" ] || return 0
|
||||||
|
|
||||||
|
config_get radio_disabled "$device" disabled
|
||||||
|
[ "$radio_disabled" = "1" ] && return 0
|
||||||
|
|
||||||
|
config_get w_key "$section" key
|
||||||
|
if [ -n "$KEY" ] && [ "$w_key" != "$KEY" ]; then
|
||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
#log "Waiting for WiFi reload (min ${MIN_ITER}s, max ${MAX_ITER}s)..."
|
config_get w_enc "$section" encryption
|
||||||
|
if [ -n "$ENCRYPTION" ] && [ "$w_enc" != "$ENCRYPTION" ]; then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
iter=0
|
config_get IFNAME "$section" ifname
|
||||||
while [ "${iter}" -lt "${MAX_ITER}" ]; do
|
MATCHED_IFNAME="$IFNAME"
|
||||||
iter=$((iter + 1))
|
RADIO_DISABLED="$radio_disabled"
|
||||||
start=$(date +%s)
|
}
|
||||||
ubus call wifi status >/dev/null 2>&1
|
|
||||||
#rc=$?
|
|
||||||
end=$(date +%s)
|
|
||||||
elapsed=$((end - start))
|
|
||||||
|
|
||||||
#log "wait_for_wifi_reload: iter=${iter}, rc=${rc}, elapsed=${elapsed}s"
|
# ------------------------------------------------------
|
||||||
|
# Iterate over stored APs and match them to wireless interfaces
|
||||||
|
# ------------------------------------------------------
|
||||||
|
match_aps_to_wireless_interfaces() {
|
||||||
|
log_prefix="match_aps_to_wireless_interfaces:"
|
||||||
|
config_load wireless
|
||||||
|
|
||||||
# If ubus took >2s and we've waited at least MIN_ITER → assume reload done
|
for i in $(seq 0 $((AP_COUNT - 1))); do
|
||||||
if [ "${elapsed}" -gt "${THRESH}" ] && [ "${iter}" -ge "${MIN_ITER}" ]; then
|
eval "SSID=\$AP_SSID_$i"
|
||||||
log "Detected long ubus response (${elapsed}s) after ${iter}s → assuming WiFi reload complete"
|
eval "BAND=\$AP_BAND_$i"
|
||||||
return 0
|
eval "ENCRYPTION=\$AP_ENCRYPTION_$i"
|
||||||
fi
|
eval "KEY=\$AP_KEY_$i"
|
||||||
|
|
||||||
# Sleep 1s between checks
|
debug "$log_prefix matching AP[$i]: ssid=|$SSID| band=|$BAND| encryption=|$ENCRYPTION| key=|$KEY|"
|
||||||
if [ "${iter}" -lt "${MAX_ITER}" ]; then
|
|
||||||
|
MATCHED_IFNAME=""
|
||||||
|
RADIO_DISABLED="0"
|
||||||
|
|
||||||
|
for try in $(seq 1 "$MAX_RETRIES"); do
|
||||||
|
config_foreach match_ap_to_wireless_interface wifi-iface
|
||||||
|
|
||||||
|
if [ -n "$MATCHED_IFNAME" ]; then
|
||||||
|
debug "$log_prefix matched AP[$i] → ifname=$MATCHED_IFNAME"
|
||||||
|
eval "AP_IFNAME_$i=\$MATCHED_IFNAME"
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$RADIO_DISABLED" = "1" ]; then
|
||||||
|
debug "$log_prefix radio is disabled, no need to retry"
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
|
||||||
|
debug "$log_prefix no match for AP[$i] ssid=$SSID (try $try/$MAX_RETRIES)"
|
||||||
sleep 1
|
sleep 1
|
||||||
|
config_load wireless
|
||||||
|
done
|
||||||
|
|
||||||
|
eval "tmp_ifname=\$AP_IFNAME_$i"
|
||||||
|
if [ -z "$tmp_ifname" ] && [ "$RADIO_DISABLED" != "1" ]; then
|
||||||
|
info "$log_prefix FAIL: could not match AP[$i] ssid=$SSID after $MAX_RETRIES tries"
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
|
||||||
log "Timeout after ${MAX_ITER}s — WiFi reload not confirmed"
|
|
||||||
return 1
|
|
||||||
}
|
}
|
||||||
|
|
||||||
###############################################################################
|
# ------------------------------------------------------
|
||||||
# mark_ap_instances_applied
|
# Verify APs runtime state via ubus
|
||||||
#
|
# ------------------------------------------------------
|
||||||
# Description:
|
verify_aps_runtime_state() {
|
||||||
# Finalizes newly created WiFi AccessPoint instances in the dmmap WiFi
|
log_prefix="verify_aps_runtime_state:"
|
||||||
# configuration.
|
|
||||||
#
|
|
||||||
# An AccessPoint instance is considered a *new instance* when the option
|
|
||||||
# __is_new__ exists and its value is "1".
|
|
||||||
#
|
|
||||||
# New instance handling logic:
|
|
||||||
#
|
|
||||||
# • The AccessPoint's controller-side section name is obtained from
|
|
||||||
# the __section_name__ option (e.g., "mapcontroller.xxx" or "wireless.xxx").
|
|
||||||
#
|
|
||||||
# • For new instances where __section_name__ begins with "mapcontroller.":
|
|
||||||
# - Remove __is_new__
|
|
||||||
# - No additional actions required
|
|
||||||
#
|
|
||||||
# • For new instances where __section_name__ begins with "wireless.":
|
|
||||||
# - Set mapcontroller=0 (indicates mapcontroller reload is not required)
|
|
||||||
# - Remove __is_new__
|
|
||||||
#
|
|
||||||
# • For all other prefixes:
|
|
||||||
# - Remove __is_new__ only
|
|
||||||
#
|
|
||||||
# After all new instances are processed, the dmmap WiFi configuration is committed.
|
|
||||||
###############################################################################
|
|
||||||
mark_ap_instances_applied() {
|
|
||||||
for sec in $(uci -q -c /etc/bbfdm/dmmap show WiFi | grep "=AccessPoint" | cut -d. -f2 | cut -d= -f1); do
|
|
||||||
is_new=$(uci -q -c /etc/bbfdm/dmmap get WiFi.${sec}.__is_new__)
|
|
||||||
|
|
||||||
if [ "${is_new}" = "1" ]; then
|
for i in $(seq 0 $((AP_COUNT - 1))); do
|
||||||
config_sec_name=$(uci -q -c /etc/bbfdm/dmmap get WiFi.${sec}.__section_name__)
|
eval "ifname=\$AP_IFNAME_$i"
|
||||||
case "${config_sec_name}" in
|
eval "ssid=\$AP_SSID_$i"
|
||||||
mapcontroller.*)
|
eval "band=\$AP_BAND_$i"
|
||||||
# New mapcontroller AP instance — remove creation flag only
|
|
||||||
uci -q -c /etc/bbfdm/dmmap delete WiFi.${sec}.__is_new__
|
|
||||||
;;
|
|
||||||
|
|
||||||
wireless.*)
|
if [ -z "$ifname" ]; then
|
||||||
# New wireless AP instance — skip mapcontroller reload
|
debug "$log_prefix ifname is empty for AP[$i] ssid=$ssid due to radio disabled"
|
||||||
mapcontroller=0
|
continue
|
||||||
uci -q -c /etc/bbfdm/dmmap delete WiFi.${sec}.__is_new__
|
|
||||||
;;
|
|
||||||
|
|
||||||
*)
|
|
||||||
# Other AP instance types — remove creation flag only
|
|
||||||
uci -q -c /etc/bbfdm/dmmap delete WiFi.${sec}.__is_new__
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
debug "$log_prefix validating runtime for IFNAME=|$ifname| ssid=|$ssid| band=|$band|"
|
||||||
|
|
||||||
|
case "$band" in
|
||||||
|
2) expected_ubus_band="2.4GHz" ;;
|
||||||
|
5) expected_ubus_band="5GHz" ;;
|
||||||
|
6) expected_ubus_band="6GHz" ;;
|
||||||
|
*)
|
||||||
|
debug "$log_prefix unknown band '$band' for AP[$i]"
|
||||||
|
continue
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
ok=0
|
||||||
|
for try in $(seq 1 "$MAX_RETRIES"); do
|
||||||
|
json="$(ubus call wifi.ap."$ifname" status 2>/dev/null)"
|
||||||
|
|
||||||
|
if [ -z "$json" ]; then
|
||||||
|
debug "$log_prefix empty ubus response for $ifname (try $try/$MAX_RETRIES)"
|
||||||
|
sleep 2
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
ubus_ssid="$(echo "$json" | jsonfilter -q -e '@.ssid')"
|
||||||
|
ubus_band="$(echo "$json" | jsonfilter -q -e '@.band')"
|
||||||
|
|
||||||
|
if [ "$ubus_ssid" != "$ssid" ]; then
|
||||||
|
debug "$log_prefix ubus ssid mismatch for $ifname: expected=$ssid got=$ubus_ssid (try $try)"
|
||||||
|
sleep 2
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$ubus_band" != "$expected_ubus_band" ]; then
|
||||||
|
debug "$log_prefix ubus band mismatch for $ifname: expected=$expected_ubus_band got=$ubus_band (try $try)"
|
||||||
|
sleep 2
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
ok=1
|
||||||
|
break
|
||||||
|
done
|
||||||
|
|
||||||
|
if [ "$ok" -ne 1 ]; then
|
||||||
|
info "$log_prefix FAIL: runtime validation failed for $ifname"
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
debug "$log_prefix IFACE=$ifname runtime validated"
|
||||||
done
|
done
|
||||||
|
|
||||||
uci -q -c /etc/bbfdm/dmmap commit WiFi
|
debug "$log_prefix runtime validation completed"
|
||||||
}
|
}
|
||||||
|
|
||||||
# Define function to reload mapcontroller
|
# ------------------------------------------------------
|
||||||
|
# Validate mapcontroller config changes
|
||||||
|
# ------------------------------------------------------
|
||||||
|
validate_mapcontroller_changes() {
|
||||||
|
AP_COUNT=0
|
||||||
|
|
||||||
|
config_load mapcontroller
|
||||||
|
config_foreach parse_mapcontroller_ap ap
|
||||||
|
|
||||||
|
if [ "$AP_COUNT" -eq 0 ]; then
|
||||||
|
debug "reload_mapcontroller: no AP found in mapcontroller"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
match_aps_to_wireless_interfaces
|
||||||
|
verify_aps_runtime_state
|
||||||
|
}
|
||||||
|
|
||||||
|
# ------------------------------------------------------
|
||||||
|
# Validate wireless config changes
|
||||||
|
# ------------------------------------------------------
|
||||||
|
validate_wireless_changes() {
|
||||||
|
AP_COUNT=0
|
||||||
|
|
||||||
|
config_load wireless
|
||||||
|
config_foreach parse_wireless_ap wifi-iface
|
||||||
|
|
||||||
|
if [ "$AP_COUNT" -eq 0 ]; then
|
||||||
|
debug "reload_wireless: no AP found in wireless"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
verify_aps_runtime_state
|
||||||
|
}
|
||||||
|
|
||||||
|
# ------------------------------------------------------
|
||||||
|
# Reload mapcontroller service
|
||||||
|
# ------------------------------------------------------
|
||||||
reload_mapcontroller() {
|
reload_mapcontroller() {
|
||||||
pid=$(pidof mapcontroller)
|
pid=$(pidof mapcontroller)
|
||||||
if [ -n "$pid" ]; then
|
if [ -n "$pid" ]; then
|
||||||
log "Reloading mapcontroller (PID: $pid)..."
|
info "Reloading mapcontroller (PID: $pid)..."
|
||||||
kill -SIGHUP "$pid"
|
kill -SIGHUP "$pid"
|
||||||
wait_for_wifi_reload
|
sleep 5
|
||||||
|
validate_mapcontroller_changes
|
||||||
else
|
else
|
||||||
log "Warning: mapcontroller process not found"
|
info "Warning: mapcontroller process not found"
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
# Define function to commit wireless config
|
# ------------------------------------------------------
|
||||||
commit_wireless_config() {
|
# Reload wireless service
|
||||||
log "Committing wireless config..."
|
# ------------------------------------------------------
|
||||||
|
reload_wireless() {
|
||||||
|
info "Reloading wireless config..."
|
||||||
ubus call uci commit '{"config":"wireless"}'
|
ubus call uci commit '{"config":"wireless"}'
|
||||||
wait_for_wifi_reload
|
sleep 5
|
||||||
|
validate_wireless_changes
|
||||||
}
|
}
|
||||||
|
|
||||||
# Finalize newly created AP AccessPoint instances
|
# ------------------------------------------------------
|
||||||
mark_ap_instances_applied
|
# Finalize Access Point instances
|
||||||
|
# ------------------------------------------------------
|
||||||
|
finalize_ap_instances() {
|
||||||
|
DMAP_PATH="uci -q -c /etc/bbfdm/dmmap"
|
||||||
|
for sec in $($DMAP_PATH show WiFi | grep "=AccessPoint" | cut -d. -f2 | cut -d= -f1); do
|
||||||
|
is_new=$($DMAP_PATH get WiFi.${sec}.__is_new__)
|
||||||
|
[ "$is_new" = "1" ] || continue
|
||||||
|
|
||||||
|
sec_name=$($DMAP_PATH get WiFi.${sec}.__section_name__)
|
||||||
|
case "$sec_name" in
|
||||||
|
wireless.*) MAPCONTROLLER=0 ;;
|
||||||
|
esac
|
||||||
|
$DMAP_PATH delete WiFi.${sec}.__is_new__
|
||||||
|
done
|
||||||
|
|
||||||
# Apply logic based on flags
|
$DMAP_PATH commit WiFi
|
||||||
if [ "$mapcontroller" -eq 1 ]; then
|
}
|
||||||
|
|
||||||
|
# ------------------------------------------------------
|
||||||
|
# Main argument parser
|
||||||
|
# ------------------------------------------------------
|
||||||
|
for arg in "$@"; do
|
||||||
|
case "$arg" in
|
||||||
|
wireless) WIRELESS=1 ;;
|
||||||
|
mapcontroller) MAPCONTROLLER=1 ;;
|
||||||
|
*)
|
||||||
|
info "Unknown option: $arg"
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
# ------------------------------------------------------
|
||||||
|
# Action logic
|
||||||
|
# ------------------------------------------------------
|
||||||
|
finalize_ap_instances
|
||||||
|
|
||||||
|
if [ "$MAPCONTROLLER" -eq 1 ]; then
|
||||||
reload_mapcontroller
|
reload_mapcontroller
|
||||||
elif [ "$wireless" -eq 1 ]; then
|
elif [ "$WIRELESS" -eq 1 ]; then
|
||||||
commit_wireless_config
|
reload_wireless
|
||||||
else
|
else
|
||||||
log "No action needed."
|
info "No valid arguments provided."
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue