1#!/bin/bash 2# 3# Copyright (c) 2024, The OpenThread Authors. 4# All rights reserved. 5# 6# Redistribution and use in source and binary forms, with or without 7# modification, are permitted provided that the following conditions are met: 8# 1. Redistributions of source code must retain the above copyright 9# notice, this list of conditions and the following disclaimer. 10# 2. Redistributions in binary form must reproduce the above copyright 11# notice, this list of conditions and the following disclaimer in the 12# documentation and/or other materials provided with the distribution. 13# 3. Neither the name of the copyright holder nor the 14# names of its contributors may be used to endorse or promote products 15# derived from this software without specific prior written permission. 16# 17# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 18# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 21# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 25# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 27# POSSIBILITY OF SUCH DAMAGE. 28# 29# Description: 30# This script manipulates DHCPv6-PD-REF configuration. 31# 32 33# TODO: set the upstream interface according to the environment variables of `script/setup`. 34UPSTREAM_INTERFACE="eth0" 35 36DHCPCD_ENTER_HOOK="/etc/dhcpcd.enter-hook" 37DHCPCD_EXIT_HOOK="/etc/dhcpcd.exit-hook" 38 39PD_DAEMON_DIR="/opt/pd-daemon" 40PD_DAEMON_PATH="${PD_DAEMON_DIR}/dhcp6_pd_daemon.py" 41PD_DAEMON_SERVICE_NAME="dhcp6_pd_daemon.service" 42PD_DAEMON_SERVICE_PATH="/etc/systemd/system/${PD_DAEMON_SERVICE_NAME}" 43 44DHCP_CONFIG_PATH="/etc/dhcpcd.conf" 45DHCP_CONFIG_ORIG_PATH="/etc/dhcpcd.conf.orig" 46DHCP_CONFIG_PD_PATH="/etc/dhcpcd.conf.pd" 47DHCP_CONFIG_NO_PD_PATH="/etc/dhcpcd.conf.no-pd" 48 49# Create dhcpcd configuration file with ipv6 prefix request. 50create_dhcpcd_conf_pd() 51{ 52 sudo tee ${DHCP_CONFIG_PD_PATH} >/dev/null <<EOF 53noipv6rs # disable router solicitation 54interface ${UPSTREAM_INTERFACE} 55 iaid 1 56 ia_pd 2/::/64 - 57release 58# Disable Router Solicitations (RS) again, specifically for ${UPSTREAM_INTERFACE}. 59# This ensures that accept_ra is prevented from being set to 0, allowing 60# the interface to accepting Router Advertisements and configuring IPv6 61# based on them. The exact reason for requiring 'noipv6rs' twice 62# is not fully understood but has been observed to be necessary through 63# experimentation. 64noipv6rs 65EOF 66} 67 68# Create dhcpcd configuration file with no prefix request. 69create_dhcpcd_conf_no_pd() 70{ 71 sudo tee ${DHCP_CONFIG_NO_PD_PATH} >/dev/null <<EOF 72noipv6rs # disable router solicitation 73EOF 74} 75 76create_dhcp6_pd_daemon_service() 77{ 78 sudo tee ${PD_DAEMON_SERVICE_PATH} <<EOF 79[Unit] 80Description=Daemon to manage dhcpcd based on otbr-agent's PD state change 81ConditionPathExists=${PD_DAEMON_PATH} 82Requires=otbr-agent.service 83After=otbr-agent.service 84 85[Service] 86Type=simple 87User=root 88ExecStart=/usr/bin/python3 ${PD_DAEMON_PATH} 89Restart=on-failure 90 91[Install] 92WantedBy=multi-user.target 93EOF 94} 95 96dhcpv6_pd_ref_uninstall() 97{ 98 with DHCPV6_PD_REF || return 0 99 100 if have systemctl; then 101 sudo systemctl disable ${PD_DAEMON_SERVICE_NAME} || true 102 sudo systemctl stop ${PD_DAEMON_SERVICE_NAME} || true 103 sudo rm -f ${PD_DAEMON_SERVICE_PATH} || true 104 fi 105 106 if [[ -f ${DHCP_CONFIG_ORIG_PATH} ]]; then 107 sudo mv ${DHCP_CONFIG_ORIG_PATH} ${DHCP_CONFIG_PATH} 108 fi 109 110 sudo rm -f ${DHCPCD_ENTER_HOOK} ${DHCPCD_EXIT_HOOK} 111 sudo rm -f ${PD_DAEMON_PATH} 112 113 if have systemctl; then 114 sudo systemctl daemon-reload 115 116 if systemctl is-active dhcpcd; then 117 sudo systemctl restart dhcpcd || true 118 fi 119 fi 120} 121 122dhcpv6_pd_ref_install() 123{ 124 with DHCPV6_PD_REF || return 0 125 126 if [[ -f ${DHCP_CONFIG_PATH} ]]; then 127 sudo mv ${DHCP_CONFIG_PATH} ${DHCP_CONFIG_ORIG_PATH} 128 fi 129 130 # Add dhcpcd.hooks 131 sudo install -m 755 "$(dirname "$0")"/reference-device/dhcpcd.enter-hook ${DHCPCD_ENTER_HOOK} 132 sudo install -m 755 "$(dirname "$0")"/reference-device/dhcpcd.exit-hook ${DHCPCD_EXIT_HOOK} 133 sudo mkdir -p ${PD_DAEMON_DIR} 134 sudo install -m 755 "$(dirname "$0")"/reference-device/dhcp6_pd_daemon.py ${PD_DAEMON_PATH} 135 136 create_dhcpcd_conf_pd 137 create_dhcpcd_conf_no_pd 138 create_dhcp6_pd_daemon_service 139 140 # The dhcp6_pd_daemon is currently disabled because it restarts dhcpcd 141 # when the PD state changes. This restart disrupts mDNS, causing 142 # connectivity issues. The daemon and its associated systemd service 143 # files are still installed for potential future use. 144 # 145 # TODO: Re-enable and start the daemon when a solution is found 146 # for dhcpcd restarts breaking mDNS. 147 # 148 # if have systemctl; then 149 # sudo systemctl daemon-reload 150 # sudo systemctl enable ${PD_DAEMON_SERVICE_NAME} 151 # sudo systemctl start ${PD_DAEMON_SERVICE_NAME} 152 # fi 153 154 # Always enable PD, which is a workaround for the currently disabled 155 # dhcp6_pd_daemon which caused mDNS disruptions. 156 sudo cp ${DHCP_CONFIG_PD_PATH} ${DHCP_CONFIG_PATH} 157 158 if have systemctl; then 159 sudo systemctl daemon-reload 160 161 # Restart dhcpcd only if it's running. This is unnecessary when the dhcp6_pd_daemon 162 # is enabled, as the daemon will handle dhcpcd restarts based on PD state changes. 163 if systemctl is-active dhcpcd; then 164 sudo systemctl restart dhcpcd || true 165 fi 166 167 sudo systemctl enable radvd 168 fi 169} 170