blob: b79e25fe4ac80f0e02d65735dfd60244fa842688 [file] [log] [blame]
#!/bin/bash
# Copyright 2021 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
[[ -n ${gbmc_br_ula_lib-} ]] && return
# shellcheck source=meta-google/recipes-google/networking/network-sh/lib.sh
source /usr/share/network/lib.sh || exit
declare -A gbmc_br_ulas=()
# BITs set for address suffixes
GBMC_BR_ULA_SFX_HAS_LL=1
GBMC_BR_ULA_SFX_HAS_ULA=2
gbmc_br_ula_cleanup() {
local addr
for addr in "${!gbmc_br_ulas[@]}"; do
local val="${gbmc_br_ulas["$addr"]}"
if (( val & GBMC_BR_ULA_SFX_HAS_LL == 0 )); then
echo "Removing Stale ULA: $addr" >&2
ip addr del "$addr"/64 dev gbmcbr || true
fi
done
}
gbmc_br_ula_is_ll() {
# shellcheck disable=SC2178
local -n bytes="$1"
(( bytes[0] == 0xfe && bytes[1] == 0x80 && bytes[2] == 0x00 &&
bytes[3] == 0x00 && bytes[4] == 0x00 && bytes[5] == 0x00 &&
bytes[6] == 0x00 && bytes[7] == 0x00 ))
}
gbmc_br_ula_is_ula() {
# shellcheck disable=SC2178
local -n bytes="$1"
(( bytes[0] == 0xfd && bytes[1] == 0xb5 && bytes[2] == 0x04 &&
bytes[3] == 0x81 && bytes[4] == 0x10 && bytes[5] == 0xce &&
bytes[6] == 0x00 && bytes[7] == 0x00 ))
}
gbmc_br_ula_hook() {
# shellcheck disable=SC2154
if [[ $change == init ]]; then
gbmc_br_ula_cleanup
elif [[ $change == addr && $intf == gbmcbr && $fam == inet6 ]]; then
local pfx_bytes=()
ip_to_bytes pfx_bytes "$ip" || return
local val=0
if gbmc_br_ula_is_ll pfx_bytes; then
val="$GBMC_BR_ULA_SFX_HAS_LL"
elif gbmc_br_ula_is_ula pfx_bytes; then
val="$GBMC_BR_ULA_SFX_HAS_ULA"
else
return 0
fi
# Force all addresses into what they would be as a ULA so that we can
# store bits about the assigned addresses on the interface
pfx_bytes[0]=0xfd
pfx_bytes[1]=0xb5
pfx_bytes[2]=0x04
pfx_bytes[3]=0x81
pfx_bytes[4]=0x10
pfx_bytes[5]=0xce
addr="$(ip_bytes_to_str pfx_bytes)"
local old=${gbmc_br_ulas["$addr"]-0}
if [[ $action == add ]]; then
val=$((old | val))
elif [[ $action == del ]]; then
val=$((old & ~val))
fi
gbmc_br_ulas["$addr"]=$val
if (( val == GBMC_BR_ULA_SFX_HAS_LL )); then
# We have a link local address but no ULA, so we need to add the ULA
echo "Adding ULA: $addr" >&2
ip addr replace "$addr"/64 dev gbmcbr
elif (( val == GBMC_BR_ULA_SFX_HAS_ULA )); then
# We have a ULA without a link local, so we should not longer have this ULA
echo "Removing ULA: $addr" >&2
ip addr del "$addr"/64 dev gbmcbr || true
elif (( val == 0 )); then
# Cleanup the map if we no longer have any addresses for the suffix
unset 'gbmc_br_ulas[$addr]'
fi
fi
}
GBMC_IP_MONITOR_HOOKS+=(gbmc_br_ula_hook)
gbmc_br_ula_lib=1