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, namespace=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._namespace = namespace 67 self._options = { 68 OPTION_INTERFACE: interface, 69 OPTION_ADV_ON_LINK: RADVD_DEFAULT_ADV_ON_LINK, 70 OPTION_ADV_AUTONOMOUS: RADVD_DEFAULT_ADV_AUTONOMOUS, 71 OPTION_ADV_ROUTER_ADDR: RADVD_DEFAULT_ADV_ROUTER_ADDR, 72 OPTION_ADV_RDNSS_LIFETIME: RADVD_DEFAULT_ADV_RDNSS_LIFETIME, 73 OPTION_DNSSL_LIST: RADVD_DEFAULT_DNSSL_LIST, 74 OPTION_MAX_ADV_INTERVAL: RADVD_DEFAULT_MAX_ADV_INTERVAL, 75 OPTION_MIN_ADV_INTERVAL: RADVD_DEFAULT_MIN_ADV_INTERVAL, 76 OPTION_PREFIX: RADVD_DEFAULT_PREFIX, 77 OPTION_RDNSS_SERVERS: RADVD_DEFAULT_RDNSS_SERVERS, 78 OPTION_SEND_ADVERT: RADVD_DEFAULT_SEND_ADVERT 79 } 80 81 @property 82 def options(self): 83 """ 84 Property dict used to generate configuration file. 85 """ 86 return self._options 87 88 def _write_config_file(self): 89 """ 90 Write out a configuration file for radvd to use. 91 """ 92 config = '\n'.join([ 93 'interface %(interface)s {', 94 ' AdvSendAdvert %(adv_send_advert)s;', 95 ' MinRtrAdvInterval %(min_adv_interval)d;', 96 ' MaxRtrAdvInterval %(max_adv_interval)d;', 97 ' prefix %(prefix)s {', 98 ' AdvOnLink %(adv_on_link)s;', 99 ' AdvAutonomous %(adv_autonomous)s;', 100 ' AdvRouterAddr %(adv_router_addr)s;', 101 ' };', 102 ' RDNSS %(rdnss_servers)s {', 103 ' AdvRDNSSLifetime %(adv_rdnss_lifetime)s;', 104 ' };', 105 ' DNSSL %(dnssl_list)s {', 106 ' };', 107 '};', 108 '']) % self.options 109 with open(RADVD_CONFIG_FILE, 'w') as f: 110 f.write(config) 111 112 def _cleanup(self): 113 """ 114 Cleanup temporary files. If PID file exists, also kill the 115 associated process. 116 """ 117 if os.path.exists(RADVD_PID_FILE): 118 with open(RADVD_PID_FILE, 'r') as rf: 119 pid = int(rf.read()) 120 os.remove(RADVD_PID_FILE) 121 try: 122 os.kill(pid, signal.SIGTERM) 123 except OSError: 124 pass 125 if os.path.exists(RADVD_CONFIG_FILE): 126 os.remove(RADVD_CONFIG_FILE) 127 128 def start_server(self): 129 """ 130 Start the radvd server. The server will daemonize itself and 131 run in the background. 132 """ 133 self._cleanup() 134 self._write_config_file() 135 cmd = '%s -p %s -C %s' 136 if self._namespace: 137 cmd = ('ip netns exec %s ' % self._namespace) + cmd 138 utils.system(cmd % 139 (RADVD_EXECUTABLE, RADVD_PID_FILE, RADVD_CONFIG_FILE)) 140 141 def stop_server(self): 142 """ 143 Halt the radvd server. 144 """ 145 self._cleanup() 146