1#!/bin/bash 2# Copyright 2010 Google Inc. 3# All right reserved. 4# Author: Szymon Jakubczak <szym@google.com> 5# 6# Configure the host and the Android phone for "reverse tethering". 7# (Route all network traffic via the host.) 8 9# default values 10: ${BRIDGE:=usbeth} 11: ${LAN_DEV:=eth0} # LAN uplink on the host 12: ${HOST_DEV:=usb0} # name of the RNDIS interface on the host 13: ${PHONE_DEV:=rndis0} # name of the RNDIS interface on the phone 14 15: ${PHONE_IP:=192.168.77.2} # for NAT and tests 16: ${HOST_IP:=192.168.77.1} 17: ${NETMASK:=255.255.255.0} 18 19# location of the hwaddr utility 20: ${HWADDR:=/home/build/nonconf/google3/experimental/users/szym/moblat/hwaddr/hwaddr-armeabi} 21: ${PHONE_HW:=""} # hardware (Ethernet) address for the interface (bridge only) 22 23# for NAT configuration 24: ${DNS1:=8.8.8.8} 25: ${DNS2:=8.8.4.4} 26 27# export ADB=/path/to/sdk/adb for custom adb 28ADB="${ADB:-adb} ${SERIAL:+-s $SERIAL}" 29 30set -e 31trap error ERR 32 33error() { 34 echo >&2 "Error occured: $?" 35} 36 37usage() { 38 echo "Usage: $0 <command>" 39 echo " rndis -- start RNDIS and test ping the phone" 40 echo " nat -- use host as NAT" 41 echo " nat+secure -- nat + extra security" 42 echo " bridge -- use host as bridge" 43 echo " stop -- switch back to 3G" 44 echo " stop-all -- clean up everything" 45 echo 46 echo "Advanced Commands" 47 echo " Host:" 48 echo " nat_start " 49 echo " nat_secure " 50 echo " nat_stop " 51 echo " bridge_start " 52 echo " bridge_add " 53 echo " bridge_stop " 54 echo " Phone:" 55 echo " rndis_start " 56 echo " rndis_stop " 57 echo " rndis_test " 58 echo " route_nat " 59 echo " route_bridge " 60 echo " route_reset " 61 echo 62 echo "Options and Environment Variables:" 63 echo " -h|--help" 64 echo " -b bridge_name BRIDGE=$BRIDGE" 65 echo " -s serial_number SERIAL=$SERIAL" 66 echo " -u host_usb_device HOST_DEV=$HOST_DEV" 67 echo " -l host_lan_device LAN_DEV=$LAN_DEV" 68 echo " -d dns1 dns2 DNS1=$DNS1" 69 echo " DNS2=$DNS2" 70 echo " -p phone_ip PHONE_IP=$PHONE_IP" 71 echo " -a host_ip HOST_IP=$HOST_IP" 72 echo " -m netmask NETMASK=$NETMASK" 73 echo " -e hardware_addr PHONE_HW=$PHONE_HW" 74 echo 75 echo " HWADDR=$HWADDR" 76 echo " ADB=$ADB" 77} 78 79################################## 80### PHONE configuration routines 81################################## 82rndis_start() { 83 echo "Starting RNDIS..." 84 $ADB wait-for-device 85 $ADB shell "svc usb setFunction rndis" 86 $ADB wait-for-device 87 $ADB shell "ifconfig $PHONE_DEV down" 88 if [[ -n "$PHONE_HW" ]]; then 89 $ADB push $HWADDR /data/local/hwaddr # TODO(szym) handle failures? 90 $ADB shell "/data/local/hwaddr $PHONE_DEV $PHONE_HW" 91 $ADB shell "/data/local/hwaddr $PHONE_DEV" 92 fi 93} 94 95rndis_stop() { 96 $ADB shell "svc usb setFunction" #empty to clear 97} 98 99rndis_test() { 100 # configure some IPs, so that we can ping 101 $ADB shell "ifconfig $PHONE_DEV $PHONE_IP netmask $NETMASK up" 102 sudo ifconfig $HOST_DEV $HOST_IP netmask $NETMASK up 103 echo "Pinging the phone..." 104 ping -q -c 1 -W 1 $PHONE_IP 105 echo "Success!" 106} 107 108update_dns() { 109 $ADB shell 'setprop net.dnschange $((`getprop net.dnschange`+1))' 110} 111 112default_routes() { 113 $ADB shell 'cat /proc/net/route' | awk '{ if ($2==00000000) print $1 }' 114} 115 116route_none() { 117 $ADB shell "svc data disable" 118 $ADB shell "svc wifi disable" 119 # kill all default route interfaces (just in case something remains) 120 for dev in `default_routes`; do 121 $ADB shell "ifconfig $dev down" 122 done 123} 124route_nat() { 125 echo "Setting up phone routes and DNS..." 126 route_none 127 $ADB shell "ifconfig $PHONE_DEV $PHONE_IP netmask $NETMASK up" 128 $ADB shell "route add default gw $HOST_IP dev $PHONE_DEV" 129 $ADB shell "setprop net.dns1 $DNS1" 130 $ADB shell "setprop net.dns2 $DNS2" 131 update_dns 132} 133route_bridge() { 134 echo "Running DHCP on the phone..." 135 route_none 136 $ADB shell "ifconfig $PHONE_DEV up" 137 $ADB shell "netcfg $PHONE_DEV dhcp" 138 $ADB shell "ifconfig $PHONE_DEV" # for diagnostics 139 140 DNS1=`$ADB shell getprop net.${PHONE_DEV}.dns1` 141 $ADB shell "setprop net.dns1 $DNS1" 142 DNS2=`$ADB shell getprop net.${PHONE_DEV}.dns2` 143 $ADB shell "setprop net.dns2 $DNS2" 144 update_dns 145} 146route_reset() { 147 route_none 148 $ADB shell "svc data enable" 149} 150 151################################# 152### HOST configuration routines 153################################# 154nat_start() { 155 echo "Configuring NAT..." 156 sudo sysctl -w net.ipv4.ip_forward=1 157 sudo iptables -F 158 sudo iptables -t nat -F 159 sudo iptables -t nat -A POSTROUTING -o $LAN_DEV -j MASQUERADE 160 sudo iptables -P FORWARD ACCEPT 161 sudo ifconfig $HOST_DEV $HOST_IP netmask $NETMASK up 162} 163nat_secure() { 164 echo "Making your NAT secure..." 165 sudo iptables -A FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT 166 sudo iptables -A FORWARD -m state --state NEW -i $HOST_DEV -j ACCEPT 167 sudo iptables -P FORWARD DROP 168 sudo ifconfig usb0 $HOST_IP netmask $NETMASK up 169} 170nat_stop() { 171 sudo sysctl -w net.ipv4.ip_forward=0 172 sudo iptables -F 173 sudo iptables -t nat -F 174} 175 176bridge_start() { 177 echo "Configuring bridge..." 178 sudo brctl addbr $BRIDGE || return 0 # all good 179 sudo brctl setfd $BRIDGE 0 180 sudo ifconfig $LAN_DEV 0.0.0.0 181 sudo brctl addif $BRIDGE $LAN_DEV 182 sudo dhclient $BRIDGE || { 183 echo "DHCP failed. Recovering..." 184 bridge_stop 185 false 186 } 187} 188bridge_add() { 189 echo "Adding usb0 to the bridge" 190 sudo brctl delif $BRIDGE $HOST_DEV 2>/dev/null || true # ignore 191 sudo ifconfig $HOST_DEV 0.0.0.0 192 sudo brctl addif $BRIDGE $HOST_DEV 193} 194bridge_stop() { 195 sudo ifconfig $BRIDGE down || true # ignore errors 196 sudo brctl delbr $BRIDGE || true 197 sudo dhclient $LAN_DEV 198} 199 200### command-line interpreter 201if [ $# == "0" ]; then 202 usage 203fi 204 205while (( $# )); do 206case $1 in 207--help|-h) 208 usage 209 exit 210 ;; 211 212-b) shift; BRIDGE=$1 ;; 213-s) shift; SERIAL=$1 ;; 214-u) shift; HOST_DEV=$1 ;; 215-l) shift; LAN_DEV=$1 ;; 216-d) shift; DNS1=$1; shift; DNS2=$1 ;; 217-p) shift; PHONE_IP=$1 ;; 218-a) shift; HOST_IP=$1 ;; 219-m) shift; NETMASK=$1 ;; 220-e) shift; PHONE_HW=$1 ;; 221 222rndis) 223 rndis_start 224 rndis_test 225 ;; 226 227bridge) 228 ifconfig $HOST_DEV >/dev/null || $0 rndis 229 bridge_start 230 bridge_add 231 route_bridge 232 ;; 233 234nat) 235 ifconfig $HOST_DEV >/dev/null || $0 rndis 236 nat_start 237 route_nat 238 ;; 239 240nat+secure) 241 $0 nat 242 nat_secure 243 ;; 244 245stop) 246 route_reset 247 ;; 248 249stop-all) 250 bridge_stop 251 nat_stop 252 route_reset 253 rndis_stop 254 ;; 255 256*) # execute 'advanced command' by function name 257 $1 258 ;; 259esac 260shift 261done 262