# 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): 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._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): pid = int(file(RADVD_PID_FILE).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() utils.system('%s -p %s -C %s' % (RADVD_EXECUTABLE, RADVD_PID_FILE, RADVD_CONFIG_FILE)) def stop_server(self): """ Halt the radvd server. """ self._cleanup()