xref: /aosp_15_r20/external/autotest/client/cros/radvd_server.py (revision 9c5db1993ded3edbeafc8092d69fe5de2ee02df7)
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