| #!/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 |
| |
| TMP_DIR="/tmp/conman" |
| CONFIG_DIR="/config/conman" |
| |
| mkdir -p $TMP_DIR |
| mkdir -p $CONFIG_DIR |
| |
| iplog() { |
| echo "running: ip" "$@" >&2 |
| ip "$@" |
| } |
| |
| # extension is either "interface_suffix.band" or just "band" |
| stopap() { |
| local extension="$1" |
| |
| bands="2.4 5" |
| for band in $bands; do |
| if [ "$extension" = "$band" ]; then |
| break |
| else |
| if endswith "$extension" "$band"; then |
| interface_suffix=${extension%.$band} |
| break |
| else |
| interface_suffix= |
| band= |
| fi |
| fi |
| done |
| if [ -z "$band" ]; then |
| echo "Failed to parse extension '$extension'" |
| return |
| fi |
| 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 '$extension'" |
| 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}.} |
| # 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 |
| |
| command= |
| access_point= |
| # This assumes command files in /tmp (for provisioning networks) will have an |
| # interface suffix, and those in /config (the user's WLAN) will not. Or, more |
| # generally, that for any given filename, files of that filename can only |
| # appear in one of ($TMP_DIR, $CONFIG_DIR). |
| if [ -e "$CONFIG_DIR/$filename" ]; then |
| which_dir="$CONFIG_DIR" |
| else |
| which_dir="$TMP_DIR" |
| fi |
| |
| if startswith "$filename" "command."; then |
| extension=${filename#command.} |
| command="$which_dir/$filename" |
| access_point="$which_dir/access_point.$extension" |
| else |
| if startswith "$filename" "access_point."; then |
| extension=${filename#access_point.} |
| command="$which_dir/command.$extension" |
| access_point="$which_dir/$filename" |
| fi |
| 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 "$extension" |
| fi |
| done |