| #!/bin/bash |
| # Copyright 2024 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_nic_neigh_lib-} ]] && return |
| |
| # shellcheck source=meta-google/recipes-google/networking/network-sh/lib.sh |
| source /usr/share/network/lib.sh || exit |
| # shellcheck source=meta-google/recipes-google/networking/gbmc-net-common/gbmc-net-lib.sh |
| source /usr/share/gbmc-net-lib.sh || exit |
| |
| gbmc_nic_neigh_intfs=(@IFS@) |
| gbmc_nic_neigh_addr= |
| |
| gbmc_nic_neigh_set() { |
| local act="$1" |
| local ip="$2" |
| |
| echo "gBMC NIC Neigh $act $ip: ${gbmc_nic_neigh_intfs[*]}" >&2 |
| |
| local intf |
| local failed_intfs=() |
| for intf in "${gbmc_nic_neigh_intfs[@]}"; do |
| # In case we don't have a base network file, make one |
| # this is intentionally 00- as it will not preceed /etc/systemd/network/00-* |
| # or /lib/systemd/network/-* files. |
| local file=/run/systemd/network/00-bmc-$intf.network |
| printf '[Match]\nName=%s\n[Network]\nDHCP=false\nIPv6AcceptRA=false\nLinkLocalAddressing=yes' \ |
| "$intf" >"$file" |
| |
| # Override any existing gateway information within files |
| # Make sure we cover `00-*` and `-*` files |
| for file in /run/systemd/network/{00,}-bmc-"$intf".network; do |
| mkdir -p "$file.d" |
| if [[ "$act" == add ]]; then |
| printf '[Network]\nIPv6ProxyNDP=yes\nIPv6ProxyNDPAddress=%s\n' \ |
| "$ip" >"$file.d"/10-nic-neigh.conf |
| else |
| rm -f "$file.d"/10-nic-neigh.conf |
| fi |
| done |
| |
| sysctl net.ipv6.conf."$intf".proxy_ndp=1 >/dev/null && \ |
| ip -6 neigh "$act" proxy "$ip" dev "$intf" || \ |
| failed_intfs+=("$intf") |
| done |
| [[ "$act" == del ]] && return |
| if (( "${#failed_intfs[@]}" > 0 )); then |
| gbmc_net_networkd_reload "${failed_intfs[@]}" |
| fi |
| } |
| |
| gbmc_nic_neigh_hook() { |
| # shellcheck disable=SC2154 |
| if [[ $change == addr && $intf == gbmcbr && $scope == global ]] && |
| [[ $fam == inet6 && $flags != *tentative* ]]; then |
| local ip_bytes=() |
| if ! ip_to_bytes ip_bytes "$ip"; then |
| echo "gBMC Bridge Ensure RA Invalid IP: $ip" >&2 |
| return 1 |
| fi |
| # Ignore ULAs |
| if (( (ip_bytes[0] & 0xfe) == 0xfc )); then |
| return 0 |
| fi |
| # Addresses must be /64 to the upstack switch |
| for (( i = 8; i < 16; ++i )); do |
| if (( ip_bytes[i] != 0 )); then |
| return 0 |
| fi |
| done |
| if [[ $action == add && "$gbmc_nic_neigh_addr" != "$ip" ]]; then |
| if [ -n "$gbmc_nic_neigh_addr" ]; then |
| gbmc_nic_neigh_set del "$gbmc_nic_neigh_addr" |
| fi |
| gbmc_nic_neigh_addr="$ip" |
| gbmc_nic_neigh_set add "$ip" |
| elif [[ $action == del && "$gbmc_nic_neigh_addr" == "$ip" ]]; then |
| gbmc_nic_neigh_addr= |
| gbmc_nic_neigh_set del "$ip" |
| fi |
| fi |
| } |
| |
| GBMC_IP_MONITOR_HOOKS+=(gbmc_nic_neigh_hook) |
| |
| gbmc_nic_neigh_lib=1 |