| 1 | #!/bin/bash |
|---|
| 2 | |
|---|
| 3 | # |
|---|
| 4 | # configures aliases of device $1 |
|---|
| 5 | # |
|---|
| 6 | # This script goes out of its way to arrive at the configuration of ip |
|---|
| 7 | # aliases described in the ifcfg-$DEV:* and ifcfg-$DEV-range* files from |
|---|
| 8 | # whatever existing configuration it may be given: existing aliases not |
|---|
| 9 | # specified in the configuration will be removed, netmasks and broadcast |
|---|
| 10 | # addrs will be updated on existing aliases, and new aliases will be setup. |
|---|
| 11 | # |
|---|
| 12 | # range specification files: |
|---|
| 13 | # |
|---|
| 14 | # One can specify ranges of alised ipaddress using ifcfg-$DEV-range* files. |
|---|
| 15 | # Specify multiple ranges using multiple files, such as ifcfg-eth0-range0 and |
|---|
| 16 | # ifcfg-eth0-range1, etc. In these files, the following configuration variables |
|---|
| 17 | # specify the range: |
|---|
| 18 | # |
|---|
| 19 | # IPADDR_START -- ipaddr to start range at. eg "192.168.30.1" |
|---|
| 20 | # IPADDR_END -- ipaddr to end range at. eg "192.168.30.254" |
|---|
| 21 | # CLONENUM_START -- interface clone number to start using for this range. eg "0" |
|---|
| 22 | # |
|---|
| 23 | # The above example values create the interfaces eth0:0 through eth0:253 using |
|---|
| 24 | # ipaddrs 192.168.30.1 through 192.168.30.254, inclusive. |
|---|
| 25 | # |
|---|
| 26 | # Other configuration variables such as NETMASK and BROADCAST may be specified |
|---|
| 27 | # in the range file and will apply to all of the ipaddresses in the range. Range |
|---|
| 28 | # files also inherit configuration from the ifcfg-$DEV file just like normal. |
|---|
| 29 | # |
|---|
| 30 | # Note that IPADDR_START and IPADR_END are required to be in the same class-c |
|---|
| 31 | # block. I.e. IPADDR_START=192.168.30.1 and IPADDR_END=192.168.31.255 is |
|---|
| 32 | # not valid. |
|---|
| 33 | # |
|---|
| 34 | # speed with large sets of interfaces: |
|---|
| 35 | # |
|---|
| 36 | # Considerable effort was spent making this script fast. It can efficiently |
|---|
| 37 | # handle a thousand ip aliases on one interface. |
|---|
| 38 | # |
|---|
| 39 | # With large sets of ipaddresses the NO_ALIASROUTING=yes configuration is |
|---|
| 40 | # highly recommended. (This can be specified in ifcfg-$DEV and inherited.) This |
|---|
| 41 | # prevents this script from setting up routing details for the virtual |
|---|
| 42 | # interfaces, which I don't think is needed, because outgoing traffic can use the |
|---|
| 43 | # main interface. However, make your own conclusions on what you need. |
|---|
| 44 | # |
|---|
| 45 | # My test setup of four class C address blocks on a P166 took 25 seconds of |
|---|
| 46 | # which 16 seconds of this was spent in the ifcconfig calls. Without the |
|---|
| 47 | # NO_ALIASROUTING=yes config an additional 12 seconds is spent in route calls. |
|---|
| 48 | # |
|---|
| 49 | # notes on internals: |
|---|
| 50 | # |
|---|
| 51 | # This script uses the bash "eval" command to lookup shell variables with names |
|---|
| 52 | # which are generated from other shell variables. This allows us to, in effect, |
|---|
| 53 | # create hashes using the shell variable namesspace by just including the hash |
|---|
| 54 | # key in the name of the variable. |
|---|
| 55 | # |
|---|
| 56 | # This script originally written by: David Harris <dharris@drh.net> |
|---|
| 57 | # Principal Engineer, DRH Internet |
|---|
| 58 | # June 30, 1999 |
|---|
| 59 | # |
|---|
| 60 | # modified by: Bill Nottingham <notting@redhat.com> |
|---|
| 61 | |
|---|
| 62 | TEXTDOMAIN=initscripts |
|---|
| 63 | TEXTDOMAINDIR=/etc/locale |
|---|
| 64 | |
|---|
| 65 | device=$1 |
|---|
| 66 | if [ "$device" = "" ]; then |
|---|
| 67 | echo $"usage: ifup-aliases <net-device> [<parent-config>]\n" |
|---|
| 68 | exit 1 |
|---|
| 69 | fi |
|---|
| 70 | |
|---|
| 71 | PARENTCONFIG=${2:-ifcfg-$device} |
|---|
| 72 | parent_device=$device |
|---|
| 73 | |
|---|
| 74 | cd /etc/sysconfig/network-scripts |
|---|
| 75 | . /etc/sysconfig/network-scripts/network-functions |
|---|
| 76 | |
|---|
| 77 | # Grab the current configuration of any running aliases device info is placed |
|---|
| 78 | # into variables in the form: rdev_$DEVICE_addr, dev_$DEVICE_mb and |
|---|
| 79 | # rdevip_$IPGLOP. A list of all the devices is created in rdev_LIST. |
|---|
| 80 | |
|---|
| 81 | eval $(LC_ALL= LANG= /sbin/ifconfig | LC_ALL=C sed -n ' |
|---|
| 82 | # Alias name: store the number in TMP, ignore the following address if the |
|---|
| 83 | # device name does not match. This may leave a hanging ||, so dummy X=x |
|---|
| 84 | # comands are used to ignore a possible previous condition. |
|---|
| 85 | /^[^[:space:]]*:[0-9A-Za-z_]*/ { |
|---|
| 86 | s|^\([^:]*\):\([0-9A-Za-z_]*\).*$|X=x; TMP="\2"; [ "$device" != "\1" ] \|\| |p |
|---|
| 87 | b |
|---|
| 88 | } |
|---|
| 89 | # Non-alias device: always ignore the following address |
|---|
| 90 | /^[^[:space:]]/ { |
|---|
| 91 | s|^.*$|X=x; true \|\| |p |
|---|
| 92 | b |
|---|
| 93 | } |
|---|
| 94 | # Address: Preceded by a device name, which was converted into |
|---|
| 95 | # condition || |
|---|
| 96 | # So this triggers only for $device. |
|---|
| 97 | # Add a trailing || (which will be swallowed by X=x) to keep the syntax |
|---|
| 98 | # correct. |
|---|
| 99 | /inet addr:[0-9]*\.[0-9]*\.[0-9]*\.[0-9]* *Bcast:[0-9.]* *Mask:[0-9.]*/ { |
|---|
| 100 | s|^.*inet addr:\(\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\)\) *Bcast:\([0-9.]*\) *Mask:\([0-9.]*\).*$|eval "rdev_${TMP}_addr=\1; rdev_${TMP}_mb=\7_\6; rdevip_\2_\3_\4_\5=${TMP}; rdev_LIST=\\"\\$rdev_LIST \\${TMP}\\"; " \|\| |p |
|---|
| 101 | b |
|---|
| 102 | }') X=x |
|---|
| 103 | |
|---|
| 104 | if [ -z "$rdev_LIST" ]; then |
|---|
| 105 | no_devices_are_up=yes |
|---|
| 106 | fi |
|---|
| 107 | |
|---|
| 108 | ##for DEVNUM in $rdev_LIST ; do |
|---|
| 109 | ##eval " |
|---|
| 110 | ##echo \"rdev_${DEVNUM}_addr = \$rdev_${DEVNUM}_addr\" |
|---|
| 111 | ##echo \"rdev_${DEVNUM}_mb = \$rdev_${DEVNUM}_mb\" "; |
|---|
| 112 | ##done |
|---|
| 113 | ##echo ""; echo "-----"; echo "" |
|---|
| 114 | |
|---|
| 115 | # |
|---|
| 116 | # Store configuration of the parent device and network |
|---|
| 117 | # |
|---|
| 118 | |
|---|
| 119 | # read from the /etc/sysconfig/network |
|---|
| 120 | eval ` ( |
|---|
| 121 | . /etc/sysconfig/network; |
|---|
| 122 | echo network_GATEWAY=$GATEWAY\;; |
|---|
| 123 | echo network_GATEWAYDEV=$GATEWAYDEV\;; |
|---|
| 124 | ) ` |
|---|
| 125 | |
|---|
| 126 | # read defaults from the parent config file |
|---|
| 127 | [ -f $PARENTCONFIG ] || { |
|---|
| 128 | echo $"Missing config file $PARENTCONFIG." >&2 |
|---|
| 129 | exit 1 |
|---|
| 130 | } |
|---|
| 131 | eval ` ( |
|---|
| 132 | . $PARENTCONFIG; |
|---|
| 133 | echo default_NETMASK=$NETMASK\;; |
|---|
| 134 | echo default_BROADCAST=$BROADCAST\;; |
|---|
| 135 | echo default_GATEWAY=$GATEWAY\;; |
|---|
| 136 | echo default_NO_ALIASROUTING=$NO_ALIASROUTING\;; |
|---|
| 137 | ) ` |
|---|
| 138 | [ -z "$default_GATEWAY" ] && default_GATEWAY=$network_GATEWAY |
|---|
| 139 | |
|---|
| 140 | function ini_env () |
|---|
| 141 | { |
|---|
| 142 | DEVICE="" |
|---|
| 143 | IPADDR="" |
|---|
| 144 | NETMASK=$default_NETMASK |
|---|
| 145 | BROADCAST=$default_BROADCAST |
|---|
| 146 | GATEWAY=$default_GATEWAY |
|---|
| 147 | NO_ALIASROUTING=$default_NO_ALIASROUTING |
|---|
| 148 | ONPARENT="" |
|---|
| 149 | } |
|---|
| 150 | |
|---|
| 151 | function is_default_gateway () |
|---|
| 152 | { |
|---|
| 153 | LC_ALL=C /sbin/route -n \ |
|---|
| 154 | | awk '$1 == "0.0.0.0" && $2 == "'"$1"'" { found = 1; } |
|---|
| 155 | END { exit found == 0; }' |
|---|
| 156 | } |
|---|
| 157 | |
|---|
| 158 | # |
|---|
| 159 | # Read the alias configuration files and enable each aliased |
|---|
| 160 | # device using new_interface() |
|---|
| 161 | # |
|---|
| 162 | |
|---|
| 163 | function new_interface () |
|---|
| 164 | { |
|---|
| 165 | |
|---|
| 166 | ipa=$IPADDR; ipb=${ipa#*.}; ipc=${ipb#*.}; |
|---|
| 167 | IPGLOP="${ipa%%.*}_${ipb%%.*}_${ipc%%.*}_${ipc#*.}"; |
|---|
| 168 | DEVNUM=${DEVICE#*:} |
|---|
| 169 | |
|---|
| 170 | MATCH='^[0-9A-Za-z_]*$' |
|---|
| 171 | if (LC_ALL=C; [[ ! "$DEVNUM" =~ $MATCH ]]); then |
|---|
| 172 | echo $"error in $FILE: invalid alias number" >&2 |
|---|
| 173 | return 1 |
|---|
| 174 | fi |
|---|
| 175 | |
|---|
| 176 | eval " |
|---|
| 177 | ipseen=\$ipseen_${IPGLOP}; devseen=\$devseen_${DEVNUM}; |
|---|
| 178 | ipseen_${IPGLOP}=$FILE; devseen_${DEVNUM}=$FILE; |
|---|
| 179 | "; |
|---|
| 180 | |
|---|
| 181 | if [ -n "$ipseen" ]; then |
|---|
| 182 | echo $"error in $FILE: already seen ipaddr $IPADDR in $ipseen" >&2 |
|---|
| 183 | return 1 |
|---|
| 184 | fi |
|---|
| 185 | |
|---|
| 186 | if [ -n "$devseen" ]; then |
|---|
| 187 | echo $"error in $FILE: already seen device $parent_device:$DEVNUM in $devseen" >&2 |
|---|
| 188 | return 1 |
|---|
| 189 | fi |
|---|
| 190 | |
|---|
| 191 | if [ -z "$DEVICE" -o -z "$IPADDR" ]; then |
|---|
| 192 | echo $"error in $FILE: didn't specify device or ipaddr" >&2 |
|---|
| 193 | return 1 |
|---|
| 194 | fi |
|---|
| 195 | |
|---|
| 196 | if [ -z "$NETMASK" ]; then |
|---|
| 197 | eval `/bin/ipcalc --netmask ${IPADDR}` |
|---|
| 198 | fi |
|---|
| 199 | |
|---|
| 200 | if [ -z "$BROADCAST" -o "$BROADCAST" = "$default_BROADCAST" ]; then |
|---|
| 201 | eval `/bin/ipcalc --broadcast ${IPADDR} ${NETMASK}` |
|---|
| 202 | nma=$NETMASK; nmb=${nma#*.}; nmc=${nmb#*.}; |
|---|
| 203 | NMGLOP="${nma%%.*}_${nmb%%.*}_${nmc%%.*}_${nmc#*.}"; |
|---|
| 204 | if [ ${nma%%.*} -eq 0 ]; then ipnm_a=0; else ipnm_a=${ipa%%.*}; fi |
|---|
| 205 | if [ ${nmb%%.*} -eq 0 ]; then ipnm_b=0; else ipnm_b=${ipb%%.*}; fi |
|---|
| 206 | if [ ${nmc%%.*} -eq 0 ]; then ipnm_c=0; else ipnm_c=${ipc%%.*}; fi |
|---|
| 207 | if [ ${nmc#*.} -eq 0 ]; then ipnm_d=0; else ipnm_d=${ipc#*.}; fi |
|---|
| 208 | CACHENAME="${NMGLOP}_${ipnm_a}_${ipnm_b}_${ipnm_c}_${ipnm_d}" |
|---|
| 209 | eval " |
|---|
| 210 | if [ -z \"\$bcastcache_${CACHENAME}\" ]; then |
|---|
| 211 | eval `/bin/ipcalc --broadcast \$IPADDR \$NETMASK` |
|---|
| 212 | bcastcache_${CACHENAME}=\$BROADCAST |
|---|
| 213 | else |
|---|
| 214 | BROADCAST=\$bcastcache_${CACHENAME} |
|---|
| 215 | fi |
|---|
| 216 | "; |
|---|
| 217 | fi |
|---|
| 218 | |
|---|
| 219 | ##echo ""; |
|---|
| 220 | ##echo "----------------------------" |
|---|
| 221 | ##echo "device = $DEVICE" |
|---|
| 222 | ##echo "ipaddr = $IPADDR" |
|---|
| 223 | ##echo "netmask = $NETMASK" |
|---|
| 224 | ##echo "broadcast = $BROADCAST" |
|---|
| 225 | ##echo "devnum = $DEVNUM"; |
|---|
| 226 | ##echo ""; |
|---|
| 227 | |
|---|
| 228 | if [ "$no_devices_are_up" = "yes" ]; then |
|---|
| 229 | setup_this=yes |
|---|
| 230 | else |
|---|
| 231 | |
|---|
| 232 | setup_this="" |
|---|
| 233 | |
|---|
| 234 | eval " |
|---|
| 235 | rdev_addr=\$rdev_${DEVNUM}_addr; |
|---|
| 236 | rdev_mb=\$rdev_${DEVNUM}_mb; |
|---|
| 237 | rdev_mark=\$rdev_${DEVNUM}_mark; |
|---|
| 238 | rdevip=\$rdevip_${IPGLOP}; |
|---|
| 239 | "; |
|---|
| 240 | |
|---|
| 241 | if [ -n "$rdev_addr" ]; then |
|---|
| 242 | if [ "$rdev_addr" = "${IPADDR}" ]; then |
|---|
| 243 | newmark=keep |
|---|
| 244 | if [ "$rdev_mb" != "${NETMASK}_${BROADCAST}" ]; then |
|---|
| 245 | setup_this=freshen |
|---|
| 246 | else |
|---|
| 247 | setup_this=no |
|---|
| 248 | fi |
|---|
| 249 | else |
|---|
| 250 | if [ "$rdev_mark" != "remove" ]; then |
|---|
| 251 | ##echo "removing device $parent_device:${DEVNUM} (devnum conflict)" |
|---|
| 252 | /sbin/ifconfig $parent_device:${DEVNUM} down |
|---|
| 253 | do_netreport=yes |
|---|
| 254 | fi |
|---|
| 255 | newmark=remove |
|---|
| 256 | setup_this=yes |
|---|
| 257 | fi |
|---|
| 258 | if [ -n "$rdev_mark" -a "$rdev_mark" != "$newmark" ]; then |
|---|
| 259 | echo $"error in ifcfg-${parent_device}: files" >&2 |
|---|
| 260 | return 1 |
|---|
| 261 | fi |
|---|
| 262 | eval " rdev_${DEVNUM}_mark=\$newmark "; |
|---|
| 263 | else |
|---|
| 264 | setup_this=yes |
|---|
| 265 | fi |
|---|
| 266 | |
|---|
| 267 | if [ -n "$rdevip" -a "$rdevip" != "${DEVNUM}" ]; then |
|---|
| 268 | eval " mark_remove=\$rdev_${rdevip}_mark "; |
|---|
| 269 | if [ -n "$mark_remove" -a "$mark_remove" != "remove" ]; then |
|---|
| 270 | echo $"error in ifcfg-${parent_device}: files" >&2 |
|---|
| 271 | return 1 |
|---|
| 272 | fi |
|---|
| 273 | if [ "$mark_remove" != "remove" ]; then |
|---|
| 274 | eval " rdev_${rdevip}_mark=remove "; |
|---|
| 275 | ##echo "removing device $parent_device:$rdevip (ipaddr conflict)" |
|---|
| 276 | /sbin/ifconfig $parent_device:$rdevip down |
|---|
| 277 | do_netreport=yes |
|---|
| 278 | fi |
|---|
| 279 | fi |
|---|
| 280 | |
|---|
| 281 | fi |
|---|
| 282 | |
|---|
| 283 | if [ "$setup_this" = "freshen" ] ; then |
|---|
| 284 | # we can do the freshen stuff right now |
|---|
| 285 | ##echo "freshening device $DEVICE" |
|---|
| 286 | /sbin/ifconfig $DEVICE netmask $NETMASK broadcast $BROADCAST; |
|---|
| 287 | fi |
|---|
| 288 | |
|---|
| 289 | if [ "$setup_this" = "yes" ] ; then |
|---|
| 290 | |
|---|
| 291 | ##echo "setting up device $DEVICE" |
|---|
| 292 | |
|---|
| 293 | /sbin/ifconfig ${DEVICE} ${IPADDR} netmask ${NETMASK} broadcast ${BROADCAST} |
|---|
| 294 | |
|---|
| 295 | if [ "$NO_ALIASROUTING" != yes ]; then |
|---|
| 296 | |
|---|
| 297 | GATEWAYDEV=$network_GATEWAYDEV; |
|---|
| 298 | |
|---|
| 299 | if [ -n "${GATEWAY}" -a \ |
|---|
| 300 | \( -z "${GATEWAYDEV}" -o "${GATEWAYDEV}" = "${DEVICE}" \) ]; then |
|---|
| 301 | # set up default gateway, if it isn't already there |
|---|
| 302 | if ! is_default_gateway "$GATEWAY"; then |
|---|
| 303 | route add default gw ${GATEWAY} \ |
|---|
| 304 | ${METRIC:+metric $METRIC} ${DEVICE} |
|---|
| 305 | fi |
|---|
| 306 | fi |
|---|
| 307 | |
|---|
| 308 | /etc/sysconfig/network-scripts/ifup-routes ${DEVICE} ${NAME} |
|---|
| 309 | |
|---|
| 310 | do_netreport=yes |
|---|
| 311 | ifuplocal_queue="$ifuplocal_queue $DEVICE" |
|---|
| 312 | |
|---|
| 313 | fi |
|---|
| 314 | |
|---|
| 315 | fi |
|---|
| 316 | |
|---|
| 317 | } |
|---|
| 318 | |
|---|
| 319 | if [ "$BASH_VERSINFO" ]; then shopt -s nullglob; else allow_null_glob_expansion=foo; fi |
|---|
| 320 | |
|---|
| 321 | for FILE in ifcfg-${parent_device}:* ; do |
|---|
| 322 | is_ignored_file "$FILE" && continue |
|---|
| 323 | ini_env; |
|---|
| 324 | . $FILE; |
|---|
| 325 | [ -z "$DEVICE" ] && DEVICE=${FILE##ifcfg-} |
|---|
| 326 | [ "$ONPARENT" != "no" -a "$ONPARENT" != "NO" ] && new_interface; |
|---|
| 327 | unset DEVICE |
|---|
| 328 | done |
|---|
| 329 | |
|---|
| 330 | for FILE in ifcfg-${parent_device}-range* ; do |
|---|
| 331 | is_ignored_file "$FILE" && continue |
|---|
| 332 | ini_env; |
|---|
| 333 | . $FILE; |
|---|
| 334 | |
|---|
| 335 | ipaddr_prefix=${IPADDR_START%.*} |
|---|
| 336 | ipaddr_startnum=${IPADDR_START##*.} |
|---|
| 337 | ipaddr_endnum=${IPADDR_END##*.} |
|---|
| 338 | |
|---|
| 339 | if [ "${IPADDR_START%.*}" != "${IPADDR_END%.*}" ]; then |
|---|
| 340 | echo $"error in $FILE: IPADDR_START and IPADDR_END don't agree" >&2; continue |
|---|
| 341 | fi |
|---|
| 342 | |
|---|
| 343 | if [ $ipaddr_startnum -gt $ipaddr_endnum ]; then |
|---|
| 344 | echo $"error in $FILE: IPADDR_START greater than IPADDR_END" >&2; continue |
|---|
| 345 | fi |
|---|
| 346 | |
|---|
| 347 | ipaddr_num=$ipaddr_startnum |
|---|
| 348 | ipaddr_clonenum=$CLONENUM_START |
|---|
| 349 | |
|---|
| 350 | while [ $ipaddr_num -le $ipaddr_endnum ]; do |
|---|
| 351 | IPADDR="$ipaddr_prefix.$ipaddr_num" |
|---|
| 352 | DEVICE="$parent_device:$ipaddr_clonenum" |
|---|
| 353 | [ "$ONPARENT" != "no" -a "$ONPARENT" != "NO" ] && new_interface; |
|---|
| 354 | let 'ipaddr_num=ipaddr_num+1' |
|---|
| 355 | let 'ipaddr_clonenum=ipaddr_clonenum+1' |
|---|
| 356 | done |
|---|
| 357 | |
|---|
| 358 | done |
|---|
| 359 | |
|---|
| 360 | # |
|---|
| 361 | # Remove any devices that should not be around |
|---|
| 362 | # |
|---|
| 363 | for DEVNUM in $rdev_LIST ; do |
|---|
| 364 | eval " rdev_mark=\$rdev_${DEVNUM}_mark "; |
|---|
| 365 | if [ -z "$rdev_mark" ]; then |
|---|
| 366 | ##echo "removing device $parent_device:${DEVNUM} (lingering)" |
|---|
| 367 | /sbin/ifconfig $parent_device:${DEVNUM} down |
|---|
| 368 | do_netreport=yes |
|---|
| 369 | fi |
|---|
| 370 | done |
|---|
| 371 | # |
|---|
| 372 | # Notify of new device creation |
|---|
| 373 | # |
|---|
| 374 | |
|---|
| 375 | if [ -n "$do_netreport" ]; then |
|---|
| 376 | do_netreport |
|---|
| 377 | fi |
|---|
| 378 | |
|---|
| 379 | if [ -x /sbin/ifup-local ]; then |
|---|
| 380 | for DEVICE in $ifuplocal_queue ; do |
|---|
| 381 | /sbin/ifup-local ${DEVICE} |
|---|
| 382 | done |
|---|
| 383 | fi |
|---|