| #!/bin/sh -e | |
| # This script is run to create persistent network device naming rules | |
| # based on properties of the device. | |
| # If the interface needs to be renamed, INTERFACE_NEW=<name> will be printed | |
| # on stdout to allow udev to IMPORT it. | |
| # variables used to communicate: | |
| # MATCHADDR MAC address used for the match | |
| # MATCHID bus_id used for the match | |
| # MATCHDEVID dev_id used for the match | |
| # MATCHDRV driver name used for the match | |
| # MATCHIFTYPE interface type match | |
| # COMMENT comment to add to the generated rule | |
| # INTERFACE_NAME requested name supplied by external tool | |
| # INTERFACE_NEW new interface name returned by rule writer | |
| # Copyright (C) 2006 Marco d'Itri <md@Linux.IT> | |
| # Copyright (C) 2007 Kay Sievers <kay.sievers@vrfy.org> | |
| # | |
| # This program is free software: you can redistribute it and/or modify | |
| # it under the terms of the GNU General Public License as published by | |
| # the Free Software Foundation, either version 2 of the License, or | |
| # (at your option) any later version. | |
| # | |
| # This program is distributed in the hope that it will be useful, | |
| # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| # GNU General Public License for more details. | |
| # | |
| # You should have received a copy of the GNU General Public License | |
| # along with this program. If not, see <http://www.gnu.org/licenses/>. | |
| # debug, if UDEV_LOG=<debug> | |
| if [ -n "$UDEV_LOG" ]; then | |
| if [ "$UDEV_LOG" -ge 7 ]; then | |
| set -x | |
| fi | |
| fi | |
| RULES_FILE='/etc/udev/rules.d/70-persistent-net.rules' | |
| . /lib/udev/rule_generator.functions | |
| interface_name_taken() { | |
| local value="$(find_all_rules 'NAME=' $INTERFACE)" | |
| if [ "$value" ]; then | |
| return 0 | |
| else | |
| return 1 | |
| fi | |
| } | |
| find_next_available() { | |
| raw_find_next_available "$(find_all_rules 'NAME=' "$1")" | |
| } | |
| write_rule() { | |
| local match="$1" | |
| local name="$2" | |
| local comment="$3" | |
| { | |
| if [ "$PRINT_HEADER" ]; then | |
| PRINT_HEADER= | |
| echo "# This file was automatically generated by the $0" | |
| echo "# program, run by the persistent-net-generator.rules rules file." | |
| echo "#" | |
| echo "# You can modify it, as long as you keep each rule on a single" | |
| echo "# line, and change only the value of the NAME= key." | |
| fi | |
| echo "" | |
| [ "$comment" ] && echo "# $comment" | |
| echo "SUBSYSTEM==\"net\", ACTION==\"add\"$match, NAME=\"$name\"" | |
| } >> $RULES_FILE | |
| } | |
| if [ -z "$INTERFACE" ]; then | |
| echo "missing \$INTERFACE" >&2 | |
| exit 1 | |
| fi | |
| # Prevent concurrent processes from modifying the file at the same time. | |
| lock_rules_file | |
| # Check if the rules file is writeable. | |
| choose_rules_file | |
| # the DRIVERS key is needed to not match bridges and VLAN sub-interfaces | |
| if [ "$MATCHADDR" ]; then | |
| match="$match, DRIVERS==\"?*\", ATTR{address}==\"$MATCHADDR\"" | |
| fi | |
| if [ "$MATCHDRV" ]; then | |
| match="$match, DRIVERS==\"$MATCHDRV\"" | |
| fi | |
| if [ "$MATCHDEVID" ]; then | |
| match="$match, ATTR{dev_id}==\"$MATCHDEVID\"" | |
| fi | |
| if [ "$MATCHID" ]; then | |
| match="$match, KERNELS==\"$MATCHID\"" | |
| fi | |
| if [ "$MATCHIFTYPE" ]; then | |
| match="$match, ATTR{type}==\"$MATCHIFTYPE\"" | |
| fi | |
| if [ -z "$match" ]; then | |
| echo "missing valid match" >&2 | |
| unlock_rules_file | |
| exit 1 | |
| fi | |
| basename=${INTERFACE%%[0-9]*} | |
| match="$match, KERNEL==\"$basename*\"" | |
| if [ "$INTERFACE_NAME" ]; then | |
| # external tools may request a custom name | |
| COMMENT="$COMMENT (custom name provided by external tool)" | |
| if [ "$INTERFACE_NAME" != "$INTERFACE" ]; then | |
| INTERFACE=$INTERFACE_NAME; | |
| echo "INTERFACE_NEW=$INTERFACE" | |
| fi | |
| else | |
| # if a rule using the current name already exists, find a new name | |
| if interface_name_taken; then | |
| INTERFACE="$basename$(find_next_available "$basename[0-9]*")" | |
| # prevent INTERFACE from being "eth" instead of "eth0" | |
| [ "$INTERFACE" = "${INTERFACE%%[ \[\]0-9]*}" ] && INTERFACE=${INTERFACE}0 | |
| echo "INTERFACE_NEW=$INTERFACE" | |
| fi | |
| fi | |
| write_rule "$match" "$INTERFACE" "$COMMENT" | |
| unlock_rules_file | |
| exit 0 |