# -*-Shell-script-*- # # This file is not a stand-alone shell script; it provides functions # to network scripts that source it. # Set up a default search path. PATH="/sbin:/usr/sbin:/bin:/usr/bin" export PATH # We need to initialize the $HOSTNAME variable by ourselves now: # (It was previously done for RHEL-6 branch, but got lost in time.) HOSTNAME="$(hostname)" [ -z "$__sed_discard_ignored_files" ] && . /etc/init.d/functions RESOLVCONF_FLAGFILE=/var/run/resolvconf/enable-updates get_hwaddr () { if [ -f /sys/class/net/${1}/address ]; then tr '[a-z]' '[A-Z]' < /sys/class/net/${1}/address elif [ -d "/sys/class/net/${1}" ]; then LC_ALL= LANG= ip -o link show ${1} 2>/dev/null | \ awk '{ print toupper(gensub(/.*link\/[^ ]* ([[:alnum:]:]*).*/, "\\1", 1)); }' fi } get_config_by_device () { LANG=C grep -l "^[[:space:]]*DEVICE=['\"]\?${1}['\"]\?\([[:space:]#]\|$\)" \ /etc/sysconfig/network-scripts/ifcfg-* \ | LC_ALL=C sed -e "$__sed_discard_ignored_files" } get_config_by_hwaddr () { LANG=C grep -il "^[[:space:]]*HWADDR=['\"]\?${1}['\"]\?\([[:space:]#]\|$\)" /etc/sysconfig/network-scripts/ifcfg-* \ | LC_ALL=C sed -e "$__sed_discard_ignored_files" } get_config_by_subchannel () { LANG=C grep -E -i -l \ "^[[:space:]]*SUBCHANNELS=['\"]?([0-9]\.[0-9]\.[a-f0-9]+,){0,2}${1}(,[0-9]\.[0-9]\.[a-f0-9]+){0,2}['\"]?([[:space:]]+#|[[:space:]]*$)" \ /etc/sysconfig/network-scripts/ifcfg-* \ | LC_ALL=C sed -e "$__sed_discard_ignored_files" } get_config_by_name () { LANG=C grep -E -i -l "^[[:space:]]*NAME=\"(Auto |System )?${1}\"" \ /etc/sysconfig/network-scripts/ifcfg-* \ | LC_ALL=C sed -e "$__sed_discard_ignored_files" } get_device_by_hwaddr () { LANG=C ip -o link | awk -F ': ' -vIGNORECASE=1 '!/link\/ieee802\.11/ && /'"$1"'/ { print $2 }' } get_uuid_by_config () { dbus-send --system --print-reply --dest=com.redhat.ifcfgrh1 /com/redhat/ifcfgrh1 com.redhat.ifcfgrh1.GetIfcfgDetails string:"/etc/sysconfig/network-scripts/$1" 2>/dev/null | awk -F '"' '/string / { print $2 }' } generate_lease_file_name () { local ver=$1 LEASEFILE="/var/lib/dhclient/dhclient$ver-${DEVICE}.leases" if [ -f $LEASEFILE ]; then return fi LEASEFILE="/var/lib/dhclient/dhclient$ver-${UUID}-${DEVICE}.lease" } generate_config_file_name () { local ver=$1 if [ -s /etc/dhcp/dhclient$ver-${DEVICE}.conf ]; then DHCLIENTCONF="-cf /etc/dhcp/dhclient$ver-${DEVICE}.conf"; elif [ -s /etc/dhclient$ver-${DEVICE}.conf ]; then DHCLIENTCONF="-cf /etc/dhclient$ver-${DEVICE}.conf"; else DHCLIENTCONF=''; fi } need_config () { local nconfig CONFIG="ifcfg-${1}" [ -f "${CONFIG}" ] && return CONFIG="${1##*/}" [ -f "${CONFIG}" ] && return nconfig=$(get_config_by_name "${1}") if [ -n "$nconfig" ] && [ -f "$nconfig" ]; then CONFIG=${nconfig##*/} return fi local addr=$(get_hwaddr ${1}) if [ -n "$addr" ]; then nconfig=$(get_config_by_hwaddr ${addr}) if [ -n "$nconfig" ] ; then CONFIG=${nconfig##*/} [ -f "${CONFIG}" ] && return fi fi nconfig=$(get_config_by_device ${1}) if [ -n "$nconfig" ] && [ -f "$nconfig" ]; then CONFIG=${nconfig##*/} return fi } source_config () { CONFIG=${CONFIG##*/} DEVNAME=${CONFIG##ifcfg-} . /etc/sysconfig/network-scripts/$CONFIG [ -r "keys-$DEVNAME" ] && . /etc/sysconfig/network-scripts/keys-$DEVNAME case "$TYPE" in Ethernet) DEVICETYPE="eth" ;; CIPE) DEVICETYPE="cipcb" ;; IPSEC) DEVICETYPE="ipsec" ;; Modem) DEVICETYPE="ppp" ;; xDSL) DEVICETYPE="ppp" ;; ISDN) DEVICETYPE="ippp" ;; Wireless) DEVICETYPE="eth" ;; "Token Ring") DEVICETYPE="eth" ;; CTC) DEVICETYPE="ctc" ;; GRE | GRE6 | IPIP | IPIP6) DEVICETYPE="tunnel" ;; SIT | sit) DEVICETYPE="sit" ;; InfiniBand | infiniband) DEVICETYPE="ib" ;; OVS*) DEVICETYPE="ovs" ;; Bridge) DEVICETYPE="eth" ;; esac if [ -n "$HWADDR" ]; then HWADDR=$(tr '[a-z]' '[A-Z]' <<<"$HWADDR") fi if [ -n "$MACADDR" ]; then MACADDR=$(tr '[a-z]' '[A-Z]' <<<"$MACADDR") fi [ -z "$DEVICE" -a -n "$HWADDR" ] && DEVICE=$(get_device_by_hwaddr $HWADDR) [ -z "$DEVICETYPE" ] && DEVICETYPE=$(echo ${DEVICE} | sed "s/[0-9]*$//") [ -z "$REALDEVICE" -a -n "$PARENTDEVICE" ] && REALDEVICE=$PARENTDEVICE [ -z "$REALDEVICE" ] && REALDEVICE=${DEVICE%%:*} [ -z "$SYSCTLDEVICE" ] && SYSCTLDEVICE=${REALDEVICE/.//} if [ "${DEVICE}" != "${REALDEVICE}" ]; then ISALIAS=yes else ISALIAS=no fi if is_nm_running && [ "$REALDEVICE" != "lo" ] ; then nm_con_load "$CONFIG" if ! is_false $NM_CONTROLLED; then UUID=$(get_uuid_by_config $CONFIG) [ -n "$UUID" ] && _use_nm=true fi fi } nm_con_load () { dbus-send --system --print-reply \ --dest=org.freedesktop.NetworkManager \ /org/freedesktop/NetworkManager/Settings \ org.freedesktop.NetworkManager.Settings.LoadConnections \ array:string:"/etc/sysconfig/network-scripts/${1}" >/dev/null 2>&1 } ethtool_set() { oldifs=$IFS; IFS=';'; if [ -n "${ETHTOOL_DELAY}" ]; then # Convert microseconds to seconds: local ETHTOOL_DELAY_SEC=$(convert2sec ${ETHTOOL_DELAY} micro) sleep ${ETHTOOL_DELAY_SEC} fi for opts in $ETHTOOL_OPTS ; do IFS=$oldifs; if [[ "${opts}" =~ [[:space:]]*- ]]; then /sbin/ethtool $opts else /sbin/ethtool -s ${REALDEVICE} $opts fi IFS=';'; done IFS=$oldifs; } expand_config () { local i=0 val for idx in '' {0..255} ; do ipaddr[$i]=$(eval echo '$'IPADDR$idx) if [ -z "${ipaddr[$i]}" ]; then [ "$idx" ] && [ $idx -ge 2 ] && break continue fi prefix[$i]=$(eval echo '$'PREFIX$idx) netmask[$i]=$(eval echo '$'NETMASK$idx) broadcast[$i]=$(eval echo '$'BROADCAST$idx) arpcheck[$i]=$(eval echo '$'ARPCHECK$idx) arpupdate[$i]=$(eval echo '$'ARPUPDATE$idx) if [ "${prefix[$i]}x" != "x" ]; then val=$(/bin/ipcalc --netmask "${ipaddr[$i]}/${prefix[$i]}") netmask[$i]=${val##NETMASK=} fi if [ "${netmask[$i]}x" = "x" ]; then val=$(/bin/ipcalc --netmask "${ipaddr[$i]}") netmask[$i]=${val##NETMASK=} fi if [ "${prefix[$i]}x" = "x" ]; then val=$(/bin/ipcalc --prefix ${ipaddr[$i]} ${netmask[$i]}) prefix[$i]=${val##PREFIX=} fi if [ "${broadcast[$i]}x" = "x" ]; then val=$(/bin/ipcalc --broadcast ${ipaddr[$i]} ${netmask[$i]}) broadcast[$i]=${val##BROADCAST=} fi if [ "${arpcheck[$i]}x" != "x" ]; then arpcheck[$i]=${arpcheck[$i]##ARPCHECK=} arpcheck[$i]=${arpcheck[$i],,*} fi if [ "${arpupdate[$i]}x" != "x" ]; then arpupdate[$i]=${arpupdate[$i]##ARPUPDATE=} arpupdate[$i]=${arpupdate[$i],,*} fi i=$((i+1)) done [ -n "$DHCP_HOSTNAME" ] && DHCP_HOSTNAME=${DHCP_HOSTNAME%%.*} if [ -z "${NETWORK}" ]; then eval $(/bin/ipcalc --network ${ipaddr[0]} ${netmask[0]}) fi } toggle_value () { if is_true "$2"; then echo "$1 on" elif is_false "$2"; then echo "$1 off" else echo '' fi } is_nm_running () { dbus-send --system --print-reply \ --dest=org.freedesktop.DBus \ /org/freedesktop/DBus \ org.freedesktop.DBus.GetNameOwner \ string:"org.freedesktop.NetworkManager" >/dev/null 2>&1 } is_nm_device_unavailable () { [ -x /usr/bin/nmcli ] && \ LANG=C LC_ALL=C nmcli -t --fields device,state dev status 2>/dev/null | grep -q "^${1}:unavailable$" } is_nm_active () { [ -x /usr/bin/nmcli ] && \ LANG=C LC_ALL=C nmcli -t --fields device,state dev status 2>/dev/null | grep -q "^${1}:connected$" } is_nm_handling () { [ -x /usr/bin/nmcli ] && \ LANG=C nmcli -t --fields device,state dev status 2>/dev/null | grep -q "^\(${1}:connected\)\|\(${1}:connecting.*\)$" } is_nm_device_unmanaged () { [ -x /usr/bin/nmcli ] && \ LANG=C LC_ALL=C nmcli -t --fields GENERAL dev show "${1}" 2>/dev/null | awk -F ':' '/GENERAL.STATE/ { if ($2 == "unmanaged") exit 0 ; else exit 1; }' } # Sets $alias to the device module if $? != 0 is_available () { [ -z "$1" ] && return 1 [ -d "/sys/class/net/$1" ] && return 0 [ -n "$BONDING_OPTS" ] && install_bonding_driver $1 alias=$(modprobe -c | awk \ 'BEGIN { alias = ""; } $1 == "alias" && $2 == "'"$1"'" { alias = $3; } $1 == "install" { install[$2] = $3; } END { cmd = install[alias]; print alias; if (alias == "" || alias == "off" || cmd == "/bin/true" || cmd == ":") exit 1; exit 0; } ') [ $? -eq 0 ] || return 2 modprobe $1 > /dev/null 2>&1 || { return 1 } if [ -n "$HWADDR" ]; then local curdev=$(get_device_by_hwaddr "$HWADDR") if [ -z "$curdev" ]; then return 1 fi fi if [ ${alias} = "bonding" ]; then install_bonding_driver $1 fi [ -d "/sys/class/net/$1" ] && return 0 || return 1 } is_available_wait () { [ -z "$1" ] && return 1 local retry=${2##*[!0-9]*} is_available $1 && return 0 ret=$? while [ 0"$retry" -gt 0 ]; do sleep 1 [ -d "/sys/class/net/$1" ] && return 0 retry=$(($retry -1)) done return $ret } is_hostname_set () { case "${HOSTNAME}" in '(none)' | 'localhost' | 'localhost.localdomain') # Hostname NOT set: return 1 ;; *) # Hostname IS set: return 0 ;; esac } need_hostname () { # Should we avoid obtaining hostname from DHCP? (user override) is_true "${NO_DHCP_HOSTNAME}" && return 1 if is_hostname_set; then # Hostname is already set, we do not need to acquire it: return 1 else # Hostname is NOT set, we need to acquire it: return 0 fi } set_hostname_options () { # User explicitly requires to *not* send DHCP_HOSTNAME, DHCP_FQDN or HOSTNAME: is_false "${DHCP_SEND_HOSTNAME}" && return if [[ -n "${DHCP_HOSTNAME}" && -n "${DHCP_FQDN}" ]]; then net_log $"Both 'DHCP_HOSTNAME=${DHCP_HOSTNAME}' and 'DHCP_FQDN=${DHCP_FQDN}' are configured... Using DHCP_FQDN." warning fi local hostname_options='' # DHCP_FQDN takes precedence before DHCP_HOSTNAME -- as it does in NetworkManager, # and DHCP_HOSTNAME takes precedence before HOSTNAME: if [[ -n "${DHCP_FQDN}" ]]; then hostname_options="-F ${DHCP_FQDN}" elif [[ -n "${DHCP_HOSTNAME}" ]]; then hostname_options="-H ${DHCP_HOSTNAME}" elif is_hostname_set; then # We need to truncate the hostname in case it is the FQDN: hostname_options="-H ${HOSTNAME%%.*}" else # Nothing to send to the DHCP server: # ['(none)', 'localhost' or 'localhost.localdomain' are not valid] return fi # Append the hostname options to the content of passed variable name: eval "$1='${!1} ${hostname_options}'" return } set_hostname () { hostname $1 if ! grep search /etc/resolv.conf >/dev/null 2>&1; then domain=$(echo $1 | sed 's/^[^\.]*\.//') if [ -n "$domain" ]; then rsctmp=$(mktemp /tmp/XXXXXX); cat /etc/resolv.conf > $rsctmp echo "search $domain" >> $rsctmp # Backup resolv.conf only if it doesn't exist already: ! [ -f /etc/resolv.conf.save ] && cp -af /etc/resolv.conf /etc/resolv.conf.save change_resolv_conf $rsctmp /bin/rm -f $rsctmp fi fi if [ -d /etc/sysconfig/network-scripts/hostname.d -a -x /usr/bin/run-parts ]; then /usr/bin/run-parts --arg $1 /etc/sysconfig/network-scripts/hostname.d fi } check_device_down () { [ ! -d /sys/class/net/$1 ] && return 0 if LC_ALL=C ip -o link show dev $1 2>/dev/null | grep -q ",UP" ; then return 1 else return 0 fi } check_link_down () { if [ "${MII_NOT_SUPPORTED}" = yes ]; then return 1 fi if ! LC_ALL=C ip link show dev $1 2>/dev/null| grep -q ",UP" ; then ip link set dev $1 up >/dev/null 2>&1 fi timeout=0 delay=10 [ -n "$LINKDELAY" ] && delay=$(($LINKDELAY * 2)) while [ $timeout -le $delay ]; do [ "$(cat /sys/class/net/$REALDEVICE/carrier 2>/dev/null)" != "0" ] && return 1 sleep 0.5 timeout=$((timeout+1)) done return 0 } check_default_route () { LC_ALL=C ip route list match 0.0.0.0/0 | grep -q default } find_gateway_dev () { . /etc/sysconfig/network if [ -n "${GATEWAY}" -a "${GATEWAY}" != "none" ] ; then dev=$(LC_ALL=C /sbin/ip route get to "${GATEWAY}" 2>/dev/null | \ sed -n 's/.* dev \([[:alnum:]]*\) .*/\1/p') if [ -n "$dev" ]; then GATEWAYDEV="$dev" fi fi } # After the device $1 goes away, restore the standard default route; typically # used for ppp with DEFROUTE temporarily replacing the "standard" default # route. # FIXME: This function doesn't support some newer features (GATEWAY in ifcfg, # $WINDOW, $METRIC) add_default_route () { . /etc/sysconfig/network check_default_route && return 0 find_gateway_dev if [ "$GATEWAYDEV" != "" -a -n "${GATEWAY}" -a \ "${GATEWAY}" != "none" ]; then if ! check_device_down $1; then if [ "$GATEWAY" = "0.0.0.0" ]; then /sbin/ip route add default dev ${GATEWAYDEV} else /sbin/ip route add default via ${GATEWAY} fi fi elif [ -f /etc/default-routes ]; then while read spec; do /sbin/ip route add $spec done < /etc/default-routes rm -f /etc/default-routes fi } is_wireless_device () { [ -x /usr/sbin/iw ] || return 1 LC_ALL=C /usr/sbin/iw dev $1 info > /dev/null 2>&1 && return 0 return 1 } phy_wireless_device () { cat /sys/class/net/$1/phy80211/name } bond_master_exists () { local bond_name [ -z "${1}" ] && return 1 [ ! -f /sys/class/net/bonding_masters ] && return 1 for bond_name in $(< /sys/class/net/bonding_masters); do [ "${bond_name}" == "${1}" ] && return 0 done return 1 } install_bonding_driver () { local fn="install_bonding_driver" if ! bond_master_exists ${1}; then modprobe bonding || return 1 echo "+$1" > /sys/class/net/bonding_masters 2>/dev/null fi ( # Set config here need_config "$1" source_config if [ -f /sys/class/net/${DEVICE}/bonding/slaves ] && [ $(wc -l < /sys/class/net/${DEVICE}/bonding/slaves) -eq 0 ]; then /sbin/ip link set dev ${DEVICE} down # parse options and put them to arrays for arg in $BONDING_OPTS ; do bopts_keys[${#bopts_keys[*]}]=${arg%%=*} bopts_vals[${#bopts_vals[*]}]=${arg##*=} done # add the bits to setup driver parameters here # first set mode, miimon for (( idx=0; idx < ${#bopts_keys[*]}; idx++ )) ; do key=${bopts_keys[$idx]} value=${bopts_vals[$idx]} if [ "${key}" = "mode" ] ; then echo "${value}" > /sys/class/net/${DEVICE}/bonding/$key || { net_log $"Failed to set value '$value' [mode] to ${DEVICE} bonding device" err $fn } bopts_keys[$idx]="" fi if [ "${key}" = "miimon" ] ; then echo "${value}" > /sys/class/net/${DEVICE}/bonding/$key || { net_log $"Failed to set value '$value' [miimon] to ${DEVICE} bonding device" err $fn } bopts_keys[$idx]="" fi done # set all other remaining options for (( idx=0; idx < ${#bopts_keys[*]}; idx++ )) ; do key=${bopts_keys[$idx]} value=${bopts_vals[$idx]} # option already set; take next [[ -z "$key" ]] && continue if [ "${key}" = "arp_ip_target" -a "${value:0:1}" != "+" ]; then OLDIFS=$IFS; IFS=','; for arp_ip in $value; do if ! grep -q $arp_ip /sys/class/net/${DEVICE}/bonding/$key; then echo +$arp_ip > /sys/class/net/${DEVICE}/bonding/$key || { net_log $"Failed to set '$arp_ip' value [arp_ip_target] to ${DEVICE} bonding device" err $fn } fi done IFS=$OLDIFS; elif [ "${key}" = "arp_ip_target" ]; then if ! grep -q ${value#+} /sys/class/net/${DEVICE}/bonding/$key; then echo "$value" > /sys/class/net/${DEVICE}/bonding/$key || { net_log $"Failed to set '$value' value [arp_ip_target] to ${DEVICE} bonding device" err $fn } fi elif [ "${key}" != "primary" ]; then echo $value > /sys/class/net/${DEVICE}/bonding/$key || { net_log $"Failed to set '$value' value [$key] to ${DEVICE} bonding device" err $fn } fi done fi ) return 0 } is_bonding_device () { [ -f "/sys/class/net/$1/bonding/slaves" ] } # Invoke this when /etc/resolv.conf has changed: change_resolv_conf () { oldumask=$(umask) umask 022 s=$(/bin/grep '^[\ \ ]*option' /etc/resolv.conf 2>/dev/null) if [ $# -gt 1 ]; then if [ "x$s" != "x" ]; then s="$s"$'\n' fi n_args=$# while [ $n_args -gt 0 ]; do case "$s" in *$1*) shift n_args=$(($n_args-1)) continue ;; esac s="$s$1" shift if [ $# -gt 0 ]; then s="$s"$'\n' fi n_args=$(($n_args-1)) done elif [ $# -eq 1 -a -r "$1" ]; then if [ "x$s" != "x" ]; then s="$s"$'\n'$(/bin/grep -vF "$s" $1) else s=$(cat $1) fi else return fi if [ -e "$RESOLVCONF_FLAGFILE" ]; then echo "$s" | /sbin/resolvconf -a ${DEVICE} else (echo "$s" > /etc/resolv.conf) >/dev/null 2>&1; fi r=$? if [ $r -eq 0 ]; then [ -x /sbin/restorecon ] && /sbin/restorecon /etc/resolv.conf >/dev/null 2>&1 # reset the correct context /usr/bin/logger -p local7.notice -t "NET" -i "$0 : updated /etc/resolv.conf" [ -e /run/nscd/socket ] && /usr/sbin/nscd -i hosts # invalidate cache fi umask "$oldumask" return $r } clear_resolv_conf () { if [ -e "$RESOLVCONF_FLAGFILE" ]; then /sbin/resolvconf -d ${DEVICE} elif [ -f /etc/resolv.conf.save ]; then change_resolv_conf /etc/resolv.conf.save rm -f /etc/resolv.conf.save fi } # Logging function # # Usage: net_log # # Default level is 'err'. net_log() { local message="$1" local level="$2" local name="$3" [ -z "$message" ] && return 1 [ -z "$level" ] && level=err [ -z "$name" ] && name=$0 case $level in 'debug') local txt_level=$"DEBUG " ;; 'err') local txt_level=$"ERROR " ;; 'warning') local txt_level=$"WARN " ;; 'info') local txt_level=$"INFO " ;; esac echo "$txt_level: [$name] $message" if [ -x /usr/bin/logger ]; then /usr/bin/logger -p daemon.$level -t "$name" "$message" fi return 0 } update_DNS_entries() { # Remove duplicate values from DNS options if any: if [ -n "${DNS3}" ] && [[ "${DNS3}" == "${DNS2}" || "${DNS3}" == "${DNS1}" ]]; then unset DNS3 fi if [ -n "${DNS2}" ] && [[ "${DNS2}" == "${DNS1}" ]]; then unset DNS2 fi # Shift the DNS options if necessary: if [ -z "${DNS1}" ] && [ -n "${DNS2}" ]; then DNS1="${DNS2}" unset DNS2 fi if [ -z "${DNS2}" ] && [ -n "${DNS3}" ]; then DNS2="${DNS3}" unset DNS3 fi # We need to check DNS1 again in case only DNS3 was set at all: if [ -z "${DNS1}" ] && [ -n "${DNS2}" ]; then DNS1="${DNS2}" unset DNS2 fi }