1# Lint as: python2, python3 2# Copyright (c) 2013 The Chromium OS Authors. All rights reserved. 3# Use of this source code is governed by a BSD-style license that can be 4# found in the LICENSE file. 5 6""" 7Encapsulate functionality of the Linux IPv6 Router Advertisement Daemon. 8Support writing out a configuration file as well as starting and stopping 9the service. 10""" 11 12import os 13import signal 14 15from autotest_lib.client.common_lib import error 16from autotest_lib.client.common_lib import utils 17 18# Filenames used for execution. 19RADVD_EXECUTABLE = '/usr/local/sbin/radvd' 20RADVD_CONFIG_FILE = '/tmp/radvd_test.conf' 21RADVD_PID_FILE = '/tmp/radvd_test.pid' 22 23# These are default configuration values. 24RADVD_DEFAULT_ADV_ON_LINK = 'on' 25RADVD_DEFAULT_ADV_AUTONOMOUS = 'on' 26RADVD_DEFAULT_ADV_ROUTER_ADDR = 'on' 27RADVD_DEFAULT_ADV_RDNSS_LIFETIME = 'infinity' 28RADVD_DEFAULT_DNSSL_LIST = 'a.com b.com' 29RADVD_DEFAULT_MAX_ADV_INTERVAL = 10 30RADVD_DEFAULT_MIN_ADV_INTERVAL = 3 31RADVD_DEFAULT_SEND_ADVERT = 'on' 32 33# The addresses below are within the 2001:0db8/32 "documentation only" prefix 34# (RFC3849), which is guaranteed never to be assigned to a real network. 35RADVD_DEFAULT_SUFFIX = '/64' 36RADVD_DEFAULT_PREFIX = '2001:db8:100:f101::/64' 37RADVD_DEFAULT_RDNSS_SERVERS = ( '2001:db8:100:f101::1 ' 38 '2001:db8:100:f101::2' ) 39 40# Option names. 41OPTION_ADV_ON_LINK = 'adv_on_link' 42OPTION_ADV_AUTONOMOUS = 'adv_autonomous' 43OPTION_ADV_ROUTER_ADDR = 'adv_router_addr' 44OPTION_ADV_RDNSS_LIFETIME = 'adv_rdnss_lifetime' 45OPTION_DNSSL_LIST = 'dnssl_list' 46OPTION_INTERFACE = 'interface' 47OPTION_MAX_ADV_INTERVAL = 'max_adv_interval' 48OPTION_MIN_ADV_INTERVAL = 'min_adv_interval' 49OPTION_PREFIX = 'prefix' 50OPTION_RDNSS_SERVERS = 'rdnss_servers' 51OPTION_SEND_ADVERT = 'adv_send_advert' 52 53class RadvdServer(object): 54 """ 55 This is an embodiment of the radvd server process. It converts an 56 option dict into parameters for the radvd configuration file and 57 manages startup and cleanup of the process. 58 """ 59 60 def __init__(self, interface = None): 61 if not os.path.exists(RADVD_EXECUTABLE): 62 raise error.TestNAError('Could not find executable %s; ' 63 'this is likely an old version of ' 64 'ChromiumOS' % 65 RADVD_EXECUTABLE) 66 self._options = { 67 OPTION_INTERFACE: interface, 68 OPTION_ADV_ON_LINK: RADVD_DEFAULT_ADV_ON_LINK, 69 OPTION_ADV_AUTONOMOUS: RADVD_DEFAULT_ADV_AUTONOMOUS, 70 OPTION_ADV_ROUTER_ADDR: RADVD_DEFAULT_ADV_ROUTER_ADDR, 71 OPTION_ADV_RDNSS_LIFETIME: RADVD_DEFAULT_ADV_RDNSS_LIFETIME, 72 OPTION_DNSSL_LIST: RADVD_DEFAULT_DNSSL_LIST, 73 OPTION_MAX_ADV_INTERVAL: RADVD_DEFAULT_MAX_ADV_INTERVAL, 74 OPTION_MIN_ADV_INTERVAL: RADVD_DEFAULT_MIN_ADV_INTERVAL, 75 OPTION_PREFIX: RADVD_DEFAULT_PREFIX, 76 OPTION_RDNSS_SERVERS: RADVD_DEFAULT_RDNSS_SERVERS, 77 OPTION_SEND_ADVERT: RADVD_DEFAULT_SEND_ADVERT 78 } 79 80 @property 81 def options(self): 82 """ 83 Property dict used to generate configuration file. 84 """ 85 return self._options 86 87 def _write_config_file(self): 88 """ 89 Write out a configuration file for radvd to use. 90 """ 91 config = '\n'.join([ 92 'interface %(interface)s {', 93 ' AdvSendAdvert %(adv_send_advert)s;', 94 ' MinRtrAdvInterval %(min_adv_interval)d;', 95 ' MaxRtrAdvInterval %(max_adv_interval)d;', 96 ' prefix %(prefix)s {', 97 ' AdvOnLink %(adv_on_link)s;', 98 ' AdvAutonomous %(adv_autonomous)s;', 99 ' AdvRouterAddr %(adv_router_addr)s;', 100 ' };', 101 ' RDNSS %(rdnss_servers)s {', 102 ' AdvRDNSSLifetime %(adv_rdnss_lifetime)s;', 103 ' };', 104 ' DNSSL %(dnssl_list)s {', 105 ' };', 106 '};', 107 '']) % self.options 108 with open(RADVD_CONFIG_FILE, 'w') as f: 109 f.write(config) 110 111 def _cleanup(self): 112 """ 113 Cleanup temporary files. If PID file exists, also kill the 114 associated process. 115 """ 116 if os.path.exists(RADVD_PID_FILE): 117 with open(RADVD_PID_FILE, 'r') as rf: 118 pid = int(rf.read()) 119 os.remove(RADVD_PID_FILE) 120 try: 121 os.kill(pid, signal.SIGTERM) 122 except OSError: 123 pass 124 if os.path.exists(RADVD_CONFIG_FILE): 125 os.remove(RADVD_CONFIG_FILE) 126 127 def start_server(self): 128 """ 129 Start the radvd server. The server will daemonize itself and 130 run in the background. 131 """ 132 self._cleanup() 133 self._write_config_file() 134 utils.system('%s -p %s -C %s' % 135 (RADVD_EXECUTABLE, RADVD_PID_FILE, RADVD_CONFIG_FILE)) 136 137 def stop_server(self): 138 """ 139 Halt the radvd server. 140 """ 141 self._cleanup() 142