You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

903 lines
26 KiB

#!/bin/sh
# shellcheck disable=SC2034
IFNETFILE="/tmp/bootnetif"
is_ip() {
echo "$1" | {
IFS=. read -r a b c d
test "$a" -ge 0 -a "$a" -le 255 \
-a "$b" -ge 0 -a "$b" -le 255 \
-a "$c" -ge 0 -a "$c" -le 255 \
-a "$d" -ge 0 -a "$d" -le 255 \
2> /dev/null
} && return 0
return 1
}
get_ip() {
local iface="$1" ip=""
ip=$(ip -f inet addr show "$iface")
ip=${ip%%/*}
ip=${ip##* }
echo "$ip"
}
iface_for_remote_addr() {
# shellcheck disable=SC2046
set -- $(ip route get to "$@" | sed 's/.*\bdev\b//p;q')
echo "$1"
}
iface_for_ip() {
# shellcheck disable=SC2046
set -- $(ip addr show to "$@")
echo "${2%:}"
}
iface_for_mac() {
local interface=""
local mac
mac="$(echo "$@" | sed 'y/ABCDEF/abcdef/')"
for interface in /sys/class/net/*; do
if [ "$(cat "$interface"/address)" = "$mac" ]; then
echo "${interface##*/}"
fi
done
}
# get the iface name for the given identifier - either a MAC, IP, or iface name
iface_name() {
case "$1" in
??:??:??:??:??:?? | ??-??-??-??-??-??) iface_for_mac "$1" ;;
*:*:* | *.*.*.*) iface_for_ip "$1" ;;
*) echo "$1" ;;
esac
}
# list the configured interfaces
configured_ifaces() {
local IFACES="" iface_id="" rv=1
[ -e "/tmp/net.ifaces" ] && read -r IFACES < /tmp/net.ifaces
if { pidof udevd || pidof systemd-udevd; } > /dev/null; then
for iface_id in $IFACES; do
printf "%s\n" "$(iface_name "$iface_id")"
rv=0
done
else
warn "configured_ifaces called before udev is running"
echo "$IFACES"
[ -n "$IFACES" ] && rv=0
fi
return $rv
}
all_ifaces_up() {
local iface="" IFACES=""
[ -e "/tmp/net.ifaces" ] && read -r IFACES < /tmp/net.ifaces
for iface in $IFACES; do
[ -e /tmp/net."$iface".up ] || return 1
done
}
all_ifaces_setup() {
local iface="" IFACES=""
[ -e "/tmp/net.ifaces" ] && read -r IFACES < /tmp/net.ifaces
for iface in $IFACES; do
[ -e /tmp/net."$iface".did-setup ] || return 1
done
}
get_netroot_ip() {
local prefix="" server="" rest=""
splitsep "$1" ":" prefix server rest
case $server in
[0-9]*\.[0-9]*\.[0-9]*\.[0-9]*)
echo "$server"
return 0
;;
esac
return 1
}
ip_is_local() {
strstr "$(ip route get "$@" 2> /dev/null)" " via "
}
ifdown() {
local netif="$1"
# ip down/flush ensures that routing info goes away as well
ip link set "$netif" down
ip addr flush dev "$netif"
echo "#empty" > /etc/resolv.conf
rm -f -- /tmp/net."$netif".did-setup
[ -z "$DO_VLAN" ] \
&& [ -e /sys/class/net/"$netif"/address ] \
&& rm -f -- "/tmp/net.$(cat /sys/class/net/"$netif"/address).did-setup"
# TODO: send "offline" uevent?
}
setup_net() {
local netif="$1" f="" gw_ip="" netroot_ip="" iface="" IFACES=""
local _p
[ -e /tmp/net."$netif".did-setup ] && return
[ -z "$DO_VLAN" ] \
&& [ -e /sys/class/net/"$netif"/address ] \
&& [ -e "/tmp/net.$(cat /sys/class/net/"$netif"/address).did-setup" ] && return
[ -e "/tmp/net.ifaces" ] && read -r IFACES < /tmp/net.ifaces
[ -z "$IFACES" ] && IFACES="$netif"
# run the scripts written by ifup
# shellcheck disable=SC1090
[ -e /tmp/net."$netif".hostname ] && . /tmp/net."$netif".hostname
# shellcheck disable=SC1090
[ -e /tmp/net."$netif".override ] && . /tmp/net."$netif".override
# shellcheck disable=SC1090
[ -e /tmp/dhclient."$netif".dhcpopts ] && . /tmp/dhclient."$netif".dhcpopts
# set up resolv.conf
[ -e /tmp/net."$netif".resolv.conf ] \
&& awk '!array[$0]++' /tmp/net."$netif".resolv.conf > /etc/resolv.conf
# shellcheck disable=SC1090
[ -e /tmp/net."$netif".gw ] && . /tmp/net."$netif".gw
# add static route
for _p in $(getargs rd.route); do
route_to_var "$_p" || continue
[ -n "$route_dev" ] && [ "$route_dev" != "$netif" ] && continue
ip route add "$route_mask" ${route_gw:+via $route_gw} ${route_dev:+dev $route_dev}
if strstr "$route_mask" ":"; then
printf -- "%s\n" "$route_mask ${route_gw:+via $route_gw} ${route_dev:+dev $route_dev}" \
> /tmp/net.route6."$netif"
else
printf -- "%s\n" "$route_mask ${route_gw:+via $route_gw} ${route_dev:+dev $route_dev}" \
> /tmp/net.route."$netif"
fi
done
# If a static route was necessary to reach the gateway, the
# first gateway setup call will have failed with
# RTNETLINK answers: Network is unreachable
# Replace the default route again after static routes to cover
# this scenario.
# shellcheck disable=SC1090
[ -e /tmp/net."$netif".gw ] && . /tmp/net."$netif".gw
# Handle STP Timeout: arping the default gateway.
# (or the root server, if a) it's local or b) there's no gateway.)
# Note: This assumes that if no router is present the
# root server is on the same subnet.
# Get DHCP-provided router IP, or the cmdline-provided "gw=" argument
[ -n "$new_routers" ] && gw_ip=${new_routers%%,*}
[ -n "$gw" ] && gw_ip=$gw
# Get the "netroot" IP (if there's an IP address in there)
netroot_ip=$(get_netroot_ip "$netroot")
# try netroot if it's local (or there's no gateway)
if ip_is_local "$netroot_ip" || [ -z "$gw_ip" ]; then
dest="$netroot_ip"
else
dest="$gw_ip"
fi
unset layer2
if [ -f /sys/class/net/"$netif"/device/layer2 ]; then
read -r layer2 < /sys/class/net/"$netif"/device/layer2
fi
if [ "$layer2" != "0" ] && [ -n "$dest" ] && ! strstr "$dest" ":"; then
if command -v arping2 > /dev/null; then
arping2 -q -C 1 -c 60 -I "$netif" "$dest" || info "Resolving $dest via ARP on $netif failed"
else
arping -q -f -w 60 -I "$netif" "$dest" || info "Resolving $dest via ARP on $netif failed"
fi
fi
unset layer2
: > /tmp/net."$netif".did-setup
[ -z "$DO_VLAN" ] \
&& [ -e /sys/class/net/"$netif"/address ] \
&& : > "/tmp/net.$(cat /sys/class/net/"$netif"/address).did-setup"
}
save_netinfo() {
local netif="$1" IFACES="" f="" i=""
[ -e /tmp/net.ifaces ] && read -r IFACES < /tmp/net.ifaces
# Add $netif to the front of IFACES (if it's not there already).
set -- "$netif"
for i in $IFACES; do [ "$i" != "$netif" ] && set -- "$@" "$i"; done
IFACES="$*"
for i in $IFACES; do
for f in "/tmp/dhclient.$i."*; do
[ -f "$f" ] && cp -f "$f" /tmp/net."${f#/tmp/dhclient.}"
done
done
echo "$IFACES" > /tmp/.net.ifaces.new
mv /tmp/.net.ifaces.new /tmp/net.ifaces
}
set_ifname() {
local name="$1" mac="$2" num=-1 n=""
# if it's already set, return the existing name
for n in $(getargs ifname=); do
strstr "$n" "$mac" && echo "${n%%:*}" && return
done
# otherwise, pick a new name and use that
while :; do
num=$((num + 1))
[ -e /sys/class/net/"$name"$num ] && continue
for n in $(getargs ifname=); do
[ "$name$num" = "${n%%:*}" ] && continue 2
done
break
done
echo "ifname=$name$num:$mac" >> /etc/cmdline.d/45-ifname.conf
echo "$name$num"
}
# pxelinux provides macaddr '-' separated, but we need ':'
fix_bootif() {
local macaddr=${1}
local IFS='-'
# shellcheck disable=SC2086
macaddr=$(printf '%s:' ${macaddr})
macaddr=${macaddr%:}
# strip hardware type field from pxelinux
[ -n "${macaddr%??:??:??:??:??:??}" ] && macaddr=${macaddr#??:}
# return macaddr with lowercase alpha characters expected by udev
echo "$macaddr" | sed 'y/ABCDEF/abcdef/'
}
ibft_to_cmdline() {
local iface=""
modprobe -q iscsi_ibft
(
for iface in /sys/firmware/ibft/ethernet*; do
local mac="" dev=""
local dhcp="" ip="" gw="" mask="" hostname=""
local dns1 dns2
[ -e "${iface}"/mac ] || continue
read -r mac < "${iface}"/mac
[ -z "$mac" ] && continue
dev=$(set_ifname ibft "$mac")
[ -e /tmp/net."${dev}".has_ibft_config ] && continue
[ -e "${iface}"/flags ] && read -r flags < "${iface}"/flags
# Skip invalid interfaces
awk -- 'BEGIN { exit (!and('"$flags"',1)) }' || continue
# Skip interfaces not used for booting unless using multipath
if ! getargbool 0 rd.iscsi.mp; then
awk -- 'BEGIN { exit (!and('"$flags"',2)) }' || continue
fi
[ -e "${iface}"/dhcp ] && read -r dhcp < "${iface}"/dhcp
[ -e "${iface}"/origin ] && read -r origin < "${iface}"/origin
[ -e "${iface}"/ip-addr ] && read -r ip < "${iface}"/ip-addr
if [ -n "$ip" ]; then
case "$ip" in
*.*.*.*)
family=ipv4
;;
*:*)
family=ipv6
;;
esac
fi
if [ -n "$dhcp" ] || [ "$origin" -eq 3 ]; then
if [ "$family" = "ipv6" ]; then
echo "ip=$dev:dhcp6"
else
echo "ip=$dev:dhcp"
fi
elif [ -e "${iface}"/ip-addr ]; then
# skip not assigned ip adresses
[ "$ip" = "0.0.0.0" ] && continue
[ -e "${iface}"/gateway ] && read -r gw < "${iface}"/gateway
[ "$gateway" = "0.0.0.0" ] && unset gateway
[ -e "${iface}"/subnet-mask ] && read -r mask < "${iface}"/subnet-mask
[ -e "${iface}"/prefix-len ] && read -r prefix < "${iface}"/prefix-len
[ -e "${iface}"/primary-dns ] && read -r dns1 < "${iface}"/primary-dns
[ "$dns1" = "0.0.0.0" ] && unset dns1
[ -e "${iface}"/secondary-dns ] && read -r dns2 < "${iface}"/secondary-dns
[ "$dns2" = "0.0.0.0" ] && unset dns
[ -e "${iface}"/hostname ] && read -r hostname < "${iface}"/hostname
if [ "$family" = "ipv6" ]; then
if [ -n "$ip" ]; then
ip="[$ip]"
[ -n "$prefix" ] || prefix=64
ip="[${ip}/${prefix}]"
mask=
fi
if [ -n "$gw" ]; then
gw="[${gw}]"
fi
fi
if [ -n "$ip" ] && [ -n "$mask" -o -n "$prefix" ]; then
echo "ip=$ip::$gw:$mask:$hostname:$dev:none${dns1:+:$dns1}${dns2:+:$dns2}"
else
warn "${iface} does not contain a valid iBFT configuration"
warn "ip-addr=$ip"
warn "gateway=$gw"
warn "subnet-mask=$mask"
warn "hostname=$hostname"
fi
else
info "${iface} does not contain a valid iBFT configuration"
# shellcheck disable=SC2012
ls -l "${iface}" | vinfo
fi
if [ -e "${iface}"/vlan ]; then
read -r vlan < "${iface}"/vlan
if [ "$vlan" -ne "0" ]; then
case "$vlan" in
[0-9]*)
echo "vlan=$dev.$vlan:$dev"
echo "$mac" > /tmp/net."${dev}"."${vlan}".has_ibft_config
;;
*)
echo "vlan=$vlan:$dev"
echo "$mac" > /tmp/net."${vlan}".has_ibft_config
;;
esac
else
echo "$mac" > /tmp/net."${dev}".has_ibft_config
fi
else
echo "$mac" > /tmp/net."${dev}".has_ibft_config
fi
done
) >> /etc/cmdline.d/40-ibft.conf
}
parse_iscsi_root() {
local v
v=${1#iscsi:}
# extract authentication info
case "$v" in
*@*:*:*:*:*)
authinfo=${v%%@*}
v=${v#*@}
# allow empty authinfo to allow having an @ in iscsi_target_name like this:
# netroot=iscsi:@192.168.1.100::3260::iqn.2009-01.com.example:testdi@sk
if [ -n "$authinfo" ]; then
OLDIFS="$IFS"
IFS=:
# shellcheck disable=SC2086
set $authinfo
IFS="$OLDIFS"
if [ $# -gt 4 ]; then
warn "Wrong authentication info in iscsi: parameter!"
return 1
fi
iscsi_username=$1
iscsi_password=$2
if [ $# -gt 2 ]; then
iscsi_in_username=$3
iscsi_in_password=$4
fi
fi
;;
esac
# extract target ip
case "$v" in
[[]*[]]:*)
iscsi_target_ip=${v#[[]}
iscsi_target_ip=${iscsi_target_ip%%[]]*}
# shellcheck disable=SC1087
v=${v#[[]$iscsi_target_ip[]]:}
;;
*)
iscsi_target_ip=${v%%[:]*}
v=${v#$iscsi_target_ip:}
;;
esac
unset iscsi_target_name
# extract target name
case "$v" in
*:iqn.*)
iscsi_target_name=iqn.${v##*:iqn.}
v=${v%:iqn.*}:
;;
*:eui.*)
iscsi_target_name=eui.${v##*:eui.}
v=${v%:eui.*}:
;;
*:naa.*)
iscsi_target_name=naa.${v##*:naa.}
v=${v%:naa.*}:
;;
esac
# parse the rest
OLDIFS="$IFS"
IFS=:
# shellcheck disable=SC2086
set $v
IFS="$OLDIFS"
iscsi_protocol=$1
shift # ignored
iscsi_target_port=$1
shift
if [ -n "$iscsi_target_name" ]; then
if [ $# -eq 3 ]; then
iscsi_iface_name=$1
shift
fi
if [ $# -eq 2 ]; then
iscsi_netdev_name=$1
shift
fi
iscsi_lun=$1
shift
if [ $# -ne 0 ]; then
warn "Invalid parameter in iscsi: parameter!"
return 1
fi
return 0
fi
if [ $# -gt 3 ] && [ -n "$1$2" ]; then
if [ -z "$3" ] || [ "$3" -ge 0 ] 2> /dev/null; then
iscsi_iface_name=$1
shift
iscsi_netdev_name=$1
shift
fi
fi
iscsi_lun=$1
shift
iscsi_target_name=$(printf "%s:" "$@")
iscsi_target_name=${iscsi_target_name%:}
}
ip_to_var() {
local v=${1}:
local i
set --
while [ -n "$v" ]; do
if [ "${v#\[*:*:*\]:}" != "$v" ]; then
# handle IPv6 address
i="${v%%\]:*}"
i="${i##\[}"
set -- "$@" "$i"
v=${v#\[$i\]:}
else
set -- "$@" "${v%%:*}"
v=${v#*:}
fi
done
unset ip srv gw mask hostname dev autoconf macaddr mtu dns1 dns2
if [ $# -eq 0 ]; then
autoconf="error"
return 0
fi
if [ $# -eq 1 ]; then
# format: ip={dhcp|on|any|dhcp6|auto6|either6|single-dhcp}
# or
# ip=<ipv4-address> means anaconda-style static config argument cluster
autoconf="$1"
if strglob "$autoconf" "*.*.*.*"; then
# ip=<ipv4-address> means anaconda-style static config argument cluster:
# ip=<ip> gateway=<gw> netmask=<nm> hostname=<host> mtu=<mtu>
# ksdevice={link|bootif|ibft|<MAC>|<ifname>}
ip="$autoconf"
gw=$(getarg gateway=)
mask=$(getarg netmask=)
hostname=$(getarg hostname=)
dev=$(getarg ksdevice=)
autoconf="none"
mtu=$(getarg mtu=)
# handle special values for ksdevice
case "$dev" in
bootif | BOOTIF) dev=$(fix_bootif "$(getarg BOOTIF=)") ;;
link) dev="" ;; # FIXME: do something useful with this
ibft) dev="" ;; # ignore - ibft is handled elsewhere
esac
fi
return 0
fi
if [ "$2" = "dhcp" -o "$2" = "on" -o "$2" = "any" -o "$2" = "dhcp6" -o "$2" = "auto6" -o "$2" = "either6" ]; then
# format: ip=<interface>:{dhcp|on|any|dhcp6|auto6}[:[<mtu>][:<macaddr>]]
[ -n "$1" ] && dev="$1"
[ -n "$2" ] && autoconf="$2"
[ -n "$3" ] && mtu=$3
if [ -z "$5" ]; then
macaddr="$4"
else
macaddr="${4}:${5}:${6}:${7}:${8}:${9}"
fi
return 0
fi
# format: ip=<client-IP>:[<peer>]:<gateway-IP>:<netmask>:<client_hostname>:<interface>:{none|off|dhcp|on|any|dhcp6|auto6|ibft}:[:[<mtu>][:<macaddr>]]
[ -n "$1" ] && ip=$1
[ -n "$2" ] && srv=$2
[ -n "$3" ] && gw=$3
[ -n "$4" ] && mask=$4
[ -n "$5" ] && hostname=$5
[ -n "$6" ] && dev=$6
[ -n "$7" ] && autoconf=$7
case "$8" in
[0-9a-fA-F]*:* | [0-9]*.[0-9]*.[0-9]*.[0-9]*)
dns1="$8"
[ -n "$9" ] && dns2="$9"
;;
[0-9]*)
mtu="$8"
if [ -n "${9}" -a -z "${10}" ]; then
macaddr="${9}"
elif [ -n "${9}" -a -n "${10}" -a -n "${11}" -a -n "${12}" -a -n "${13}" -a -n "${14}" ]; then
macaddr="${9}:${10}:${11}:${12}:${13}:${14}"
fi
;;
*)
if [ -n "${9}" -a -z "${10}" ]; then
macaddr="${9}"
elif [ -n "${9}" -a -n "${10}" -a -n "${11}" -a -n "${12}" -a -n "${13}" -a -n "${14}" ]; then
macaddr="${9}:${10}:${11}:${12}:${13}:${14}"
fi
;;
esac
return 0
}
route_to_var() {
local v=${1}:
local i
set --
while [ -n "$v" ]; do
if [ "${v#\[*:*:*\]:}" != "$v" ]; then
# handle IPv6 address
i="${v%%\]:*}"
i="${i##\[}"
set -- "$@" "$i"
v=${v#\[$i\]:}
else
set -- "$@" "${v%%:*}"
v=${v#*:}
fi
done
unset route_mask route_gw route_dev
case $# in
2)
[ -n "$1" ] && route_mask="$1"
[ -n "$2" ] && route_gw="$2"
return 0
;;
3)
[ -n "$1" ] && route_mask="$1"
[ -n "$2" ] && route_gw="$2"
[ -n "$3" ] && route_dev="$3"
return 0
;;
*) return 1 ;;
esac
}
parse_ifname_opts() {
local IFS=:
# shellcheck disable=SC2086
set -- $1
case $# in
7)
ifname_if=$1
# udev requires MAC addresses to be lower case
ifname_mac=$(echo "$2:$3:$4:$5:$6:$7" | sed 'y/ABCDEF/abcdef/')
;;
21)
ifname_if=$1
# udev requires MAC addresses to be lower case
ifname_mac=$(echo "$2:$3:$4:$5:$6:$7:$8:$9:${10}:${11}:${12}:${13}:${14}:${15}:${16}:${17}:${18}:${19}:${20}:${21}" | sed 'y/ABCDEF/abcdef/')
;;
*)
die "Invalid arguments for ifname="
;;
esac
case $ifname_if in
eth[0-9] | eth[0-9][0-9] | eth[0-9][0-9][0-9] | eth[0-9][0-9][0-9][0-9])
warn "ifname=$ifname_if uses the kernel name space for interfaces"
warn "This can fail for multiple network interfaces and is discouraged!"
warn 'Please use a custom name like "netboot" or "bluesocket"'
warn "or use biosdevname and no ifname= at all."
;;
esac
}
# some network driver need long time to initialize, wait before it's ready.
wait_for_if_link() {
local cnt=0
local li
local timeout
timeout=$(getargs rd.net.timeout.iflink=)
timeout=${timeout:-60}
timeout=$((timeout * 10))
while [ $cnt -lt $timeout ]; do
li=$(ip link show dev "$@" 2> /dev/null)
[ -n "$li" ] && return 0
sleep 0.1
cnt=$((cnt + 1))
done
return 1
}
wait_for_if_up() {
local cnt=0
local li
local timeout
timeout=$(getargs rd.net.timeout.ifup=)
timeout=${timeout:-20}
timeout=$((timeout * 10))
while [ $cnt -lt $timeout ]; do
li=$(ip link show up dev "$@")
if [ -n "$li" ]; then
case "$li" in
*\<UP*)
return 0
;;
*\<*,UP\>*)
return 0
;;
*\<*,UP,*\>*)
return 0
;;
esac
fi
if strstr "$li" "LOWER_UP" \
&& strstr "$li" "state UNKNOWN" \
&& ! strstr "$li" "DORMANT"; then
return 0
fi
sleep 0.1
cnt=$((cnt + 1))
done
return 1
}
wait_for_route_ok() {
local cnt=0
local timeout
timeout=$(getargs rd.net.timeout.route=)
timeout=${timeout:-20}
timeout=$((timeout * 10))
while [ $cnt -lt $timeout ]; do
li=$(ip route show)
[ -n "$li" ] && [ -z "${li##*$1*}" ] && return 0
sleep 0.1
cnt=$((cnt + 1))
done
return 1
}
wait_for_ipv6_dad_link() {
local cnt=0
local timeout
timeout=$(getargs rd.net.timeout.ipv6dad=)
timeout=${timeout:-50}
timeout=$((timeout * 10))
while [ $cnt -lt $timeout ]; do
[ -n "$(ip -6 addr show dev "$@" scope link)" ] \
&& [ -z "$(ip -6 addr show dev "$@" scope link tentative)" ] \
&& return 0
[ -n "$(ip -6 addr show dev "$@" scope link dadfailed)" ] \
&& return 1
sleep 0.1
cnt=$((cnt + 1))
done
return 1
}
wait_for_ipv6_dad() {
local cnt=0
local timeout
timeout=$(getargs rd.net.timeout.ipv6dad=)
timeout=${timeout:-50}
timeout=$((timeout * 10))
while [ $cnt -lt $timeout ]; do
[ -n "$(ip -6 addr show dev "$@")" ] \
&& [ -z "$(ip -6 addr show dev "$@" tentative)" ] \
&& { ip -6 route list proto ra dev "$@" | grep -q ^default; } \
&& return 0
[ -n "$(ip -6 addr show dev "$@" dadfailed)" ] \
&& return 1
sleep 0.1
cnt=$((cnt + 1))
done
return 1
}
wait_for_ipv6_auto() {
local cnt=0
local timeout
timeout=$(getargs rd.net.timeout.ipv6auto=)
timeout=${timeout:-40}
timeout=$((timeout * 10))
while [ $cnt -lt $timeout ]; do
[ -z "$(ip -6 addr show dev "$@" tentative)" ] \
&& { ip -6 route list proto ra dev "$@" | grep -q ^default; } \
&& return 0
sleep 0.1
cnt=$((cnt + 1))
done
return 1
}
linkup() {
wait_for_if_link "$@" 2> /dev/null && ip link set "$@" up 2> /dev/null && wait_for_if_up "$@" 2> /dev/null
}
type hostname > /dev/null 2>&1 \
|| hostname() {
cat /proc/sys/kernel/hostname
}
iface_has_carrier() {
local cnt=0
local iface="$1" flags=""
local timeout
local iface_sys_path
[ -n "$iface" ] || return 2
iface_sys_path="/sys/class/net/$iface"
[ -d "$iface_sys_path" ] || return 2
timeout=$(getargs rd.net.timeout.carrier=)
timeout=${timeout:-10}
timeout=$((timeout * 10))
linkup "$1"
li=$(ip link show up dev "$iface")
strstr "$li" "NO-CARRIER" && _no_carrier_flag=1
while [ $cnt -lt $timeout ]; do
if [ -n "$_no_carrier_flag" ]; then
li=$(ip link show up dev "$iface")
# NO-CARRIER flag was cleared
strstr "$li" "NO-CARRIER" || return 0
elif ! [ -e "$iface_sys_path/carrier" ]; then
# sysfs not available and "NO-CARRIER" not displayed
return 0
fi
# double check the syscfs carrier flag
[ -e "$iface_sys_path/carrier" ] && [ "$(cat "$iface_sys_path"/carrier)" = 1 ] && return 0
sleep 0.1
cnt=$((cnt + 1))
done
return 1
}
iface_has_link() {
iface_has_carrier "$@"
}
iface_is_enslaved() {
local _li
_li=$(ip link show dev "$@")
strstr "$_li" " master " || return 1
return 0
}
find_iface_with_link() {
local iface_path="" iface=""
for iface_path in /sys/class/net/*; do
iface=${iface_path##*/}
str_starts "$iface" "lo" && continue
if iface_has_link "$iface"; then
echo "$iface"
return 0
fi
done
return 1
}
is_persistent_ethernet_name() {
local _netif="$1"
local _name_assign_type="0"
[ -f "/sys/class/net/$_netif/name_assign_type" ] \
&& _name_assign_type=$(cat "/sys/class/net/$_netif/name_assign_type" 2> /dev/null)
# NET_NAME_ENUM 1
[ "$_name_assign_type" = "1" ] && return 1
# NET_NAME_PREDICTABLE 2
[ "$_name_assign_type" = "2" ] && return 0
case "$_netif" in
# udev persistent interface names
eno[0-9] | eno[0-9][0-9] | eno[0-9][0-9][0-9]*) ;;
ens[0-9] | ens[0-9][0-9] | ens[0-9][0-9][0-9]*) ;;
enp[0-9]s[0-9]* | enp[0-9][0-9]s[0-9]* | enp[0-9][0-9][0-9]*s[0-9]*) ;;
enP*p[0-9]s[0-9]* | enP*p[0-9][0-9]s[0-9]* | enP*p[0-9][0-9][0-9]*s[0-9]*) ;;
# biosdevname
em[0-9] | em[0-9][0-9] | em[0-9][0-9][0-9]*) ;;
p[0-9]p[0-9]* | p[0-9][0-9]p[0-9]* | p[0-9][0-9][0-9]*p[0-9]*) ;;
*)
return 1
;;
esac
return 0
}
is_kernel_ethernet_name() {
local _netif="$1"
local _name_assign_type="1"
if [ -e "/sys/class/net/$_netif/name_assign_type" ]; then
_name_assign_type=$(cat "/sys/class/net/$_netif/name_assign_type")
case "$_name_assign_type" in
2 | 3 | 4)
# NET_NAME_PREDICTABLE 2
# NET_NAME_USER 3
# NET_NAME_RENAMED 4
return 1
;;
1 | *)
# NET_NAME_ENUM 1
return 0
;;
esac
fi
# fallback to error prone manual name check
case "$_netif" in
eth[0-9] | eth[0-9][0-9] | eth[0-9][0-9][0-9]*)
return 0
;;
*)
return 1
;;
esac
}
iface_get_subchannels() {
local _netif
local _subchannels
_netif="$1"
_subchannels=$({
for i in /sys/class/net/"$_netif"/device/cdev[0-9]*; do
[ -e "$i" ] || continue
channel=$(readlink -f "$i")
printf -- "%s" "${channel##*/},"
done
})
[ -n "$_subchannels" ] || return 1
printf -- "%s" "${_subchannels%,}"
}