# Lint as: python2, python3
# Copyright 2010 The ChromiumOS Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

from __future__ import absolute_import
from __future__ import division
from __future__ import print_function

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

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
import six
from six.moves import range


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'])
IPTablesRule = collections.namedtuple('IPTablesRule',
                                      ['chain', 'rule', 'table'])

# 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)
    # Don't bother pinging if manually specified. It could, for instance, be
    # only accessible over SSH.
    if not router_addr:
        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 host auto detection
    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_'
    UP_INTERFACES = ("eth0", "lo", "br-lan", "lan")
    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'

    _IPTABLES_CMD = '/sbin/iptables'
    _ENABLE_WAN_IPTABLE_RULES = [
            IPTablesRule(chain='POSTROUTING',
                         rule='-o {wan_if} -j MASQUERADE',
                         table='nat'),
            IPTablesRule(
                    chain='INPUT',
                    rule='-i {wan_if} -m state --state ESTABLISHED,RELATED'
                    ' -j ACCEPT',
                    table=None),
            IPTablesRule(chain='OUTPUT', rule='-j ACCEPT', table=None),
            IPTablesRule(chain='INPUT',
                         rule='-i {wap_if} -j ACCEPT',
                         table=None)
    ]

    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, role='router'):
        """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.
        @param role string description of host (e.g. router, pcap)

        """
        super(LinuxRouter, self).__init__(host, role)
        self._ssid_prefix = test_name
        self._enable_avahi = enable_avahi
        self._enable_wan = False
        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')

        self.setup_logs()

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

        # Tear down all redundant interfaces
        self.tear_down_redundant_interfaces()

        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()
        self.get_logs(router_log)
        super(LinuxRouter, self).close()


    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 six.iteritems(hostapd_conf_dict))))

        # 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 = (
            'OPENSSL_CONF=/etc/ssl/openssl.cnf.compat '
            'OPENSSL_CHROMIUM_SKIP_TRUSTED_PURPOSE_CHECK=1 '
            '%s -dd -t -K %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 -e "Setup of interface done" -e "AP-ENABLED" %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_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_%s_%s.log' %
                          (self.role, log_identifier)),
                         (instance.stderr_log_file,
                          'debug/hostapd_%s_%s.stderr.log' %
                          (self.role, 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,
                         enable_wan_access=False):
        """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.
        @param enable_wan_access True iff traffic to the WAN is allowed.
        """
        if multi_interface and enable_wan_access:
            raise error.TestFail(
                    'Enable wan access is currently not supported '
                    'for multiple APs.')
        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.start_local_server(interface, bridge=configuration.bridge)
        if enable_wan_access:
            self.enable_wan_access(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_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 list(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 list(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)

                if self._enable_wan:
                    self.disable_wan_access(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 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 main 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 main interface of virtual ethernet pair.
        self.start_local_server(
                self.get_virtual_ethernet_main_interface())
        # Add peer interface to the bridge.
        self.add_interface_to_bridge(
                self.get_virtual_ethernet_peer_interface())


    def create_brif(self):
        """Initialize a new bridge interface

        @return string bridge interface name
        """
        brif_name = '%s%d' % (self.HOSTAP_BRIDGE_INTERFACE_PREFIX,
                              self._brif_index)
        self._brif_index += 1
        self.host.run('brctl addbr %s' % brif_name)
        return brif_name


    def tear_down_redundant_interfaces(self):
        """Tear down redundant interfaces

        Tear down all redundant interfaces except those in up_interfaces

        """
        all_interfaces = []
        # Example "ip link show up" output:
        # 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UP mode DEFAULT group default qlen 1000
        #    link/loopback 00:00:00:00:00:00 brd ff:ff:ff:ff:ff:ff
        output = self.router.run('%s link show up' % (self.cmd_ip))
        if output.exit_status:
            raise error.TestError('"%s link show up" error: %s' %
                                    (self.cmd_ip, output.stderr))
        content = output.stdout.strip().split('\n')
        for line in content:
            interface_name = self.get_interface_name(line)
            if interface_name:
                all_interfaces.append(interface_name)

        for interface_name in all_interfaces:
            if interface_name in self.UP_INTERFACES:
                continue
            self.router.run('%s link set %s down' % (self.cmd_ip, interface_name))


    def get_interface_name(self, line):
        """Get the interface name from the string

        @return string interface name
        """
        # Example of a line which matches the pattern, where "lo" is the
        # interface name
        # 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UP mode DEFAULT group default qlen 1000
        # Check if the line starts like "1: iface:" or "1: iface@alias:"
        if not re.match("^\\d+:\\s+([^@:]+)@?[^:]*:", line):
            return None
        # Split the line by whitespaces, a valid input should have at least 5
        # fields
        fields = line.split()
        if len(fields) < 5:
            raise error.TestError('invalid "%s link show up" output: %s' %
                                    (self.cmd_ip, line))
        # fields[1] is "iface:" or "iface@alias:"
        interface_with_possible_alias = fields[1].strip(':')
        # Split interface_with_possible_alias by '@', interface_alias[0] is the
        # interface name, and interface_alias[1] (if exists) is the alias name
        interface_alias = interface_with_possible_alias.split("@")
        return interface_alias[0]

    def _add_iptable_rule(self, chain, rule, table=None):
        """Add an iptable rule to a chain.

        Will not add the rule if it already exists.

        @param chain The name of the chain to add the rule to.
        @param rule The iptable rule to be added.
        @param table The table to manipulate iff not the default.
        """
        cmd = self._IPTABLES_CMD
        if table:
            cmd = cmd + ' -t %s' % (table)
        cmd = '%s -C %s %s || %s -A %s %s' % (cmd, chain, rule, cmd, chain,
                                              rule)
        self.host.run(cmd)

    def _drop_iptable_rule(self, chain, rule, table=None):
        """Remove an iptable rule from a chain.

        Will drop all instances of the rule on the chain if any.

        @param chain The name of the chain to remove the rule from.
        @param rule The iptable rule to be removed.
        @param table The table to manipulate iff not the default.
        """
        cmd = self._IPTABLES_CMD
        if table:
            cmd = cmd + ' -t %s' % (table)
        cmd = '%s -D %s %s' % (cmd, chain, rule)
        self.host.run(cmd, ignore_status=True)

    def enable_wan_access(self, wap_if, wan_if='eth0'):
        """Enable WAN access via NAT.

        Add iptable rules to NAT AP traffic onto the `wan_if`.

        @param wap_if Interface of AP on which to disable WAN access.
        @param wan_if Name of the interface connected to the WAN.
        """
        if len(self.hostapd_instances) > 1:
            raise error.TestFail(
                    'Enable wan access is currently not supported '
                    'for multiple APs.')
        logging.info('Enable wan access on interface: %s', wap_if)
        for instance in self._ENABLE_WAN_IPTABLE_RULES:
            self._add_iptable_rule(
                    instance.chain,
                    instance.rule.format(wap_if=wap_if, wan_if=wan_if),
                    instance.table)
        self.host.run('echo 1 > /proc/sys/net/ipv4/ip_forward')
        self._enable_wan = True

    def disable_wan_access(self, wap_if, wan_if='eth0'):
        """Disable WAN access.

        Remove iptable rules that NAT AP traffic onto the `wan_if`.

        @param wap_if Interface of AP on which to disable WAN access.
        @param wan_if Name of the interface connected to the WAN.
        """
        logging.info('Disable wan access on interface: %s', wap_if)
        self.host.run('echo 0 > /proc/sys/net/ipv4/ip_forward')
        for instance in reversed(self._ENABLE_WAN_IPTABLE_RULES):
            self._drop_iptable_rule(
                    instance.chain,
                    instance.rule.format(wap_if=wap_if, wan_if=wan_if),
                    instance.table)
        self._enable_wan = False
