Rev 57 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed
#!/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=initscriptsTEXTDOMAINDIR=/etc/localedevice=$1if [ "$device" = "" ]; thenecho $"usage: ifup-aliases <net-device> [<parent-config>]\n"exit 1fiPARENTCONFIG=${2:-ifcfg-$device}parent_device=$devicecd /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/prefixsplit($2,IPADDR,"/");# Create A_B_C_D IP address formIP_ADDR=IPADDR[1];gsub(/\./,"_",IP_ADDR);# Split device into device:indexsplit($NF,DEV,":");# Update last deviceLAST_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/networkeval ` (. /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\;;) `[ -z "$default_GATEWAY" ] && default_GATEWAY=$network_GATEWAYfunction ini_env (){DEVICE=""IPADDR=""PREFIX=$default_PREFIXNETMASK=$default_NETMASKBROADCAST=$default_BROADCASTGATEWAY=$default_GATEWAYNO_ALIASROUTING=$default_NO_ALIASROUTINGONPARENT=""ARPCHECK=$default_ARPCHECK}function is_default_gateway (){LC_ALL=C /sbin/route -n \| awk '$1 == "0.0.0.0" && $2 == "'"$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 ]]); thennet_log $"error in $FILE: invalid alias number"return 1fieval "ipseen=\$ipseen_${IPGLOP}; devseen=\$devseen_${DEVNUM};ipseen_${IPGLOP}=$FILE; devseen_${DEVNUM}=$FILE;";if [ -n "$ipseen" ]; thennet_log $"error in $FILE: already seen ipaddr $IPADDR in $ipseen"return 1fiif [ -n "$devseen" ]; thennet_log $"error in $FILE: already seen device $parent_device:$DEVNUM in $devseen"return 1fiif [ -z "$DEVICE" -o -z "$IPADDR" ]; thennet_log $"error in $FILE: didn't specify device or ipaddr"return 1fiif [ -z "$NETMASK" -a -z "$PREFIX" ]; thennet_log $"error iN $FILE: didn't specify netmask or prefix"fiif [ -z "$PREFIX" ]; theneval $(/bin/ipcalc --prefix ${IPADDR} ${NETMASK})fiif [ -z "$BROADCAST" -o "$BROADCAST" = "$default_BROADCAST" ]; theneval $(/bin/ipcalc --broadcast ${IPADDR}/${PREFIX})fiif [ "$no_devices_are_up" = "yes" ]; thensetup_this=yeselsesetup_this=""eval "rdev_addr=\$rdev_${DEVNUM}_addr;rdev_pb=\$rdev_${DEVNUM}_pb;rdev_mark=\$rdev_${DEVNUM}_mark;rdevip=\$rdevip_${IPGLOP};";if [ -n "$rdev_addr" ]; thenif [ "$rdev_addr" = "${IPADDR}" ]; thennewmark=keepif [ "$rdev_pb" != "${PREFIX}_${BROADCAST}" ]; thensetup_this=freshenelsesetup_this=nofielseif [ "$rdev_mark" != "remove" ]; then/sbin/ip addr flush dev $parent_device label $parent_device:${DEVNUM}do_netreport=yesfinewmark=removesetup_this=yesfiif [ -n "$rdev_mark" -a "$rdev_mark" != "$newmark" ]; thennet_log $"error in ifcfg-${parent_device}: files"return 1fieval " rdev_${DEVNUM}_mark=\$newmark ";elsesetup_this=yesfiif [ -n "$rdevip" -a "$rdevip" != "${DEVNUM}" ]; theneval " mark_remove=\$rdev_${rdevip}_mark ";if [ -n "$mark_remove" -a "$mark_remove" != "remove" ]; thennet_log $"error in ifcfg-${parent_device}: files"return 1fiif [ "$mark_remove" != "remove" ]; theneval " rdev_${rdevip}_mark=remove ";/sbin/ip addr flush dev $parent_device label $parent_device:$rdevipdo_netreport=yesfififiif [ "$setup_this" = "freshen" ] ; then# we can do the freshen stuff right now/sbin/ip addr change ${IPADDR}/${PREFIX} brd ${BROADCAST}fiif [ "$setup_this" = "yes" ] ; thenif [ "${parent_device}" != "lo" ] && [ "${ARPCHECK}" != "no" ] && \is_available ${parent_device} && \( grep -qswi "up" /sys/class/net/${parent_device}/operstate || grep -qswi "1" /sys/class/net/${parent_device}/carrier ) ; thenecho $"Determining if ip address ${IPADDR} is already in use for device ${parent_device}..."ARPING=$(/sbin/arping -q -c 2 -w ${ARPING_WAIT:-3} -D -I ${parent_device} ${IPADDR})if [ $? = 1 ]; thenARPINGMAC=$(echo $ARPING | sed -ne 's/.*\[\(.*\)\].*/\1/p')net_log $"Error, some other host ($ARPINGMAC) already uses address ${IPADDR}."return 1fifi/sbin/ip addr add ${IPADDR}/${PREFIX} brd ${BROADCAST} dev ${parent_device} label ${DEVICE}# update ARP cache of neighboring computers:if [ "${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 &fiif [ "$NO_ALIASROUTING" != yes ]; thenGATEWAYDEV=$network_GATEWAYDEV;if [ -n "${GATEWAY}" -a \\( -z "${GATEWAYDEV}" -o "${GATEWAYDEV}" = "${DEVICE}" \) ]; then# set up default gateway, if it isn't already thereif ! is_default_gateway "$GATEWAY"; thenroute add default gw ${GATEWAY} \${METRIC:+metric $METRIC} ${DEVICE}fifi/etc/sysconfig/network-scripts/ifup-routes ${DEVICE} ${NAME}do_netreport=yesifuplocal_queue="$ifuplocal_queue $DEVICE"fifi}if [ "$BASH_VERSINFO" ]; then shopt -s nullglob; else allow_null_glob_expansion=foo; fifor FILE in ifcfg-${parent_device}:* ; dois_ignored_file "$FILE" && continueini_env;. ./$FILE;[ -z "$DEVICE" ] && DEVICE=${FILE##ifcfg-}[ "$ONPARENT" != "no" -a "$ONPARENT" != "NO" ] && new_interface;unset DEVICEdonefor FILE in ifcfg-${parent_device}-range* ; dois_ignored_file "$FILE" && continueini_env;. ./$FILE;ipaddr_prefix=${IPADDR_START%.*}ipaddr_startnum=${IPADDR_START##*.}ipaddr_endnum=${IPADDR_END##*.}if [ "${IPADDR_START%.*}" != "${IPADDR_END%.*}" ]; thennet_log $"error in $FILE: IPADDR_START and IPADDR_END don't agree"; continuefiif [ $ipaddr_startnum -gt $ipaddr_endnum ]; thennet_log $"error in $FILE: IPADDR_START greater than IPADDR_END"; continuefiipaddr_num=$ipaddr_startnumipaddr_clonenum=$CLONENUM_STARTwhile [ $ipaddr_num -le $ipaddr_endnum ]; doIPADDR="$ipaddr_prefix.$ipaddr_num"DEVICE="$parent_device:$ipaddr_clonenum"[ "$ONPARENT" != "no" -a "$ONPARENT" != "NO" ] && new_interface;ipaddr_num=$(($ipaddr_num+1))ipaddr_clonenum=$(($ipaddr_clonenum+1))donedone## Remove any devices that should not be around#for DEVNUM in $rdev_LIST ; doeval " rdev_mark=\$rdev_${DEVNUM}_mark ";if [ -z "$rdev_mark" ]; then/sbin/ip addr flush dev $parent_device label $parent_device:${DEVNUM}do_netreport=yesfidone## Notify of new device creation#if [ -n "$do_netreport" ]; thendo_netreportfiif [ -x /sbin/ifup-local ]; thenfor DEVICE in $ifuplocal_queue ; do/sbin/ifup-local ${DEVICE}donefi