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 |
---|