2025-01-20 22:42:26 +08:00

209 lines
6.1 KiB
Bash

#!/bin/sh /etc/rc.common
START=20
USE_PROCD=1
boot() {
# procd will call service_triggers
rc_procd true
}
service_triggers() {
procd_add_reload_trigger "network" "ap_modem"
}
find_uci_section_i() {
local key="$2"
local value="$3"
local testv
config_get testv "$1" "$key"
[[ "$value" = "$testv" ]] && echo "$1"
}
find_uci_section() {
local config="$1"
local type="$2"
local key="$3"
local value="$4"
(
config_load "$config"
config_foreach find_uci_section_i "$type" "$key" "$value"
)
}
generate_config() {
[[ "`uci -q get network.lan.device`" = "br-lan" ]] || {
echo "network.lan.device != br-lan in uci" >&2
return 1
}
local wan_dev="`uci -q get network.wan.device`"
[[ -z "$wan_dev" ]] && {
echo "get network.wan.device in uci failed" >&2
return 1
}
local lan_dev=`find_uci_section network device name 'br-lan' | head -1`
[[ -z "$lan_dev" ]] && {
echo "network.device.name=br-lan not found in uci" >&2
return 1
}
local wan_zone=`find_uci_section firewall zone name 'wan' | head -1`
[[ -z "$wan_zone" ]] && {
echo "firewall.zone.name=wan not found in uci" >&2
return 1
}
# virutal lan device
uci -q get network.veth_lan >/dev/null || uci -q batch <<-EOF >/dev/null
set network.veth_lan=device
set network.veth_lan.type=veth
set network.veth_lan.name=vap-lan
set network.veth_lan.sendredirects=0
set network.veth_lan.ipv6=0
set network.veth_lan.multicast=0
set network.veth_lan.peer_name=vap-lan-peer
EOF
uci -q get network.veth_lan_peer >/dev/null || uci -q batch <<-EOF >/dev/null
set network.veth_lan_peer=device
set network.veth_lan_peer.name=vap-lan-peer
set network.veth_lan_peer.sendredirects=0
set network.veth_lan_peer.ipv6=0
set network.veth_lan_peer.multicast=0
EOF
uci -q get "network.$lan_dev.ports" | grep -Fwq 'vap-lan' || uci add_list "network.$lan_dev.ports=vap-lan"
# interface
if uci -q get network.vap_lan >/dev/null; then
uci -q delete network.vap_lan.auto
else
uci -q batch <<-EOF >/dev/null
set network.vap_lan=interface
set network.vap_lan.proto=static
set network.vap_lan.device=vap-lan-peer
set network.vap_lan.defaultroute=0
set network.vap_lan.delegate=0
EOF
fi
if uci -q get network.vap_wan >/dev/null; then
uci -q delete network.vap_wan.auto
else
uci -q batch <<-EOF >/dev/null
set network.vap_wan=interface
set network.vap_wan.proto=static
set network.vap_wan.device=$wan_dev
set network.vap_wan.defaultroute=0
set network.vap_wan.delegate=0
EOF
fi
# firewall
local fw_wan_net="`uci -q get firewall.$wan_zone.network`"
echo "$fw_wan_net" | grep -Fwq 'vap_lan' || uci -q batch <<-EOF >/dev/null
add_list firewall.$wan_zone.network=vap_lan
EOF
echo "$fw_wan_net" | grep -Fwq 'vap_wan' || uci -q batch <<-EOF >/dev/null
add_list firewall.$wan_zone.network=vap_wan
EOF
uci commit firewall
# ip
local bip
local black_ip="127.0.0.1/8"
[[ "`uci -q get network.lan.proto`" = "static" ]] && {
local lan_ip="`uci -q get network.lan.ipaddr`"
if [[ -n "$lan_ip" ]]; then
local netmask="`uci -q get network.lan.netmask`"
[[ -n "$netmask" ]] || netmask=255.255.255.255
for bip in $lan_ip; do
if [[ "$bip" = "*/*" ]]; then
eval "$(ipcalc.sh $bip )";black_ip="$black_ip $IP/$PREFIX"
else
eval "$(ipcalc.sh $bip $netmask )";black_ip="$black_ip $IP/$PREFIX"
fi
done
fi
}
logger -t 'ap_modem' -p INFO "black: $black_ip"
local ipaddr
local vip
local vip_p
local vnet
local bnet
local ok
local vif
for vif in lan wan; do
config_get ipaddr $vif ipaddr
[[ -n "$ipaddr" ]] || continue
for vip in $ipaddr; do
ok=1
[[ "$vip" = "*/*" ]] || vip="$vip/24"
eval "$(ipcalc.sh $vip )";vip="$IP";vip_p="$PREFIX"
[[ "$vip_p" = 32 ]] && {
logger -t 'ap_modem' -p DEBUG "vap_$vif skip $vip/$vip_p"
break
}
for bip in $black_ip; do
eval "$(ipcalc.sh "$bip" )";bip="$IP";
[[ "$PREFIX" -le "$vip_p" ]] || PREFIX=$vip_p
eval "$(ipcalc.sh "$vip/$PREFIX" )";vnet="$NETWORK";
eval "$(ipcalc.sh "$bip/$PREFIX" )";bnet="$NETWORK";
if [[ "$vnet" = "$bnet" ]]; then
logger -t 'ap_modem' -p DEBUG "vap_$vif skip $vip/$vip_p"
ok=0
break
fi
done
[[ "$ok" = 1 ]] && {
uci add_list "network.vap_$vif.ipaddr=$vip/$vip_p"
black_ip="$black_ip $vip/$vip_p"
}
done
done
uci commit network
}
clean_config() {
local wan_zone=`find_uci_section firewall zone name 'wan' | head -1`
[[ -z "$wan_zone" ]] || uci -q batch <<-EOF >/dev/null
del_list firewall.$wan_zone.network=vap_lan
del_list firewall.$wan_zone.network=vap_wan
commit firewall
EOF
local lan_dev=`find_uci_section network device name 'br-lan' | head -1`
[[ -z "$lan_dev" ]] || {
uci del_list "network.$lan_dev.ports=vap-lan"
}
uci -q batch <<-EOF >/dev/null
set network.vap_lan.auto=0
set network.vap_wan.auto=0
delete network.veth_lan_peer
delete network.veth_lan
commit network
EOF
}
start_service() {
config_load ap_modem
config_get_bool enabled "config" enabled 0
uci -q batch <<-EOF >/dev/null
delete network.vap_lan.ipaddr
delete network.vap_wan.ipaddr
commit network
EOF
if [[ "$enabled" = "1" ]]; then
generate_config
else
clean_config
fi
/etc/init.d/network reload
return 0
}
stop_service() {
clean_config
/etc/init.d/network reload
}