blob: 76bd0e91e6af5ca246bbabcae5320e64fb91ce62 [file] [edit]
#!/bin/bash
#
# Copyright (c) 2024, 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.
#
# Description:
# This script manipulates DHCPv6-PD-REF configuration.
#
# TODO: set the upstream interface according to the environment variables of `script/setup`.
UPSTREAM_INTERFACE="eth0"
WPAN_INTERFACE="wpan0"
LARGE_METRIC="2048" # A high metric value for loopback to make its routes less preferred.
DHCPCD_ENTER_HOOK="/etc/dhcpcd.enter-hook"
DHCPCD_EXIT_HOOK="/etc/dhcpcd.exit-hook"
PD_DAEMON_DIR="/opt/pd-daemon"
PD_DAEMON_PATH="${PD_DAEMON_DIR}/dhcp6_pd_daemon.py"
PD_DAEMON_SERVICE_NAME="dhcp6_pd_daemon.service"
PD_DAEMON_SERVICE_PATH="/etc/systemd/system/${PD_DAEMON_SERVICE_NAME}"
DHCP_CONFIG_PATH="/etc/dhcpcd.conf"
DHCP_CONFIG_ORIG_PATH="/etc/dhcpcd.conf.orig"
DHCP_CONFIG_PD_PATH="/etc/dhcpcd.conf.pd"
DHCP_CONFIG_NO_PD_PATH="/etc/dhcpcd.conf.no-pd"
# Create dhcpcd configuration file with ipv6 prefix request.
create_dhcpcd_conf_pd()
{
sudo tee ${DHCP_CONFIG_PD_PATH} >/dev/null <<EOF
noipv6rs # disable router solicitation
# The 'interface lo' block with a high 'metric' value ensures that dhcpcd's
# default reject route for unassigned delegated prefixes on loopback interface,
# are less preferred.
# OpenThread will later install an active route for the delegated prefix on
# ${WPAN_INTERFACE} with a standard (lower) metric, ensuring it takes precedence.
interface lo
metric ${LARGE_METRIC}
interface ${UPSTREAM_INTERFACE}
iaid 1
ia_pd 2/::/64
release
# Disable Router Solicitations (RS) again, specifically for ${UPSTREAM_INTERFACE}.
# This ensures that accept_ra is prevented from being set to 0, allowing
# the interface to accepting Router Advertisements and configuring IPv6
# based on them. The exact reason for requiring 'noipv6rs' twice
# is not fully understood but has been observed to be necessary through
# experimentation.
noipv6rs
EOF
}
# Create dhcpcd configuration file with no prefix request.
create_dhcpcd_conf_no_pd()
{
sudo tee ${DHCP_CONFIG_NO_PD_PATH} >/dev/null <<EOF
noipv6rs # disable router solicitation
EOF
}
create_dhcp6_pd_daemon_service()
{
sudo tee ${PD_DAEMON_SERVICE_PATH} <<EOF
[Unit]
Description=Daemon to manage dhcpcd based on otbr-agent's PD state change
ConditionPathExists=${PD_DAEMON_PATH}
Requires=otbr-agent.service
After=otbr-agent.service
[Service]
Type=simple
User=root
ExecStart=/usr/bin/python3 ${PD_DAEMON_PATH}
Restart=on-failure
[Install]
WantedBy=multi-user.target
EOF
}
dhcpcd_uninstall()
{
[[ ${OTBR_DHCP6_PD_CLIENT} == "dhcpcd" ]] || return 0
if have systemctl; then
sudo systemctl disable ${PD_DAEMON_SERVICE_NAME} || true
sudo systemctl stop ${PD_DAEMON_SERVICE_NAME} || true
sudo rm -f ${PD_DAEMON_SERVICE_PATH} || true
fi
if [[ -f ${DHCP_CONFIG_ORIG_PATH} ]]; then
sudo mv ${DHCP_CONFIG_ORIG_PATH} ${DHCP_CONFIG_PATH}
fi
sudo rm -f ${DHCPCD_ENTER_HOOK} ${DHCPCD_EXIT_HOOK}
sudo rm -f ${PD_DAEMON_PATH}
if have systemctl; then
sudo systemctl daemon-reload
if systemctl is-active dhcpcd; then
sudo systemctl restart dhcpcd || true
fi
fi
}
dhcpcd_install()
{
[[ ${OTBR_DHCP6_PD_CLIENT} == "dhcpcd" ]] || return 0
if [[ -f ${DHCP_CONFIG_PATH} ]]; then
sudo mv ${DHCP_CONFIG_PATH} ${DHCP_CONFIG_ORIG_PATH}
fi
# Add dhcpcd.hooks
sudo install -m 755 "$(dirname "$0")"/reference-device/dhcpcd.enter-hook ${DHCPCD_ENTER_HOOK}
sudo install -m 755 "$(dirname "$0")"/reference-device/dhcpcd.exit-hook ${DHCPCD_EXIT_HOOK}
sudo mkdir -p ${PD_DAEMON_DIR}
sudo install -m 755 "$(dirname "$0")"/reference-device/dhcp6_pd_daemon.py ${PD_DAEMON_PATH}
create_dhcpcd_conf_pd
create_dhcpcd_conf_no_pd
create_dhcp6_pd_daemon_service
# The dhcp6_pd_daemon is currently disabled because it restarts dhcpcd
# when the PD state changes. This restart disrupts mDNS, causing
# connectivity issues. The daemon and its associated systemd service
# files are still installed for potential future use.
#
# TODO: Re-enable and start the daemon when a solution is found
# for dhcpcd restarts breaking mDNS.
#
# if have systemctl; then
# sudo systemctl daemon-reload
# sudo systemctl enable ${PD_DAEMON_SERVICE_NAME}
# sudo systemctl start ${PD_DAEMON_SERVICE_NAME}
# fi
# Always enable PD, which is a workaround for the currently disabled
# dhcp6_pd_daemon which caused mDNS disruptions.
sudo cp ${DHCP_CONFIG_PD_PATH} ${DHCP_CONFIG_PATH}
if have systemctl; then
sudo systemctl daemon-reload
# Restart dhcpcd only if it's running. This is unnecessary when the dhcp6_pd_daemon
# is enabled, as the daemon will handle dhcpcd restarts based on PD state changes.
if systemctl is-active dhcpcd; then
sudo systemctl restart dhcpcd || true
fi
sudo systemctl enable radvd
fi
}