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