import subprocess
import sys
+from telemetry.core import util
from telemetry.core.backends import adb_commands
"""Forwards traffic using RNDIS. Assuming the device has root access.
"""
_RNDIS_DEVICE = '/sys/class/android_usb/android0'
+ _NETWORK_INTERFACES = '/etc/network/interfaces'
+ _TELEMETRY_MARKER = '# Added by Telemetry #'
def __init__(self, adb):
"""Args:
adb: an instance of AdbCommands
"""
is_root_enabled = adb.Adb().EnableAdbRoot()
- assert is_root_enabled, 'RNDIS forwarding could not enable root'
+ assert is_root_enabled, 'RNDIS forwarding requires a rooted device'
self._adb = adb.Adb()
self._host_port = 80
def OverrideDns(self):
"""Overrides DNS on device to point at the host."""
self._original_dns = self._GetCurrentDns()
+ if not self._original_dns[0]:
+ # No default route. Install one via the host. This is needed because
+ # getaddrinfo in bionic uses routes to determine AI_ADDRCONFIG.
+ self._adb.RunShellCommand('route add default gw %s dev %s' %
+ (self._host_ip, self._device_iface))
self._OverrideDns(self._device_iface, self._host_ip, self._host_ip)
def _IsRndisSupported(self):
elif ether_address in line:
return interface_name
+ def _WriteProtectedFile(self, path, contents):
+ subprocess.check_call(
+ ['sudo', 'bash', '-c', 'echo -e "%s" > %s' % (contents, path)])
+
def _DisableRndis(self):
- self._adb.RunShellCommand('setprop sys.usb.config adb')
+ self._adb.system_properties['sys.usb.config'] = 'adb'
self._WaitForDevice()
def _EnableRndis(self):
if candidate not in used_addresses:
return candidate
- addresses, host_address = self._GetHostAddresses(host_iface)
+ interfaces = open(self._NETWORK_INTERFACES, 'r').read()
+ if 'auto ' + host_iface not in interfaces:
+ config = ('%(orig)s\n\n'
+ '%(marker)s\n'
+ 'auto %(iface)s\n'
+ 'iface %(iface)s inet static\n'
+ ' address 192.168.123.1\n' # Arbitrary IP.
+ ' netmask 255.255.255.0' % {'orig': interfaces,
+ 'marker': self._TELEMETRY_MARKER,
+ 'iface': host_iface})
+ self._WriteProtectedFile(self._NETWORK_INTERFACES, config)
+ subprocess.check_call(['sudo', '/etc/init.d/networking', 'restart'])
+
+ def HasHostAddress():
+ _, host_address = self._GetHostAddresses(host_iface)
+ return bool(host_address)
+ logging.info('Waiting for RNDIS connectivity...')
+ util.WaitFor(HasHostAddress, 10)
- assert host_address, ('Interface %(iface)s was not configured.\n'
- 'To configure it automatically, add to /etc/network/interfaces:\n'
- 'auto %(iface)s\n'
- 'iface %(iface)s inet static\n'
- ' address 192.168.<unique>.1\n'
- ' netmask 255.255.255.0' % {'iface': host_iface})
+ addresses, host_address = self._GetHostAddresses(host_iface)
+ assert host_address, 'Interface %s could not be configured.' % host_iface
addresses = [_IpPrefix2AddressMask(addr) for addr in addresses]
host_ip, netmask = _IpPrefix2AddressMask(host_address)
default_routes = [route[0] for route in routes if route[1] == '00000000']
return (
default_routes[0] if default_routes else None,
- self._adb.RunShellCommand('getprop net.dns1')[0],
- self._adb.RunShellCommand('getprop net.dns2')[0],
+ self._adb.system_properties['net.dns1'],
+ self._adb.system_properties['net.dns2'],
)
def _OverrideDns(self, iface, dns1, dns2):
return # If there is no route, then nobody cares about DNS.
# DNS proxy in older versions of Android is configured via properties.
# TODO(szym): run via su -c if necessary.
- self._adb.RunShellCommand('setprop net.dns1 ' + dns1)
- self._adb.RunShellCommand('setprop net.dns2 ' + dns2)
- dnschange = self._adb.RunShellCommand('getprop net.dnschange')[0]
+ self._adb.system_properties['net.dns1'] = dns1
+ self._adb.system_properties['net.dns2'] = dns2
+ dnschange = self._adb.system_properties['net.dnschange']
if dnschange:
- self._adb.RunShellCommand('setprop net.dnschange %s' %
- (int(dnschange) + 1))
+ self._adb.system_properties['net.dnschange'] = int(dnschange) + 1
# Since commit 8b47b3601f82f299bb8c135af0639b72b67230e6 to frameworks/base
# the net.dns1 properties have been replaced with explicit commands for netd
self._adb.RunShellCommand('ndc netd resolver setifdns %s %s %s' %
def Close(self):
self._OverrideDns(*self._original_dns)
+ self._DisableRndis()