1#!/bin/sh -e 2# 3# This script is run if the interface (recognized by its MAC address) lacks 4# a rule for persistent naming. 5# 6# If there is already a persistent rule with that interface name then the 7# current interface needs to be renamed. 8# 9# If the interface needs to be renamed, a NAME=value pair will be printed 10# on stdout to allow udev to IMPORT it. Then a rule for the MAC address and 11# interface name is written. 12# 13# (C) 2006 Marco d'Itri <md@Linux.IT> 14# 15# This program is free software; you can redistribute it and/or modify it 16# under the terms of the GNU General Public License as published by the 17# Free Software Foundation version 2 of the License. 18 19RULES_FILE='/etc/udev/rules.d/70-persistent-net.rules' 20 21. /lib/udev/rule_generator.functions 22 23interface_name_taken() { 24 local value="$(find_all_rules 'NAME=' $INTERFACE)" 25 if [ "$value" ]; then 26 return 0 27 else 28 return 1 29 fi 30} 31 32find_next_available() { 33 raw_find_next_available "$(find_all_rules 'NAME=' "$1")" 34} 35 36write_rule() { 37 local match="$1" 38 local name="$2" 39 local comment="$3" 40 41 { 42 if [ "$PRINT_HEADER" ]; then 43 PRINT_HEADER= 44 echo "# This file was automatically generated by the $0" 45 echo "# program, probably run by the persistent-net-generator.rules rules file." 46 echo "#" 47 echo "# You can modify it, as long as you keep each rule on a single line." 48 fi 49 50 echo "" 51 [ "$comment" ] && echo "# $comment" 52 echo "SUBSYSTEM==\"net\", $match, NAME=\"$name\"" 53 } >> $RULES_FILE 54} 55 56# used only if $RULES_FILE is empty, like on installation 57if [ "$1" = "all_interfaces" ]; then 58 if [ -e $RULES_FILE ]; then 59 printf "$RULES_FILE exists, persistent interface names\nnot saved.\n" >&2 60 exit 0 61 fi 62 63 if [ ! -e /sys/class/net/ ]; then 64 echo "/sys/class/net/ is not available, persistent interface names not saved." >&2 65 exit 0 66 fi 67 68 cd /sys/class/net/ || return 0 69 70 for INTERFACE in *; do 71 case $INTERFACE in 72 eth*|ath*|wlan*|ra*|sta*) ;; 73 *) continue ;; 74 esac 75 76 INTERFACE="$INTERFACE" DEVPATH="/class/net/$INTERFACE" \ 77 /lib/udev/write_net_rules || true 78 done 79 80 exit 0 81fi 82 83if [ -z "$INTERFACE" ]; then 84 echo "Missing \$INTERFACE." >&2 85 exit 1 86fi 87 88if [ "$1" ]; then 89 MAC_ADDR="$1" 90else 91 MAC_ADDR=$(sysread address) 92fi 93 94if [ -z "$MAC_ADDR" ]; then 95 echo "No MAC address for $INTERFACE." >&2 96 exit 1 97fi 98if [ "$MAC_ADDR" = "00:00:00:00:00:00" ]; then 99 echo "NULL MAC address for $INTERFACE." >&2 100 exit 1 101fi 102 103# Prevent concurrent processes from modifying the file at the same time. 104lock_rules_file 105 106# Check if the rules file is writeable. 107choose_rules_file 108 109# If a rule using the current name already exists then find a new name and 110# report it to udev which will rename the interface. 111basename=${INTERFACE%%[0-9]*} 112if interface_name_taken; then 113 INTERFACE="$basename$(find_next_available "$basename[0-9]*")" 114 if [ ! -t 1 ]; then 115 echo "INTERFACE_NEW=$INTERFACE" 116 fi 117fi 118 119# the DRIVERS key is needed to not match bridges and VLAN sub-interfaces 120match="DRIVERS==\"?*\", ATTRS{address}==\"$MAC_ADDR\"" 121if [ $basename = "ath" -o $basename = "wlan" ]; then 122 match="$match, ATTRS{type}==\"1\"" # do not match the wifi* interfaces 123fi 124 125write_rule "$match" "$INTERFACE" "$COMMENT" 126 127unlock_rules_file 128 129exit 0 130