summaryrefslogtreecommitdiff
path: root/testing/hosts/alice/etc/init.d/net.eth0
blob: fa12002426ba38146edaa948eb23994482595973 (plain)
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
#!/sbin/runscript
# Copyright 1999-2004 Gentoo Technologies, Inc.
# Distributed under the terms of the GNU General Public License v2

#NB: Config is in /etc/conf.d/net

if [[ -n $NET_DEBUG ]]; then
	set -x
	devnull=/dev/stderr
else
	devnull=/dev/null
fi

# For pcmcia users. note that pcmcia must be added to the same
# runlevel as the net.* script that needs it.
depend() {
	use hotplug pcmcia
}

checkconfig() {
	if [[ -z "${ifconfig_IFACE}" ]]; then
		eerror "Please make sure that /etc/conf.d/net has \$ifconfig_$IFACE set"
		eerror "(or \$iface_$IFACE for old-style configuration)"
		return 1
	fi
	if [[ -n "${vlans_IFACE}" && ! -x /sbin/vconfig ]]; then
		eerror "For VLAN (802.1q) support, emerge net-misc/vconfig"
		return 1
	fi
}

# Fix bug 50039 (init.d/net.eth0 localization)
# Some other commands in this script might need to be wrapped, but
# we'll get them one-by-one.  Note that LC_ALL trumps LC_anything_else
# according to locale(7)
ifconfig() {
	LC_ALL=C /sbin/ifconfig "$@"
}

# setup_vars: setup variables based on $1 and content of /etc/conf.d/net
# The following variables are set, which should be declared local by
# the calling routine.
#	status_IFACE			(up or '')
#	vlans_IFACE				(space-separated list)
#	ifconfig_IFACE			(array of ifconfig lines, replaces iface_IFACE)
#	dhcpcd_IFACE			(command-line args for dhcpcd)
#	routes_IFACE			(array of route lines)
#	inet6_IFACE				(array of inet6 lines)
#	ifconfig_fallback_IFACE	(fallback ifconfig if dhcp fails)
setup_vars() {
	local i iface="${1//\./_}"

	status_IFACE="$(ifconfig ${1} 2>${devnull} | gawk '$1 == "UP" {print "up"}')"
	eval vlans_IFACE=\"\$\{iface_${iface}_vlans\}\"
	eval ifconfig_IFACE=( \"\$\{ifconfig_$iface\[@\]\}\" )
	eval dhcpcd_IFACE=\"\$\{dhcpcd_$iface\}\"
	eval routes_IFACE=( \"\$\{routes_$iface\[@\]\}\" )
	eval inet6_IFACE=( \"\$\{inet6_$iface\[@\]\}\" )
	eval ifconfig_fallback_IFACE=( \"\$\{ifconfig_fallback_$iface\[@\]\}\" )

	# BACKWARD COMPATIBILITY: populate the ifconfig_IFACE array
	# if iface_IFACE is set (fex. iface_eth0 instead of ifconfig_eth0)
	eval local iface_IFACE=\"\$\{iface_$iface\}\"
	if [[ -n ${iface_IFACE} && -z ${ifconfig_IFACE} ]]; then
		# Make sure these get evaluated as arrays
		local -a aliases broadcasts netmasks

		# Start with the primary interface
		ifconfig_IFACE=( "${iface_IFACE}" )

		# ..then add aliases
		eval aliases=( \$\{alias_$iface\} )
		eval broadcasts=( \$\{broadcast_$iface\} )
		eval netmasks=( \$\{netmask_$iface\} )
		for ((i = 0; i < ${#aliases[@]}; i = i + 1)); do
			ifconfig_IFACE[i+1]="${aliases[i]} ${broadcasts[i]:+broadcast ${broadcasts[i]}} ${netmasks[i]:+netmask ${netmasks[i]}}"
		done
	fi

	# BACKWARD COMPATIBILITY: check for space-separated inet6 addresses
	if [[ ${#inet6_IFACE[@]} == 1 && ${inet6_IFACE} == *' '* ]]; then
		inet6_IFACE=( ${inet6_IFACE} )
	fi
}

iface_start() {
	local IFACE=${1} i x retval
	checkconfig || return 1

	if [[ ${ifconfig_IFACE} != dhcp ]]; then
		# Show the address, but catch if this interface will be inet6 only
		i=${ifconfig_IFACE%% *}
		if [[ ${i} == *.*.*.* ]]; then
			ebegin "Bringing ${IFACE} up (${i})"
		else
			ebegin "Bringing ${IFACE} up"
		fi
		# ifconfig does not always return failure ..
		ifconfig ${IFACE} ${ifconfig_IFACE} >${devnull} && \
		ifconfig ${IFACE} up &>${devnull}
		eend $? || return $?
	else
		# Check that eth0 was not brought up by the kernel ...
		if [[ ${status_IFACE} == up ]]; then
			einfo "Keeping kernel configuration for ${IFACE}"
		else
			ebegin "Bringing ${IFACE} up via DHCP"
			/sbin/dhcpcd ${dhcpcd_IFACE} ${IFACE}
			retval=$?
			eend $retval
			if [[ $retval == 0 ]]; then
				# DHCP succeeded, show address retrieved
				i=$(ifconfig ${IFACE} | grep -m1 -o 'inet addr:[^ ]*' | 
					cut -d: -f2)
				[[ -n ${i} ]] && einfo "  ${IFACE} received address ${i}"
			elif [[ -n "${ifconfig_fallback_IFACE}" ]]; then
				# DHCP failed, try fallback.
				# Show the address, but catch if this interface will be inet6 only
				i=${ifconfig_fallback_IFACE%% *}
				if [[ ${i} == *.*.*.* ]]; then
					ebegin "Using fallback configuration (${i}) for ${IFACE}"
				else
					ebegin "Using fallback configuration for ${IFACE}"
				fi
				ifconfig ${IFACE} ${ifconfig_fallback_IFACE} >${devnull} && \
				ifconfig ${IFACE} up &>${devnull}
				eend $? || return $?
			else
				return $retval
			fi
		fi
	fi

	if [[ ${#ifconfig_IFACE[@]} -gt 1 ]]; then
		einfo "  Adding aliases"
		for ((i = 1; i < ${#ifconfig_IFACE[@]}; i = i + 1)); do
			ebegin "    ${IFACE}:${i} (${ifconfig_IFACE[i]%% *})"
			ifconfig ${IFACE}:${i} ${ifconfig_IFACE[i]}
			eend $?
		done
	fi

	if [[ -n ${inet6_IFACE} ]]; then
		einfo "  Adding inet6 addresses"
		for ((i = 0; i < ${#inet6_IFACE[@]}; i = i + 1)); do
			ebegin "    ${IFACE} inet6 add ${inet6_IFACE[i]}"
			ifconfig ${IFACE} inet6 add ${inet6_IFACE[i]} >${devnull}
			eend $?
		done
	fi

	# Set static routes
	if [[ -n ${routes_IFACE} ]]; then
		einfo "  Adding routes"
		for ((i = 0; i < ${#routes_IFACE[@]}; i = i + 1)); do
			ebegin "    ${routes_IFACE[i]}"
			/sbin/route add ${routes_IFACE[i]}
			eend $?
		done
	fi

	# Set default route if applicable to this interface
	if [[ ${gateway} == ${IFACE}/* ]]; then
		local ogw=$(/bin/netstat -rn | awk '$1 == "0.0.0.0" {print $2}')
		local gw=${gateway#*/}
		if [[ ${ogw} != ${gw} ]]; then
			ebegin "  Setting default gateway ($gw)"

			# First delete any existing route if it was setup by kernel...
			/sbin/route del default dev ${IFACE} &>${devnull}

			# Second delete old gateway if it was set...
			/sbin/route del default gw ${ogw} &>${devnull}

			# Third add our new default gateway
			/sbin/route add default gw ${gw} >${devnull}
			eend $? || {
				true # need to have some command in here
				# Note: This originally called stop, which is obviously
				# wrong since it's calling with a local version of IFACE.
				# The below code works correctly to abort configuration of
				# the interface, but is commented because we're assuming
				# that default route failure should not cause the interface
				# to be unconfigured.
				#local error=$?
				#ewarn "Aborting configuration of ${IFACE}"
				#iface_stop ${IFACE}
				#return ${error}
			}
		fi
	fi

	# Enabling rp_filter causes wacky packets to be auto-dropped by
	# the kernel.  Note that we only do this if it is not set via
	# /etc/sysctl.conf ...
	if [[ -e /proc/sys/net/ipv4/conf/${IFACE}/rp_filter && \
			-z "$(grep -s '^[^#]*rp_filter' /etc/sysctl.conf)" ]]; then
		echo -n 1 > /proc/sys/net/ipv4/conf/${IFACE}/rp_filter
	fi
}

# iface_stop: bring down an interface.  Don't trust information in
# /etc/conf.d/net since the configuration might have changed since
# iface_start ran.  Instead query for current configuration and bring
# down the interface.
iface_stop() {
	local IFACE=${1} i x aliases inet6 count

	# Try to do a simple down (no aliases, no inet6, no dhcp)
	aliases="$(ifconfig | grep -o "^$IFACE:[0-9]*" | tac)"
	inet6="$(ifconfig ${IFACE} | awk '$1 == "inet6" {print $2}')"
	if [[ -z ${aliases} && -z ${inet6} && ! -e /var/run/dhcpcd-${IFACE}.pid ]]; then
		ebegin "Bringing ${IFACE} down"
		ifconfig ${IFACE} down &>/dev/null
		eend 0
		return 0
	fi

	einfo "Bringing ${IFACE} down"

	# Stop aliases before primary interface.
	# Note this must be done in reverse order, since ifconfig eth0:1 
	# will remove eth0:2, etc.  It might be sufficient to simply remove 
	# the base interface but we're being safe here.
	for i in ${aliases} ${IFACE}; do

		# Delete all the inet6 addresses for this interface
		inet6="$(ifconfig ${i} | awk '$1 == "inet6" {print $3}')"
		if [[ -n ${inet6} ]]; then
			einfo "  Removing inet6 addresses"
			for x in ${inet6}; do 
				ebegin "    ${IFACE} inet6 del ${x}"
				ifconfig ${i} inet6 del ${x}
				eend $?
			done
		fi

		# Stop DHCP (should be N/A for aliases)
		# Don't trust current configuration... investigate ourselves
		if /sbin/dhcpcd -z ${i} &>${devnull}; then
			ebegin "  Releasing DHCP lease for ${IFACE}"
			for ((count = 0; count < 9; count = count + 1)); do
				/sbin/dhcpcd -z ${i} &>${devnull} || break
				sleep 1
			done
			[[ ${count} -lt 9 ]]
			eend $? "Timed out"
		fi
		ebegin "  Stopping ${i}"
		ifconfig ${i} down &>${devnull}
		eend 0
	done

	return 0
}

start() {
	# These variables are set by setup_vars
	local status_IFACE vlans_IFACE dhcpcd_IFACE 
	local -a ifconfig_IFACE routes_IFACE inet6_IFACE

	# Call user-defined preup function if it exists
	if [[ $(type -t preup) == function ]]; then
		einfo "Running preup function"
		preup ${IFACE} || {
			eerror "preup ${IFACE} failed"
			return 1
		}
	fi

	# Start the primary interface and aliases
	setup_vars ${IFACE}
	iface_start ${IFACE} || return 1

	# Start vlans
	local vlan
	for vlan in ${vlans_IFACE}; do
		/sbin/vconfig add ${IFACE} ${vlan} >${devnull}
		setup_vars ${IFACE}.${vlan}
		iface_start ${IFACE}.${vlan}
	done

	# Call user-defined postup function if it exists
	if [[ $(type -t postup) == function ]]; then
		einfo "Running postup function"
		postup ${IFACE}
	fi
}

stop() {
	# Call user-defined predown function if it exists
	if [[ $(type -t predown) == function ]]; then
		einfo "Running predown function"
		predown ${IFACE}
	fi

	# Don't depend on setup_vars since configuration might have changed.
	# Investigate current configuration instead.
	local vlan
	for vlan in $(ifconfig | grep -o "^${IFACE}\.[^ ]*"); do
		iface_stop ${vlan}
		/sbin/vconfig rem ${vlan} >${devnull}
	done

	iface_stop ${IFACE} || return 1  # always succeeds, btw

	# Call user-defined postdown function if it exists
	if [[ $(type -t postdown) == function ]]; then
		einfo "Running postdown function"
		postdown ${IFACE}
	fi
}

# vim:ts=4