readonly packageLockFile="/var/run/${packageName}.lock"
readonly dnsmasqFileDefault="/var/dnsmasq.d/${packageName}"
readonly _OK_='\033[0;32m\xe2\x9c\x93\033[0m'
-readonly _FAIL_='\033[0;31m\xe2\x9c\x97\033[0m'
readonly __OK__='\033[0;32m[\xe2\x9c\x93]\033[0m'
+readonly _OKB_='\033[1;34m\xe2\x9c\x93\033[0m'
+readonly __OKB__='\033[1;34m[\xe2\x9c\x93]\033[0m'
+readonly _FAIL_='\033[0;31m\xe2\x9c\x97\033[0m'
readonly __FAIL__='\033[0;31m[\xe2\x9c\x97]\033[0m'
readonly _ERROR_='\033[0;31mERROR\033[0m'
readonly _WARNING_='\033[0;33mWARNING\033[0m'
readonly ssConfigFile='/etc/shadowsocks'
readonly torConfigFile='/etc/tor/torrc'
readonly xrayIfacePrefix='xray_'
+readonly rtTablesFile='/etc/iproute2/rt_tables'
# package config options
procd_boot_timeout=
output_ok() { output 1 "$_OK_"; output 2 "$__OK__\\n"; }
output_okn() { output 1 "$_OK_\\n"; output 2 "$__OK__\\n"; }
+output_okb() { output 1 "$_OKB_"; output 2 "$__OKB__\\n"; }
+output_okbn() { output 1 "$_OKB_\\n"; output 2 "$__OKB__\\n"; }
output_fail() { output 1 "$_FAIL_"; output 2 "$__FAIL__\\n"; }
output_failn() { output 1 "$_FAIL_\\n"; output 2 "$__FAIL__\\n"; }
# shellcheck disable=SC2317
is_lan() { local d; network_get_device d "$1"; str_contains "$d" 'br-lan'; }
is_l2tp() { local p; network_get_protocol p "$1"; [ "${p:0:4}" = "l2tp" ]; }
is_mac_address() { expr "$1" : '[0-9a-fA-F][0-9a-fA-F]:[0-9a-fA-F][0-9a-fA-F]:[0-9a-fA-F][0-9a-fA-F]:[0-9a-fA-F][0-9a-fA-F]:[0-9a-fA-F][0-9a-fA-F]:[0-9a-fA-F][0-9a-fA-F]$' >/dev/null; }
-is_netifd_table() { local iface="$1"; [ "$(uci_get 'network' "$iface" 'ip4table')" = "${packageName}_${iface%6}" ]; }
+is_netifd_table() { grep -q "ip.table.*$1" /etc/config/network; }
+is_netifd_table_interface() { local iface="$1"; [ "$(uci_get 'network' "$iface" 'ip4table')" = "${packageName}_${iface%6}" ]; }
is_oc() { local p; network_get_protocol p "$1"; [ "${p:0:11}" = "openconnect" ]; }
is_ovpn() { local d; uci_get_device d "$1"; [ "${d:0:3}" = "tun" ] || [ "${d:0:3}" = "tap" ] || [ -f "/sys/devices/virtual/net/${d}/tun_flags" ]; }
is_ovpn_valid() { local dev_net dev_ovpn; uci_get_device dev_net "$1"; dev_ovpn="$(uci_get 'openvpn' "$1" 'dev')"; [ -n "$dev_net" ] && [ -n "$dev_ovpn" ] && [ "$dev_net" = "$dev_ovpn" ]; }
# shellcheck disable=SC2155
get_tor_traffic_port() { local i="$(grep -m1 TransPort "$torConfigFile" | awk -F: '{print $2}')"; echo "${i:-9040}"; }
get_xray_traffic_port() { local i="${1//$xrayIfacePrefix}"; [ "$i" = "$1" ] && unset i; echo "$i"; }
-get_rt_tables_id() { local iface="$1"; grep "${ipTablePrefix}_${iface}\$" '/etc/iproute2/rt_tables' | awk '{print $1;}'; }
-get_rt_tables_next_id() { echo "$(($(sort -r -n '/etc/iproute2/rt_tables' | grep -o -E -m 1 "^[0-9]+")+1))"; }
-get_rt_tables_non_pbr_next_id() { echo "$(($(grep -v "${ipTablePrefix}_" '/etc/iproute2/rt_tables' | sort -r -n | grep -o -E -m 1 "^[0-9]+")+1))"; }
+get_rt_tables_id() { local iface="$1"; grep "${ipTablePrefix}_${iface}\$" "$rtTablesFile" | awk '{print $1;}'; }
+get_rt_tables_next_id() { echo "$(($(sort -r -n "$rtTablesFile" | grep -o -E -m 1 "^[0-9]+")+1))"; }
+get_rt_tables_non_pbr_next_id() { echo "$(($(grep -v "${ipTablePrefix}_" "$rtTablesFile" | sort -r -n | grep -o -E -m 1 "^[0-9]+")+1))"; }
# shellcheck disable=SC2016
resolveip_to_ipt() { resolveip "$@" | sed -n 'H;${x;s/\n/,/g;s/^,//;p;};d'; }
resolveip_to_ipt4() { resolveip_to_ipt -4 "$@"; }
errorResolverNotSupported) r="Resolver set (${resolver_set}) is not supported on this system!";;
errorServiceDisabled) r="The ${packageName} service is currently disabled!";;
errorNoWanGateway) r="The ${serviceName} service failed to discover WAN gateway!";;
+ errorNoWanInterface) r="The %s inteface not found, you need to set the 'pbr.config.procd_wan_interface' option!";;
+ errorNoWanInterfaceHint) r="Refer to https://docs.openwrt.melmac.net/pbr/#procd_wan_interface.";;
errorIpsetNameTooLong) r="The ipset name '%s' is longer than allowed 31 characters!";;
errorNftsetNameTooLong) r="The nft set name '%s' is longer than allowed 255 characters!";;
errorUnexpectedExit) r="Unexpected exit or service termination: '%s'!";;
errorPolicyProcessInsertionFailedIpv4) r="Insertion failed for IPv4 for policy '%s'!";;
errorInterfaceRoutingEmptyValues) r="Received empty tid/mark or interface name when setting up routing!";;
errorFailedToResolve) r="Failed to resolve '%s'!";;
+ errorTryFailed) r="Command failed: %s";;
errorNftFileInstall) r="Failed to install fw4 nft file '%s'!";;
errorDownloadUrlNoHttps) r="Failed to download '%s', HTTPS is not supported!";;
errorDownloadUrl) r="Failed to download '%s'!";;
load_network "$param"
[ "$procd_wan_ignore_status" -eq '0' ] || return 0
[ "$param" = 'on_boot' ] || procd_boot_timeout='1'
+ if [ -z "$(uci_get network "$procd_wan_interface")" ]; then
+ state add 'errorSummary' 'errorNoWanInterface' "$procd_wan_interface"
+ state add 'errorSummary' 'errorNoWanInterfaceHint'
+ return 1
+ fi
while [ -z "$wanGW" ] ; do
load_network "$param"
if [ $((sleepCount)) -gt $((procd_boot_timeout)) ] || [ -n "$wanGW" ]; then break; fi
fi
}
-cleanup_rt_tables() { sed -i "/${ipTablePrefix}_/d" '/etc/iproute2/rt_tables'; sync; }
+cleanup_rt_tables() {
+ local i
+# shellcheck disable=SC2013
+ for i in $(grep -oh "${ipTablePrefix}_.*" $rtTablesFile); do
+ ! is_netifd_table "$i" && sed -i "/${i}/d" "$rtTablesFile"
+ done
+ sync
+}
cleanup_main_chains() {
local i
fi
}
+try() {
+ if ! "$@"; then
+ state add 'errorSummary' 'errorTryFailed' "$*"
+ return 1
+ fi
+}
+
interface_routing() {
local action="$1" tid="$2" mark="$3" iface="$4" gw4="$5" dev="$6" gw6="$7" dev6="$8" priority="$9"
local dscp s=0 i ipv4_error=1 ipv6_error=1
fi
case "$action" in
create)
- if is_netifd_table "$iface"; then
+ if is_netifd_table_interface "$iface"; then
ipv4_error=0
$ip_bin rule del table "$tid" >/dev/null 2>&1
- $ip_bin -4 rule add fwmark "${mark}/${fw_mask}" table "$tid" priority "$priority" || ipv4_error=1
+ try "$ip_bin" -4 rule add fwmark "${mark}/${fw_mask}" table "$tid" priority "$priority" || ipv4_error=1
if is_nft_mode; then
- nft add chain inet "$nftTable" "${nftPrefix}_mark_${mark}" || ipv4_error=1
- nft add rule inet "$nftTable" "${nftPrefix}_mark_${mark} counter mark set mark and ${fw_maskXor} xor ${mark}" || ipv4_error=1
- nft add rule inet "$nftTable" "${nftPrefix}_mark_${mark} return" || ipv4_error=1
+ try nft add chain inet "$nftTable" "${nftPrefix}_mark_${mark}" || ipv4_error=1
+ try nft add rule inet "$nftTable" "${nftPrefix}_mark_${mark} counter mark set mark and ${fw_maskXor} xor ${mark}" || ipv4_error=1
+ try nft add rule inet "$nftTable" "${nftPrefix}_mark_${mark} return" || ipv4_error=1
else
ipt -t mangle -N "${iptPrefix}_MARK_${mark}" || ipv4_error=1
ipt -t mangle -A "${iptPrefix}_MARK_${mark}" -j MARK --set-xmark "${mark}/${fw_mask}" || ipv4_error=1
fi
if [ -n "$ipv6_enabled" ]; then
ipv6_error=0
- $ip_bin -6 rule add fwmark "${mark}/${fw_mask}" table "$tid" priority "$priority" || ipv6_error=1
+ try "$ip_bin" -6 rule add fwmark "${mark}/${fw_mask}" table "$tid" priority "$priority" || ipv6_error=1
fi
else
- if ! grep -q "$tid ${ipTablePrefix}_${iface}" '/etc/iproute2/rt_tables'; then
- sed -i "/${ipTablePrefix}_${iface}/d" '/etc/iproute2/rt_tables'
+ if ! grep -q "$tid ${ipTablePrefix}_${iface}" "$rtTablesFile"; then
+ sed -i "/${ipTablePrefix}_${iface}/d" "$rtTablesFile"
sync
- echo "$tid ${ipTablePrefix}_${iface}" >> '/etc/iproute2/rt_tables'
+ echo "$tid ${ipTablePrefix}_${iface}" >> "$rtTablesFile"
sync
fi
$ip_bin rule del table "$tid" >/dev/null 2>&1
if [ -n "$gw4" ] || [ "$strict_enforcement" -ne 0 ]; then
ipv4_error=0
if [ -z "$gw4" ]; then
- $ip_bin -4 route add unreachable default table "$tid" >/dev/null 2>&1 || ipv4_error=1
+ try "$ip_bin" -4 route add unreachable default table "$tid" >/dev/null 2>&1 || ipv4_error=1
else
- $ip_bin -4 route add default via "$gw4" dev "$dev" table "$tid" >/dev/null 2>&1 || ipv4_error=1
+ try "$ip_bin" -4 route add default via "$gw4" dev "$dev" table "$tid" >/dev/null 2>&1 || ipv4_error=1
fi
# shellcheck disable=SC2086
while read -r i; do
i="$(echo "$i" | sed 's/ onlink$//')"
idev="$(echo "$i" | grep -Eso 'dev [^ ]*' | awk '{print $2}')"
if ! is_supported_iface_dev "$idev"; then
- $ip_bin -4 route add $i table "$tid" >/dev/null 2>&1 || ipv4_error=1
+ try "$ip_bin" -4 route add $i table "$tid" >/dev/null 2>&1 || ipv4_error=1
fi
done << EOF
$($ip_bin -4 route list table main)
EOF
- $ip_bin -4 rule add fwmark "${mark}/${fw_mask}" table "$tid" priority "$priority" || ipv4_error=1
+ try "$ip_bin" -4 rule add fwmark "${mark}/${fw_mask}" table "$tid" priority "$priority" || ipv4_error=1
if is_nft_mode; then
- nft add chain inet "$nftTable" "${nftPrefix}_mark_${mark}" || ipv4_error=1
- nft add rule inet "$nftTable" "${nftPrefix}_mark_${mark} counter mark set mark and ${fw_maskXor} xor ${mark}" || ipv4_error=1
- nft add rule inet "$nftTable" "${nftPrefix}_mark_${mark} return" || ipv4_error=1
+ try nft add chain inet "$nftTable" "${nftPrefix}_mark_${mark}" || ipv4_error=1
+ try nft add rule inet "$nftTable" "${nftPrefix}_mark_${mark} counter mark set mark and ${fw_maskXor} xor ${mark}" || ipv4_error=1
+ try nft add rule inet "$nftTable" "${nftPrefix}_mark_${mark} return" || ipv4_error=1
else
ipt -t mangle -N "${iptPrefix}_MARK_${mark}" || ipv4_error=1
ipt -t mangle -A "${iptPrefix}_MARK_${mark}" -j MARK --set-xmark "${mark}/${fw_mask}" || ipv4_error=1
ipv6_error=0
if { [ -n "$gw6" ] && [ "$gw6" != "::/0" ]; } || [ "$strict_enforcement" -ne 0 ]; then
if [ -z "$gw6" ] || [ "$gw6" = "::/0" ]; then
- $ip_bin -6 route add unreachable default table "$tid" >/dev/null 2>&1 || ipv6_error=1
- elif $ip_bin -6 route list table main | grep -q " dev $dev6 "; then
- $ip_bin -6 route add default via "$gw6" dev "$dev6" table "$tid" >/dev/null 2>&1 || ipv6_error=1
+ try "$ip_bin" -6 route add unreachable default table "$tid" >/dev/null 2>&1 || ipv6_error=1
+ elif try "$ip_bin" -6 route list table main | grep -q " dev $dev6 "; then
+ try "$ip_bin" -6 route add default via "$gw6" dev "$dev6" table "$tid" >/dev/null 2>&1 || ipv6_error=1
while read -r i; do
i="$(echo "$i" | sed 's/ linkdown$//')"
i="$(echo "$i" | sed 's/ onlink$//')"
# shellcheck disable=SC2086
- $ip_bin -6 route add $i table "$tid" >/dev/null 2>&1 || ipv6_error=1
+ try "$ip_bin" -6 route add $i table "$tid" >/dev/null 2>&1 || ipv6_error=1
done << EOF
$($ip_bin -6 route list table main | grep " dev $dev6 ")
EOF
else
- $ip_bin -6 route add "$($ip_bin -6 -o a show "$dev6" | awk '{print $4}')" dev "$dev6" table "$tid" >/dev/null 2>&1 || ipv6_error=1
- $ip_bin -6 route add default dev "$dev6" table "$tid" >/dev/null 2>&1 || ipv6_error=1
+ try "$ip_bin" -6 route add "$($ip_bin -6 -o a show "$dev6" | awk '{print $4}')" dev "$dev6" table "$tid" >/dev/null 2>&1 || ipv6_error=1
+ try "$ip_bin" -6 route add default dev "$dev6" table "$tid" >/dev/null 2>&1 || ipv6_error=1
fi
fi
- $ip_bin -6 rule add fwmark "${mark}/${fw_mask}" table "$tid" priority "$priority" >/dev/null 2>&1 || ipv6_error=1
+ try "$ip_bin" -6 rule add fwmark "${mark}/${fw_mask}" table "$tid" priority "$priority" >/dev/null 2>&1 || ipv6_error=1
fi
fi
if [ "$ipv4_error" -eq 0 ] || [ "$ipv6_error" -eq 0 ]; then
dscp="$(uci_get "$packageName" 'config' "${iface}_dscp")"
if is_nft_mode; then
if [ "${dscp:-0}" -ge 1 ] && [ "${dscp:-0}" -le 63 ]; then
- nft add rule inet "$nftTable" "${nftPrefix}_prerouting ${nftIPv4Flag} dscp ${dscp} goto ${nftPrefix}_mark_${mark}" || s=1
+ try nft add rule inet "$nftTable" "${nftPrefix}_prerouting ${nftIPv4Flag} dscp ${dscp} goto ${nftPrefix}_mark_${mark}" || s=1
if [ -n "$ipv6_enabled" ]; then
- nft add rule inet "$nftTable" "${nftPrefix}_prerouting ${nftIPv6Flag} dscp ${dscp} goto ${nftPrefix}_mark_${mark}" || s=1
+ try nft add rule inet "$nftTable" "${nftPrefix}_prerouting ${nftIPv6Flag} dscp ${dscp} goto ${nftPrefix}_mark_${mark}" || s=1
fi
fi
if [ "$iface" = "$icmp_interface" ]; then
- nft add rule inet "$nftTable" "${nftPrefix}_output ${nftIPv4Flag} protocol icmp goto ${nftPrefix}_mark_${mark}" || s=1
+ try nft add rule inet "$nftTable" "${nftPrefix}_output ${nftIPv4Flag} protocol icmp goto ${nftPrefix}_mark_${mark}" || s=1
if [ -n "$ipv6_enabled" ]; then
- nft add rule inet "$nftTable" "${nftPrefix}_output ${nftIPv6Flag} protocol icmp goto ${nftPrefix}_mark_${mark}" || s=1
+ try nft add rule inet "$nftTable" "${nftPrefix}_output ${nftIPv6Flag} protocol icmp goto ${nftPrefix}_mark_${mark}" || s=1
fi
fi
else
;;
delete|destroy)
$ip_bin rule del table "$tid" >/dev/null 2>&1
- if ! is_netifd_table "$iface"; then
+ if ! is_netifd_table_interface "$iface"; then
$ip_bin route flush table "$tid" >/dev/null 2>&1
- sed -i "/${ipTablePrefix}_${iface}\$/d" '/etc/iproute2/rt_tables'
+ sed -i "/${ipTablePrefix}_${iface}\$/d" "$rtTablesFile"
sync
fi
return "$s"
;;
reload_interface)
- is_netifd_table "$iface" && return 0;
+ is_netifd_table_interface "$iface" && return 0;
ipv4_error=0
$ip_bin rule del table "$tid" >/dev/null 2>&1
- if ! is_netifd_table "$iface"; then
+ if ! is_netifd_table_interface "$iface"; then
$ip_bin route flush table "$tid" >/dev/null 2>&1
fi
if [ -n "$gw4" ] || [ "$strict_enforcement" -ne 0 ]; then
if [ -z "$gw4" ]; then
- $ip_bin -4 route add unreachable default table "$tid" >/dev/null 2>&1 || ipv4_error=1
+ try "$ip_bin" -4 route add unreachable default table "$tid" >/dev/null 2>&1 || ipv4_error=1
else
- $ip_bin -4 route add default via "$gw4" dev "$dev" table "$tid" >/dev/null 2>&1 || ipv4_error=1
+ try "$ip_bin" -4 route add default via "$gw4" dev "$dev" table "$tid" >/dev/null 2>&1 || ipv4_error=1
fi
- $ip_bin rule add fwmark "${mark}/${fw_mask}" table "$tid" priority "$priority" || ipv4_error=1
+ try "$ip_bin" rule add fwmark "${mark}/${fw_mask}" table "$tid" priority "$priority" || ipv4_error=1
fi
if [ -n "$ipv6_enabled" ]; then
ipv6_error=0
if { [ -n "$gw6" ] && [ "$gw6" != "::/0" ]; } || [ "$strict_enforcement" -ne 0 ]; then
if [ -z "$gw6" ] || [ "$gw6" = "::/0" ]; then
- $ip_bin -6 route add unreachable default table "$tid" || ipv6_error=1
+ try "$ip_bin" -6 route add unreachable default table "$tid" || ipv6_error=1
elif $ip_bin -6 route list table main | grep -q " dev $dev6 "; then
while read -r i; do
# shellcheck disable=SC2086
- $ip_bin -6 route add $i table "$tid" >/dev/null 2>&1 || ipv6_error=1
+ try "$ip_bin" -6 route add $i table "$tid" >/dev/null 2>&1 || ipv6_error=1
done << EOF
$($ip_bin -6 route list table main | grep " dev $dev6 ")
EOF
else
- $ip_bin -6 route add "$($ip_bin -6 -o a show "$dev6" | awk '{print $4}')" dev "$dev6" table "$tid" >/dev/null 2>&1 || ipv6_error=1
- $ip_bin -6 route add default dev "$dev6" table "$tid" >/dev/null 2>&1 || ipv6_error=1
+ try "$ip_bin" -6 route add "$($ip_bin -6 -o a show "$dev6" | awk '{print $4}')" dev "$dev6" table "$tid" >/dev/null 2>&1 || ipv6_error=1
+ try "$ip_bin" -6 route add default dev "$dev6" table "$tid" >/dev/null 2>&1 || ipv6_error=1
fi
fi
- $ip_bin -6 rule add fwmark "${mark}/${fw_mask}" table "$tid" priority "$priority" || ipv6_error=1
+ try "$ip_bin" -6 rule add fwmark "${mark}/${fw_mask}" table "$tid" priority "$priority" || ipv6_error=1
fi
if [ "$ipv4_error" -eq 0 ] || [ "$ipv6_error" -eq 0 ]; then
s=0
[ -z "$ifaceMark" ] && ifaceMark="$(printf '0x%06x' "$wan_mark")"
[ -z "$ifacePriority" ] && ifacePriority="$wan_ip_rules_priority"
- if [ "$action" = 'pre-init' ]; then
- pbr_get_gateway6 gw6 "$iface" "$dev6"
- [ -n "$gw6" ] && ipv6_enabled=1
- [ -z "$ifaceTableID" ] && ifaceTableID="$(get_rt_tables_non_pbr_next_id)"
- eval "pre_init_mark_${iface//-/_}"='$ifaceMark'
- eval "pre_init_priority_${iface//-/_}"='$ifacePriority'
- eval "pre_init_tid_${iface//-/_}"='$ifaceTableID'
- ifaceMark="$(printf '0x%06x' $((ifaceMark + wan_mark)))"
- ifacePriority="$((ifacePriority + 1))"
- ifaceTableID="$((ifaceTableID + 1))"
- return 0
- fi
-
-# TODO: if interfaces are started out of order the rt_tables ID may be incorrect
-# use the expected_tid_${iface} ???
- ifaceTableID="$(get_rt_tables_id "$iface")"
- [ -z "$ifaceTableID" ] && ifaceTableID="$(get_rt_tables_next_id)"
- eval "mark_${iface//-/_}"='$ifaceMark'
- eval "tid_${iface//-/_}"='$ifaceTableID'
- pbr_get_gateway gw4 "$iface" "$dev"
- pbr_get_gateway6 gw6 "$iface" "$dev6"
- dispGw4="${gw4:-0.0.0.0}"
- dispGw6="${gw6:-::/0}"
- [ "$iface" != "$dev" ] && dispDev="$dev"
- if is_default_dev "$dev"; then
- [ "$verbosity" = '1' ] && dispStatus="$_OK_" || dispStatus="$__OK__"
- fi
- displayText="${iface}/${dispDev:+$dispDev/}${dispGw4}${ipv6_enabled:+/$dispGw6}"
-
case "$action" in
+ pre_init)
+ [ -z "$ifaceTableID" ] && ifaceTableID="$(get_rt_tables_non_pbr_next_id)"
+ eval "pre_init_mark_${iface//-/_}"='$ifaceMark'
+ eval "pre_init_priority_${iface//-/_}"='$ifacePriority'
+ eval "pre_init_tid_${iface//-/_}"='$ifaceTableID'
+ ifaceMark="$(printf '0x%06x' $((ifaceMark + wan_mark)))"
+ ifacePriority="$((ifacePriority - 1))"
+ ifaceTableID="$((ifaceTableID + 1))"
+ return 0
+ ;;
create)
+ ifaceTableID="$(get_rt_tables_id "$iface")"
+ [ -z "$ifaceTableID" ] && ifaceTableID="$(get_rt_tables_next_id)"
+ eval "mark_${iface//-/_}"='$ifaceMark'
+ eval "tid_${iface//-/_}"='$ifaceTableID'
+ pbr_get_gateway gw4 "$iface" "$dev"
+ pbr_get_gateway6 gw6 "$iface" "$dev6"
+ dispGw4="${gw4:-0.0.0.0}"
+ dispGw6="${gw6:-::/0}"
+ [ "$iface" != "$dev" ] && dispDev="$dev"
+ if is_default_dev "$dev"; then
+ [ "$verbosity" = '1' ] && dispStatus="$_OK_" || dispStatus="$__OK__"
+ fi
+ displayText="${iface}/${dispDev:+$dispDev/}${dispGw4}${ipv6_enabled:+/$dispGw6}"
output 2 "Setting up routing for '$displayText' "
if interface_routing 'create' "$ifaceTableID" "$ifaceMark" "$iface" "$gw4" "$dev" "$gw6" "$dev6" "$ifacePriority"; then
json_add_gateway 'create' "$ifaceTableID" "$ifaceMark" "$iface" "$gw4" "$dev" "$gw6" "$dev6" "$ifacePriority" "$dispStatus"
gatewaySummary="${gatewaySummary}${displayText}${dispStatus:+ $dispStatus}\\n"
- output_ok
+ if is_netifd_table_interface "$iface"; then output_okb; else output_ok; fi
else
state add 'errorSummary' 'errorFailedSetup' "$displayText"
output_fail
fi
;;
create_user_set)
+ ifaceTableID="$(get_rt_tables_id "$iface")"
+ [ -z "$ifaceTableID" ] && ifaceTableID="$(get_rt_tables_next_id)"
+ eval "mark_${iface//-/_}"='$ifaceMark'
+ eval "tid_${iface//-/_}"='$ifaceTableID'
+ pbr_get_gateway gw4 "$iface" "$dev"
+ pbr_get_gateway6 gw6 "$iface" "$dev6"
+ dispGw4="${gw4:-0.0.0.0}"
+ dispGw6="${gw6:-::/0}"
+ [ "$iface" != "$dev" ] && dispDev="$dev"
+ if is_default_dev "$dev"; then
+ [ "$verbosity" = '1' ] && dispStatus="$_OK_" || dispStatus="$__OK__"
+ fi
+ displayText="${iface}/${dispDev:+$dispDev/}${dispGw4}${ipv6_enabled:+/$dispGw6}"
interface_routing 'create_user_set' "$ifaceTableID" "$ifaceMark" "$iface" "$gw4" "$dev" "$gw6" "$dev6" "$ifacePriority"
;;
destroy)
+ ifaceTableID="$(get_rt_tables_id "$iface")"
+ [ -z "$ifaceTableID" ] && ifaceTableID="$(get_rt_tables_next_id)"
+ eval "mark_${iface//-/_}"='$ifaceMark'
+ eval "tid_${iface//-/_}"='$ifaceTableID'
+ pbr_get_gateway gw4 "$iface" "$dev"
+ pbr_get_gateway6 gw6 "$iface" "$dev6"
+ dispGw4="${gw4:-0.0.0.0}"
+ dispGw6="${gw6:-::/0}"
+ [ "$iface" != "$dev" ] && dispDev="$dev"
+ if is_default_dev "$dev"; then
+ [ "$verbosity" = '1' ] && dispStatus="$_OK_" || dispStatus="$__OK__"
+ fi
+ displayText="${iface}/${dispDev:+$dispDev/}${dispGw4}${ipv6_enabled:+/$dispGw6}"
displayText="${iface}/${dispDev:+$dispDev/}${dispGw4}${ipv6_enabled:+/$dispGw6}"
output 2 "Removing routing for '$displayText' "
interface_routing 'destroy' "${ifaceTableID}" "${ifaceMark}" "${iface}"
- output_ok
+ if is_netifd_table_interface "$iface"; then output_okb; else output_ok; fi
;;
reload)
+ ifaceTableID="$(get_rt_tables_id "$iface")"
+ [ -z "$ifaceTableID" ] && ifaceTableID="$(get_rt_tables_next_id)"
+ eval "mark_${iface//-/_}"='$ifaceMark'
+ eval "tid_${iface//-/_}"='$ifaceTableID'
+ pbr_get_gateway gw4 "$iface" "$dev"
+ pbr_get_gateway6 gw6 "$iface" "$dev6"
+ dispGw4="${gw4:-0.0.0.0}"
+ dispGw6="${gw6:-::/0}"
+ [ "$iface" != "$dev" ] && dispDev="$dev"
+ if is_default_dev "$dev"; then
+ [ "$verbosity" = '1' ] && dispStatus="$_OK_" || dispStatus="$__OK__"
+ fi
+ displayText="${iface}/${dispDev:+$dispDev/}${dispGw4}${ipv6_enabled:+/$dispGw6}"
gatewaySummary="${gatewaySummary}${displayText}${dispStatus:+ $dispStatus}\\n"
;;
reload_interface)
+ ifaceTableID="$(get_rt_tables_id "$iface")"
+ [ -z "$ifaceTableID" ] && ifaceTableID="$(get_rt_tables_next_id)"
+ eval "mark_${iface//-/_}"='$ifaceMark'
+ eval "tid_${iface//-/_}"='$ifaceTableID'
+ pbr_get_gateway gw4 "$iface" "$dev"
+ pbr_get_gateway6 gw6 "$iface" "$dev6"
+ dispGw4="${gw4:-0.0.0.0}"
+ dispGw6="${gw6:-::/0}"
+ [ "$iface" != "$dev" ] && dispDev="$dev"
+ if is_default_dev "$dev"; then
+ [ "$verbosity" = '1' ] && dispStatus="$_OK_" || dispStatus="$__OK__"
+ fi
+ displayText="${iface}/${dispDev:+$dispDev/}${dispGw4}${ipv6_enabled:+/$dispGw6}"
if [ "$iface" = "$reloadedIface" ]; then
output 2 "Reloading routing for '$displayText' "
if interface_routing 'reload_interface' "$ifaceTableID" "$ifaceMark" "$iface" "$gw4" "$dev" "$gw6" "$dev6" "$ifacePriority"; then
json_add_gateway 'reload_interface' "$ifaceTableID" "$ifaceMark" "$iface" "$gw4" "$dev" "$gw6" "$dev6" "$ifacePriority" "$dispStatus"
gatewaySummary="${gatewaySummary}${displayText}${dispStatus:+ $dispStatus}\\n"
- output_ok
+ if is_netifd_table_interface "$iface"; then output_okb; else output_ok; fi
else
state add 'errorSummary' 'errorFailedReload' "$displayText"
output_fail
esac
# ifaceTableID="$((ifaceTableID + 1))"
ifaceMark="$(printf '0x%06x' $((ifaceMark + wan_mark)))"
- ifacePriority="$((ifacePriority + 1))"
+ ifacePriority="$((ifacePriority - 1))"
return $s
}
is_wan_up "$param" || return 1
interface_process 'all' 'prepare'
- config_foreach interface_process 'interface' 'pre-init'
+ config_foreach interface_process 'interface' 'pre_init'
case "$param" in
on_boot)
# echo "$_SEPARATOR_"
# ip rule list | grep "${packageName}_"
echo "$_SEPARATOR_"
- tableCount="$(grep -c "${packageName}_" /etc/iproute2/rt_tables)" || tableCount=0
+ tableCount="$(grep -c "${packageName}_" $rtTablesFile)" || tableCount=0
wan_tid=$(($(get_rt_tables_next_id)-tableCount))
i=0; while [ $i -lt "$tableCount" ]; do
echo "IPv4 table $((wan_tid + i)) route: $($ip_bin -4 route show table $((wan_tid + i)) | grep default)"
echo "$_SEPARATOR_"
echo "Routes/IP Rules"
- tableCount="$(grep -c "${packageName}_" /etc/iproute2/rt_tables)" || tableCount=0
+ tableCount="$(grep -c "${packageName}_" $rtTablesFile)" || tableCount=0
if [ -n "$set_d" ]; then route; else route | grep '^default'; fi
if [ -n "$set_d" ]; then ip rule list; fi
wan_tid=$(($(get_rt_tables_next_id)-tableCount))
+++ /dev/null
-#!/bin/sh /etc/rc.common
-# Copyright 2020-2022 Stan Grishin (stangri@melmac.ca)
-# shellcheck disable=SC1091,SC2018,SC2019,SC3043,SC3057,SC3060
-
-# sysctl net.ipv4.conf.default.rp_filter=1
-# sysctl net.ipv4.conf.all.rp_filter=1
-
-# shellcheck disable=SC2034
-START=94
-# shellcheck disable=SC2034
-USE_PROCD=1
-
-if type extra_command >/dev/null 2>&1; then
- extra_command 'status' "Generates output required to troubleshoot routing issues
- Use '-d' option for more detailed output
- Use '-p' option to automatically upload data under VPR paste.ee account
- WARNING: while paste.ee uploads are unlisted, they are still publicly available
- List domain names after options to include their lookup in report"
- extra_command 'version' 'Show version information'
- extra_command 'on_firewall_reload' ' Run service on firewall reload'
- extra_command 'on_interface_reload' ' Run service on indicated interface reload'
-else
-# shellcheck disable=SC2034
- EXTRA_COMMANDS='on_firewall_reload on_interface_reload status version'
-# shellcheck disable=SC2034
- EXTRA_HELP=" status Generates output required to troubleshoot routing issues
- Use '-d' option for more detailed output
- Use '-p' option to automatically upload data under VPR paste.ee account
- WARNING: while paste.ee uploads are unlisted, they are still publicly available
- List domain names after options to include their lookup in report"
-fi
-
-readonly PKG_VERSION='dev-test'
-readonly packageName='pbr'
-readonly serviceName="$packageName $PKG_VERSION"
-readonly serviceTrapSignals='exit SIGHUP SIGQUIT SIGKILL'
-readonly packageConfigFile="/etc/config/${packageName}"
-readonly packageLockFile="/var/run/${packageName}.lock"
-readonly nftTempFile="/var/run/${packageName}.nft"
-#readonly nftPermFile="/etc/nftables.d/table-post/30-pbr.nft"
-readonly dnsmasqFile="/var/dnsmasq.d/${packageName}"
-readonly _OK_='\033[0;32m\xe2\x9c\x93\033[0m'
-readonly _FAIL_='\033[0;31m\xe2\x9c\x97\033[0m'
-readonly __OK__='\033[0;32m[\xe2\x9c\x93]\033[0m'
-readonly __FAIL__='\033[0;31m[\xe2\x9c\x97]\033[0m'
-readonly _ERROR_='\033[0;31mERROR\033[0m'
-readonly _WARNING_='\033[0;33mWARNING\033[0m'
-readonly ip_full='/usr/libexec/ip-full'
-# shellcheck disable=SC2155
-readonly ip_bin="$(command -v ip)"
-readonly ipTablePrefix='pbr'
-# shellcheck disable=SC2155
-readonly iptables="$(command -v iptables)"
-# shellcheck disable=SC2155
-readonly ip6tables="$(command -v ip6tables)"
-# shellcheck disable=SC2155
-readonly ipset="$(command -v ipset)"
-readonly ipsPrefix='pbr'
-readonly iptPrefix='PBR'
-# shellcheck disable=SC2155
-readonly agh="$(command -v AdGuardHome)"
-readonly aghConfigFile='/etc/adguardhome.yaml'
-readonly aghIpsetFile="/var/run/${packageName}.adguardhome.ipsets"
-# shellcheck disable=SC2155
-readonly nft="$(command -v nft)"
-readonly nftTable="fw4"
-readonly nftPrefix='pbr'
-readonly chainsList='forward input output postrouting prerouting'
-
-# package config options
-boot_timeout=
-enabled=
-fw_mask=
-icmp_interface=
-ignored_interface=
-ipv6_enabled=
-nft_user_set_policy=
-nft_user_set_counter=
-procd_boot_delay=
-procd_reload_delay=
-resolver_set=
-rule_create_option=
-secure_reload=
-strict_enforcement=
-supported_interface=
-verbosity=
-wan_ip_rules_priority=
-wan_mark=
-
-# run-time
-gatewaySummary=
-errorSummary=
-warningSummary=
-wanIface4=
-wanIface6=
-ifaceMark=
-ifaceTableID=
-ifacePriority=
-ifacesAll=
-ifacesSupported=
-firewallWanZone=
-wanGW4=
-wanGW6=
-serviceStartTrigger=
-processPolicyError=
-processPolicyWarning=
-resolver_set_supported=
-nftPrevParam4=
-nftPrevParam6=
-
-get_text() {
- local r
- case "$1" in
- errorConfigValidation) r="Config ($packageConfigFile) validation failure!";;
- errorNoIpFull) r="ip-full binary cannot be found!";;
- errorNoIptables) r="iptables binary cannot be found!";;
- errorNoIpset) r="Resolver set support (${resolver_set}) requires ipset, but ipset binary cannot be found!";;
- errorNoNft) r="Resolver set support (${resolver_set}) requires nftables, but nft binary cannot be found!";;
- errorResolverNotSupported) r="Resolver set (${resolver_set}) is not supported on this system!";;
- errorServiceDisabled) r="The ${packageName} service is currently disabled!";;
- errorNoWanGateway) r="The ${serviceName} service failed to discover WAN gateway!";;
- errorIpsetNameTooLong) r="The ipset name '%s' is longer than allowed 31 characters!";;
- errorNftsetNameTooLong) r="The nft set name '%s' is longer than allowed 31 characters!";;
- errorUnexpectedExit) r="Unexpected exit or service termination: '%s'!";;
- errorPolicyNoSrcDest) r="Policy '%s' has no source/destination parameters!";;
- errorPolicyNoInterface) r="Policy '%s' has no assigned interface!";;
- errorPolicyUnknownInterface) r="Policy '%s' has an unknown interface!";;
- errorPolicyProcessCMD) r="'%s'!";;
- errorFailedSetup) r="Failed to set up '%s'!";;
- errorFailedReload) r="Failed to reload '%s'!";;
- errorUserFileNotFound) r="Custom user file '%s' not found or empty!";;
- errorUserFileSyntax) r="Syntax error in custom user file '%s'!";;
- errorUserFileRunning) r="Error running custom user file '%s'!";;
- errorUserFileNoCurl) r="Use of 'curl' is detected in custom user file '%s', but 'curl' isn't installed!";;
- errorNoGateways) r="Failed to set up any gateway!";;
- errorResolver) r="Resolver '%s'!";;
- errorPolicyProcessNoIpv6) r="Skipping IPv6 policy '%s' as IPv6 support is disabled!";;
- errorPolicyProcessUnknownFwmark) r="Unknown packet mark for interface '%s'!";;
- errorPolicyProcessMismatchFamily) r="Mismatched IP family between in policy '%s'!";;
- errorPolicyProcessUnknownProtocol) r="Unknown protocol in policy '%s'!";;
- errorPolicyProcessInsertionFailed) r="Insertion failed for both IPv4 and IPv6 for policy '%s'!";;
- errorPolicyProcessInsertionFailedIpv4) r="Insertion failed for IPv4 for policy '%s'!";;
- errorInterfaceRoutingEmptyValues) r="Received empty tid/mark or interface name when setting up routing!";;
- errorFailedToResolve) r="Failed to resolve '%s'!";;
- warningInvalidOVPNConfig) r="Invalid OpenVPN config for '%s' interface.";;
- warningResolverNotSupported) r="Resolver set (${resolver_set}) is not supported on this system.";;
- warningAGHVersionTooLow) r="Installed AdGuardHome ('%s') doesn't support 'ipset_file' option.";;
- warningPolicyProcessCMD) r="'%s'";;
- warningTorUnsetParams) r="Please unset 'src_addr', 'src_port' and 'dest_port' for policy '%s'.";;
- warningTorUnsetProto) r="Please unset 'proto' or set 'proto' to 'all' for policy '%s'.";;
- warningTorUnsetChainIpt) r="Please unset 'chain' or set 'chain' to 'PREROUTING' for policy '%s'.";;
- warningTorUnsetChainNft) r="Please unset 'chain' or set 'chain' to 'prerouting' for policy '%s'.";;
- warningOutdatedWebUIApp) r="The WebUI application is outdated (version %s), please update it.";;
- esac
- echo "$r"
-}
-
-version() { echo "$PKG_VERSION"; }
-output_ok() { output 1 "$_OK_"; output 2 "$__OK__\\n"; }
-output_okn() { output 1 "$_OK_\\n"; output 2 "$__OK__\\n"; }
-output_fail() { s=1; output 1 "$_FAIL_"; output 2 "$__FAIL__\\n"; }
-output_failn() { output 1 "$_FAIL_\\n"; output 2 "$__FAIL__\\n"; }
-# shellcheck disable=SC2317
-str_replace() { printf "%b" "$1" | sed -e "s/$(printf "%b" "$2")/$(printf "%b" "$3")/g"; }
-str_replace() { echo "${1//$2/$3}"; }
-str_contains() { [ -n "$1" ] && [ -n "$2" ] && [ "${1//$2}" != "$1" ]; }
-is_greater() { test "$(printf '%s\n' "$@" | sort -V | head -n 1)" != "$1"; }
-is_greater_or_equal() { test "$(printf '%s\n' "$@" | sort -V | head -n 1)" = "$2"; }
-str_contains_word() { echo "$1" | grep -q -w "$2"; }
-str_to_lower() { echo "$1" | tr 'A-Z' 'a-z'; }
-str_to_upper() { echo "$1" | tr 'a-z' 'A-Z'; }
-str_extras_to_underscore() { echo "$1" | tr '[\. ~`!@#$%^&*()\+/,<>?//;:]' '_'; }
-str_extras_to_space() { echo "$1" | tr ';{}' ' '; }
-debug() { local i j; for i in "$@"; do eval "j=\$$i"; echo "${i}: ${j} "; done; }
-output() {
-# Can take a single parameter (text) to be output at any verbosity
-# Or target verbosity level and text to be output at specifc verbosity
- local msg memmsg logmsg
- local sharedMemoryOutput="/dev/shm/$packageName-output"
- verbosity="${verbosity:-2}"
- if [ "$#" -ne 1 ]; then
- if [ $((verbosity & $1)) -gt 0 ] || [ "$verbosity" = "$1" ]; then shift; else return 0; fi
- fi
- [ -t 1 ] && printf "%b" "$1"
- msg="${1//$serviceName /service }";
- if [ "$(printf "%b" "$msg" | wc -l)" -gt 0 ]; then
- [ -s "$sharedMemoryOutput" ] && memmsg="$(cat "$sharedMemoryOutput")"
- logmsg="$(printf "%b" "${memmsg}${msg}" | sed 's/\x1b\[[0-9;]*m//g')"
- logger -t "${packageName:-service}" "$(printf "%b" "$logmsg")"
- rm -f "$sharedMemoryOutput"
- else
- printf "%b" "$msg" >> "$sharedMemoryOutput"
- fi
-}
-is_present() { command -v "$1" >/dev/null 2>&1; }
-is_installed() { [ -s "/usr/lib/opkg/info/${1}.control" ]; }
-is_variant_installed() { [ "$(echo /usr/lib/opkg/info/"${1}"*.control)" != "/usr/lib/opkg/info/${1}*.control" ]; }
-is_nft() { [ -x "$nft" ] && ! str_contains "$resolver_set" 'ipset' && "$nft" list chains inet | grep -q "${nftPrefix}_prerouting"; }
-_find_firewall_wan_zone() { [ "$(uci -q get "firewall.${1}.name")" = "wan" ] && firewallWanZone="$1"; }
-_build_ifaces_all() { ifacesAll="${ifacesAll}${1} "; }
-_build_ifaces_supported() { is_supported_interface "$1" && ! str_contains "$ifacesSupported" "$1" && ifacesSupported="${ifacesSupported}${1} "; }
-pbr_find_iface() {
- local iface i param="$2"
- [ "$param" = 'wan6' ] || param='wan'
- "network_find_${param}" iface
- is_tunnel "$iface" && unset iface
- if [ -z "$iface" ]; then
- for i in $ifacesAll; do
- if "is_${param}" "$i"; then break; else unset i; fi
- done
- fi
- eval "$1"='${iface:-$i}'
-}
-pbr_get_gateway() {
- local iface="$2" dev="$3" gw
- network_get_gateway gw "$iface" true
- if [ -z "$gw" ] || [ "$gw" = '0.0.0.0' ]; then
-# gw="$(ubus call "network.interface.${iface}" status | jsonfilter -e "@.route[0].nexthop")"
- gw="$($ip_bin -4 a list dev "$dev" 2>/dev/null | grep inet | awk '{print $2}' | awk -F "/" '{print $1}')"
- fi
- eval "$1"='$gw'
-}
-pbr_get_gateway6() {
- local iface="$2" dev="$3" gw
- network_get_gateway6 gw "$iface" true
- if [ -z "$gw" ] || [ "$gw" = '::/0' ] || [ "$gw" = '::0/0' ] || [ "$gw" = '::' ]; then
- gw="$($ip_bin -6 a list dev "$dev" 2>/dev/null | grep inet6 | grep 'scope global' | awk '{print $2}')"
- fi
- eval "$1"='$gw'
-}
-is_dslite() { local proto; proto=$(uci -q get network."$1".proto); [ "${proto:0:6}" = "dslite" ]; }
-is_l2tp() { local proto; proto=$(uci -q get network."$1".proto); [ "${proto:0:4}" = "l2tp" ]; }
-is_oc() { local proto; proto=$(uci -q get network."$1".proto); [ "${proto:0:11}" = "openconnect" ]; }
-# is_ovpn() { local dev; network_get_device dev "$1"; [ "${dev:0:3}" = "tun" ] || [ "${dev:0:3}" = "tap" ] || [ -f "/sys/devices/virtual/net/${dev}/tun_flags" ]; }
-is_ovpn() { local dev; dev="$(uci -q get "network.${1}.device")"; [ -z "$dev" ] && dev="$(uci -q get "network.${1}.dev")"; [ "${dev:0:3}" = "tun" ] || [ "${dev:0:3}" = "tap" ] || [ -f "/sys/devices/virtual/net/${dev}/tun_flags" ]; }
-is_valid_ovpn() { local dev_net dev_ovpn; dev_net="$(uci -q get "network.${1}.device")"; [ -z "$dev_net" ] && dev_net="$(uci -q get "network.${1}.dev")"; dev_ovpn="$(uci -q get "openvpn.${1}.dev")"; [ -n "$dev_net" ] && [ -n "$dev_ovpn" ] && [ "$dev_net" = "$dev_ovpn" ]; }
-is_pptp() { local proto; proto=$(uci -q get network."$1".proto); [ "${proto:0:4}" = "pptp" ]; }
-is_softether() { local dev; network_get_device dev "$1"; [ "${dev:0:4}" = "vpn_" ]; }
-is_tor() { [ "$(str_to_lower "$1")" = "tor" ]; }
-is_tor_running() {
- local ret=0
- if [ -s "/etc/tor/torrc" ]; then
- json_load "$(ubus call service list "{ 'name': 'tor' }")"
- json_select 'tor'; json_select 'instances'; json_select 'instance1';
- json_get_var ret 'running'; json_cleanup
- fi
- if [ "$ret" = "0" ]; then return 1; else return 0; fi
-}
-is_wg() { local proto; proto=$(uci -q get network."$1".proto); [ "${proto:0:9}" = "wireguard" ]; }
-is_tunnel() { is_dslite "$1" || is_l2tp "$1" || is_oc "$1" || is_ovpn "$1" || is_pptp "$1" || is_softether "$1" || is_tor "$1" || is_wg "$1"; }
-is_wan() { [ "$1" = "$wanIface4" ] || { [ "${1##wan}" != "$1" ] && [ "${1##wan6}" = "$1" ]; } || [ "${1%%wan}" != "$1" ]; }
-is_wan6() { [ -n "$wanIface6" ] && [ "$1" = "$wanIface6" ] || [ "${1/#wan6}" != "$1" ] || [ "${1/%wan6}" != "$1" ]; }
-is_ignored_interface() { str_contains_word "$ignored_interface" "$1"; }
-is_supported_interface() { str_contains_word "$supported_interface" "$1" || { ! is_ignored_interface "$1" && { is_wan "$1" || is_wan6 "$1" || is_tunnel "$1"; }; } || is_ignore_target "$1"; }
-is_ignore_target() { [ "$(str_to_lower "$1")" = 'ignore' ]; }
-is_mac_address() { expr "$1" : '[0-9a-fA-F][0-9a-fA-F]:[0-9a-fA-F][0-9a-fA-F]:[0-9a-fA-F][0-9a-fA-F]:[0-9a-fA-F][0-9a-fA-F]:[0-9a-fA-F][0-9a-fA-F]:[0-9a-fA-F][0-9a-fA-F]$' >/dev/null; }
-is_ipv4() { expr "$1" : '[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*$' >/dev/null; }
-is_ipv6() { ! is_mac_address "$1" && str_contains "$1" ":"; }
-is_family_mismatch() { ( is_netmask "${1//!}" && is_ipv6 "${2//!}" ) || ( is_ipv6 "${1//!}" && is_netmask "${2//!}" ); }
-is_ipv6_link_local() { [ "${1:0:4}" = "fe80" ]; }
-is_ipv6_unique_local() { [ "${1:0:2}" = "fc" ] || [ "${1:0:2}" = "fd" ]; }
-is_ipv6_global() { [ "${1:0:4}" = "2001" ]; }
-# is_ipv6_global() { is_ipv6 "$1" && ! is_ipv6_link_local "$1" && ! is_ipv6_link_local "$1"; }
-is_list() { str_contains "$1" "," || str_contains "$1" " "; }
-is_netmask() { local ip="${1%/*}"; [ "$ip" != "$1" ] && is_ipv4 "$ip"; }
-is_domain() { ! is_ipv6 "$1" && str_contains "$1" '[a-zA-Z]'; }
-is_phys_dev() { [ "${1:0:1}" = "@" ] && ip l show | grep -E -q "^\\d+\\W+${1:1}"; }
-dnsmasq_kill() { killall -q -s HUP dnsmasq; }
-dnsmasq_restart() { output 3 'Restarting dnsmasq '; if /etc/init.d/dnsmasq restart >/dev/null 2>&1; then output_okn; else output_failn; fi; }
-is_default_dev() { [ "$1" = "$($ip_bin -4 r | grep -m1 'dev' | grep -Eso 'dev [^ ]*' | awk '{print $2}')" ]; }
-is_supported_iface_dev() { local n dev; for n in $ifacesSupported; do network_get_device dev "$n"; [ "$1" = "$dev" ] && return 0; done; return 1; }
-is_supported_protocol() { grep -o '^[^#]*' /etc/protocols | grep -w -v '0' | grep . | awk '{print $1}' | grep -q "$1"; }
-is_service_running_iptables() { [ -x "$iptables" ] && "$iptables" -t mangle -L | grep -q "${iptPrefix}_PREROUTING" >/dev/null 2>&1; }
-is_service_running_nft() { [ -x "$nft" ] && [ -n "$(get_mark_nft_chains)" ]; }
-# atomic
-# is_service_running_nft() { [ -x "$nft" ] && [ -s "$nftPermFile" ]; }
-is_service_running() { if is_nft; then is_service_running_nft; else is_service_running_iptables; fi; }
-is_netifd_table() { local iface="$1"; [ "$(uci -q get "network.${iface}.ip4table")" = "${packageName}_${iface%6}" ]; }
-get_rt_tables_id() { local iface="$1"; grep "${ipTablePrefix}_${iface}\$" '/etc/iproute2/rt_tables' | awk '{print $1;}'; }
-get_rt_tables_next_id() { echo "$(($(sort -r -n '/etc/iproute2/rt_tables' | grep -o -E -m 1 "^[0-9]+")+1))"; }
-_check_config() { local en; config_get_bool en "$1" 'enabled' 1; [ "$en" -gt 0 ] && _cfg_enabled=0; }
-is_config_enabled() {
- local cfg="$1" _cfg_enabled=1
- [ -n "$1" ] || return 1
- config_load "$packageName"
- config_foreach _check_config "$cfg"
- return "$_cfg_enabled"
-}
-# shellcheck disable=SC2016
-resolveip_to_ipt() { resolveip "$@" | sed -n 'H;${x;s/\n/,/g;s/^,//;p;};d'; }
-resolveip_to_ipt4() { resolveip_to_ipt -4 "$@"; }
-resolveip_to_ipt6() { [ -n "$ipv6_enabled" ] && resolveip_to_ipt -6 "$@"; }
-# shellcheck disable=SC2016
-resolveip_to_nftset() { resolveip "$@" | sed -n 'H;${x;s/\n/,/g;s/^,//;p;};d' | tr '\n' ' '; }
-resolveip_to_nftset4() { resolveip_to_nftset -4 "$@"; }
-resolveip_to_nftset6() { [ -n "$ipv6_enabled" ] && resolveip_to_nftset -6 "$@"; }
-# shellcheck disable=SC2016
-ipv4_leases_to_nftset() { [ -s '/tmp/dhcp.leases' ] || return 1; grep "$1" '/tmp/dhcp.leases' | awk '{print $3}' | sed -n 'H;${x;s/\n/,/g;s/^,//;p;};d' | tr '\n' ' '; }
-# shellcheck disable=SC2016
-ipv6_leases_to_nftset() { [ -s '/tmp/hosts/odhcpd' ] || return 1; grep -v '^\#' '/tmp/hosts/odhcpd' | grep "$1" | awk '{print $1}' | sed -n 'H;${x;s/\n/,/g;s/^,//;p;};d' | tr '\n' ' '; }
-# shellcheck disable=SC3037
-ports_to_nftset() { echo -ne "$value"; }
-get_mark_ipt_chains() { [ -n "$(command -v iptables-save)" ] && iptables-save | grep ":${iptPrefix}_MARK_" | awk '{ print $1 }' | sed 's/://'; }
-get_mark_nft_chains() { [ -x "$nft" ] && "$nft" list table inet "$nftTable" 2>/dev/null | grep chain | grep "${nftPrefix}_mark_" | awk '{ print $2 }'; }
-get_ipsets() { [ -x "$(command -v ipset)" ] && ipset list | grep "${ipsPrefix}_" | awk '{ print $2 }'; }
-get_nft_sets() { [ -x "$nft" ] && "$nft" list table inet "$nftTable" 2>/dev/null | grep 'set' | grep "${nftPrefix}_" | awk '{ print $2 }'; }
-is_ipset_type_supported() { ipset help hash:"$1" >/dev/null 2>&1; }
-ubus_get_status() { ubus call service list "{ 'name': '$packageName' }" | jsonfilter -e "@.${packageName}.instances.main.data.status.${1}"; }
-ubus_get_iface() { ubus call service list "{ 'name': '$packageName' }" | jsonfilter -e "@.${packageName}.instances.main.data.interfaces[@.name='${1}']${2:+.$2}"; }
-opkg_get_version() { grep -m1 -A1 "Package: $1$" '/usr/lib/opkg/status' | grep -m1 'Version: ' | sed 's|Version: \(.*\)|\1|'; }
-
-load_package_config() {
- config_load "$packageName"
- config_get boot_timeout 'config' 'boot_timeout' '30'
- config_get_bool enabled 'config' 'enabled' '0'
- config_get fw_mask 'config' 'fw_mask' 'ff0000'
- config_get icmp_interface 'config' 'icmp_interface'
- config_get ignored_interface 'config' 'ignored_interface'
- config_get_bool ipv6_enabled 'config' 'ipv6_enabled' '0'
- config_get nft_user_set_policy 'config' 'nft_user_set_policy' 'memory'
- config_get_bool nft_user_set_counter 'config' 'nft_user_set_counter' '0'
- config_get procd_boot_delay 'config' 'procd_boot_delay' '0'
- config_get resolver_set 'config' 'resolver_set'
- config_get rule_create_option 'config' 'rule_create_option' 'add'
- config_get_bool secure_reload 'config' 'secure_reload' '1'
- config_get_bool strict_enforcement 'config' 'strict_enforcement' '0'
- config_get supported_interface 'config' 'supported_interface'
- config_get verbosity 'config' 'verbosity' '2'
- config_get wan_ip_rules_priority 'config' 'wan_ip_rules_priority' '30000'
- config_get wan_mark 'config' 'wan_mark' '010000'
- fw_mask="0x${fw_mask}"
- wan_mark="0x${wan_mark}"
- [ -n "$ipv6_enabled" ] && [ "$ipv6_enabled" -eq 0 ] && unset ipv6_enabled
- . /lib/functions/network.sh
- . /usr/share/libubox/jshn.sh
- mkdir -p "${dnsmasqFile%/*}"
- if is_nft; then
- fw_maskXor="$(printf '%#x' "$((fw_mask ^ 0xffffffff))")"
- fw_maskXor="${fw_maskXor:-0xff00ffff}"
- if [ "$nft_user_set_counter" -eq '0' ]; then
- unset nft_user_set_counter
- fi
- else
- case $rule_create_option in
- insert|-i|-I) rule_create_option='-I';;
- add|-a|-A|*) rule_create_option='-A';;
- esac
- fi
-}
-
-load_environment() {
- local param="$1" validation_result="$2"
- load_package_config
- case "$param" in
- on_start)
- if [ -n "$validation_result" ] && [ "$validation_result" != '0' ]; then
- output "${_ERROR_}: The $packageName config validation failed!\\n"
- output "Please check if the '$packageConfigFile' contains correct values for config options.\\n"
- state add 'errorSummary' 'errorConfigValidation'
- return 1
- fi
- if [ "$enabled" -eq 0 ]; then
- state add 'errorSummary' 'errorServiceDisabled'
- return 1
- fi
- if [ ! -x "$ip_bin" ]; then
- state add 'errorSummary' 'errorNoIpFull'
- return 1
- fi
- if ! is_nft; then
- if [ -z "$iptables" ] || [ ! -x "$iptables" ]; then
- state add 'errorSummary' 'errorNoIptables'
- return 1
- fi
- fi
- rm -f "$packageLockFile"
- resolver 'check_support'
- ;;
- on_stop)
- touch "$packageLockFile"
- ;;
- esac
- load_network "$param"
-}
-
-load_network() {
- local i
- config_load 'network'
- [ -z "$ifacesAll" ] && config_foreach _build_ifaces_all 'interface'
- if [ -z "$ifacesSupported" ]; then
- config_load 'firewall'
- config_foreach _find_firewall_wan_zone 'zone'
- for i in $(uci -q get "firewall.${firewallWanZone}.network"); do
- is_supported_interface "$i" && ! str_contains "$ifacesSupported" "$1" && ifacesSupported="${ifacesSupported}${i} "
- done
- config_load 'network'
- config_foreach _build_ifaces_supported 'interface'
- fi
- pbr_find_iface wanIface4 'wan'
- [ -n "$ipv6_enabled" ] && pbr_find_iface wanIface6 'wan6'
- [ -n "$wanIface4" ] && network_get_gateway wanGW4 "$wanIface4"
- [ -n "$wanIface6" ] && network_get_gateway6 wanGW6 "$wanIface6"
- wanGW="${wanGW4:-$wanGW6}"
-}
-
-is_wan_up() {
- local sleepCount='1'
- load_network
- while [ -z "$wanGW" ] ; do
- load_network
- if [ $((sleepCount)) -gt $((boot_timeout)) ] || [ -n "$wanGW" ]; then break; fi
- output "$serviceName waiting for wan gateway...\\n"
- sleep 1
- network_flush_cache
- sleepCount=$((sleepCount+1))
- done
- if [ -n "$wanGW" ]; then
- return 0
- else
- state add 'errorSummary' 'errorNoWanGateway'
- return 1
- fi
-}
-
-# shellcheck disable=SC2086
-ipt4() {
- local d
- [ -x "$iptables" ] || return 1
- for d in "${*//-A/-D}" "${*//-I/-D}" "${*//-N/-F}" "${*//-N/-X}"; do
- [ "$d" != "$*" ] && "$iptables" $d >/dev/null 2>&1
- done
- d="$*"; "$iptables" $d >/dev/null 2>&1
-}
-
-# shellcheck disable=SC2086
-ipt6() {
- local d
- [ -n "$ipv6_enabled" ] || return 0
- [ -x "$ip6tables" ] || return 1
- for d in "${*//-A/-D}" "${*//-I/-D}" "${*//-N/-F}" "${*//-N/-X}"; do
- [ "$d" != "$*" ] && "$ip6tables" $d >/dev/null 2>&1
- done
- d="$*"
- "$ip6tables" $d >/dev/null 2>&1
-}
-
-# shellcheck disable=SC2086
-ipt() {
- local d failFlagIpv4=1 failFlagIpv6=1
- [ -x "$iptables" ] || return 1
- for d in "${*//-A/-D}" "${*//-I/-D}" "${*//-N/-F}" "${*//-N/-X}"; do
- if [ "$d" != "$*" ]; then
- "$iptables" $d >/dev/null 2>&1
- [ -x "$ip6tables" ] && "$ip6tables" $d >/dev/null 2>&1
- fi
- done
- d="$*"; "$iptables" $d >/dev/null 2>&1 && failFlagIpv4=0;
- if [ -n "$ipv6_enabled" ] && [ -x "$ip6tables" ]; then
- "$ip6tables" $d >/dev/null 2>&1 && failFlagIpv6=0
- fi
- [ "$failFlagIpv4" -eq 0 ] || [ "$failFlagIpv6" -eq 0 ]
-}
-
-# shellcheck disable=SC2086
-ips4() { [ -x "$ipset" ] && "$ipset" "$@" >/dev/null 2>&1; }
-ips6() { [ -x "$ipset" ] && { if [ -n "$ipv6_enabled" ] && [ -n "$*" ]; then "$ipset" "$@" >/dev/null 2>&1; else return 1; fi; }; }
-ips() {
- local command="$1" iface="$2" target="${3:-dst}" type="${4:-ip}" uid="$5" comment="$6" param="$7" mark="$7"
- local ipset4 ipset6 i
- local ipv4_error=1 ipv6_error=1
- ipset4="${ipsPrefix}${iface:+_$iface}_4${target:+_$target}${type:+_$type}${uid:+_$uid}"
- ipset6="${ipsPrefix}${iface:+_$iface}_6${target:+_$target}${type:+_$type}${uid:+_$uid}"
-
- [ -x "$ipset" ] || return 1
-
- if [ "${#ipset4}" -gt 31 ]; then
- state add 'errorSummary' 'errorIpsetNameTooLong' "$ipset4"
- return 1
- fi
-
- case "$command" in
- add)
- ips4 -q -! add "$ipset4" ["$param"] comment "$comment" && ipv4_error=0
- ips6 -q -! add "$ipset6" ["$param"] comment "$comment" && ipv6_error=0
- ;;
- add_agh_element)
- [ -n "$ipv6_enabled" ] || unset ipset6
- echo "${param}/${ipset4}${ipset6:+,$ipset6}" >> "$aghIpsetFile" && ipv4_error=0
- ;;
- add_dnsmasq_element)
- [ -n "$ipv6_enabled" ] || unset ipset6
- echo "ipset=/${param}/${ipset4}${ipset6:+,$ipset6} # $comment" >> "$dnsmasqFile" && ipv4_error=0
- ;;
- create)
- ips4 -q -! create "$ipset4" "hash:$type" comment && ipv4_error=0
- ips6 -q -! create "$ipset6" "hash:$type" comment family inet6 && ipv6_error=0
- ;;
- create_agh_set)
- ips4 -q -! create "$ipset4" "hash:$type" comment && ipv4_error=0
- ips6 -q -! create "$ipset6" "hash:$type" comment family inet6 && ipv6_error=0
- ;;
- create_dnsmasq_set)
- ips4 -q -! create "$ipset4" "hash:$type" comment && ipv4_error=0
- ips6 -q -! create "$ipset6" "hash:$type" comment family inet6 && ipv6_error=0
- ;;
- create_user_set)
- case "$type" in
- ip|net)
- ips4 -q -! create "$ipset4" "hash:$type" comment && ipv4_error=0
- ips6 -q -! create "$ipset6" "hash:$type" comment family inet6 && ipv6_error=0
- case "$target" in
- dst)
- ipt4 -t mangle -A "${iptPrefix}_PREROUTING" -m set --match-set "$ipset4" dst -g "${iptPrefix}_MARK_${mark}" && ipv4_error=0
- ipt6 -t mangle -A "${iptPrefix}_PREROUTING" -m set --match-set "$ipset6" dst -g "${iptPrefix}_MARK_${mark}" && ipv6_error=0
- ;;
- src)
- ipt4 -t mangle -A "${iptPrefix}_PREROUTING" -m set --match-set "$ipset4" src -g "${iptPrefix}_MARK_${mark}" && ipv4_error=0
- ipt6 -t mangle -A "${iptPrefix}_PREROUTING" -m set --match-set "$ipset6" src -g "${iptPrefix}_MARK_${mark}" && ipv6_error=0
- ;;
- esac
- ;;
- mac)
- ips4 -q -! create "$ipset4" "hash:$type" comment && ipv4_error=0
- ips6 -q -! create "$ipset6" "hash:$type" comment family inet6 && ipv4_error=0
- ipt4 -t mangle -A "${iptPrefix}_PREROUTING" -m set --match-set "$ipset4" src -g "${iptPrefix}_MARK_${mark}" && ipv4_error=0
- ipt6 -t mangle -A "${iptPrefix}_PREROUTING" -m set --match-set "$ipset6" src -g "${iptPrefix}_MARK_${mark}" && ipv6_error=0
- ;;
- esac
- ;;
- delete|destroy)
- ips4 -q -! destroy "$ipset4" && ipv4_error=0
- ips6 -q -! destroy "$ipset6" && ipv6_error=0
- ;;
- delete_user_set)
- ips4 -q -! destroy "$ipset4" && ipv4_error=0
- ips6 -q -! destroy "$ipset6" family inet6 && ipv6_error=0
- case "$type" in
- ip|net)
- case "$target" in
- dst)
- ipt4 -t mangle -D "${iptPrefix}_PREROUTING" -m set --match-set "$ipset4" dst -g "${iptPrefix}_MARK_${mark}" && ipv4_error=0
- ipt6 -t mangle -D "${iptPrefix}_PREROUTING" -m set --match-set "$ipset6" dst -g "${iptPrefix}_MARK_${mark}" && ipv6_error=0
- ;;
- src)
- ipt4 -t mangle -D "${iptPrefix}_PREROUTING" -m set --match-set "$ipset4" src -g "${iptPrefix}_MARK_${mark}" && ipv4_error=0
- ipt6 -t mangle -D "${iptPrefix}_PREROUTING" -m set --match-set "$ipset6" src -g "${iptPrefix}_MARK_${mark}" && ipv6_error=0
- ;;
- esac
- ;;
- mac)
- ipt4 -t mangle -D "${iptPrefix}_PREROUTING" -m set --match-set "$ipset4" src -g "${iptPrefix}_MARK_${mark}" && ipv4_error=0
- ipt6 -t mangle -D "${iptPrefix}_PREROUTING" -m set --match-set "$ipset6" src -g "${iptPrefix}_MARK_${mark}" && ipv6_error=0
- ;;
- esac
- ;;
- flush|flush_user_set)
- ips4 -q -! flush "$ipset4" && ipv4_error=0
- ips6 -q -! flush "$ipset6" && ipv6_error=0
- ;;
- esac
- if [ "$ipv4_error" -eq '0' ] || [ "$ipv6_error" -eq '0' ]; then
- return 0
- else
- return 1
- fi
-}
-
-# atomic
-#nfta() { echo "$@" >> "$nftTempFile"; }
-#nfta4() { echo "$@" >> "$nftTempFile"; }
-#nfta6() { [ -z "$ipv6_enabled" ] || echo "$@" >> "$nftTempFile"; }
-#nft() { nfta "$@"; [ -x "$nft" ] && "$nft" "$@" >/dev/null 2>&1; }
-#nft4() { nfta "$@"; [ -x "$nft" ] && "$nft" "$@" >/dev/null 2>&1; }
-#nft6() { nfta "$@"; [ -n "$ipv6_enabled" ] || return 0; [ -x "$nft" ] && [ -n "$*" ] && "$nft" "$@" >/dev/null 2>&1; }
-nft() { [ -x "$nft" ] && "$nft" "$@" >/dev/null 2>&1; }
-nft4() { [ -x "$nft" ] && "$nft" "$@" >/dev/null 2>&1; }
-nft6() { [ -n "$ipv6_enabled" ] || return 0; [ -x "$nft" ] && [ -n "$*" ] && "$nft" "$@" >/dev/null 2>&1; }
-nftset() {
- local command="$1" iface="$2" target="${3:-dst}" type="${4:-ip}" uid="$5" comment="$6" param="$7" mark="$7"
- local nftset4 nftset6 i param4 param6
- local ipv4_error=1 ipv6_error=1
- nftset4="${nftPrefix}${iface:+_$iface}_4${target:+_$target}${type:+_$type}${uid:+_$uid}"
- nftset6="${nftPrefix}${iface:+_$iface}_6${target:+_$target}${type:+_$type}${uid:+_$uid}"
-
- [ -x "$nft" ] || return 1
-
- if [ "${#nftset4}" -gt 255 ]; then
- state add 'errorSummary' 'errorNftsetNameTooLong' "$nftset4"
- return 1
- fi
-
- case "$command" in
- add)
- if is_netmask "$param" || is_ipv4 "$param" || is_ipv6 "$param" \
- || is_mac_address "$param" || is_list "$param"; then
- nft4 add element inet "$nftTable" "$nftset4" "{ $param }" && ipv4_error=0
- nft6 add element inet "$nftTable" "$nftset6" "{ $param }" && ipv6_error=0
- else
- if [ "$target" = 'src' ]; then
- param4="$(ipv4_leases_to_nftset "$param")"
- param6="$(ipv6_leases_to_nftset "$param")"
- fi
- [ -z "$param4" ] && param4="$(resolveip_to_nftset4 "$param")"
- [ -z "$param6" ] && param6="$(resolveip_to_nftset6 "$param")"
- if [ -z "$param4" ] && [ -z "$param6" ]; then
- state add 'errorSummary' 'errorFailedToResolve' "$param"
- else
- nft4 add element inet "$nftTable" "$nftset4" "{ $param4 }" && ipv4_error=0
- nft6 add element inet "$nftTable" "$nftset6" "{ $param6 }" && ipv6_error=0
- fi
- fi
- ;;
- add_dnsmasq_element)
- [ -n "$ipv6_enabled" ] || unset nftset6
- echo "nftset=/${param}/4#inet#${nftTable}#${nftset4}${nftset6:+,6#inet#${nftTable}#$nftset6} # $comment" >> "$dnsmasqFile" && ipv4_error=0
- ;;
- create)
- case "$type" in
- ip|net)
- nft4 add set inet "$nftTable" "$nftset4" "{ type ipv4_addr; counter; flags interval; auto-merge; comment \"$comment\"; }" && ipv4_error=0
- nft6 add set inet "$nftTable" "$nftset6" "{ type ipv6_addr; counter; flags interval; auto-merge; comment \"$comment\"; }" && ipv6_error=0
- ;;
- mac)
- nft4 add set inet "$nftTable" "$nftset4" "{ type ether_addr; counter; flags interval; auto-merge; comment \"$comment\"; }" && ipv4_error=0
- nft6 add set inet "$nftTable" "$nftset6" "{ type ether_addr; counter; flags interval; auto-merge; comment \"$comment\"; }" && ipv6_error=0
- ;;
- esac
- ;;
- create_dnsmasq_set)
- nft4 add set inet "$nftTable" "$nftset4" "{ type ipv4_addr; counter; flags interval; auto-merge; comment \"$comment\"; }" && ipv4_error=0
- nft6 add set inet "$nftTable" "$nftset6" "{ type ipv6_addr; counter; flags interval; auto-merge; comment \"$comment\"; }" && ipv6_error=0
- ;;
- create_user_set)
- case "$type" in
- ip|net)
- nft4 add set inet "$nftTable" "$nftset4" "{ type ipv4_addr; ${nft_user_set_counter:+counter;} flags interval; auto-merge; policy $nft_user_set_policy; comment \"$comment\"; }" && ipv4_error=0
- nft6 add set inet "$nftTable" "$nftset6" "{ type ipv6_addr; ${nft_user_set_counter:+counter;} flags interval; auto-merge; policy $nft_user_set_policy; comment \"$comment\"; }" && ipv6_error=0
- case "$target" in
- dst)
- nft add rule inet "$nftTable" "${nftPrefix}_prerouting" ip daddr "@${nftset4}" goto "${nftPrefix}_mark_${mark}" && ipv4_error=0
- nft add rule inet "$nftTable" "${nftPrefix}_prerouting" ip daddr "@${nftset6}" goto "${nftPrefix}_mark_${mark}" && ipv6_error=0
- ;;
- src)
- nft add rule inet "$nftTable" "${nftPrefix}_prerouting" ip saddr "@${nftset4}" goto "${nftPrefix}_mark_${mark}" && ipv4_error=0
- nft add rule inet "$nftTable" "${nftPrefix}_prerouting" ip saddr "@${nftset6}" goto "${nftPrefix}_mark_${mark}" && ipv6_error=0
- ;;
- esac
- ;;
- mac)
- nft4 add set inet "$nftTable" "$nftset4" "{ type ether_addr; ${nft_user_set_counter:+counter;} flags interval; auto-merge; policy $nft_user_set_policy; comment \"$comment\"; }" && ipv4_error=0
- nft6 add set inet "$nftTable" "$nftset6" "{ type ether_addr; ${nft_user_set_counter:+counter;} flags interval; auto-merge; policy $nft_user_set_policy; comment \"$comment\"; }" && ipv6_error=0
- nft add rule inet "$nftTable" "${nftPrefix}_prerouting" ether saddr "@${nftset4}" goto "${nftPrefix}_mark_${mark}" && ipv4_error=0
- nft add rule inet "$nftTable" "${nftPrefix}_prerouting" ether saddr "@${nftset6}" goto "${nftPrefix}_mark_${mark}" && ipv6_error=0
- ;;
- esac
- ;;
- delete|destroy)
- nft delete set inet "$nftTable" "$nftset4" && ipv4_error=0
- nft delete set inet "$nftTable" "$nftset6" && ipv6_error=0
- ;;
- delete_user_set)
- nft delete set inet "$nftTable" "$nftset4" && ipv4_error=0
- nft delete set inet "$nftTable" "$nftset6" && ipv6_error=0
- case "$type" in
- ip|net)
- case "$target" in
- dst)
- nft delete rule inet "$nftTable" "${nftPrefix}_prerouting" ip daddr "@${nftset4}" goto "${nftPrefix}_mark_${mark}" && ipv4_error=0
- nft delete rule inet "$nftTable" "${nftPrefix}_prerouting" ip daddr "@${nftset6}" goto "${nftPrefix}_mark_${mark}" && ipv6_error=0
- ;;
- src)
- nft delete rule inet "$nftTable" "${nftPrefix}_prerouting" ip saddr "@${nftset4}" goto "${nftPrefix}_mark_${mark}" && ipv4_error=0
- nft delete rule inet "$nftTable" "${nftPrefix}_prerouting" ip saddr "@${nftset6}" goto "${nftPrefix}_mark_${mark}" && ipv6_error=0
- ;;
- esac
- ;;
- mac)
- nft delete rule inet "$nftTable" "${nftPrefix}_prerouting" ether saddr "@${nftset4}" goto "${nftPrefix}_mark_${mark}" && ipv4_error=0
- nft delete rule inet "$nftTable" "${nftPrefix}_prerouting" ether saddr "@${nftset6}" goto "${nftPrefix}_mark_${mark}" && ipv6_error=0
- ;;
- esac
- ;;
- flush|flush_user_set)
- nft flush set inet "$nftTable" "$nftset4" && ipv4_error=0
- nft flush set inet "$nftTable" "$nftset6" && ipv6_error=0
- ;;
- esac
-# nft6 returns true if IPv6 support is not enabled
- [ -z "$ipv6_enabled" ] && ipv6_error='1'
- if [ "$ipv4_error" -eq '0' ] || [ "$ipv6_error" -eq '0' ]; then
- return 0
- else
- return 1
- fi
-}
-
-cleanup_rt_tables() { sed -i '/pbr_/d' '/etc/iproute2/rt_tables'; sync; }
-cleanup_dnsmasq() { [ -s "$dnsmasqFile" ] && resolverStoredHash="$(md5sum $dnsmasqFile | awk '{ print $1; }')" && rm "$dnsmasqFile" >/dev/null 2>&1; }
-
-cleanup_main_chains() {
- local i
- for i in $chainsList; do
- i="$(str_to_lower "$i")"
- nft flush chain inet "$nftTable" "${nftPrefix}_${i}"
- done
- for i in $chainsList; do
- i="$(str_to_upper "$i")"
- ipt -t mangle -D "${i}" -m mark --mark "0x0/${fw_mask}" -j "${iptPrefix}_${i}"
- ipt -t mangle -F "${iptPrefix}_${i}"
- ipt -t mangle -X "${iptPrefix}_${i}"
- done
-}
-
-cleanup_marking_chains() {
- local i
- for i in $(get_mark_nft_chains); do
- nft flush chain inet "$nftTable" "$i"
- nft delete chain inet "$nftTable" "$i"
- done
- for i in $(get_mark_ipt_chains); do
- ipt -t mangle -F "$i"
- ipt -t mangle -X "$i"
- done
-}
-
-cleanup_sets() {
- local i
- for i in $(get_nft_sets); do
- nft flush set inet "$nftTable" "$i"
- nft delete set inet "$nftTable" "$i"
- done
- for i in $(get_ipsets); do
- ipset -q -! flush "$i" >/dev/null 2>&1
- ipset -q -! destroy "$i" >/dev/null 2>&1
- done
-}
-
-state() {
- local action="$1" param="$2" value="${3//#/_}"
- shift 3
-# shellcheck disable=SC2124
- local extras="$@"
- local line error_id error_extra label
- case "$action" in
- add)
- line="$(eval echo "\$$param")"
- eval "$param"='${line:+$line#}${value}${extras:+ $extras}'
- ;;
- json)
- json_init
- json_add_object "$packageName"
- case "$param" in
- errorSummary)
- json_add_array 'errors';;
- warningSummary)
- json_add_array 'warnings';;
- esac
- if [ -n "$(eval echo "\$$param")" ]; then
- while read -r line; do
- if str_contains "$line" ' '; then
- error_id="${line% *}"
- error_extra="${line#* }"
- else
- error_id="$line"
- fi
- json_add_object
- json_add_string 'id' "$error_id"
- json_add_string 'extra' "$error_extra"
- json_close_object
- done <<EOF
-$(eval echo "\$$param" | tr \# \\n)
-EOF
- fi
- json_close_array
- json_close_object
- json_dump
- ;;
- print)
- [ -z "$(eval echo "\$$param")" ] && return 0
- case "$param" in
- errorSummary)
- label="${_ERROR_}:";;
- warningSummary)
- label="${_WARNING_}:";;
- esac
- while read -r line; do
- if str_contains "$line" ' '; then
- error_id="${line% *}"
- error_extra="${line#* }"
- printf "%b $(get_text "$error_id")\\n" "$label" "$error_extra"
- else
- error_id="$line"
- printf "%b $(get_text "$error_id")\\n" "$label"
- fi
- done <<EOF
-$(eval echo "\$$param" | tr \# \\n)
-EOF
- ;;
- set)
- eval "$param"='${value}${extras:+ $extras}'
- ;;
- esac
-}
-
-resolver() {
- local agh_version
- local param="$1"
- shift
-
- if [ "$param" = 'cleanup_all' ]; then
- sed -i "/ipset_file: ${aghIpsetFile}/d" "$aghConfigFile" >/dev/null 2>&1
- rm -f "$aghIpsetFile"
- rm -f "$dnsmasqFile"
- return 0
- fi
-
- case "$resolver_set" in
- ''|none)
- case "$param" in
- add_resolver_element) return 1;;
- create_resolver_set) return 1;;
- check_support) return 0;;
- cleanup) return 0;;
- configure) return 0;;
- init) return 0;;
- init_end) return 0;;
- kill) return 0;;
- reload) return 0;;
- restart) return 0;;
- compare_hash) return 0;;
- store_hash) return 0;;
- esac
- ;;
- adguardhome.ipset)
- case "$param" in
- add_resolver_element)
- [ -n "$resolver_set_supported" ] && ips 'add_agh_element' "$@";;
- create_resolver_set)
- [ -n "$resolver_set_supported" ] && ips 'create_agh_set' "$@";;
- check_support)
- if [ ! -x "$ipset" ]; then
- state add 'errorSummary' 'errorNoIpset'
- return 1
- fi
- if [ -n "$agh" ] && [ -s "$aghConfigFile" ]; then
- agh_version="$($agh --version | sed 's|AdGuard Home, version v\(.*\)|\1|' | sed 's|-.*||')"
- if is_greater_or_equal "$agh_version" '0.107.13'; then
- resolver_set_supported='true'
- return 0
- else
- state add 'warningSummary' 'warningAGHVersionTooLow' "$agh_version"
- return 1
- fi
- else
- state add 'warningSummary' 'warningResolverNotSupported'
- return 1
- fi
- ;;
- cleanup)
- [ -z "$resolver_set_supported" ] && return 0
- rm -f "$aghIpsetFile"
- sed -i "/ipset_file: ${aghIpsetFile}/d" "$aghConfigFile" >/dev/null 2>&1
- ;;
- configure)
- [ -z "$resolver_set_supported" ] && return 1
- mkdir -p "${aghIpsetFile%/*}"
- touch "$aghIpsetFile"
- sed -i '/ipset_file/d' "$aghConfigFile" >/dev/null 2>&1
- sed -i "/ ipset:/a \ \ ipset_file: $aghIpsetFile" "$aghConfigFile"
- ;;
- init) :;;
- init_end) :;;
- kill)
- [ -n "$resolver_set_supported" ] && [ -n "$agh" ] && killall -q -s HUP "$agh";;
- reload)
- [ -z "$resolver_set_supported" ] && return 1
- output 3 'Reloading adguardhome '
- if /etc/init.d/adguardhome reload >/dev/null 2>&1; then
- output_okn
- return 0
- else
- output_failn
- return 1
- fi
- ;;
- restart)
- [ -z "$resolver_set_supported" ] && return 1
- output 3 'Restarting adguardhome '
- if /etc/init.d/adguardhome restart >/dev/null 2>&1; then
- output_okn
- return 0
- else
- output_failn
- return 1
- fi
- ;;
- compare_hash)
- [ -z "$resolver_set_supported" ] && return 1
- local resolverNewHash
- if [ -s "$aghIpsetFile" ]; then
- resolverNewHash="$(md5sum $aghIpsetFile | awk '{ print $1; }')"
- fi
- [ "$resolverNewHash" != "$resolverStoredHash" ]
- ;;
- store_hash)
- [ -s "$aghIpsetFile" ] && resolverStoredHash="$(md5sum $aghIpsetFile | awk '{ print $1; }')";;
- esac
- ;;
- dnsmasq.ipset)
- case "$param" in
- add_resolver_element)
- [ -n "$resolver_set_supported" ] && ips 'add_dnsmasq_element' "$@";;
- create_resolver_set)
- [ -n "$resolver_set_supported" ] && ips 'create_dnsmasq_set' "$@";;
- check_support)
- if [ ! -x "$ipset" ]; then
- state add 'errorSummary' 'errorNoIpset'
- return 1
- fi
- if ! dnsmasq -v 2>/dev/null | grep -q 'no-ipset' && dnsmasq -v 2>/dev/null | grep -q 'ipset'; then
- resolver_set_supported='true'
- return 0
- else
- state add 'warningSummary' 'warningResolverNotSupported'
- return 1
- fi
- ;;
- cleanup)
- [ -n "$resolver_set_supported" ] && rm -f "$dnsmasqFile";;
- configure)
- [ -n "$resolver_set_supported" ] && mkdir -p "${dnsmasqFile%/*}";;
- init) :;;
- init_end) :;;
- kill)
- [ -n "$resolver_set_supported" ] && killall -q -s HUP dnsmasq;;
- reload)
- [ -z "$resolver_set_supported" ] && return 1
- output 3 'Reloading dnsmasq '
- if /etc/init.d/dnsmasq reload >/dev/null 2>&1; then
- output_okn
- return 0
- else
- output_failn
- return 1
- fi
- ;;
- restart)
- [ -z "$resolver_set_supported" ] && return 1
- output 3 'Restarting dnsmasq '
- if /etc/init.d/dnsmasq restart >/dev/null 2>&1; then
- output_okn
- return 0
- else
- output_failn
- return 1
- fi
- ;;
- compare_hash)
- [ -z "$resolver_set_supported" ] && return 1
- local resolverNewHash
- if [ -s "$dnsmasqFile" ]; then
- resolverNewHash="$(md5sum $dnsmasqFile | awk '{ print $1; }')"
- fi
- [ "$resolverNewHash" != "$resolverStoredHash" ]
- ;;
- store_hash)
- [ -s "$dnsmasqFile" ] && resolverStoredHash="$(md5sum $dnsmasqFile | awk '{ print $1; }')";;
- esac
- ;;
- dnsmasq.nftset)
- case "$param" in
- add_resolver_element)
- [ -n "$resolver_set_supported" ] && nftset 'add_dnsmasq_element' "$@";;
- create_resolver_set)
- [ -n "$resolver_set_supported" ] && nftset 'create_dnsmasq_set' "$@";;
- check_support)
- if [ ! -x "$nft" ]; then
- state add 'errorSummary' 'errorNoNft'
- return 1
- fi
- if ! dnsmasq -v 2>/dev/null | grep -q 'no-nftset' && dnsmasq -v 2>/dev/null | grep -q 'nftset'; then
- resolver_set_supported='true'
- return 0
- else
- state add 'warningSummary' 'warningResolverNotSupported'
- return 1
- fi
- ;;
- cleanup)
- [ -n "$resolver_set_supported" ] && rm -f "$dnsmasqFile";;
- configure)
- [ -n "$resolver_set_supported" ] && mkdir -p "${dnsmasqFile%/*}";;
- init) :;;
- init_end) :;;
- kill)
- [ -n "$resolver_set_supported" ] && killall -q -s HUP dnsmasq;;
- reload)
- [ -z "$resolver_set_supported" ] && return 1
- output 3 'Reloading dnsmasq '
- if /etc/init.d/dnsmasq reload >/dev/null 2>&1; then
- output_okn
- return 0
- else
- output_failn
- return 1
- fi
- ;;
- restart)
- [ -z "$resolver_set_supported" ] && return 1
- output 3 'Restarting dnsmasq '
- if /etc/init.d/dnsmasq restart >/dev/null 2>&1; then
- output_okn
- return 0
- else
- output_failn
- return 1
- fi
- ;;
- compare_hash)
- [ -z "$resolver_set_supported" ] && return 1
- local resolverNewHash
- if [ -s "$dnsmasqFile" ]; then
- resolverNewHash="$(md5sum $dnsmasqFile | awk '{ print $1; }')"
- fi
- [ "$resolverNewHash" != "$resolverStoredHash" ]
- ;;
- store_hash)
- [ -s "$dnsmasqFile" ] && resolverStoredHash="$(md5sum $dnsmasqFile | awk '{ print $1; }')";;
- esac
- ;;
- unbound.ipset)
- case "$param" in
- add_resolver_element) :;;
- create_resolver_set) :;;
- check_support) :;;
- cleanup) :;;
- configure) :;;
- init) :;;
- init_end) :;;
- kill) :;;
- reload) :;;
- restart) :;;
- compare_hash) :;;
- store_hash) :;;
- esac
- ;;
- unbound.nftset)
- case "$param" in
- add_resolver_element) :;;
- create_resolver_set) :;;
- check_support) :;;
- cleanup) :;;
- configure) :;;
- init) :;;
- init_end) :;;
- kill) :;;
- reload) :;;
- restart) :;;
- compare_hash) :;;
- store_hash) :;;
- esac
- ;;
- esac
-}
-
-trap_process() {
- output "\\n"
- output "Unexpected exit or service termination: '${1}'!\\n"
- state add 'errorSummary' 'errorUnexpectedExit' "$1"
- traffic_killswitch 'remove'
-}
-
-traffic_killswitch() {
- local s=0
- case "$1" in
- insert)
- local lan_subnet wan_device
- [ "$secure_reload" -ne 0 ] || return 0
- for i in $serviceTrapSignals; do
-# shellcheck disable=SC2064
- trap "trap_process $i" "$i"
- done
- output 3 'Activating traffic killswitch '
- network_get_subnet lan_subnet 'lan'
- network_get_physdev wan_device 'wan'
- if is_nft; then
- nft add chain inet "$nftTable" "${nftPrefix}_killswitch" '{ type filter hook forward priority 0; policy accept; }' || s=1
- nft add rule inet "$nftTable" "${nftPrefix}_killswitch" oifname "$wan_device" ip saddr "$lan_subnet" counter reject || s=1
- else
- ipt -N "${iptPrefix}_KILLSWITCH" || s=1
- ipt -A "${iptPrefix}_KILLSWITCH" -s "$lan_subnet" -o "$wan_device" -j REJECT || s=1
- ipt -I FORWARD -j "${iptPrefix}_KILLSWITCH" || s=1
- fi
- if [ "$s" -eq 0 ]; then
- output_okn
- else
- output_failn
- fi
- ;;
- remove)
- if [ "$secure_reload" -ne 0 ]; then
- output 3 'Deactivating traffic killswitch '
- fi
- if is_nft; then
- nft flush chain inet "$nftTable" "${nftPrefix}_killswitch" || s=1
- nft delete chain inet "$nftTable" "${nftPrefix}_killswitch" || s=1
- else
- ipt -D FORWARD -j "${iptPrefix}_KILLSWITCH" || s=1
- ipt -F "${iptPrefix}_KILLSWITCH" || s=1
- ipt -X "${iptPrefix}_KILLSWITCH" || s=1
- fi
- if [ "$secure_reload" -ne 0 ]; then
- if [ "$s" -eq 0 ]; then
- output_okn
- else
- output_failn
- fi
- fi
-# shellcheck disable=SC2086
- trap - $serviceTrapSignals
- ;;
- esac
-}
-
-policy_routing_tor() { if is_nft; then policy_routing_tor_nft "$@"; else policy_routing_tor_iptables "$@"; fi; }
-policy_routing_tor_iptables() {
- local comment="$1" iface="$2" src_addr="$3" src_port="$4" dest_addr="$5" dest_port="$6" proto chain uid="$9"
- proto="$(str_to_lower "$7")"
- chain="$(str_to_upper "$8")"
- chain="${chain:-PREROUTING}"
- if [ -n "${src_addr}${src_port}${dest_port}" ]; then
- state add 'warningSummary' 'warningTorUnsetParams' "$comment"
- fi
- if [ -n "$proto" ] && [ "$proto" != "all" ]; then
- state add 'warningSummary' 'warningTorUnsetProto' "$comment"
- fi
- if [ "$chain" != "PREROUTING" ]; then
- state add 'warningSummary' 'warningTorUnsetChainIpt' "$comment"
- fi
- if ! resolver 'add_resolver_element' "$iface" 'dst' 'ip' '' "${comment}: $dest_addr" "$dest_addr"; then
- processPolicyError='true'
- state add 'errorSummary' 'errorResolver' "'add_resolver_element' '$iface' 'dst' 'ip' '${comment}: $dest_addr' '$dest_addr'"
- return 1
- fi
- return 0
-}
-policy_routing_tor_nft() {
- local comment="$1" iface="$2" src_addr="$3" src_port="$4" dest_addr="$5" dest_port="$6" proto chain uid="$9"
- proto="$(str_to_lower "$7")"
- chain="$(str_to_lower "$8")"
- chain="${chain:-prerouting}"
- if [ -n "${src_addr}${src_port}${dest_port}" ]; then
- state add 'warningSummary' 'warningTorUnsetParams' "$comment"
- fi
- if [ -n "$proto" ] && [ "$proto" != "all" ]; then
- state add 'warningSummary' 'warningTorUnsetProto' "$comment"
- fi
- if [ "$chain" != "prerouting" ]; then
- state add 'warningSummary' 'warningTorUnsetChainNft' "$comment"
- fi
- if ! resolver 'add_resolver_element' "$iface" 'dst' 'ip' '' "${comment}: $dest_addr" "$dest_addr"; then
- processPolicyError='true'
- state add 'errorSummary' 'errorResolver' "'add_resolver_element' '$iface' 'dst' 'ip' '${comment}: $dest_addr' '$dest_addr'"
- return 1
- fi
- return 0
-}
-
-policy_routing() { if is_nft; then policy_routing_nft "$@"; else policy_routing_iptables "$@"; fi; }
-policy_routing_iptables() {
- local mark param4 param6 i negation value dest ipInsertOption="-A"
- local ip4error='1' ip6error='1'
- local name="$1" iface="$2" laddr="$3" lport="$4" raddr="$5" rport="$6" proto chain uid="$9"
- proto="$(str_to_lower "$7")"
- chain="$(str_to_upper "$8")"
- chain="${chain:-PREROUTING}"
- mark=$(eval echo "\$mark_${iface//-/_}")
-
- if [ -n "$ipv6_enabled" ] && { is_ipv6 "$laddr" || is_ipv6 "$raddr"; }; then
- processPolicyError='true'
- state add 'errorSummary' 'errorPolicyProcessNoIpv6' "$name"
- return 1
- fi
-
- if [ -n "$mark" ]; then
- dest="-g ${iptPrefix}_MARK_${mark}"
- elif [ "$iface" = "ignore" ]; then
- dest="-j RETURN"
- else
- processPolicyError='true'
- state add 'errorSummary' 'errorPolicyProcessUnknownFwmark' "$iface"
- return 1
- fi
-
- if is_family_mismatch "$laddr" "$raddr"; then
- processPolicyError='true'
- state add 'errorSummary' 'errorPolicyProcessMismatchFamily' "${name}: '$laddr' '$raddr'"
- return 1
- fi
-
- if [ -z "$proto" ]; then
- if [ -n "${lport}${rport}" ]; then
- proto='tcp udp'
- else
- proto='all'
- fi
- fi
-
- for i in $proto; do
- if [ "$i" = 'all' ]; then
- param4="-t mangle ${ipInsertOption} ${iptPrefix}_${chain} $dest"
- param6="-t mangle ${ipInsertOption} ${iptPrefix}_${chain} $dest"
- elif ! is_supported_protocol "$i"; then
- processPolicyError='true'
- state add 'errorSummary' 'errorPolicyProcessUnknownProtocol' "${name}: '$i'"
- return 1
- else
- param4="-t mangle ${ipInsertOption} ${iptPrefix}_${chain} $dest -p $i"
- param6="-t mangle ${ipInsertOption} ${iptPrefix}_${chain} $dest -p $i"
- fi
-
- if [ -n "$laddr" ]; then
- if [ "${laddr:0:1}" = "!" ]; then
- negation='!'; value="${laddr:1}"
- else
- unset negation; value="$laddr";
- fi
- if is_phys_dev "$value"; then
- param4="$param4 $negation -m physdev --physdev-in ${value:1}"
- param6="$param6 $negation -m physdev --physdev-in ${value:1}"
- elif is_netmask "$value"; then
- local target='src' type='net'
- if ips 'create' "$iface" "$target" "$type" "$uid" "${name}: $laddr" && \
- ips 'add' "$iface" "$target" "$type" "$uid" "${name}: $laddr" "$value"; then
- param4="$param4 -m set $negation --match-set ${ipsPrefix}_${iface}_4_${target}_${type}_${uid} $target"
- param6="$param6 -m set $negation --match-set ${ipsPrefix}_${iface}_6_${target}_${type}_${uid} $target"
- else
- param4="$param4 $negation -s $value"
- param6="$param6 $negation -s $value"
- fi
- elif is_mac_address "$value"; then
- local target='src' type='mac'
- if ips 'create' "$iface" "$target" "$type" "$uid" "${name}: $laddr" && \
- ips 'add' "$iface" "$target" "$type" "$uid" "${name}: $laddr" "$value"; then
- param4="$param4 -m set $negation --match-set ${ipsPrefix}_${iface}_4_${target}_${type}_${uid} $target"
- param6="$param6 -m set $negation --match-set ${ipsPrefix}_${iface}_6_${target}_${type}_${uid} $target"
- else
- param4="$param4 -m mac $negation --mac-source $value"
- param6="$param6 -m mac $negation --mac-source $value"
- fi
- else
- local target='src' type='ip'
- if ips 'create' "$iface" "$target" "$type" "$uid" "${name}: $laddr" && \
- ips 'add' "$iface" "$target" "$type" "$uid" "${name}: $laddr" "$value"; then
- param4="$param4 -m set $negation --match-set ${ipsPrefix}_${iface}_4_${target}_${type}_${uid} $target"
- param6="$param6 -m set $negation --match-set ${ipsPrefix}_${iface}_6_${target}_${type}_${uid} $target"
- else
- local resolvedIP4 resolvedIP6
- resolvedIP4="$(resolveip_to_ipt4 "$value")"
- resolvedIP6="$(resolveip_to_ipt6 "$value")"
- if [ -z "$resolvedIP4" ] && [ -z "$resolvedIP6" ]; then
- state add 'errorSummary' 'errorFailedToResolve' "$value"
- fi
- param4="$param4 $negation -s $resolvedIP4"
- param6="$param6 $negation -s $resolvedIP6"
- fi
- fi
- fi
-
- if [ -n "$lport" ]; then
- if [ "${lport:0:1}" = "!" ]; then
- negation='!'; value="${lport:1}"
- else
- unset negation; value="$lport";
- fi
- param4="$param4 -m multiport $negation --sport ${value//-/:}"
- param6="$param6 -m multiport $negation --sport ${value//-/:}"
- fi
-
- if [ -n "$raddr" ]; then
- if [ "${raddr:0:1}" = "!" ]; then
- negation='!'; value="${raddr:1}"
- else
- unset negation; value="$raddr";
- fi
- if is_netmask "$value"; then
- local target='dst' type='net'
- if ips 'create' "$iface" "$target" "$type" "$uid" "${name}: $raddr" && \
- ips 'add' "$iface" "$target" "$type" "$uid" "${name}: $raddr" "$value"; then
- param4="$param4 -m set $negation --match-set ${ipsPrefix}_${iface}_4_${target}_${type}_${uid} $target"
- param6="$param6 -m set $negation --match-set ${ipsPrefix}_${iface}_6_${target}_${type}_${uid} $target"
- else
- param4="$param4 $negation -d $value"
- param6="$param6 $negation -d $value"
- fi
- elif is_domain "$value"; then
- local target='dst' type='ip'
- if resolver 'create_resolver_set' "$iface" "$target" "$type" "$uid" "${name}: $raddr" && \
- resolver 'add_resolver_element' "$iface" "$target" "$type" "$uid" "${name}: $raddr" "$value"; then
- param4="$param4 -m set $negation --match-set ${ipsPrefix}_${iface}_4_${target}_${type}_${uid} $target"
- param6="$param6 -m set $negation --match-set ${ipsPrefix}_${iface}_6_${target}_${type}_${uid} $target"
- elif ips 'create' "$iface" "$target" "$type" "$uid" "${name}: $raddr" && \
- ips 'add' "$iface" "$target" "$type" "$uid" "${name}: $raddr" "$value"; then
- param4="$param4 -m set $negation --match-set ${ipsPrefix}_${iface}_4_${target}_${type}_${uid} $target"
- param6="$param6 -m set $negation --match-set ${ipsPrefix}_${iface}_6_${target}_${type}_${uid} $target"
- else
- local resolvedIP4 resolvedIP6
- resolvedIP4="$(resolveip_to_ipt4 "$value")"
- resolvedIP6="$(resolveip_to_ipt6 "$value")"
- if [ -z "$resolvedIP4" ] && [ -z "$resolvedIP6" ]; then
- state add 'errorSummary' 'errorFailedToResolve' "$value"
- fi
- param4="$param4 $negation -d $resolvedIP4"
- param6="$param6 $negation -d $resolvedIP6"
- fi
- else
- local target='dst' type='ip'
- if ips 'create' "$iface" "$target" "$type" "$uid" "${name}: $raddr" && \
- ips 'add' "$iface" "$target" "$type" "$uid" "${name}: $raddr" "$value"; then
- param4="$param4 -m set $negation --match-set ${ipsPrefix}_${iface}_4_${target}_${type}_${uid} $target"
- param6="$param6 -m set $negation --match-set ${ipsPrefix}_${iface}_6_${target}_${type}_${uid} $target"
- else
- param4="$param4 $negation -d $value"
- param6="$param6 $negation -d $value"
- fi
- fi
- fi
-
- if [ -n "$rport" ]; then
- if [ "${rport:0:1}" = "!" ]; then
- negation='!'; value="${rport:1}"
- else
- unset negation; value="$rport";
- fi
- param4="$param4 -m multiport $negation --dport ${value//-/:}"
- param6="$param6 -m multiport $negation --dport ${value//-/:}"
- fi
-
- if [ -n "$name" ]; then
- param4="$param4 -m comment --comment $(str_extras_to_underscore "$name")"
- param6="$param6 -m comment --comment $(str_extras_to_underscore "$name")"
- fi
-
- local ipv4_error='0' ipv6_error='0'
- if [ "$param4" = "$param6" ]; then
- ipt4 "$param4" || ipv4_error='1'
- else
- ipt4 "$param4" || ipv4_error='1'
- ipt6 "$param6" || ipv6_error='1'
- fi
-
- if [ -n "$ipv6_enabled" ] && [ "$ipv4_error" -eq '1' ] && [ "$ipv6_error" -eq '1' ]; then
- processPolicyError='true'
- state add 'errorSummary' 'errorPolicyProcessInsertionFailed' "$name"
- state add 'errorSummary' 'errorPolicyProcessCMD' "iptables $param4"
- state add 'errorSummary' 'errorPolicyProcessCMD' "iptables $param6"
- logger -t "$packageName" "ERROR: iptables $param4"
- logger -t "$packageName" "ERROR: iptables $param6"
- elif [ -z "$ipv6_enabled" ] && [ "$ipv4_error" -eq '1' ]; then
- processPolicyError='true'
- state add 'errorSummary' 'errorPolicyProcessInsertionFailedIpv4' "$name"
- state add 'errorSummary' 'errorPolicyProcessCMD' "iptables $param4"
- logger -t "$packageName" "ERROR: iptables $param4"
- fi
-
- done
-}
-policy_routing_nft() {
- local mark i nftInsertOption='add'
- local param4 param6 proto_i negation value dest
- local ip4Flag='ip' ip6Flag='ip6'
- local name="$1" iface="$2" laddr="$3" lport="$4" raddr="$5" rport="$6" proto chain uid="$9"
- proto="$(str_to_lower "$7")"
- chain="$(str_to_lower "$8")"
- chain="${chain:-prerouting}"
- mark=$(eval echo "\$mark_${iface//-/_}")
-
- if [ -z "$ipv6_enabled" ] && { is_ipv6 "$src_addr" || is_ipv6 "$dest_addr"; }; then
- processPolicyError='true'
- state add 'errorSummary' 'errorPolicyProcessNoIpv6' "$name"
- return 1
- fi
-
- if [ -n "$mark" ]; then
- dest="goto ${nftPrefix}_mark_${mark}"
- elif [ "$iface" = "ignore" ]; then
- dest="return"
- else
- processPolicyError='true'
- state add 'errorSummary' 'errorPolicyProcessUnknownFwmark' "$iface"
- return 1
- fi
-
- if is_family_mismatch "$src_addr" "$dest_addr"; then
- processPolicyError='true'
- state add 'errorSummary' 'errorPolicyProcessMismatchFamily' "${name}: '$laddr' '$raddr'"
- return 1
- fi
-
- if [ -z "$proto" ]; then
- if [ -n "${src_port}${dest_port}" ]; then
- proto='tcp udp'
- else
- proto='all'
- fi
- fi
-
- for proto_i in $proto; do
- unset param4
- unset param6
- if [ "$proto_i" = 'all' ]; then
- unset proto_i
- elif ! is_supported_protocol "$proto_i"; then
- processPolicyError='true'
- state add 'errorSummary' 'errorPolicyProcessUnknownProtocol' "${name}: '$proto_i'"
- return 1
- fi
-
- if [ -n "$src_addr" ]; then
- if [ "${src_addr:0:1}" = "!" ]; then
- negation='!='; value="${src_addr:1}"
- else
- unset negation; value="$src_addr";
- fi
- if is_phys_dev "$value"; then
- param4="$param4 iifname $negation ${value:1}"
- param6="$param6 iifname $negation ${value:1}"
- elif is_mac_address "$value"; then
- local target='src' type='mac'
- if nftset 'create' "$iface" "$target" "$type" "$uid" "$name" && \
- nftset 'add' "$iface" "$target" "$type" "$uid" "$name" "$value"; then
- param4="$param4 ether saddr $negation @${nftPrefix}_${iface}_4_${target}_${type}_${uid}"
- param6="$param6 ether saddr $negation @${nftPrefix}_${iface}_6_${target}_${type}_${uid}"
- else
- param4="$param4 ether saddr $negation $value"
- param6="$param6 ether saddr $negation $value"
- fi
- else
- local target='src' type='ip'
- if nftset 'create' "$iface" "$target" "$type" "$uid" "$name" && \
- nftset 'add' "$iface" "$target" "$type" "$uid" "$name" "$value"; then
- param4="$param4 $ip4Flag saddr $negation @${nftPrefix}_${iface}_4_${target}_${type}_${uid}"
- param6="$param6 $ip6Flag saddr $negation @${nftPrefix}_${iface}_6_${target}_${type}_${uid}"
- else
- param4="$param4 $ip4Flag saddr $negation $value"
- param6="$param6 $ip6Flag saddr $negation $value"
- fi
- fi
- fi
-
- if [ -n "$dest_addr" ]; then
- if [ "${dest_addr:0:1}" = "!" ]; then
- negation='!='; value="${dest_addr:1}"
- else
- unset negation; value="$dest_addr";
- fi
- if is_phys_dev "$value"; then
- param4="$param4 oifname $negation ${value:1}"
- param6="$param6 oifname $negation ${value:1}"
- elif is_domain "$value"; then
- local target='dst' type='ip'
- if resolver 'create_resolver_set' "$iface" "$target" "$type" "$uid" "$name" && \
- resolver 'add_resolver_element' "$iface" "$target" "$type" "$uid" "$name" "$value"; then
- param4="$param4 $ip4Flag daddr $negation @${nftPrefix}_${iface}_4_${target}_${type}_${uid}"
- param6="$param6 $ip6Flag daddr $negation @${nftPrefix}_${iface}_6_${target}_${type}_${uid}"
- elif nftset 'create' "$iface" "$target" "$type" "$uid" "$name" && \
- nftset 'add' "$iface" "$target" "$type" "$uid" "$name" "$value"; then
- param4="$param4 $ip4Flag daddr $negation @${nftPrefix}_${iface}_4_${target}_${type}_${uid}"
- param6="$param6 $ip6Flag daddr $negation @${nftPrefix}_${iface}_6_${target}_${type}_${uid}"
- else
- local resolvedIP4 resolvedIP6
- resolvedIP4="$(resolveip_to_nftset4 "$value")"
- resolvedIP6="$(resolveip_to_nftset6 "$value")"
- if [ -z "$resolvedIP4" ] && [ -z "$resolvedIP6" ]; then
- state add 'errorSummary' 'errorFailedToResolve' "$value"
- fi
- param4="$param4 $ip4Flag daddr $negation { $resolvedIP4 }"
- param6="$param6 $ip6Flag daddr $negation { $resolvedIP6 }"
- fi
- else
- local target='dst' type='ip'
- if nftset 'create' "$iface" "$target" "$type" "$uid" "$name" && \
- nftset 'add' "$iface" "$target" "$type" "$uid" "$name" "$value"; then
- param4="$param4 $ip4Flag daddr $negation @${nftPrefix}_${iface}_4_${target}_${type}_${uid}"
- param6="$param6 $ip6Flag daddr $negation @${nftPrefix}_${iface}_6_${target}_${type}_${uid}"
- else
- param4="$param4 $ip4Flag daddr $negation $value"
- param6="$param6 $ip6Flag daddr $negation $value"
- fi
- fi
- fi
-
- if [ -n "$src_port" ]; then
- if [ "${src_port:0:1}" = "!" ]; then
- negation='!='; value="${src_port:1}"
- else
- unset negation; value="$src_port";
- fi
- param4="$param4 ${proto_i:+$proto_i }sport $negation {$(ports_to_nftset "$value")}"
- param6="$param6 ${proto_i:+$proto_i }sport $negation {$(ports_to_nftset "$value")}"
- fi
-
- if [ -n "$dest_port" ]; then
- if [ "${dest_port:0:1}" = "!" ]; then
- negation='!='; value="${dest_port:1}"
- else
- unset negation; value="$dest_port";
- fi
- param4="$param4 ${proto_i:+$proto_i }dport $negation {$(ports_to_nftset "$value")}"
- param6="$param6 ${proto_i:+$proto_i }dport $negation {$(ports_to_nftset "$value")}"
- fi
-
- param4="$nftInsertOption rule inet $nftTable ${nftPrefix}_${chain} $param4 $dest comment \"$name\""
- param6="$nftInsertOption rule inet $nftTable ${nftPrefix}_${chain} $param6 $dest comment \"$name\""
-
- local ipv4_error='0' ipv6_error='0'
- if [ "$nftPrevParam4" != "$param4" ]; then
- nft4 "$param4" || ipv4_error='1'
- nftPrevParam4="$param4"
- fi
- if [ "$nftPrevParam6" != "$param6" ]; then
- nft6 "$param6" || ipv6_error='1'
- nftPrevParam6="$param6"
- fi
-
- if [ -n "$ipv6_enabled" ] && [ "$ipv4_error" -eq '1' ] && [ "$ipv6_error" -eq '1' ]; then
- processPolicyError='true'
- state add 'errorSummary' 'errorPolicyProcessInsertionFailed' "$name"
- state add 'errorSummary' 'errorPolicyProcessCMD' "nft $param4"
- state add 'errorSummary' 'errorPolicyProcessCMD' "nft $param6"
- logger -t "$packageName" "ERROR: nft $param4"
- logger -t "$packageName" "ERROR: nft $param6"
- elif [ -z "$ipv6_enabled" ] && [ "$ipv4_error" -eq '1' ]; then
- processPolicyError='true'
- state add 'errorSummary' 'errorPolicyProcessInsertionFailedIpv4' "$name"
- state add 'errorSummary' 'errorPolicyProcessCMD' "nft $param4"
- logger -t "$packageName" "ERROR: nft $param4"
- fi
-
- done
-}
-
-policy_process() {
- local i j uid="$9"
- if [ -z "$uid" ]; then # first non-recursive call
- [ "$enabled" -gt 0 ] || return 0
- unset processPolicyError
- uid="$1"
- if is_nft; then
- chain="$(str_to_lower "$chain")"
- else
- chain="$(str_to_upper "$chain")"
- fi
- proto="$(str_to_lower "$proto")"
- [ "$proto" = 'auto' ] && unset proto
- [ "$proto" = 'all' ] && unset proto
- output 2 "Routing '$name' via $interface "
- if [ -z "${src_addr}${src_port}${dest_addr}${dest_port}" ]; then
- state add 'errorSummary' 'errorPolicyNoSrcDest' "$name"
- output_fail; return 1;
- fi
- if [ -z "$interface" ]; then
- state add 'errorSummary' 'errorPolicyNoInterface' "$name"
- output_fail; return 1;
- fi
- if ! is_supported_interface "$interface"; then
- state add 'errorSummary' 'errorPolicyUnknownInterface' "$name"
- output_fail; return 1;
- fi
- src_port="${src_port// / }"; src_port="${src_port// /,}"; src_port="${src_port//,\!/ !}";
- dest_port="${dest_port// / }"; dest_port="${dest_port// /,}"; dest_port="${dest_port//,\!/ !}";
-# if is_nft; then
-# nftset 'flush' "$interface" "dst" "ip" "$uid"
-# nftset 'flush' "$interface" "src" "ip" "$uid"
-# nftset 'flush' "$interface" "src" "mac" "$uid"
-# else
-# ips 'flush' "$interface" "dst" "ip" "$uid"
-# ips 'flush' "$interface" "src" "ip" "$uid"
-# ips 'flush' "$interface" "src" "mac" "$uid"
-# fi
- policy_process "$name" "$interface" "$src_addr" "$src_port" "$dest_addr" "$dest_port" "$proto" "$chain" "$uid"
- if [ -n "$processPolicyError" ]; then
- output_fail
- else
- output_ok
- fi
- else # recursive call, get options from passed variables
- local name="$1" interface="$2" src_addr="$3" src_port="$4" dest_addr="$5" dest_port="$6" proto="$7" chain="$8"
- if str_contains "$src_addr" '[ ;\{\}]'; then
- for i in $(str_extras_to_space "$src_addr"); do [ -n "$i" ] && policy_process "$name" "$interface" "$i" "$src_port" "$dest_addr" "$dest_port" "$proto" "$chain" "$uid"; done
- elif str_contains "$src_port" '[ ;\{\}]'; then
- for i in $(str_extras_to_space "$src_port"); do [ -n "$i" ] && policy_process "$name" "$interface" "$src_addr" "$i" "$dest_addr" "$dest_port" "$proto" "$chain" "$uid"; done
- elif str_contains "$dest_addr" '[ ;\{\}]'; then
- for i in $(str_extras_to_space "$dest_addr"); do [ -n "$i" ] && policy_process "$name" "$interface" "$src_addr" "$src_port" "$i" "$dest_port" "$proto" "$chain" "$uid"; done
- elif str_contains "$dest_port" '[ ;\{\}]'; then
- for i in $(str_extras_to_space "$dest_port"); do [ -n "$i" ] && policy_process "$name" "$interface" "$src_addr" "$src_port" "$dest_addr" "$i" "$proto" "$chain" "$uid"; done
- elif str_contains "$proto" '[ ;\{\}]'; then
- for i in $(str_extras_to_space "$proto"); do [ -n "$i" ] && policy_process "$name" "$interface" "$src_addr" "$src_port" "$dest_addr" "$dest_port" "$i" "$chain" "$uid"; done
- else
- if is_tor "$interface"; then
- policy_routing_tor "$name" "$interface" "$src_addr" "$src_port" "$dest_addr" "$dest_port" "$proto" "$chain" "$uid"
- else
- policy_routing "$name" "$interface" "$src_addr" "$src_port" "$dest_addr" "$dest_port" "$proto" "$chain" "$uid"
- fi
- fi
- fi
-}
-
-interface_process_tor() { if is_nft; then interface_process_tor_nft "$@"; else interface_process_tor_iptables "$@"; fi; }
-interface_process_tor_iptables() {
- local s=0 iface="$1" action="$2"
- local displayText set_name4 set_name6
- local dnsPort trafficPort
- case "$action" in
- reload)
- displayText="${iface}/53->${dnsPort}/80,443->${trafficPort}"
- gatewaySummary="${gatewaySummary}${displayText}\\n"
- ;;
- destroy)
- for i in $chainsList; do
- i="$(str_to_upper "$i")"
- ipt -t nat -D "${i}" -m mark --mark "0x0/${fw_mask}" -j "${iptPrefix}_${i}"
- ipt -t nat -F "${iptPrefix}_${i}"; ipt -t nat -X "${iptPrefix}_${i}";
- done
- ;;
- create)
- output 2 "Creating TOR redirects "
- dnsPort="$(grep -m1 DNSPort /etc/tor/torrc | awk -F: '{print $2}')"
- trafficPort="$(grep -m1 TransPort /etc/tor/torrc | awk -F: '{print $2}')"
- dnsPort="${dnsPort:-9053}"; trafficPort="${trafficPort:-9040}";
- for i in $chainsList; do
- i="$(str_to_upper "$i")"
- ipt -t nat -N "${iptPrefix}_${i}"
- ipt -t nat -A "$i" -m mark --mark "0x0/${fw_mask}" -j "${iptPrefix}_${i}"
- done
- if resolver 'create_resolver_set' "$iface" 'dst' 'ip' && ips 'flush' "$iface" 'dst' 'ip'; then
- set_name4="${ipsPrefix}_${iface}_4_dst_ip"
- for i in $chainsList; do
- i="$(str_to_upper "$i")"
- ipt -t nat -I "${iptPrefix}_${i}" -p udp -m udp --dport 53 -m set --match-set "${set_name4}" dst -j REDIRECT --to-ports "$dnsPort" -m comment --comment "TorDNS-UDP" || s=1
- ipt -t nat -I "${iptPrefix}_${i}" -p tcp -m tcp --dport 80 -m set --match-set "${set_name4}" dst -j REDIRECT --to-ports "$trafficPort" -m comment --comment "TorHTTP-TCP" || s=1
- ipt -t nat -I "${iptPrefix}_${i}" -p udp -m udp --dport 80 -m set --match-set "${set_name4}" dst -j REDIRECT --to-ports "$trafficPort" -m comment --comment "TorHTTP-UDP" || s=1
- ipt -t nat -I "${iptPrefix}_${i}" -p tcp -m tcp --dport 443 -m set --match-set "${set_name4}" dst -j REDIRECT --to-ports "$trafficPort" -m comment --comment "TorHTTPS-TCP" || s=1
- ipt -t nat -I "${iptPrefix}_${i}" -p udp -m udp --dport 443 -m set --match-set "${set_name4}" dst -j REDIRECT --to-ports "$trafficPort" -m comment --comment "TorHTTPS-UDP" || s=1
- done
- else
- s=1
- fi
- displayText="${iface}/53->${dnsPort}/80,443->${trafficPort}"
- if [ "$s" -eq 0 ]; then
- gatewaySummary="${gatewaySummary}${displayText}\\n"
- output_ok
- else
- state add 'errorSummary' 'errorFailedSetup' "$displayText"
- output_fail
- fi
- ;;
- esac
- return $s
-}
-interface_process_tor_nft() {
- local s=0 iface="$1" action="$2"
- local displayText set_name4 set_name6
- local dnsPort trafficPort
- case "$action" in
- reload)
- displayText="${iface}/53->${dnsPort}/80,443->${trafficPort}"
- gatewaySummary="${gatewaySummary}${displayText}\\n"
- ;;
- destroy)
- ;;
- create)
- output 2 "Creating TOR redirects "
- dnsPort="$(grep -m1 DNSPort /etc/tor/torrc | awk -F: '{print $2}')"
- trafficPort="$(grep -m1 TransPort /etc/tor/torrc | awk -F: '{print $2}')"
- dnsPort="${dnsPort:-9053}"; trafficPort="${trafficPort:-9040}";
- if resolver 'create_resolver_set' "$iface" 'dst' 'ip' && nftset 'flush' "$iface" 'dst' 'ip'; then
- set_name4="${nftPrefix}_${iface}_4_dst_ip"
- set_name6="${nftPrefix}_${iface}_6_dst_ip"
- nft add rule inet "$nftTable" dstnat meta nfproto ipv4 ip daddr "@${set_name4}" udp dport 53 counter redirect to :"$dnsPort" comment "Tor-DNS-UDP-ipv4" || s=1
- nft add rule inet "$nftTable" dstnat meta nfproto ipv4 ip daddr "@${set_name4}" tcp dport 80 counter redirect to :"$trafficPort" comment "Tor-HTTP-TCP-ipv4" || s=1
- nft add rule inet "$nftTable" dstnat meta nfproto ipv4 ip daddr "@${set_name4}" udp dport 80 counter redirect to :"$trafficPort" comment "Tor-HTTP-UDP-ipv4" || s=1
- nft add rule inet "$nftTable" dstnat meta nfproto ipv4 ip daddr "@${set_name4}" tcp dport 443 counter redirect to :"$trafficPort" comment "Tor-HTTPS-TCP-ipv4" || s=1
- nft add rule inet "$nftTable" dstnat meta nfproto ipv4 ip daddr "@${set_name4}" udp dport 443 counter redirect to :"$trafficPort" comment "Tor-HTTPS-UDP-ipv4" || s=1
- nft6 add rule inet "$nftTable" dstnat meta nfproto ipv6 ip6 daddr "@${set_name6}" udp dport 53 counter redirect to :"$dnsPort" comment "Tor-DNS-UDP-ipv6" || s=1
- nft6 add rule inet "$nftTable" dstnat meta nfproto ipv6 ip6 daddr "@${set_name6}" tcp dport 80 counter redirect to :"$trafficPort" comment "Tor-HTTP-TCP-ipv6" || s=1
- nft6 add rule inet "$nftTable" dstnat meta nfproto ipv6 ip6 daddr "@${set_name6}" udp dport 80 counter redirect to :"$trafficPort" comment "Tor-HTTP-UDP-ipv6" || s=1
- nft6 add rule inet "$nftTable" dstnat meta nfproto ipv6 ip6 daddr "@${set_name6}" tcp dport 443 counter redirect to :"$trafficPort" comment "Tor-HTTPS-TCP-ipv6" || s=1
- nft6 add rule inet "$nftTable" dstnat meta nfproto ipv6 ip6 daddr "@${set_name6}" udp dport 443 counter redirect to :"$trafficPort" comment "Tor-HTTPS-UDP-ipv6" || s=1
- else
- s=1
- fi
- displayText="${iface}/53->${dnsPort}/80,443->${trafficPort}"
- if [ "$s" -eq 0 ]; then
- gatewaySummary="${gatewaySummary}${displayText}\\n"
- output_ok
- else
- state add 'errorSummary' 'errorFailedSetup' "$displayText"
- output_fail
- fi
- ;;
- esac
- return $s
-}
-
-interface_routing() {
- local action="$1" tid="$2" mark="$3" iface="$4" gw4="$5" dev="$6" gw6="$7" dev6="$8" priority="$9"
- local dscp s=0 i ipv4_error=1 ipv6_error=1
- if [ -z "$tid" ] || [ -z "$mark" ] || [ -z "$iface" ]; then
- state add 'errorSummary' 'errorInterfaceRoutingEmptyValues'
- return 1
- fi
- case "$action" in
- create)
- if is_netifd_table "$iface"; then
- ipv4_error=0
- $ip_bin rule del table "$tid" >/dev/null 2>&1
- $ip_bin -4 rule add fwmark "${mark}/${fw_mask}" table "$tid" priority "$priority" || ipv4_error=1
- if is_nft; then
- nft add chain inet "$nftTable" "${nftPrefix}_mark_${mark}" || ipv4_error=1
- nft add rule inet "$nftTable" "${nftPrefix}_mark_${mark} counter mark set mark and ${fw_maskXor} xor ${mark}" || ipv4_error=1
- nft add rule inet "$nftTable" "${nftPrefix}_mark_${mark} return" || ipv4_error=1
- else
- ipt -t mangle -N "${iptPrefix}_MARK_${mark}" || ipv4_error=1
- ipt -t mangle -A "${iptPrefix}_MARK_${mark}" -j MARK --set-xmark "${mark}/${fw_mask}" || ipv4_error=1
- ipt -t mangle -A "${iptPrefix}_MARK_${mark}" -j RETURN || ipv4_error=1
- fi
- if [ -n "$ipv6_enabled" ]; then
- ipv6_error=0
- $ip_bin -6 rule add fwmark "${mark}/${fw_mask}" table "$tid" priority "$priority" || ipv6_error=1
- fi
- else
- if ! grep -q "$tid ${ipTablePrefix}_${iface}" '/etc/iproute2/rt_tables'; then
- sed -i "/${ipTablePrefix}_${iface}/d" '/etc/iproute2/rt_tables'
- sync
- echo "$tid ${ipTablePrefix}_${iface}" >> '/etc/iproute2/rt_tables'
- sync
- fi
- $ip_bin rule del table "$tid" >/dev/null 2>&1
- $ip_bin route flush table "$tid" >/dev/null 2>&1
- if [ -n "$gw4" ] || [ "$strict_enforcement" -ne 0 ]; then
- ipv4_error=0
- if [ -z "$gw4" ]; then
- $ip_bin -4 route add unreachable default table "$tid" >/dev/null 2>&1 || ipv4_error=1
- else
- $ip_bin -4 route add default via "$gw4" dev "$dev" table "$tid" >/dev/null 2>&1 || ipv4_error=1
- fi
-# shellcheck disable=SC2086
- while read -r i; do
- i="$(echo "$i" | sed 's/ linkdown$//')"
- i="$(echo "$i" | sed 's/ onlink$//')"
- idev="$(echo "$i" | grep -Eso 'dev [^ ]*' | awk '{print $2}')"
- if ! is_supported_iface_dev "$idev"; then
- $ip_bin -4 route add $i table "$tid" >/dev/null 2>&1 || ipv4_error=1
- fi
- done << EOF
- $($ip_bin -4 route list table main)
-EOF
- $ip_bin -4 rule add fwmark "${mark}/${fw_mask}" table "$tid" priority "$priority" || ipv4_error=1
- if is_nft; then
- nft add chain inet "$nftTable" "${nftPrefix}_mark_${mark}" || ipv4_error=1
- nft add rule inet "$nftTable" "${nftPrefix}_mark_${mark} counter mark set mark and ${fw_maskXor} xor ${mark}" || ipv4_error=1
- nft add rule inet "$nftTable" "${nftPrefix}_mark_${mark} return" || ipv4_error=1
- else
- ipt -t mangle -N "${iptPrefix}_MARK_${mark}" || ipv4_error=1
- ipt -t mangle -A "${iptPrefix}_MARK_${mark}" -j MARK --set-xmark "${mark}/${fw_mask}" || ipv4_error=1
- ipt -t mangle -A "${iptPrefix}_MARK_${mark}" -j RETURN || ipv4_error=1
- fi
- fi
- if [ -n "$ipv6_enabled" ]; then
- ipv6_error=0
- if { [ -n "$gw6" ] && [ "$gw6" != "::/0" ]; } || [ "$strict_enforcement" -ne 0 ]; then
- if [ -z "$gw6" ] || [ "$gw6" = "::/0" ]; then
- $ip_bin -6 route add unreachable default table "$tid" >/dev/null 2>&1 || ipv6_error=1
- elif $ip_bin -6 route list table main | grep -q " dev $dev6 "; then
- while read -r i; do
- i="$(echo "$i" | sed 's/ linkdown$//')"
- i="$(echo "$i" | sed 's/ onlink$//')"
- # shellcheck disable=SC2086
- $ip_bin -6 route add $i table "$tid" >/dev/null 2>&1 || ipv6_error=1
- done << EOF
- $($ip_bin -6 route list table main | grep " dev $dev6 ")
-EOF
- else
- $ip_bin -6 route add "$($ip_bin -6 -o a show "$dev6" | awk '{print $4}')" dev "$dev6" table "$tid" >/dev/null 2>&1 || ipv6_error=1
- $ip_bin -6 route add default dev "$dev6" table "$tid" >/dev/null 2>&1 || ipv6_error=1
- fi
- fi
- $ip_bin -6 rule add fwmark "${mark}/${fw_mask}" table "$tid" priority "$priority" >/dev/null 2>&1 || ipv6_error=1
- fi
- fi
- if [ "$ipv4_error" -eq 0 ] || [ "$ipv6_error" -eq 0 ]; then
- dscp="$(uci -q get "${packageName}".config."${iface}"_dscp)"
- if is_nft; then
- if [ "${dscp:-0}" -ge 1 ] && [ "${dscp:-0}" -le 63 ]; then
- nft add rule inet "$nftTable" "${nftPrefix}_prerouting ip dscp ${dscp} goto ${nftPrefix}_mark_${mark}" || s=1
- fi
- if [ "$iface" = "$icmp_interface" ]; then
- nft add rule inet "$nftTable" "${nftPrefix}_output ip protocol icmp goto ${nftPrefix}_mark_${mark}" || s=1
- fi
- else
- if [ "${dscp:-0}" -ge 1 ] && [ "${dscp:-0}" -le 63 ]; then
- ipt -t mangle -I "${iptPrefix}_PREROUTING" -m dscp --dscp "${dscp}" -g "${iptPrefix}_MARK_${mark}" || s=1
- fi
- if [ "$iface" = "$icmp_interface" ]; then
- ipt -t mangle -I "${iptPrefix}_OUTPUT" -p icmp -g "${iptPrefix}_MARK_${mark}" || s=1
- fi
- fi
- else
- s=1
- fi
- return "$s"
- ;;
- create_user_set)
- if is_nft; then
- nftset 'create_user_set' "$iface" 'dst' 'ip' 'user' '' "$mark" || s=1
- nftset 'create_user_set' "$iface" 'src' 'ip' 'user' '' "$mark" || s=1
- nftset 'create_user_set' "$iface" 'src' 'mac' 'user' '' "$mark" || s=1
- else
- ips 'create_user_set' "$iface" 'dst' 'ip' 'user' '' "$mark" || s=1
- ips 'create_user_set' "$iface" 'src' 'ip' 'user' '' "$mark" || s=1
- ips 'create_user_set' "$iface" 'dst' 'net' 'user' '' "$mark" || s=1
- ips 'create_user_set' "$iface" 'src' 'net' 'user' '' "$mark" || s=1
- ips 'create_user_set' "$iface" 'src' 'mac' 'user' '' "$mark" || s=1
- fi
- return "$s"
- ;;
- delete|destroy)
- $ip_bin rule del table "$tid" >/dev/null 2>&1
- if ! is_netifd_table "$iface"; then
- $ip_bin route flush table "$tid" >/dev/null 2>&1
- sed -i "/${ipTablePrefix}_${iface}\$/d" '/etc/iproute2/rt_tables'
- sync
- fi
- return "$s"
- ;;
- reload_interface)
- is_netifd_table "$iface" && return 0;
- ipv4_error=0
- $ip_bin rule del table "$tid" >/dev/null 2>&1
- if ! is_netifd_table "$iface"; then
- $ip_bin route flush table "$tid" >/dev/null 2>&1
- fi
- if [ -n "$gw4" ] || [ "$strict_enforcement" -ne 0 ]; then
- if [ -z "$gw4" ]; then
- $ip_bin -4 route add unreachable default table "$tid" >/dev/null 2>&1 || ipv4_error=1
- else
- $ip_bin -4 route add default via "$gw4" dev "$dev" table "$tid" >/dev/null 2>&1 || ipv4_error=1
- fi
- $ip_bin rule add fwmark "${mark}/${fw_mask}" table "$tid" priority "$priority" || ipv4_error=1
- fi
- if [ -n "$ipv6_enabled" ]; then
- ipv6_error=0
- if { [ -n "$gw6" ] && [ "$gw6" != "::/0" ]; } || [ "$strict_enforcement" -ne 0 ]; then
- if [ -z "$gw6" ] || [ "$gw6" = "::/0" ]; then
- $ip_bin -6 route add unreachable default table "$tid" || ipv6_error=1
- elif $ip_bin -6 route list table main | grep -q " dev $dev6 "; then
- while read -r i; do
- # shellcheck disable=SC2086
- $ip_bin -6 route add $i table "$tid" >/dev/null 2>&1 || ipv6_error=1
- done << EOF
- $($ip_bin -6 route list table main | grep " dev $dev6 ")
-EOF
- else
- $ip_bin -6 route add "$($ip_bin -6 -o a show "$dev6" | awk '{print $4}')" dev "$dev6" table "$tid" >/dev/null 2>&1 || ipv6_error=1
- $ip_bin -6 route add default dev "$dev6" table "$tid" >/dev/null 2>&1 || ipv6_error=1
- fi
- fi
- $ip_bin -6 rule add fwmark "${mark}/${fw_mask}" table "$tid" priority "$priority" || ipv6_error=1
- fi
- if [ "$ipv4_error" -eq 0 ] || [ "$ipv6_error" -eq 0 ]; then
- s=0
- else
- s=1
- fi
- return "$s"
- ;;
- esac
-}
-
-json_add_gateway() {
- local action="$1" tid="$2" mark="$3" iface="$4" gw4="$5" dev4="$6" gw6="$7" dev6="$8" priority="$9" default="${10}"
- json_add_object ''
- json_add_string name "$iface"
- json_add_string device_ipv4 "$dev4"
- json_add_string gateway_ipv4 "$gw4"
- json_add_string device_ipv6 "$dev6"
- json_add_string gateway_ipv6 "$gw6"
- if [ -n "$default" ]; then
- json_add_boolean default true
- else
- json_add_boolean default false
- fi
- json_add_string action "$action"
- json_add_string table_id "$tid"
- json_add_string mark "$mark"
- json_add_string priority "$priority"
- json_close_object
-}
-
-interface_process() {
- local gw4 gw6 dev dev6 s=0 dscp iface="$1" action="$2" reloadedIface="$3"
- local displayText dispDev dispGw4 dispGw6 dispStatus
-
- if [ "$iface" = 'all' ] && [ "$action" = 'prepare' ]; then
- config_load 'network'
- ifaceMark="$(printf '0x%06x' "$wan_mark")"
- ifacePriority="$wan_ip_rules_priority"
- return 0
- fi
-
- is_supported_interface "$iface" || return 0
- is_wan6 "$iface" && return 0
- [ $((ifaceMark)) -gt $((fw_mask)) ] && return 1
-
- if is_ovpn "$iface" && ! is_valid_ovpn "$iface"; then
- : || state add 'warningSummary' 'warningInvalidOVPNConfig' "$iface"
- fi
-
- network_get_device dev "$iface"
- [ -z "$dev" ] && network_get_physdev dev "$iface"
- if is_wan "$iface" && [ -n "$wanIface6" ] && str_contains "$wanIface6" "$iface"; then
- network_get_device dev6 "$wanIface6"
- [ -z "$dev6" ] && network_get_physdev dev6 "$wanIface6"
- fi
-
- [ -z "$dev6" ] && dev6="$dev"
- [ -z "$ifaceMark" ] && ifaceMark="$(printf '0x%06x' "$wan_mark")"
- [ -z "$ifacePriority" ] && ifacePriority="$wan_ip_rules_priority"
-
- ifaceTableID="$(get_rt_tables_id "$iface")"
- [ -z "$ifaceTableID" ] && ifaceTableID="$(get_rt_tables_next_id)"
- eval "mark_${iface//-/_}"='$ifaceMark'
- eval "tid_${iface//-/_}"='$ifaceTableID'
- pbr_get_gateway gw4 "$iface" "$dev"
- pbr_get_gateway6 gw6 "$iface" "$dev6"
- dispGw4="${gw4:-0.0.0.0}"
- dispGw6="${gw6:-::/0}"
- [ "$iface" != "$dev" ] && dispDev="$dev"
- is_default_dev "$dev" && dispStatus="${__OK__}"
- displayText="${iface}/${dispDev:+$dispDev/}${dispGw4}${ipv6_enabled:+/$dispGw6}"
-
- case "$action" in
- create)
- output 2 "Setting up routing for '$displayText' "
- if interface_routing 'create' "$ifaceTableID" "$ifaceMark" "$iface" "$gw4" "$dev" "$gw6" "$dev6" "$ifacePriority"; then
- json_add_gateway 'create' "$ifaceTableID" "$ifaceMark" "$iface" "$gw4" "$dev" "$gw6" "$dev6" "$ifacePriority" "$dispStatus"
- gatewaySummary="${gatewaySummary}${displayText}${dispStatus:+ $dispStatus}\\n"
- output_ok
- else
- state add 'errorSummary' 'errorFailedSetup' "$displayText"
- output_fail
- fi
- ;;
- create_user_set)
- interface_routing 'create_user_set' "$ifaceTableID" "$ifaceMark" "$iface" "$gw4" "$dev" "$gw6" "$dev6" "$ifacePriority"
- ;;
- destroy)
- displayText="${iface}/${dispDev:+$dispDev/}${dispGw4}${ipv6_enabled:+/$dispGw6}"
- output 2 "Removing routing for '$displayText' "
- interface_routing 'destroy' "${ifaceTableID}" "${ifaceMark}" "${iface}"
- output_ok
- ;;
- reload)
- gatewaySummary="${gatewaySummary}${displayText}${dispStatus:+ $dispStatus}\\n"
- ;;
- reload_interface)
- if [ "$iface" = "$reloadedIface" ]; then
- output 2 "Reloading routing for '$displayText' "
- if interface_routing 'reload_interface' "$ifaceTableID" "$ifaceMark" "$iface" "$gw4" "$dev" "$gw6" "$dev6" "$ifacePriority"; then
- json_add_gateway 'reload_interface' "$ifaceTableID" "$ifaceMark" "$iface" "$gw4" "$dev" "$gw6" "$dev6" "$ifacePriority" "$dispStatus"
- gatewaySummary="${gatewaySummary}${displayText}${dispStatus:+ $dispStatus}\\n"
- output_ok
- else
- state add 'errorSummary' 'errorFailedReload' "$displayText"
- output_fail
- fi
- else
- gatewaySummary="${gatewaySummary}${displayText}${dispStatus:+ $dispStatus}\\n"
- fi
- ;;
- esac
-# ifaceTableID="$((ifaceTableID + 1))"
- ifaceMark="$(printf '0x%06x' $((ifaceMark + wan_mark)))"
- ifacePriority="$((ifacePriority + 1))"
- return $s
-}
-
-user_file_process() {
- local shellBin="${SHELL:-/bin/ash}"
- [ "$enabled" -gt 0 ] || return 0
- if [ ! -s "$path" ]; then
- state add 'errorSummary' 'errorUserFileNotFound' "$path"
- output_fail
- return 1
- fi
- if ! $shellBin -n "$path"; then
- state add 'errorSummary' 'errorUserFileSyntax' "$path"
- output_fail
- return 1
- fi
- output 2 "Running $path "
-# shellcheck disable=SC1090
- if ! . "$path"; then
- state add 'errorSummary' 'errorUserFileRunning' "$path"
- if grep -q -w 'curl' "$path" && ! is_present 'curl'; then
- state add 'errorSummary' 'errorUserFileNoCurl' "$path"
- fi
- output_fail
- return 1
- else
- output_ok
- return 0
- fi
-}
-
-boot() {
- ubus -t 30 wait_for network.interface 2>/dev/null
- rc_procd start_service 'on_boot'
-}
-
-on_firewall_reload() {
- if [ -e "$packageLockFile" ]; then # service is stopped, do not start it on firewall reload
- logger -t "$packageName" "Reload on firewall action aborted: service is stopped."
- return 0
- else
- rc_procd start_service 'on_firewall_reload' "$1"
- fi
-}
-on_interface_reload() {
- if [ -e "$packageLockFile" ]; then # service is stopped, do not start it on interface change
- logger -t "$packageName" "Reload on interface change aborted: service is stopped."
- return 0
- else
- rc_procd start_service 'on_interface_reload' "$1"
- fi
-}
-
-start_service() {
- local resolverStoredHash resolverNewHash i param="$1" reloadedIface
-
- load_environment 'on_start' "$(load_validate_config)" || return 1
- is_wan_up || return 1
- rm -f "$nftTempFile"
-
- case "$param" in
- on_boot)
- serviceStartTrigger='on_start'
- ;;
- on_firewall_reload)
- serviceStartTrigger='on_start'
- ;;
- on_interface_reload)
- reloadedIface="$2"
- if is_ovpn "$reloadedIface"; then
- logger -t "$packageName" "Updated interface is an OpenVPN tunnel, restarting."
- serviceStartTrigger='on_start'
- unset reloadedIface
- else
- serviceStartTrigger='on_interface_reload'
- fi
- ;;
- on_reload)
- serviceStartTrigger='on_reload'
- ;;
- on_restart)
- serviceStartTrigger='on_start'
- ;;
- esac
-
- if [ -n "$reloadedIface" ] && ! is_supported_interface "$reloadedIface"; then
- return 0
- fi
-
- if [ -n "$(ubus_get_status error)" ] || [ -n "$(ubus_get_status warning)" ]; then
- serviceStartTrigger='on_start'
- unset reloadedIface
- elif ! is_service_running; then
- serviceStartTrigger='on_start'
- unset reloadedIface
- elif [ -z "$(ubus_get_status gateway)" ]; then
- serviceStartTrigger='on_start'
- unset reloadedIface
- elif [ "$serviceStartTrigger" = 'on_interface_reload' ] && \
- [ -z "$(ubus_get_interface "$reloadedIface" 'gateway_4')" ] && \
- [ -z "$(ubus_get_interface "$reloadedIface" 'gateway_6')" ]; then
- serviceStartTrigger='on_start'
- unset reloadedIface
- else
- serviceStartTrigger="${serviceStartTrigger:-on_start}"
- fi
-
- procd_open_instance "main"
- procd_set_param command /bin/true
- procd_set_param stdout 1
- procd_set_param stderr 1
- procd_open_data
-
- case $serviceStartTrigger in
- on_interface_reload)
- output 1 "Reloading Interface: $reloadedIface "
- json_add_array 'gateways'
- interface_process 'all' 'prepare'
- config_foreach interface_process 'interface' 'reload_interface' "$reloadedIface"
- json_close_array
- output 1 '\n'
- ;;
- on_reload)
- traffic_killswitch 'insert'
- resolver 'store_hash'
- resolver 'cleanup_all'
- resolver 'configure'
- resolver 'init'
- cleanup_main_chains
- cleanup_sets
- if ! is_nft; then
- for i in $chainsList; do
- i="$(str_to_upper "$i")"
- ipt -t mangle -N "${iptPrefix}_${i}"
- ipt -t mangle "$rule_create_option" "$i" -m mark --mark "0x0/${fw_mask}" -j "${iptPrefix}_${i}"
- done
- fi
- json_add_array 'gateways'
- interface_process 'all' 'prepare'
- config_foreach interface_process 'interface' 'reload'
- interface_process_tor 'tor' 'destroy'
- is_tor_running && interface_process_tor 'tor' 'reload'
- json_close_array
- if is_config_enabled 'policy'; then
- output 1 'Processing policies '
- config_load "$packageName"
- config_foreach load_validate_policy 'policy' policy_process
- output 1 '\n'
- fi
- if is_config_enabled 'include'; then
- interface_process 'all' 'prepare'
- config_foreach interface_process 'interface' 'create_user_set'
- output 1 'Processing user file(s) '
- config_load "$packageName"
- config_foreach load_validate_include 'include' user_file_process
- output 1 '\n'
- fi
- resolver 'init_end'
- resolver 'compare_hash' && resolver 'restart'
- traffic_killswitch 'remove'
- ;;
- on_start|*)
- traffic_killswitch 'insert'
- resolver 'store_hash'
- resolver 'cleanup_all'
- resolver 'configure'
- resolver 'init'
- cleanup_main_chains
- cleanup_sets
- cleanup_marking_chains
- cleanup_rt_tables
- if ! is_nft; then
- for i in $chainsList; do
- i="$(str_to_upper "$i")"
- ipt -t mangle -N "${iptPrefix}_${i}"
- ipt -t mangle "$rule_create_option" "$i" -m mark --mark "0x0/${fw_mask}" -j "${iptPrefix}_${i}"
- done
- fi
- output 1 'Processing interfaces '
- json_add_array 'gateways'
- interface_process 'all' 'prepare'
- config_foreach interface_process 'interface' 'create'
- interface_process_tor 'tor' 'destroy'
- is_tor_running && interface_process_tor 'tor' 'create'
- json_close_array
- ip route flush cache
- output 1 '\n'
- if is_config_enabled 'policy'; then
- output 1 'Processing policies '
- config_load "$packageName"
- config_foreach load_validate_policy 'policy' policy_process
- output 1 '\n'
- fi
- if is_config_enabled 'include'; then
- interface_process 'all' 'prepare'
- config_foreach interface_process 'interface' 'create_user_set'
- output 1 'Processing user file(s) '
- config_load "$packageName"
- config_foreach load_validate_include 'include' user_file_process
- output 1 '\n'
- fi
- resolver 'init_end'
- resolver 'compare_hash' && resolver 'restart'
- traffic_killswitch 'remove'
- ;;
- esac
-
- if [ -z "$gatewaySummary" ]; then
- state add 'errorSummary' 'errorNoGateways'
- fi
- json_add_object 'status'
- [ -n "$gatewaySummary" ] && json_add_string 'gateways' "$gatewaySummary"
- [ -n "$errorSummary" ] && json_add_string 'errors' "$errorSummary"
- [ -n "$warningSummary" ] && json_add_string 'warnings' "$warningSummary"
- if [ "$strict_enforcement" -ne 0 ] && str_contains "$gatewaySummary" '0.0.0.0'; then
- json_add_string 'mode' "strict"
- fi
- json_close_object
- procd_close_data
- procd_close_instance
-}
-
-service_started() {
- if is_nft; then
- [ -n "$gatewaySummary" ] && output "$serviceName (nft) started with gateways:\\n${gatewaySummary}"
- else
- [ -n "$gatewaySummary" ] && output "$serviceName (iptables) started with gateways:\\n${gatewaySummary}"
- fi
- state print 'errorSummary'
- state print 'warningSummary'
- if [ -n "$errorSummary" ]; then
- return 2
- elif [ -n "$warningSummary" ]; then
- return 1
- else
- return 0
- fi
-}
-
-service_triggers() {
- local n
- load_environment 'on_triggers'
-# shellcheck disable=SC2034
- PROCD_RELOAD_DELAY=$(( procd_reload_delay * 1000 ))
- procd_open_validate
- load_validate_config
- load_validate_policy
- load_validate_include
- procd_close_validate
- procd_open_trigger
- procd_add_reload_trigger 'openvpn'
- procd_add_config_trigger "config.change" "${packageName}" /etc/init.d/${packageName} reload
- for n in $ifacesSupported; do
- procd_add_interface_trigger "interface.*" "$n" /etc/init.d/${packageName} on_interface_reload "$n"
- done
- procd_close_trigger
- if [ "$serviceStartTrigger" = 'on_start' ]; then
- output 3 "$serviceName monitoring interfaces: ${ifacesSupported}\\n"
- fi
-}
-
-stop_service() {
- local i
- load_environment 'on_stop'
- is_service_running || return 0
- traffic_killswitch 'insert'
- cleanup_main_chains
- cleanup_sets
- cleanup_marking_chains
- output 1 'Resetting interfaces '
- config_load 'network'
- config_foreach interface_process 'interface' 'destroy'
- interface_process_tor 'tor' 'destroy'
- cleanup_rt_tables
- output 1 "\\n"
- ip route flush cache
- unset ifaceMark
- unset ifaceTableID
- resolver 'store_hash'
- resolver 'cleanup_all'
- resolver 'compare_hash' && resolver 'restart'
- traffic_killswitch 'remove'
- if [ "$enabled" -ne 0 ]; then
- if is_nft; then
- output "$serviceName (nft) stopped "; output_okn;
- else
- output "$serviceName (iptables) stopped "; output_okn;
- fi
- fi
-}
-
-status_service() {
- local _SEPARATOR_='============================================================'
- load_environment 'on_status'
- if is_nft; then
- status_service_nft "$@"
- else
- status_service_iptables "$@"
- fi
-}
-
-status_service_nft() {
- local i dev dev6 wan_tid
-
- json_load "$(ubus call system board)"; json_select release; json_get_var dist distribution; json_get_var vers version
- if [ -n "$wanIface4" ]; then
- network_get_gateway wanGW4 "$wanIface4"
- network_get_device dev "$wanIface4"
- fi
- if [ -n "$wanIface6" ]; then
- network_get_device dev6 "$wanIface6"
- wanGW6=$($ip_bin -6 route show | grep -m1 " dev $dev6 " | awk '{print $1}')
- [ "$wanGW6" = "default" ] && wanGW6=$($ip_bin -6 route show | grep -m1 " dev $dev6 " | awk '{print $3}')
- fi
- while [ "${1:0:1}" = "-" ]; do param="${1//-/}"; eval "set_$param=1"; shift; done
- [ -e "/var/${packageName}-support" ] && rm -f "/var/${packageName}-support"
- status="$serviceName running on $dist $vers."
- [ -n "$wanIface4" ] && status="$status WAN (IPv4): ${wanIface4}/${dev}/${wanGW4:-0.0.0.0}."
- [ -n "$wanIface6" ] && status="$status WAN (IPv6): ${wanIface6}/${dev6}/${wanGW6:-::/0}."
-
- echo "$_SEPARATOR_"
- echo "$packageName - environment"
- echo "$status"
- echo "$_SEPARATOR_"
- dnsmasq --version 2>/dev/null | sed '/^$/,$d'
- echo "$_SEPARATOR_"
- echo "$packageName chains - policies"
- for i in forward input output prerouting postrouting; do
- "$nft" -a list table inet "$nftTable" | sed -n "/chain ${nftPrefix}_${i} {/,/\t}/p"
- done
- echo "$_SEPARATOR_"
- echo "$packageName chains - marking"
- for i in $(get_mark_nft_chains); do
- "$nft" -a list table inet "$nftTable" | sed -n "/chain ${i} {/,/\t}/p"
- done
- echo "$_SEPARATOR_"
- echo "$packageName nft sets"
- for i in $(get_nft_sets); do
- "$nft" -a list table inet "$nftTable" | sed -n "/set ${i} {/,/\t}/p"
- done
- if [ -s "$dnsmasqFile" ]; then
- echo "$_SEPARATOR_"
- echo "dnsmasq sets"
- cat "$dnsmasqFile"
- fi
-# echo "$_SEPARATOR_"
-# ip rule list | grep "${packageName}_"
- echo "$_SEPARATOR_"
- tableCount="$(grep -c "${packageName}_" /etc/iproute2/rt_tables)" || tableCount=0
- wan_tid=$(($(get_rt_tables_next_id)-tableCount))
- i=0; while [ $i -lt "$tableCount" ]; do
- echo "IPv4 table $((wan_tid + i)) route: $($ip_bin -4 route show table $((wan_tid + i)) | grep default)"
- echo "IPv4 table $((wan_tid + i)) rule(s):"
- $ip_bin -4 rule list table "$((wan_tid + i))"
- if [ -n "$ipv6_enabled" ]; then
- echo "IPv6 table $((wan_tid + i)) route: $($ip_bin -6 route show table $((wan_tid + i)) | grep default)"
- echo "IPv6 table $((wan_tid + i)) rule(s):"
- $ip_bin -6 route show table $((wan_tid + i))
- fi
- i=$((i + 1))
- done
-}
-
-status_service_iptables() {
- local dist vers out id s param status set_d set_p tableCount i=0 dev dev6 j wan_tid
-
- json_load "$(ubus call system board)"; json_select release; json_get_var dist distribution; json_get_var vers version
- if [ -n "$wanIface4" ]; then
- network_get_gateway wanGW4 "$wanIface4"
- network_get_device dev "$wanIface4"
- fi
- if [ -n "$wanIface6" ]; then
- network_get_device dev6 "$wanIface6"
- wanGW6=$($ip_bin -6 route show | grep -m1 " dev $dev6 " | awk '{print $1}')
- [ "$wanGW6" = "default" ] && wanGW6=$($ip_bin -6 route show | grep -m1 " dev $dev6 " | awk '{print $3}')
- fi
- while [ "${1:0:1}" = "-" ]; do param="${1//-/}"; eval "set_$param=1"; shift; done
- [ -e "/var/${packageName}-support" ] && rm -f "/var/${packageName}-support"
- status="$serviceName running on $dist $vers."
- [ -n "$wanIface4" ] && status="$status WAN (IPv4): ${wanIface4}/${dev}/${wanGW4:-0.0.0.0}."
- [ -n "$wanIface6" ] && status="$status WAN (IPv6): ${wanIface6}/${dev6}/${wanGW6:-::/0}."
- {
- echo "$status"
- echo "$_SEPARATOR_"
- dnsmasq --version 2>/dev/null | sed '/^$/,$d'
- if [ -n "$1" ]; then
- echo "$_SEPARATOR_"
- echo "Resolving domains"
- for i in $1; do
- echo "$i: $(resolveip "$i" | tr '\n' ' ')"
- done
- fi
-
- echo "$_SEPARATOR_"
- echo "Routes/IP Rules"
- tableCount="$(grep -c "${packageName}_" /etc/iproute2/rt_tables)" || tableCount=0
- if [ -n "$set_d" ]; then route; else route | grep '^default'; fi
- if [ -n "$set_d" ]; then ip rule list; fi
- wan_tid=$(($(get_rt_tables_next_id)-tableCount))
- i=0; while [ $i -lt "$tableCount" ]; do
- echo "IPv4 table $((wan_tid + i)) route: $($ip_bin -4 route show table $((wan_tid + i)) | grep default)"
- echo "IPv4 table $((wan_tid + i)) rule(s):"
- $ip_bin -4 rule list table "$((wan_tid + i))"
- i=$((i + 1))
- done
-
- if [ -n "$ipv6_enabled" ]; then
- i=0; while [ $i -lt "$tableCount" ]; do
- $ip_bin -6 route show table $((wan_tid + i)) | while read -r param; do
- echo "IPv6 Table $((wan_tid + i)): $param"
- done
- i=$((i + 1))
- done
- fi
-
- for j in Mangle NAT; do
- if [ -z "$set_d" ]; then
- for i in $chainsList; do
- i="$(str_to_upper "$i")"
- if iptables -v -t "$(str_to_lower $j)" -S "${iptPrefix}_${i}" >/dev/null 2>&1; then
- echo "$_SEPARATOR_"
- echo "$j IP Table: $i"
- iptables -v -t "$(str_to_lower $j)" -S "${iptPrefix}_${i}"
- if [ -n "$ipv6_enabled" ]; then
- echo "$_SEPARATOR_"
- echo "$j IPv6 Table: $i"
- iptables -v -t "$(str_to_lower $j)" -S "${iptPrefix}_${i}"
- fi
- fi
- done
- else
- echo "$_SEPARATOR_"
- echo "$j IP Table"
- iptables -L -t "$(str_to_lower $j)"
- if [ -n "$ipv6_enabled" ]; then
- echo "$_SEPARATOR_"
- echo "$j IPv6 Table"
- iptables -L -t "$(str_to_lower $j)"
- fi
- fi
- i=0; ifaceMark="$wan_mark";
- while [ $i -lt "$tableCount" ]; do
- if iptables -v -t "$(str_to_lower $j)" -S "${iptPrefix}_MARK_${ifaceMark}" >/dev/null 2>&1; then
- echo "$_SEPARATOR_"
- echo "$j IP Table MARK Chain: ${iptPrefix}_MARK_${ifaceMark}"
- iptables -v -t "$(str_to_lower $j)" -S "${iptPrefix}_MARK_${ifaceMark}"
- ifaceMark="$(printf '0x%06x' $((ifaceMark + wan_mark)))";
- fi
- i=$((i + 1))
- done
- done
-
- echo "$_SEPARATOR_"
- echo "Current ipsets"
- ipset save
- if [ -s "$dnsmasqFile" ]; then
- echo "$_SEPARATOR_"
- echo "DNSMASQ sets"
- cat "$dnsmasqFile"
- fi
- if [ -s "$aghIpsetFile" ]; then
- echo "$_SEPARATOR_"
- echo "AdGuardHome sets"
- cat "$aghIpsetFile"
- fi
- echo "$_SEPARATOR_"
- } | tee -a /var/${packageName}-support
- if [ -n "$set_p" ]; then
- printf "%b" "Pasting to paste.ee... "
- if is_present 'curl' && is_variant_installed 'libopenssl' && is_installed 'ca-bundle'; then
- json_init; json_add_string "description" "${packageName}-support"
- json_add_array "sections"; json_add_object '0'
- json_add_string "name" "$(uci -q get system.@system[0].hostname)"
- json_add_string "contents" "$(cat /var/${packageName}-support)"
- json_close_object; json_close_array; payload=$(json_dump)
- out=$(curl -s -k "https://api.paste.ee/v1/pastes" -X "POST" -H "Content-Type: application/json" -H "X-Auth-Token:uVOJt6pNqjcEWu7qiuUuuxWQafpHhwMvNEBviRV2B" -d "$payload")
- json_load "$out"; json_get_var id id; json_get_var s success
- [ "$s" = "1" ] && printf "%b" "https://paste.ee/p/$id $__OK__\\n" || printf "%b" "$__FAIL__\\n"
- [ -e "/var/${packageName}-support" ] && rm -f "/var/${packageName}-support"
- else
- printf "%b" "${__FAIL__}\\n"
- printf "%b" "${_ERROR_}: The curl, libopenssl or ca-bundle packages were not found!\\nRun 'opkg update; opkg install curl libopenssl ca-bundle' to install them.\\n"
- fi
- else
- printf "%b" "Your support details have been logged to '/var/${packageName}-support'. $__OK__\\n"
- fi
-}
-
-# shellcheck disable=SC2120
-load_validate_config() {
- uci_load_validate "$packageName" "$packageName" "$1" "${2}${3:+ $3}" \
- 'enabled:bool:0' \
- 'procd_boot_delay:integer:0' \
- 'strict_enforcement:bool:1' \
- 'secure_reload:bool:0' \
- 'ipv6_enabled:bool:0' \
- 'resolver_set:or("", "none", "dnsmasq.ipset", "dnsmasq.nftset")' \
- 'verbosity:range(0,2):1' \
- "wan_mark:regex('0x[A-Fa-f0-9]{8}'):0x010000" \
- "fw_mask:regex('0x[A-Fa-f0-9]{8}'):0xff0000" \
- 'icmp_interface:or("", "tor", uci("network", "@interface"))' \
- 'ignored_interface:list(or("tor", uci("network", "@interface")))' \
- 'supported_interface:list(or("tor", uci("network", "@interface")))' \
- 'boot_timeout:integer:30' \
- 'wan_ip_rules_priority:uinteger:30000' \
- 'rule_create_option:or("", "add", "insert"):add' \
- 'procd_reload_delay:integer:0' \
- 'webui_supported_protocol:list(string)' \
- 'nft_user_set_policy:or("", "memory", "performance")'\
- 'nft_user_set_counter:bool:0'
-}
-
-# shellcheck disable=SC2120
-load_validate_policy() {
- local name
- local enabled
- local interface
- local proto
- local chain
- local src_addr
- local src_port
- local dest_addr
- local dest_port
- uci_load_validate "$packageName" 'policy' "$1" "${2}${3:+ $3}" \
- 'name:string:Untitled' \
- 'enabled:bool:1' \
- 'interface:or("ignore", "tor", uci("network", "@interface")):wan' \
- 'proto:or(string)' \
- 'chain:or("", "forward", "input", "output", "prerouting", "postrouting", "FORWARD", "INPUT", "OUTPUT", "PREROUTING", "POSTROUTING"):prerouting' \
- 'src_addr:list(neg(or(host,network,macaddr,string)))' \
- 'src_port:list(neg(or(portrange,string)))' \
- 'dest_addr:list(neg(or(host,network,string)))' \
- 'dest_port:list(neg(or(portrange,string)))'
-}
-
-# shellcheck disable=SC2120
-load_validate_include() {
- local path=
- local enabled=
- uci_load_validate "$packageName" 'include' "$1" "${2}${3:+ $3}" \
- 'path:file' \
- 'enabled:bool:0'
-}