mac-address-set: adding vcu2 support (hw23)
After an overall refactoring this script now does: * Wait on devices being ready before changing the address * Handle errors when setting wlan or bluetooth mac address * Handle different MAC address schemes * Handle different behaviors when setting wlan mac: On HW21, the address must be set while the interface is down, but on HW23 it must be set while the interface is up and if it is down, no error is thrown, so the modified address is checked. * Handle different behaviors while setting BT mac: On HW21, the address must be given with the bytes in reverse order. We therefore first try with the right order and check the address and retry with the reversed address if it failed. BugzID: 77171 Signed-off-by: Patrick Zysset <patrick.zysset@netmodule.com>
This commit is contained in:
parent
54d559d706
commit
da62ee6786
|
|
@ -1,25 +1,313 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
eth_mac=$(ip addr show eth0 | awk '$1 == "link/ether" {gsub(/\/.*$/, "", $2); print $2}')
|
||||
wlan_mac=$(echo $eth_mac | sed -r "s/^(.{9})50(.{6})/\170\2/")
|
||||
bt_addr=$(echo $eth_mac | sed -r "s/^(.{9})50(.{6})/\180\2/")
|
||||
help_text='
|
||||
This script configures bluetooth and wifi mac addresses
|
||||
It is using the eth0 mac address as reference and then applying
|
||||
a logical operation based on the mac address range.
|
||||
|
||||
Since the handling of wifi and bluetooth devices may be different
|
||||
on different devices, this script is doing several attempts with
|
||||
different approaches to be compatible with all devices.
|
||||
|
||||
# Set WLAN address
|
||||
ifconfig wlan0 | grep UP > /dev/null
|
||||
up=$?
|
||||
if [[ $up == 0 ]]; then
|
||||
Currently supported devices: HW21 and HW23
|
||||
|
||||
It currently supports two schemes:
|
||||
|
||||
* VCU1 scheme, starts with 7C:97:63: and ends with:
|
||||
eth0: :50:XX:YY
|
||||
wlan0: :70:XX:YY
|
||||
bt0: :80:XX:YY
|
||||
|
||||
* VCU2 scheme, starts with 00:11:2B: and ends with:
|
||||
eth0: :XX:YY:ZZ
|
||||
wlan0: :XX:YY:ZZ+3
|
||||
bt0: :XX:YY:ZZ+4
|
||||
|
||||
This script is NOT setting eth0 mac address, this must be done
|
||||
before (usually bootloader).
|
||||
'
|
||||
|
||||
level_error=0
|
||||
level_warning=1
|
||||
level_info=2
|
||||
|
||||
log_level="$level_info"
|
||||
|
||||
log () {
|
||||
msg_level="$1"
|
||||
level_string="$2"
|
||||
msg="$3"
|
||||
|
||||
if [ "$log_level" -ge "$msg_level" ]; then
|
||||
echo "$0: $level_string: $msg"
|
||||
fi
|
||||
}
|
||||
|
||||
log_info() {
|
||||
msg="$1"
|
||||
log "$level_info" "info" "$msg"
|
||||
}
|
||||
|
||||
log_warning() {
|
||||
msg="$1"
|
||||
log "$level_warning" "warning" "$msg"
|
||||
}
|
||||
|
||||
log_error() {
|
||||
msg="$1"
|
||||
log "$level_error" "error" "$msg"
|
||||
}
|
||||
|
||||
wait_on() {
|
||||
cmd=$1
|
||||
device=$2
|
||||
if $cmd "$device" > /dev/null 2>/dev/null; then
|
||||
return
|
||||
fi
|
||||
log_info "$device not ready"
|
||||
log_info "Waiting...."
|
||||
while ! $cmd "$device" > /dev/null 2>/dev/null; do
|
||||
sleep 1
|
||||
done
|
||||
log_info "$device ready"
|
||||
}
|
||||
|
||||
wait_on_wlan0() {
|
||||
wait_on ifconfig wlan0
|
||||
}
|
||||
|
||||
wait_on_hci0() {
|
||||
wait_on hciconfig hci0
|
||||
}
|
||||
|
||||
is_wlan0_up() {
|
||||
if ifconfig wlan0 | grep UP > /dev/null;
|
||||
then
|
||||
return "1"
|
||||
else
|
||||
return "0"
|
||||
fi
|
||||
}
|
||||
|
||||
set_wlan_mac_address() {
|
||||
address=$1
|
||||
log_info "Setting wlan0 mac address to $address"
|
||||
ip link set wlan0 address "$address"
|
||||
ret=$?
|
||||
if [ $ret -ne 0 ]; then
|
||||
log_warning "Setting wlan address failed $ret"
|
||||
fi
|
||||
return $ret
|
||||
}
|
||||
|
||||
set_and_check_wlan_mac_address() {
|
||||
address=$1
|
||||
|
||||
set_wlan_mac_address "$address"
|
||||
ret=$?
|
||||
|
||||
if [ $ret -ne 0 ]; then
|
||||
log_warning "Setting wlan address failed: $ret"
|
||||
return $ret
|
||||
fi
|
||||
|
||||
log_info "Checking success"
|
||||
# Setting the mac may fail without error
|
||||
# Checking MAC to be sure it worked
|
||||
if ifconfig wlan0 | grep -i "$address" > /dev/null; then
|
||||
log_info "wlan mac address successfully set"
|
||||
return 0
|
||||
else
|
||||
log_warning "Setting wlan address failed without throwing an error"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
prepare_wlan() {
|
||||
is_wlan0_up
|
||||
wlan_iface_was_up=$?
|
||||
|
||||
if [[ "$wlan_iface_was_up" -eq "1" ]]; then
|
||||
log_info "Taking wlan0 down"
|
||||
ifconfig wlan0 down
|
||||
fi
|
||||
ip link set wlan0 address $wlan_mac
|
||||
return "$wlan_iface_was_up"
|
||||
}
|
||||
|
||||
if [[ $up == 0 ]]; then
|
||||
unprepare_wlan() {
|
||||
wlan_iface_was_up=$1
|
||||
|
||||
if [[ "$wlan_iface_was_up" -eq "1" ]]; then
|
||||
log_info "Taking wlan0 back up"
|
||||
ifconfig wlan0 up
|
||||
else
|
||||
log_info "Making sure wlan0 is down"
|
||||
ifconfig wlan0 down
|
||||
fi
|
||||
}
|
||||
|
||||
prepare_and_set_wlan_mac_address() {
|
||||
address="$1"
|
||||
|
||||
wait_on_wlan0
|
||||
prepare_wlan
|
||||
wlan_iface_was_up=$?
|
||||
|
||||
set_and_check_wlan_mac_address "$address"
|
||||
ret=$?
|
||||
if [[ "$ret" -ne 0 ]]; then
|
||||
# On some devices the interface must be up to set the address
|
||||
log_warning "Setting wlan address failed, trying with interface up"
|
||||
ifconfig wlan0 up
|
||||
set_and_check_wlan_mac_address "$address"
|
||||
ret=$?
|
||||
fi
|
||||
|
||||
unprepare_wlan "$wlan_iface_was_up"
|
||||
|
||||
# Set BT address
|
||||
bt_addr_rev=$(echo $bt_addr | sed -r "s/^(.{2}):(.{2}):(.{2}):(.{2}):(.{2}):(.{2})/\6:\5:\4:\3:\2:\1/")
|
||||
bdaddr $bt_addr_rev
|
||||
return $ret
|
||||
}
|
||||
|
||||
|
||||
set_and_check_bt_mac_address() {
|
||||
address="$1"
|
||||
addr_to_set="$address" # Because of some bug the address to set may be inverted
|
||||
invert="$2"
|
||||
if [[ "$invert" -eq "1" ]]; then
|
||||
addr_to_set=$(echo "$address" | sed -r "s/^(.{2}):(.{2}):(.{2}):(.{2}):(.{2}):(.{2})/\\6:\\5:\\4:\\3:\\2:\\1/")
|
||||
fi
|
||||
|
||||
bdaddr "$addr_to_set" > /dev/null
|
||||
ret=$?
|
||||
if [ $ret -ne 0 ]; then
|
||||
log_warning "Setting bluetooth address failed: $ret"
|
||||
fi
|
||||
|
||||
log_info "Restarting bluetooth service"
|
||||
hciconfig hci0 reset
|
||||
systemctl restart bluetooth
|
||||
sleep 1
|
||||
wait_on_hci0
|
||||
hciconfig hci0 up
|
||||
|
||||
log_info "Checking success"
|
||||
if hciconfig hci0 | grep -i "$address" > /dev/null; then
|
||||
log_info "Bluetooth address successfully set"
|
||||
ret=0
|
||||
else
|
||||
log_warning "Setting bluetooth address failed without error"
|
||||
ret=1
|
||||
fi
|
||||
return $ret
|
||||
}
|
||||
|
||||
prepare_and_set_bt_mac_address() {
|
||||
address=$1
|
||||
|
||||
wait_on_hci0
|
||||
|
||||
hciconfig hci0 up
|
||||
|
||||
log_info "Setting bluetooth mac address to $address"
|
||||
set_and_check_bt_mac_address "$address" 0
|
||||
ret=$?
|
||||
if [ $ret -ne 0 ]; then
|
||||
log_info "Trying with reversed address" # This is a bug in some systems
|
||||
set_and_check_bt_mac_address "$address" 1
|
||||
ret=$?
|
||||
fi
|
||||
|
||||
return $ret
|
||||
}
|
||||
|
||||
# VCU1 scheme, starts with 7C:97:63:
|
||||
# eth0: 50:XX:YY
|
||||
# wlan0: 70:XX:YY
|
||||
# bt0: 80:XX:YY
|
||||
is_vcu1_mac() {
|
||||
[[ $1 == "7C:97:63:"* ]]
|
||||
}
|
||||
|
||||
vcu1_eth_to_wlan() {
|
||||
echo "$1" | sed -r "s/^(.{9})50(.{6})/\\170\\2/"
|
||||
}
|
||||
|
||||
vcu1_eth_to_bt() {
|
||||
echo "$1" | sed -r "s/^(.{9})50(.{6})/\\180\\2/"
|
||||
}
|
||||
|
||||
# VCU2 scheme, starts with 00:11:2B:
|
||||
# eth0: XX:YY:ZZ
|
||||
# wlan0: XX:YY:ZZ+3
|
||||
# bt0: XX:YY:ZZ+4
|
||||
is_vcu2_mac() {
|
||||
[[ $1 == "00:11:2B:"* ]]
|
||||
}
|
||||
|
||||
vcu2_eth_to_wlan_and_bt() {
|
||||
IFS=':' read -r -a digits <<< "$1"
|
||||
|
||||
digits[5]=$((digits[5] + 3))
|
||||
wlan_mac=$(printf ":%s" "${digits[@]}")
|
||||
wlan_mac=${wlan_mac:1} # Remove first ":"
|
||||
|
||||
digits[5]=$((digits[5] + 1))
|
||||
bt_mac=$(printf ":%s" "${digits[@]}")
|
||||
bt_mac=${bt_mac:1} # Remove first ":"
|
||||
|
||||
|
||||
echo "$wlan_mac"
|
||||
echo "$bt_mac"
|
||||
}
|
||||
|
||||
|
||||
|
||||
main() {
|
||||
ret=0
|
||||
|
||||
eth_mac=$(ip addr show eth0 | awk '$1 == "link/ether" {gsub(/\/.*$/, "", $2); print $2}')
|
||||
eth_mac=${eth_mac^^} # UPPER case
|
||||
if is_vcu1_mac "$eth_mac"; then
|
||||
log_info "VCU1 mac address scheme"
|
||||
wlan_mac=$(vcu1_eth_to_wlan "$eth_mac")
|
||||
bt_addr=$(vcu1_eth_to_bt "$eth_mac")
|
||||
elif is_vcu2_mac "$eth_mac"; then
|
||||
log_info "VCU2 mac address scheme"
|
||||
wlan_and_bt_macs=$(vcu2_eth_to_wlan_and_bt "$eth_mac")
|
||||
wlan_mac=$(echo "$wlan_and_bt_macs" | head -n 1)
|
||||
bt_addr=$(echo "$wlan_and_bt_macs" | tail -n 1)
|
||||
else
|
||||
log_error "Unknown mac address scheme for: $eth_mac"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
prepare_and_set_wlan_mac_address "$wlan_mac"
|
||||
ret_wlan=$?
|
||||
if [ $ret_wlan -ne 0 ]; then
|
||||
log_error "Failed to set wlan mac address"
|
||||
ret="$ret_wlan"
|
||||
fi
|
||||
|
||||
prepare_and_set_bt_mac_address "$bt_addr"
|
||||
ret_bt=$?
|
||||
if [ $ret_bt -ne 0 ]; then
|
||||
log_error "Failed to set bluetooth mac address"
|
||||
ret="$ret_bt"
|
||||
fi
|
||||
|
||||
exit "$ret"
|
||||
}
|
||||
|
||||
|
||||
|
||||
if [ "$1" = "-h" ]; then
|
||||
echo "$help_text"
|
||||
echo "Usage:"
|
||||
echo " $0"
|
||||
echo " $0 -l <loglevel> # loglevel being between 0 (errors) and 2 (info)"
|
||||
exit 0
|
||||
elif [ "$1" = "-l" ]; then
|
||||
log_level="$2"
|
||||
fi
|
||||
|
||||
main
|
||||
|
|
|
|||
Loading…
Reference in New Issue