summaryrefslogtreecommitdiffstats
path: root/builder/modules.d/slx-network/scripts/udhcpc-trigger.stage4
blob: b4dfeafa0594fc640e0f8e1a3633efedb83d4d95 (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
#!/bin/bash
#
# This script is triggered by udhcpc and handle the DHCP information
# given to this script as parameters.

export PATH=$PATH:/opt/openslx/sbin:/opt/openslx/bin

. /opt/openslx/config

if [ -z "$SLX_PXE_NETIF" ]; then
	echo "Missing PXE network interface information."
	exit 1
fi

MAIN_NETIF="$SLX_PXE_NETIF"
[ -n "$SLX_VLAN_ID" ] && MAIN_NETIF="${SLX_PXE_NETIF}.${SLX_VLAN_ID}"
[ -n "$SLX_BRIDGE" ]  && MAIN_NETIF="$SLX_BRIDGE"
readonly MAIN_NETIF

RESOLV_CONF="/opt/openslx/resolv.conf"
THIS_RESOLV="/run/network/${MAIN_NETIF}.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
	# only run for the boot network interface
	# TODO VLAN support
	if [ "$interface" != "$MAIN_NETIF" ]; then
		echo "Ignoring '$interface'..."
		exit 1
	fi
}

case "$1" in
	bound|renew)
		check_env "$1"
		# 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 replace default via "$router"
		fi
		
		# get domain, hostname and thus fqdn from DNS
		dns_fqdn=$(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

		# TODO: check if we really want/need to overwrite the PXE_IP,
		# it might be better/clearer to change the SLX_DHCP_CLIENT_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

		# TODO find a better way to trigger additional code, hook dir?
		# Update /etc/issue for proper spacing
		[ -x "/opt/openslx/scripts/openslx-create_issue" ] && /opt/openslx/scripts/openslx-create_issue

		# 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
		
		# Write to openslx-config
		echo "# Config written by openslx-dhcp-script (2)" >> /opt/openslx/config
		sed -i "/^SLX_DNS=/d" /opt/openslx/config
		echo "SLX_DNS='$dns'" >> /opt/openslx/config
	;;
	
	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