blob: 94d77786fba379c470a4d7f9c17edeaf0b629955 [file] [log] [blame]
#!/bin/selfclean /bin/sh
#
# This script monitors /tmp/conman/command* /tmp/conman/access_point_enabled*
# and starts or stops access points accordingly.
#
# Also adds routes based on gateways output by dhclient-script.
#
. /etc/utils.sh
if experiment BigInitRwnd; then
initrwnd='initrwnd 1000'
else
initrwnd=
fi
if experiment ConmanDebug; then
set -x
fi
TMP_DIR="/tmp/conman"
CONFIG_DIR="/config/conman"
mkdir -p $TMP_DIR
mkdir -p $CONFIG_DIR
iplog() {
echo "running: ip" "$@" >&2
ip "$@"
}
valid_word() {
case "$1" in
access_point|command) return 0 ;;
*) return 1 ;;
esac
}
valid_band() {
case "$1" in
2.4|5) return 0 ;;
*) return 1 ;;
esac
}
stopap() {
local interface_suffix="$1"
local band="$2"
flags="--band $band"
if [ -n "$interface_suffix" ]; then
flags="$flags --interface-suffix "$interface_suffix""
fi
if ! $(wifi stopap $flags); then
echo "Failed to stop access point for $suffix $band"
false
fi
}
# Check all existing command and gateway files, then monitor those as well as
# access_point files for changes.
{ cd "$TMP_DIR" && ls gateway.* command.* subnet.*;
cd "$CONFIG_DIR" && ls command.*;
watch-dir $TMP_DIR $CONFIG_DIR; } |
while read filename; do
route_type=
if startswith "$filename" "subnet."; then
route_type="subnet"
fi
if startswith "$filename" "gateway."; then
route_type="gateway"
fi
if [ "$route_type" != "" ]; then
filepath="$TMP_DIR/$filename"
if [ -e "$filepath" ]; then
interface=${filename#${route_type}.}
# make sure interface is actually an interface, and not a .tmp file
if [ ! -e "/sys/class/net/$interface" ]; then
continue
fi
# Trying to add a default route without a subnet route fails, because
# there is no route to the gateway. So just always update the subnet
# route first, and then update the default route if we know the gateway.
subnet_filepath="$TMP_DIR/subnet.$interface"
if [ -e "$subnet_filepath" ]; then
subnet=$(cat "$subnet_filepath")
# If this script is running as conman's deathrattle, it is possible that
# there is a wifi route up too and also that acs_autoprovisioning is
# enabled. Between deleting and re-adding this default route, traffic
# could be routed via wifi, and if autoprovisioning is enabled and the
# wifi connection is to a neighbor's RG then the ACS could provision this
# device to the neighbor. Removing the file which enables that
# autoprovisioning here prevents that from happening.
rm -f /tmp/conman/acs_autoprovisioning
# Remove all subnet routes on $interface except default, with 'scope
# link', then recreate the desired subnet route.
iplog -4 route show dev "$interface" |
while read route junk; do
# Ignore the RFC2365 multicast route.
if ! startswith "$route" "239"; then
if contains "$route" "/" && [ "$route" != "$subnet" ]; then
iplog -4 route del "$route" dev "$interface"
fi
fi
done
iplog -4 route add "$subnet" dev "$interface" $initrwnd
gateway_filepath="$TMP_DIR/gateway.$interface"
if [ -e "$gateway_filepath" ]; then
gateway=$(cat "$gateway_filepath")
if ! ip route show dev "$interface" | grep default | grep "via $gateway"; then
iplog -4 route del default dev "$interface"
iplog -4 route add default via "$gateway" dev "$interface" $initrwnd
fi
fi
fi
fi
continue
fi
# This assumes command files in /tmp (for provisioning networks) will have an
# interface suffix, and those in /config (the user's WLAN) will not.
word=
suffix=
band=
IFS='.' read word band <<EOF
$filename
EOF
if valid_word "$word" && valid_band "$band"; then
expect_dir="$CONFIG_DIR"
else
IFS='.' read word suffix band <<EOF
$filename
EOF
if valid_word "$word" && valid_band "$band"; then
expect_dir="$TMP_DIR"
else
continue
fi
fi
if [ -z "$suffix" ]; then
command="$expect_dir/command.$band"
access_point="$expect_dir/access_point.$band"
else
command="$expect_dir/command.$suffix.$band"
access_point="$expect_dir/access_point.$suffix.$band"
fi
if [ -e "$command" ] && [ -e "$access_point" ]; then
if ! run_command_lines $command; then
echo "Failed to start access point for '$extension'"
fi
else
stopap "$suffix" "$band"
fi
done