1 #!/bin/bash 2 # Copyright 2010 Google Inc. 3 # All right reserved. 4 # Author: Szymon Jakubczak <szym (at] 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 28 ADB="${ADB:-adb} ${SERIAL:+-s $SERIAL}" 29 30 set -e 31 trap error ERR 32 33 error() { 34 echo >&2 "Error occured: $?" 35 } 36 37 usage() { 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 ################################## 82 rndis_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 95 rndis_stop() { 96 $ADB shell "svc usb setFunction" #empty to clear 97 } 98 99 rndis_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 108 update_dns() { 109 $ADB shell 'setprop net.dnschange $((`getprop net.dnschange`+1))' 110 } 111 112 default_routes() { 113 $ADB shell 'cat /proc/net/route' | awk '{ if ($2==00000000) print $1 }' 114 } 115 116 route_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 } 124 route_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 } 133 route_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 } 146 route_reset() { 147 route_none 148 $ADB shell "svc data enable" 149 } 150 151 ################################# 152 ### HOST configuration routines 153 ################################# 154 nat_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 } 163 nat_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 } 170 nat_stop() { 171 sudo sysctl -w net.ipv4.ip_forward=0 172 sudo iptables -F 173 sudo iptables -t nat -F 174 } 175 176 bridge_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 } 188 bridge_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 } 194 bridge_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 201 if [ $# == "0" ]; then 202 usage 203 fi 204 205 while (( $# )); do 206 case $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 222 rndis) 223 rndis_start 224 rndis_test 225 ;; 226 227 bridge) 228 ifconfig $HOST_DEV >/dev/null || $0 rndis 229 bridge_start 230 bridge_add 231 route_bridge 232 ;; 233 234 nat) 235 ifconfig $HOST_DEV >/dev/null || $0 rndis 236 nat_start 237 route_nat 238 ;; 239 240 nat+secure) 241 $0 nat 242 nat_secure 243 ;; 244 245 stop) 246 route_reset 247 ;; 248 249 stop-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 ;; 259 esac 260 shift 261 done 262