• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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