15d074370SPatrick Williams#!/bin/bash
21285115cSWilliam A. Kennington III# Copyright 2021 Google LLC
31285115cSWilliam A. Kennington III#
41285115cSWilliam A. Kennington III# Licensed under the Apache License, Version 2.0 (the "License");
51285115cSWilliam A. Kennington III# you may not use this file except in compliance with the License.
61285115cSWilliam A. Kennington III# You may obtain a copy of the License at
71285115cSWilliam A. Kennington III#
81285115cSWilliam A. Kennington III#      http://www.apache.org/licenses/LICENSE-2.0
91285115cSWilliam A. Kennington III#
101285115cSWilliam A. Kennington III# Unless required by applicable law or agreed to in writing, software
111285115cSWilliam A. Kennington III# distributed under the License is distributed on an "AS IS" BASIS,
121285115cSWilliam A. Kennington III# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
131285115cSWilliam A. Kennington III# See the License for the specific language governing permissions and
141285115cSWilliam A. Kennington III# limitations under the License.
151285115cSWilliam A. Kennington III
161285115cSWilliam A. Kennington III# Internal handler used for signalling child processes that they should
171285115cSWilliam A. Kennington III# terminate.
1859486679SPatrick Williamsfunction HandleTerm() {
191285115cSWilliam A. Kennington III    GOT_TERM=1
201285115cSWilliam A. Kennington III    if ShouldTerm && (( ${#CHILD_PIDS[@]} > 0 )); then
21d7989581SWilliam A. Kennington III        kill -s TERM "${!CHILD_PIDS[@]}"
221285115cSWilliam A. Kennington III    fi
231285115cSWilliam A. Kennington III}
241285115cSWilliam A. Kennington III
251285115cSWilliam A. Kennington III# Sets up the signal handler and global variables needed to run interruptible
261285115cSWilliam A. Kennington III# services that can be killed gracefully.
2759486679SPatrick Williamsfunction InitTerm() {
281285115cSWilliam A. Kennington III    declare -g -A CHILD_PIDS=()
291285115cSWilliam A. Kennington III    declare -g GOT_TERM=0
301285115cSWilliam A. Kennington III    declare -g SUPPRESS_TERM=0
311285115cSWilliam A. Kennington III    trap HandleTerm TERM
321285115cSWilliam A. Kennington III}
331285115cSWilliam A. Kennington III
341285115cSWilliam A. Kennington III# Used to suppress the handling of SIGTERM for critical components that should
351285115cSWilliam A. Kennington III# not respect SIGTERM. To finish suppressing, use UnsuppressTerm()
3659486679SPatrick Williamsfunction SuppressTerm() {
371285115cSWilliam A. Kennington III    SUPPRESS_TERM=$((SUPPRESS_TERM + 1))
381285115cSWilliam A. Kennington III}
391285115cSWilliam A. Kennington III
401285115cSWilliam A. Kennington III# Stops suppressing SIGTERM for a single invocation of SuppresssTerm()
4159486679SPatrick Williamsfunction UnsuppressTerm() {
421285115cSWilliam A. Kennington III    SUPPRESS_TERM=$((SUPPRESS_TERM - 1))
431285115cSWilliam A. Kennington III}
441285115cSWilliam A. Kennington III
451285115cSWilliam A. Kennington III# Determines if we got a SIGTERM and should respect it
4659486679SPatrick Williamsfunction ShouldTerm() {
471285115cSWilliam A. Kennington III    (( GOT_TERM == 1 && SUPPRESS_TERM == 0 ))
481285115cSWilliam A. Kennington III}
491285115cSWilliam A. Kennington III
501285115cSWilliam A. Kennington III# Internal, ensures that functions called in a subprocess properly initialize
511285115cSWilliam A. Kennington III# their SIGTERM handling logic
5259486679SPatrick Williamsfunction RunInterruptibleFunction() {
531285115cSWilliam A. Kennington III    CHILD_PIDS=()
541285115cSWilliam A. Kennington III    trap HandleTerm TERM
551285115cSWilliam A. Kennington III    "$@"
561285115cSWilliam A. Kennington III}
571285115cSWilliam A. Kennington III
581285115cSWilliam A. Kennington III# Runs the provided commandline in the background, and passes any received
591285115cSWilliam A. Kennington III# SIGTERMS to the child. Can be waited on using WaitInterruptibleBg
6059486679SPatrick Williamsfunction RunInterruptibleBg() {
611285115cSWilliam A. Kennington III    if ShouldTerm; then
621285115cSWilliam A. Kennington III        return 143
631285115cSWilliam A. Kennington III    fi
641285115cSWilliam A. Kennington III    if [ "$(type -t "$1")" = "function" ]; then
651285115cSWilliam A. Kennington III        RunInterruptibleFunction "$@" &
661285115cSWilliam A. Kennington III    else
671285115cSWilliam A. Kennington III        "$@" &
681285115cSWilliam A. Kennington III    fi
691285115cSWilliam A. Kennington III    CHILD_PIDS["$!"]=1
701285115cSWilliam A. Kennington III}
711285115cSWilliam A. Kennington III
721285115cSWilliam A. Kennington III# Runs the provided commandline to completion, and passes any received
731285115cSWilliam A. Kennington III# SIGTERMS to the child.
7459486679SPatrick Williamsfunction RunInterruptible() {
751285115cSWilliam A. Kennington III    RunInterruptibleBg "$@" || return
761285115cSWilliam A. Kennington III    local child_pid="$!"
771285115cSWilliam A. Kennington III    wait "$child_pid" || true
781285115cSWilliam A. Kennington III    unset CHILD_PIDS["$child_pid"]
791285115cSWilliam A. Kennington III    wait "$child_pid"
801285115cSWilliam A. Kennington III}
811285115cSWilliam A. Kennington III
821285115cSWilliam A. Kennington III# Waits until all of the RunInterruptibleBg() jobs have terminated
8359486679SPatrick Williamsfunction WaitInterruptibleBg() {
841285115cSWilliam A. Kennington III    local wait_on=("${!CHILD_PIDS[@]}")
851285115cSWilliam A. Kennington III    if (( ${#wait_on[@]} > 0 )); then
861285115cSWilliam A. Kennington III        wait "${wait_on[@]}" || true
871285115cSWilliam A. Kennington III        CHILD_PIDS=()
881285115cSWilliam A. Kennington III        local rc=0
891285115cSWilliam A. Kennington III        local id
901285115cSWilliam A. Kennington III        for id in "${wait_on[@]}"; do
911285115cSWilliam A. Kennington III            wait "$id" || rc=$?
921285115cSWilliam A. Kennington III        done
931285115cSWilliam A. Kennington III        return $rc
941285115cSWilliam A. Kennington III    fi
951285115cSWilliam A. Kennington III}
961285115cSWilliam A. Kennington III
97d7989581SWilliam A. Kennington III# Runs the provided commandline to completion, capturing stdout
98d7989581SWilliam A. Kennington III# into a variable
9959486679SPatrick Williamsfunction CaptureInterruptible() {
100d7989581SWilliam A. Kennington III    local var="$1"
101d7989581SWilliam A. Kennington III    shift
102d7989581SWilliam A. Kennington III    if ShouldTerm; then
103d7989581SWilliam A. Kennington III        return 143
104d7989581SWilliam A. Kennington III    fi
105d7989581SWilliam A. Kennington III    coproc "$@" || return
106d7989581SWilliam A. Kennington III    local child_pid="$COPROC_PID"
107d7989581SWilliam A. Kennington III    CHILD_PIDS["$child_pid"]=1
108d7989581SWilliam A. Kennington III    exec {COPROC[1]}>&-
109d7989581SWilliam A. Kennington III    read -d $'\0' -ru "${COPROC[0]}" "$var" || true
110d7989581SWilliam A. Kennington III    wait "$child_pid" || true
111d7989581SWilliam A. Kennington III    unset CHILD_PIDS[$child_pid]
112d7989581SWilliam A. Kennington III    wait "$child_pid"
113d7989581SWilliam A. Kennington III}
114d7989581SWilliam A. Kennington III
1151285115cSWilliam A. Kennington III# Determines if an address could be a valid IPv4 address
1161285115cSWilliam A. Kennington III# NOTE: this doesn't sanitize invalid IPv4 addresses
11759486679SPatrick Williamsfunction IsIPv4() {
1181285115cSWilliam A. Kennington III    local ip="$1"
1191285115cSWilliam A. Kennington III
1201285115cSWilliam A. Kennington III    [[ "$ip" =~ ^([0-9]{1,3}\.){3}[0-9]{1,3}$ ]]
1211285115cSWilliam A. Kennington III}
1221285115cSWilliam A. Kennington III
1231285115cSWilliam A. Kennington III# Takes lines of text from an application on stdin and parses out a single
1241285115cSWilliam A. Kennington III# MAC address per line of input.
12559486679SPatrick Williamsfunction ParseMACFromLine() {
1261285115cSWilliam A. Kennington III    sed -n 's,.*\(\([0-9a-fA-F]\{2\}:\)\{5\}[0-9a-fA-F]\{2\}\).*,\1,p'
1271285115cSWilliam A. Kennington III}
1281285115cSWilliam A. Kennington III
1291285115cSWilliam A. Kennington III# Looks up the MAC address of the IPv4 neighbor using ARP
13059486679SPatrick Williamsfunction DetermineNeighbor4() {
1311285115cSWilliam A. Kennington III    local netdev="$1"
1321285115cSWilliam A. Kennington III    local ip="$2"
1331285115cSWilliam A. Kennington III
1341285115cSWilliam A. Kennington III    # Grep intentionally prevented from returning an error to preserve the error
1351285115cSWilliam A. Kennington III    # value of arping
1361285115cSWilliam A. Kennington III    RunInterruptible arping -f -c 5 -w 5 -I "$netdev" "$ip" | \
1371285115cSWilliam A. Kennington III        { grep 'reply from' || true; } | ParseMACFromLine
1381285115cSWilliam A. Kennington III}
1391285115cSWilliam A. Kennington III
1401285115cSWilliam A. Kennington III# Looks up the MAC address of the IPv6 neighbor using ICMPv6 ND
14159486679SPatrick Williamsfunction DetermineNeighbor6() {
1421285115cSWilliam A. Kennington III    local netdev="$1"
1431285115cSWilliam A. Kennington III    local ip="$2"
1441285115cSWilliam A. Kennington III
1451285115cSWilliam A. Kennington III    RunInterruptible ndisc6 -1 -r 5 -w 1000 -q "$ip" "$netdev"
1461285115cSWilliam A. Kennington III}
1471285115cSWilliam A. Kennington III
1481285115cSWilliam A. Kennington III# Looks up the MAC address of the neighbor regardless of type
14959486679SPatrick Williamsfunction DetermineNeighbor() {
1501285115cSWilliam A. Kennington III    local netdev="$1"
1511285115cSWilliam A. Kennington III    local ip="$2"
1521285115cSWilliam A. Kennington III
1531285115cSWilliam A. Kennington III    if IsIPv4 "$ip"; then
1541285115cSWilliam A. Kennington III        DetermineNeighbor4 "$netdev" "$ip"
1551285115cSWilliam A. Kennington III    else
1561285115cSWilliam A. Kennington III        DetermineNeighbor6 "$netdev" "$ip"
1571285115cSWilliam A. Kennington III    fi
1581285115cSWilliam A. Kennington III}
1591285115cSWilliam A. Kennington III
1601285115cSWilliam A. Kennington III# Performs a mapper call to get the subroot for the object root
1611285115cSWilliam A. Kennington III# with a maxdepth and list of required interfaces. Returns a streamed list
1621285115cSWilliam A. Kennington III# of JSON objects that contain an { object, service }.
16359486679SPatrick Williamsfunction GetSubTree() {
1641285115cSWilliam A. Kennington III    local root="$1"
1651285115cSWilliam A. Kennington III    shift
1661285115cSWilliam A. Kennington III    local max_depth="$1"
1671285115cSWilliam A. Kennington III    shift
1681285115cSWilliam A. Kennington III
1691285115cSWilliam A. Kennington III    busctl --json=short call \
1701285115cSWilliam A. Kennington III        'xyz.openbmc_project.ObjectMapper' \
1711285115cSWilliam A. Kennington III        '/xyz/openbmc_project/object_mapper' \
1721285115cSWilliam A. Kennington III        'xyz.openbmc_project.ObjectMapper' \
1731285115cSWilliam A. Kennington III        'GetSubTree' sias "$root" "$max_depth" "$#" "$@" | \
1741285115cSWilliam A. Kennington III        jq -c '.data[0] | to_entries[] | { object: .key, service: (.value | keys[0]) }'
1751285115cSWilliam A. Kennington III}
1761285115cSWilliam A. Kennington III
1771285115cSWilliam A. Kennington III# Returns all of the properties for a DBus interface on an object as a JSON
1781285115cSWilliam A. Kennington III# object where the keys are the property names
17959486679SPatrick Williamsfunction GetProperties() {
1801285115cSWilliam A. Kennington III    local service="$1"
1811285115cSWilliam A. Kennington III    local object="$2"
1821285115cSWilliam A. Kennington III    local interface="$3"
1831285115cSWilliam A. Kennington III
1841285115cSWilliam A. Kennington III    busctl --json=short call \
1851285115cSWilliam A. Kennington III        "$service" \
1861285115cSWilliam A. Kennington III        "$object" \
1871285115cSWilliam A. Kennington III        'org.freedesktop.DBus.Properties' \
1881285115cSWilliam A. Kennington III        'GetAll' s "$interface" | \
1891285115cSWilliam A. Kennington III        jq -c '.data[0] | with_entries({ key, value: .value.data })'
1901285115cSWilliam A. Kennington III}
1911285115cSWilliam A. Kennington III
1921285115cSWilliam A. Kennington III# Returns the property for a DBus interface on an object
19359486679SPatrick Williamsfunction GetProperty() {
1941285115cSWilliam A. Kennington III    local service="$1"
1951285115cSWilliam A. Kennington III    local object="$2"
1961285115cSWilliam A. Kennington III    local interface="$3"
1971285115cSWilliam A. Kennington III    local property="$4"
1981285115cSWilliam A. Kennington III
1991285115cSWilliam A. Kennington III    busctl --json=short call \
2001285115cSWilliam A. Kennington III        "$service" \
2011285115cSWilliam A. Kennington III        "$object" \
2021285115cSWilliam A. Kennington III        'org.freedesktop.DBus.Properties' \
2031285115cSWilliam A. Kennington III        'Get' ss "$interface" "$property" | \
2041285115cSWilliam A. Kennington III        jq -r '.data[0].data'
2051285115cSWilliam A. Kennington III}
2061285115cSWilliam A. Kennington III
2071285115cSWilliam A. Kennington III# Deletes any OpenBMC DBus object from a service
20859486679SPatrick Williamsfunction DeleteObject() {
2091285115cSWilliam A. Kennington III    local service="$1"
2101285115cSWilliam A. Kennington III    local object="$2"
2111285115cSWilliam A. Kennington III
2121285115cSWilliam A. Kennington III    busctl call \
2131285115cSWilliam A. Kennington III        "$service" \
2141285115cSWilliam A. Kennington III        "$object" \
2151285115cSWilliam A. Kennington III        'xyz.openbmc_project.Object.Delete' \
2161285115cSWilliam A. Kennington III        'Delete'
2171285115cSWilliam A. Kennington III}
2181285115cSWilliam A. Kennington III
2191285115cSWilliam A. Kennington III# Transforms the given JSON dictionary into bash local variable
2201285115cSWilliam A. Kennington III# statements that can be directly evaluated by the interpreter
22159486679SPatrick Williamsfunction JSONToVars() {
2221285115cSWilliam A. Kennington III    jq -r 'to_entries[] | @sh "local \(.key)=\(.value)"'
2231285115cSWilliam A. Kennington III}
2241285115cSWilliam A. Kennington III
2251285115cSWilliam A. Kennington III# Returns the DBus object root for the ethernet interface
22659486679SPatrick Williamsfunction EthObjRoot() {
2271285115cSWilliam A. Kennington III    local netdev="$1"
2281285115cSWilliam A. Kennington III
2291285115cSWilliam A. Kennington III    echo "/xyz/openbmc_project/network/$netdev"
2301285115cSWilliam A. Kennington III}
2311285115cSWilliam A. Kennington III
2321285115cSWilliam A. Kennington III# Returns all of the neighbor { service, object } data for an interface as if
2331285115cSWilliam A. Kennington III# a call to GetSubTree() was made
23459486679SPatrick Williamsfunction GetNeighborObjects() {
2351285115cSWilliam A. Kennington III    local netdev="$1"
2361285115cSWilliam A. Kennington III
237*0ddcb163SWilliam A. Kennington III    GetSubTree "$(EthObjRoot "$netdev")" 0 \
2381285115cSWilliam A. Kennington III        'xyz.openbmc_project.Network.Neighbor'
2391285115cSWilliam A. Kennington III}
2401285115cSWilliam A. Kennington III
2411285115cSWilliam A. Kennington III# Returns the neighbor properties as a JSON object
24259486679SPatrick Williamsfunction GetNeighbor() {
2431285115cSWilliam A. Kennington III    local service="$1"
2441285115cSWilliam A. Kennington III    local object="$2"
2451285115cSWilliam A. Kennington III
2461285115cSWilliam A. Kennington III    GetProperties "$service" "$object" 'xyz.openbmc_project.Network.Neighbor'
2471285115cSWilliam A. Kennington III}
2481285115cSWilliam A. Kennington III
2491285115cSWilliam A. Kennington III# Adds a static neighbor to the system network daemon
25059486679SPatrick Williamsfunction AddNeighbor() {
2511285115cSWilliam A. Kennington III    local service="$1"
2521285115cSWilliam A. Kennington III    local netdev="$2"
2531285115cSWilliam A. Kennington III    local ip="$3"
2541285115cSWilliam A. Kennington III    local mac="$4"
2551285115cSWilliam A. Kennington III
2561285115cSWilliam A. Kennington III    busctl call \
2571285115cSWilliam A. Kennington III        "$service" \
2581285115cSWilliam A. Kennington III        "$(EthObjRoot "$netdev")" \
2591285115cSWilliam A. Kennington III        'xyz.openbmc_project.Network.Neighbor.CreateStatic' \
2601285115cSWilliam A. Kennington III        'Neighbor' ss "$ip" "$mac" >/dev/null
2611285115cSWilliam A. Kennington III}
2621285115cSWilliam A. Kennington III
2631285115cSWilliam A. Kennington III# Returns all of the IP { service, object } data for an interface as if
2641285115cSWilliam A. Kennington III# a call to GetSubTree() was made
26559486679SPatrick Williamsfunction GetIPObjects() {
2661285115cSWilliam A. Kennington III    local netdev="$1"
2671285115cSWilliam A. Kennington III
2681285115cSWilliam A. Kennington III    GetSubTree "$(EthObjRoot "$netdev")" 0 \
2691285115cSWilliam A. Kennington III        'xyz.openbmc_project.Network.IP'
2701285115cSWilliam A. Kennington III}
2711285115cSWilliam A. Kennington III
2721285115cSWilliam A. Kennington III# Returns the IP properties as a JSON object
27359486679SPatrick Williamsfunction GetIP() {
2741285115cSWilliam A. Kennington III    local service="$1"
2751285115cSWilliam A. Kennington III    local object="$2"
2761285115cSWilliam A. Kennington III
2771285115cSWilliam A. Kennington III    GetProperties "$service" "$object" 'xyz.openbmc_project.Network.IP'
2781285115cSWilliam A. Kennington III}
2791285115cSWilliam A. Kennington III
280b163a2c1SWilliam A. Kennington III# Returns the Gateway address for the interface and type
28159486679SPatrick Williamsfunction GetGateways() {
282b163a2c1SWilliam A. Kennington III    local service="$1"
283b163a2c1SWilliam A. Kennington III    local netdev="$2"
284b163a2c1SWilliam A. Kennington III
285b163a2c1SWilliam A. Kennington III    # We fetch both the system properties and the netdev specific properties
286b163a2c1SWilliam A. Kennington III    # as OpenBMC is in the process of transitioning these to the netdev object
287b163a2c1SWilliam A. Kennington III    # but the migration is not yet complete.
288b163a2c1SWilliam A. Kennington III    {
289b163a2c1SWilliam A. Kennington III        GetProperties "$service" '/xyz/openbmc_project/network/config' \
290b163a2c1SWilliam A. Kennington III            'xyz.openbmc_project.Network.SystemConfiguration'
291b163a2c1SWilliam A. Kennington III        GetProperties "$service" "$(EthObjRoot "$netdev")" \
292b163a2c1SWilliam A. Kennington III            'xyz.openbmc_project.Network.EthernetInterface'
293b163a2c1SWilliam A. Kennington III    } | jq -s '
294b163a2c1SWilliam A. Kennington III      . | map(
295b163a2c1SWilliam A. Kennington III        if .DefaultGateway != "" then
296b163a2c1SWilliam A. Kennington III          {DefaultGateway: .DefaultGateway}
297b163a2c1SWilliam A. Kennington III        else
298b163a2c1SWilliam A. Kennington III          {}
299b163a2c1SWilliam A. Kennington III        end +
300b163a2c1SWilliam A. Kennington III        if .DefaultGateway6 != "" then
301b163a2c1SWilliam A. Kennington III          {DefaultGateway6: .DefaultGateway6}
302b163a2c1SWilliam A. Kennington III        else
303b163a2c1SWilliam A. Kennington III          {}
304b163a2c1SWilliam A. Kennington III        end
305b163a2c1SWilliam A. Kennington III    ) | {DefaultGateway: "", DefaultGateway6: ""} + add'
306b163a2c1SWilliam A. Kennington III}
307b163a2c1SWilliam A. Kennington III
3081285115cSWilliam A. Kennington III# Adds a static IP to the system network daemon
30959486679SPatrick Williamsfunction AddIP() {
3101285115cSWilliam A. Kennington III    local service="$1"
3111285115cSWilliam A. Kennington III    local netdev="$2"
3121285115cSWilliam A. Kennington III    local ip="$3"
3131285115cSWilliam A. Kennington III    local prefix="$4"
3141285115cSWilliam A. Kennington III
3151285115cSWilliam A. Kennington III    local protocol='xyz.openbmc_project.Network.IP.Protocol.IPv4'
3161285115cSWilliam A. Kennington III    if ! IsIPv4 "$ip"; then
3171285115cSWilliam A. Kennington III        protocol='xyz.openbmc_project.Network.IP.Protocol.IPv6'
3181285115cSWilliam A. Kennington III    fi
3191285115cSWilliam A. Kennington III
3201285115cSWilliam A. Kennington III    busctl call \
3211285115cSWilliam A. Kennington III        "$service" \
3221285115cSWilliam A. Kennington III        "$(EthObjRoot "$netdev")" \
3231285115cSWilliam A. Kennington III        'xyz.openbmc_project.Network.IP.Create' \
3241285115cSWilliam A. Kennington III        'IP' ssys "$protocol" "$ip" "$prefix" '' >/dev/null
3251285115cSWilliam A. Kennington III}
3261285115cSWilliam A. Kennington III
3271285115cSWilliam A. Kennington III# Determines if two IP addresses have the same address family
3281285115cSWilliam A. Kennington III# IE: Both are IPv4 or both are IPv6
32959486679SPatrick Williamsfunction MatchingAF() {
3301285115cSWilliam A. Kennington III    local rc1=0 rc2=0
3311285115cSWilliam A. Kennington III    IsIPv4 "$1" || rc1=$?
3321285115cSWilliam A. Kennington III    IsIPv4 "$2" || rc2=$?
3331285115cSWilliam A. Kennington III    (( rc1 == rc2 ))
3341285115cSWilliam A. Kennington III}
3351285115cSWilliam A. Kennington III
3361285115cSWilliam A. Kennington III# Checks to see if the machine has the provided IP address information
3371285115cSWilliam A. Kennington III# already configured. If not, it deletes all of the information for that
3381285115cSWilliam A. Kennington III# address family and adds the provided IP address.
33959486679SPatrick Williamsfunction UpdateIP() {
3401285115cSWilliam A. Kennington III    local service="$1"
3411285115cSWilliam A. Kennington III    local netdev="$2"
3421e5029b4SWilliam A. Kennington III    local ip="$(normalize_ip $3)"
3431285115cSWilliam A. Kennington III    local prefix="$4"
3441285115cSWilliam A. Kennington III
3451285115cSWilliam A. Kennington III    local should_add=1
3461285115cSWilliam A. Kennington III    local delete_services=()
3471285115cSWilliam A. Kennington III    local delete_objects=()
3481285115cSWilliam A. Kennington III    local entry
3491285115cSWilliam A. Kennington III    while read entry; do
3501285115cSWilliam A. Kennington III        eval "$(echo "$entry" | JSONToVars)" || return $?
3511285115cSWilliam A. Kennington III        eval "$(GetIP "$service" "$object" | JSONToVars)" || return $?
3521e5029b4SWilliam A. Kennington III        if [ "$(normalize_ip "$Address")" = "$ip" ] && \
3531285115cSWilliam A. Kennington III            [ "$PrefixLength" = "$prefix" ]; then
3541285115cSWilliam A. Kennington III            should_add=0
35527364013SWilliam A. Kennington III        elif MatchingAF "$ip" "$Address" && [[ "$Origin" == *.Static ]]; then
3561285115cSWilliam A. Kennington III            echo "Deleting spurious IP: $Address/$PrefixLength" >&2
3571285115cSWilliam A. Kennington III            delete_services+=("$service")
3581285115cSWilliam A. Kennington III            delete_objects+=("$object")
3591285115cSWilliam A. Kennington III        fi
3601285115cSWilliam A. Kennington III    done < <(GetIPObjects "$netdev")
3611285115cSWilliam A. Kennington III
3621285115cSWilliam A. Kennington III    local i
3631285115cSWilliam A. Kennington III    for (( i=0; i<${#delete_objects[@]}; ++i )); do
3642be0536cSWilliam A. Kennington III        DeleteObject "${delete_services[$i]}" "${delete_objects[$i]}" || true
3651285115cSWilliam A. Kennington III    done
3661285115cSWilliam A. Kennington III
3671e5029b4SWilliam A. Kennington III    # The default address is treated as a delete only request
3681e5029b4SWilliam A. Kennington III    if [ "$ip" = :: -o "$ip" = 0.0.0.0 ]; then
3691e5029b4SWilliam A. Kennington III      return
3701e5029b4SWilliam A. Kennington III    fi
3711e5029b4SWilliam A. Kennington III
3721285115cSWilliam A. Kennington III    if (( should_add == 0 )); then
3731285115cSWilliam A. Kennington III        echo "Not adding IP: $ip/$prefix" >&2
3741285115cSWilliam A. Kennington III    else
3751285115cSWilliam A. Kennington III        echo "Adding IP: $ip/$prefix" >&2
3761285115cSWilliam A. Kennington III        AddIP "$service" "$netdev" "$ip" "$prefix" || return $?
3771285115cSWilliam A. Kennington III    fi
3781285115cSWilliam A. Kennington III}
3791285115cSWilliam A. Kennington III
3801285115cSWilliam A. Kennington III# Sets the system gateway property to the provided IP address if not already
3811285115cSWilliam A. Kennington III# set to the current value.
38259486679SPatrick Williamsfunction UpdateGateway() {
3831285115cSWilliam A. Kennington III    local service="$1"
3842d6858ddSWilliam A. Kennington III    local netdev="$2"
3852d6858ddSWilliam A. Kennington III    local ip="$3"
3861285115cSWilliam A. Kennington III
3872d6858ddSWilliam A. Kennington III    local object="$(EthObjRoot "$netdev")"
3882d6858ddSWilliam A. Kennington III    local interface='xyz.openbmc_project.Network.EthernetInterface'
3891285115cSWilliam A. Kennington III    local property='DefaultGateway'
3901285115cSWilliam A. Kennington III    if ! IsIPv4 "$ip"; then
3911285115cSWilliam A. Kennington III        property='DefaultGateway6'
3921285115cSWilliam A. Kennington III    fi
3931285115cSWilliam A. Kennington III
3941285115cSWilliam A. Kennington III    local current_ip
3951285115cSWilliam A. Kennington III    current_ip="$(GetProperty "$service" "$object" "$interface" "$property")" || \
3961285115cSWilliam A. Kennington III        return $?
3971285115cSWilliam A. Kennington III    if [ -n "$current_ip" ] && \
3981285115cSWilliam A. Kennington III        [ "$(normalize_ip "$ip")" = "$(normalize_ip "$current_ip")" ]; then
3991285115cSWilliam A. Kennington III        echo "Not reconfiguring gateway: $ip" >&2
4001285115cSWilliam A. Kennington III        return 0
4011285115cSWilliam A. Kennington III    fi
4021285115cSWilliam A. Kennington III
4031285115cSWilliam A. Kennington III    echo "Setting gateway: $ip" >&2
4041285115cSWilliam A. Kennington III    busctl set-property "$service" "$object" "$interface" "$property" s "$ip"
4051285115cSWilliam A. Kennington III}
4061285115cSWilliam A. Kennington III
4071285115cSWilliam A. Kennington III# Checks to see if the machine has the provided neighbor information
4081285115cSWilliam A. Kennington III# already configured. If not, it deletes all of the information for that
4091285115cSWilliam A. Kennington III# address family and adds the provided neighbor entry.
41059486679SPatrick Williamsfunction UpdateNeighbor() {
4111285115cSWilliam A. Kennington III    local service="$1"
4121285115cSWilliam A. Kennington III    local netdev="$2"
4131285115cSWilliam A. Kennington III    local ip="$3"
4141285115cSWilliam A. Kennington III    local mac="$4"
4151285115cSWilliam A. Kennington III
4161285115cSWilliam A. Kennington III    local should_add=1
4171285115cSWilliam A. Kennington III    local delete_services=()
4181285115cSWilliam A. Kennington III    local delete_objects=()
4191285115cSWilliam A. Kennington III    local entry
4201285115cSWilliam A. Kennington III    while read entry; do
4211285115cSWilliam A. Kennington III        eval "$(echo "$entry" | JSONToVars)" || return $?
4221285115cSWilliam A. Kennington III        eval "$(GetNeighbor "$service" "$object" | JSONToVars)" || return $?
4231285115cSWilliam A. Kennington III        if [ "$(normalize_ip "$IPAddress")" = "$(normalize_ip "$ip")" ] && \
4241285115cSWilliam A. Kennington III            [ "$(normalize_mac "$MACAddress")" = "$(normalize_mac "$mac")" ]; then
4251285115cSWilliam A. Kennington III            should_add=0
4261285115cSWilliam A. Kennington III        elif MatchingAF "$ip" "$IPAddress"; then
4271285115cSWilliam A. Kennington III            echo "Deleting spurious neighbor: $IPAddress $MACAddress" >&2
4281285115cSWilliam A. Kennington III            delete_services+=("$service")
4291285115cSWilliam A. Kennington III            delete_objects+=("$object")
4301285115cSWilliam A. Kennington III        fi
4311285115cSWilliam A. Kennington III    done < <(GetNeighborObjects "$netdev" 2>/dev/null)
4321285115cSWilliam A. Kennington III
4331285115cSWilliam A. Kennington III    local i
4341285115cSWilliam A. Kennington III    for (( i=0; i<${#delete_objects[@]}; ++i )); do
4352be0536cSWilliam A. Kennington III        DeleteObject "${delete_services[$i]}" "${delete_objects[$i]}" || true
4361285115cSWilliam A. Kennington III    done
4371285115cSWilliam A. Kennington III
4381285115cSWilliam A. Kennington III    if (( should_add == 0 )); then
4391285115cSWilliam A. Kennington III        echo "Not adding neighbor: $ip $mac" >&2
4401285115cSWilliam A. Kennington III    else
4411285115cSWilliam A. Kennington III        echo "Adding neighbor: $ip $mac" >&2
4421285115cSWilliam A. Kennington III        AddNeighbor "$service" "$netdev" "$ip" "$mac" || return $?
4431285115cSWilliam A. Kennington III    fi
4441285115cSWilliam A. Kennington III}
445b163a2c1SWilliam A. Kennington III
446b163a2c1SWilliam A. Kennington III# Determines the ip and mac of the IPv6 router
44759486679SPatrick Williamsfunction DiscoverRouter6() {
448b163a2c1SWilliam A. Kennington III    local netdev="$1"
449b163a2c1SWilliam A. Kennington III    local retries="$2"
450b163a2c1SWilliam A. Kennington III    local timeout="$3"
451b163a2c1SWilliam A. Kennington III    local router="${4-}"
452b163a2c1SWilliam A. Kennington III
453b163a2c1SWilliam A. Kennington III    local output
454b163a2c1SWilliam A. Kennington III    local st=0
455b163a2c1SWilliam A. Kennington III    local args=(-1 -w "$timeout" -n $router "$netdev")
456b163a2c1SWilliam A. Kennington III    if (( retries < 0 )); then
457b163a2c1SWilliam A. Kennington III        args+=(-d)
458b163a2c1SWilliam A. Kennington III    else
459b163a2c1SWilliam A. Kennington III        args+=(-r "$retries")
460b163a2c1SWilliam A. Kennington III    fi
461d7989581SWilliam A. Kennington III    CaptureInterruptible output rdisc6 "${args[@]}" || st=$?
462b163a2c1SWilliam A. Kennington III    if (( st != 0 )); then
463b163a2c1SWilliam A. Kennington III        echo "rdisc6 failed with: " >&2
464b163a2c1SWilliam A. Kennington III        echo "$output" >&2
465b163a2c1SWilliam A. Kennington III        return $st
466b163a2c1SWilliam A. Kennington III    fi
467b163a2c1SWilliam A. Kennington III
468b163a2c1SWilliam A. Kennington III    local ip="$(echo "$output" | grep 'from' | awk '{print $2}')"
469b163a2c1SWilliam A. Kennington III    local mac="$(echo "$output" | grep 'Source link-layer' | ParseMACFromLine)"
470379b061fSWilliam A. Kennington III    local staddr="$(echo "$output" | grep 'Stateful address conf.*Yes')"
471379b061fSWilliam A. Kennington III    printf '{"router_ip":"%s","router_mac":"%s","stateful_address":"%s"}\n' \
472379b061fSWilliam A. Kennington III        "$ip" "$mac" "$staddr"
473b163a2c1SWilliam A. Kennington III}
474a7af2e08SWilliam A. Kennington III
475a7af2e08SWilliam A. Kennington III# Sets the network configuration of an interface to be static
47659486679SPatrick Williamsfunction SetStatic() {
477a7af2e08SWilliam A. Kennington III    local service="$1"
478a7af2e08SWilliam A. Kennington III    local netdev="$2"
479a7af2e08SWilliam A. Kennington III
480a7af2e08SWilliam A. Kennington III    echo "Disabling DHCP" >&2
481a7af2e08SWilliam A. Kennington III    busctl set-property "$service" "$(EthObjRoot "$netdev")" \
482a7af2e08SWilliam A. Kennington III        xyz.openbmc_project.Network.EthernetInterface DHCPEnabled \
483a7af2e08SWilliam A. Kennington III        s xyz.openbmc_project.Network.EthernetInterface.DHCPConf.none
484a7af2e08SWilliam A. Kennington III}
485