1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
|
#!/bin/bash
# Copyright (c) 2004-2005 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
# Contributed by Roy Marples (uberlord@gentoo.org)
# Fix any potential localisation problems
# Note that LC_ALL trumps LC_anything_else according to locale(7)
ifconfig() {
LC_ALL=C /sbin/ifconfig "$@"
}
ifconfig_tunnel() {
LC_ALL=C /sbin/iptunnel "$@"
}
route() {
LC_ALL=C /sbin/route "$@"
}
# void ifconfig_depend(void)
#
# Sets up the dependancies for the module
ifconfig_depend() {
provide interface
variables config routes fallback metric ifconfig \
ifconfig_fallback routes inet6 iface alias broadcast netmask
}
# bool ifconfig_check_installed(void)
#
# Returns 1 if ifconfig is installed, otherwise 0
ifconfig_check_installed() {
[[ -x /sbin/ifconfig ]] && return 0
${1:-false} && eerror "For ifconfig support, emerge sys-apps/net-tools"
return 1
}
# bool ifconfig_exists(char *interface, bool report)
#
# Returns 1 if the interface exists, otherwise 0
ifconfig_exists() {
local e=$( ifconfig -a | grep -o "^$1" ) report="${2:-false}"
[[ -n ${e} ]] && return 0
if ${report} ; then
eerror "network interface $1 does not exist"
eerror "Please verify hardware or kernel module (driver)"
fi
return 1
}
# void ifconfig_up(char *iface)
#
# provides a generic interface for bringing interfaces up
ifconfig_up() {
ifconfig "$1" up
}
# void ifconfig_down(char *iface)
#
# provides a generic interface for bringing interfaces down
ifconfig_down() {
ifconfig "$1" down
}
# bool ifconfig_is_up(char *iface, bool withaddress)
#
# Returns 0 if the interface is up, otherwise 1
# If withaddress is true then the interface has to have an IPv4 address
# assigned as well
ifconfig_is_up() {
local check="\<UP\>" addr="${2:-false}"
${addr} && check="\<inet addr:.*${check}"
ifconfig "$1" | grep -Eq "${check}" && return 0
return 1
}
# void ifconfig_set_flag(char *iface, char *flag, bool enabled)
#
# Sets or disables the interface flag
ifconfig_set_flag() {
local iface="$1" flag="$2" enable="$3"
${enable} || flag="-${flag}"
ifconfig "${iface}" "${flag}"
}
# void ifconfig_get_address(char *interface)
#
# Fetch the address retrieved by DHCP. If successful, echoes the
# address on stdout, otherwise echoes nothing.
ifconfig_get_address() {
local -a x=( $( ifconfig "$1" \
| sed -n -e 's/.*inet addr:\([^ ]*\).*Mask:\([^ ]*\).*/\1 \2/p' ) )
x[1]=$( netmask2cidr "${x[1]}" )
[[ -n ${x[0]} ]] && echo "${x[0]}/${x[1]}"
}
# void ifconfig_get_mac_address(char *interface)
#
# Fetch the mac address assingned to the network card
ifconfig_get_mac_address() {
local mac=$( ifconfig "$1" | sed -n -e \
's/.*HWaddr[ \t]*\<\(..:..:..:..:..:..\)\>.*/\U\1/p' )
[[ ${mac} != '00:00:00:00:00:00' \
&& ${mac} != '44:44:44:44:44:44' \
&& ${mac} != 'FF:FF:FF:FF:FF:FF' ]] \
&& echo "${mac}"
}
# void ifconfig_set_mac_address(char *interface, char *mac)
#
# Assigned the mac address to the network card
ifconfig_set_mac_address() {
ifconfig "$1" hw ether "$2"
}
# int ifconfig_set_name(char *interface, char *new_name)
#
# Renames the interface
# This will not work if the interface is setup!
ifconfig_set_name() {
[[ -z $2 ]] && return 1
local current="$1" new="$2"
local mac=$( ifconfig_get_mac_address "${current}" )
if [[ -z ${mac} ]]; then
eerror "${iface} does not have a MAC address"
return 1
fi
/sbin/nameif "${new}" "${mac}"
}
# void ifconfig_get_aliases_rev(char *interface)
#
# Fetch the list of aliases for an interface.
# Outputs a space-separated list on stdout, in reverse order, for
# example "eth0:2 eth0:1"
ifconfig_get_aliases_rev() {
ifconfig | grep -o "^$1:[0-9]* " | tac
}
# bool ifconfig_del_addresses(char *interface, bool onlyinet)
#
# Remove addresses from interface. Returns 0 (true) if there
# were addresses to remove (whether successful or not). Returns 1
# (false) if there were no addresses to remove.
# If onlyinet is true then we only delete IPv4 / inet addresses
ifconfig_del_addresses() {
local iface="$1" i onlyinet="${2:-false}"
# We don't remove addresses from aliases
[[ ${iface} == *:* ]] && return 0
# If the interface doesn't exist, don't try and delete
ifconfig_exists "${iface}" || return 0
# iproute2 can add many addresses to an iface unlike ifconfig ...
# iproute2 added addresses cause problems for ifconfig
# as we delete an address, a new one appears, so we have to
# keep polling
while ifconfig "${iface}" | grep -q -m1 -o 'inet addr:[^ ]*' ; do
ifconfig "${iface}" 0.0.0.0 || break
done
# Remove IPv6 addresses
if ! ${onlyinet} ; then
for i in $( ifconfig "${iface}" \
| sed -n -e 's/^.*inet6 addr: \([^ ]*\) Scope:[^L].*/\1/p' ) ; do
/sbin/ifconfig "${iface}" inet6 del "${i}"
done
fi
return 0
}
# bool ifconfig_get_old_config(char *iface)
#
# Returns config and config_fallback for the given interface
ifconfig_get_old_config() {
local iface="$1" ifvar=$( bash_variable "$1" ) i inet6
config="ifconfig_${ifvar}[@]"
config=( "${!config}" )
config_fallback="ifconfig_fallback_${ifvar}[@]"
config_fallback=( "${!config_fallback}" )
inet6="inet6_${ifvar}[@]"
inet6=( "${!inet6}" )
# BACKWARD COMPATIBILITY: populate the config_IFACE array
# if iface_IFACE is set (fex. iface_eth0 instead of ifconfig_eth0)
i="iface_${ifvar}"
if [[ -n ${!i} && -z ${config} ]]; then
# Make sure these get evaluated as arrays
local -a aliases broadcasts netmasks
# Start with the primary interface
config=( ${!i} )
# ..then add aliases
aliases="alias_${ifvars}"
aliases=( ${!aliases} )
broadcasts="broadcast_${ifvar}"
broadcasts=( ${!broadcasts} )
netmasks="netmask_${ifvar}"
netmasks=( ${!netmasks} )
for (( i=0; i<${#aliases[@]}; i++ )); do
config[i+1]="${aliases[i]} ${broadcasts[i]:+broadcast ${broadcasts[i]}} ${netmasks[i]:+netmask ${netmasks[i]}}"
done
fi
# BACKWARD COMPATIBILITY: check for space-separated inet6 addresses
[[ ${#inet6[@]} == 1 && ${inet6} == *' '* ]] && inet6=( ${inet6} )
# Add inet6 addresses to our config if required
[[ -n ${inet6} ]] && config=( "${config[@]}" "${inet6[@]}" )
return 0
}
# bool ifconfig_iface_stop(char *interface)
#
# Do final shutdown for an interface or alias.
#
# Returns 0 (true) when successful, non-zero (false) on failure
ifconfig_iface_stop() {
# If an alias is already down, then "ifconfig eth0:1 down"
# will try to bring it up with an address of "down" which
# fails. Do some double-checking before returning error
# status
ifconfig_is_up "$1" || return 0
ifconfig_down "$1" && return 0
# It is sometimes impossible to transition an alias from the
# UP state... particularly if the alias has no address. So
# ignore the failure, which should be okay since the entire
# interface will be shut down eventually.
[[ $1 == *:* ]] && return 0
return 1
}
# bool ifconfig_pre_start(char *interface)
#
# Runs any pre_start stuff on our interface - just the MTU atm
# We set MTU twice as it may be needed for DHCP - a dhcp client could
# change it in error, so we set MTU in post start too
ifconfig_pre_start() {
local iface="$1"
interface_exists "${iface}" || return 0
local ifvar=$( bash_variable "$1" ) mtu
# MTU support
mtu="mtu_${ifvar}"
[[ -n ${!mtu} ]] && ifconfig "${iface}" mtu "${!mtu}"
return 0
}
# bool ifconfig_post_start(char *iface)
#
# Bring up iface using ifconfig utilities, called from iface_start
#
# Returns 0 (true) when successful on the primary interface, non-zero
# (false) when the primary interface fails. Aliases are allowed to
# fail, the routine should still return success to indicate that
# net.eth0 was successful
ifconfig_post_start() {
local iface="$1" ifvar=$( bash_variable "$1" ) routes x metric mtu cidr
metric="metric_${ifvar}"
ifconfig_exists "${iface}" || return 0
# Make sure interface is marked UP
ifconfig_up "${iface}"
# MTU support
mtu="mtu_${ifvar}"
[[ -n ${!mtu} ]] && ifconfig "${iface}" mtu "${!mtu}"
routes="routes_${ifvar}[@]"
routes=( "${!routes}" )
# BACKWARD COMPATIBILITY: set the default gateway
if [[ ${gateway} == "${iface}/"* ]]; then
# We don't add the old gateway if one has been set in routes_IFACE
local gw=true
for x in "${routes[@]}"; do
[[ ${x} != *"default gw"* ]] && continue
gw=false
break
done
${gw} && routes=( "${routes[@]}" "default gw ${gateway#*/}" )
fi
[[ -z ${routes} ]] && return 0
# Add routes for this interface, might even include default gw
einfo "Adding routes"
eindent
for x in "${routes[@]}"; do
ebegin "${x}"
# Support iproute2 style routes
x="${x//via/gw} "
x="${x//scope * / }"
# Assume we're a net device unless told otherwise
[[ " ${x} " != *" -net "* && " ${x} " != *" -host "* ]] && x="-net ${x}"
# Support adding IPv6 addresses easily
if [[ ${x} == *:* ]]; then
[[ ${x} != *"-A inet6"* ]] && x="-A inet6 ${x}"
x="${x// -net / }"
fi
# Add a metric if we don't have one
[[ ${x} != *" metric "* ]] && x="${x} metric ${!metric}"
route add ${x} dev "${iface}"
eend $?
done
eoutdent
return 0
}
# bool ifconfig_add_address(char *iface, char *options ...)
#
# Adds the given address to the interface
ifconfig_add_address() {
local iface="$1" i=0 r e real_iface=$(interface_device "$1")
ifconfig_exists "${real_iface}" true || return 1
# Extract the config
local -a config=( "$@" )
config=( ${config[@]:1} )
if [[ ${config[0]} == *:* ]]; then
# Support IPv6 - nice and simple
config[0]="inet6 add ${config[0]}"
else
# IPv4 is tricky - ifconfig requires an aliased device
# for multiple addresses
if ifconfig "${iface}" | grep -Eq "\<inet addr:.*" ; then
# Get the last alias made for the interface and add 1 to it
i=$( ifconfig | tac | grep -m 1 -o "^${iface}:[0-9]*" \
| sed -n -e 's/'"${iface}"'://p' )
i="${i:-0}"
(( i++ ))
iface="${iface}:${i}"
fi
# ifconfig doesn't like CIDR addresses
local ip="${config[0]%%/*}" cidr="${config[0]##*/}" netmask
if [[ -n ${cidr} && ${cidr} != "${ip}" ]]; then
netmask=$( cidr2netmask "${cidr}" )
config[0]="${ip} netmask ${netmask}"
fi
# Support iproute2 style config where possible
r="${config[@]}"
config=( ${r//brd +/} )
config=( "${config[@]//brd/broadcast}" )
config=( "${config[@]//peer/pointopoint}" )
fi
# Ensure that the interface is up so we can add IPv6 addresses
interface_up "${real_iface}"
# Some kernels like to apply lo with an address when they are brought up
if [[ ${iface} == "lo" && ${config[@]} == "127.0.0.1 netmask 255.0.0.0 broadcast 127.255.255.255" ]]; then
ifconfig "${iface}" 0.0.0.0
fi
ifconfig "${iface}" ${config[@]}
r="$?"
[[ ${r} != "0" ]] && return ${r}
local metric ifvar=$(bash_variable "${real_iface}")
# Remove the newly added route and replace with our metric
metric="metric_${ifvar}"
[[ ${!metric} == "0" || ${RC_AUTO_INTERFACE} != "yes" ]] && return ${r}
if [[ -z ${netmask} ]]; then
for (( i=1; i<${#config[@]}-1; i++ )); do
if [[ ${config[i]} == "netmask" ]]; then
netmask="${config[i+1]}"
cidr=$( netmask2cidr "${netmask}" )
break
fi
done
[[ -z ${netmask} ]] && return ${r}
fi
local network=$( ip_network "${ip}" "${netmask}" )
if route del -net "${network}/${cidr}" metric 0 dev "${iface}" \
2>/dev/null ; then
route add -net "${network}/${cidr}" metric "${!metric}" dev "${iface}"
fi
return ${r}
}
# void ifconfig_route_metric(char* interface, int metric)
#
# Change all routes for an interface to a given metric
ifconfig_route_metric() {
local dest gateway mask flags metric ref use
route -n | grep " $1$" | {
while read dest gateway mask flags metric ref use ; do
if [[ ${gateway} != "0.0.0.0" ]]; then
gateway="gw ${gateway}"
else
unset gateway
fi
route del ${dest}
route add -net ${dest} netmask ${mask} ${gateway} metric "$2" dev "$1"
done
}
}
# void ifconfig_default_route(char* interface, char* gateway_ip, int metric)
#
# Force default route to the specified gateway
ifconfig_default_route() {
local metric="${3:-0}"
# Delete any existing default routes
while true ; do
route del default metric "${metric}" dev "$1" 2>/dev/null || break
done
# Then we add our route
route add default gw "$2" metric "${metric}" dev "$1"
}
# vim:ts=4
|