[Networking] cmrcx:
Hello everybody,

I have seen some scripts for USB reverse tethering, which all did not work very well for me, so I wrote my own. The script keeps running while the tethering connection is established. When the tethering connection gets disconnected, the script sets the network configuration back to the normal mobile network and finishes. The mobile network just stays connected while tethering, so all applications still think we're connected and make no problems.

I use Script Manager Pro 2.8.8 and SMWidgets to run the script. The widget shows "Running" and a notification while the script runs. Additionally toast messages are displayed when the connection is established or disconnected. You can also use the free Script Manager without the widget. In the current Script Manager Pro 2.9.3 unfortunately the notification and the toast messages are broken, but you can also use it without the widget.

Sometimes the script disconnects, because the default route has changed. I don't know why, maybe the phone somehow thinks that the route is not correct for the mobile network and corrects it. But then I just reconnect.

I use the script on a Fairphone (Android 4.2.2) connecting to a Mac (OS X 10.9.2) with HoRNDIS and enabled internet sharing.

#!/system/bin/sh
# reverse_tether.sh
# run as root

# show executed commands
set -x

# configuration
# tethering network interface
DEV=rndis0
# ip address and netmask for this android phone
PHONE=192.168.2.2/24
# ip address of the host
HOST=192.168.2.1
# nameserver on the host
DNS1=$HOST
# Googles public nameserver as fallback
DNS2=8.8.8.8
# host to ping to test internet connection
PING=google.com

# check for any already active tethering
if [ "$( netcfg | grep 192.168.2. )" ]
then
echo showToastLong "Some tethering seems to be already active" >&$SM_GUIFD
exit 1
fi

# activate rndis
PREV_USB_CONFIG="$( getprop sys.usb.config )"
setprop sys.usb.config rndis
until [ "$( getprop sys.usb.state )" = rndis ]
do
sleep 1
done

# activate tethering network link
ip rule add from all lookup main
ip addr flush dev $DEV || exit 1
ip addr add $PHONE dev $DEV
ip link set $DEV up
netcfg

# check if usb cable is plugged in and host reachable
if ping -q -c 1 -w 3 -s 0 $HOST
then

# set new default route
route add default gw $HOST dev $DEV
ip route show

# save dns config for later restore
PREV_DNS1=$( getprop net.dns1 )
PREV_DNS2=$( getprop net.dns2 )
setprop net.dns1 $DNS1
setprop net.dns2 $DNS2
setprop net.dnschange $((`getprop net.dnschange`+1))

# test internet access
ping -q -c 1 -w 3 $PING \
&& echo showToastLong "Tethering connected, Internet ping OK" >&$SM_GUIFD \
|| echo showToastLong "Tethering connected, but Internet ping FAILED" >&$SM_GUIFD

# wait until cable gets unplugged or network config gets changed
while true
do
date
if ! ping -q -c 1 -w 3 -s 0 $HOST
then
echo showToastLong "Ping to tethering host failed, turning off tethering ..." >&$SM_GUIFD
break
fi
if [[ "$( ip route show )" != "default via $HOST dev $DEV"* ]]
then
echo showToastLong "Default route changed, turning off tethering ..." >&$SM_GUIFD
ip route show
break
fi
sleep 5
done

# restore previous dns config if it has not been changed manually in between
if [ $( getprop net.dns1 ) = $DNS1 -a $( getprop net.dns2 ) = $DNS2 ]
then
setprop net.dns1 $PREV_DNS1
setprop net.dns2 $PREV_DNS2
setprop net.dnschange $((`getprop net.dnschange`+1))
fi

fi

# deactivate tethering network link and route
ip link set $DEV down
ip addr flush dev $DEV
ip rule del from all lookup main

# restore previous usb config because otherwise the device will not be available next time
if [ "$( getprop sys.usb.state )" = rndis ]
then
setprop sys.usb.config "$PREV_USB_CONFIG"
until [ "$( getprop sys.usb.state )" = "$PREV_USB_CONFIG" ]
do
sleep 1
done
fi

# show restored state
netcfg
ip route show
getprop net.dns1
getprop net.dns2

ping -q -c 1 -w 3 $PING \
&& echo showToastLong "Mobile data restored, Internet ping OK" >&$SM_GUIFD \
|| echo showToastLong "Mobile data restored, but Internet ping FAILED" >&$SM_GUIFD

echo finished