Home | History | Annotate | Download | only in scripts
      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