aboutsummaryrefslogtreecommitdiffstats
path: root/main/dnsmasq/dnsmasq.initd
blob: 85a3b42db82346cbcf70bd02eddbfa9c86e51294 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
#!/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 $?
}