aports/main/dnsmasq/dnsmasq.initd
Dominique Martinet d1dad93197 main/dnsmasq: init: add extra setup command hook
for cases other than bridges dnsmasq might need some
extra configuration step before starting

Tested with conf.d value, used for NetworkManager (if it's slow to start
it won't have time to create required dir for resolv-file, nor setup lo
if bind-interfaces is set):
```
setup_command=extra_setup
extra_setup() {
	ip a add 127.0.0.1/8 dev lo >/dev/null 2>&1
	ip a add ::1/128 dev lo >/dev/null 2>&1
	mkdir -p /run/NetworkManager
}
```
2022-06-26 15:48:32 +02:00

156 lines
4.6 KiB
Bash

#!/sbin/openrc-run
description="A lightweight DNS, DHCP, RA, TFTP and PXE server"
extra_commands="checkconfig"
description_checkconfig="Check configuration syntax"
extra_started_commands="reload"
description_reload="Clear cache and reload hosts files"
# DNSMASQ_CONFFILE is here for backward compatibility (Alpine <3.16).
: ${cfgfile:=${DNSMASQ_CONFFILE:-"/etc/dnsmasq.conf"}}
: ${leasefile:="/var/lib/misc/$RC_SVCNAME.leases"}
: ${user:="dnsmasq"}
: ${group:="dnsmasq"}
: ${setup_bridge:="yes"}
: ${setup_command:=""}
command="/usr/sbin/dnsmasq"
# Tell dnsmasq to not create pidfile, that's responsibility of init system.
# DNSMASQ_OPTS is here for backward compatibility (Alpine <3.16).
command_args="--keep-in-foreground --pid-file= $DNSMASQ_OPTS $command_args --conf-file=$cfgfile"
command_background="yes"
pidfile="/run/$RC_SVCNAME.pid"
if [ "${RC_SVCNAME#*.}" != "$RC_SVCNAME" ] && yesno "$setup_bridge"; then
BRIDGE="${RC_SVCNAME#*.}"
: ${BRIDGE_ADDR:="10.0.3.1"}
: ${BRIDGE_NETMASK:="255.255.255.0"}
: ${BRIDGE_NETWORK:="10.0.3.0/24"}
: ${BRIDGE_DHCP_RANGE:="10.0.3.2,10.0.3.254"}
: ${BRIDGE_DHCP_MAX:="253"}
: ${BRIDGE_MAC:="00:16:3e:00:00:00" }
: ${DNSMASQ_LISTEN_BRIDGE_ADDR:=yes}
fi
depend() {
provide dns
need localmount net
after bootmisc dbus
use logger
}
setup_firewall() {
local ins=$1 add=$2
iptables -w $ins INPUT -i "$BRIDGE" -p udp --dport 67 -j ACCEPT
iptables -w $ins INPUT -i "$BRIDGE" -p tcp --dport 67 -j ACCEPT
iptables -w $ins INPUT -i "$BRIDGE" -p udp --dport 53 -j ACCEPT
iptables -w $ins INPUT -i "$BRIDGE" -p tcp --dport 53 -j ACCEPT
iptables -w $ins FORWARD -i "$BRIDGE" -j ACCEPT
iptables -w $ins FORWARD -o "$BRIDGE" -j ACCEPT
iptables -w -t nat $add POSTROUTING -s "$BRIDGE_NETWORK" ! -d "$BRIDGE_NETWORK" -j MASQUERADE
iptables -w -t mangle $add POSTROUTING -o "$BRIDGE" -p udp -m udp --dport 68 -j CHECKSUM --checksum-fill
if yesno "$BRIDGE_IPV6_NAT" && [ -n "$BRIDGE_IPV6_NETWORK" ]; then
ip6tables -w -t nat $add POSTROUTING -s "$BRIDGE_IPV6_NETWORK" ! -d "$BRIDGE_IPV6_NETWORK" -j MASQUERADE
fi
}
setup_bridge() {
einfo "Creating bridge $BRIDGE"
if ! [ -d "/sys/class/net/$BRIDGE" ]; then
ip link add dev "$BRIDGE" type bridge
fi
local addr
ip link set dev "$BRIDGE" address "$BRIDGE_MAC" \
&& for addr in $BRIDGE_ADDR $BRIDGE_ADDR_EXTRA; do
case "$addr" in
*/*) ip addr add "$addr" dev "$BRIDGE";;
*) ip addr add "$addr/$BRIDGE_NETMASK" dev "$BRIDGE";;
esac
done \
&& ip link set dev "$BRIDGE" up
echo 1 > /proc/sys/net/ipv4/ip_forward
echo 0 > "/proc/sys/net/ipv6/conf/$BRIDGE/accept_dad" || true
if [ -n "$BRIDGE_IPV6_ADDR" ] && [ -n "$BRIDGE_IPV6_MASK" ] && [ "$BRIDGE_IPV6_NETWORK" ]; then
echo 1 > /proc/sys/net/ipv6/conf/all/forwarding
echo 0 > "/proc/sys/net/ipv6/conf/$BRIDGE/autoconf"
ip -6 addr add dev "$BRIDGE" "$BRIDGE_IPV6_ADDR/$BRIDGE_IPV6_MASK"
command_args="$command_args --dhcp-range=$BRIDGE_IPV6_ADDR,ra-only --listen-address $BRIDGE_IPV6_ADDR"
fi
}
start_pre() {
$command --test --conf-file="$cfgfile" >/dev/null 2>&1 \
|| $command --test \
|| return 1
checkpath -m 0644 -o "$user:$group" -f "$leasefile" || return 1
if [ -n "$BRIDGE" ]; then
setup_bridge
if ! yesno "$DISABLE_IPTABLES"; then
setup_firewall -I -A
fi
if yesno "$DNSMASQ_LISTEN_BRIDGE_ADDR"; then
local addr; for addr in $BRIDGE_ADDR; do
command_args="$command_args --listen-address ${addr%/*}"
done
fi
command_args="$command_args --strict-order --bind-interfaces --except-interface=lo --interface=$BRIDGE"
command_args="$command_args --dhcp-range $BRIDGE_DHCP_RANGE --dhcp-lease-max=$BRIDGE_DHCP_MAX --dhcp-no-override --dhcp-leasefile=$leasefile --dhcp-authoritative"
fi
if command -v "$setup_command" >/dev/null; then
$setup_command || return 1
fi
}
stop_post() {
if [ -n "$BRIDGE" ]; then
local addr; for addr in $BRIDGE_ADDR $BRIDGE_ADDR_EXTRA; do
case "$addr" in
*/*) ip addr del "$addr" dev "$BRIDGE";;
*) ip addr del "$addr/$BRIDGE_NETMASK" dev "$BRIDGE";;
esac
done
ip link set dev "$BRIDGE" down
if ! yesno "$DISABLE_IPTABLES"; then
setup_firewall -D -D
fi
# dont destroy if there are attached interfaces
ls /sys/class/net/"$BRIDGE"/brif/* > /dev/null 2>&1 || ip link delete "$BRIDGE"
fi
}
reload() {
ebegin "Reloading $RC_SVCNAME"
$command --test --conf-file="$cfgfile" >/dev/null 2>&1 \
|| $command --test \
|| return 1
if [ "$supervisor" ]; then
$supervisor "$RC_SVCNAME" --signal HUP
else
start-stop-daemon --signal HUP --pidfile "$pidfile"
fi
eend $?
}
checkconfig() {
ebegin "Checking $RC_SVCNAME configuration"
$command --test --conf-file="$cfgfile"
eend $?
}