# 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 random
import string
import tempfile
import time

from autotest_lib.client.common_lib import error
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
from autotest_lib.server.cros.network import hostap_config


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)

    return LinuxRouter(hosts.create_host(router_hostname), 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 = 10
    SUFFIX_LETTERS = string.ascii_lowercase + string.digits
    SUBNET_PREFIX_OCTETS = (192, 168)

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

    STATION_CONF_FILE_PATTERN = '/tmp/wpa-supplicant-test-%s.conf'
    STATION_LOG_FILE_PATTERN = '/tmp/wpa-supplicant-test-%s.log'
    STATION_PID_FILE_PATTERN = '/tmp/wpa-supplicant-test-%s.pid'

    MGMT_FRAME_SENDER_LOG_FILE = '/tmp/send_management_frame-test.log'

    PROBE_RESPONSE_FOOTER_FILE = '/tmp/autotest-probe_response_footer'

    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 = '/tmp/dhcpd.%s.conf'
        self.dhcpd_leases = '/tmp/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').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().split(None, 2)[0]
        logging.debug('Will only retrieve logs after %s.',
                      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

        # 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')

        # Reset all antennas to be active
        self.set_default_antenna_bitmap()

        # 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)


    def close(self):
        """Close global resources held by this system."""
        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 >/tmp/router_log" %
                      self._log_start_timestamp, ignore_status=True)
        self.host.get_file('/tmp/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.
        if configuration.min_streams is None:
            interface = self.get_wlanif(configuration.frequency, 'managed')
        else:
            interface = self.get_wlanif(
                configuration.frequency, 'managed', configuration.min_streams)

        conf_file = self.HOSTAPD_CONF_FILE_PATTERN % interface
        log_file = self.HOSTAPD_LOG_FILE_PATTERN % interface
        stderr_log_file = self.HOSTAPD_STDERR_LOG_FILE_PATTERN % interface
        control_interface = 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, self.iw_runner.get_interface(interface).phy,
                     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.')
        start_time = time.time()
        while time.time() - start_time < self.STARTUP_TIMEOUT_SECONDS:
            success = self.router.run(
                    'grep "Setup of interface done" %s' % log_file,
                    ignore_status=True).exit_status == 0
            if success:
                break

            # 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.')

            time.sleep(self.POLLING_INTERVAL_SECONDS)
        else:
            raise error.TestFail('Timed out while waiting for hostapd '
                                 'to start.')


    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)
        is_dead = False
        start_time = time.time()
        while not is_dead and time.time() - start_time < timeout_seconds:
            time.sleep(self.POLLING_INTERVAL_SECONDS)
            is_dead = self.host.run(
                    'pgrep -l %s' % search_arg,
                    ignore_status=True).exit_status != 0
        if is_dead or ignore_timeouts:
            return is_dead

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


    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 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')

        self.start_hostapd(configuration)
        interface = self.hostapd_instances[-1].interface
        self.iw_runner.set_tx_power(interface, 'auto')
        self.set_beacon_footer(interface, configuration.beacon_footer)
        self.start_local_server(interface)
        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_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):
        """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

        """
        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['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))
        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['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)


    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 _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)
            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 setup_management_frame_interface(self, channel):
        """
        Setup interface for injecting management frames.

        @param channel int channel to inject the frames.

        @return string name of the interface.

        """
        frequency = hostap_config.HostapConfig.get_frequency_for_channel(
                channel)
        interface = self.get_wlanif(frequency, 'monitor')
        self.router.run('%s link set %s up' % (self.cmd_ip, interface))
        self.iw_runner.set_freq(interface, frequency)
        return 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 $!' % (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 add_connected_peer(self, instance=0):
        """Configure a station connected to a running AP instance.

        Extract relevant configuration objects from the hostap
        configuration for |instance| and generate a wpa_supplicant
        instance that connects to it.  This allows the DUT to interact
        with a client entity that is also connected to the same AP.  A
        full wpa_supplicant instance is necessary here (instead of just
        using the "iw" command to connect) since we want to enable
        advanced features such as TDLS.

        @param instance int indicating which hostapd instance to connect to.

        """
        if not self.hostapd_instances:
            raise error.TestFail('Hostapd is not configured.')

        if self.station_instances:
            raise error.TestFail('Station is already configured.')

        ssid = self.get_ssid(instance)
        hostap_conf = self.hostapd_instances[instance].config_dict
        frequency = hostap_config.HostapConfig.get_frequency_for_channel(
                hostap_conf['channel'])
        self.configure_managed_station(
                ssid, frequency, self.local_peer_ip_address(instance))
        interface = self.station_instances[0].interface
        # Since we now have two network interfaces connected to the same
        # network, we need to disable the kernel's protection against
        # incoming packets to an "unexpected" interface.
        self.router.run('echo 2 > /proc/sys/net/ipv4/conf/%s/rp_filter' %
                        interface)

        # Similarly, we'd like to prevent the hostap interface from
        # replying to ARP requests for the peer IP address and vice
        # versa.
        self.router.run('echo 1 > /proc/sys/net/ipv4/conf/%s/arp_ignore' %
                        interface)
        self.router.run('echo 1 > /proc/sys/net/ipv4/conf/%s/arp_ignore' %
                        hostap_conf['interface'])


    def configure_managed_station(self, ssid, frequency, ip_addr):
        """Configure a router interface to connect as a client to a network.

        @param ssid: string SSID of network to join.
        @param frequency: int frequency required to join the network.
        @param ip_addr: IP address to assign to this interface
                        (e.g. '192.168.1.200').

        """
        interface = self.get_wlanif(frequency, 'managed')

        # TODO(pstew): Configure other bits like PSK, 802.11n if tests
        # require them...
        supplicant_config = (
                'network={\n'
                '  ssid="%(ssid)s"\n'
                '  key_mgmt=NONE\n'
                '}\n' % {'ssid': ssid}
        )

        conf_file = self.STATION_CONF_FILE_PATTERN % interface
        log_file = self.STATION_LOG_FILE_PATTERN % interface
        pid_file = self.STATION_PID_FILE_PATTERN % interface

        self.router.run('cat <<EOF >%s\n%s\nEOF\n' %
            (conf_file, supplicant_config))

        # Connect the station.
        self.router.run('%s link set %s up' % (self.cmd_ip, interface))
        start_command = ('%s -dd -t -i%s -P%s -c%s -D%s >%s 2>&1 &' %
                         (self.cmd_wpa_supplicant,
                         interface, pid_file, conf_file,
                         self.HOSTAPD_DRIVER_NAME, log_file))
        self.router.run(start_command)
        self.iw_runner.wait_for_link(interface)

        # Assign an IP address to this interface.
        self.router.run('%s addr add %s/24 dev %s' %
                        (self.cmd_ip, ip_addr, interface))
        self.station_instances.append(
                StationInstance(ssid=ssid, interface=interface,
                                dev_type='managed'))


    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 set_beacon_footer(self, interface, footer=''):
        """Sets the beacon footer (appended IE information) for this interface.

        @param interface string interface to set the footer on.
        @param footer string footer to be set on the interface.

        """
        footer_file = ('/sys/kernel/debug/ieee80211/%s/beacon_footer' %
                       self.iw_runner.get_interface(interface).phy)
        if self.router.run('test -e %s' % footer_file,
                           ignore_status=True).exit_status != 0:
            logging.info('Beacon footer file does not exist.  Ignoring.')
            return
        self.host.run('echo -ne %s > %s' % ('%r' % footer, footer_file))


    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())
