summaryrefslogtreecommitdiffstats
path: root/babeld/files/babeld.init
blob: 416bbe4028daf91a0c9068214e7331f4f4460c21 (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
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
#!/bin/sh /etc/rc.common

. $IPKG_INSTROOT/lib/functions/network.sh

USE_PROCD=1
START=70

CONFIGFILE='/var/etc/babeld.conf'
OTHERCONFIGFILE="/etc/babeld.conf"
OTHERCONFIGDIR="/tmp/babeld.d/"
EXTRA_COMMANDS="status"
EXTRA_HELP="        status Dump Babel's table to the log file."

# Options to ignore for the global section (old options that are translated
# for backward compatibility with old configuration files)
ignored_options="carrier_sense assume_wireless no_split_horizon random_router_id multicast_address port hello_interval wired_hello_interval smoothing_half_time duplication_priority local_server conf_file conf_dir"

# Append a line to the configuration file
cfg_append() {
        local value="$1"
        echo "$value" >> $CONFIGFILE
}

cfg_append_option() {
	local section="$1"
	local option="$2"
	local value
	config_get value "$section" "$option"
	# babeld convention for options is '-', not '_'
	[ -n "$value" ] && cfg_append "${option//_/-} $value"
}

# Append to the "$buffer" variable
append_ifname() {
	local section="$1"
	local option="$2"
	local switch="$3"
	local _name
	config_get _name "$section" "$option"
	[ -z "$_name" ] && return 0
	local ifname=$(uci_get_state network "$_name" ifname "$_name")
	append buffer "$switch $ifname"
}

append_bool() {
	local section="$1"
	local option="$2"
	local value="$3"
	local _loctmp
	config_get_bool _loctmp "$section" "$option" 0
	[ "$_loctmp" -gt 0 ] && append buffer "$value"
}

append_parm() {
	local section="$1"
	local option="$2"
	local switch="$3"
	local _loctmp
	config_get _loctmp "$section" "$option"
	[ -z "$_loctmp" ] && return 0
	append buffer "$switch $_loctmp"
}


# Provides backward compatibility for old option names in the global section.
translate_option() {
	local section="$1"
	local old_option="$2"
	local new_option="$3"
	local _value
	config_get _value "$section" "$old_option"
	[ -z "$_value" ] && return
	cfg_append "${new_option//_/-} $_value"
}

translate_bool() {
	local section="$1"
	local old_option="$2"
	local new_option="$3"
	local _bool
	local _value
	config_get_bool _bool "$section" "$old_option" 0
	[ "$_bool" -eq 0 ] && return
	cfg_append "${new_option//_/-} true"
}

# Adds a new interface section for setting default interface options.
add_default_option() {
	local option="$1"
	local value="$2"
	cfg_append "default ${option//_/-} $value"
}

# Global 'hello_interval' and 'wired_hello_interval' options are ignored,
# because they have no direct equivalent: you should use
# interface-specific settings.
parse_old_global_options() {
	local section="$1"
	translate_bool   "$section" 'carrier_sense'	'link_detect'
	translate_bool   "$section" 'random_router_id'	'random_id'
	translate_option "$section" 'multicast_address'	'protocol_group'
	translate_option "$section" 'port'		'protocol_port'
	translate_option "$section" 'local_server'	'local_port'
	translate_option "$section" 'smoothing_half_time'	'smoothing_half_life'
	translate_option "$section" 'duplication_priority'	'allow_duplicates'
	# These two global options are turned into default interface options.
	local _bool
	config_get_bool _bool "$section" 'assume_wireless' 0
	[ "$_bool" -eq 1 ] && add_default_option "wired" "false"
	config_get_bool _bool "$section" 'no_split_horizon' 0
	[ "$_bool" -eq 1 ] && add_default_option "split_horizon" "false"
        # Configure alternative configuration file and directory
	local conf_file
	config_get conf_file "$section" "conf_file"
	[ -n "$conf_file" ] && OTHERCONFIGFILE="$conf_file"
	local conf_dir
	config_get conf_dir "$section" "conf_dir"
	[ -n "$conf_dir" ] && OTHERCONFIGDIR="$conf_dir"
}

babel_filter() {
	local cfg="$1"
	local _loctmp

	local _ignored
	config_get_bool _ignored "$cfg" 'ignore' 0
	[ "$_ignored" -eq 1 ] && return 0

	unset buffer
	append_parm "$cfg" 'type' ''

	append_bool "$cfg" 'local' 'local'

	append_parm "$cfg" 'ip' 'ip'
	append_parm "$cfg" 'eq' 'eq'
	append_parm "$cfg" 'le' 'le'
	append_parm "$cfg" 'ge' 'ge'
	append_parm "$cfg" 'src_ip' 'src-ip'
	append_parm "$cfg" 'src_eq' 'src-eq'
	append_parm "$cfg" 'src_le' 'src-le'
	append_parm "$cfg" 'src_ge' 'src-ge'
	append_parm "$cfg" 'neigh' 'neigh'
	append_parm "$cfg" 'id' 'id'
	append_parm "$cfg" 'proto' 'proto'

	append_ifname "$cfg" 'if' 'if'

	append_parm "$cfg" 'action' ''

	cfg_append "$buffer"
}

# Only one of babeld's options is allowed multiple times, "import-table".
# We just append it multiple times.
list_cb() {
	option_cb "$@"
}

babel_config_cb() {
	local type="$1"
	local section="$2"
	case "$type" in
	"general")
		option_cb() {
			local option="$1"
			local value="$2"
			# Ignore old options
			list_contains ignored_options "$option" && return
			# Skip lists. They will be taken care of by list_cb
			test "${option#*_ITEM}" != "$option" && return
			test "${option#*_LENGTH}" != "$option" && return
			cfg_append "${option//_/-} $value"
		}
	;;
	"interface")
		local _ifname
		config_get _ifname "$section" 'ifname'
		# Backward compatibility: try to use the section name
		# if no "option ifname" was used.
		[ -z "$_ifname" -a "${section:0:3}" != "cfg" ] && _ifname="$section"
		# Try to resolve the logical interface name
		unset interface
		network_get_device interface "$_ifname" || interface="$_ifname"
		option_cb() {
			local option="$1"
			local value="$2"
			local _interface
			# "option ifname" is a special option, don't actually
			# generate configuration for it.
			[ "$option" = "ifname" ] && return
			[ -n "$interface" ] && _interface="interface $interface" || _interface="default"
			cfg_append "$_interface ${option//_/-} $value"
		}
		# Handle ignore options.
		local _ignored
		# This works because we loaded the whole configuration
		# beforehand (see config_load below).
		config_get_bool _ignored "$section" 'ignore' 0
		if [ "$_ignored" -eq 1 ]
		then
			option_cb() { return; }
		else
			# Also include an empty "interface $interface" statement,
			# so that babeld operates on this interface.
			[ -n "$interface" ] && cfg_append "interface $interface"
		fi
	;;
	*)
		# Don't use reset_cb, this would also reset config_cb
		option_cb() { return; }
	;;
	esac
}

start_service() {
	mkdir -p /var/lib
	mkdir -p /var/etc
	mkdir -p $OTHERCONFIGDIR

	# Start by emptying the generated config file
	>"$CONFIGFILE"
	# Import dynamic config files
	for f in $OTHERCONFIGDIR/*.conf; do
		[ -f "$f" ] && cat $f >> $CONFIGFILE
	done
	# First load the whole config file, without callbacks, so that we are
	# aware of all "ignore" options in the second pass.
	config_load babeld
	# Parse general and interface sections thanks to the "config_cb()"
	# callback.  This allows to loop over all options without having to
	# know their name in advance.
	config_cb() { babel_config_cb "$@"; }
	config_load babeld
	# Backward compatibility
	config_foreach parse_old_global_options general
	# Parse filters separately, since we know which options we expect
	config_foreach babel_filter filter
	procd_open_instance
	# Using multiple config files is supported since babeld 1.5.1
	procd_set_param command /usr/sbin/babeld -L /var/log/babeld.log -I "" -c "$OTHERCONFIGFILE" -c "$CONFIGFILE"
	procd_set_param file "$OTHERCONFIGFILE" "$CONFIGFILE"
	procd_set_param respawn
	procd_close_instance
}

service_triggers() {
	procd_add_reload_trigger babeld
}

status() {
	kill -USR1 $(pgrep -P 1 babeld)
}