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