aboutsummaryrefslogtreecommitdiffstats
path: root/network-scripts/ifup-aliases
diff options
context:
space:
mode:
Diffstat (limited to 'network-scripts/ifup-aliases')
-rwxr-xr-xnetwork-scripts/ifup-aliases370
1 files changed, 370 insertions, 0 deletions
diff --git a/network-scripts/ifup-aliases b/network-scripts/ifup-aliases
new file mode 100755
index 00000000..971ce208
--- /dev/null
+++ b/network-scripts/ifup-aliases
@@ -0,0 +1,370 @@
+#!/bin/bash
+
+#
+# configures aliases of device $1
+#
+# This script goes out of its way to arrive at the configuration of ip
+# aliases described in the ifcfg-$DEV:* and ifcfg-$DEV-range* files from
+# whatever existing configuration it may be given: existing aliases not
+# specified in the configuration will be removed, netmasks and broadcast
+# addrs will be updated on existing aliases, and new aliases will be setup.
+#
+# range specification files:
+#
+# One can specify ranges of alised ipaddress using ifcfg-$DEV-range* files.
+# Specify multiple ranges using multiple files, such as ifcfg-eth0-range0 and
+# ifcfg-eth0-range1, etc. In these files, the following configuration variables
+# specify the range:
+#
+# IPADDR_START -- ipaddr to start range at. eg "192.168.30.1"
+# IPADDR_END -- ipaddr to end range at. eg "192.168.30.254"
+# CLONENUM_START -- interface clone number to start using for this range. eg "0"
+#
+# The above example values create the interfaces eth0:0 through eth0:253 using
+# ipaddrs 192.168.30.1 through 192.168.30.254, inclusive.
+#
+# Other configuration variables such as NETMASK and BROADCAST may be specified
+# in the range file and will apply to all of the ipaddresses in the range. Range
+# files also inherit configuration from the ifcfg-$DEV file just like normal.
+#
+# Note that IPADDR_START and IPADR_END are required to be in the same class-c
+# block. I.e. IPADDR_START=192.168.30.1 and IPADDR_END=192.168.31.255 is
+# not valid.
+#
+# speed with large sets of interfaces:
+#
+# Considerable effort was spent making this script fast. It can efficiently
+# handle a thousand ip aliases on one interface.
+#
+# With large sets of ipaddresses the NO_ALIASROUTING=yes configuration is
+# highly recommended. (This can be specified in ifcfg-$DEV and inherited.) This
+# prevents this script from setting up routing details for the virtual
+# interfaces, which I don't think is needed, because outgoing traffic can use the
+# main interface. However, make your own conclusions on what you need.
+#
+# My test setup of four class C address blocks on a P166 took 25 seconds of
+# which 16 seconds of this was spent in the ifcconfig calls. Without the
+# NO_ALIASROUTING=yes config an additional 12 seconds is spent in route calls.
+#
+# notes on internals:
+#
+# This script uses the bash "eval" command to lookup shell variables with names
+# which are generated from other shell variables. This allows us to, in effect,
+# create hashes using the shell variable namesspace by just including the hash
+# key in the name of the variable.
+#
+# This script originally written by: David Harris <dharris@drh.net>
+# Principal Engineer, DRH Internet
+# June 30, 1999
+#
+# modified by: Bill Nottingham <notting@redhat.com>
+
+TEXTDOMAIN=initscripts
+TEXTDOMAINDIR=/etc/locale
+
+device=$1
+if [ "$device" = "" ]; then
+ echo $"usage: ifup-aliases <net-device> [<parent-config>]\n"
+ exit 1
+fi
+
+PARENTCONFIG=${2:-ifcfg-$device}
+parent_device=$device
+
+cd /etc/sysconfig/network-scripts
+. ./network-functions
+
+# Grab the current configuration of any running aliases, place device info
+# into variables of the form:
+# rdev_<index>_addr = <ip address>
+# rdev_<index>_pb = <prefix>_<broadcast>
+# rdevip_<ipaddress> = <index>
+# Example:
+# rdev_0_addr=192.168.1.1
+# rdev_0_pb=24_192.16.1.255
+# rdevip_192_168_1_1=0
+#
+# A list of all the devices is created in rdev_LIST.
+
+eval $( ip addr show $device label $device:* | \
+ awk 'BEGIN { COUNT=0;LAST_DEV="" } /inet / {
+ # Split IP address into address/prefix
+ split($2,IPADDR,"/");
+ # Create A_B_C_D IP address form
+ IP_ADDR=IPADDR[1];
+ gsub(/\./,"_",IP_ADDR);
+ # Split device into device:index
+ split($NF,DEV,":");
+ # Update last device
+ LAST_DEV=LAST_DEV " " DEV[2];
+ printf("rdev_%s_addr=%s\nrdevip_%s=%s\nrdev_%s_pb=%s_%s\nrdev_LIST=\"%s\"\n",
+ DEV[2],IPADDR[1],IP_ADDR,DEV[2],DEV[2],IPADDR[2],$4,LAST_DEV);
+ } END {
+ if(LAST_DEV == "") print "no_devices_are_up=yes"
+ }' );
+
+#
+# Store configuration of the parent device and network
+#
+
+# read from the /etc/sysconfig/network
+eval ` (
+ . /etc/sysconfig/network;
+ echo network_GATEWAY=$GATEWAY\;;
+ echo network_GATEWAYDEV=$GATEWAYDEV\;;
+) `
+
+# read defaults from the parent config file
+[ -f $PARENTCONFIG ] || {
+ net_log $"Missing config file $PARENTCONFIG."
+ exit 1
+}
+eval ` (
+ . ./$PARENTCONFIG;
+ echo default_PREFIX=$PREFIX\;;
+ echo default_NETMASK=$NETMASK\;;
+ echo default_BROADCAST=$BROADCAST\;;
+ echo default_GATEWAY=$GATEWAY\;;
+ echo default_NO_ALIASROUTING=$NO_ALIASROUTING\;;
+ echo default_ARPCHECK=$ARPCHECK\;;
+ echo default_ARPUPDATE=$ARPUPDATE\;;
+) `
+[ -z "$default_GATEWAY" ] && default_GATEWAY=$network_GATEWAY
+
+function ini_env ()
+{
+ DEVICE=""
+ IPADDR=""
+ IPV6ADDR=""
+ PREFIX=$default_PREFIX
+ NETMASK=$default_NETMASK
+ BROADCAST=$default_BROADCAST
+ GATEWAY=$default_GATEWAY
+ NO_ALIASROUTING=$default_NO_ALIASROUTING
+ ONPARENT=""
+ ARPCHECK=$default_ARPCHECK
+ ARPUPDATE=$default_ARPUPDATE
+}
+
+function is_default_gateway ()
+{
+ LC_ALL=C /sbin/ip route ls default scope global \
+ | awk '$3 == "'"$1"'" { found = 1; } END { exit found == 0; }'
+}
+
+#
+# Read the alias configuration files and enable each aliased
+# device using new_interface()
+#
+
+function new_interface ()
+{
+
+ ipa=$IPADDR; ipb=${ipa#*.}; ipc=${ipb#*.};
+ IPGLOP="${ipa%%.*}_${ipb%%.*}_${ipc%%.*}_${ipc#*.}";
+ DEVNUM=${DEVICE#*:}
+
+ MATCH='^[0-9A-Za-z_]*$'
+ if (LC_ALL=C; [[ ! "$DEVNUM" =~ $MATCH ]]); then
+ net_log $"error in $FILE: invalid alias number"
+ return 1
+ fi
+
+ eval "
+ ipseen=\$ipseen_${IPGLOP}; devseen=\$devseen_${DEVNUM};
+ ipseen_${IPGLOP}=$FILE; devseen_${DEVNUM}=$FILE;
+ ";
+
+ if [ -n "$ipseen" ]; then
+ net_log $"error in $FILE: already seen ipaddr $IPADDR in $ipseen"
+ return 1
+ fi
+
+ if [ -n "$devseen" ]; then
+ net_log $"error in $FILE: already seen device $parent_device:$DEVNUM in $devseen"
+ return 1
+ fi
+
+ if [ -z "$DEVICE" -o -z "$IPADDR" ]; then
+ if [ -n "$IPV6ADDR" -a -n "$DEVICE" ] && ! is_false "$IPV6INIT"; then
+ /etc/sysconfig/network-scripts/ifup-ipv6 ${DEVICE}
+ return $?
+ fi
+ net_log $"error in $FILE: didn't specify device or ipaddr"
+ return 1
+ fi
+
+ if [ -z "$NETMASK" -a -z "$PREFIX" ]; then
+ net_log $"error iN $FILE: didn't specify netmask or prefix"
+ fi
+
+ if [ -z "$PREFIX" ]; then
+ eval $(/bin/ipcalc --prefix ${IPADDR} ${NETMASK})
+ fi
+
+ if [ -z "$BROADCAST" -o "$BROADCAST" = "$default_BROADCAST" ]; then
+ eval $(/bin/ipcalc --broadcast ${IPADDR}/${PREFIX})
+ fi
+
+ if is_true "$no_devices_are_up"; then
+ setup_this=yes
+ else
+
+ setup_this=""
+
+ eval "
+ rdev_addr=\$rdev_${DEVNUM}_addr;
+ rdev_pb=\$rdev_${DEVNUM}_pb;
+ rdev_mark=\$rdev_${DEVNUM}_mark;
+ rdevip=\$rdevip_${IPGLOP};
+ ";
+
+ if [ -n "$rdev_addr" ]; then
+ if [ "$rdev_addr" = "${IPADDR}" ]; then
+ newmark=keep
+ if [ "$rdev_pb" != "${PREFIX}_${BROADCAST}" ]; then
+ setup_this=freshen
+ else
+ setup_this=no
+ fi
+ else
+ if [ "$rdev_mark" != "remove" ]; then
+ /sbin/ip addr flush dev $parent_device label $parent_device:${DEVNUM}
+ fi
+ newmark=remove
+ setup_this=yes
+ fi
+ if [ -n "$rdev_mark" -a "$rdev_mark" != "$newmark" ]; then
+ net_log $"error in ifcfg-${parent_device}: files"
+ return 1
+ fi
+ eval " rdev_${DEVNUM}_mark=\$newmark ";
+ else
+ setup_this=yes
+ fi
+
+ if [ -n "$rdevip" -a "$rdevip" != "${DEVNUM}" ]; then
+ eval " mark_remove=\$rdev_${rdevip}_mark ";
+ if [ -n "$mark_remove" -a "$mark_remove" != "remove" ]; then
+ net_log $"error in ifcfg-${parent_device}: files"
+ return 1
+ fi
+ if [ "$mark_remove" != "remove" ]; then
+ eval " rdev_${rdevip}_mark=remove ";
+ /sbin/ip addr flush dev $parent_device label $parent_device:$rdevip
+ fi
+ fi
+
+ fi
+
+ if [ "$setup_this" = "freshen" ] ; then
+ # we can do the freshen stuff right now
+ /sbin/ip addr change ${IPADDR}/${PREFIX} brd ${BROADCAST}
+ fi
+
+ if is_true "$setup_this"; then
+ if [ "${parent_device}" != "lo" ] && ! is_false "${ARPCHECK}" && \
+ is_available ${parent_device} && \
+ ( grep -qswi "up" /sys/class/net/${parent_device}/operstate || grep -qswi "1" /sys/class/net/${parent_device}/carrier ) ; then
+ echo $"Determining if IP address ${IPADDR} is already in use for device ${parent_device}…"
+ ARPING=$(/sbin/arping -c 2 -w ${ARPING_WAIT:-3} -D -I ${parent_device} ${IPADDR})
+ if [ $? = 1 ]; then
+ ARPINGMAC=$(echo $ARPING | sed -ne 's/.*\[\(.*\)\].*/\1/p')
+ net_log $"Error, some other host ($ARPINGMAC) already uses address ${IPADDR}."
+ return 1
+ fi
+ fi
+
+ /sbin/ip addr add ${IPADDR}/${PREFIX} brd ${BROADCAST} \
+ dev ${parent_device} label ${DEVICE}
+
+ # update ARP cache of neighboring computers:
+ if ! is_false "${ARPUPDATE}" && [ "${REALDEVICE}" != "lo" ]; then
+ /sbin/arping -q -A -c 1 -I ${parent_device} ${IPADDR}
+ ( sleep 2; /sbin/arping -q -U -c 1 -I ${parent_device} ${IPADDR} ) > /dev/null 2>&1 < /dev/null &
+ fi
+
+ ! is_false "$IPV6INIT" && \
+ /etc/sysconfig/network-scripts/ifup-ipv6 ${DEVICE}
+
+ if ! is_true "$NO_ALIASROUTING"; then
+
+ GATEWAYDEV=$network_GATEWAYDEV;
+
+ if [ -n "${GATEWAY}" -a \
+ \( -z "${GATEWAYDEV}" -o "${GATEWAYDEV}" = "${DEVICE}" \) ]; then
+ # set up default gateway, if it isn't already there
+ if ! is_default_gateway "$GATEWAY"; then
+ ip route replace default ${METRIC:+metric $METRIC} via ${GATEWAY} dev ${DEVICE}
+ fi
+ fi
+
+ /etc/sysconfig/network-scripts/ifup-routes ${DEVICE} ${NAME}
+
+ ifuplocal_queue="$ifuplocal_queue $DEVICE"
+ fi
+ fi
+}
+
+if [ "$BASH_VERSINFO" ]; then
+ shopt -s nullglob
+else
+ allow_null_glob_expansion=foo
+fi
+
+for FILE in ifcfg-${parent_device}:* ; do
+ is_ignored_file "$FILE" && continue
+ ini_env
+ . ./$FILE
+ [ -z "$DEVICE" ] && DEVICE=${FILE##ifcfg-}
+ ! is_false "$ONPARENT" && new_interface
+ unset DEVICE
+done
+
+for FILE in ifcfg-${parent_device}-range* ; do
+ is_ignored_file "$FILE" && continue
+ ini_env
+ . ./$FILE
+
+ ipaddr_prefix=${IPADDR_START%.*}
+ ipaddr_startnum=${IPADDR_START##*.}
+ ipaddr_endnum=${IPADDR_END##*.}
+
+ if [ "${IPADDR_START%.*}" != "${IPADDR_END%.*}" ]; then
+ net_log $"error in $FILE: IPADDR_START and IPADDR_END don't agree"
+ continue
+ fi
+
+ if [ $ipaddr_startnum -gt $ipaddr_endnum ]; then
+ net_log $"error in $FILE: IPADDR_START greater than IPADDR_END"
+ continue
+ fi
+
+ ipaddr_num=$ipaddr_startnum
+ ipaddr_clonenum=$CLONENUM_START
+
+ while [ $ipaddr_num -le $ipaddr_endnum ]; do
+ IPADDR="$ipaddr_prefix.$ipaddr_num"
+ DEVICE="$parent_device:$ipaddr_clonenum"
+ IPV6INIT="no"
+ ! is_false "$ONPARENT" && new_interface
+ ipaddr_num=$(($ipaddr_num+1))
+ ipaddr_clonenum=$(($ipaddr_clonenum+1))
+ done
+done
+
+#
+# Remove any devices that should not be around
+#
+for DEVNUM in $rdev_LIST ; do
+ eval " rdev_mark=\$rdev_${DEVNUM}_mark "
+ if [ -z "$rdev_mark" ]; then
+ /sbin/ip addr flush dev $parent_device label $parent_device:${DEVNUM}
+ fi
+done
+
+if [ -x /sbin/ifup-local ]; then
+ for DEVICE in $ifuplocal_queue ; do
+ /sbin/ifup-local ${DEVICE}
+ done
+fi