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