#!/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." # 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" } 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 options that are not supposed to be given to babeld [ "$option" = "conf_file" ] && return [ "$option" = "conf_dir" ] && 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 _ignored config_get_bool _ignored "$section" 'ignore' 0 [ "$_ignored" == "1" ] && { option_cb() { return; } return } local _ifname config_get _ifname "$section" 'ifname' # Try to resolve the logical interface name local interface network_get_device interface "$_ifname" || interface="$_ifname" # Ignore section if ifname is not provided [ -z "$interface" ] && { logger -s -t babeld "Ignoring interface section which miss ifname" return } interfaceFile="${OTHERCONFIGDIR}/interface_$interface.conf" if [ "$interface" == "default" ]; then echo "default" > "$interfaceFile" else echo "interface $interface" > "$interfaceFile" fi option_cb() { local option="$1" local value="$2" # "option ifname" is a special option, don't actually # generate configuration for it. [ "$option" == "ifname" ] && return echo "$(cat $interfaceFile) ${option//_/-} $value" > "$interfaceFile" } } ;; *) # Don't use reset_cb, this would also reset config_cb option_cb() { return; } ;; esac } # Support for conf_file and conf_dir babel_configpaths() { local cfg="$1" local conf_file config_get conf_file "$cfg" "conf_file" [ -n "$conf_file" ] && OTHERCONFIGFILE="$conf_file" local conf_dir config_get conf_dir "$cfg" "conf_dir" [ -n "$conf_dir" ] && OTHERCONFIGDIR="$conf_dir" } start_service() { mkdir -p /var/lib mkdir -p /var/etc mkdir -p "$OTHERCONFIGDIR" # Start by emptying the generated config file >"$CONFIGFILE" # First load the whole config file, without callbacks, so that we are # aware of all "ignore" options in the second pass. This also allows # to load the configuration paths (conf_file and conf_dir). config_load babeld # Configure alternative configuration file and directory config_foreach babel_configpaths "general" # 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 # Parse filters separately, since we know which options we expect config_foreach babel_filter filter # Import dynamic config files for f in "$OTHERCONFIGDIR"/*.conf; do [ -f "$f" ] && cat "$f" >> "$CONFIGFILE" done procd_open_instance # Using multiple config files is supported since babeld 1.5.1 procd_set_param command /usr/sbin/babeld -I "" -c "$OTHERCONFIGFILE" -c "$CONFIGFILE" procd_set_param stdout 1 procd_set_param stderr 1 procd_set_param file "$OTHERCONFIGFILE" "$OTHERCONFIGDIR"/*.conf "$CONFIGFILE" ### Respawn automatically when process dies, after waiting respawn_timeout seconds ### If respawn_retry consecutives respawns die before respawn_threshold seconds (i.e. they crash) ### it will stop trying and leave it dead. procd_set_param respawn ${respawn_threshold:-60} ${respawn_timeout:-3} ${respawn_retry:-5} procd_close_instance } service_triggers() { procd_add_reload_trigger babeld } status() { kill -USR1 $(pgrep -P 1 babeld) }