blob: 5f3f47feddd6808d9f95d25aec608adbdf489e4c [file] [log] [blame]
William A. Kennington III031f6a62024-09-05 02:22:15 -07001#!/bin/bash
2# Copyright 2024 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_nic_neigh_lib-} ]] && return
17
18# shellcheck source=meta-google/recipes-google/networking/network-sh/lib.sh
19source /usr/share/network/lib.sh || exit
20
21gbmc_nic_neigh_intfs=(@IFS@)
22gbmc_nic_neigh_addr=
23
24gbmc_nic_neigh_set() {
25 local act="$1"
26 local ip="$2"
27
28 echo "gBMC NIC Neigh $act $ip: ${gbmc_nic_neigh_intfs[*]}" >&2
29
30 local intf
31 local failed_intfs=()
32 for intf in "${gbmc_nic_neigh_intfs[@]}"; do
33 # In case we don't have a base network file, make one
34 # this is intentionally 00- as it will not preceed /etc/systemd/network/00-*
35 # or /lib/systemd/network/-* files.
36 local file=/run/systemd/network/00-bmc-$intf.network
37 printf '[Match]\nName=%s\n[Network]\nDHCP=false\nIPv6AcceptRA=false\nLinkLocalAddressing=yes' \
38 "$intf" >"$file"
39
40 # Override any existing gateway information within files
41 # Make sure we cover `00-*` and `-*` files
42 for file in /run/systemd/network/{00,}-bmc-"$intf".network; do
43 mkdir -p "$file.d"
44 if [[ "$act" == add ]]; then
45 printf '[Network]\nIPv6ProxyNDP=yes\nIPv6ProxyNDPAddress=%s\n' \
46 "$ip" >"$file.d"/10-nic-neigh.conf
47 else
48 rm -f "$file.d"/10-nic-neigh.conf
49 fi
50 done
51
52 sysctl net.ipv6.conf."$intf".proxy_ndp=1 >/dev/null && \
53 ip -6 neigh "$act" proxy "$ip" dev "$intf" || \
54 failed_intfs+=("$intf")
55 done
56 [[ "$act" == del ]] && return
57 if (( "${#failed_intfs[@]}" > 0 )); then
58 networkctl reload || true
59 fi
60 for intf in "${failed_intfs[@]}"; do
61 networkctl reconfigure "$intf" || true
62 done
63}
64
65gbmc_nic_neigh_hook() {
66 # shellcheck disable=SC2154
67 if [[ $change == addr && $intf == gbmcbr && $scope == global ]] &&
68 [[ $fam == inet6 && $flags != *tentative* ]]; then
69 local ip_bytes=()
70 if ! ip_to_bytes ip_bytes "$ip"; then
71 echo "gBMC Bridge Ensure RA Invalid IP: $ip" >&2
72 return 1
73 fi
74 # Ignore ULAs
75 if (( (ip_bytes[0] & 0xfe) == 0xfc )); then
76 return 0
77 fi
78 # Addresses must be /64 to the upstack switch
79 for (( i = 8; i < 16; ++i )); do
80 if (( ip_bytes[i] != 0 )); then
81 return 0
82 fi
83 done
84 if [[ $action == add && "$gbmc_nic_neigh_addr" != "$ip" ]]; then
85 if [ -n "$gbmc_nic_neigh_addr" ]; then
86 gbmc_nic_neigh_set del "$gbmc_nic_neigh_addr"
87 fi
88 gbmc_nic_neigh_addr="$ip"
89 gbmc_nic_neigh_set add "$ip"
90 elif [[ $action == del && "$gbmc_nic_neigh_addr" == "$ip" ]]; then
91 gbmc_nic_neigh_addr=
92 gbmc_nic_neigh_set del "$ip"
93 fi
94 fi
95}
96
97GBMC_IP_MONITOR_HOOKS+=(gbmc_nic_neigh_hook)
98
99gbmc_nic_neigh_lib=1