ACC SHELL
#!/bin/bash
# Network interface configuration
#
# Copyright (c) 2002-2006 SuSE Linux AG Nuernberg, Germany.
# All rights reserved.
#
# 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, write to the Free Software Foundation, Inc., 59 Temple
# Place, Suite 330, Boston, MA 02111-1307 USA
#
# Authors: Michal Svec <msvec@suse.cz>
# Mads Martin Joergensen <mmj@suse.de>
# Marius Tomaschewski <mt@suse.de>
#
# $Id$
#
. /etc/sysconfig/network/scripts/functions.common
NETWORK_RUNFILE="$RUN_FILES_BASE/started"
STAMPFILE_STUB="$RUN_FILES_BASE/new-stamp-"
NETWORKMANAGER_BIN=/usr/sbin/NetworkManager
NM_ONLINE_BIN=/usr/bin/nm-online
#
# to test the next two functions:
#
# for i in {0..32}; do
# echo $i: $(pfxlen2mask $i) " ---> " $(mask2pfxlen $(pfxlen2mask $i))
# done
mask2pfxlen() {
local i octet width=0 mask=(${1//./ })
test ${#mask[@]} -eq 4 || return 1
for octet in 0 1 2 3; do
test "${mask[octet]}" -ge 0 -a \
"${mask[octet]}" -le 255 2>/dev/null \
|| return 1
for i in 128 192 224 240 248 252 254 255; do
test ${mask[octet]} -ge $i && ((width++))
done
done
echo $width
return 0
}
pfxlen2mask() {
test -n "$1" || return 1
local o i n=0 adr=() len=$(($1))
for o in 0 1 2 3; do
adr[$o]=0
for i in 128 64 32 16 8 4 2 1; do
((n++ < len)) && \
((adr[$o] = ${adr[$o]} + $i))
done
done
echo ${adr[0]}.${adr[1]}.${adr[2]}.${adr[3]}
return 0
}
add_to_wordlist() {
local v="${1}"
local l=(${!v}) ; shift
local a w
for a in ${@} ; do
for w in ${l[@]} ; do
[ "x$w" = "x$a" ] && \
continue 2
done
l=(${l[@]} $a)
done
eval "$v='${l[@]}'"
}
is_iface_available () {
local IFNAME=${1}
local IFTYPE=${2:-$INTERFACETYPE}
test -z "$IFNAME" && return 1
test -d /sys/class/net/$IFNAME && return 0
test "${SCRIPTNAME%%-*}" = ifdown -a \
"$MODE" = hotplug && return 0
: ${IFTYPE:=$(get_iface_type "$IFNAME")}
: ${IFTYPE:=$(get_iface_type_from_config "$IFNAME")}
test "${SCRIPTNAME%%-*}" = ifup && { \
case ${IFTYPE} in
bond|bridge|vlan|ibchild) return 0 ;;
ppp|isdn|dummy|tun|tap) return 0 ;;
ipip|ip6tnl|sit|gre|mip6mnha) return 0 ;;
esac
}
test -d /sys/class/net/$IFNAME
}
is_iface_up () {
test -z "$1" && return 1
test -d /sys/class/net/$1 || return 1
case "`LC_ALL=POSIX ip link show $1 2>/dev/null`" in
*$1*UP*) ;;
*) return 1 ;;
esac
}
link_ready_check () {
local c=`cat /sys/class/net/${1}/carrier 2>/dev/null`
local d=`cat /sys/class/net/${1}/dormant 2>/dev/null`
local o=`cat /sys/class/net/${1}/operstate 2>/dev/null`
#debug "link ready ${1}: carrier=$c, dormant=$d, operstate=$o"
if test -e "/sys/class/net/${1}/operstate" ; then
# SLE 11 has carrier + operstate + dormant
test "$d" = "0" || return 3
test "$c" = "1" || return 2
test \( "$o" = "up" -o "$o" = "unknown" \) || return 1
else
# e.g. SLE 10 does not have operstate/dormant
test "$c" = "1" || return 1
fi
return 0
}
ipv6_addr_dad_check()
{
local iface="$1" word i
local nodad=1 tentative=1 dadfailed=1
test -f "/sys/class/net/$iface/ifindex" || return 1
while read -a word ; do
test "${word[0]}" != "inet6" && continue
for((i=2; i<${#word[@]}; ++i)) ; do
case ${word[$i]} in
nodad) nodad=0 ;;
tentative) tentative=0 ;;
dadfailed) dadfailed=0 ;;
flags) ((i++))
rx='^[[:xdigit:]]+$'
[[ "${word[$i]}" =~ $rx ]] || continue
hx="0x${word[$i]}"
test $(( $hx & 0x02 )) -ne 0 && nodad=0
test $(( $hx & 0x08 )) -ne 0 && dadfailed=0
test $(( $hx & 0x40 )) -ne 0 && tentative=0
;;
esac
done
#debug "ipv6 dad $iface: nodad=$nodad, dadfailed=$dadfailed, tentative=$tentative"
test $nodad -eq 0 && continue
test $dadfailed -eq 0 && return 2
test $tentative -eq 0 && return 3
done < <(LC_ALL=C ip -6 addr show ${iface:+dev "$iface"} 2>/dev/null)
return $R_SUCCESS
}
link_ready_wait ()
{
local iface=$1
local -i wsecs=${2:-0}
local -i uwait=25000
local -i loops=$(((wsecs * 1000000) / $uwait))
local -i loop=0 ret=0
link_ready_check "$iface" ; ret=$?
while ((ret != 0 && loop++ < loops)) ; do
usleep $uwait
link_ready_check "$iface" ; ret=$?
done
return $ret
}
ipv6_addr_dad_wait()
{
local iface=$1
local -i wsecs=${2:-0}
local -i uwait=25000
local -i loops=$(((wsecs * 1000000) / $uwait))
local -i loop=0 ret=0
ipv6_addr_dad_check "$iface" ; ret=$?
while ((ret == 3 && loop++ < loops)) ; do
usleep $uwait
ipv6_addr_dad_check "$iface" ; ret=$?
done
return $ret
}
get_ethtool_drv_info () {
test -n "$1" || return 1
local ethtool="/sbin/ethtool"
if [ ! -x $ethtool ] ; then
[ -x /usr${ethtool} ] && ethtool="/usr${ethtool}" || return 1
fi
local key val
$ethtool -i "$1" 2>/dev/null |
while read key val ; do
case "$key" in
driver:) printf 'ETHTOOL_DRV_NAME=%q\n' "$val" ;;
version:) printf 'ETHTOOL_DRV_VERSION=%q\n' "$val" ;;
firmware-version:) printf 'ETHTOOL_DRV_FW_VERSION=%q\n' "$val" ;;
bus-info:) printf 'ETHTOOL_DRV_BUS_INFO=%q\n' "$val" ;;
esac
done 2>/dev/null # bash printf required for %q format
}
get_iface_type () {
local IF=$1 TYPE
test -n "$IF" || return 1
test -d /sys/class/net/$IF || return 2
case "`cat /sys/class/net/$IF/type`" in
1)
TYPE=eth
# Ethernet, may also be wireless, ...
if test -d /sys/class/net/$IF/wireless -o \
-L /sys/class/net/$IF/phy80211 ; then
TYPE=wlan
elif test -d /sys/class/net/$IF/bridge ; then
TYPE=bridge
elif test -f /proc/net/vlan/$IF ; then
TYPE=vlan
elif test -d /sys/class/net/$IF/bonding ; then
TYPE=bond
elif test -f /sys/class/net/$IF/tun_flags ; then
TYPE=tap
elif test -d /sys/devices/virtual/net/$IF ; then
case $IF in
(dummy*) TYPE=dummy ;;
esac
fi
;;
24) TYPE=eth ;; # firewire ;; # IEEE 1394 IPv4 - RFC 2734
32) # InfiniBand
case $IF in
*.*) TYPE=ibchild ;; *) TYPE=ib ;;
esac
;;
512) TYPE=ppp ;;
768) TYPE=ipip ;; # IPIP tunnel
769) TYPE=ip6tnl ;; # IP6IP6 tunnel
772) TYPE=lo ;;
776) TYPE=sit ;; # sit0 device - IPv6-in-IPv4
778) TYPE=gre ;; # GRE over IP
783) TYPE=irda ;; # Linux-IrDA
801) TYPE=wlan_aux ;;
65534) TYPE=tun ;;
esac
# The following case statement still has to be replaced by something
# which does not rely on the interface names.
case $IF in
ippp*|isdn*) TYPE=isdn;;
mip6mnha*) TYPE=mip6mnha;;
esac
test -n "$TYPE" && echo $TYPE && return 0
return 3
}
get_iface_type_from_config () {
local VARIABLE VALUE TYPE IF=$1
local INTERFACETYPE WIRELESS WIRELESS_MODE BONDING_MASTER ETHERDEVICE
local BRIDGE TUNNEL PPPMODE MODEM_DEVICE ENCAP
test -z "$IF" && return 3
test -r ifcfg-$IF || return 2
# If variable (1st word) has the right value (2nd word) then this
# interface is of this type (3rd word). If variable can have any
# value except empty, then use "_not_empty_" as value.
# INTERFACETYPE gets special handling and has variable type
while read VARIABLE VALUE TYPE; do
eval $VARIABLE=
get_variable $VARIABLE $IF
if [ "$VALUE" == _not_empty_ ] ; then
test -n "${!VARIABLE}" && break
else
test "${!VARIABLE}" == "$VALUE" && break
fi
done <<- EOL
INTERFACETYPE _not_empty_
WIRELESS yes wlan
WIRELESS_MODE _not_empty_ wlan
BONDING_MASTER yes bond
ETHERDEVICE _not_empty_ vlan
BRIDGE yes bridge
TUNNEL tap tap
TUNNEL tun tun
TUNNEL sit sit
TUNNEL gre gre
TUNNEL ipip ipip
PPPMODE pppoe ppp
PPPMODE pppoatm ppp
PPPMODE capi-adsl ppp
PPPMODE pptp ppp
MODEM_DEVICE _not_empty_ ppp
ENCAP syncppp isdn
ENCAP rawip isdn
EOL
case "$IF" in
ib*.*) INTERFACETYPE=ibchild ;;
ib*) INTERFACETYPE=ib ;;
esac
# bnc#458412: map obsolete (s390) eth type overrides
case "$INTERFACETYPE" in
(qeth|hsi|lcs|ctc|iucv|tr) INTERFACETYPE=eth ;;
esac
test -n "$INTERFACETYPE" && echo $INTERFACETYPE && return
if [ -z "$TYPE" ] ; then
case $IF in
lo) TYPE=lo;;
dummy*) TYPE=dummy;;
ib*) TYPE=ib;;
ip6tnl*) TYPE=ip6tnl;;
mip6mnha*) TYPE=mip6mnha;;
esac
fi
# There is a config file, but it has no special type: This must be ethernet
test -n "$TYPE" && echo $TYPE || echo eth
}
#
# supported_on_localfs($INTERFACE [, $INTERFACETYPE])
#
# Returns 0 (true) when we support to start the interface
# (configuration) on local-fs only, or 1 (false) when
# also remote-fs is required (e.g. because of utilities
# in /usr that may be on NFS) or 2 (false) on errors.
#
supported_on_localfs() {
local IFNAME=$1
local IFTYPE=${2:-$INTERFACETYPE}
test "x$IFNAME" = x && return 2
test "x$IFTYPE" = x && IFTYPE=$(get_iface_type $IFNAME)
test "x$IFTYPE" = x && IFTYPE=$(get_iface_type_from_config $IFNAME)
# Currently it is sufficient to check the type only.
local result=1 # remote-fs requirement as default
case $IFTYPE in
"") result=2 ;;
lo|dummy) result=0 ;;
eth|tr|ib) result=0 ;;
ibchild|tap) result=0 ;;
vlan|bridge|bond) result=0 ;;
esac
# tunnels in principle too, but it may be not possible
# to resolve the base / slave interface correctly ...
#tun|sit|gre|ipip) result=0 ;;
return $result
}
get_hwaddress () {
cat /sys/class/net/$1/address >/dev/null
}
# This will echo the first address listed for the given interface.
get_ipv4address () {
test -z "$1" && return 1
local a b c
while read a b c; do
if [ "$a" = inet ] ; then
break
fi
done < <(LC_ALL=POSIX ip -4 address list "$1" 2>/dev/null)
test -z "$b" && return 1
echo ${b%%/*}
}
convert_ipv4address_to_6to4 () {
printf "2002:%02x%02x:%02x%02x::1\n" $(IFS=.; echo $1)
}
convert_6to4_to_ipv4address () {
ADDR=$1
LIST=($(IFS=:; echo $ADDR))
if [ ${#LIST[@]} -ne 4 -o "${LIST[0]}" != "2002" ] ; then
echo $ADDR
fi
NORM_1=`printf "%04x" 0x${LIST[1]} 2>/dev/null`
NORM_2=`printf "%04x" 0x${LIST[2]} 2>/dev/null`
printf "::%u.%u.%u.%u" \
0x${NORM_1:0:2} 0x${NORM_1:2:2} \
0x${NORM_2:0:2} 0x${NORM_2:2:2}
}
get_variable () {
local line
while read line; do
eval $line
done < <(grep "^[[:space:]]*$1" ifcfg-$2 2>/dev/null)
}
get_startmode () {
local STARTMODE
get_variable STARTMODE $1
echo "$STARTMODE"
}
get_slaves () {
local ret=1
local v vv
case $1 in
ib*.*) echo -n "${1%%\.*} " ; ret=0 ;;
esac
for v in BONDING_SLAVE ETHERDEVICE TUNNEL_DEVICE \
TUNNEL_LOCAL_INTERFACE BRIDGE_PORTS; do
get_variable $v $1
for vv in `eval echo \$\{\!$v\*\}`; do
if [ -n "${!vv}" ] ; then
echo -n "${!vv} "
ret=0
fi
unset $vv
done
test $ret = 0 && return 0
done
return 1
}
get_ifplugd_priority () {
local IFPLUGD_PRIORITY=0
declare -i IFPLUGD_PRIORITY
get_variable IFPLUGD_PRIORITY $1
echo "$IFPLUGD_PRIORITY"
}
# We have to write status files per interface or per configuration for at least
# these reasons:
# 1) remember the used configuration if getcfg cannot get it after the device
# has been unplugged --> OBSOLETE: no more getcfg
# 2) store ifup options while restarting the network (e.g. the choosen provider)
# 3) pass status information to smpppd to allow kinternet to show them to the
# user.
# 4) control running ifup/down processes (ifdown has to stop a running ifup)
# To handle this cached information, there are the *_cached_config_data
# functions.
# write_cached_config_data <type> <data> <name> [PFX=<prefix>]
# needs at least 3 arguments
# - the type of data to write: config, options, state, ...
# - the data itself
# - the configuration or interface name
# - the file prefix is optional and must be given in the form PFX=<prefix>
# (default prefix is 'if-'
# prints nothing
# You have to commit changes after writing with commit_cached_config_data()
write_cached_config_data () {
touch $RUN_FILES_BASE/tmp/test 2>/dev/null || return 1
local PFX FILE TMPFILE MODFILE
test -n "$4" && eval $4
: ${PFX:=if-}
FILE=$RUN_FILES_BASE/$PFX$3
MODFILE=$RUN_FILES_BASE/tmp/$PFX$3.$$ # MODFILE
TMPFILE=$RUN_FILES_BASE/tmp/$PFX$3.$$.tmp # MODFILE
test -f $MODFILE || cp $FILE $MODFILE 2>/dev/null
FILE=$MODFILE # MODFILE
touch $FILE
while IFS== read a b; do
case $a in
$1) ;;
*) echo "$a=$b" ;;
esac
done < <(cat $FILE) > $TMPFILE
if [ -n "$2" ] ; then
echo "$1=$2" >> $TMPFILE
fi
if [ -f $TMPFILE ] ; then
mv $TMPFILE $FILE
fi
}
# INTERFACE=`read_cached_config_data <type> <name> [PFX=<prefix>]`
# needs at least 2 arguments
# - the type of data to read: config, options, state, ...
# - the configuration or interface name
# - the file prefix is optional and must be given in the form PFX=<prefix>
# (default prefix is 'if-'
# prints the wanted data
read_cached_config_data () {
touch $RUN_FILES_BASE/tmp/test 2>/dev/null || return 1
local PFX
test -n "$3" && eval $3
: ${PFX:=if-}
if [ -r "$RUN_FILES_BASE/$PFX$2" ] ; then
while IFS== read a b; do
case $a in
$1) echo "$b" ;;
*) ;;
esac
done < $RUN_FILES_BASE/$PFX$2
fi
}
# delete_from_cached_config_data <type> [<data> [<name>]] [PFX=<prefix>]
# Deletes an entry "$1=$2" from all config data cache files.
# If there is a third argument, we delete it only from this configuration. All
# handled files that are empty after modification will be deleted.
# If $2 is empty then remove line $1=* from this ($3) or all configuration.
# If $1 is '*' it will remove all entries.
#
# !!! WIP !!!
# It currently works only on one file and 2nd and 3rd argument are mandatory
# !!! WIP !!!
#
# needs at least 1 argument
# - the type of data to delete: config, options, state, ...
# - optional the data itself
# - optional the configuration or interface name
# - the file prefix is also optional and must be given in the form PFX=<prefix>
# (default prefix is 'if-'
# prints nothing
# You have to commit changes after deleting with commit_cached_config_data()
delete_from_cached_config_data () {
touch $RUN_FILES_BASE/tmp/test 2>/dev/null || return 1
local TYPE DATA PFX FILE TMPFILE MODFILE NAME
TYPE=$1; shift
if [ "$1" = "${1#PFX}" ] ; then
DATA=$1; shift
fi
if [ "$1" = "${1#PFX}" ] ; then
NAME=$1; shift
fi
test -n "$1" && eval $1
: ${PFX:=if-}
FILE=$RUN_FILES_BASE/$PFX$NAME # MODFILE
MODFILE=$RUN_FILES_BASE/tmp/$PFX$NAME.$$ # MODFILE
TMPFILE=$RUN_FILES_BASE/tmp/$PFX$NAME.$$.tmp # MODFILE
test -f $MODFILE || cp $FILE $MODFILE 2>/dev/null
FILE=$MODFILE # MODFILE
touch $FILE
if [ -s "$FILE" ] ; then
while IFS== read a b; do
case $a in
$TYPE)
if [ "$b" != "$DATA" -a -n "$DATA" ] ; then
echo "$a=$b"
fi
;;
*) echo "$a=$b" ;;
esac
done < <(cat $FILE) > $TMPFILE
fi
if [ -f $TMPFILE ] ; then
mv $TMPFILE $FILE
fi
if [ ! -s $FILE ] ; then
rm -Rf $FILE
fi
# done MODFILE
}
# HWDESC NIX < <(grep_cached_config_data <type> <data> [PFX=<prefix>])
# needs 2 arguments:
# - the type of data to grep for: config, options, state, ...
# - the data itself
# - the file prefix is optional and must be given in the form PFX=<prefix>
# (default prefix is 'if-'
# prints all matching configuration names in a single line
grep_cached_config_data () {
touch $RUN_FILES_BASE/tmp/test 2>/dev/null || return 1
local PFX
test -n "$3" && eval $3
: ${PFX:=if-}
local restore_nullglob="$(shopt -p nullglob)"
shopt -s nullglob
for f in $RUN_FILES_BASE/$PFX*; do
while IFS== read a b; do
case $a in
$1)
if [ "$b" = "$2" ] ; then
echo -n "${f#$RUN_FILES_BASE/$PFX} "
fi
;;
esac
done < $f
done
eval $restore_nullglob
echo
}
# Writing and deleting cached config data is always done in temporary files. To
# make this changes visible in the right file you must commit the changes. This
# helps to make file changes atomic.
commit_cached_config_data () {
touch $RUN_FILES_BASE/tmp/test 2>/dev/null || return 1
local PFX FILE MODFILE
test -n "$2" && eval $2
: ${PFX:=if-}
FILE=$RUN_FILES_BASE/$PFX$1
MODFILE=$RUN_FILES_BASE/tmp/$PFX$1.$$
if [ -f $MODFILE ] ; then
mv $MODFILE $FILE
else
rm -f $FILE
fi
}
is_connected () {
case `read_cached_config_data status $1` in
connected) return 0 ;;
connecting) return 0 ;; # might be wrong, test for link to
esac
return 1
}
has_link () {
case `read_cached_config_data link $1` in
yes) return 0 ;;
esac
return 1
}
# This function looks for interfaces which depend on the given interface. It
# prints a list with all depending interfaces. It returns 0 if there are
# depending interfaces and !=0 if not.
# Currently it checks only for vlan and optionally bonding slave interfaces.
# FIXME: Add other types of interfaces that depend on others.
get_depending_ifaces() {
local VLAN_PATH BOND_PATH DEP_VLANS DEP_BONDS BASE_IFACE i
local -a DEP_IFACES=()
VLAN_PATH="/proc/net/vlan"
BOND_PATH=""
while [ $# -gt 0 ]; do
case $1 in
--with-bonding-slaves)
BOND_PATH="/proc/net/bonding"
shift
;;
-*) shift ;;
*) break ;;
esac
done
BASE_IFACE="$1"
if [ -z "$BASE_IFACE" ]; then
return 1
fi
if [ -d "$VLAN_PATH" ]; then
DEP_VLANS=`cd "$VLAN_PATH"
grep -lws "Device: *$BASE_IFACE" *`
DEP_IFACES+=($DEP_VLANS)
fi
if [ -n "$BOND_PATH" -a -d "$BOND_PATH" ]; then
DEP_BONDS=`cd "$BOND_PATH"
grep -s '^Slave Interface:' $BASE_IFACE |
while IFS=':' read text iface ; do echo -n "$iface" ; done`
DEP_IFACES+=($DEP_BONDS)
fi
case $BASE_IFACE in
(ib*.*) ;;
(ib*) # the infiniband children -- is there a better way?
for i in `ls -1 /sys/class/net/ 2>/dev/null` ; do
test -d /sys/class/net/$i || continue
case $i in (${BASE_IFACE}.*)
DEP_IFACES+=($i)
;;
esac
done
;;
esac
if [ ${#DEP_IFACES[*]} -gt 0 ]; then
echo "${DEP_IFACES[*]}"
return 0
else
return 1
fi
}
resolve_iface_startorder()
{
#
# resolve_iface_startorder <name of the result variable>
# <list of interfaces to resolve>
# [ <skip list> [filter fuction] ]
#
# This function creates a start ordered list of virtual interfaces
# as bondings, vlans and bridges known by the get_slaves() function.
# It reads the base or "slave" interfaces of each virtual interface
# recursively and inserts the slaves into the result list before the
# virtual interface itself. Further it detects interface usage loops
# like: interface "a" needs "b" and "b" needs "a" and skips them.
#
# The optional skip list allows to stop the recursion insertion at
# e.g. already started / existing physical slave interfaces.
# Addding interfaces to resolve to this skip list causes resolving
# of the recursive list of slave interfaces without the requested
# interfaces themself (resolve_iface_startorder slaves "br0" "br0").
#
# The optional filter function allows to filter out interfaces as
# well as all depending interfaces. For example a vlan interface
# will be filtered out, when the underlying interface gets filtered
# out. This happens also, when the function does not cause to filter
# out the vlan interface directly. Main purpose is to filter out
# interfaces, that are not supported without a mounted remotefs.
#
# $1: the name of the result start ordered list variable to set
# $2: list of virtual interfaces to resolve the start order for
# $3: optional list of interfaces to skip/stop reading
# $4: optional (white list) filter function returning true for
# acceptable interfaces and false to filter out an interface.
#
# returns 0 on success,
# 1 on empty result list name,
# [2 on interface usage loop error; disabled]
#
local NAME="$1"
local TODO="$2"
local SKIP="$3"
local FUNC="$4"
local LIST=()
_resolve_iface_startorder() {
local todo="$1"
local skip="$2"
local func="$3"
local guard="$4"
local level="$5"
local slaves iface i ret
local result=0
for iface in ${todo} ; do
for i in ${guard} ; do
if [ "x${i}" = "x${iface}" ] ; then
err_mesg "Interface dependency loop " \
"detected: ${guard} ${iface}"
# guard non-empty in level > 0
return 2
fi
done
if [ "x$func" != x ] && ! $func "$iface" &>/dev/null ; then
[ $level -eq 0 ] && continue || return 3
fi
slaves=(`get_slaves $iface 2>/dev/null`)
if [ $? = 0 -a ${#slaves[@]} -gt 0 ] ; then
ret=0
_resolve_iface_startorder \
"${slaves[*]}" \
"${skip}" \
"${func}" \
"${guard} $iface" \
$(($level+1)) \
|| ret=$?
if [ $ret -ne 0 ] ; then
if [ $level -eq 0 ] ; then
#result=$ret
continue
else
return $ret
fi
fi
fi
for i in ${LIST[@]} ${skip} ; do
[ "x$i" = "x$iface" ] && continue 2
done
LIST=(${LIST[@]} $iface)
done
return $result
}
[ "x$NAME" = x ] && return 1
_resolve_iface_startorder "$TODO" "$SKIP" "$FUNC" "" 0 || return $?
eval "$NAME='${LIST[@]}'"
}
nm_running () {
local MSG RET
test -x "$NETWORKMANAGER_BIN" || return
MSG=`checkproc $NETWORKMANAGER_BIN 2>&1`
RET=$?
info_mesg "$MSG"
return $RET
}
netcontrol_running() {
test -f $NETWORK_RUNFILE
}
# returns 0 if ifup is currently working on this interface
ifup_on_iface() {
ps axhww | grep -qs "[i]fup.* $INTERFACE\>"
}
# returns 0 if there is a dhcp client running on this interface
# prints pids of all dhcp clients on this interface
# prints nothing if called with option '-q'
# Usually it should not happen that more then one dhcpcd is running on one
# interface, but it may happen. So better safe than sorry!
dhcpc4_on_iface() {
local pid retval=1
[ "x$DHCLIENT" != x -a "x$INTERFACE" != x ] || return $retval
# when the dhcp client forks, it may be not visible
# in the process list for a short (usleep) while...
typeset -i retries=3
for ((; retries > 0; retries--)) ; do
for pid in `pgrep -f "^(/.*/)?$DHCLIENT\>.*\<$INTERFACE\>$" 2>/dev/null` ; do
retval=0
test "x$1" == "x-q" && break
echo $pid
done
(( retval == 0 )) && break || usleep 100000
done
return $retval
}
dhcpc6_on_iface() {
local pid retval=1
[ "x$DHCLIENT6" != x -a "x$INTERFACE" != x ] || return $retval
# when the dhcp client forks, it may be not visible
# in the process list for a short (usleep) while...
typeset -i retries=3
for ((; retries > 0; retries--)) ; do
for pid in `pgrep -f "^(/.*/)?$DHCLIENT6\>.*\<$INTERFACE\>$" 2>/dev/null` ; do
retval=0
test "x$1" == "x-q" && break
echo $pid
done
(( retval == 0 )) && break || usleep 100000
done
return $retval
}
dhcpc_on_iface() {
local pid retval=1 pattern
[ "x$DHCLIENT" != x ] && pattern=$DHCLIENT || pattern=""
[ "x$DHCLIENT6" != x ] && pattern="${pattern:+$pattern|}$DHCLIENT6"
[ "x$pattern" != x -a "x$INTERFACE" != x ] || return $retval
# when the dhcp client forks, it may be not visible
# in the process list for a short (usleep) while...
typeset -i retries=3
for ((; retries > 0; retries--)) ; do
for pid in `pgrep -f "^(/.*/)?($pattern)\>.*\<$INTERFACE\>$" 2>/dev/null` ; do
retval=0
test "$1" == "-q" && break
echo $pid
done
(( retval == 0 )) && break || usleep 100000
done
return $retval
}
any_dhcpc_on_iface()
{
local pid retval=1 pattern=""
[ "x$INTERFACE" != x ] || return $retval
# just search for all known dhcp clients
pattern="dhcpcd|dhclient|dhcp6c|dhclient6"
# when the dhcp client forks, it may be not visible
# in the process list for a short (usleep) while...
typeset -i retries=3
for ((; retries > 0; retries--)) ; do
for pid in `pgrep -f "^(/.*/)?($pattern)\>.*\<$INTERFACE\>$" 2>/dev/null` ; do
retval=0
test "$1" == "-q" && break
echo $pid
done
(( retval == 0 )) && break || usleep 100000
done
return $retval
}
dhcp_interfaces() {
local old_if=$INTERFACE
for INTERFACE in `ls -1 /sys/class/net`; do
if test -d "/sys/class/net/$INTERFACE" ; then
any_dhcpc_on_iface -q && echo "$INTERFACE"
fi
done
INTERFACE=$old_if
return 0
}
# Parse iSCSI Boot Firmare Table settings of given interface
# and provide as adequate ifcfg/netcontrol scripts settings.
parse_ifname_ibft_settings()
{
case $1 in ""|.|..|*/*) return 1 ;; esac
test -d "/sys/class/net/$1" || return 1
local IF="$1" sysfs_ibft="/sys/firmware/ibft"
#test -d "$sysfs_ibft" || modprobe -qs iscsi_ibft 2>/dev/null
test -d "$sysfs_ibft" || return 1
local edir ibft_e_origin
for edir in $(ls -1d "$sysfs_ibft/ethernet"* 2>/dev/null) ;
do
if test -d "$edir/device/net/$IF" ; then
# Check another flags (flags bit 1, FW Boot Selected)?
# IpPrefixOrigin: Other,Manual,WellKnown,Dhcp,RouterAdv
ibft_e_origin=`cat "$edir/origin" 2>/dev/null`
case $ibft_e_origin in
3) # IpPrefixOriginDdhcp
echo "BOOTPROTO='dhcp'"
;;
*) # ... everything else ('static' ?!)
echo "BOOTPROTO='none'"
;;
esac
return 0
fi
done
return 1
}
ACC SHELL 2018