summaryrefslogtreecommitdiff
path: root/meta-openbmc-mods/meta-common/recipes-network/network/static-mac-addr/mac-check
blob: e949a9117b281f8fd6bfbf6e822caeed9311825b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
#!/bin/bash
# Copyright 2018 Intel Corporation
#
# 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.

SOFS_MNT=/var/sofs
SOFS_MACDIR=${SOFS_MNT}/factory-settings/network/mac

read_hw_mac() {
	local iface="$1"
	cat /sys/class/net/"$iface"/address 2>/dev/null | tr [:upper:] [:lower:] 2>/dev/null
}

set_hw_mac() {
	local iface="$1"
	local mac="$2"
	ip link show dev "$iface" | grep -q "${iface}:.*\<UP\>" 2>/dev/null
	local up=$?
	[[ $up -eq 0 ]] && ip link set dev "$iface" down
	ip link set dev "$iface" address "$mac"
	[[ $up -eq 0 ]] && ip link set dev "$iface" up
}

read_sofs_mac() {
	local iface="$1"
	cat "${SOFS_MACDIR}/${iface}" 2>/dev/null | tr [:upper:] [:lower:] 2>/dev/null
}

read_fw_env_mac() {
	local envname="$1"
	fw_printenv "$envname" 2>/dev/null | sed "s/^$envname=//" 2>/dev/null | tr [:upper:] [:lower:] 2>/dev/null
}

set_fw_env_mac() {
	local envname="$1"
	local mac="$2"
	fw_setenv "$envname" "$mac"
}

create_macdir() {
if [ -a ${SOFS_MACDIR} ]; then
	if [ ! -d ${SOFS_MACDIR} ]; then
		rm -rf ${SOFS_MACDIR}
		mkdir -p ${SOFS_MACDIR}
	fi
else
	mkdir -p ${SOFS_MACDIR}
fi
return 0
}

# An earlier version of the mac_check utility disabled the netipmid for
# eth1. This was done to eliminate an error message being logged in the
# journal for systems that only had a single NIC. The error message is
# undesirable as it is present in Redfish session log output.

# Systems that have both NICs have also had the eth1 netipmid disabled.
# The reason for this is failing to specify the correct kernel device
# tree during the U-Boot kernel boot process. Without the correct
# device tree, eth1 is not enumerated by the kernel. The mac-check
# script turned off the netipmid service for eth1.

# The configure_netipmid_svc_eth1 function manages enabling and
# disabling netipmid for eth1. It is explicit, and does not rely upon
# previous state to enable or disable the service.

# Note: Enabling the service is independent of the IPMI channel
# enable/disable command. This means "ipmitool lan set <chid> access
# off" functions correctly with the netipmid service enabled.
configure_netipmid_svc_eth1() {
    if [ -h /sys/class/net/eth1 ]; then
        if [ $(systemctl is-enabled phosphor-ipmi-net@eth1.socket) == "disabled" ];
        then
            /bin/systemctl enable "phosphor-ipmi-net@eth1.socket"
            /bin/systemctl start "phosphor-ipmi-net@eth1.socket"
        fi
        if [ $(systemctl is-enabled phosphor-ipmi-net@eth1.service) == "disabled" ];
        then
            /bin/systemctl enable "phosphor-ipmi-net@eth1.service"
            /bin/systemctl start "phosphor-ipmi-net@eth1.service"
        fi
    else
        if [ $(systemctl is-enabled phosphor-ipmi-net@eth1.socket) == "enabled" ];
        then
            /bin/systemctl disable "phosphor-ipmi-net@eth1.socket"
            /bin/systemctl stop "phosphor-ipmi-net@eth1.socket"
        fi
        if [ $(systemctl is-enabled phosphor-ipmi-net@eth1.service) == "enabled" ];
        then
            /bin/systemctl disable "phosphor-ipmi-net@eth1.service"
            /bin/systemctl stop "phosphor-ipmi-net@eth1.service"
        fi
    fi
}

mac_check() {
	local iface="$1"
	local envname="$2"

	# Read the MAC address in use by the NIC
	local hw_mac=$(read_hw_mac "$iface")

	# Read the MAC address stored in the non-volatile file provisioned in
	# manufacturing.
	local sofs_mac=$(read_sofs_mac "$iface")

	if [ -n "$sofs_mac" ] && [ "$hw_mac" != "$sofs_mac" ]; then
		# A factory assigned address was found, and it is newly assigned.
		# Update the active interface and save the new value to the u-boot
		# environment.
		set_hw_mac "$iface" "$sofs_mac"
		set_fw_env_mac "$envname" "$sofs_mac"
		return $?
	elif [ -n "$hw_mac" ]; then
		# Read the MAC address stored by U-Boot
		local fw_env_mac=$(read_fw_env_mac "$envname")
		if [ -z "$fw_env_mac" ] || [ "$fw_env_mac" != "$hw_mac" ]; then
			set_fw_env_mac "$envname" "$hw_mac"
			return $?
		fi
	else
	    # Could not identify a MAC address
	    return 255
	fi
	return 0
}

create_macdir

configure_netipmid_svc_eth1

error=0
first_error_seen=0

while read IFACE UBDEV; do
	# Try to configure the MAC address if the kernel finds the NIC. Blindly
	# trying all of the interfaces listed in the DOCSTRING (END_CONF) below
	# may result in first_error_seen being set to a non-zero value. If that
	# happens the journal log will report the error, which is undesirable.
	if [ -h /sys/class/net/$IFACE ]; then
		mac_check "$IFACE" "$UBDEV"
		error=$?
		if [ $error -ne 0 ] && [ $first_error_seen -eq 0 ]; then
		    first_error_seen=$error
		fi
	fi
done <<-END_CONF
	eth0 eth1addr
	eth1 ethaddr
END_CONF

### HOSTNAME FEATURE ###
if [[ $* == *--no-unique-hostname* ]]; then
	echo "mac-check: Skipping hostname check"
else
	# Read MAC and strip colon chars
	hw_mac=$(cat /sys/class/net/eth0/address | tr -d ":")
	# Read Hostname
	hostname=$(hostname)
	#Match bmc-mac<any MAC address> (a MAC address has 12 hex digits)
	bmc_mac_format="^bmc-mac[a-f0-9]{12}$"
	#Match bmc-mac<current MAC address>
	inteldefault="bmc-mac$hw_mac"
	#if the current hostname already has the current MAC address, we won't rewrite the name unnecessarily.
	#Otherwise, match intel-obmc or bmc-mac<any MAC address>, and change the hostname to use the current MAC address
	if [[ "$hostname" == "intel-obmc" || \
		("$hostname" != "$inteldefault" && \
		"$hostname" =~ $bmc_mac_format) ]]; then
		hostnamectl set-hostname "$inteldefault"
		echo "mac-check: HOSTNAME CHANGED (hostname deemed to be default or wrong MAC Address)"
	else
		echo "mac-check: HOSTNAME NOT CHANGED (hostname is already correct or is custom)"
	fi
fi

exit $first_error_seen