11285115cSWilliam A. Kennington III# Copyright 2021 Google LLC
21285115cSWilliam A. Kennington III#
31285115cSWilliam A. Kennington III# Licensed under the Apache License, Version 2.0 (the "License");
41285115cSWilliam A. Kennington III# you may not use this file except in compliance with the License.
51285115cSWilliam A. Kennington III# You may obtain a copy of the License at
61285115cSWilliam A. Kennington III#
71285115cSWilliam A. Kennington III#      http://www.apache.org/licenses/LICENSE-2.0
81285115cSWilliam A. Kennington III#
91285115cSWilliam A. Kennington III# Unless required by applicable law or agreed to in writing, software
101285115cSWilliam A. Kennington III# distributed under the License is distributed on an "AS IS" BASIS,
111285115cSWilliam A. Kennington III# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
121285115cSWilliam A. Kennington III# See the License for the specific language governing permissions and
131285115cSWilliam A. Kennington III# limitations under the License.
141285115cSWilliam A. Kennington III
151285115cSWilliam A. Kennington III# Internal handler used for signalling child processes that they should
161285115cSWilliam A. Kennington III# terminate.
171285115cSWilliam A. Kennington IIIHandleTerm() {
181285115cSWilliam A. Kennington III  GOT_TERM=1
191285115cSWilliam A. Kennington III  if ShouldTerm && (( ${#CHILD_PIDS[@]} > 0 )); then
201285115cSWilliam A. Kennington III    kill "${!CHILD_PIDS[@]}"
211285115cSWilliam A. Kennington III  fi
221285115cSWilliam A. Kennington III}
231285115cSWilliam A. Kennington III
241285115cSWilliam A. Kennington III# Sets up the signal handler and global variables needed to run interruptible
251285115cSWilliam A. Kennington III# services that can be killed gracefully.
261285115cSWilliam A. Kennington IIIInitTerm() {
271285115cSWilliam A. Kennington III  declare -g -A CHILD_PIDS=()
281285115cSWilliam A. Kennington III  declare -g GOT_TERM=0
291285115cSWilliam A. Kennington III  declare -g SUPPRESS_TERM=0
301285115cSWilliam A. Kennington III  trap HandleTerm TERM
311285115cSWilliam A. Kennington III}
321285115cSWilliam A. Kennington III
331285115cSWilliam A. Kennington III# Used to suppress the handling of SIGTERM for critical components that should
341285115cSWilliam A. Kennington III# not respect SIGTERM. To finish suppressing, use UnsuppressTerm()
351285115cSWilliam A. Kennington IIISuppressTerm() {
361285115cSWilliam A. Kennington III  SUPPRESS_TERM=$((SUPPRESS_TERM + 1))
371285115cSWilliam A. Kennington III}
381285115cSWilliam A. Kennington III
391285115cSWilliam A. Kennington III# Stops suppressing SIGTERM for a single invocation of SuppresssTerm()
401285115cSWilliam A. Kennington IIIUnsuppressTerm() {
411285115cSWilliam A. Kennington III  SUPPRESS_TERM=$((SUPPRESS_TERM - 1))
421285115cSWilliam A. Kennington III}
431285115cSWilliam A. Kennington III
441285115cSWilliam A. Kennington III# Determines if we got a SIGTERM and should respect it
451285115cSWilliam A. Kennington IIIShouldTerm() {
461285115cSWilliam A. Kennington III  (( GOT_TERM == 1 && SUPPRESS_TERM == 0 ))
471285115cSWilliam A. Kennington III}
481285115cSWilliam A. Kennington III
491285115cSWilliam A. Kennington III# Internal, ensures that functions called in a subprocess properly initialize
501285115cSWilliam A. Kennington III# their SIGTERM handling logic
511285115cSWilliam A. Kennington IIIRunInterruptibleFunction() {
521285115cSWilliam A. Kennington III  CHILD_PIDS=()
531285115cSWilliam A. Kennington III  trap HandleTerm TERM
541285115cSWilliam A. Kennington III  "$@"
551285115cSWilliam A. Kennington III}
561285115cSWilliam A. Kennington III
571285115cSWilliam A. Kennington III# Runs the provided commandline in the background, and passes any received
581285115cSWilliam A. Kennington III# SIGTERMS to the child. Can be waited on using WaitInterruptibleBg
591285115cSWilliam A. Kennington IIIRunInterruptibleBg() {
601285115cSWilliam A. Kennington III  if ShouldTerm; then
611285115cSWilliam A. Kennington III    return 143
621285115cSWilliam A. Kennington III  fi
631285115cSWilliam A. Kennington III  if [ "$(type -t "$1")" = "function" ]; then
641285115cSWilliam A. Kennington III    RunInterruptibleFunction "$@" &
651285115cSWilliam A. Kennington III  else
661285115cSWilliam A. Kennington III    "$@" &
671285115cSWilliam A. Kennington III  fi
681285115cSWilliam A. Kennington III  CHILD_PIDS["$!"]=1
691285115cSWilliam A. Kennington III}
701285115cSWilliam A. Kennington III
711285115cSWilliam A. Kennington III# Runs the provided commandline to completion, and passes any received
721285115cSWilliam A. Kennington III# SIGTERMS to the child.
731285115cSWilliam A. Kennington IIIRunInterruptible() {
741285115cSWilliam A. Kennington III  RunInterruptibleBg "$@" || return
751285115cSWilliam A. Kennington III  local child_pid="$!"
761285115cSWilliam A. Kennington III  wait "$child_pid" || true
771285115cSWilliam A. Kennington III  unset CHILD_PIDS["$child_pid"]
781285115cSWilliam A. Kennington III  wait "$child_pid"
791285115cSWilliam A. Kennington III}
801285115cSWilliam A. Kennington III
811285115cSWilliam A. Kennington III# Waits until all of the RunInterruptibleBg() jobs have terminated
821285115cSWilliam A. Kennington IIIWaitInterruptibleBg() {
831285115cSWilliam A. Kennington III  local wait_on=("${!CHILD_PIDS[@]}")
841285115cSWilliam A. Kennington III  if (( ${#wait_on[@]} > 0 )); then
851285115cSWilliam A. Kennington III    wait "${wait_on[@]}" || true
861285115cSWilliam A. Kennington III    CHILD_PIDS=()
871285115cSWilliam A. Kennington III    local rc=0
881285115cSWilliam A. Kennington III    local id
891285115cSWilliam A. Kennington III    for id in "${wait_on[@]}"; do
901285115cSWilliam A. Kennington III      wait "$id" || rc=$?
911285115cSWilliam A. Kennington III    done
921285115cSWilliam A. Kennington III    return $rc
931285115cSWilliam A. Kennington III  fi
941285115cSWilliam A. Kennington III}
951285115cSWilliam A. Kennington III
961285115cSWilliam A. Kennington III# Determines if an address could be a valid IPv4 address
971285115cSWilliam A. Kennington III# NOTE: this doesn't sanitize invalid IPv4 addresses
981285115cSWilliam A. Kennington IIIIsIPv4() {
991285115cSWilliam A. Kennington III  local ip="$1"
1001285115cSWilliam A. Kennington III
1011285115cSWilliam A. Kennington III  [[ "$ip" =~ ^([0-9]{1,3}\.){3}[0-9]{1,3}$ ]]
1021285115cSWilliam A. Kennington III}
1031285115cSWilliam A. Kennington III
1041285115cSWilliam A. Kennington III# Takes lines of text from an application on stdin and parses out a single
1051285115cSWilliam A. Kennington III# MAC address per line of input.
1061285115cSWilliam A. Kennington IIIParseMACFromLine() {
1071285115cSWilliam A. Kennington III  sed -n 's,.*\(\([0-9a-fA-F]\{2\}:\)\{5\}[0-9a-fA-F]\{2\}\).*,\1,p'
1081285115cSWilliam A. Kennington III}
1091285115cSWilliam A. Kennington III
1101285115cSWilliam A. Kennington III# Looks up the MAC address of the IPv4 neighbor using ARP
1111285115cSWilliam A. Kennington IIIDetermineNeighbor4() {
1121285115cSWilliam A. Kennington III  local netdev="$1"
1131285115cSWilliam A. Kennington III  local ip="$2"
1141285115cSWilliam A. Kennington III
1151285115cSWilliam A. Kennington III  # Grep intentionally prevented from returning an error to preserve the error
1161285115cSWilliam A. Kennington III  # value of arping
1171285115cSWilliam A. Kennington III  RunInterruptible arping -f -c 5 -w 5 -I "$netdev" "$ip" | \
1181285115cSWilliam A. Kennington III    { grep 'reply from' || true; } | ParseMACFromLine
1191285115cSWilliam A. Kennington III}
1201285115cSWilliam A. Kennington III
1211285115cSWilliam A. Kennington III# Looks up the MAC address of the IPv6 neighbor using ICMPv6 ND
1221285115cSWilliam A. Kennington IIIDetermineNeighbor6() {
1231285115cSWilliam A. Kennington III  local netdev="$1"
1241285115cSWilliam A. Kennington III  local ip="$2"
1251285115cSWilliam A. Kennington III
1261285115cSWilliam A. Kennington III  RunInterruptible ndisc6 -1 -r 5 -w 1000 -q "$ip" "$netdev"
1271285115cSWilliam A. Kennington III}
1281285115cSWilliam A. Kennington III
1291285115cSWilliam A. Kennington III# Looks up the MAC address of the neighbor regardless of type
1301285115cSWilliam A. Kennington IIIDetermineNeighbor() {
1311285115cSWilliam A. Kennington III  local netdev="$1"
1321285115cSWilliam A. Kennington III  local ip="$2"
1331285115cSWilliam A. Kennington III
1341285115cSWilliam A. Kennington III  if IsIPv4 "$ip"; then
1351285115cSWilliam A. Kennington III    DetermineNeighbor4 "$netdev" "$ip"
1361285115cSWilliam A. Kennington III  else
1371285115cSWilliam A. Kennington III    DetermineNeighbor6 "$netdev" "$ip"
1381285115cSWilliam A. Kennington III  fi
1391285115cSWilliam A. Kennington III}
1401285115cSWilliam A. Kennington III
1411285115cSWilliam A. Kennington III# Performs a mapper call to get the subroot for the object root
1421285115cSWilliam A. Kennington III# with a maxdepth and list of required interfaces. Returns a streamed list
1431285115cSWilliam A. Kennington III# of JSON objects that contain an { object, service }.
1441285115cSWilliam A. Kennington IIIGetSubTree() {
1451285115cSWilliam A. Kennington III  local root="$1"
1461285115cSWilliam A. Kennington III  shift
1471285115cSWilliam A. Kennington III  local max_depth="$1"
1481285115cSWilliam A. Kennington III  shift
1491285115cSWilliam A. Kennington III
1501285115cSWilliam A. Kennington III  busctl --json=short call \
1511285115cSWilliam A. Kennington III      'xyz.openbmc_project.ObjectMapper' \
1521285115cSWilliam A. Kennington III      '/xyz/openbmc_project/object_mapper' \
1531285115cSWilliam A. Kennington III      'xyz.openbmc_project.ObjectMapper' \
1541285115cSWilliam A. Kennington III      'GetSubTree' sias "$root" "$max_depth" "$#" "$@" | \
1551285115cSWilliam A. Kennington III    jq -c '.data[0] | to_entries[] | { object: .key, service: (.value | keys[0]) }'
1561285115cSWilliam A. Kennington III}
1571285115cSWilliam A. Kennington III
1581285115cSWilliam A. Kennington III# Returns all of the properties for a DBus interface on an object as a JSON
1591285115cSWilliam A. Kennington III# object where the keys are the property names
1601285115cSWilliam A. Kennington IIIGetProperties() {
1611285115cSWilliam A. Kennington III  local service="$1"
1621285115cSWilliam A. Kennington III  local object="$2"
1631285115cSWilliam A. Kennington III  local interface="$3"
1641285115cSWilliam A. Kennington III
1651285115cSWilliam A. Kennington III  busctl --json=short call \
1661285115cSWilliam A. Kennington III      "$service" \
1671285115cSWilliam A. Kennington III      "$object" \
1681285115cSWilliam A. Kennington III      'org.freedesktop.DBus.Properties' \
1691285115cSWilliam A. Kennington III      'GetAll' s "$interface" | \
1701285115cSWilliam A. Kennington III    jq -c '.data[0] | with_entries({ key, value: .value.data })'
1711285115cSWilliam A. Kennington III}
1721285115cSWilliam A. Kennington III
1731285115cSWilliam A. Kennington III# Returns the property for a DBus interface on an object
1741285115cSWilliam A. Kennington IIIGetProperty() {
1751285115cSWilliam A. Kennington III  local service="$1"
1761285115cSWilliam A. Kennington III  local object="$2"
1771285115cSWilliam A. Kennington III  local interface="$3"
1781285115cSWilliam A. Kennington III  local property="$4"
1791285115cSWilliam A. Kennington III
1801285115cSWilliam A. Kennington III  busctl --json=short call \
1811285115cSWilliam A. Kennington III      "$service" \
1821285115cSWilliam A. Kennington III      "$object" \
1831285115cSWilliam A. Kennington III      'org.freedesktop.DBus.Properties' \
1841285115cSWilliam A. Kennington III      'Get' ss "$interface" "$property" | \
1851285115cSWilliam A. Kennington III    jq -r '.data[0].data'
1861285115cSWilliam A. Kennington III}
1871285115cSWilliam A. Kennington III
1881285115cSWilliam A. Kennington III# Deletes any OpenBMC DBus object from a service
1891285115cSWilliam A. Kennington IIIDeleteObject() {
1901285115cSWilliam A. Kennington III  local service="$1"
1911285115cSWilliam A. Kennington III  local object="$2"
1921285115cSWilliam A. Kennington III
1931285115cSWilliam A. Kennington III  busctl call \
1941285115cSWilliam A. Kennington III    "$service" \
1951285115cSWilliam A. Kennington III    "$object" \
1961285115cSWilliam A. Kennington III    'xyz.openbmc_project.Object.Delete' \
1971285115cSWilliam A. Kennington III    'Delete'
1981285115cSWilliam A. Kennington III}
1991285115cSWilliam A. Kennington III
2001285115cSWilliam A. Kennington III# Transforms the given JSON dictionary into bash local variable
2011285115cSWilliam A. Kennington III# statements that can be directly evaluated by the interpreter
2021285115cSWilliam A. Kennington IIIJSONToVars() {
2031285115cSWilliam A. Kennington III  jq -r 'to_entries[] | @sh "local \(.key)=\(.value)"'
2041285115cSWilliam A. Kennington III}
2051285115cSWilliam A. Kennington III
2061285115cSWilliam A. Kennington III# Returns the DBus object root for the ethernet interface
2071285115cSWilliam A. Kennington IIIEthObjRoot() {
2081285115cSWilliam A. Kennington III  local netdev="$1"
2091285115cSWilliam A. Kennington III
2101285115cSWilliam A. Kennington III  echo "/xyz/openbmc_project/network/$netdev"
2111285115cSWilliam A. Kennington III}
2121285115cSWilliam A. Kennington III
2131285115cSWilliam A. Kennington III# Returns the DBus object root for the static neighbors of an intrerface
2141285115cSWilliam A. Kennington IIIStaticNeighborObjRoot() {
2151285115cSWilliam A. Kennington III  local netdev="$1"
2161285115cSWilliam A. Kennington III
2171285115cSWilliam A. Kennington III  echo "$(EthObjRoot "$netdev")/static_neighbor"
2181285115cSWilliam A. Kennington III}
2191285115cSWilliam A. Kennington III
2201285115cSWilliam A. Kennington III# Returns all of the neighbor { service, object } data for an interface as if
2211285115cSWilliam A. Kennington III# a call to GetSubTree() was made
2221285115cSWilliam A. Kennington IIIGetNeighborObjects() {
2231285115cSWilliam A. Kennington III  local netdev="$1"
2241285115cSWilliam A. Kennington III
2251285115cSWilliam A. Kennington III  GetSubTree "$(StaticNeighborObjRoot "$netdev")" 0 \
2261285115cSWilliam A. Kennington III    'xyz.openbmc_project.Network.Neighbor'
2271285115cSWilliam A. Kennington III}
2281285115cSWilliam A. Kennington III
2291285115cSWilliam A. Kennington III# Returns the neighbor properties as a JSON object
2301285115cSWilliam A. Kennington IIIGetNeighbor() {
2311285115cSWilliam A. Kennington III  local service="$1"
2321285115cSWilliam A. Kennington III  local object="$2"
2331285115cSWilliam A. Kennington III
2341285115cSWilliam A. Kennington III  GetProperties "$service" "$object" 'xyz.openbmc_project.Network.Neighbor'
2351285115cSWilliam A. Kennington III}
2361285115cSWilliam A. Kennington III
2371285115cSWilliam A. Kennington III# Adds a static neighbor to the system network daemon
2381285115cSWilliam A. Kennington IIIAddNeighbor() {
2391285115cSWilliam A. Kennington III  local service="$1"
2401285115cSWilliam A. Kennington III  local netdev="$2"
2411285115cSWilliam A. Kennington III  local ip="$3"
2421285115cSWilliam A. Kennington III  local mac="$4"
2431285115cSWilliam A. Kennington III
2441285115cSWilliam A. Kennington III  busctl call \
2451285115cSWilliam A. Kennington III    "$service" \
2461285115cSWilliam A. Kennington III    "$(EthObjRoot "$netdev")" \
2471285115cSWilliam A. Kennington III    'xyz.openbmc_project.Network.Neighbor.CreateStatic' \
2481285115cSWilliam A. Kennington III    'Neighbor' ss "$ip" "$mac" >/dev/null
2491285115cSWilliam A. Kennington III}
2501285115cSWilliam A. Kennington III
2511285115cSWilliam A. Kennington III# Returns all of the IP { service, object } data for an interface as if
2521285115cSWilliam A. Kennington III# a call to GetSubTree() was made
2531285115cSWilliam A. Kennington IIIGetIPObjects() {
2541285115cSWilliam A. Kennington III  local netdev="$1"
2551285115cSWilliam A. Kennington III
2561285115cSWilliam A. Kennington III  GetSubTree "$(EthObjRoot "$netdev")" 0 \
2571285115cSWilliam A. Kennington III    'xyz.openbmc_project.Network.IP'
2581285115cSWilliam A. Kennington III}
2591285115cSWilliam A. Kennington III
2601285115cSWilliam A. Kennington III# Returns the IP properties as a JSON object
2611285115cSWilliam A. Kennington IIIGetIP() {
2621285115cSWilliam A. Kennington III  local service="$1"
2631285115cSWilliam A. Kennington III  local object="$2"
2641285115cSWilliam A. Kennington III
2651285115cSWilliam A. Kennington III  GetProperties "$service" "$object" 'xyz.openbmc_project.Network.IP'
2661285115cSWilliam A. Kennington III}
2671285115cSWilliam A. Kennington III
268b163a2c1SWilliam A. Kennington III# Returns the Gateway address for the interface and type
269b163a2c1SWilliam A. Kennington IIIGetGateways() {
270b163a2c1SWilliam A. Kennington III  local service="$1"
271b163a2c1SWilliam A. Kennington III  local netdev="$2"
272b163a2c1SWilliam A. Kennington III
273b163a2c1SWilliam A. Kennington III  # We fetch both the system properties and the netdev specific properties
274b163a2c1SWilliam A. Kennington III  # as OpenBMC is in the process of transitioning these to the netdev object
275b163a2c1SWilliam A. Kennington III  # but the migration is not yet complete.
276b163a2c1SWilliam A. Kennington III  {
277b163a2c1SWilliam A. Kennington III    GetProperties "$service" '/xyz/openbmc_project/network/config' \
278b163a2c1SWilliam A. Kennington III      'xyz.openbmc_project.Network.SystemConfiguration'
279b163a2c1SWilliam A. Kennington III    GetProperties "$service" "$(EthObjRoot "$netdev")" \
280b163a2c1SWilliam A. Kennington III      'xyz.openbmc_project.Network.EthernetInterface'
281b163a2c1SWilliam A. Kennington III  } | jq -s '
282b163a2c1SWilliam A. Kennington III      . | map(
283b163a2c1SWilliam A. Kennington III        if .DefaultGateway != "" then
284b163a2c1SWilliam A. Kennington III          {DefaultGateway: .DefaultGateway}
285b163a2c1SWilliam A. Kennington III        else
286b163a2c1SWilliam A. Kennington III          {}
287b163a2c1SWilliam A. Kennington III        end +
288b163a2c1SWilliam A. Kennington III        if .DefaultGateway6 != "" then
289b163a2c1SWilliam A. Kennington III          {DefaultGateway6: .DefaultGateway6}
290b163a2c1SWilliam A. Kennington III        else
291b163a2c1SWilliam A. Kennington III          {}
292b163a2c1SWilliam A. Kennington III        end
293b163a2c1SWilliam A. Kennington III      ) | {DefaultGateway: "", DefaultGateway6: ""} + add'
294b163a2c1SWilliam A. Kennington III}
295b163a2c1SWilliam A. Kennington III
2961285115cSWilliam A. Kennington III# Adds a static IP to the system network daemon
2971285115cSWilliam A. Kennington IIIAddIP() {
2981285115cSWilliam A. Kennington III  local service="$1"
2991285115cSWilliam A. Kennington III  local netdev="$2"
3001285115cSWilliam A. Kennington III  local ip="$3"
3011285115cSWilliam A. Kennington III  local prefix="$4"
3021285115cSWilliam A. Kennington III
3031285115cSWilliam A. Kennington III  local protocol='xyz.openbmc_project.Network.IP.Protocol.IPv4'
3041285115cSWilliam A. Kennington III  if ! IsIPv4 "$ip"; then
3051285115cSWilliam A. Kennington III    protocol='xyz.openbmc_project.Network.IP.Protocol.IPv6'
3061285115cSWilliam A. Kennington III  fi
3071285115cSWilliam A. Kennington III
3081285115cSWilliam A. Kennington III  busctl call \
3091285115cSWilliam A. Kennington III    "$service" \
3101285115cSWilliam A. Kennington III    "$(EthObjRoot "$netdev")" \
3111285115cSWilliam A. Kennington III    'xyz.openbmc_project.Network.IP.Create' \
3121285115cSWilliam A. Kennington III    'IP' ssys "$protocol" "$ip" "$prefix" '' >/dev/null
3131285115cSWilliam A. Kennington III}
3141285115cSWilliam A. Kennington III
3151285115cSWilliam A. Kennington III# Determines if two IP addresses have the same address family
3161285115cSWilliam A. Kennington III# IE: Both are IPv4 or both are IPv6
3171285115cSWilliam A. Kennington IIIMatchingAF() {
3181285115cSWilliam A. Kennington III  local rc1=0 rc2=0
3191285115cSWilliam A. Kennington III  IsIPv4 "$1" || rc1=$?
3201285115cSWilliam A. Kennington III  IsIPv4 "$2" || rc2=$?
3211285115cSWilliam A. Kennington III  (( rc1 == rc2 ))
3221285115cSWilliam A. Kennington III}
3231285115cSWilliam A. Kennington III
3241285115cSWilliam A. Kennington III# Checks to see if the machine has the provided IP address information
3251285115cSWilliam A. Kennington III# already configured. If not, it deletes all of the information for that
3261285115cSWilliam A. Kennington III# address family and adds the provided IP address.
3271285115cSWilliam A. Kennington IIIUpdateIP() {
3281285115cSWilliam A. Kennington III  local service="$1"
3291285115cSWilliam A. Kennington III  local netdev="$2"
3301285115cSWilliam A. Kennington III  local ip="$3"
3311285115cSWilliam A. Kennington III  local prefix="$4"
3321285115cSWilliam A. Kennington III
3331285115cSWilliam A. Kennington III  local should_add=1
3341285115cSWilliam A. Kennington III  local delete_services=()
3351285115cSWilliam A. Kennington III  local delete_objects=()
3361285115cSWilliam A. Kennington III  local entry
3371285115cSWilliam A. Kennington III  while read entry; do
3381285115cSWilliam A. Kennington III    eval "$(echo "$entry" | JSONToVars)" || return $?
3391285115cSWilliam A. Kennington III    eval "$(GetIP "$service" "$object" | JSONToVars)" || return $?
3401285115cSWilliam A. Kennington III    if [ "$(normalize_ip "$Address")" = "$(normalize_ip "$ip")" ] && \
3411285115cSWilliam A. Kennington III        [ "$PrefixLength" = "$prefix" ]; then
3421285115cSWilliam A. Kennington III      should_add=0
3431285115cSWilliam A. Kennington III    elif MatchingAF "$ip" "$Address"; then
3441285115cSWilliam A. Kennington III      echo "Deleting spurious IP: $Address/$PrefixLength" >&2
3451285115cSWilliam A. Kennington III      delete_services+=("$service")
3461285115cSWilliam A. Kennington III      delete_objects+=("$object")
3471285115cSWilliam A. Kennington III    fi
3481285115cSWilliam A. Kennington III  done < <(GetIPObjects "$netdev")
3491285115cSWilliam A. Kennington III
3501285115cSWilliam A. Kennington III  local i
3511285115cSWilliam A. Kennington III  for (( i=0; i<${#delete_objects[@]}; ++i )); do
3522be0536cSWilliam A. Kennington III    DeleteObject "${delete_services[$i]}" "${delete_objects[$i]}" || true
3531285115cSWilliam A. Kennington III  done
3541285115cSWilliam A. Kennington III
3551285115cSWilliam A. Kennington III  if (( should_add == 0 )); then
3561285115cSWilliam A. Kennington III    echo "Not adding IP: $ip/$prefix" >&2
3571285115cSWilliam A. Kennington III  else
3581285115cSWilliam A. Kennington III    echo "Adding IP: $ip/$prefix" >&2
3591285115cSWilliam A. Kennington III    AddIP "$service" "$netdev" "$ip" "$prefix" || return $?
3601285115cSWilliam A. Kennington III  fi
3611285115cSWilliam A. Kennington III}
3621285115cSWilliam A. Kennington III
3631285115cSWilliam A. Kennington III# Sets the system gateway property to the provided IP address if not already
3641285115cSWilliam A. Kennington III# set to the current value.
3651285115cSWilliam A. Kennington IIIUpdateGateway() {
3661285115cSWilliam A. Kennington III  local service="$1"
3672d6858ddSWilliam A. Kennington III  local netdev="$2"
3682d6858ddSWilliam A. Kennington III  local ip="$3"
3691285115cSWilliam A. Kennington III
3702d6858ddSWilliam A. Kennington III  local object="$(EthObjRoot "$netdev")"
3712d6858ddSWilliam A. Kennington III  local interface='xyz.openbmc_project.Network.EthernetInterface'
3721285115cSWilliam A. Kennington III  local property='DefaultGateway'
3731285115cSWilliam A. Kennington III  if ! IsIPv4 "$ip"; then
3741285115cSWilliam A. Kennington III    property='DefaultGateway6'
3751285115cSWilliam A. Kennington III  fi
3761285115cSWilliam A. Kennington III
3771285115cSWilliam A. Kennington III  local current_ip
3781285115cSWilliam A. Kennington III  current_ip="$(GetProperty "$service" "$object" "$interface" "$property")" || \
3791285115cSWilliam A. Kennington III    return $?
3801285115cSWilliam A. Kennington III  if [ -n "$current_ip" ] && \
3811285115cSWilliam A. Kennington III      [ "$(normalize_ip "$ip")" = "$(normalize_ip "$current_ip")" ]; then
3821285115cSWilliam A. Kennington III    echo "Not reconfiguring gateway: $ip" >&2
3831285115cSWilliam A. Kennington III    return 0
3841285115cSWilliam A. Kennington III  fi
3851285115cSWilliam A. Kennington III
3861285115cSWilliam A. Kennington III  echo "Setting gateway: $ip" >&2
3871285115cSWilliam A. Kennington III  busctl set-property "$service" "$object" "$interface" "$property" s "$ip"
3881285115cSWilliam A. Kennington III}
3891285115cSWilliam A. Kennington III
3901285115cSWilliam A. Kennington III# Checks to see if the machine has the provided neighbor information
3911285115cSWilliam A. Kennington III# already configured. If not, it deletes all of the information for that
3921285115cSWilliam A. Kennington III# address family and adds the provided neighbor entry.
3931285115cSWilliam A. Kennington IIIUpdateNeighbor() {
3941285115cSWilliam A. Kennington III  local service="$1"
3951285115cSWilliam A. Kennington III  local netdev="$2"
3961285115cSWilliam A. Kennington III  local ip="$3"
3971285115cSWilliam A. Kennington III  local mac="$4"
3981285115cSWilliam A. Kennington III
3991285115cSWilliam A. Kennington III  local should_add=1
4001285115cSWilliam A. Kennington III  local delete_services=()
4011285115cSWilliam A. Kennington III  local delete_objects=()
4021285115cSWilliam A. Kennington III  local entry
4031285115cSWilliam A. Kennington III  while read entry; do
4041285115cSWilliam A. Kennington III    eval "$(echo "$entry" | JSONToVars)" || return $?
4051285115cSWilliam A. Kennington III    eval "$(GetNeighbor "$service" "$object" | JSONToVars)" || return $?
4061285115cSWilliam A. Kennington III    if [ "$(normalize_ip "$IPAddress")" = "$(normalize_ip "$ip")" ] && \
4071285115cSWilliam A. Kennington III        [ "$(normalize_mac "$MACAddress")" = "$(normalize_mac "$mac")" ]; then
4081285115cSWilliam A. Kennington III      should_add=0
4091285115cSWilliam A. Kennington III    elif MatchingAF "$ip" "$IPAddress"; then
4101285115cSWilliam A. Kennington III      echo "Deleting spurious neighbor: $IPAddress $MACAddress" >&2
4111285115cSWilliam A. Kennington III      delete_services+=("$service")
4121285115cSWilliam A. Kennington III      delete_objects+=("$object")
4131285115cSWilliam A. Kennington III    fi
4141285115cSWilliam A. Kennington III  done < <(GetNeighborObjects "$netdev" 2>/dev/null)
4151285115cSWilliam A. Kennington III
4161285115cSWilliam A. Kennington III  local i
4171285115cSWilliam A. Kennington III  for (( i=0; i<${#delete_objects[@]}; ++i )); do
4182be0536cSWilliam A. Kennington III    DeleteObject "${delete_services[$i]}" "${delete_objects[$i]}" || true
4191285115cSWilliam A. Kennington III  done
4201285115cSWilliam A. Kennington III
4211285115cSWilliam A. Kennington III  if (( should_add == 0 )); then
4221285115cSWilliam A. Kennington III    echo "Not adding neighbor: $ip $mac" >&2
4231285115cSWilliam A. Kennington III  else
4241285115cSWilliam A. Kennington III    echo "Adding neighbor: $ip $mac" >&2
4251285115cSWilliam A. Kennington III    AddNeighbor "$service" "$netdev" "$ip" "$mac" || return $?
4261285115cSWilliam A. Kennington III  fi
4271285115cSWilliam A. Kennington III}
428b163a2c1SWilliam A. Kennington III
429b163a2c1SWilliam A. Kennington III# Determines the ip and mac of the IPv6 router
430b163a2c1SWilliam A. Kennington IIIDiscoverRouter6() {
431b163a2c1SWilliam A. Kennington III  local netdev="$1"
432b163a2c1SWilliam A. Kennington III  local retries="$2"
433b163a2c1SWilliam A. Kennington III  local timeout="$3"
434b163a2c1SWilliam A. Kennington III  local router="${4-}"
435b163a2c1SWilliam A. Kennington III
436b163a2c1SWilliam A. Kennington III  local output
437b163a2c1SWilliam A. Kennington III  local st=0
438b163a2c1SWilliam A. Kennington III  local args=(-1 -w "$timeout" -n $router "$netdev")
439b163a2c1SWilliam A. Kennington III  if (( retries < 0 )); then
440b163a2c1SWilliam A. Kennington III    args+=(-d)
441b163a2c1SWilliam A. Kennington III  else
442b163a2c1SWilliam A. Kennington III    args+=(-r "$retries")
443b163a2c1SWilliam A. Kennington III  fi
444b163a2c1SWilliam A. Kennington III  output="$(RunInterruptible rdisc6 "${args[@]}")" || st=$?
445b163a2c1SWilliam A. Kennington III  if (( st != 0 )); then
446b163a2c1SWilliam A. Kennington III    echo "rdisc6 failed with: " >&2
447b163a2c1SWilliam A. Kennington III    echo "$output" >&2
448b163a2c1SWilliam A. Kennington III    return $st
449b163a2c1SWilliam A. Kennington III  fi
450b163a2c1SWilliam A. Kennington III
451b163a2c1SWilliam A. Kennington III  local ip="$(echo "$output" | grep 'from' | awk '{print $2}')"
452b163a2c1SWilliam A. Kennington III  local mac="$(echo "$output" | grep 'Source link-layer' | ParseMACFromLine)"
453379b061fSWilliam A. Kennington III  local staddr="$(echo "$output" | grep 'Stateful address conf.*Yes')"
454379b061fSWilliam A. Kennington III  printf '{"router_ip":"%s","router_mac":"%s","stateful_address":"%s"}\n' \
455379b061fSWilliam A. Kennington III    "$ip" "$mac" "$staddr"
456b163a2c1SWilliam A. Kennington III}
457*a7af2e08SWilliam A. Kennington III
458*a7af2e08SWilliam A. Kennington III# Sets the network configuration of an interface to be static
459*a7af2e08SWilliam A. Kennington IIISetStatic() {
460*a7af2e08SWilliam A. Kennington III  local service="$1"
461*a7af2e08SWilliam A. Kennington III  local netdev="$2"
462*a7af2e08SWilliam A. Kennington III
463*a7af2e08SWilliam A. Kennington III  echo "Disabling DHCP" >&2
464*a7af2e08SWilliam A. Kennington III  busctl set-property "$service" "$(EthObjRoot "$netdev")" \
465*a7af2e08SWilliam A. Kennington III    xyz.openbmc_project.Network.EthernetInterface DHCPEnabled \
466*a7af2e08SWilliam A. Kennington III    s xyz.openbmc_project.Network.EthernetInterface.DHCPConf.none
467*a7af2e08SWilliam A. Kennington III}
468