diff --git a/script/reference-device/dhcp6_pd_daemon.py b/script/reference-device/dhcp6_pd_daemon.py new file mode 100755 index 00000000000..f239d9b05a8 --- /dev/null +++ b/script/reference-device/dhcp6_pd_daemon.py @@ -0,0 +1,95 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2021, The OpenThread Authors. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# 3. Neither the name of the copyright holder nor the +# names of its contributors may be used to endorse or promote products +# derived from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +# +# This script subscribes to the Dhcp6PdState provided by the OT stack via D-Bus interface. +# It triggers dhcpcd to request the PD prefix via a pre-defined dhcpcd.conf when the state +# changes to "running" and restores the default dhcpcd.conf when the PD state is not "running". + +from dbus.mainloop.glib import DBusGMainLoop + +import dbus +import gi.repository.GLib as GLib +import subprocess +import time +import subprocess +import os + +dbus_loop = DBusGMainLoop(set_as_default=True) +bus = dbus.SystemBus() +obj = None +iface = None + +def properties_changed_handler(interface_name, changed_properties, invalidated_properties): + if "Dhcp6PdState" in changed_properties: + new_state = changed_properties["Dhcp6PdState"] + print(f"Dhcp6PdState changed to: {new_state}") + if new_state == "running": # Check for string equality + try: + subprocess.run(["sudo", "service", "dhcpcd", "restart"], check=True) + print("Successfully restarted dhcpcd service.") + except subprocess.CalledProcessError as e: + print(f"Error restarting dhcpcd service: {e}") + elif new_state == "stopped": + if os.path.isfile("/etc/dhcpcd.conf.orig"): # Check if backup exists + try: + subprocess.run(["sudo", "cp", "/etc/dhcpcd.conf.orig", "/etc/dhcpcd.conf"], check=True) + print("Successfully restored default dhcpcd config.") + except subprocess.CalledProcessError as e: + print(f"Error restoring dhcpcd config: {e}") + else: + print("Backup configuration file not found. Cannot restore default.") + +def connect_to_signal(): + global obj, iface + try: + obj = bus.get_object('io.openthread.BorderRouter.wpan0', '/io/openthread/BorderRouter/wpan0') + iface = dbus.Interface(obj, 'org.freedesktop.DBus.Properties') + obj.connect_to_signal("PropertiesChanged", properties_changed_handler, dbus_interface=iface.dbus_interface) + print("Connected to D-Bus signal.") + except dbus.DBusException as ex: + print(f"Error connecting to D-Bus: {ex}") + obj = None + iface = None + + +def check_and_reconnect(): + if obj is None: + connect_to_signal() + +def main(): + connect_to_signal() + + loop = GLib.MainLoop() + + GLib.timeout_add_seconds(5, check_and_reconnect) # Check every 5 seconds + + loop.run() + +if __name__ == '__main__': + main()