op-packages/openwrt-alwaysonline/files/alwaysonline.init
github-actions[bot] 32600acc60 🌴 Sync 2026-03-05 23:51:42
2026-03-05 23:51:42 +08:00

172 lines
4.0 KiB
Bash

#!/bin/sh /etc/rc.common
# Copyright (C) 2023-2025 muink
#
# depends rgmac
. "${IPKG_INSTROOT}/lib/functions/network.sh"
START=99
USE_PROCD=1
# alwaysonline
[ -x "$(command -v nft)" ] && FW='fw4' || FW='fw3'
PROG='/usr/sbin/alwaysonline'
HOSTFILE='/var/hosts/alwaysonline'
USERNAME=alwaysonline
# uci
CONFIG_NAME='alwaysonline'
TYPEDSECTION='alwaysonline'
DOMAINS='domain'
config_load "$CONFIG_NAME"
find_op_ifnames() {
local ifnames ifname iface _c
ifnames="lo $($FW -q zone $($FW -q device "br-lan"))"
for _c in network_find_wan network_find_wan6; do
$_c iface 1
ifname=$($FW -q zone $($FW -q network "$iface"))
ifnames="${ifnames:+$ifnames }$ifname"
done
echo $ifnames | sed 's|\s|\n|g' | sort -u
}
gen_uhttpd_listen_ips() {
local regexp
regexp=$(find_op_ifnames | tr '\n' '|' | sed 's,^|*,,;s,|*$,,')
ip -o addr | grep -v "\bscope link\b" | sed -En -e "/^[0-9]+:\s*($regexp)\s/{s|^.*\binet6?\s+([^/]+)/.*|\1|p}" | sed '/:/{s|^|\[|;s|$|\]|}'
}
validate_section_domain() {
uci_load_validate $CONFIG_NAME $DOMAINS "$1" "$2" \
'enabled:bool:0' \
'name:hostname' \
'group:string' \
'family:or("4", "6", "both"):both' \
'overwrite:ipaddr'
}
init_hosts() {
mkdir -p "${HOSTFILE%/*}" 2>/dev/null
echo "# auto-generated config file from /etc/config/alwaysonline" > "${HOSTFILE}"
}
gen_hosts() {
[ "$2" == "0" ] || { >&2 echo "section $1 validation failed"; return 1; }
[ "$enabled" == "0" ] && return 0
local _addr4="${tun_addr4%/*}"
local _addr6="${tun_addr6%/*}"
local familys
[ "$family" == "both" ] && familys="4 6" || familys="$family"
for v in $familys; do
eval "domain_list=\"\${domain_list}\${overwrite:-\$_addr$v} \${name}\n\""
done
}
gen_eui64() {
local mac=$(rgmac)
local head=${mac:0:2}
if [ "$(( 0x$head & 2 ))" = "0" ]; then
printf "fe80::%x%s" $(( 0x$head | 2 )) "${mac:2:2}:${mac:4:2}ff:fe${mac:6:2}:${mac:8}"
else
printf "fe80::%x%s" $(( 0x$head & 0xfd )) "${mac:2:2}:${mac:4:2}ff:fe${mac:6:2}:${mac:8}"
fi
}
# set_uhttpd [host:port list]
set_uhttpd() {
local listen_http="${1:-0.0.0.0:80 [::]:80}" _v
uci -q delete uhttpd.main.listen_http
for _v in $listen_http; do
uci add_list uhttpd.main.listen_http="$_v"
done
uci commit uhttpd
}
start_instance() {
# TUN
ip tuntap add mode tun user "$USERNAME" name "$tun_name"
sleep 1s
ip link set "$tun_name" up
ip addr add "${tun_addr4}" dev "$tun_name"
ip addr add "${tun_addr6}" dev "$tun_name"
ip addr add "$(gen_eui64)/64" scope link dev "$tun_name"
procd_open_instance "$CONFIG_NAME"
procd_set_param command "$PROG" -port 80
procd_append_param command --disable-dns-server
procd_append_param command -ipv4 "${tun_addr4%/*}" -ipv6 "${tun_addr6%/*}"
procd_append_param netdev "br-lan"
procd_append_param netdev "$tun_name"
procd_set_param respawn
procd_set_param user root
procd_set_param stderr 1
procd_close_instance
}
start_service() {
local enabled tun_name tun_addr4 tun_addr6
config_get enabled global enabled 0
[ "$enabled" == "0" ] && return 1
config_get tun_name global tun_name 'awoltun0'
config_get tun_addr4 global tun_addr4 '172.25.26.1/30'
config_get tun_addr6 global tun_addr6 'fdfe:aead:2526::1/126'
config_get port global port '8083'
# DNS
init_hosts
local domain_list
config_foreach validate_section_domain "$DOMAINS" gen_hosts || return $?
sed -Ei "1a$domain_list" "$HOSTFILE"
# HTTP
/etc/init.d/uhttpd stop
set_uhttpd "$(gen_uhttpd_listen_ips | sed 's|$|:80|')"
start_instance
}
service_triggers() {
procd_add_reload_trigger "$CONFIG_NAME" 'network'
local iface=$(uci show network|grep "device='br-lan'"|cut -f2 -d'.'|head -n1)
[ -n "$iface" ] && procd_add_reload_interface_trigger "$iface"
}
reload_service() {
stop
start
}
service_started() {
# DNS
/etc/init.d/dnsmasq reload
# HTTP
/etc/init.d/uhttpd start
}
service_stopped() {
# DNS
init_hosts
/etc/init.d/dnsmasq reload
# HTTP
set_uhttpd
/etc/init.d/uhttpd restart
# TUN
local tun_name
config_get tun_name global tun_name 'awoltun0'
ip link set "$tun_name" down 2>/dev/null
ip tuntap del mode tun name "$tun_name" 2>/dev/null
}