# Copyright (c) 2014 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.

from autotest_lib.client.common_lib import error
from autotest_lib.client.cros import dhcp_handling_rule
from autotest_lib.client.cros import dhcp_packet
from autotest_lib.client.cros import dhcp_test_base

# Length of time the lease from the DHCP server is valid.
LEASE_TIME_SECONDS = 3600
# We'll fill in the subnet and give this address to the client.
INTENDED_IP_SUFFIX = "0.0.0.101"

class network_DhcpNak(dhcp_test_base.DhcpTestBase):
    """
    Tests a DHCP client's handling of NAK messages.

    Negotiates a lease, and then tests how the DHCP client processes
    NAKs in two scenarios. In the first scenario, the DHCP client
    is started anew, but with the cached lease on disk. In the
    second scenario, an already-running DHCP client is asked to
    renew its lease.

    In both scenarios, the NAK messages omit the DHCP server-id
    option. This is to emulate some DHCP servers (e.g. OpenBSD 4.6),
    which omit the DHCP server-id in NAK messages.
    """

    def common_setup(self):
        """
        Run common setup steps.
        """
        subnet_mask = self.ethernet_pair.interface_subnet_mask
        self.intended_ip = dhcp_test_base.DhcpTestBase.rewrite_ip_suffix(
            subnet_mask, self.server_ip, INTENDED_IP_SUFFIX)
        self.interface_name = self.ethernet_pair.peer_interface_name
        self.dhcp_options = {
            dhcp_packet.OPTION_SERVER_ID : self.server_ip,
            dhcp_packet.OPTION_SUBNET_MASK : subnet_mask,
            dhcp_packet.OPTION_IP_LEASE_TIME : LEASE_TIME_SECONDS,
            dhcp_packet.OPTION_REQUESTED_IP : self.intended_ip,
            dhcp_packet.OPTION_DNS_SERVERS : [],
            dhcp_packet.OPTION_DOMAIN_NAME : '',
            dhcp_packet.OPTION_DNS_DOMAIN_SEARCH_LIST : [],
            }
        self.negotiate_and_check_lease(self.dhcp_options)

    def reconnect_service(self):
        """
        Disconnect and reconnect Ethernet.

        Ask shill to disconnect and reconnect the Service for our
        virtual Ethernet link. This causes shill to shut down and
        restart dhcpcd for the link.
        """
        service = self.find_ethernet_service(self.interface_name)
        service.Disconnect()
        rules = [
            # Respond to DISCOVERY, but then NAK the REQUEST.
            dhcp_handling_rule.DhcpHandlingRule_RespondToDiscovery(
                self.intended_ip, self.server_ip, self.dhcp_options, {}),
            dhcp_handling_rule.DhcpHandlingRule_RejectRequest(),

            # Allow a successful negotiation the second time around.
            dhcp_handling_rule.DhcpHandlingRule_RespondToDiscovery(
                self.intended_ip, self.server_ip, self.dhcp_options, {}),
            dhcp_handling_rule.DhcpHandlingRule_RespondToRequest(
                self.intended_ip, self.server_ip, self.dhcp_options, {}),
            ]
        rules[-1].is_final_handler = True
        self.server.start_test(
            rules, dhcp_test_base.DHCP_NEGOTIATION_TIMEOUT_SECONDS)
        service.Connect()

    def force_dhcp_renew(self):
        """
        Force a DHCP renewal.

        Ask shill to Refresh the configuration for the IPConfig object
        associated with our virtual Ethernet link. This causes shill
        to ask dhcpcd to renew its DHCP lease.
        """
        rules = [
            # Reject REQUEST from renewal attempt.
            dhcp_handling_rule.DhcpHandlingRule_RejectRequest(),

            # Allow a successful negotiation after that.
            dhcp_handling_rule.DhcpHandlingRule_RespondToDiscovery(
                self.intended_ip, self.server_ip, self.dhcp_options, {}),
            dhcp_handling_rule.DhcpHandlingRule_RespondToRequest(
                self.intended_ip, self.server_ip, self.dhcp_options, {}),
            ]
        rules[-1].is_final_handler = True
        self.server.start_test(
            rules, dhcp_test_base.DHCP_NEGOTIATION_TIMEOUT_SECONDS)
        self.get_interface_ipconfig_objects(self.interface_name)[0].Refresh()

    def test_body(self):
        """
        Entry point for this test.

        This is called from DhcpTestBase.run_once().
        """
        self.common_setup()
        for sub_test in self.reconnect_service, self.force_dhcp_renew:
            sub_test()
            self.server.wait_for_test_to_finish()
            if not self.server.last_test_passed:
                raise error.TestFail('Test failed (%s): active rule is %s' % (
                        sub_test.__name__, self.server.current_rule))
