79e7456beb45b6f0723a1811a20e2b8854da499b
[feed/routing.git] / nodogsplash / files / nodogsplash.init
1 #!/bin/sh /etc/rc.common
2 #
3 # description: Startup/shutdown script for nodogsplash captive portal
4 #
5 # Alexander Couzens <lynxis@fe80.eu> 2014
6 # P. Kube 2007
7 #
8 # (Based on wifidog startup script
9 # Date : 2004-08-25
10 # Version : 1.0
11 # Comment by that author: Could be better, but it's working as expected)
12 #
13
14 START=95
15 STOP=95
16
17 USE_PROCD=1
18
19 IPT=/usr/sbin/iptables
20 WD_DIR=/usr/bin
21 # -s -d 5 runs in background, with level 5 (not so verbose) messages to syslog
22 # -f -d 7 runs in foreground, with level 7 (verbose) debug messages to terminal
23 OPTIONS="-s -f -d 5"
24 CONFIGFILE="/tmp/invalid_nodogsplash.conf"
25
26 # nolog(loglevel message ...)
27 nolog() {
28 local level=$1
29 shift
30 logger -s -t nodogsplash -p daemon.$level $@
31 }
32
33 # append_config_option_map <cfgfile> <uci_cfg_obj> <option_name> <config_counterpart> [<optional default>]
34 # append "$config_counterpart $value" to cfgfile if option_name exists
35 # e.g. append_config_option "$CONFIGFILE" "$cfg" bind_address BindAddress 0.0.0.0
36 # will append "BindAddress 192.168.1.1" if uci bind_address is '192.168.1.1'
37 append_config_option_map() {
38 local val=""
39 local config_file="$1"
40 local cfg="$2"
41 local option_name="$3"
42 local config_counterpart="$4"
43 local default="$5"
44 config_get val "$cfg" "$option_name" "$default"
45 [ -n "$val" ] && echo "$config_counterpart $val" >> $config_file
46 }
47
48 # append_config_option <cfgfile> <uci_cfg_obj> <option_name> [<optional default>]
49 # append "$option_name $value" to cfgfile if option_name exists
50 # e.g. append_config_option "$CONFIGFILE" "$cfg" bind_address 0.0.0.0
51 # will append "bind_address 192.168.1.1" if uci bind_address is '192.168.1.1'
52 # if uci bind_address is unset append "bind_address 0.0.0.0"
53 append_config_option() {
54 local val=""
55 local config_file="$1"
56 local cfg="$2"
57 local option_name="$3"
58 local default="$4"
59 config_get val "$cfg" "$option_name" "$default"
60 [ -n "$val" ] && echo "$option_name $val" >> $config_file
61 }
62
63 setup_user_authentication() {
64 local cfg="$1"
65 local val
66
67 config_get_bool val "$cfg" authenticate_immediately 0
68 [ $val -gt 0 ] && echo "AuthenticateImmediately yes" >> $CONFIGFILE
69
70 config_get val "$cfg" username
71 if [ -n "$val" ] ; then
72 echo "UsernameAuthentication 1" >> $CONFIGFILE
73 echo "Username $val" >> $CONFIGFILE
74 fi
75
76 config_get val "$cfg" password
77 if [ -n "$val" ] ; then
78 echo "PasswordAuthentication 1" >> $CONFIGFILE
79 echo "Password $val" >> $CONFIGFILE
80 fi
81 }
82
83 setup_mac_lists() {
84 local cfg="$1"
85 local MAC=""
86 local val
87
88 append_mac() {
89 append MAC "$1" ","
90 }
91
92 config_get val "$cfg" macmechanism
93 if [ -z "$val" ] ; then
94 # check if we have AllowedMACList or BlockedMACList defined they will be ignored
95 config_get val "$cfg" allowedmac
96 if [ -n "$val" ] ; then
97 echo "Ignoring allowedmac - macmechanism not \"allow\"" >&2
98 fi
99
100 config_get val "$cfg" blockedmac
101 if [ -n "$val" ] ; then
102 echo "Ignoring blockedmac - macmechanism not \"block\"" >&2
103 fi
104 elif [ "$val" == "allow" ] ; then
105 MAC=""
106 config_list_foreach "$cfg" allowedmac append_mac
107 echo "AllowedMACList $MAC" >> $CONFIGFILE
108 elif [ "$val" == "block" ] ; then
109 MAC=""
110 config_list_foreach "$cfg" blockedmac append_mac
111 echo "BlockedMACList $MAC" >> $CONFIGFILE
112 else
113 nolog error "$cfg Invalid macmechanism '$val' - allow or block are valid."
114 return 1
115 fi
116 MAC=""
117 config_list_foreach "$cfg" trustedmac append_mac
118 [ -n "$MAC" ] && echo "TrustedMACList $MAC" >> $CONFIGFILE
119 }
120
121 setup_firewall() {
122 local cfg="$1"
123 local uciname
124 local val
125
126 append_firewall() {
127 echo " FirewallRule $1" >> $CONFIGFILE
128 }
129
130 for rule in $(echo authenticated-users preauthenticated-users users-to-router trusted-users trusted-users-to-router)
131 do
132 uci_name=${rule//-/_}
133 # uci does not allow - dashes
134 echo "FirewallRuleSet $rule {" >> $CONFIGFILE
135 config_list_foreach "$cfg" ${uci_name} append_firewall
136 echo "}" >> $CONFIGFILE
137 config_get val "$cfg" policy_${uci_name}
138 [ -n "$val" ] && echo "EmptyRuleSetPolicy $rule $val" >> $CONFIGFILE
139 done
140 }
141
142 generate_uci_config() {
143 local cfg="$1"
144 local val
145 local ifname
146 local download
147 local upload
148
149 CONFIGFILE="/tmp/etc/nodogsplash_$cfg.conf"
150
151 echo "# auto-generated config file from /etc/config/nodogsplash" > $CONFIGFILE
152
153 config_get val "$cfg" config
154 if [ -n "$val" ] ; then
155 if [ ! -f "$val" ] ; then
156 nolog error "Configuration file '$file' doesn't exist"
157 return 0
158 fi
159 cat "$val" >> CONFIGFILE
160 fi
161
162 config_get val "$cfg" network
163 if [ -n "$val" ] ; then
164 if ! network_get_device ifname "$val" ; then
165 nolog error "$cfg can not find ifname for network '$val'"
166 return 1
167 fi
168 fi
169
170 config_get val "$cfg" gatewayinterface
171 if [ -n "$val" ] ; then
172 if [ -n "$ifname" ] ; then
173 nolog error "$cfg cannot use both option network and gatewayinterface"
174 return 1
175 fi
176 ifname="$val"
177 fi
178
179 if [ -z "$ifname" ] ; then
180 nolog error "$cfg option network or gatewayinterface missing"
181 return 1
182 fi
183
184 echo "GatewayInterface $ifname" >> $CONFIGFILE
185
186 append_config_option "$CONFIGFILE" "$cfg" gatewayname
187 append_config_option "$CONFIGFILE" "$cfg" gatewayaddress
188 append_config_option "$CONFIGFILE" "$cfg" gatewayport
189 append_config_option "$CONFIGFILE" "$cfg" maxclients
190 append_config_option "$CONFIGFILE" "$cfg" webroot
191 append_config_option "$CONFIGFILE" "$cfg" debuglevel
192 append_config_option "$CONFIGFILE" "$cfg" splashpage
193 append_config_option "$CONFIGFILE" "$cfg" pagesdir
194 append_config_option "$CONFIGFILE" "$cfg" checkinterval
195 append_config_option "$CONFIGFILE" "$cfg" syslogfacility
196 append_config_option "$CONFIGFILE" "$cfg" gatewayiprange
197 append_config_option "$CONFIGFILE" "$cfg" imagedir
198 append_config_option "$CONFIGFILE" "$cfg" redirecturl
199 append_config_option "$CONFIGFILE" "$cfg" clientidletimeout
200 append_config_option "$CONFIGFILE" "$cfg" clientforcetimeout
201 append_config_option "$CONFIGFILE" "$cfg" gatewayiprange
202 append_config_option "$CONFIGFILE" "$cfg" passwordattempts
203 append_config_option "$CONFIGFILE" "$cfg" macmechanism
204 append_config_option "$CONFIGFILE" "$cfg" uploadlimit
205 append_config_option "$CONFIGFILE" "$cfg" downloadlimit
206 append_config_option "$CONFIGFILE" "$cfg" remoteauthenticatoraction
207 append_config_option "$CONFIGFILE" "$cfg" enablepreauth
208 append_config_option "$CONFIGFILE" "$cfg" binvoucher
209 append_config_option "$CONFIGFILE" "$cfg" forcevoucher
210 append_config_option "$CONFIGFILE" "$cfg" passwordauthentication
211 append_config_option "$CONFIGFILE" "$cfg" usernameauthentication
212 append_config_option "$CONFIGFILE" "$cfg" passwordattempts
213 append_config_option "$CONFIGFILE" "$cfg" username
214 append_config_option "$CONFIGFILE" "$cfg" password
215 append_config_option "$CONFIGFILE" "$cfg" authenticateimmediately
216 append_config_option "$CONFIGFILE" "$cfg" decongesthttpdthreads
217 append_config_option "$CONFIGFILE" "$cfg" httpdthreadthreshold
218 append_config_option "$CONFIGFILE" "$cfg" httpdthreaddelayms
219 append_config_option "$CONFIGFILE" "$cfg" fw_mark_authenticated
220 append_config_option "$CONFIGFILE" "$cfg" fw_mark_trusted
221 append_config_option "$CONFIGFILE" "$cfg" fw_mark_blocked
222
223 config_get download "$cfg" downloadlimit
224 config_get upload "$cfg" uploadlimit
225 [ -n "$upload" -o -n "$download" ] && echo "TrafficControl yes" >> $CONFIGFILE
226
227 setup_mac_lists "$cfg"
228 setup_user_authentication "$cfg"
229 setup_firewall "$cfg"
230 }
231
232 # setup configuration and start instance
233 create_instance() {
234 local cfg="$1"
235 local manual_config
236 local val
237
238 config_get_bool val "$cfg" enabled 0
239 [ $val -gt 0 ] || return 0
240
241 generate_uci_config "$cfg"
242
243 if ! test_module ; then
244 logger -s -t nodogsplash -p daemon.error "nodogsplash is missing some kernel modules"
245 fi
246
247 procd_open_instance $cfg
248 procd_set_param command /usr/bin/nodogsplash -c $CONFIGFILE $OPTIONS
249 procd_set_param respawn
250 procd_set_param file $CONFIGFILE
251 procd_close_instance
252 }
253
254 start_service() {
255 include /lib/functions
256
257 mkdir -p /tmp/etc/
258 config_load nodogsplash
259
260 config_foreach create_instance instance
261 }
262
263 stop_service() {
264 # nodogsplash doesn't exit fast enought, when procd terminates it.
265 # otherwise procd will restart nodogsplash twice. first time starting nodogsplash fails, second time it succeeds
266 sleep 1
267 }
268
269 status() {
270 $WD_DIR/ndsctl status
271 }
272
273 # Test if we got all modules loaded
274 test_module() {
275 ### Test ipt_mark with iptables
276 test_ipt_mark () {
277 ($IPT -A FORWARD -m mark --mark 2 -j ACCEPT 2>&1) > /dev/null
278 IPTABLES_OK=$?
279 if [ "$IPTABLES_OK" -eq 0 ]; then
280 ($IPT -D FORWARD -m mark --mark 2 -j ACCEPT 2>&1) > /dev/null
281 return 0
282 else
283 return 1
284 fi
285 }
286
287 ### Test ipt_mac with iptables
288 test_ipt_mac () {
289 ($IPT -A INPUT -m mac --mac-source 00:00:00:00:00:00 -j ACCEPT 2>&1) > /dev/null
290 IPTABLES_OK=$?
291 if [ "$IPTABLES_OK" -eq 0 ]; then
292 ($IPT -D INPUT -m mac --mac-source 00:00:00:00:00:00 -j ACCEPT 2>&1) > /dev/null
293 return 0
294 else
295 return 1
296 fi
297 }
298
299 ### Test ipt_IMQ with iptables
300 test_ipt_IMQ () {
301 ($IPT -t mangle -A PREROUTING -j IMQ --todev 0 2>&1) > /dev/null
302 IPTABLES_OK=$?
303 if [ "$IPTABLES_OK" -eq 0 ]; then
304 ($IPT -t mangle -D PREROUTING -j IMQ --todev 0 2>&1) > /dev/null
305 return 0
306 else
307 return 1
308 fi
309 }
310
311 ### Test imq with ip
312 test_imq () {
313 (ip link set imq0 up 2>&1) > /dev/null
314 IMQ0_OK=$?
315 (ip link set imq1 up 2>&1) > /dev/null
316 IMQ1_OK=$?
317 if [ "$IMQ0_OK" -eq 0 -a "$IMQ1_OK" -eq 0 ]; then
318 (ip link set imq0 down 2>&1) > /dev/null
319 (ip link set imq1 down 2>&1) > /dev/null
320 return 0
321 else
322 return 1
323 fi
324 }
325
326 ### Test sch_htb with tc; requires imq0
327 test_sch_htb () {
328 (tc qdisc del dev imq0 root 2>&1) > /dev/null
329 (tc qdisc add dev imq0 root htb 2>&1) > /dev/null
330 TC_OK=$?
331 if [ "$TC_OK" -eq 0 ]; then
332 (tc qdisc del dev imq0 root 2>&1) > /dev/null
333 return 0
334 else
335 return 1
336 fi
337 }
338
339 ### Find a module on disk
340 module_exists () {
341 EXIST=$(find /lib/modules/`uname -r` -name $1.*o 2> /dev/null)
342 if [ -n "$EXIST" ]; then
343 return 0
344 else
345 return 1
346 fi
347 }
348
349 ### Test if a module is in memory
350 module_in_memory () {
351 MODULE=$(lsmod | grep $1 | awk '{print $1}')
352 if [ "$MODULE" = "$1" ]; then
353 return 0
354 else
355 return 1
356 fi
357 }
358
359 ### Test functionality of a module; load if necessary
360 do_module_tests () {
361 echo " Testing module $1 $2"
362 "test_$1"
363 if [ $? -ne 0 ]; then
364 echo " Module $1 $2 needed"
365 echo " Scanning disk for $1 module"
366 module_exists $1
367 if [ $? -ne 0 ]; then
368 echo " $1 module missing: please install it"
369 exit 1
370 else
371 echo " $1 exists, trying to load"
372 insmod $1 $2 > /dev/null
373 if [ $? -ne 0 ]; then
374 echo " Error: insmod $1 $2 failed"
375 exit 1
376 else
377 echo " $1 $2 loaded successfully"
378 fi
379 fi
380 else
381 echo " $1 is working"
382 fi
383 }
384
385 echo " Testing required modules"
386
387 do_module_tests "ipt_mac"
388 do_module_tests "ipt_mark"
389
390 # test for imq modules, only if TrafficControl is enabled in conf
391 if ( grep -q -E '^[[:space:]]*TrafficControl[[:space:]]+(yes|true|1)' "$CONFIGFILE" ) ; then
392 do_module_tests "imq" "numdevs=2"
393 do_module_tests "ipt_IMQ"
394 do_module_tests "sch_htb"
395 fi
396 }