1#!/bin/bash 2# Copyright 2021 Google LLC 3# 4# Licensed under the Apache License, Version 2.0 (the "License"); 5# you may not use this file except in compliance with the License. 6# You may obtain a copy of the License at 7# 8# http://www.apache.org/licenses/LICENSE-2.0 9# 10# Unless required by applicable law or agreed to in writing, software 11# distributed under the License is distributed on an "AS IS" BASIS, 12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13# See the License for the specific language governing permissions and 14# limitations under the License. 15 16[[ -n ${gbmc_br_ula_lib-} ]] && return 17 18# shellcheck source=meta-google/recipes-google/networking/network-sh/lib.sh 19source /usr/share/network/lib.sh || exit 20 21declare -A gbmc_br_ulas=() 22 23# BITs set for address suffixes 24GBMC_BR_ULA_SFX_HAS_LL=1 25GBMC_BR_ULA_SFX_HAS_ULA=2 26 27gbmc_br_ula_cleanup() { 28 local addr 29 for addr in "${!gbmc_br_ulas[@]}"; do 30 local val="${gbmc_br_ulas["$addr"]}" 31 if (( val & GBMC_BR_ULA_SFX_HAS_LL == 0 )); then 32 echo "Removing Stale ULA: $addr" >&2 33 ip addr del "$addr"/64 dev gbmcbr || true 34 fi 35 done 36} 37 38gbmc_br_ula_is_ll() { 39 # shellcheck disable=SC2178 40 local -n bytes="$1" 41 (( bytes[0] == 0xfe && bytes[1] == 0x80 && bytes[2] == 0x00 && 42 bytes[3] == 0x00 && bytes[4] == 0x00 && bytes[5] == 0x00 && 43 bytes[6] == 0x00 && bytes[7] == 0x00 )) 44} 45 46gbmc_br_ula_is_ula() { 47 # shellcheck disable=SC2178 48 local -n bytes="$1" 49 (( bytes[0] == 0xfd && bytes[1] == 0xb5 && bytes[2] == 0x04 && 50 bytes[3] == 0x81 && bytes[4] == 0x10 && bytes[5] == 0xce && 51 bytes[6] == 0x00 && bytes[7] == 0x00 )) 52} 53 54gbmc_br_ula_hook() { 55 # shellcheck disable=SC2154 56 if [[ $change == init ]]; then 57 gbmc_br_ula_cleanup 58 elif [[ $change == addr && $intf == gbmcbr && $fam == inet6 ]]; then 59 local pfx_bytes=() 60 ip_to_bytes pfx_bytes "$ip" || return 61 local val=0 62 if gbmc_br_ula_is_ll pfx_bytes; then 63 val="$GBMC_BR_ULA_SFX_HAS_LL" 64 elif gbmc_br_ula_is_ula pfx_bytes; then 65 val="$GBMC_BR_ULA_SFX_HAS_ULA" 66 else 67 return 0 68 fi 69 # Force all addresses into what they would be as a ULA so that we can 70 # store bits about the assigned addresses on the interface 71 pfx_bytes[0]=0xfd 72 pfx_bytes[1]=0xb5 73 pfx_bytes[2]=0x04 74 pfx_bytes[3]=0x81 75 pfx_bytes[4]=0x10 76 pfx_bytes[5]=0xce 77 addr="$(ip_bytes_to_str pfx_bytes)" 78 local old=${gbmc_br_ulas["$addr"]-0} 79 if [[ $action == add ]]; then 80 val=$((old | val)) 81 elif [[ $action == del ]]; then 82 val=$((old & ~val)) 83 fi 84 gbmc_br_ulas["$addr"]=$val 85 if (( val == GBMC_BR_ULA_SFX_HAS_LL )); then 86 # We have a link local address but no ULA, so we need to add the ULA 87 echo "Adding ULA: $addr" >&2 88 ip addr replace "$addr"/64 dev gbmcbr 89 elif (( val == GBMC_BR_ULA_SFX_HAS_ULA )); then 90 # We have a ULA without a link local, so we should not longer have this ULA 91 echo "Removing ULA: $addr" >&2 92 ip addr del "$addr"/64 dev gbmcbr || true 93 elif (( val == 0 )); then 94 # Cleanup the map if we no longer have any addresses for the suffix 95 unset 'gbmc_br_ulas[$addr]' 96 fi 97 fi 98} 99 100GBMC_IP_MONITOR_HOOKS+=(gbmc_br_ula_hook) 101 102gbmc_br_ula_lib=1 103