Hi,
attached and inline you will find a improved and more robust version
of if2mac initscript and a example configuration file.
The script is tested only on 5 systems, my desktop (3 nics)
and my 2 routers (8/12 nics + wlan) and 2 NAS and seems to work.
If there are any bold testers who want to give it a try
their feedback, hints, critics and improvements are
appreciated.
What works:
1) basic renaming of interfaces based on configuration file
is stable.
2) Interfaces of type en*, et*, wl* unknown to the config
file are added to the end of the list on the fly and renamed too
as they would stay as ethXrenamed after the first pass.
A warning is printed and the user is invited to add them
to the config file. If you know a better solution please tell me.
3) config file format same as previous versions
What deos not work
1) interaction with udev/eudev in the case of rmmod/insmod.
What I changed in this version:
1) mac address from the config file are validated to avoid
to suck in garbage (empty lines etc.)
mac address retrieved from /sysfs are validated also
just for paranoia.
Ciao,
Tito
<--- snip ---->
#!/bin/sh
### BEGIN INIT INFO
# Provides: if2mac
# Required-Start: mountkernfs
# Required-Stop:
# Should-Start:
# Should-Stop:
# Default-Start: S
# Default-Stop:
# X-Start-Before: $network
# X-Start-After:
# Short-Description: Rename network interface based on MAC address
# Description: Rename network interface based on MAC address on boot.
### END INIT INFO
# if2mac v. 0.3 (C) 2020-2021 T.R. <farmatito@???> GPLv2
PATH=/sbin:/bin:/usr/sbin:/usr/bin
. /lib/lsb/init-functions
NAME=if2mac
SCRIPTNAME="/etc/init.d/$NAME"
DESC="Rename network interfaces based on MAC address"
CONFIG_FILE="/etc/if2mac.conf"
SUFFIX="renamed"
# Paths that must exist and programs needed
SYSFS_NET="/sys/class/net"
SED="/bin/sed"
if test -x "/bin/ip" ; then
IP="/bin/ip"
elif test -x "/sbin/ip" ; then
IP="/sbin/ip"
else
log_warning_msg "Command $IP not found"
exit 1
fi
if test ! -x "$SED" ; then
log_warning_msg "Command $SED not found"
exit 1
fi
if test ! -f "$CONFIG_FILE" ; then
log_warning_msg "Configuration file $CONFIG_FILE not found"
exit 1
fi
if test ! -d "$SYSFS_NET" ; then
log_warning_msg "Directory $SYSFS_NET not found"
exit 1
fi
# We source for WIRED_MAC_LIST, WIRELESS_MAC_LIST,
# WIRED_PREFIX and WIRELESS_PREFIX.
# shellcheck source=/etc/if2mac.conf
. "$CONFIG_FILE"
fnmatch() { case "$2" in $1) return 0;; *) return 1 ;; esac ; }
iface_rename () {
"$IP" link set "$1" down
"$IP" link set "$1" name "$2"
RET=$?
if [ "x$RET" = "x0" ] ; then
log_action_msg "renamed $1 to $2"
"$IP" link set "$2" up
return 0
else
log_warning_msg "failed to rename $1 to $2"
"$IP" link set "$1" up
return 1
fi
}
ismac() {
case $1
in
[0-9a-f][0-9a-f]:[0-9a-z][0-9a-f]:[0-9a-f][0-9a-f]:[0-9a-f][0-9a-f]:[0-9a-f][0-9a-f]:[0-9a-f][0-9a-f])
return 0;
;;
*)
log_warning_msg "Invalid MAC address $1"
return 1;
;;
esac
}
if2mac() {
# We need two passes to allow interface swapping
log_action_msg "Pass 1..."
# We exit if there are no interfaces in list
INTERFACE_LIST=$(ls "$SYSFS_NET")
if test -z "$INTERFACE_LIST" ; then
log_daemon_msg "No interfaces detected!"
return 0
fi
for IFNAME in $INTERFACE_LIST
do
# PREFIXES AND PATHS:
# en Ethernet wired
# et Ethernet wired old
# ib InfiniBand
# sl Serial line IP (slip)
# wl Wireless local area network (WLAN)
# ww Wireless wide area network (WWAN)
# WARNING: Only en, et and wl are supported.
if fnmatch 'en*' "$IFNAME" || fnmatch 'et*' "$IFNAME" || fnmatch 'wl*' "$IFNAME"; then
iface_rename "$IFNAME" "$IFNAME$SUFFIX"
fi
done
log_action_msg "Pass 2..."
# We exit if there are no interfaces in list
INTERFACE_LIST=$(ls "$SYSFS_NET")
if test -z "INTERFACE_$LIST" ; then
log_daemon_msg "No interfaces detected!"
return 0
fi
for IFNAME in $INTERFACE_LIST
do
if fnmatch 'en*' "$IFNAME" || fnmatch 'et*' "$IFNAME" || fnmatch 'wl*' "$IFNAME"; then
PREFIX="$WIRED_PREFIX"
MAC_LIST="$WIRED_MAC_LIST"
if fnmatch 'wl*' "$IFNAME" ; then
PREFIX="$WIRELESS_PREFIX"
MAC_LIST="$WIRELESS_MAC_LIST"
fi
IFNAME_MAC=$(cat "$SYSFS_NET/$IFNAME/address")
# Convert to lowercase
IFNAME_MAC=$(echo "$IFNAME_MAC" | "$SED" 's/[A-Z]/\L&/g')
NUM=0
FOUND=0
for CONFIG_MAC in $MAC_LIST
do
# Convert to lowercase
CONFIG_MAC=$(echo "$CONFIG_MAC" | "$SED" 's/[A-Z]/\L&/g')
# Check validity of input from config file
# and of the macddress retrieved from /sys.
if ismac "$CONFIG_MAC" && ismac "$IFNAME_MAC"; then
if [ "$CONFIG_MAC" = "$IFNAME_MAC" ] ; then
FOUND=1
iface_rename "$IFNAME" "$PREFIX$NUM" "$CONFIG_MAC"
break
fi
NUM=$((NUM + 1))
fi
done
if [ "x$FOUND" = "x0" ] ; then
log_warning_msg "MAC address $IFNAME_MAC not found in $CONFIG_FILE. Please add it."
iface_rename "$IFNAME" "$PREFIX$NUM" "$IFNAME_MAC"
# Add it to end of the list or if there are more than one they will get all the same number
if fnmatch 'en*' "$IFNAME" || fnmatch 'et*' "$IFNAME" ; then
WIRED_MAC_LIST="$WIRED_MAC_LIST $IFNAME_MAC"
else
WIRELESS_MAC_LIST="$WIRELESS_MAC_LIST $IFNAME_MAC"
fi
fi
fi
done
return 0
}
case "$1" in
start|reload|force-reload|restart)
log_action_msg "$DESC: $NAME"
if2mac
exit 0
;;
stop)
;;
*)
log_action_msg "Usage: $SCRIPTNAME {start|stop|reload|force-reload|restart}"
exit 2
;;
esac
exit 0
<---snip--->