# Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

import collections
import copy
import logging
import os
import random
import string
import tempfile
import time

from autotest_lib.client.common_lib import error
from autotest_lib.client.common_lib import utils
from autotest_lib.client.common_lib.cros import path_utils
from autotest_lib.client.common_lib.cros.network import interface
from autotest_lib.client.common_lib.cros.network import netblock
from autotest_lib.client.common_lib.cros.network import ping_runner
from autotest_lib.server import hosts
from autotest_lib.server import site_linux_system
from autotest_lib.server.cros import dnsname_mangler


StationInstance = collections.namedtuple('StationInstance',
                                         ['ssid', 'interface', 'dev_type'])
HostapdInstance = collections.namedtuple('HostapdInstance',
                                         ['ssid', 'conf_file', 'log_file',
                                          'interface', 'config_dict',
                                          'stderr_log_file',
                                          'scenario_name'])

# Send magic packets here, so they can wake up the system but are otherwise
# dropped.
UDP_DISCARD_PORT = 9

def build_router_hostname(client_hostname=None, router_hostname=None):
    """Build a router hostname from a client hostname.

    @param client_hostname: string hostname of DUT connected to a router.
    @param router_hostname: string hostname of router.
    @return string hostname of connected router or None if the hostname
            cannot be inferred from the client hostname.

    """
    if not router_hostname and not client_hostname:
        raise error.TestError('Either client_hostname or router_hostname must '
                              'be specified to build_router_hostname.')

    return dnsname_mangler.get_router_addr(client_hostname,
                                           cmdline_override=router_hostname)


def build_router_proxy(test_name='', client_hostname=None, router_addr=None,
                       enable_avahi=False):
    """Build up a LinuxRouter object.

    Verifies that the remote host responds to ping.
    Either client_hostname or router_addr must be specified.

    @param test_name: string name of this test (e.g. 'network_WiFi_TestName').
    @param client_hostname: string hostname of DUT if we're in the lab.
    @param router_addr: string DNS/IPv4 address to use for router host object.
    @param enable_avahi: boolean True iff avahi should be started on the router.

    @return LinuxRouter or raise error.TestError on failure.

    """
    router_hostname = build_router_hostname(client_hostname=client_hostname,
                                            router_hostname=router_addr)
    logging.info('Connecting to router at %s', router_hostname)
    ping_helper = ping_runner.PingRunner()
    if not ping_helper.simple_ping(router_hostname):
        raise error.TestError('Router at %s is not pingable.' %
                              router_hostname)

    # Use CrosHost for all router hosts and avoid host detection.
    # Host detection would use JetstreamHost for Whirlwind routers.
    # JetstreamHost assumes ap-daemons are running.
    # Testbed routers run the testbed-ap profile with no ap-daemons.
    # TODO(ecgh): crbug.com/757075 Fix testbed-ap JetstreamHost detection.
    return LinuxRouter(hosts.create_host(router_hostname,
                                         host_class=hosts.CrosHost),
                       test_name,
                       enable_avahi=enable_avahi)


class LinuxRouter(site_linux_system.LinuxSystem):
    """Linux/mac80211-style WiFi Router support for WiFiTest class.

    This class implements test methods/steps that communicate with a
    router implemented with Linux/mac80211.  The router must
    be pre-configured to enable ssh access and have a mac80211-based
    wireless device.  We also assume hostapd 0.7.x and iw are present
    and any necessary modules are pre-loaded.

    """

    KNOWN_TEST_PREFIX = 'network_WiFi_'
    POLLING_INTERVAL_SECONDS = 0.5
    STARTUP_TIMEOUT_SECONDS = 30
    SUFFIX_LETTERS = string.ascii_lowercase + string.digits
    SUBNET_PREFIX_OCTETS = (192, 168)

    HOSTAPD_CONF_FILE_PATTERN = 'hostapd-test-%s.conf'
    HOSTAPD_LOG_FILE_PATTERN = 'hostapd-test-%s.log'
    HOSTAPD_STDERR_LOG_FILE_PATTERN = 'hostapd-stderr-test-%s.log'
    HOSTAPD_CONTROL_INTERFACE_PATTERN = 'hostapd-test-%s.ctrl'
    HOSTAPD_DRIVER_NAME = 'nl80211'

    MGMT_FRAME_SENDER_LOG_FILE = 'send_management_frame-test.log'

    PROBE_RESPONSE_FOOTER_FILE = '/tmp/autotest-probe_response_footer'

    _RNG_AVAILABLE = '/sys/class/misc/hw_random/rng_available'
    _RNG_CURRENT = '/sys/class/misc/hw_random/rng_current'

    def get_capabilities(self):
        """@return iterable object of AP capabilities for this system."""
        caps = set()
        try:
            self.cmd_send_management_frame = path_utils.must_be_installed(
                    '/usr/bin/send_management_frame', host=self.host)
            caps.add(self.CAPABILITY_SEND_MANAGEMENT_FRAME)
        except error.TestFail:
            pass
        return super(LinuxRouter, self).get_capabilities().union(caps)


    @property
    def router(self):
        """Deprecated.  Use self.host instead.

        @return Host object representing the remote router.

        """
        return self.host


    @property
    def wifi_ip(self):
        """Simple accessor for the WiFi IP when there is only one AP.

        @return string IP of WiFi interface.

        """
        if len(self.local_servers) != 1:
            raise error.TestError('Could not pick a WiFi IP to return.')

        return self.get_wifi_ip(0)


    def __init__(self, host, test_name, enable_avahi=False):
        """Build a LinuxRouter.

        @param host Host object representing the remote machine.
        @param test_name string name of this test.  Used in SSID creation.
        @param enable_avahi: boolean True iff avahi should be started on the
                router.

        """
        super(LinuxRouter, self).__init__(host, 'router')
        self._ssid_prefix = test_name
        self._enable_avahi = enable_avahi
        self.__setup()


    def __setup(self):
        """Set up this system.

        Can be used either to complete initialization of a LinuxRouter
        object, or to re-establish a good state after a reboot.

        """
        self.cmd_dhcpd = '/usr/sbin/dhcpd'
        self.cmd_hostapd = path_utils.must_be_installed(
                '/usr/sbin/hostapd', host=self.host)
        self.cmd_hostapd_cli = path_utils.must_be_installed(
                '/usr/sbin/hostapd_cli', host=self.host)
        self.cmd_wpa_supplicant = path_utils.must_be_installed(
                '/usr/sbin/wpa_supplicant', host=self.host)
        self.dhcpd_conf = os.path.join(self.logdir, 'dhcpd.%s.conf')
        self.dhcpd_leases = os.path.join(self.logdir, 'dhcpd.leases')

        # Log the most recent message on the router so that we can rebuild the
        # suffix relevant to us when debugging failures.
        last_log_line = self.host.run('tail -1 /var/log/messages',
                                      ignore_status=True).stdout
        # We're trying to get the timestamp from:
        # 2014-07-23T17:29:34.961056+00:00 localhost kernel: blah blah blah
        self._log_start_timestamp = last_log_line.strip().partition(' ')[0]
        if self._log_start_timestamp:
            logging.debug('Will only retrieve logs after %s.',
                          self._log_start_timestamp)
        else:
            # If syslog is empty, we just use a wildcard pattern, to grab
            # everything.
            logging.debug('Empty or corrupt log; will retrieve whole log')
            self._log_start_timestamp = '.'

        # hostapd configuration persists throughout the test, subsequent
        # 'config' commands only modify it.
        if self._ssid_prefix.startswith(self.KNOWN_TEST_PREFIX):
            # Many of our tests start with an uninteresting prefix.
            # Remove it so we can have more unique bytes.
            self._ssid_prefix = self._ssid_prefix[len(self.KNOWN_TEST_PREFIX):]
        self._number_unique_ssids = 0

        self._total_hostapd_instances = 0
        self.local_servers = []
        self.server_address_index = []
        self.hostapd_instances = []
        self.station_instances = []
        self.dhcp_low = 1
        self.dhcp_high = 128

        # Tear down hostapbr bridge and intermediate functional block
        # interfaces.
        result = self.host.run('ls -d /sys/class/net/%s* /sys/class/net/%s*'
                               ' 2>/dev/null' %
                               (self.HOSTAP_BRIDGE_INTERFACE_PREFIX,
                                self.IFB_INTERFACE_PREFIX),
                               ignore_status=True)
        for path in result.stdout.splitlines():
            self.delete_link(path.split('/')[-1])

        # Kill hostapd and dhcp server if already running.
        self._kill_process_instance('hostapd', timeout_seconds=30)
        self.stop_dhcp_server(instance=None)

        # Place us in the US by default
        self.iw_runner.set_regulatory_domain('US')

        self.enable_all_antennas()

        # Some tests want this functionality, but otherwise, it's a distraction.
        if self._enable_avahi:
            self.host.run('start avahi', ignore_status=True)
        else:
            self.host.run('stop avahi', ignore_status=True)

        # Some routers have bad (slow?) random number generators.
        self.rng_configure()


    def close(self):
        """Close global resources held by this system."""
        router_log = os.path.join(self.logdir, 'router_log')
        self.deconfig()
        # dnsmasq and hostapd cause interesting events to go to system logs.
        # Retrieve only the suffix of the logs after the timestamp we stored on
        # router creation.
        self.host.run("sed -n -e '/%s/,$p' /var/log/messages >%s" %
                      (self._log_start_timestamp, router_log),
                      ignore_status=True)
        self.host.get_file(router_log, 'debug/router_host_messages')
        super(LinuxRouter, self).close()


    def reboot(self, timeout):
        """Reboot this router, and restore it to a known-good state.

        @param timeout Maximum seconds to wait for router to return.

        """
        super(LinuxRouter, self).reboot(timeout)
        self.__setup()


    def has_local_server(self):
        """@return True iff this router has local servers configured."""
        return bool(self.local_servers)


    def start_hostapd(self, configuration):
        """Start a hostapd instance described by conf.

        @param configuration HostapConfig object.

        """
        # Figure out the correct interface.
        interface = self.get_wlanif(configuration.frequency, 'managed',
                                    configuration.min_streams)
        phy_name = self.iw_runner.get_interface(interface).phy

        conf_file = os.path.join(self.logdir,
                self.HOSTAPD_CONF_FILE_PATTERN % interface)
        log_file = os.path.join(self.logdir,
                self.HOSTAPD_LOG_FILE_PATTERN % interface)
        stderr_log_file = os.path.join(self.logdir,
                self.HOSTAPD_STDERR_LOG_FILE_PATTERN % interface)
        control_interface = os.path.join(self.logdir,
                self.HOSTAPD_CONTROL_INTERFACE_PATTERN % interface)
        hostapd_conf_dict = configuration.generate_dict(
                interface, control_interface,
                self.build_unique_ssid(suffix=configuration.ssid_suffix))
        logging.debug('hostapd parameters: %r', hostapd_conf_dict)

        # Generate hostapd.conf.
        self.router.run("cat <<EOF >%s\n%s\nEOF\n" %
            (conf_file, '\n'.join(
            "%s=%s" % kv for kv in hostapd_conf_dict.iteritems())))

        # Run hostapd.
        logging.info('Starting hostapd on %s(%s) channel=%s...',
                     interface, phy_name, configuration.channel)
        self.router.run('rm %s' % log_file, ignore_status=True)
        self.router.run('stop wpasupplicant', ignore_status=True)
        start_command = '%s -dd -t %s > %s 2> %s & echo $!' % (
                self.cmd_hostapd, conf_file, log_file, stderr_log_file)
        pid = int(self.router.run(start_command).stdout.strip())
        self.hostapd_instances.append(HostapdInstance(
                hostapd_conf_dict['ssid'],
                conf_file,
                log_file,
                interface,
                hostapd_conf_dict.copy(),
                stderr_log_file,
                configuration.scenario_name))

        # Wait for confirmation that the router came up.
        logging.info('Waiting for hostapd to startup.')
        utils.poll_for_condition(
                condition=lambda: self._has_hostapd_started(log_file, pid),
                exception=error.TestFail('Timed out while waiting for hostapd '
                                         'to start.'),
                timeout=self.STARTUP_TIMEOUT_SECONDS,
                sleep_interval=self.POLLING_INTERVAL_SECONDS)

        if configuration.frag_threshold:
            threshold = self.iw_runner.get_fragmentation_threshold(phy_name)
            if threshold != configuration.frag_threshold:
                raise error.TestNAError('Router does not support setting '
                                        'fragmentation threshold')


    def _has_hostapd_started(self, log_file, pid):
        """Determines if hostapd has started.

        @return Whether or not hostapd has started.
        @raise error.TestFail if there was a bad config or hostapd terminated.
        """
        success = self.router.run(
            'grep "Setup of interface done" %s' % log_file,
            ignore_status=True).exit_status == 0
        if success:
            return True

        # A common failure is an invalid router configuration.
        # Detect this and exit early if we see it.
        bad_config = self.router.run(
            'grep "Interface initialization failed" %s' % log_file,
            ignore_status=True).exit_status == 0
        if bad_config:
            raise error.TestFail('hostapd failed to initialize AP '
                                 'interface.')

        if pid:
            early_exit = self.router.run('kill -0 %d' % pid,
                                         ignore_status=True).exit_status
            if early_exit:
                raise error.TestFail('hostapd process terminated.')

        return False


    def _kill_process_instance(self,
                               process,
                               instance=None,
                               timeout_seconds=10,
                               ignore_timeouts=False):
        """Kill a process on the router.

        Kills remote program named |process| (optionally only a specific
        |instance|).  Wait |timeout_seconds| for |process| to die
        before returning.  If |ignore_timeouts| is False, raise
        a TestError on timeouts.

        @param process: string name of process to kill.
        @param instance: string fragment of the command line unique to
                this instance of the remote process.
        @param timeout_seconds: float timeout in seconds to wait.
        @param ignore_timeouts: True iff we should ignore failures to
                kill processes.
        @return True iff the specified process has exited.

        """
        if instance is not None:
            search_arg = '-f "^%s.*%s"' % (process, instance)
        else:
            search_arg = process

        self.host.run('pkill %s' % search_arg, ignore_status=True)

        # Wait for process to die
        time.sleep(self.POLLING_INTERVAL_SECONDS)
        try:
            utils.poll_for_condition(
                    condition=lambda: self.host.run(
                            'pgrep -l %s' % search_arg,
                            ignore_status=True).exit_status != 0,
                    timeout=timeout_seconds,
                    sleep_interval=self.POLLING_INTERVAL_SECONDS)
        except utils.TimeoutError:
            if ignore_timeouts:
                return False

            raise error.TestError(
                'Timed out waiting for %s%s to die' %
                (process,
                '' if instance is None else ' (instance=%s)' % instance))
        return True


    def kill_hostapd_instance(self, instance):
        """Kills a hostapd instance.

        @param instance HostapdInstance object.

        """
        is_dead = self._kill_process_instance(
                self.cmd_hostapd,
                instance=instance.conf_file,
                timeout_seconds=30,
                ignore_timeouts=True)
        if instance.scenario_name:
            log_identifier = instance.scenario_name
        else:
            log_identifier = '%d_%s' % (
                self._total_hostapd_instances, instance.interface)
        files_to_copy = [(instance.log_file,
                          'debug/hostapd_router_%s.log' % log_identifier),
                         (instance.stderr_log_file,
                          'debug/hostapd_router_%s.stderr.log' %
                          log_identifier)]
        for remote_file, local_file in files_to_copy:
            if self.host.run('ls %s >/dev/null 2>&1' % remote_file,
                             ignore_status=True).exit_status:
                logging.error('Did not collect hostapd log file because '
                              'it was missing.')
            else:
                self.router.get_file(remote_file, local_file)
        self._total_hostapd_instances += 1
        if not is_dead:
            raise error.TestError('Timed out killing hostapd.')


    def build_unique_ssid(self, suffix=''):
        """ Build our unique token by base-<len(self.SUFFIX_LETTERS)> encoding
        the number of APs we've constructed already.

        @param suffix string to append to SSID

        """
        base = len(self.SUFFIX_LETTERS)
        number = self._number_unique_ssids
        self._number_unique_ssids += 1
        unique = ''
        while number or not unique:
            unique = self.SUFFIX_LETTERS[number % base] + unique
            number = number / base
        # And salt the SSID so that tests running in adjacent cells are unlikely
        # to pick the same SSID and we're resistent to beacons leaking out of
        # cells.
        salt = ''.join([random.choice(self.SUFFIX_LETTERS) for x in range(5)])
        return '_'.join([self._ssid_prefix, unique, salt, suffix])[-32:]


    def rng_configure(self):
        """Configure the random generator to our liking.

        Some routers (particularly, Gale) seem to have bad Random Number
        Generators, such that hostapd can't always generate keys fast enough.
        The on-board TPM seems to serve as a better generator, so we try to
        switch to that if available.

        Symptoms of a slow RNG: hostapd complains with:

          WPA: Not enough entropy in random pool to proceed - reject first
          4-way handshake

        Ref:
        https://chromium.googlesource.com/chromiumos/third_party/hostap/+/7ea51f728bb7/src/ap/wpa_auth.c#1854

        Linux devices may have RNG parameters at
        /sys/class/misc/hw_random/rng_{available,current}. See:

          https://www.kernel.org/doc/Documentation/hw_random.txt

        """

        available = self.host.run('cat %s' % self._RNG_AVAILABLE, \
                                  ignore_status=True).stdout.strip().split(' ')
        # System may not have HWRNG support. Just skip this.
        if available == "":
            return
        current = self.host.run('cat %s' % self._RNG_CURRENT).stdout. \
                                strip()
        want_rng = "tpm-rng"

        logging.debug("Available / current RNGs on router: %r / %s",
                      available, current)
        if want_rng in available and want_rng != current:
            logging.debug("Switching RNGs: %s -> %s", current, want_rng)
            self.host.run('echo -n "%s" > %s' % (want_rng, self._RNG_CURRENT))


    def hostap_configure(self, configuration, multi_interface=None):
        """Build up a hostapd configuration file and start hostapd.

        Also setup a local server if this router supports them.

        @param configuration HosetapConfig object.
        @param multi_interface bool True iff multiple interfaces allowed.

        """
        if multi_interface is None and (self.hostapd_instances or
                                        self.station_instances):
            self.deconfig()
        if configuration.is_11ac:
            router_caps = self.get_capabilities()
            if site_linux_system.LinuxSystem.CAPABILITY_VHT not in router_caps:
                raise error.TestNAError('Router does not have AC support')

        if configuration.use_bridge:
            configuration._bridge = self.get_brif()

        self.start_hostapd(configuration)
        interface = self.hostapd_instances[-1].interface
        self.iw_runner.set_tx_power(interface, 'auto')
        self.start_local_server(interface, bridge=configuration.bridge)
        logging.info('AP configured.')


    def ibss_configure(self, config):
        """Configure a station based AP in IBSS mode.

        Extract relevant configuration objects from |config| despite not
        actually being a hostap managed endpoint.

        @param config HostapConfig object.

        """
        if self.station_instances or self.hostapd_instances:
            self.deconfig()
        interface = self.get_wlanif(config.frequency, 'ibss')
        ssid = (config.ssid or
                self.build_unique_ssid(suffix=config.ssid_suffix))
        # Connect the station
        self.router.run('%s link set %s up' % (self.cmd_ip, interface))
        self.iw_runner.ibss_join(interface, ssid, config.frequency)
        # Always start a local server.
        self.start_local_server(interface)
        # Remember that this interface is up.
        self.station_instances.append(
                StationInstance(ssid=ssid, interface=interface,
                                dev_type='ibss'))


    def local_server_address(self, index):
        """Get the local server address for an interface.

        When we multiple local servers, we give them static IP addresses
        like 192.168.*.254.

        @param index int describing which local server this is for.

        """
        return '%d.%d.%d.%d' % (self.SUBNET_PREFIX_OCTETS + (index, 254))


    def local_peer_ip_address(self, index):
        """Get the IP address allocated for the peer associated to the AP.

        This address is assigned to a locally associated peer device that
        is created for the DUT to perform connectivity tests with.
        When we have multiple local servers, we give them static IP addresses
        like 192.168.*.253.

        @param index int describing which local server this is for.

        """
        return '%d.%d.%d.%d' % (self.SUBNET_PREFIX_OCTETS + (index, 253))

    def local_bridge_address(self, index):
        """Get the bridge address for an interface.

        This address is assigned to a local bridge device.

        @param index int describing which local server this is for.

        """
        return '%d.%d.%d.%d' % (self.SUBNET_PREFIX_OCTETS + (index, 252))

    def local_peer_mac_address(self):
        """Get the MAC address of the peer interface.

        @return string MAC address of the peer interface.

        """
        iface = interface.Interface(self.station_instances[0].interface,
                                    self.router)
        return iface.mac_address


    def _get_unused_server_address_index(self):
        """@return an unused server address index."""
        for address_index in range(0, 256):
            if address_index not in self.server_address_index:
                return address_index
        raise error.TestFail('No available server address index')


    def change_server_address_index(self, ap_num=0, server_address_index=None):
        """Restart the local server with a different server address index.

        This will restart the local server with different gateway IP address
        and DHCP address ranges.

        @param ap_num: int hostapd instance number.
        @param server_address_index: int server address index.

        """
        interface = self.local_servers[ap_num]['interface'];
        # Get an unused server address index if one is not specified, which
        # will be different from the one that's currently in used.
        if server_address_index is None:
            server_address_index = self._get_unused_server_address_index()

        # Restart local server with the new server address index.
        self.stop_local_server(self.local_servers[ap_num])
        self.start_local_server(interface,
                                ap_num=ap_num,
                                server_address_index=server_address_index)


    def start_local_server(self,
                           interface,
                           ap_num=None,
                           server_address_index=None,
                           bridge=None):
        """Start a local server on an interface.

        @param interface string (e.g. wlan0)
        @param ap_num int the ap instance to start the server for
        @param server_address_index int server address index
        @param bridge string (e.g. br0)

        """
        logging.info('Starting up local server...')

        if len(self.local_servers) >= 256:
            raise error.TestFail('Exhausted available local servers')

        # Get an unused server address index if one is not specified.
        # Validate server address index if one is specified.
        if server_address_index is None:
            server_address_index = self._get_unused_server_address_index()
        elif server_address_index in self.server_address_index:
            raise error.TestFail('Server address index %d already in used' %
                                 server_address_index)

        server_addr = netblock.from_addr(
                self.local_server_address(server_address_index),
                prefix_len=24)

        params = {}
        params['address_index'] = server_address_index
        params['netblock'] = server_addr
        params['dhcp_range'] = ' '.join(
            (server_addr.get_addr_in_block(1),
             server_addr.get_addr_in_block(128)))
        params['interface'] = interface
        params['bridge'] = bridge
        params['ip_params'] = ('%s broadcast %s dev %s' %
                               (server_addr.netblock,
                                server_addr.broadcast,
                                interface))
        if ap_num is None:
            self.local_servers.append(params)
        else:
            self.local_servers.insert(ap_num, params)
        self.server_address_index.append(server_address_index)

        self.router.run('%s addr flush %s' %
                        (self.cmd_ip, interface))
        self.router.run('%s addr add %s' %
                        (self.cmd_ip, params['ip_params']))
        self.router.run('%s link set %s up' %
                        (self.cmd_ip, interface))
        if params['bridge']:
            bridge_addr = netblock.from_addr(
                    self.local_bridge_address(server_address_index),
                    prefix_len=24)
            self.router.run("ifconfig %s %s" %
                           (params['bridge'], bridge_addr.netblock))
        self.start_dhcp_server(interface)


    def stop_local_server(self, server):
        """Stop a local server on the router

        @param server object server configuration parameters.

        """
        self.stop_dhcp_server(server['interface'])
        self.router.run("%s addr del %s" %
                        (self.cmd_ip, server['ip_params']),
                        ignore_status=True)
        self.server_address_index.remove(server['address_index'])
        self.local_servers.remove(server)


    def start_dhcp_server(self, interface):
        """Start a dhcp server on an interface.

        @param interface string (e.g. wlan0)

        """
        for server in self.local_servers:
            if server['interface'] == interface:
                params = server
                break
        else:
            raise error.TestFail('Could not find local server '
                                 'to match interface: %r' % interface)
        server_addr = params['netblock']
        dhcpd_conf_file = self.dhcpd_conf % interface
        dhcp_conf = '\n'.join([
            'port=0',  # disables DNS server
            'bind-interfaces',
            'log-dhcp',
            'dhcp-range=%s' % ','.join((server_addr.get_addr_in_block(1),
                                        server_addr.get_addr_in_block(128))),
            'interface=%s' % (params['bridge'] or params['interface']),
            'dhcp-leasefile=%s' % self.dhcpd_leases])
        self.router.run('cat <<EOF >%s\n%s\nEOF\n' %
            (dhcpd_conf_file, dhcp_conf))
        self.router.run('dnsmasq --conf-file=%s' % dhcpd_conf_file)


    def stop_dhcp_server(self, instance=None):
        """Stop a dhcp server on the router.

        @param instance string instance to kill.

        """
        self._kill_process_instance('dnsmasq', instance=instance)


    def get_wifi_channel(self, ap_num):
        """Return channel of BSS corresponding to |ap_num|.

        @param ap_num int which BSS to get the channel of.
        @return int primary channel of BSS.

        """
        instance = self.hostapd_instances[ap_num]
        return instance.config_dict['channel']


    def get_wifi_ip(self, ap_num):
        """Return IP address on the WiFi subnet of a local server on the router.

        If no local servers are configured (e.g. for an RSPro), a TestFail will
        be raised.

        @param ap_num int which local server to get an address from.

        """
        if not self.local_servers:
            raise error.TestError('No IP address assigned')

        return self.local_servers[ap_num]['netblock'].addr


    def get_wifi_ip_subnet(self, ap_num):
        """Return subnet of WiFi AP instance.

        If no APs are configured a TestError will be raised.

        @param ap_num int which local server to get an address from.

        """
        if not self.local_servers:
            raise error.TestError('No APs configured.')

        return self.local_servers[ap_num]['netblock'].subnet


    def get_hostapd_interface(self, ap_num):
        """Get the name of the interface associated with a hostapd instance.

        @param ap_num: int hostapd instance number.
        @return string interface name (e.g. 'managed0').

        """
        if ap_num not in range(len(self.hostapd_instances)):
            raise error.TestFail('Invalid instance number (%d) with %d '
                                 'instances configured.' %
                                 (ap_num, len(self.hostapd_instances)))

        instance = self.hostapd_instances[ap_num]
        return instance.interface


    def get_station_interface(self, instance):
        """Get the name of the interface associated with a station.

        @param instance: int station instance number.
        @return string interface name (e.g. 'managed0').

        """
        if instance not in range(len(self.station_instances)):
            raise error.TestFail('Invalid instance number (%d) with %d '
                                 'instances configured.' %
                                 (instance, len(self.station_instances)))

        instance = self.station_instances[instance]
        return instance.interface


    def get_hostapd_mac(self, ap_num):
        """Return the MAC address of an AP in the test.

        @param ap_num int index of local server to read the MAC address from.
        @return string MAC address like 00:11:22:33:44:55.

        """
        interface_name = self.get_hostapd_interface(ap_num)
        ap_interface = interface.Interface(interface_name, self.host)
        return ap_interface.mac_address


    def get_hostapd_phy(self, ap_num):
        """Get name of phy for hostapd instance.

        @param ap_num int index of hostapd instance.
        @return string phy name of phy corresponding to hostapd's
                managed interface.

        """
        interface = self.iw_runner.get_interface(
                self.get_hostapd_interface(ap_num))
        return interface.phy


    def deconfig(self):
        """A legacy, deprecated alias for deconfig_aps."""
        self.deconfig_aps()


    def deconfig_aps(self, instance=None, silent=False):
        """De-configure an AP (will also bring wlan down).

        @param instance: int or None.  If instance is None, will bring down all
                instances of hostapd.
        @param silent: True if instances should be brought without de-authing
                the DUT.

        """
        if not self.hostapd_instances and not self.station_instances:
            return

        if self.hostapd_instances:
            local_servers = []
            if instance is not None:
                instances = [ self.hostapd_instances.pop(instance) ]
                for server in self.local_servers:
                    if server['interface'] == instances[0].interface:
                        local_servers = [server]
                        break
            else:
                instances = self.hostapd_instances
                self.hostapd_instances = []
                local_servers = copy.copy(self.local_servers)

            for instance in instances:
                if silent:
                    # Deconfigure without notifying DUT.  Remove the interface
                    # hostapd uses to send beacon and DEAUTH packets.
                    self.remove_interface(instance.interface)

                self.kill_hostapd_instance(instance)
                self.release_interface(instance.interface)
        if self.station_instances:
            local_servers = copy.copy(self.local_servers)
            instance = self.station_instances.pop()
            if instance.dev_type == 'ibss':
                self.iw_runner.ibss_leave(instance.interface)
            elif instance.dev_type == 'managed':
                self._kill_process_instance(self.cmd_wpa_supplicant,
                                            instance=instance.interface)
            else:
                self.iw_runner.disconnect_station(instance.interface)
            self.router.run('%s link set %s down' %
                            (self.cmd_ip, instance.interface))

        for server in local_servers:
            self.stop_local_server(server)

        for brif in range(self._brif_index):
            self.delete_link('%s%d' %
                             (self.HOSTAP_BRIDGE_INTERFACE_PREFIX, brif))


    def delete_link(self, name):
        """Delete link using the `ip` command.

        @param name string link name.

        """
        self.host.run('%s link del %s' % (self.cmd_ip, name),
                      ignore_status=True)


    def set_ap_interface_down(self, instance=0):
        """Bring down the hostapd interface.

        @param instance int router instance number.

        """
        self.host.run('%s link set %s down' %
                      (self.cmd_ip, self.get_hostapd_interface(instance)))


    def confirm_pmksa_cache_use(self, instance=0):
        """Verify that the PMKSA auth was cached on a hostapd instance.

        @param instance int router instance number.

        """
        log_file = self.hostapd_instances[instance].log_file
        pmksa_match = 'PMK from PMKSA cache'
        result = self.router.run('grep -q "%s" %s' % (pmksa_match, log_file),
                                 ignore_status=True)
        if result.exit_status:
            raise error.TestFail('PMKSA cache was not used in roaming.')


    def get_ssid(self, instance=None):
        """@return string ssid for the network stemming from this router."""
        if instance is None:
            instance = 0
            if len(self.hostapd_instances) > 1:
                raise error.TestFail('No instance of hostapd specified with '
                                     'multiple instances present.')

        if self.hostapd_instances:
            return self.hostapd_instances[instance].ssid

        if self.station_instances:
            return self.station_instances[0].ssid

        raise error.TestFail('Requested ssid of an unconfigured AP.')


    def deauth_client(self, client_mac):
        """Deauthenticates a client described in params.

        @param client_mac string containing the mac address of the client to be
               deauthenticated.

        """
        control_if = self.hostapd_instances[-1].config_dict['ctrl_interface']
        self.router.run('%s -p%s deauthenticate %s' %
                        (self.cmd_hostapd_cli, control_if, client_mac))

    def send_bss_tm_req(self, client_mac, neighbor_list):
        """Send a BSS Transition Management Request to a client.

        @param client_mac string containing the mac address of the client.
        @param neighbor_list list of strings containing mac addresses of
               candidate APs.
        @return string reply received from command

        """
        control_if = self.hostapd_instances[0].config_dict['ctrl_interface']
        command = ('%s -p%s BSS_TM_REQ %s neighbor=%s,0,0,0,0 pref=1' %
                   (self.cmd_hostapd_cli, control_if, client_mac,
                    ',0,0,0,0 neighbor='.join(neighbor_list)))
        ret = self.router.run(command).stdout
        return ret.splitlines()[-1]

    def _prep_probe_response_footer(self, footer):
        """Write probe response footer temporarily to a local file and copy
        over to test router.

        @param footer string containing bytes for the probe response footer.
        @raises AutoservRunError: If footer file copy fails.

        """
        with tempfile.NamedTemporaryFile() as fp:
            fp.write(footer)
            fp.flush()
            try:
                self.host.send_file(fp.name, self.PROBE_RESPONSE_FOOTER_FILE)
            except error.AutoservRunError:
                logging.error('failed to copy footer file to AP')
                raise


    def send_management_frame_on_ap(self, frame_type, channel, instance=0):
        """Injects a management frame into an active hostapd session.

        @param frame_type string the type of frame to send.
        @param channel int targeted channel
        @param instance int indicating which hostapd instance to inject into.

        """
        hostap_interface = self.hostapd_instances[instance].interface
        interface = self.get_wlanif(0, 'monitor', same_phy_as=hostap_interface)
        self.router.run("%s link set %s up" % (self.cmd_ip, interface))
        self.router.run('%s -i %s -t %s -c %d' %
                        (self.cmd_send_management_frame, interface, frame_type,
                         channel))
        self.release_interface(interface)


    def send_management_frame(self, interface, frame_type, channel,
                              ssid_prefix=None, num_bss=None,
                              frame_count=None, delay=None,
                              dest_addr=None, probe_resp_footer=None):
        """
        Injects management frames on specify channel |frequency|.

        This function will spawn off a new process to inject specified
        management frames |frame_type| at the specified interface |interface|.

        @param interface string interface to inject frames.
        @param frame_type string message type.
        @param channel int targeted channel.
        @param ssid_prefix string SSID prefix.
        @param num_bss int number of BSS.
        @param frame_count int number of frames to send.
        @param delay int milliseconds delay between frames.
        @param dest_addr string destination address (DA) MAC address.
        @param probe_resp_footer string footer for probe response.

        @return int PID of the newly created process.

        """
        command = '%s -i %s -t %s -c %d' % (self.cmd_send_management_frame,
                                interface, frame_type, channel)
        if ssid_prefix is not None:
            command += ' -s %s' % (ssid_prefix)
        if num_bss is not None:
            command += ' -b %d' % (num_bss)
        if frame_count is not None:
            command += ' -n %d' % (frame_count)
        if delay is not None:
            command += ' -d %d' % (delay)
        if dest_addr is not None:
            command += ' -a %s' % (dest_addr)
        if probe_resp_footer is not None:
            self._prep_probe_response_footer(footer=probe_resp_footer)
            command += ' -f %s' % (self.PROBE_RESPONSE_FOOTER_FILE)
        command += ' > %s 2>&1 & echo $!' % (os.path.join(self.logdir,
            self.MGMT_FRAME_SENDER_LOG_FILE))
        pid = int(self.router.run(command).stdout)
        return pid


    def detect_client_deauth(self, client_mac, instance=0):
        """Detects whether hostapd has logged a deauthentication from
        |client_mac|.

        @param client_mac string the MAC address of the client to detect.
        @param instance int indicating which hostapd instance to query.

        """
        interface = self.hostapd_instances[instance].interface
        deauth_msg = "%s: deauthentication: STA=%s" % (interface, client_mac)
        log_file = self.hostapd_instances[instance].log_file
        result = self.router.run("grep -qi '%s' %s" % (deauth_msg, log_file),
                                 ignore_status=True)
        return result.exit_status == 0


    def detect_client_coexistence_report(self, client_mac, instance=0):
        """Detects whether hostapd has logged an action frame from
        |client_mac| indicating information about 20/40MHz BSS coexistence.

        @param client_mac string the MAC address of the client to detect.
        @param instance int indicating which hostapd instance to query.

        """
        coex_msg = ('nl80211: MLME event frame - hexdump(len=.*): '
                    '.. .. .. .. .. .. .. .. .. .. %s '
                    '.. .. .. .. .. .. .. .. 04 00.*48 01 ..' %
                    ' '.join(client_mac.split(':')))
        log_file = self.hostapd_instances[instance].log_file
        result = self.router.run("grep -qi '%s' %s" % (coex_msg, log_file),
                                 ignore_status=True)
        return result.exit_status == 0


    def send_magic_packet(self, dest_ip, dest_mac):
        """Sends a magic packet to the NIC with the given IP and MAC addresses.

        @param dest_ip the IP address of the device to send the packet to
        @param dest_mac the hardware MAC address of the device

        """
        # magic packet is 6 0xff bytes followed by the hardware address
        # 16 times
        mac_bytes = ''.join([chr(int(b, 16)) for b in dest_mac.split(':')])
        magic_packet = '\xff' * 6 + mac_bytes * 16

        logging.info('Sending magic packet to %s...', dest_ip)
        self.host.run('python -uc "import socket, sys;'
                      's = socket.socket(socket.AF_INET, socket.SOCK_DGRAM);'
                      's.sendto(sys.stdin.read(), (\'%s\', %d))"' %
                      (dest_ip, UDP_DISCARD_PORT),
                      stdin=magic_packet)


    def setup_bridge_mode_dhcp_server(self):
        """Setup an DHCP server for bridge mode.

        Setup an DHCP server on the master interface of the virtual ethernet
        pair, with peer interface connected to the bridge interface. This is
        used for testing APs in bridge mode.

        """
        # Start a local server on master interface of virtual ethernet pair.
        self.start_local_server(
                self.get_virtual_ethernet_master_interface())
        # Add peer interface to the bridge.
        self.add_interface_to_bridge(
                self.get_virtual_ethernet_peer_interface())
