summaryrefslogtreecommitdiffstats
path: root/core/modules/dhcpc-busybox/data/opt/openslx/scripts/udhcpc-openslx
blob: 81c9491bd7ad284006d4c5a3996cf7f58055324b (plain) (blame)
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
#!/bin/bash
# Needs bash for printf -v VARNAME
# -----------------------------------------------------------------------------
#
# Copyright (c) 2011..2018 bwLehrpool-Projektteam
#
# This program/file is free software distributed under the GPL version 2.
# See https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
#
# If you have any feedback please consult https://bwlehrpool.de and
# send your feedback to bwlehrpool@hs-offenburg.de.
#
# General information about bwLehrpool can be found at https://bwlehrpool.de
#
# -----------------------------------------------------------------------------
#
#                               Mini-Linux Toolkit
#
# -----------------------------------------------------------------------------

. /opt/openslx/config

primary="br0"
[ -n "$SLX_BRIDGE" ] && primary="$SLX_BRIDGE"

RESOLV_CONF="/opt/openslx/resolv.conf"
THIS_RESOLV="/run/network/${interface}.resolv"

rebuild_resolv_conf () {
	# Don't do anything if the active resolv.conf is not ours
	# Also this will not run resolvconf update.d... No idea if we should still do so...
	[ -L "/etc/resolv.conf" ] || return 0
	[ "x$(readlink "/etc/resolv.conf")" == "x${RESOLV_CONF}" ] || return 0
	# Maybe make this smarter some time, if anyone is using clients that are on multiple networks at once etc...
	# This is a little braindead but should work most of the time
	sort -u /run/network/*.resolv > "$RESOLV_CONF" 2> /dev/null

	# add support for resolv.conf update scripts // see man(8) resolvconf
	for s in /etc/resolvconf/update.d/*.sh; do
		[ -f "$s" ] && [ -x "$s" ] && "$s"
	done
}

escape_search() {
	echo "$@" | sed -e 's/[]\/()$*.^|[]/\\&/g'
}

escape_replace() {
	echo "$@" | sed -e 's/[\/&]/\\&/g'
}

check_env() {
	if [ -z "$ip" ] || [ -z "$subnet" ] || [ -z "$interface" ]; then
		echo "$1 event with missing data" >&2
		echo "ip = '$ip'" >&2
		echo "subnet = '$subnet'" >&2
		echo "interface = '$interface'" >&2
		exit 1
	fi
}

if [ ! -d /run ]; then
	echo -n "Waiting for /run." >&2
	while [ ! -d /run ]; do
		echo -n "." >&2
		usleep 500000
	done
	echo "" >&2
fi

mkdir -p "/run/network"

case "$1" in
	bound|renew)
		check_env "$1"
		mkdir -p "/run/dhcpc"
		# Set address on interface
		ip addr add "$ip/$(ipcalc -s -p "$ip" "$subnet" | sed s/.*=//)" dev "$interface"
		# Set default route, if given
		if [ -n "$router" ]; then
			ip route add default via "$router"
		fi
		
		# get domain, hostname and thus fqdn from DNS
		dns_fqdn=$(/opt/openslx/bin/busybox timeout -t 3 rdns "$ip")
		dns_short="${dns_fqdn%%.*}"
		# check if it is fqdn
		if [ "$dns_fqdn" == "$dns_short" ]; then
			unset dns_fqdn dns_short
		fi

		# Update resolver configuration file
		conf_file="$(mktemp)"
		# Own domain suffix
		if [ -n "$domain" ]; then
			:
		elif [ -n "$dns_fqdn" ]; then
			domain="${dns_fqdn#*.}"
			
		elif [ -n "$SLX_NET_DOMAIN" ]; then
			domain="$SLX_NET_DOMAIN"
		fi
		if [ -n "$domain" ]; then
			echo "domain ${domain%% *}" >> "${conf_file}"
		fi
		# Add domain to list of search domains if not in there yet
		if [ -n "$domain" ] && [ -n "$search" ]; then
			FOUND=no
			for sd in $search; do
				[ "x$sd" = "x$domain" ] && FOUND=yes
			done
			[ "$FOUND" = "no" ] && search="$domain $search"
		elif [ -n "$domain" ]; then
			search="$domain"
		fi
		# Search domains
		if [ -n "$search" ]; then
			echo "search $search" >> "${conf_file}"
		elif [ -n "$SLX_NET_SEARCH" ]; then
			echo "search $SLX_NET_SEARCH" >> "${conf_file}"
		elif [ -n "$SLX_NET_DOMAIN" ]; then
			echo "search $SLX_NET_DOMAIN" >> "${conf_file}"
		fi
		for i in $dns; do
			echo "$0: Adding DNS $i"
			echo "nameserver $i" >> "${conf_file}"
		done
		
		if [ -x "/sbin/resolvconf" ] && [ -L "/etc/resolv.conf" ] && [ -d "/etc/resolvconf/update.d" ]; then
			# Automatic handling :-)
			resolvconf --create-runtime-directories
			resolvconf --enable-updates
			< "$conf_file"  resolvconf -a "${interface}.udhcpc"
			rm -- "$conf_file"
		else
			# Manual handling required :-(
			mv -f "$conf_file" "$THIS_RESOLV"
			rebuild_resolv_conf
		fi

		
		# Things that should only happen for the main interface that was used for booting
		if [ "$interface" = "$primary" ]; then
			# Update IP
			sed -i "s/^\(SLX_PXE_CLIENT_IP=\).*$/\1'$ip'/" /opt/openslx/config
			# Write DOMAIN and SEARCH to /opt/openslx/config if empty
			if [ -z "$SLX_NET_DOMAIN" ] && [ -n "$domain" ]; then
				sed -i "/^SLX_NET_DOMAIN=/d" /opt/openslx/config
				echo "SLX_NET_DOMAIN='$domain'" >> /opt/openslx/config
			fi
			if [ -z "$SLX_NET_SEARCH" ] && [ -n "$search" ]; then
				sed -i "/^SLX_NET_SEARCH=/d" /opt/openslx/config
				echo "SLX_NET_SEARCH='$search'" >> /opt/openslx/config
			fi
			# Same for WINS servers
			if [ -z "$SLX_NET_WINS" ] && [ -n "$wins" ]; then
				sed -i "/^SLX_NET_WINS=/d" /opt/openslx/config
				echo "SLX_NET_WINS='$wins'" >> /opt/openslx/config
			fi
			
			# Only if network is not ready yet
			if [ ! -e "/run/network/network-ready" ]; then
				# Update hostname
				if [ -z "$dns_fqdn" ] && [ -n "$domain" ] && [ -n "$hostname" ]; then
					# fallback to what the dhcp told us
					dns_fqdn="${hostname}.${domain}"
				fi
				if [ -z "$dns_fqdn" ]; then
					# only if there is no /etc/hostname, we fall back (far back, that is)
					[ ! -s "/etc/hostname" ] && dns_fqdn="slx-client"
				fi
				# finally, if dns_fqdn was set to anything, apply it
				if [ -n "$dns_fqdn" ]; then
					dns_short="${dns_fqdn%%.*}"
					echo "$dns_short" > "/proc/sys/kernel/hostname"
					echo "$dns_short" > "/etc/hostname"
					if grep '^SLX_HOSTNAME=' /opt/openslx/config 2>/dev/null; then
						sed -i "s/^\(SLX_HOSTNAME=\).*$/\1'$dns_short'/" /opt/openslx/config
					else
						echo "# Config written by openslx-dhcp-script (1)" >> /opt/openslx/config
						echo "SLX_HOSTNAME='$dns_short'" >> /opt/openslx/config
					fi
				fi

				# Update /etc/issue for proper spacing
				/opt/openslx/scripts/openslx-create_issue
				touch "/run/network/network-ready"
				# Mark network target as reached
				systemctl start network.target &
			fi # end "network not ready yet"
			# Remove any stray addresses; we expect the primary interface to only have one
			# address supplied via DHCP. We do this after adding the new one, obviously.
			rem_list=$( ip -o addr show "$interface" | awk '{ for (i=1;i<NF;++i) if ($i == "inet") print $(i+1) }' | grep -v "^${ip}/" )
			if [ -n "$rem_list" ]; then
				echo "PRIMARY: Removing $rem_list since we just got assigned $ip"
				echo 1 > "/proc/sys/net/ipv4/conf/$interface/promote_secondaries"
				for addr in $rem_list; do
					ip addr del "$addr" dev "$interface"
					sed -i "/^$(escape_search "${addr%/*}")(\s|$)/d" /etc/hosts
				done
			fi
		fi # end "primary only"
		
		# Hostname in /etc/hosts
		touch "/etc/hosts"
		hostlist=""
		[ -n "$dns_fqdn" ] && hostlist="$dns_fqdn"
		[ -n "$hostname" ] && [ -n "$domain" ] && [ "x${hostname}.${domain}" != "x$dns_fqdn" ] && hostlist="$hostlist ${hostname}.${domain}"
		if [ -n "$hostlist" ]; then
			for host in $hostlist; do
				host_short="${host%%.*}"
				[ "x$host_short" = "x$host" ] && host_short=""
				sed -i -r "s/\s$(escape_search "$host")(\s|$)/ /g" /etc/hosts
				[ -n "$host_short" ] && sed -i -r "s/\s$(escape_search "$host_short")(\s|$)/ /g" /etc/hosts
				if grep -q -E "^$ip\s" /etc/hosts; then
					sed -i "s/^$(escape_search "$ip")\s.*/$(escape_replace "$ip $host $host_short")/g" /etc/hosts
				else
					echo "$ip $host $host_short" >> /etc/hosts
				fi
			done
		fi
		# Get rid of orphaned lines in /etc/hosts
		sed -i -r '/^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+\s*$/d' /etc/hosts
		
		# "dns ready" target
		if [ -n "$dns" ] && [ ! -e "/run/network/dns-ready" ]; then
			touch "/run/network/dns-ready"
			# Write to openslx-config
			echo "# Config written by openslx-dhcp-script (2)" >> /opt/openslx/config
			echo "SLX_DNS='$dns'" >> /opt/openslx/config
			systemctl start network-dns.target &
		fi
		# "default route exists" target
		if [ -n "$router" ] && [ ! -e "/run/network/gateway-ready" ]; then
			touch "/run/network/gateway-ready"
			systemctl start network-gateway.target &
		fi
		
			# Port redirection for printing happens in printergui module (iptables-helper rule)
			####iptables -A INPUT -i br0 -p tcp --dport 515 -j DROP
			####iptables -A INPUT -i br0 -p tcp --dport 5515 -j DROP
			####iptables -t nat -A PREROUTING -s 192.168.0.0/16 -p tcp --dport 515 -j REDIRECT --to-port 5515
	;;
	
	deconfig)
		check_env "$1"
		if [ "$interface" = "$primary" ]; then
			echo "Ignoring deconfig for primary interface"
		else
			echo 1 > "/proc/sys/net/ipv4/conf/$interface/promote_secondaries"
			clientip=${ip%%:*}
			ip addr del "$clientip/$(ipcalc -s -p "$clientip" "$subnet" | sed s/.*=//)" dev "$interface"
			sed -i "/^$(escape_search "$ip")(\s|$)/d" /etc/hosts
		fi
		
		if [ -x /sbin/resolvconf ] && [ -L /etc/resolv.conf ] && [ -d /etc/resolvconf/update.d ]; then
			# Automatic handling :-)
			resolvconf -d "${interface}.udhcpc"
		else
			# Manual handling required :-(
			rm -f -- "$THIS_RESOLV"
			rebuild_resolv_conf
		fi
	;;
	
	leasefail)
		echo "$0: Lease failed: $message" >&2
		
	;;
	
	nak)
		echo "$0: Received a NAK: $message" >&2
		
	;;
	
	*)
		echo "$0: Unknown udhcpc command: $1" >&2
		exit 1
		
	;;
esac

exit 0