Files
webgui/etc/rc.d/rc.library.source
2025-05-08 16:01:37 +02:00

186 lines
4.7 KiB
Bash

#!/bin/bash
#
# script: rc.library.source
#
# Library used by nfsd, ntpd, rpc, samba, nginx, sshd, avahidaemon, show_interfaces
#
# Bergware - created for Unraid OS, December 2023
# Bergware - updated May 2025
WIREGUARD="/etc/wireguard"
NETWORK_INI="/var/local/emhttp/network.ini"
NETWORK_EXTRA="/boot/config/network-extra.cfg"
var(){
if [[ $# -eq 3 ]]; then
[[ -r "$3" ]] && sed -n "/^\[$1\]\$/,/^\[/p" "$3" | grep -Pom1 "^$2=\"\K[^\"]+"
elif [[ $# -eq 2 ]]; then
[[ -r "$2" ]] && grep -Pom1 "^$1=\"\K[^\"]+" "$2"
fi
}
ipv(){
local t=${1//[^:]}
[[ ${#t} -le 1 ]] && echo 4 || echo 6
}
this(){
local MAP ADDR
case $CALLER in
'avahi')
grep -Pom1 "^$1=\K.*" $CONF ;;
'smb')
grep -Pom1 "^$1 = \K.*" $CONF ;;
'ntp'|'ssh')
grep -Po "^$1 \K\S+" $CONF | tr '\n' ' ' | sed 's/ $//' ;;
'nfs')
grep -Pom1 "^RPC_NFSD_OPTS=\"$OPTIONS \K[^\"]+" $NFS ;;
'rpc')
grep -Pom1 "^RPCBIND_OPTS=\"\K[^\"]+" $RPC ;;
'nginx')
grep -Po "^NGINX_BIND=\"\K[^\"]+" ${INI%.*} 2>/dev/null ;;
esac
}
scan(){
grep -Pom1 "^$1=\"?\K[^\"]+" $2
}
good(){
local TAG BAD
for TAG in ${BIND[@]}; do
[[ -z $1 || $1 == $TAG || ${1:0:4} == fe80 ]] && BAD=1 && break
done
echo $BAD
}
show(){
case $# in
1) ip -br addr show scope global primary -deprecated to $1 2>/dev/null | awk '{gsub("@.+","",$1);print $1;exit}' ;;
2) ip -br addr show scope global primary -deprecated $1 $2 2>/dev/null | awk '{$1=$2="";print;exit}' | sed -r 's/ metric [0-9]+//g' ;;
esac
}
unmask(){
if [[ $CALLER != smb ]]; then
# remove netmask
echo ${1/\/*}
elif [[ $(ipv $1) == 4 ]]; then
# replace netmask
echo ${1/\/32/\/24}
elif [[ -z $DENY6 ]]; then
# IPv6 only when netbios is disabled
echo ${1/\/128/\/64}
fi
}
remove(){
local i ADDR
for ADDR in $@; do
ADDR=$(unmask $ADDR)
[[ -z $ADDR ]] && continue
for i in ${!BIND[@]}; do
[[ $ADDR == ${BIND[$i]} ]] && unset 'BIND[i]'
done
done
}
isname(){
[[ -z ${1//[^.:]} || ${1//[^.:]} == . ]] && return 0 || return 1
}
add_name(){
local NET
for NET in $include_interfaces; do
if $(isname $NET); then
# NET is an interface name, validate
[[ -n $(show dev $NET) && -z $(good $NET) ]] && BIND+=($NET)
else
# NET is an IP address, convert to name
NET=$(show $NET)
[[ -n $NET && -z $(good $NET) ]] && BIND+=($NET)
fi
done
for NET in $exclude_interfaces; do
if $(isname $NET); then
# NET is an interface name
remove "$NET"
else
# NET is an IP address, convert to name
remove "$(show $NET)"
fi
done
}
add_addr(){
local NET MAP ADDR
for NET in $include_interfaces; do
if $(isname $NET); then
# NET is an interface name, get IP addresses
MAP="$(show dev $NET)"
else
# NET is an IP address, validate
MAP="$(show to $NET)"
fi
for ADDR in $MAP; do
ADDR=$(unmask $ADDR)
[[ -z $(good $ADDR) ]] && BIND+=($ADDR) || continue
[[ $(ipv $ADDR) == 4 ]] && IPV4=yes || IPV6=yes
done
done
for NET in $exclude_interfaces; do
if $(isname $NET); then
# NET is an interface name, get IP addresses
remove "$(show dev $NET)"
else
# NET is an IP address
remove "$(show to $NET)"
fi
done
}
check(){
# quick check
[[ -n $BIND ]] && return 0;
# preset return values
BIND=(); IPV4=no; IPV6=no; FAMILY=any;
# read active interfaces (including wireguard tunnels)
while IFS=$'\n' read -r NET; do
NET=($NET)
if [[ ${NET:0:2} == wg ]]; then
# skip wireguard tunnel if NTP or VPN type
[[ $CALLER == ntp || $(grep -Pom1 '^TYPE:1="\K[^"]+' $WIREGUARD/$NET.cfg) == 8 ]] && continue
fi
for ADDR in ${NET[@]/$NET}; do
ADDR=$(unmask $ADDR)
if [[ "ntp avahi show" =~ "$CALLER" ]]; then
[[ -z $(good $NET) ]] && BIND+=($NET)
else
[[ -z $(good $ADDR) ]] && BIND+=($ADDR) || continue
fi
[[ $(ipv $ADDR) == 4 ]] && IPV4=yes || IPV6=yes
done
done <<< $(ip -br addr show scope global primary -deprecated | awk '$1~"^(br|bond|eth|wlan|wg)[0-9]+(.[0-9]+)?" && $3!="" {gsub("@.+","",$1);$2="";print}' | sed -r 's/ metric [0-9]+//g' | sort)
# add loopback interface
if [[ "smb nfs" =~ "$CALLER" ]]; then
[[ $IPV4 == yes ]] && BIND+=(127.0.0.1)
[[ $IPV6 == yes ]] && BIND+=(::1)
fi
# add user defined interfaces
if [[ -f $NETWORK_EXTRA && $CALLER != ntp ]]; then
. <(fromdos <$NETWORK_EXTRA)
[[ "avahi show" =~ "$CALLER" ]] && add_name || add_addr
fi
if [[ $CALLER == ssh ]]; then
# BIND stays array
BIND=(${BIND[@]})
[[ $IPV4 == yes && $IPV6 == no ]] && FAMILY=inet
[[ $IPV6 == yes && $IPV4 == no ]] && FAMILY=inet6
else
# convert array to string
BIND=${BIND[@]}
[[ $CALLER == avahi ]] && BIND=${BIND// /,}
fi
return 0
}