|
|
@ -1,425 +0,0 @@ |
|
|
|
#!/bin/sh /etc/rc.common |
|
|
|
# Copyright (C) 2012-2013 OpenWrt.org |
|
|
|
|
|
|
|
START=95 |
|
|
|
|
|
|
|
SERVICE_USE_PID=1 |
|
|
|
|
|
|
|
EXTRA_COMMANDS="up down show_key generate_key" |
|
|
|
|
|
|
|
LIST_SEP=" |
|
|
|
" |
|
|
|
TMP_FASTD=/tmp/fastd |
|
|
|
FASTD_COMMAND=/usr/bin/fastd |
|
|
|
|
|
|
|
|
|
|
|
section_enabled() { |
|
|
|
config_get_bool enabled "$1" 'enabled' 0 |
|
|
|
[ $enabled -gt 0 ] |
|
|
|
} |
|
|
|
|
|
|
|
error() { |
|
|
|
echo "${initscript}:" "$@" 1>&2 |
|
|
|
} |
|
|
|
|
|
|
|
get_key_instance() { |
|
|
|
local s="$1" |
|
|
|
|
|
|
|
config_get secret "$s" secret |
|
|
|
if [ "$secret" = 'generate' ]; then |
|
|
|
secret=`"$FASTD_COMMAND" --generate-key --machine-readable` |
|
|
|
uci -q set fastd."$s".secret="$secret" && uci -q commit fastd |
|
|
|
fi |
|
|
|
|
|
|
|
echo "$secret" |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
escape_string() { |
|
|
|
local t=${1//\\/\\\\} |
|
|
|
echo -n "\"${t//\"/\\\"}\"" |
|
|
|
} |
|
|
|
|
|
|
|
guard_value() { |
|
|
|
local t=${1//[^-a-z0-9\[\].:]/} |
|
|
|
echo -n "$t" |
|
|
|
} |
|
|
|
|
|
|
|
guard_remote() { |
|
|
|
local t=${1//[^-a-zA-Z0-9\[\].:\"% ]/} |
|
|
|
local quotes=${t//[^\"]/} |
|
|
|
if [ "${#quotes}" = 0 -o "${#quotes}" = 2 ]; then |
|
|
|
echo -n "$t" |
|
|
|
fi |
|
|
|
} |
|
|
|
|
|
|
|
yes_no() { |
|
|
|
case "$1" in |
|
|
|
0|no|off|false|disabled) echo -n no;; |
|
|
|
*) echo -n yes;; |
|
|
|
esac |
|
|
|
} |
|
|
|
|
|
|
|
config_string_config='include $(escape_string "$value");' |
|
|
|
config_string_config_peer='include peer $(escape_string "$value");' |
|
|
|
config_string_config_peer_dir='include peers from $(escape_string "$value");' |
|
|
|
config_string_bind='bind $(guard_value "$value");' |
|
|
|
config_string_method='method $(escape_string "$value");' |
|
|
|
config_string_syslog_level='log to syslog level $(guard_value "$value");' |
|
|
|
config_string_mode='mode $(guard_value "$value");' |
|
|
|
config_string_interface='interface $(escape_string "$value");' |
|
|
|
config_string_mtu='mtu $(guard_value "$value");' |
|
|
|
config_string_peer_limit='peer limit $(guard_value "$value");' |
|
|
|
config_string_user='user $(escape_string "$value");' |
|
|
|
config_string_group='group $(escape_string "$value");' |
|
|
|
config_string_pmtu='pmtu $(yes_no "$value");' |
|
|
|
config_string_forward='forward $(yes_no "$value");' |
|
|
|
config_string_hide_ip_addresses='hide ip addresses $(yes_no "$value");' |
|
|
|
config_string_hide_mac_addresses='hide mac addresses $(yes_no "$value");' |
|
|
|
config_string_secure_handshakes='secure handshakes $(yes_no "$value");' |
|
|
|
config_string_packet_mark='packet mark $(guard_value "$value");' |
|
|
|
|
|
|
|
config_string_peer='peer $(escape_string "$value") {' |
|
|
|
config_string_peer_group='peer group $(escape_string "$value") {' |
|
|
|
|
|
|
|
peer_string_key='key $(escape_string "$value");' |
|
|
|
peer_string_float='float $(yes_no "$value");' |
|
|
|
peer_string_remote='remote $(guard_remote "$value");' |
|
|
|
|
|
|
|
generate_option() { |
|
|
|
local __string=$(eval echo \"\$$2\") |
|
|
|
local value="$1"; |
|
|
|
eval echo "\"$__string\"" |
|
|
|
} |
|
|
|
|
|
|
|
append_option() { |
|
|
|
local v; local len; local s="$1"; local prefix="$2"; local p="$3" |
|
|
|
|
|
|
|
config_get len "$s" "${p}_LENGTH" |
|
|
|
|
|
|
|
if [ -z "$len" ]; then |
|
|
|
config_get v "$s" "$p" |
|
|
|
[ -n "$v" ] && generate_option "$v" "${prefix}_string_${p}" |
|
|
|
else |
|
|
|
config_list_foreach "$s" "$p" generate_option "${prefix}_string_${p}" |
|
|
|
fi |
|
|
|
} |
|
|
|
|
|
|
|
append_options() { |
|
|
|
local p; local s="$1"; local prefix="$2"; shift; shift |
|
|
|
for p in $*; do |
|
|
|
append_option "$s" "$prefix" "$p" |
|
|
|
done |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
generate_config_secret() { |
|
|
|
echo "secret $(escape_string "$1");" |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
generate_peer_config() { |
|
|
|
local peer="$1" |
|
|
|
|
|
|
|
# These options are deprecated |
|
|
|
config_get address "$peer" address |
|
|
|
config_get hostname "$peer" hostname |
|
|
|
config_get address_family "$peer" address_family |
|
|
|
config_get port "$peer" port |
|
|
|
|
|
|
|
if [ "$address" -o "$hostname" ]; then |
|
|
|
if [ -z "$port" ]; then |
|
|
|
error "peer $peer: address or hostname, but no port given" |
|
|
|
return 1 |
|
|
|
fi |
|
|
|
|
|
|
|
if [ "$hostname" ]; then |
|
|
|
generate_option peer_string_remote "$address_family \"$hostname\" port $port" |
|
|
|
fi |
|
|
|
|
|
|
|
if [ "$address" ]; then |
|
|
|
generate_option peer_string_remote "$address port $port" |
|
|
|
fi |
|
|
|
fi |
|
|
|
|
|
|
|
append_options "$peer" peer \ |
|
|
|
key float remote |
|
|
|
} |
|
|
|
|
|
|
|
generate_single_peer_config() { |
|
|
|
local peer="$1"; local net="$2" |
|
|
|
|
|
|
|
config_get peer_net "$peer" net |
|
|
|
config_get peer_group "$peer" group |
|
|
|
[ "$net" = "$peer_net" -a "$peer_group" = '' ] || return 0 |
|
|
|
|
|
|
|
section_enabled "$peer" || return 0 |
|
|
|
|
|
|
|
generate_option "$peer" config_string_peer |
|
|
|
generate_peer_config "$peer" |
|
|
|
echo '}' |
|
|
|
} |
|
|
|
|
|
|
|
create_peer_config() { |
|
|
|
local peer="$1"; local net="$2"; local group="$3"; local path="$4" |
|
|
|
|
|
|
|
config_get peer_net "$peer" net |
|
|
|
config_get peer_group "$peer" group |
|
|
|
[ "$group" = "$peer_group" ] || return 0 |
|
|
|
|
|
|
|
if [ "$net" != "$peer_net" ]; then |
|
|
|
[ -z "$group" ] || error "warning: the peer group of peer '$peer' doesn't match its net, the peer will be ignored" |
|
|
|
return 0 |
|
|
|
fi |
|
|
|
|
|
|
|
section_enabled "$peer" || return 0 |
|
|
|
|
|
|
|
generate_peer_config "$peer" >"$path/$peer" |
|
|
|
} |
|
|
|
|
|
|
|
update_peer_group() { |
|
|
|
local net="$1"; local group_dir="$2"; local group="$3"; local update_only="$4" |
|
|
|
local path="$TMP_FASTD/fastd.$net/$group_dir" |
|
|
|
|
|
|
|
rm -rf "$path" |
|
|
|
mkdir -p "$path" |
|
|
|
|
|
|
|
config_foreach create_peer_config 'peer' "$net" "$group" "$path" |
|
|
|
|
|
|
|
if [ -z "$update_only" ]; then |
|
|
|
generate_option "$path" config_string_config_peer_dir |
|
|
|
fi |
|
|
|
|
|
|
|
config_foreach generate_peer_group_config 'peer_group' "$net" "$group_dir" "$update_only" "$group" |
|
|
|
} |
|
|
|
|
|
|
|
generate_peer_group_config() { |
|
|
|
local group="$1"; local net="$2"; local group_dir="$3%$group"; local update_only="$4"; local parent="$5" |
|
|
|
|
|
|
|
config_get group_net "$group" net |
|
|
|
config_get group_parent "$group" parent |
|
|
|
[ "$parent" = "$group_parent" ] || return 0 |
|
|
|
|
|
|
|
if [ "$net" != "$peer_net" ]; then |
|
|
|
[ -z "$parent" ] || error "warning: the parent of peer group '$group' doesn't match its net, the peer group will be ignored" |
|
|
|
return 0 |
|
|
|
fi |
|
|
|
|
|
|
|
section_enabled "$group" || return 0 |
|
|
|
|
|
|
|
if [ -z "$update_only" ]; then |
|
|
|
generate_option "$group" config_string_peer_group |
|
|
|
append_options "$group" config \ |
|
|
|
config config_peer config_peer_dir peer_limit |
|
|
|
fi |
|
|
|
|
|
|
|
update_peer_group "$net" "$group_dir" "$group" "$update_only" |
|
|
|
|
|
|
|
if [ -z "$update_only" ]; then |
|
|
|
echo '}' |
|
|
|
fi |
|
|
|
} |
|
|
|
|
|
|
|
update_peer_groups() { |
|
|
|
local net="$1"; local update_only="$2" |
|
|
|
|
|
|
|
update_peer_group "$net" 'peers' '' "$update_only" |
|
|
|
} |
|
|
|
|
|
|
|
generate_config() { |
|
|
|
local s="$1" |
|
|
|
|
|
|
|
generate_option 'info' config_string_syslog_level |
|
|
|
|
|
|
|
append_options "$s" config \ |
|
|
|
config config_peer config_peer_dir bind method syslog_level mode interface mtu peer_limit \ |
|
|
|
user group pmtu forward hide_ip_addresses hide_mac_addresses secure_handshakes packet_mark |
|
|
|
|
|
|
|
config_get mode "$s" mode |
|
|
|
|
|
|
|
if [ "$mode" = "tun" ]; then |
|
|
|
config_foreach generate_single_peer_config 'peer' "$s" |
|
|
|
else |
|
|
|
update_peer_groups "$s" |
|
|
|
fi |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
generate_key_instance() { |
|
|
|
local s="$1" |
|
|
|
|
|
|
|
config_get secret "$s" secret |
|
|
|
if [ -z "$secret" -o "$secret" = 'generate' ]; then |
|
|
|
secret=`fastd --generate-key --machine-readable` |
|
|
|
uci -q set fastd."$s".secret="$secret" && uci -q commit fastd |
|
|
|
fi |
|
|
|
|
|
|
|
generate_config_secret "$secret" | "$FASTD_COMMAND" --config - --show-key --machine-readable |
|
|
|
} |
|
|
|
|
|
|
|
show_key_instance() { |
|
|
|
local s="$1" |
|
|
|
|
|
|
|
local secret=`get_key_instance "$s"` |
|
|
|
if [ -z "$secret" ]; then |
|
|
|
error "$s: secret is not set" |
|
|
|
return 1 |
|
|
|
fi |
|
|
|
|
|
|
|
generate_config_secret "$secret" | "$FASTD_COMMAND" --config - --show-key --machine-readable |
|
|
|
} |
|
|
|
|
|
|
|
start_instance() { |
|
|
|
local s="$1" |
|
|
|
|
|
|
|
section_enabled "$s" || return 1 |
|
|
|
|
|
|
|
SERVICE_PID_FILE="/var/run/fastd.$s.pid" |
|
|
|
|
|
|
|
config_get interface "$s" interface |
|
|
|
if [ -z "$interface" ]; then |
|
|
|
error "$s: interface is not set" |
|
|
|
return 1 |
|
|
|
fi |
|
|
|
|
|
|
|
if ifconfig "$interface" &>/dev/null; then |
|
|
|
error "$s: interface '$interface' is already in use" |
|
|
|
return 1 |
|
|
|
fi |
|
|
|
|
|
|
|
config_get mode "$s" mode |
|
|
|
if [ -z "$mode" ]; then |
|
|
|
error "$s: mode is not set" |
|
|
|
return 1 |
|
|
|
fi |
|
|
|
|
|
|
|
local secret=`get_key_instance "$s"` |
|
|
|
if [ -z "$secret" ]; then |
|
|
|
error "$s: secret is not set" |
|
|
|
return 1 |
|
|
|
fi |
|
|
|
|
|
|
|
rm -f "$SERVICE_PID_FILE" |
|
|
|
touch "$SERVICE_PID_FILE" |
|
|
|
|
|
|
|
config_get user "$s" user |
|
|
|
if [ "$user" ]; then |
|
|
|
chown "$user" "$SERVICE_PID_FILE" |
|
|
|
fi |
|
|
|
|
|
|
|
(generate_config_secret "$secret"; generate_config "$s") | service_start "$FASTD_COMMAND" --config - --daemon --pid-file "$SERVICE_PID_FILE" |
|
|
|
|
|
|
|
if ! ifconfig "$interface" >/dev/null 2>&1; then |
|
|
|
error "$s: startup failed" |
|
|
|
return 1 |
|
|
|
fi |
|
|
|
|
|
|
|
config_get up "$s" up |
|
|
|
[ -n "$up" ] && sh -c "$up" - "$interface" |
|
|
|
} |
|
|
|
|
|
|
|
stop_instance() { |
|
|
|
local s="$1" |
|
|
|
|
|
|
|
section_enabled "$s" || return 1 |
|
|
|
|
|
|
|
SERVICE_PID_FILE="/var/run/fastd.$s.pid" |
|
|
|
|
|
|
|
config_get interface "$s" interface |
|
|
|
if [ -z "$interface" ]; then |
|
|
|
error "$s: interface is not set" |
|
|
|
return 1 |
|
|
|
fi |
|
|
|
|
|
|
|
if ! ifconfig "$interface" &>/dev/null; then |
|
|
|
error "$s: interface '$interface' does not exist" |
|
|
|
return 1 |
|
|
|
fi |
|
|
|
|
|
|
|
config_get down "$s" down |
|
|
|
[ -n "$down" ] && sh -c "$down" - "$interface" |
|
|
|
|
|
|
|
service_stop "$FASTD_COMMAND" |
|
|
|
|
|
|
|
rm -rf "$TMP_FASTD/fastd.$s" |
|
|
|
} |
|
|
|
|
|
|
|
reload_instance() { |
|
|
|
local s="$1" |
|
|
|
|
|
|
|
section_enabled "$s" || return 1 |
|
|
|
|
|
|
|
config_get mode "$s" mode |
|
|
|
[ "$mode" = "tun" ] && return 1 |
|
|
|
|
|
|
|
update_peer_groups "$s" true |
|
|
|
|
|
|
|
SERVICE_PID_FILE="/var/run/fastd.$s.pid" |
|
|
|
service_reload "$FASTD_COMMAND" |
|
|
|
} |
|
|
|
|
|
|
|
start() { |
|
|
|
config_load 'fastd' |
|
|
|
config_foreach start_instance 'fastd' |
|
|
|
return 0 |
|
|
|
} |
|
|
|
|
|
|
|
stop() { |
|
|
|
config_load 'fastd' |
|
|
|
config_foreach stop_instance 'fastd' |
|
|
|
return 0 |
|
|
|
} |
|
|
|
|
|
|
|
reload() { |
|
|
|
config_load 'fastd' |
|
|
|
config_foreach reload_instance 'fastd' |
|
|
|
return 0 |
|
|
|
} |
|
|
|
|
|
|
|
up() { |
|
|
|
local exists |
|
|
|
local instance |
|
|
|
config_load 'fastd' |
|
|
|
for instance in "$@"; do |
|
|
|
config_get exists "$instance" 'TYPE' |
|
|
|
if [ "$exists" = 'fastd' ]; then |
|
|
|
start_instance "$instance" |
|
|
|
fi |
|
|
|
done |
|
|
|
} |
|
|
|
|
|
|
|
down() { |
|
|
|
local exists |
|
|
|
local instance |
|
|
|
config_load 'fastd' |
|
|
|
for instance in "$@"; do |
|
|
|
config_get exists "$instance" 'TYPE' |
|
|
|
if [ "$exists" = 'fastd' ]; then |
|
|
|
stop_instance "$instance" |
|
|
|
fi |
|
|
|
done |
|
|
|
} |
|
|
|
|
|
|
|
show_key() { |
|
|
|
local exists |
|
|
|
local instance |
|
|
|
config_load 'fastd' |
|
|
|
for instance in "$@"; do |
|
|
|
config_get exists "$instance" 'TYPE' |
|
|
|
if [ "$exists" = 'fastd' ]; then |
|
|
|
show_key_instance "$instance" |
|
|
|
fi |
|
|
|
done |
|
|
|
} |
|
|
|
|
|
|
|
generate_key() { |
|
|
|
local exists |
|
|
|
local instance |
|
|
|
config_load 'fastd' |
|
|
|
for instance in "$@"; do |
|
|
|
config_get exists "$instance" 'TYPE' |
|
|
|
if [ "$exists" = 'fastd' ]; then |
|
|
|
generate_key_instance "$instance" |
|
|
|
fi |
|
|
|
done |
|
|
|
} |