From deb3aaa4f057ed913350f2cee77c61e30a36d055 Mon Sep 17 00:00:00 2001 From: Julian Date: Wed, 15 Jan 2025 06:54:55 +0000 Subject: [PATCH] [busybox] 1.37.0-8: add support for networkmanager & fix mdev helper mac addr bug mdev-helper-settle-nics now supports another argument '--notify-udev' and may only be used in mdev.conf. PROBLEMS Some programs e.g. NetworkManager relies on udev events to wait for udev to populate devices, which may not work on pure mdev-based systems. Since NetworkManager 1.4.0, MAC address spoofing is enabled by default, making mdev-helper-settle-nics unable to get original mac addresses (also called permaddrs) from nics, which will cause infinite increasing interface names when booting OS or nics are replugged. SOLUTIONS By using libudev-helper provided by libudev-zero, the script can trigger NetworkManager *correctly*; By using external tools like iproute2 or ethtool, it is now able to get permaddrs and works well even when NetworkManager is running. If neither of the tools above exist, the original method, i.e. reading from sysfs, will be used. reverts: 9806fe4 (incorrect way to fix mac addr bug) refs: NetworkManager/NetworkManager@4f6c91d (spoofing enabled by default), NetworkManager/NetworkManager@1b49f94 (spoofing implementation) --- PKGBUILD | 6 +- mdev-helper-settle-nics | 148 +++++++++++++++++++++++++--------------- mdev.conf | 2 +- 3 files changed, 96 insertions(+), 60 deletions(-) mode change 100644 => 100755 mdev-helper-settle-nics diff --git a/PKGBUILD b/PKGBUILD index 30862d5f..4687bc99 100644 --- a/PKGBUILD +++ b/PKGBUILD @@ -2,7 +2,7 @@ pkgname=busybox pkgver=1.37.0 -pkgrel=7 +pkgrel=8 pkgdesc="Utilities for rescue and embedded systems" arch=(x86_64 aarch64 riscv64 loongarch64) url="https://www.busybox.net" @@ -40,11 +40,11 @@ sha256sums=('3311dff32e746499f4df0d5df04d7eb396382d7e108bb9250e7b519b837043a4' 'a54856a9825e3aeb161a19c0665fa6f98695a4cf15ca66d864a8dbed0f6268fe' '69e028725a63763e21684fb0ce941f6a34a4b72bb328a0cab43b4d39d6d767dc' 'd090013b1537d43c3925bf69cb6bcd8ca304b91774ceb1b944ae6edd8714ad1f' - '9c6d96a3e0d044d0ebb39e00bcad0eceb98001146c807eea98b0685076ed1945' + '8fd346df4a87aee80fc959d4b817239c7cfeebe3a514ffd7dbe276eab401000b' 'ff1cd59bf41a658916459636b93bc98d8bfaf0482c5c879095c31116c88b0a00' '622d0a1743a127bab1fc15e5057034db52c7fa475298b8d085cfc7c046ae5537' '3557692ba310fc114459819f690fdf76047d67c8146dddbb4cc9ad7b8d931b64' - 'b73dae2cc94111a28f235116bbee5f3c59e1b7075bfb593b622c5cfb1b016efb' + 'f79b25408a7071563cf0dee19a75bc35d56b1b8a724d3c8a871c59462f14cb89' 'f157359b7992e9d08da728b2c48c10f338e149e44856f3cb9665164c35f6e232' 'f641a4d722dfaeb70e43ee87d8b1ce6ecadc0aec4ee21bdc28bbe4564dd743f4' '32c89049dfcb5de3b2591b1039b25aa8ad83f0af9b6782ef460ed4dde7a8493d' diff --git a/mdev-helper-settle-nics b/mdev-helper-settle-nics old mode 100644 new mode 100755 index 75df05ba..f44fe93d --- a/mdev-helper-settle-nics +++ b/mdev-helper-settle-nics @@ -1,5 +1,6 @@ #!/bin/sh # Copyright (c) 2012, Piotr Karbowski +# Copyright (c) 2025, Julian Droske # All rights reserved. # # Redistribution and use in source and binary forms, with or without modification, are @@ -28,7 +29,9 @@ # First it will run nameif to rename interfaces if configured in /etc/mactab # Then it will dump known interfaces to new mactab file. # Next it will parse old /etc/mactab and copy all interfaces which wasnt added in step two. -# On the end, it will replace /etc/mactab with the new one. +# And it will replace /etc/mactab with the new one, controlled by '--write-mactab'. +# Finally it will dispatch a udev event for current nic if executed by mdev, controlled by +# '--notify-udev'. # Info: Step two will only care about eth*, wlan*, ath*, wifi* and ra* interfaces. @@ -39,6 +42,10 @@ if [ -n "${USER}" ] && [ "${USER}" != 'root' ]; then exit 1 fi +command_exists() { + command -v "${1}" >/dev/null 2>&1 +} + in_comma_list() { # Check whatever $1 is in the comma separated list $2. local x @@ -51,6 +58,30 @@ in_comma_list() { return 1 } +get_nic_macaddr() { + # Try to get real mac address from nic $1. + local nic="$1" + local macaddr + if command_exists ethtool; then + macaddr="$(ethtool -P ${nic} 2>/dev/null)" + macaddr="${macaddr##*: }" + if [ -n "${macaddr}" ] && [ "${macaddr}" != 'not set' ]; then + echo "${macaddr}" + return 0 + fi + fi + if command_exists ip; then + macaddr="$(ip link show dev ${nic} |grep permaddr)" + macaddr="${macaddr##*permaddr }" + if [ -n "${macaddr}" ]; then + echo "${macaddr}" + return 0 + fi + fi + # Fallback to get mac address from sysfs. + cat "/sys/class/net/${nic}/address" +} + lockfile='/etc/mactab.settle-nics_lockfile' while : ; do if ! test -f "${lockfile}" && ( set -o noclobber; echo "$$" > "${lockfile}") 2> /dev/null; then @@ -60,27 +91,28 @@ while : ; do fi done -case "$1" in - --write-mactab) - write_mactab='true' - tmpfile="/etc/mactab.settle-nics_tmpfile.$$" - rm -f "${tmpfile}" - ;; - '') - tmpfile='/dev/null' - ;; - *) - echo "Wrong argument!" >&2 - exit 1 - ;; - -esac +for opt in "$@"; do + case "${opt}" in + --write-mactab) + write_mactab='true' + tmpfile="/etc/mactab.settle-nics_tmpfile.$$" + rm -f "${tmpfile}" + ;; + --notify-udev) + notify_udev='true' + ;; + '') + tmpfile='/dev/null' + ;; + *) + echo "Wrong argument!" >&2 + exit 1 + ;; + esac +done trap 'status="$?"; rm -f "${lockfile}"; test -f "${tmpfile}" && rm -f "${tmpfile}"; exit "${status}"' INT TERM EXIT -# iwlwifi bug: must wait for several seconds for setting real MAC address -sleep 3 - # If we do have configured nics but the configured names are already used by something else, rename it to temp name. # I wish nameif or ifrename could be smart enough to do it itself... inconf_nics="" @@ -94,7 +126,7 @@ if [ -f '/etc/mactab' ]; then inconf_nics="${inconf_nics},${nic}" inconf_macs="${inconf_macs},${macaddr}" if [ -e "/sys/class/net/${nic}" ]; then - curr_macaddr="$(cat /sys/class/net/${nic}/address)" + curr_macaddr="$(get_nic_macaddr ${nic})" if [ "${curr_macaddr}" != "${macaddr}" ]; then # Okey, so kernel added another NIC with name which we preserved for other NIC. echo "Looks like '${nic}' is preserved. renaming current '${nic}' to '${nic}_tmp' ..." >&2 @@ -107,7 +139,7 @@ if [ -f '/etc/mactab' ]; then fi # Run nameif so all interfaces will be renamed to specified names. -if command -v nameif >/dev/null 2>&1 && test -f /etc/mactab; then +if command_exists nameif && test -f /etc/mactab; then nameif fi @@ -128,47 +160,51 @@ for nic in /sys/class/net/*_tmp; do done done -if [ "${write_mactab}" != 'true' ]; then - # We don't want write mactab thus there is no reason to check the network interfaces' mac addresses and so on... - exit 0 -fi - -printf '%s\n' "# Generated by settle-nics from mdev-like-a-boss." >> "${tmpfile}" +# We don't want write mactab thus there is no reason to check the network interfaces' mac addresses and so on... +if [ "${write_mactab}" = 'true' ]; then + printf '%s\n' "# Generated by settle-nics from mdev-like-a-boss." >> "${tmpfile}" -# First get all the macs of current accessable nics -detected_nics="" -detected_macs="" -for i in /sys/class/net/*; do - unset device macaddr - device="${i##*/}" - case "${device}" in - *_tmp) - ;; - eth[0-9]*|wlan[0-9]*|ath[0-9]*|wifi[0-9]*|ra[0-9]*) - macaddr="$(cat /sys/class/net/${device}/address 2>/dev/null)" - if [ -n "${macaddr}" ] && ! in_comma_list "${macaddr}" "${inconf_macs}" && ! in_comma_list "${device}" "${inconf_nics}"; then - detected_nics="${detected_nics},${device}" - detected_macs="${detected_macs},${macaddr}" - printf '%-15s %s\n' "${device}" "${macaddr}" >> "${tmpfile}" - fi - ;; - esac -done - -# Now lets parse current /etc/mactab so we no loose any configured but not available at this moment interface. -if [ -f '/etc/mactab' ]; then - unset device macaddr - while read device macaddr; do + # First get all the macs of current accessable nics + detected_nics="" + detected_macs="" + for i in /sys/class/net/*; do + unset device macaddr + device="${i##*/}" case "${device}" in - '#'*) + *_tmp) ;; - *) - if [ -n "${macaddr}" ] && ! in_comma_list "${macaddr}" "${detected_macs}" && ! in_comma_list "${device}" "${detected_nics}"; then + eth[0-9]*|wlan[0-9]*|ath[0-9]*|wifi[0-9]*|ra[0-9]*) + macaddr="$(get_nic_macaddr ${device} 2>/dev/null)" + if [ -n "${macaddr}" ] && ! in_comma_list "${macaddr}" "${inconf_macs}" && ! in_comma_list "${device}" "${inconf_nics}"; then + detected_nics="${detected_nics},${device}" + detected_macs="${detected_macs},${macaddr}" printf '%-15s %s\n' "${device}" "${macaddr}" >> "${tmpfile}" fi ;; esac - done < '/etc/mactab' + done + + # Now lets parse current /etc/mactab so we no loose any configured but not available at this moment interface. + if [ -f '/etc/mactab' ]; then + unset device macaddr + while read device macaddr; do + case "${device}" in + '#'*) + ;; + *) + if [ -n "${macaddr}" ] && ! in_comma_list "${macaddr}" "${detected_macs}" && ! in_comma_list "${device}" "${detected_nics}"; then + printf '%-15s %s\n' "${device}" "${macaddr}" >> "${tmpfile}" + fi + ;; + esac + done < '/etc/mactab' + fi + + mv "${tmpfile}" '/etc/mactab' fi -mv "${tmpfile}" '/etc/mactab' +# It's time to dispatch a udev event +# This only works when in mdev.conf as which sets a necessary envar SEQNUM, we may not set a custom one +if [ "${notify_udev}" = 'true' ] && [ -n "${SEQNUM}" ] && command_exists libudev-helper; then + libudev-helper +fi diff --git a/mdev.conf b/mdev.conf index 00f60c13..3239ae49 100644 --- a/mdev.conf +++ b/mdev.conf @@ -87,7 +87,7 @@ msr([0-9]+) root:root 600 =cpu/%1/msr SUBSYSTEM=usb;DEVTYPE=usb_device;.* root:root 660 */usr/bin/mdev-helper-dev-bus-usb SUBSYSTEM=sound;.* root:audio 660 @/usr/bin/mdev-helper-sound-control SUBSYSTEM=block;.* root:disk 660 */usr/bin/mdev-helper-storage-device --SUBSYSTEM=net;DEVPATH=.*/net/.*;.* root:root 600 @/usr/bin/mdev-helper-settle-nics --write-mactab +-SUBSYSTEM=net;DEVPATH=.*/net/.*;.* root:root 600 @/usr/bin/mdev-helper-settle-nics --write-mactab --notify-udev # libudev-zero helper SUBSYSTEM=drm;.* root:video 660 */usr/bin/libudev-helper