1*9c5db199SXin Li#!/bin/bash 2*9c5db199SXin Li# 3*9c5db199SXin Li# Copyright 2016 The Android Open Source Project 4*9c5db199SXin Li# 5*9c5db199SXin Li# Licensed under the Apache License, Version 2.0 (the "License"); 6*9c5db199SXin Li# you may not use this file except in compliance with the License. 7*9c5db199SXin Li# You may obtain a copy of the License at 8*9c5db199SXin Li# 9*9c5db199SXin Li# http://www.apache.org/licenses/LICENSE-2.0 10*9c5db199SXin Li# 11*9c5db199SXin Li# Unless required by applicable law or agreed to in writing, software 12*9c5db199SXin Li# distributed under the License is distributed on an "AS IS" BASIS, 13*9c5db199SXin Li# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14*9c5db199SXin Li# See the License for the specific language governing permissions and 15*9c5db199SXin Li# limitations under the License. 16*9c5db199SXin Li# 17*9c5db199SXin Li 18*9c5db199SXin Liset -euo pipefail 19*9c5db199SXin Li 20*9c5db199SXin Lifunction set_route { 21*9c5db199SXin Li local mode="${1}" 22*9c5db199SXin Li local ip="${2}" 23*9c5db199SXin Li local host="${3}" 24*9c5db199SXin Li local gw="${4}" 25*9c5db199SXin Li 26*9c5db199SXin Li if [ "${mode}" = "ethernet" ]; then 27*9c5db199SXin Li ${ip} route del "${host}" via "${gw}" 28*9c5db199SXin Li else 29*9c5db199SXin Li # FIXME: This *should* work for IPv6, but it returns EINVAL. 30*9c5db199SXin Li ${ip} route add "${host}" via "${gw}" 31*9c5db199SXin Li dbus-send --system --dest=org.chromium.flimflam --print-reply / \ 32*9c5db199SXin Li org.chromium.flimflam.Manager.SetServiceOrder \ 33*9c5db199SXin Li string:"vpn,wifi,ethernet,cellular" 34*9c5db199SXin Li fi 35*9c5db199SXin Li} 36*9c5db199SXin Li 37*9c5db199SXin Lifunction find_route { 38*9c5db199SXin Li local mode="${1}" 39*9c5db199SXin Li local host="${2}" 40*9c5db199SXin Li local ip="ip -4" 41*9c5db199SXin Li 42*9c5db199SXin Li if [[ "${host}" = *:* ]]; then 43*9c5db199SXin Li ip="ip -6" 44*9c5db199SXin Li fi 45*9c5db199SXin Li 46*9c5db199SXin Li set_route "${mode}" "${ip}" "${host}" 192.168.231.254 47*9c5db199SXin Li exit 0 48*9c5db199SXin Li} 49*9c5db199SXin Li 50*9c5db199SXin Lifunction parse_netstat { 51*9c5db199SXin Li local mode="${1}" 52*9c5db199SXin Li 53*9c5db199SXin Li while read -r proto recv_q send_q local foreign state; do 54*9c5db199SXin Li if [[ "${proto}" = tcp* && \ 55*9c5db199SXin Li ("${local}" = *:22 || "${local}" = *:2222) && \ 56*9c5db199SXin Li "${state}" == ESTABLISHED ]]; then 57*9c5db199SXin Li find_route "${mode}" "${foreign%:*}" 58*9c5db199SXin Li exit 0 59*9c5db199SXin Li fi 60*9c5db199SXin Li done 61*9c5db199SXin Li 62*9c5db199SXin Li echo "Could not find ssh connection in netstat" 63*9c5db199SXin Li exit 1 64*9c5db199SXin Li} 65*9c5db199SXin Li 66*9c5db199SXin Limode="${1:-}" 67*9c5db199SXin Liif [ "${mode}" != "wifi" -a "${mode}" != "ethernet" ]; then 68*9c5db199SXin Li echo "Tells shill to prioritize ethernet or wifi, and adds a route" 69*9c5db199SXin Li echo "back to the ssh/adb host so that the device can still be controlled" 70*9c5db199SXin Li echo "remotely." 71*9c5db199SXin Li echo "" 72*9c5db199SXin Li echo "usage: ${0} { ethernet | wifi }" 73*9c5db199SXin Li exit 1 74*9c5db199SXin Lifi 75*9c5db199SXin Li 76*9c5db199SXin Liif [ "${mode}" = "ethernet" ]; then 77*9c5db199SXin Li # Switch the service order first, because the IP lookup might fail. 78*9c5db199SXin Li dbus-send --system --dest=org.chromium.flimflam --print-reply / \ 79*9c5db199SXin Li org.chromium.flimflam.Manager.SetServiceOrder \ 80*9c5db199SXin Li string:"vpn,ethernet,wifi,cellular" 81*9c5db199SXin Lifi 82*9c5db199SXin Li 83*9c5db199SXin Li# Find the first connection to our local port 22 (ssh), then use it to 84*9c5db199SXin Li# set a static route via eth0. 85*9c5db199SXin Li# This should ideally use $SSH_CLIENT instead, but that will require enabling 86*9c5db199SXin Li# transparent mode in sslh because $SSH_CLIENT currently points to 87*9c5db199SXin Li# 127.0.0.1. 88*9c5db199SXin Linetstat --tcp --numeric --wide | parse_netstat "${mode}" 89*9c5db199SXin Liexit 0 90*9c5db199SXin Li 91