File: install.GATEWAY.sh

package info (click to toggle)
debian-edu-router 2.12.8~deb12u1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 3,468 kB
  • sloc: sh: 5,373; perl: 74; makefile: 25
file content (332 lines) | stat: -rwxr-xr-x 12,683 bytes parent folder | download
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
#! /bin/bash

set -e

# Copyright (C) 2022-2023 Pädagogisches Landesinstitut Rheinland-Pfalz
# Copyright (C) 2022-2023 Mike Gabriel <mike.gabriel@das-netzwerkteam.de>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the
# Free Software Foundation, Inc.,
# 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.

# This script has been localized...
export TEXTDOMAIN="debian-edu-router-fai"
. gettext.sh

mask2cdr() {
   # Assumes there's no "255." after a non-255 byte in the mask
   local x=${1##*255.}
   set -- 0^^^128^192^224^240^248^252^254^ $(( (${#1} - ${#x})*2 )) ${x%%.*}
   x=${1%%$3*}
   echo $(( $2 + (${#x}/4) ))
}

#
#   Check if IPv4 network is available and offer manual configuration otherwise.
#
#   Set env variable TEST_MODE to some value if you want to test the dialogs of
#   this script as a developer.
#

if [ -z "${TEST_MODE}" ]; then
	URL="http://deb.debian.org/"
	_tmp="tmp"
else
	URL="http://some.unknown.server/"
	_tmp="$(mktemp -d)"
fi

# The network configuration part in this script will only do the
# absolutely necessary. The real network setup (external, internal,
# VLANs, etc.) is done by DEB package debian-edu-router-config...

# make sure, we can create ${_tmp}/network-check-v4
touch ${_tmp}/network-check-v4

red=$(mktemp)
echo 'screen_color = (CYAN,RED,ON)' > $red

function show_dialogs_manual_ipv4_conf() {
	uplink_iface=""

	STATE=1
	QCOUNT=5

	while [ "$STATE" != 0 -a "$STATE" != "$(($QCOUNT+1))" ]; do
		case "$STATE" in
			1)
				# Pick / Discover the NIC for uplink internet connectivity
				while [ -z "${uplink_iface}" ]; do

					ifaces_connected=`ip a | grep -E "^[0-9]+:.*" | grep -v "NO-CARRIER" | awk '{ print $2}' | sed -e "s/:.*//" | grep -E -v "(lo|vnet[0-9]+|virbr[0-9]+|lxcbr[0-9]+|docker[0-9]+|br-[a-f0-9]{12})"`

					# No interfaces connected? If so, throw a warning and offer retry or cancel
					if [ -z "${ifaces_connected}" ]; then

						if ! { dialog --stdout --backtitle " $(eval_gettext "Configure Internet Access") " \
							--title " $(eval_gettext "No network adapter connected!") " \
							--yes-label "$(eval_gettext "Try again")" --no-label "$(eval_gettext "Cancel installation")" \
							--yesno "\n$(eval_gettext "Please plugin a network cable to the uplink network interface and try again.")" 10 78; } ; then
							exit 1
						fi

					else

						# Only one interface found? Then use it. Otherwise, ask which NIC to use as uplink.
						ifaces_tagnitems=""
						for iface in ${ifaces_connected}; do
							field="ID_MODEL_FROM_DATABASE"
							set +e
							iface_description=`udevadm info /sys/class/net/${iface} | grep "${field}" | sed -rn -e "s/^E: $field=(.+)/\1/p" | sed -e "s/ /_/g"`
							set -e
							ifaces_tagnitems="${ifaces_tagnitems} ${iface} ${iface_description}"
						done
						uplink_iface=`dialog --stdout --backtitle " $(eval_gettext "Configure Internet Access") " \
							--title " $(eval_gettext "Please choose uplink [external] network interface") " \
							--ok-label "$(eval_gettext "Select")" --cancel-label "$(eval_gettext "Re-scan network interfaces")" \
							--menu "\n$(eval_gettext "Please plugin a network cable to the uplink network interface and try again.")" 15 78 5 ${ifaces_tagnitems} ` || true

					fi

					if [ ! -z ${TEST_MODE} ]; then
						reset
						echo
						echo "hooks/install.GATEWAY.sh: Uplink NIC chosen: ${uplink_iface}"
						echo
						sleep 2
					fi

				done

				# if we get here, we can continue...
				cont=0
				;;
			2)
				set +e
				uplink_address_v4=`dialog --stdout --backtitle " $(eval_gettext "Configure Internet Access") " --title " $(eval_gettext "External IPv4 address") " --cancel-label "$(eval_gettext "Cancel installation")" --inputbox \
									"\n$(eval_gettext "Please specify the external IPv4 address of this system.")" 9 78`
				cont=$?
				set -e

				# provide an exit point here
				if [ ! ${cont} -eq 0 ]; then
					reset
					echo
					echo "hooks/install.GATEWAY.sh: Manual network setup cancelled."
					echo
					exit 1
				fi

				# valid IPv4 address syntax?
				if [ ${cont} -eq 0 ] && ! echo ${uplink_address_v4} | grep -qE '^(\b25[0-5]|\b2[0-4][0-9]|\b[01]?[0-9][0-9]?)(\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$'; then

					DIALOGRC=${red} \
					dialog --stdout \
						--backtitle " $(eval_gettext "Configure Internet Access") " \
						--title " $(eval_gettext "External IPv4 address") " \
						--msgbox "\n`printf "$(eval_gettext "IPv4 address '%s' is of invalid format, please try again.")" "${uplink_address_v4}"`" 8 45

					cont=10
				fi
				;;
			3)
				set +e
				uplink_netmask_v4=`dialog --stdout --backtitle " $(eval_gettext "Configure Internet Access") " --title " $(eval_gettext "External IPv4 netmask") " --cancel-label "$(eval_gettext "Back")" --inputbox \
									"\n$(eval_gettext "Please specify the external interface's IPv4 netmask.")" 9 78`
				cont=$?
				set -e

				# valid IPv4 netmask syntax?
				if [ ${cont} -eq 0 ] && ! echo ${uplink_netmask_v4} | grep -qE '^(((255\.){3}(255|254|252|248|240|224|192|128+))|((255\.){2}(255|254|252|248|240|224|192|128|0+)\.0)|((255\.)(255|254|252|248|240|224|192|128|0+)(\.0+){2})|((255|254|252|248|240|224|192|128|0+)(\.0+){3}))$'; then

					DIALOGRC=${red} \
					dialog --stdout \
						--backtitle " $(eval_gettext "Configure Internet Access") " \
						--title " $(eval_gettext "External IPv4 netmask") " \
						--msgbox "\n`printf "$(eval_gettext "IPv4 netmask '%s' is of invalid format, please try again.")" "${uplink_netmask_v4}"`" 8 45

					cont=10
				fi
				;;
			4)
				set +e
				uplink_gateway_v4=`dialog --stdout --backtitle " $(eval_gettext "Configure Internet Access") " --title " $(eval_gettext "External IPv4 gateway") " --cancel-label "$(eval_gettext "Back")" --inputbox \
									"\n$(eval_gettext "Please specify the external interface's IPv4 gateway address.")" 9 78`
				cont=$?
				set -e

				# valid IPv4 address syntax?
				if [ ${cont} -eq 0 ] && ! echo ${uplink_gateway_v4} | grep -qE '^(\b25[0-5]|\b2[0-4][0-9]|\b[01]?[0-9][0-9]?)(\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$'; then

					DIALOGRC=${red} \
					dialog --stdout \
						--backtitle " $(eval_gettext "Configure Internet Access") " \
						--title " $(eval_gettext "External IPv4 gateway") " \
						--msgbox "\n`printf "$(eval_gettext "IPv4 address '%s' is of invalid format, please try again.")" "${uplink_gateway_v4}"`" 8 45

					cont=10
				fi

				# FIXME/TODO: validate IPv4 gateway; Same subnet?
				;;
			5)
				set +e
				dns_nameservers_v4=`dialog --stdout --backtitle " $(eval_gettext "Configure Internet Access") " --title " $(eval_gettext "Upstream DNS servers") " --cancel-label "$(eval_gettext "Back")" --inputbox \
									"\n$(eval_gettext "Please specify available IPv4 DNS servers on the external network. Use commas or blanks to separate several DNS server addresses.")" 10 78`
				cont=$?
				set -e

				if [ ${cont} -eq 0 ]; then

					# remove commas and superfluous white-spaces
					dns_nameservers_v4="$(echo ${dns_nameservers_v4} | sed -E -e "s/,/ /g" -e "s/\s+/ /g")"
					for dns_v4_addr in ${dns_nameservers_v4}; do
						if ! echo ${dns_v4_addr} | grep -qE '^(\b25[0-5]|\b2[0-4][0-9]|\b[01]?[0-9][0-9]?)(\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$'; then

							DIALOGRC=${red} \
							dialog --stdout \
								--backtitle " $(eval_gettext "Configure Internet Access") " \
								--title " $(eval_gettext "Upstream DNS servers") " \
								--msgbox "\n`printf "$(eval_gettext "DNS server's IPv4 address '%s' is of invalid format, please try again.")" "${dns_v4_addr}"`" 8 45

							cont=10
							break 1
						fi
					done
				fi
				;;
		esac

		if [ $cont -eq 0 ]; then
			STATE=$(($STATE + 1))
		elif [ $cont -eq 1 ]; then
			STATE=$(($STATE - 1))
		elif [ $cont -eq 10 ]; then
			:
		else
			exit 1
		fi

	done
}

checked_inet_connection_once_before=false

# If IPv4 connectivity is not yet available (i.e. DHCPv4 address retrieval failed) we offer a manual IPv4 setup
while ! curl --ipv4 --fail --silent $URL > ${_tmp}/network-check-v4; do

	if [ "$checked_inet_connection_once_before" == true ]; then
		dialog --stdout --backtitle " $(eval_gettext "Configure Internet Access") " --title " $(eval_gettext "Manual IPv4 network setup [required]") " --yesno \
			"\n$(eval_gettext "Internet access still fails using the IPv4 networking data you entered manually.")\n\n$(eval_gettext "Do you want to retry setting up IPv4 internet access manually?")" 9 78;
	else
		dialog --stdout --backtitle " $(eval_gettext "Configure Internet Access") " --title " $(eval_gettext "Manual IPv4 network setup [required]") " --yesno \
			"\n$(eval_gettext "The system failed to obtain an IPv4 address via DHCP automatically.")\n\n$(eval_gettext "Do you want to setup IPv4 internet access manually?")" 9 78;
	fi

	# Check if user cancelled the dialog before.
	if [ ! "$?" -eq 0 ]; then
		if ! { dialog --stdout --backtitle " $(eval_gettext "Configure Internet Access") " \
			--title " $(eval_gettext "No IPv4 network / internet access available!") " \
			--yes-label "$(eval_gettext "Try again")" --no-label "$(eval_gettext "Cancel installation")" \
			--yesno "\n$(eval_gettext "Could not access test URL '$URL' via IPv4. Please make sure internet access is available during installation.")\n\n\
			$(eval_gettext "Fix this problem [Ctrl-Alt-F2] and try again.")" 10 78; }
		then
			reset
			echo
			echo "hooks/install.GATEWAY.sh: Uplink network setup cancelled, installation can't proceed."
			echo
			exit 1
		fi
	fi

	show_dialogs_manual_ipv4_conf

	checked_inet_connection_once_before=true

	if [ -z "${TEST_MODE}" ]; then
		# only execute this if not in (dialog) TEST_MODE

		# use above data to set up networking and test again...
		if [ -n "$uplink_iface" ] && \
		   [ -n "$uplink_address_v4" ] && \
		   [ -n "$uplink_netmask_v4" ] && \
		   [ -n "$uplink_gateway_v4" ] && \
		   [ -n "$dns_nameservers_v4" ]; then

			ip address add ${uplink_address_v4}/${uplink_netmask_v4} dev ${uplink_iface}
			ip link set ${uplink_iface} up
			ip -4 route add default via ${uplink_gateway_v4} dev ${uplink_iface}
			mv /etc/resolv.conf /etc/resolv.conf.FAI-orig
			for dns_nameserver_v4 in $dns_nameservers_v4; do
				echo "nameserver $dns_nameserver_v4" >> /etc/resolv.conf
			done

			# tear down above network config, if not usable for internet connectivity
			if ! curl --ipv4 --fail --silent $URL > ${_tmp}/network-check-v4; then
				mv /etc/resolv.conf.FAI-orig /etc/resolv.conf
				ip -4 route del default via ${uplink_gateway_v4} dev ${uplink_iface}
				ip address delete ${uplink_address_v4}/${uplink_netmask_v4} dev ${uplink_iface}
				ip link set ${uplink_iface} down
			else
				# we don't need this anymore...
				rm /etc/resolv.conf.FAI-orig
			fi

			# fill uplink_full_address_v4
			uplink_full_address_v4="${uplink_address_v4}/$(mask2cdr $uplink_netmask_v4)"
		fi
	else
		break 1
	fi
done

if [ -z "${TEST_MODE}" ]; then

	# only execute this if not in (dialog) TEST_MODE

	if [ -n "$uplink_iface" ] && \
	   [ -n "$uplink_address_v4" ] && \
	   [ -n "$uplink_full_address_v4" ] && \
	   [ -n "$uplink_netmask_v4" ] && \
	   [ -n "$uplink_gateway_v4" ] && \
	   [ -n "$dns_nameservers_v4" ]; then

		echo "UPLINK_IFACE=$uplink_iface"                       >> $LOGDIR/additional.var
		echo "UPLINK_ADDRESS_V4=${uplink_address_v4}"           >> $LOGDIR/additional.var
		echo "UPLINK_FULL_ADDRESS_V4=${uplink_full_address_v4}" >> $LOGDIR/additional.var
		echo "UPLINK_NETMASK_V4=${uplink_netmask_v4}"           >> $LOGDIR/additional.var
		echo "UPLINK_GATEWAY_V4=${uplink_gateway_v4}"           >> $LOGDIR/additional.var
		echo "DNS_NAMESERVERS_V4=${dns_nameservers_v4}"         >> $LOGDIR/additional.var

	fi

else

	reset
	echo
	echo "hooks/install.GATEWAY.sh: Uplink ifupdown config will look like this:"
	echo
	echo '```'
	echo "auto ${uplink_iface}"
	echo "iface ${uplink_iface} inet static"
	echo "        address ${uplink_address_v4}"
	echo "        netmask ${uplink_netmask_v4}"
	echo "        gateway ${uplink_gateway_v4}"
	echo "        dns-nameservers ${dns_nameservers_v4}"
	echo '```'
	echo

fi

set +e