# Lint as: python2, python3
# Copyright (c) 2013 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.

"""
Encapsulate functionality of the Linux IPv6 Router Advertisement Daemon.
Support writing out a configuration file as well as starting and stopping
the service.
"""

import os
import signal

from autotest_lib.client.common_lib import error
from autotest_lib.client.common_lib import utils

# Filenames used for execution.
RADVD_EXECUTABLE = '/usr/local/sbin/radvd'
RADVD_CONFIG_FILE = '/tmp/radvd_test.conf'
RADVD_PID_FILE = '/tmp/radvd_test.pid'

# These are default configuration values.
RADVD_DEFAULT_ADV_ON_LINK = 'on'
RADVD_DEFAULT_ADV_AUTONOMOUS = 'on'
RADVD_DEFAULT_ADV_ROUTER_ADDR = 'on'
RADVD_DEFAULT_ADV_RDNSS_LIFETIME = 'infinity'
RADVD_DEFAULT_DNSSL_LIST = 'a.com b.com'
RADVD_DEFAULT_MAX_ADV_INTERVAL = 10
RADVD_DEFAULT_MIN_ADV_INTERVAL = 3
RADVD_DEFAULT_SEND_ADVERT = 'on'

# The addresses below are within the  2001:0db8/32 "documentation only" prefix
# (RFC3849), which is guaranteed never to be assigned to a real network.
RADVD_DEFAULT_SUFFIX = '/64'
RADVD_DEFAULT_PREFIX = '2001:db8:100:f101::/64'
RADVD_DEFAULT_RDNSS_SERVERS = ( '2001:db8:100:f101::1 '
                                '2001:db8:100:f101::2' )

# Option names.
OPTION_ADV_ON_LINK = 'adv_on_link'
OPTION_ADV_AUTONOMOUS = 'adv_autonomous'
OPTION_ADV_ROUTER_ADDR = 'adv_router_addr'
OPTION_ADV_RDNSS_LIFETIME = 'adv_rdnss_lifetime'
OPTION_DNSSL_LIST = 'dnssl_list'
OPTION_INTERFACE = 'interface'
OPTION_MAX_ADV_INTERVAL = 'max_adv_interval'
OPTION_MIN_ADV_INTERVAL = 'min_adv_interval'
OPTION_PREFIX = 'prefix'
OPTION_RDNSS_SERVERS = 'rdnss_servers'
OPTION_SEND_ADVERT = 'adv_send_advert'

class RadvdServer(object):
    """
    This is an embodiment of the radvd server process.  It converts an
    option dict into parameters for the radvd configuration file and
    manages startup and cleanup of the process.
    """

    def __init__(self, interface=None, namespace=None):
        if not os.path.exists(RADVD_EXECUTABLE):
            raise error.TestNAError('Could not find executable %s; '
                                    'this is likely an old version of '
                                    'ChromiumOS' %
                                    RADVD_EXECUTABLE)
        self._namespace = namespace
        self._options = {
            OPTION_INTERFACE: interface,
            OPTION_ADV_ON_LINK: RADVD_DEFAULT_ADV_ON_LINK,
            OPTION_ADV_AUTONOMOUS: RADVD_DEFAULT_ADV_AUTONOMOUS,
            OPTION_ADV_ROUTER_ADDR: RADVD_DEFAULT_ADV_ROUTER_ADDR,
            OPTION_ADV_RDNSS_LIFETIME: RADVD_DEFAULT_ADV_RDNSS_LIFETIME,
            OPTION_DNSSL_LIST: RADVD_DEFAULT_DNSSL_LIST,
            OPTION_MAX_ADV_INTERVAL: RADVD_DEFAULT_MAX_ADV_INTERVAL,
            OPTION_MIN_ADV_INTERVAL: RADVD_DEFAULT_MIN_ADV_INTERVAL,
            OPTION_PREFIX: RADVD_DEFAULT_PREFIX,
            OPTION_RDNSS_SERVERS: RADVD_DEFAULT_RDNSS_SERVERS,
            OPTION_SEND_ADVERT: RADVD_DEFAULT_SEND_ADVERT
        }

    @property
    def options(self):
        """
        Property dict used to generate configuration file.
        """
        return self._options

    def _write_config_file(self):
        """
        Write out a configuration file for radvd to use.
        """
        config = '\n'.join([
                     'interface %(interface)s {',
                     '  AdvSendAdvert %(adv_send_advert)s;',
                     '  MinRtrAdvInterval %(min_adv_interval)d;',
                     '  MaxRtrAdvInterval %(max_adv_interval)d;',
                     '  prefix %(prefix)s {',
                     '    AdvOnLink %(adv_on_link)s;',
                     '    AdvAutonomous %(adv_autonomous)s;',
                     '    AdvRouterAddr %(adv_router_addr)s;',
                     '  };',
                     '  RDNSS %(rdnss_servers)s {',
                     '    AdvRDNSSLifetime %(adv_rdnss_lifetime)s;',
                     '  };',
                     '  DNSSL %(dnssl_list)s {',
                     '  };',
                     '};',
                     '']) % self.options
        with open(RADVD_CONFIG_FILE, 'w') as f:
            f.write(config)

    def _cleanup(self):
        """
        Cleanup temporary files.  If PID file exists, also kill the
        associated process.
        """
        if os.path.exists(RADVD_PID_FILE):
            with open(RADVD_PID_FILE, 'r') as rf:
                pid = int(rf.read())
            os.remove(RADVD_PID_FILE)
            try:
                os.kill(pid, signal.SIGTERM)
            except OSError:
                pass
        if os.path.exists(RADVD_CONFIG_FILE):
            os.remove(RADVD_CONFIG_FILE)

    def start_server(self):
        """
        Start the radvd server.  The server will daemonize itself and
        run in the background.
        """
        self._cleanup()
        self._write_config_file()
        cmd = '%s -p %s -C %s'
        if self._namespace:
            cmd = ('ip netns exec %s ' % self._namespace) + cmd
        utils.system(cmd %
                     (RADVD_EXECUTABLE, RADVD_PID_FILE, RADVD_CONFIG_FILE))

    def stop_server(self):
        """
        Halt the radvd server.
        """
        self._cleanup()
