Overall Freifunk improvements
[project/luci.git] / contrib / package / olsrd-luci / files / etc / init.d / olsrd
1 #!/bin/sh /etc/rc.common
2 # Copyright (C) 2008  Alina Friedrichsen <x-alina@gmx.net>
3 # Special thanks to bittorf wireless ))
4 START=50
5
6 BIN=/usr/sbin/olsrd
7 CONF=/var/etc/olsrd.conf
8 PID=/var/run/olsrd.pid
9
10 OLSRD_OLSRD_SCHEMA='ignore:internal config_file:internal DebugLevel=0 IpVersion=4 AllowNoInt:bool=1 Pollrate=0.025 TcRedundancy=2 MprCoverage=3 LinkQualityFishEye=1 LinkQualityWinSize=100 LinkQualityDijkstraLimit=0+9.0 LinkQualityLevel=2 UseHysteresis:bool=0 FIBMetric=flat ClearScreen:bool=1 Willingness=3 LinkQualityAging=0.1 LinkQualityAlgorithm=etx_fpm'
11 OLSRD_IPCCONNECT_SCHEMA='ignore:internal Host:list Net:list2'
12 OLSRD_LOADPLUGIN_SCHEMA='ignore:internal library:internal Host:list Net:list2 Ping:list redistribute:list NonOlsrIf:list name:list lat lon latlon_infile HNA:list2 hosts:list2'
13 OLSRD_INTERFACE_SCHEMA='ignore:internal interface:internal AutoDetectChanges:bool Ip4Broadcast=255.255.255.255 HelloInterval=2.0 HelloValidityTime=40.0 TcInterval=5.0 TcValidityTime=100.0 MidInterval=18.0 MidValidityTime=324.0 HnaInterval=18.0 HnaValidityTime=108.0'
14
15 T='     '
16 N='
17 '
18
19 validate_varname() {
20         local varname=$1
21         [ -z "$varname" -o "$varname" != "${varname%%[!A-Za-z0-9_]*}" ] && return 1
22         return 0
23 }
24
25 validate_ifname() {
26         local ifname=$1
27         [ -z "$ifname" -o "$ifname" != "${ifname%%[!A-Za-z0-9.:_-]*}" ] && return 1
28         return 0
29 }
30
31 validate_olsrd_option() {
32         local str=$1
33         [ -z "$str" -o "$str" != "${str%%[!     0-9A-Za-z./:_-]*}" ] && return 1
34         return 0
35 }
36
37 get_ifname() {
38         IFNAME=
39         local interface=$1
40         validate_varname "$interface" || return 1
41         local ifname
42
43         config_get ifname "$interface" ifname
44         validate_ifname "$ifname" || return 1
45         IFNAME=$ifname
46
47         return 0
48 }
49
50 system_config() {
51         local cfg=$1
52         local cfgt
53         local hostname
54         local latlon
55
56         config_get cfgt "$cfg" TYPE
57
58         if [ "$cfgt" = "system" ]; then
59                 config_get hostname "$cfg" hostname
60                 hostname=${hostname:-OpenWrt}
61                 SYSTEM_HOSTNAME=$hostname
62         fi
63
64         if [ -z "$SYSTEM_LAT" -o -z "$SYSTEM_LON" ]; then
65                 config_get latlon "$cfg" latlon
66                 IFS=" ${T}${N},"
67                 set -- $latlon
68                 unset IFS
69                 SYSTEM_LAT=$1
70                 SYSTEM_LON=$2
71         fi
72 }
73
74 olsrd_find_config_file() {
75         local cfg=$1
76         validate_varname "$cfg" || return 0
77
78         config_get_bool ignore "$cfg" ignore 0
79         [ "$ignore" -ne 0 ] && return 0
80         config_get OLSRD_CONFIG_FILE "$cfg" config_file
81
82         return 0
83 }
84
85 warning_invalid_value() {
86         local package=$1
87         validate_varname "$package" || package=
88         local config=$2
89         validate_varname "$config" || config=
90         local option=$3
91         validate_varname "$option" || option=
92
93         echo -n "Warning: Invalid value" 1>&2
94
95         if [ -n "$package" -a -n "$config" ]; then
96                 echo -n " in option '$package.$config${option:+.}$option'" 1>&2
97         fi
98
99         echo ", skipped" 1>&2
100
101         return 0
102 }
103
104 olsrd_write_option() {
105         local param=$1
106         local cfg=$2
107         validate_varname "$cfg" || return 1
108         local option=$3
109         validate_varname "$option" || return 1
110         local value=$4
111         local option_type=$5
112
113         if [ "$option_type" = bool ]; then
114                 case "$value" in
115                         1|on|true|enabled|yes) value=yes;;
116                         0|off|false|disabled|no) value=no;;
117                         *) warning_invalid_value olsrd "$cfg" "$option"; return 1;;
118                 esac
119         fi
120
121         if ! validate_olsrd_option "$value"; then
122                 warning_invalid_value olsrd "$cfg" "$option"
123                 return 1
124         fi
125
126         if [ "$value" != "${value%%[G-Zg-z_-]*}" ]; then
127                 if [ "$value" != "yes" -a "$value" != "no" ]; then
128                         value="\"$value\""
129                 fi
130         fi
131
132         echo -n "${N}$param$option $value"
133
134         return 0
135 }
136
137 olsrd_write_plparam() {
138         local param=$1
139         local cfg=$2
140         validate_varname "$cfg" || return 1
141         local option=$3
142         validate_varname "$option" || return 1
143         local value=$4
144         local option_type=$5
145         local _option
146
147         if [ "$option_type" = bool ]; then
148                 case "$value" in
149                         1|on|true|enabled|yes) value=yes;;
150                         0|off|false|disabled|no) value=no;;
151                         *) warning_invalid_value olsrd "$cfg" "$option"; return 1;;
152                 esac
153         fi
154
155         if ! validate_olsrd_option "$value"; then
156                 warning_invalid_value olsrd "$cfg" "$option"
157                 return 1
158         fi
159
160         IFS='-_'
161         set -- $option
162         option="$*"
163         unset IFS
164         _option="$option"
165         if [ "$option" = 'hosts' ]; then
166                 set -- $value
167                 option=$1
168                 shift
169                 value="$*"
170         fi
171
172         echo -n "${N}${param}PlParam \"$option\" \"$value\""
173
174         return 0
175 }
176
177 config_update_schema() {
178         unset IFS
179         local schema_varname=$1
180         validate_varname "$schema_varname" || return 1
181         local command=$2
182         validate_varname "$command" || return 1
183         local option=$3
184         validate_varname "$option" || return 1
185         local value=$4
186         local schema
187         local cur_option
188
189         case "$varname" in
190                 *_LENGTH) return 0;;
191                 *_ITEM*) return 0;;
192         esac
193
194         eval "export -n -- \"schema=\${$schema_varname}\""
195
196         for cur_option in $schema; do
197                 [ "${cur_option%%[:=]*}" = "$option" ] && return 0
198         done
199
200         if [ "$command" = list ]; then
201                 set -- $value
202                 if [ "$#" -ge "3" ]; then
203                         schema_entry="$option:list3"
204                 elif [ "$#" -ge "2" ]; then
205                         schema_entry="$option:list2"
206                 else
207                         schema_entry="$option:list"
208                 fi
209         else
210                 schema_entry="$option"
211         fi
212
213         append "$schema_varname" "$schema_entry"
214
215         return 0
216 }
217
218 config_write_options() {
219         unset IFS
220         local schema=$1
221         local cfg=$2
222         validate_varname "$cfg" || return 1
223         local write_func=$3
224         [ -z "$write_func" ] && output_func=echo
225         local write_param=$4
226         local schema_entry
227         local option
228         local option_length
229         local option_type
230         local default
231         local value
232         local list_size
233         local list_item
234         local list_value
235         local i
236         local position
237
238         for schema_entry in $schema; do
239                 default=${schema_entry#*[=]}
240                 [ "$default" = "$schema_entry" ] && default=
241                 option=${schema_entry%%[=]*}
242                 IFS=':'
243                 set -- $option
244                 unset IFS
245                 option=$1
246                 option_type=$2
247                 validate_varname "$option" || continue
248                 [ -z "$option_type" ] || validate_varname "$option_type" || continue
249                 [ "$option_type" = internal ] && continue
250                 config_get value "$cfg" "$option"
251
252                 if [ -z "$value" ]; then
253                         IFS='+'
254                         set -- $default
255                         unset IFS
256                         value=$*
257                 elif [ "$value" = '-' -a -n "$default" ]; then
258                         continue
259                 fi
260
261                 [ -z "$value" ] && continue
262
263                 case "$option_type" in
264                         list) list_size=1;;
265                         list2) list_size=2;;
266                         list3) list_size=3;;
267                         *) list_size=0;;
268                 esac
269
270                 if [ "$list_size" -gt 0 ]; then
271                         config_get option_length "$cfg" "${option}_LENGTH"
272                         if [ -n "$option_length" ]; then
273                                 i=1
274                                 while [ "$i" -le "$option_length" ]; do
275                                         config_get list_value "$cfg" "${option}_ITEM$i"
276                                         "$write_func" "$write_param" "$cfg" "$option" "$list_value" "$option_type" || break
277                                         i=$((i + 1))
278                                 done
279                         else
280                                 list_value=
281                                 i=0
282                                 for list_item in $value; do
283                                         append "list_value" "$list_item"
284                                         i=$((i + 1))
285                                         position=$((i % list_size))
286                                         if [ "$position" -eq 0 ]; then
287                                                 "$write_func" "$write_param" "$cfg" "$option" "$list_value" "$option_type" || break
288                                                 list_value=
289                                         fi
290                                 done
291                                 [ "$position" -ne 0 ] && "$write_func" "$write_param" "$cfg" "$option" "$list_value" "$option_type"
292                         fi
293                 else
294                         "$write_func" "$write_param" "$cfg" "$option" "$value" "$option_type"
295                 fi
296         done
297
298         return 0
299 }
300
301 olsrd_write_olsrd() {
302         local cfg=$1
303         validate_varname "$cfg" || return 0
304         local ignore
305
306         config_get_bool ignore "$cfg" ignore 0
307         [ "$ignore" -ne 0 ] && return 0
308
309         [ "$OLSRD_COUNT" -gt 0 ] && return 0
310
311         config_write_options "$OLSRD_OLSRD_SCHEMA" "$cfg" olsrd_write_option
312         echo
313         OLSRD_COUNT=$((OLSRD_COUNT + 1))
314
315         return 0
316 }
317
318 olsrd_write_ipcconnect() {
319         local cfg=$1
320         validate_varname "$cfg" || return 0
321         local ignore
322
323         config_get_bool ignore "$cfg" ignore 0
324         [ "$ignore" -ne 0 ] && return 0
325
326         [ "$IPCCONNECT_COUNT" -gt 0 ] && return 0
327
328         echo -n "${N}IpcConnect${N}{"
329         config_write_options "$OLSRD_IPCCONNECT_SCHEMA" "$cfg" olsrd_write_option "${T}"
330         echo "${N}}"
331         IPCCONNECT_COUNT=$((IPCCONNECT_COUNT + 1))
332
333         return 0
334 }
335
336 olsrd_write_hna4() {
337         local cfg=$1
338         validate_varname "$cfg" || return 0
339         local ignore
340
341         config_get_bool ignore "$cfg" ignore 0
342         [ "$ignore" -ne 0 ] && return 0
343
344         config_get netaddr "$cfg" netaddr
345         if ! validate_olsrd_option "$netaddr"; then
346                 warning_invalid_value olsrd "$cfg" "netaddr"
347                 return 0
348         fi
349
350         config_get netmask "$cfg" netmask
351         if ! validate_olsrd_option "$netmask"; then
352                 warning_invalid_value olsrd "$cfg" "netmask"
353                 return 0
354         fi
355
356         [ "$HNA4_COUNT" -le 0 ] && echo -n "${N}Hna4${N}{"
357         echo -n "${N}${T}$netaddr $netmask"
358         HNA4_COUNT=$((HNA4_COUNT + 1))
359
360         return 0
361 }
362
363 olsrd_write_hna6() {
364         local cfg=$1
365         validate_varname "$cfg" || return 0
366         local ignore
367
368         config_get_bool ignore "$cfg" ignore 0
369         [ "$ignore" -ne 0 ] && return 0
370
371         config_get netaddr "$cfg" netaddr
372         if ! validate_olsrd_option "$netaddr"; then
373                 warning_invalid_value olsrd "$cfg" "netaddr"
374                 return 0
375         fi
376
377         config_get prefix "$cfg" prefix
378         if ! validate_olsrd_option "$prefix"; then
379                 warning_invalid_value olsrd "$cfg" "prefix"
380                 return 0
381         fi
382
383         [ "$HNA6_COUNT" -le 0 ] && echo -n "${N}Hna6${N}{"
384         echo -n "${N}${T}$netaddr $prefix"
385         HNA6_COUNT=$((HNA6_COUNT + 1))
386
387         return 0
388 }
389
390 olsrd_write_loadplugin() {
391         local cfg=$1
392         validate_varname "$cfg" || return 0
393         local ignore
394         local name
395         local suffix
396         local lat
397         local lon
398         local latlon_infile
399
400         config_get_bool ignore "$cfg" ignore 0
401         [ "$ignore" -ne 0 ] && return 0
402
403         config_get library "$cfg" library
404         if ! validate_olsrd_option "$library"; then
405                 warning_invalid_value olsrd "$cfg" "library"
406                 return 0
407         fi
408         if ! [ -x "/lib/$library" -o -x "/usr/lib/$library" -o -x "/usr/local/lib/$library" ]; then
409                 echo "Warning: Plugin library '$library' not found, skipped" 1>&2
410                 return 0
411         fi
412
413         case "$library" in
414                 olsrd_nameservice.*)
415                         config_get name "$cfg" name
416                         [ -z "$name" ] && config_set "$cfg" name $SYSTEM_HOSTNAME
417
418                         config_get suffix "$cfg" suffix
419                         [ -z "$suffix" ] && config_set "$cfg" suffix '.olsr'
420
421                         config_get lat "$cfg" lat
422                         config_get lon "$cfg" lon
423                         config_get latlon_infile "$cfg" latlon_infile
424                         if [ \( -z "$lat" -o -z "$lat" \) -a -z "$latlon_infile" ]; then
425                                 if [ -f '/var/run/latlon.txt' ]; then
426                                         config_set "$cfg" lat ''
427                                         config_set "$cfg" lon ''
428                                         config_set "$cfg" latlon_infile '/var/run/latlon.txt'
429                                 else
430                                         config_set "$cfg" lat "$SYSTEM_LAT"
431                                         config_set "$cfg" lon "$SYSTEM_LON"
432                                 fi
433                         fi
434
435                         config_get latlon_file "$cfg" latlon_file
436                         [ -z "$latlon_file" ] && config_set "$cfg" latlon_file '/var/run/latlon.js'
437                 ;;
438         esac
439
440         echo -n "${N}LoadPlugin \"$library\"${N}{"
441         config_write_options "$OLSRD_LOADPLUGIN_SCHEMA" "$cfg" olsrd_write_plparam "${T}"
442         echo "${N}}"
443
444         return 0
445 }
446
447 olsrd_write_interface() {
448         local cfg=$1
449         validate_varname "$cfg" || return 0
450         local ignore
451         local interfaces
452         local interface
453         local ifnames
454
455         config_get_bool ignore "$cfg" ignore 0
456         [ "$ignore" -ne 0 ] && return 0
457
458         ifnames=
459         config_get interfaces "$cfg" interface
460         for interface in $interfaces; do
461                 if validate_varname "$interface"; then
462                         if get_ifname "$interface"; then
463                                 ifnames="$ifnames \"$IFNAME\""
464                         else
465                                 echo "Warning: Interface '$interface' not found, skipped" 1>&2
466                         fi
467                 else
468                         warning_invalid_value olsrd "$cfg" "interface"
469                 fi
470         done
471
472         [ -z "$ifnames" ] && return 0
473
474         echo -n "${N}Interface$ifnames${N}{"
475         config_write_options "$OLSRD_INTERFACE_SCHEMA" "$cfg" olsrd_write_option "${T}"
476         echo "${N}}"
477         INTERFACES_COUNT=$((INTERFACES_COUNT + 1))
478
479         return 0
480 }
481
482 olsrd_update_schema() {
483         local command="$1"
484         validate_varname "$command" || return 0
485         local varname="$2"
486         validate_varname "$varname" || return 0
487         local value="$3"
488         local cfg="$CONFIG_SECTION"
489         local cfgt
490         local cur_varname
491
492         config_get cfgt "$cfg" TYPE
493         case "$cfgt" in
494                 olsrd) config_update_schema OLSRD_OLSRD_SCHEMA "$command" "$varname" "$value";;
495                 IpcConnect) config_update_schema OLSRD_IPCCONNECT_SCHEMA "$command" "$varname" "$value";;
496                 LoadPlugin) config_update_schema OLSRD_LOADPLUGIN_SCHEMA "$command" "$varname" "$value";;
497                 Interface) config_update_schema OLSRD_INTERFACE_SCHEMA "$command" "$varname" "$value";;
498         esac
499
500         return 0
501 }
502
503 olsrd_write_config() {
504         OLSRD_COUNT=0
505         config_foreach olsrd_write_olsrd olsrd
506         IPCCONNECT_COUNT=0
507         config_foreach olsrd_write_ipcconnect IpcConnect
508         HNA4_COUNT=0
509         config_foreach olsrd_write_hna4 Hna4
510         [ "$HNA4_COUNT" -gt 0 ] && echo "${N}}"
511         HNA6_COUNT=0
512         config_foreach olsrd_write_hna6 Hna6
513         [ "$HNA6_COUNT" -gt 0 ] && echo "${N}}"
514         config_foreach olsrd_write_loadplugin LoadPlugin
515         INTERFACES_COUNT=0
516         config_foreach olsrd_write_interface Interface
517         echo
518
519         return 0
520 }
521
522 start() {
523         ### check for running instance
524         if [ -s $PID ]; then
525                 if kill -0 $(cat $PID) 2>&-; then
526                         echo "there is already a running instance ($(cat $PID))"
527                         return 1
528                 fi
529         fi
530         
531         SYSTEM_HOSTNAME=
532         SYSTEM_LAT=
533         SYSTEM_LON=
534         config_load system
535         config_foreach system_config system
536
537         option_cb() {
538                 olsrd_update_schema "option" "$@"
539         }
540
541         list_cb() {
542                 olsrd_update_schema "list" "$@"
543         }
544
545         include /lib/network
546         scan_interfaces
547         config_load olsrd
548         reset_cb
549
550         OLSRD_CONFIG_FILE=
551         config_foreach olsrd_find_config_file olsrd
552
553         if [ -z "$OLSRD_CONFIG_FILE" ]; then
554                 ### generate config
555                 mkdir -p ${CONF%/*}
556                 olsrd_write_config > $CONF
557                 if [ "$INTERFACES_COUNT" -gt 0 -a "$OLSRD_COUNT" -gt 0 ]; then
558                         OLSRD_CONFIG_FILE=$CONF
559                 fi
560         fi
561
562         [ -z "$OLSRD_CONFIG_FILE" ] && return 1
563
564         ### start olsrd
565         start-stop-daemon -b -m -p $PID -x $BIN -S -- -f $CONF -nofork
566 }
567
568 stop() {
569         ### stop olsrd
570         start-stop-daemon -q -p $PID -a ${BIN##*/} -K
571 }
572
573 restart() {
574         ### override generic restart because we need some time between stop and start
575         stop; sleep 3; start
576 }