setup-interfaces.in 8.61 KB
Newer Older
Natanael Copa's avatar
Natanael Copa committed
1 2 3 4 5
#!/bin/sh

PROGRAM=setup-interfaces
PREFIX=

Natanael Copa's avatar
Natanael Copa committed
6 7 8
for i in ./libalpine.sh $PREFIX/lib/libalpine.sh; do
	[ -e $i ] && . $i && break
done
Natanael Copa's avatar
Natanael Copa committed
9

10 11 12 13
unconfigured_add() {
	touch $1.noconf
}

Natanael Copa's avatar
Natanael Copa committed
14 15 16 17
unconfigured_detect() {
	local i=
	for i in ${INTERFACES:-$(available_ifaces)}; do
		if [ "$i" != "lo" ]; then
18
			unconfigured_add $i
Natanael Copa's avatar
Natanael Copa committed
19 20
		fi
	done
Natanael Copa's avatar
Natanael Copa committed
21 22
}

Natanael Copa's avatar
Natanael Copa committed
23
unconfigured_get_first() {
Natanael Copa's avatar
Natanael Copa committed
24 25 26
	ls *.noconf 2>/dev/null | head -n 1 | sed 's/.noconf//'
}

Natanael Copa's avatar
Natanael Copa committed
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
unconfigured_del() {
	rm $1.noconf
}

unconfigured_all_done() {
	local i=
	for i in *.noconf; do
		[ -e $i ] && return 1
	done
	return 0
}

unconfigured_list() {
	local list= i=
	for i in *.noconf; do
		[ -e "$i" ] || continue
		list="${list} ${i%.noconf}"
	done
	echo $list
}

unconfigured_isin() {
	[ -f $1.noconf ]
}

52 53 54 55
iface_exists() {
	test -e /sys/class/net/$1
}

Natanael Copa's avatar
Natanael Copa committed
56 57 58 59
get_default_addr() {
	# check if dhcpcd is running
	if pidof dhcpcd > /dev/null && [ -f "$ROOT/var/lib/dhcpc/dhcpcd-$1.info" ]; then
		echo dhcp
60
	elif iface_exists; then
Natanael Copa's avatar
Natanael Copa committed
61
		ip addr show $1 | awk '/inet / {print $2}' | head -n 1 | sed 's:/.*::'
62
	fi
Natanael Copa's avatar
Natanael Copa committed
63 64 65 66 67 68 69 70 71 72 73 74 75 76
}

get_default_mask() {
	if [ "$1" ] ; then
		ipcalc -m $1 | sed 's/.*=//'
	else
		echo "255.255.255.0"
	fi
}

get_default_gateway() {
	ip route show dev $1 | awk '/^default/ {print $3}'
}

77 78 79 80 81 82 83 84 85 86 87 88 89
ipaddr_help() {
	cat <<__EOF__

For static ip:
Enter the ip address in the format x.x.x.x

For dhcp:
Enter 'dhcp'

To add this interface to a bridge enter the bridge name (eg 'br0' or 'bridge0')

__EOF__
}
Natanael Copa's avatar
Natanael Copa committed
90

91
bridge_add_port() {
92 93 94 95 96 97 98 99 100
	local bridge=$1 iface=
	shift
	for iface; do
		echo $iface >> $bridge.bridge_ports
		unconfigured_add $bridge
		unconfigured_del $iface
	done
}

101 102 103 104 105 106
bridge_list_ports() {
	if [ -r $1.bridge_ports ]; then
		echo $(cat $1.bridge_ports)
	fi
}

Natanael Copa's avatar
Natanael Copa committed
107 108
config_iface() {
	local iface=$1
109
	local prefix=$2
110
	local address= netmask= gateway= bridge_ports=
111
	local bridge
112
	local conf=$prefix$iface.conf
113
	local answer=
114

115
	while [ -n "$ask_bridge" ]; do
116
		ask "Do you want to bridge the interface $iface?" no
117 118
		case "$resp" in
			yes|y) resp=yes; break;;
119 120 121
			no|n) break;;
		esac
	done
122

123
	if [ "$resp" = "yes" ]; then
124
		bridge="br"`echo $iface | sed 's/[^0-9]//g'`
125
		ask "Name of the bridge you want add $iface to:" $bridge
126
		bridge_add_port $resp $iface
127
		return
128
	fi
129

130
	if [ -r "$iface.bridge_ports" ]; then
131
		bridge_ports=$(echo $(cat $iface.bridge_ports))
132 133
		echo "bridge_ports=\"$bridge_ports\"" >> $conf
	fi
134 135 136 137
	if [ -r "$iface.bond_slaves" ]; then
		bond_slaves=$(echo $(cat $iface.bond_slaves))
		echo "bond_slaves=\"$bond_slaves\"" >> $conf
	fi
138 139 140 141
	# use ipcalc to validate the address. we do accept /mask
	# we are no interested in the result, only error code, so
	# we send result to /dev/null
	while ! ipcalc -s -m $address >/dev/null 2>&1; do
Natanael Copa's avatar
Natanael Copa committed
142
		address=`get_default_addr $iface`
143
		[ -z "$address" ] && address="dhcp"
144
		ask "Ip address for $iface? (or 'dhcp', 'none', '?')" $address
145
		address=$resp
146 147 148 149
		case "$resp" in
		'?')	ipaddr_help;;
		"abort") return;;
		"dhcp")
150
			echo "type=dhcp" >> $conf
Natanael Copa's avatar
Natanael Copa committed
151
			unconfigured_del $iface
152
			return ;;
153 154 155 156
		"none")
			echo "type=manual" >> $conf
			unconfigured_del $iface
			return;;
157 158 159 160 161
		br[0-9]*|bridge[0-9]*)
			case "$iface" in
				# we dont allow bridge bridges
				br[0-9]*|bridge[0-9]*) continue;;
			esac
162
			bridge_add_port $resp $iface
163 164
			return ;;
		esac
Natanael Copa's avatar
Natanael Copa committed
165 166
	done

167 168 169 170 171 172 173 174
	# extract netmask if entered together with address
	if [ "$address" != "${address%%/*}" ]; then
		netmask=$(ipcalc -s -m $address | cut -d= -f2)
	fi

	# use ipcalc -m to validate netmask. we dont accept <addr>/mask suffix
	# so we pass on a dummy mask to ipcalc.
	while ! ipcalc -s -m $netmask/0 >/dev/null 2>&1; do
Natanael Copa's avatar
Natanael Copa committed
175
		netmask=`get_default_mask $address`
176 177
		ask "Netmask?" $netmask
		netmask=$resp
Natanael Copa's avatar
Natanael Copa committed
178 179 180
		[ "$netmask" = "abort" ] && return
	done

181 182 183
	# use ipcalc -m to validate netmask. we dont accept <addr>/mask suffix
	# so we pass on a dummy mask to ipcalc.
	while ! ipcalc -s -m $gateway/0 >/dev/null 2>&1; do
Natanael Copa's avatar
Natanael Copa committed
184 185
		gateway=`get_default_gateway $iface`
		[ -z "$gateway" ] && gateway=none
186 187
		ask "Gateway? (or 'none')" $gateway
		gateway=$resp
Natanael Copa's avatar
Natanael Copa committed
188 189 190 191 192
		[ "$gateway" = "abort" ] && return
		[ "$gateway" = "none" ] && gateway=""
		[ -z "$gateway" ] && break
	done
	
193
	echo "type=static" >> $conf
194 195 196
	if [ -n "$bridge_ports" ]; then
		echo "bridge_ports=$bridge_ports" >> $conf
	fi
197 198 199
	echo "address=${address%%/*}" >> $conf  #strip off /mask if there
	echo "netmask=$netmask" >> $conf
	echo "gateway=$gateway" >> $conf
200

201

202 203
	# print summary
	echo "Configuration for $iface:"
204
	sed 's/^/  /' $conf
Natanael Copa's avatar
Natanael Copa committed
205
	
Natanael Copa's avatar
Natanael Copa committed
206
	unconfigured_del $iface
Natanael Copa's avatar
Natanael Copa committed
207 208
}

209
is_bridge() {
210 211 212 213 214
	[ -e /sys/class/net/$1/bridge ] || [ -e $1.bridge_ports ]
}

is_bond_master() {
	[ -e $1.bond_slaves ]
215 216
}

217
unconfigured_available() {
218 219
	local local i= iflist=
	for i in $(unconfigured_list); do
220
		if ! is_bridge $i && ! is_bond_master $i; then
221 222 223 224 225 226 227 228 229 230 231 232 233 234 235
			iflist="${iflist}${iflist:+ }$i"
		fi
	done
	echo $iflist
}

unconfigured_all_are() {
	local i=
	for i; do
		unconfigured_isin $i || return 1
	done
	return 0
}

config_bridge() {
236
	local bridge=$1 iflist= i= ports=
237
	while ! unconfigured_all_done; do
238
		set -- $(unconfigured_available)
239
		[ $# -eq 0 ] && return 0;
240 241 242 243
		ports=$(bridge_list_ports $bridge)
		if [ -n "$ports" ]; then
			echo "Bridge ports in $bridge are: $ports"
		fi
244 245
		echo "Available bridge ports are: $@"
		ask "Which port(s) do you want add to bridge $bridge? (or 'done')" $1
246 247 248 249
		case $resp in
			'abort') return 1;;
			'done') return 0;;
		esac
250 251 252 253 254 255 256
		for i in $resp; do
			if unconfigured_isin $i; then
				bridge_add_port $bridge $i
			else
				echo "$i is not valid"
			fi
		done
257 258 259
	done
}

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
bond_add_slave() {
	local master=$1 slave=
	shift
	for slave; do
		echo $slave >> $master.bond_slaves
		unconfigured_add $master
		unconfigured_del $slave
	done
}

bond_list_slaves() {
	if [ -r $1.bond_slaves ]; then
		echo $(cat $1.bond_slaves)
	fi
}

config_bond() {
	local master=$1 slaves=
	while ! unconfigured_all_done; do
		set -- $(unconfigured_available)
		[ $# -eq 0 ] && return 0;
		slaves=$(bond_list_slaves $master)
		if [ -n "$slaves" ]; then
			echo "Bond slaves in $master are: $slaves"
		fi
		echo "Available bond slaves are: $@"
		ask "Which slave(s) do you want add to $master? (or 'done')" $1
		case $resp in
			'abort') return 1;;
			'done') return 0;;
		esac
		for i in $resp; do
			if unconfigured_isin $i; then
				bond_add_slave $master $i
			else
				echo "$i is not valid"
			fi
		done
	done
}

301 302
usage() {
        cat <<__EOF__
303
usage: setup-interfaces [-bhi] [-p ROOT]
Natanael Copa's avatar
Natanael Copa committed
304

305
Setup network interfaces
Natanael Copa's avatar
Natanael Copa committed
306

307
options:
308
 -b  Ask for bridging of interfaces
309 310
 -h  Show this help
 -i  Read new contents of /etc/network/interfaces from stdin
311
 -p  Use ROOT as system prefix
312 313 314
__EOF__
        exit 1
}
Natanael Copa's avatar
Natanael Copa committed
315

Natanael Copa's avatar
Natanael Copa committed
316
prompt_for_interfaces() {
317 318 319
	init_tmpdir TMP
	
	cd $TMP
Natanael Copa's avatar
Natanael Copa committed
320
	unconfigured_detect
321 322
	
	index=1
Natanael Copa's avatar
Natanael Copa committed
323 324
	while ! unconfigured_all_done; do
		echo "Available interfaces are: $(unconfigured_list)."
325 326 327
		ask "Which one do you want to initialize? (or 'done')" \
			$(unconfigured_get_first)
		iface=$resp
328
	
329 330 331 332
		case "$iface" in
			"done") break;;
			br[0-9]*|bridge[0-9]*|virbr[0-9]*)
				config_bridge $iface || continue;;
333 334
			bond[0-9]*)
				config_bond $iface || continue;;
335 336
			*) unconfigured_isin $iface || continue;;
		esac
337 338 339 340 341 342
		config_iface $iface $(printf "%.3d~" $index)
		index=$(( $index + 1 ))
	done
	
	echo "type=loopback" > 000~lo.conf
	echo "" > interface
Natanael Copa's avatar
Natanael Copa committed
343
	hostname=$(cat $ROOT/etc/hostname 2>/dev/null)
344 345 346 347
	
	for i in *.conf ; do
		iface=`basename $i .conf`
		iface=${iface#[0-9]*~}
348
		bridge_ports=
349
		bond_slaves=
350 351 352
		address=
		type=
		gateway=
353
		. ./$i
354 355
		echo "auto $iface" >> interfaces
		echo "iface $iface inet $type" >> interfaces
356 357 358
		if [ -n "$bridge_ports" ]; then
			echo -e "\tbridge-ports $bridge_ports" >> interfaces
		fi
359 360 361
		if [ -n "$bond_slaves" ]; then
			echo -e "\tbond-slaves $bond_slaves" >> interfaces
		fi
362
		case $type in
363 364 365 366
		manual)
			echo -e "\tup ip link set \$IFACE up" >> interfaces
			echo -e "\tdown ip link set \$IFACE down" >> interfaces
			;;
367 368 369 370 371 372 373 374 375 376 377
		dhcp)
			[ -n "$hostname" ] \
				&& echo -e "\thostname $hostname" >> interfaces
			;;
		static)
			echo -e "\taddress $address" >> interfaces
			echo -e "\tnetmask $netmask" >> interfaces
			[ "$gateway" ] \
				&& echo -e "\tgateway $gateway" >> interfaces
			;;
		esac
378
		echo "" >> interfaces
379 380 381
	done
	
	while [ "$answer" != "yes" ] && [ "$answer" != "no" ] ; do
382
		ask "Do you want to do any manual network configuration?" no
383 384 385 386 387
		case $resp in
			y) answer=yes;;
			n) answer=no;;
			*) answer=$resp;;
		esac
388
	done
Natanael Copa's avatar
Natanael Copa committed
389

390
	if yesno "$answer"; then
391
		case "$EDITOR" in
392 393
			nano)	apk add nano;;
			vim)	apk add vim;;
394 395 396 397 398 399
		esac
		${EDITOR:-vi} interfaces
	fi
		
	mkdir -p $ROOT/etc/network
	cp interfaces $ROOT/etc/network/
Natanael Copa's avatar
Natanael Copa committed
400 401
}

402 403 404
ask_bridge=
is_xen_dom0 && ask_bridge=1

Natanael Copa's avatar
Natanael Copa committed
405
while getopts "bhip:" opt; do
Natanael Copa's avatar
Natanael Copa committed
406
        case $opt in
407
		b) ask_bridge=1;;
Natanael Copa's avatar
Natanael Copa committed
408 409
                h) usage;;
		i) STDINPUT=1;;
Natanael Copa's avatar
Natanael Copa committed
410
		p) ROOT=$OPTARG;;
Natanael Copa's avatar
Natanael Copa committed
411 412 413
        esac
done

Natanael Copa's avatar
Natanael Copa committed
414
mkdir -p $ROOT/etc/network
Natanael Copa's avatar
Natanael Copa committed
415 416 417 418
if [ "$STDINPUT" = "1" ]; then
	cat > $ROOT/etc/network/interfaces
else
	prompt_for_interfaces
Natanael Copa's avatar
Natanael Copa committed
419
fi