:: [DNG] if2mac V0.3 init.d service fo…
Top Page
Delete this message
Reply to this message
Author: tito
Date:  
To: dng
Subject: [DNG] if2mac V0.3 init.d service for persistent network interface names
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--->