Robert Greenwalt | 9089c7d | 2012-04-27 10:45:07 -0700 | [diff] [blame] | 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 |
| 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 |